mirror of
git://git.proxmox.com/git/perlmod.git
synced 2025-01-09 05:17:38 +03:00
add methods to 'bless' values
Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
This commit is contained in:
parent
5d716926a8
commit
87c102370e
@ -19,6 +19,7 @@ bitflags = "1.2.1"
|
||||
libc = "0.2"
|
||||
perlmod-macro = { path = "../perlmod-macro", optional = true, version = "0.1" }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
thiserror = "1.0"
|
||||
|
||||
[features]
|
||||
default = ["exporter"]
|
||||
|
@ -1,16 +1,12 @@
|
||||
#[derive(Debug)]
|
||||
use thiserror::Error as ThisError;
|
||||
|
||||
#[derive(ThisError, Debug)]
|
||||
#[error("wrong type")]
|
||||
pub struct CastError;
|
||||
|
||||
impl std::fmt::Display for CastError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
write!(f, "wrong type")
|
||||
}
|
||||
}
|
||||
|
||||
impl std::error::Error for CastError {}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Error(String);
|
||||
#[derive(ThisError, Clone, Debug)]
|
||||
#[error("error: {0}")]
|
||||
pub struct Error(pub(crate) String);
|
||||
|
||||
impl Error {
|
||||
#[inline]
|
||||
@ -24,14 +20,6 @@ impl Error {
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for Error {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
write!(f, "error: {}", self.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::error::Error for Error {}
|
||||
|
||||
impl serde::de::Error for Error {
|
||||
fn custom<T: std::fmt::Display>(msg: T) -> Self {
|
||||
Self(msg.to_string())
|
||||
|
@ -91,6 +91,9 @@ extern "C" {
|
||||
pub fn RSPL_hv_iternext(hv: *mut HV) -> *mut HE;
|
||||
pub fn RSPL_hv_iterkeysv(he: *mut HE) -> *mut SV;
|
||||
pub fn RSPL_hv_iterval(hv: *mut HV, he: *mut HE) -> *mut SV;
|
||||
|
||||
pub fn RSPL_gv_stashsv(name: *const SV, flags: i32) -> *mut HV;
|
||||
pub fn RSPL_sv_bless(sv: *mut SV, stash: *mut HV) -> *mut SV;
|
||||
}
|
||||
|
||||
/// Argument marker for the stack.
|
||||
|
@ -270,6 +270,14 @@ extern SV* RSPL_hv_iterval(HV *hv, HE *he) {
|
||||
return hv_iterval(hv, he);
|
||||
}
|
||||
|
||||
extern HV* RSPL_gv_stashsv(SV *name, int32_t flags) {
|
||||
return gv_stashsv(name, flags);
|
||||
}
|
||||
|
||||
extern SV* RSPL_sv_bless(SV *sv, HV *stash) {
|
||||
return sv_bless(sv, stash);
|
||||
}
|
||||
|
||||
/*
|
||||
These make are convoluted brainfarts:
|
||||
SVt_NULL undef
|
||||
|
@ -14,6 +14,7 @@
|
||||
//! [`make_package!`]: macro.make_package.html
|
||||
|
||||
pub(crate) mod error;
|
||||
pub use error::Error;
|
||||
|
||||
pub mod de;
|
||||
pub mod ffi;
|
||||
|
@ -7,6 +7,7 @@ use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::ffi::{self, SV};
|
||||
use crate::scalar::ScalarRef;
|
||||
use crate::Error;
|
||||
use crate::{Array, Hash, Scalar};
|
||||
|
||||
/// A higher level value. This is basically an `SV` already cast to `AV` or `HV` for arrays and
|
||||
@ -58,6 +59,36 @@ impl Value {
|
||||
Value::Reference(unsafe { Scalar::from_raw_move(ffi::RSPL_newRV_inc(value.sv())) })
|
||||
}
|
||||
|
||||
/// Bless a value into a package. This turns the value into a reference and forwards to
|
||||
/// [`Value::bless_ref`].
|
||||
pub fn bless_value(&self, package: &str) -> Result<Value, Error> {
|
||||
self.clone_ref().bless_ref(package)
|
||||
}
|
||||
|
||||
/// Bless a reference into a package. The `Value` must be a reference.
|
||||
pub fn bless_ref(&self, package: &str) -> Result<Value, Error> {
|
||||
let value = match self {
|
||||
Value::Reference(v) => v,
|
||||
_ => Error::fail("trying to bless a non-reference")?,
|
||||
};
|
||||
|
||||
let pkgsv = Scalar::new_string(package);
|
||||
let stash = unsafe { ffi::RSPL_gv_stashsv(pkgsv.sv(), 0) };
|
||||
if stash.is_null() {
|
||||
return Err(Error(format!("failed to find package {:?}", package)));
|
||||
}
|
||||
|
||||
let value = unsafe { ffi::RSPL_sv_bless(value.sv(), stash) };
|
||||
if value.is_null() {
|
||||
return Err(Error(format!(
|
||||
"failed to bless value into package {:?}",
|
||||
package
|
||||
)));
|
||||
}
|
||||
|
||||
Ok(Value::Reference(unsafe { Scalar::from_raw_move(value) }))
|
||||
}
|
||||
|
||||
/// Take over a raw `SV` value, assuming that we then own a reference to it.
|
||||
///
|
||||
/// # Safety
|
||||
|
Loading…
Reference in New Issue
Block a user