mirror of
https://git.proxmox.com/git/perlmod
synced 2025-10-05 06:58:39 +00:00
deserialize by reference
Allow deserializing things such as `&[u8]` to reference the original data instead of requiring a `Vec<u8>` instead. Introduces `perlmod::from_ref_value` next to `perlmod::from_value` with a new signature. Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
This commit is contained in:
parent
755df92f64
commit
dd7f83c3ee
@ -92,14 +92,15 @@ pub fn handle_function(
|
|||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
deserialized_arguments.extend(quote! {
|
deserialized_arguments.extend(quote! {
|
||||||
let #deserialized_name: #arg_type = match ::perlmod::from_value(#extracted_name) {
|
let #deserialized_name: #arg_type =
|
||||||
Ok(data) => data,
|
match ::perlmod::from_ref_value(&#extracted_name) {
|
||||||
Err(err) => {
|
Ok(data) => data,
|
||||||
return Err(::perlmod::Value::new_string(&err.to_string())
|
Err(err) => {
|
||||||
.into_mortal()
|
return Err(::perlmod::Value::new_string(&err.to_string())
|
||||||
.into_raw());
|
.into_mortal()
|
||||||
}
|
.into_raw());
|
||||||
};
|
}
|
||||||
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
//! Serde deserializer for perl values.
|
//! Serde deserializer for perl values.
|
||||||
|
|
||||||
use serde::de::{self, DeserializeOwned, DeserializeSeed, MapAccess, SeqAccess, Visitor};
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
|
use serde::de::{self, Deserialize, DeserializeSeed, MapAccess, SeqAccess, Visitor};
|
||||||
|
|
||||||
use crate::error::Error;
|
use crate::error::Error;
|
||||||
use crate::scalar::Type;
|
use crate::scalar::Type;
|
||||||
@ -8,26 +10,43 @@ use crate::Value;
|
|||||||
use crate::{array, ffi, hash};
|
use crate::{array, ffi, hash};
|
||||||
|
|
||||||
/// Perl [`Value`](crate::Value) deserializer.
|
/// Perl [`Value`](crate::Value) deserializer.
|
||||||
struct Deserializer {
|
struct Deserializer<'de> {
|
||||||
input: Value,
|
input: Value,
|
||||||
option_allowed: bool,
|
option_allowed: bool,
|
||||||
|
_lifetime: PhantomData<&'de Value>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Deserialize a perl [`Value`](crate::Value).
|
/// Deserialize a perl [`Value`](crate::Value).
|
||||||
|
///
|
||||||
|
/// Note that this causes all the underlying data to be copied recursively.
|
||||||
pub fn from_value<T>(input: Value) -> Result<T, Error>
|
pub fn from_value<T>(input: Value) -> Result<T, Error>
|
||||||
where
|
where
|
||||||
T: DeserializeOwned,
|
T: serde::de::DeserializeOwned,
|
||||||
{
|
{
|
||||||
let mut deserializer = Deserializer::from_value(input);
|
let mut deserializer = Deserializer::<'static>::from_value(input);
|
||||||
let out = T::deserialize(&mut deserializer)?;
|
let out = T::deserialize(&mut deserializer)?;
|
||||||
Ok(out)
|
Ok(out)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Deserializer {
|
/// Deserialize a reference to a perl [`Value`](crate::Value).
|
||||||
|
///
|
||||||
|
/// Note that this causes all the underlying data to be copied recursively, except for data
|
||||||
|
/// deserialized to `&[u8]`, which will reference the original value.
|
||||||
|
pub fn from_ref_value<'de, T>(input: &'de Value) -> Result<T, Error>
|
||||||
|
where
|
||||||
|
T: Deserialize<'de>,
|
||||||
|
{
|
||||||
|
let mut deserializer = Deserializer::<'de>::from_value(input.clone_ref());
|
||||||
|
let out = T::deserialize(&mut deserializer)?;
|
||||||
|
Ok(out)
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'deserializer> Deserializer<'deserializer> {
|
||||||
pub fn from_value(input: Value) -> Self {
|
pub fn from_value(input: Value) -> Self {
|
||||||
Deserializer {
|
Deserializer {
|
||||||
input,
|
input,
|
||||||
option_allowed: true,
|
option_allowed: true,
|
||||||
|
_lifetime: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,9 +79,7 @@ impl Deserializer {
|
|||||||
self.sanity_check()?;
|
self.sanity_check()?;
|
||||||
Ok(&self.input)
|
Ok(&self.input)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl Deserializer {
|
|
||||||
/// deserialize_any, preferring a string value
|
/// deserialize_any, preferring a string value
|
||||||
fn deserialize_any_string<'de, V>(&mut self, visitor: V) -> Result<V::Value, Error>
|
fn deserialize_any_string<'de, V>(&mut self, visitor: V) -> Result<V::Value, Error>
|
||||||
where
|
where
|
||||||
@ -148,7 +165,7 @@ impl Deserializer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer {
|
impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Error>
|
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Error>
|
||||||
@ -312,7 +329,10 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer {
|
|||||||
use crate::scalar::Flags;
|
use crate::scalar::Flags;
|
||||||
|
|
||||||
if flags.contains(Flags::STRING) {
|
if flags.contains(Flags::STRING) {
|
||||||
visitor.visit_bytes(value.pv_bytes())
|
let bytes = value.pv_bytes();
|
||||||
|
let bytes: &'de [u8] =
|
||||||
|
unsafe { std::slice::from_raw_parts(bytes.as_ptr(), bytes.len()) };
|
||||||
|
visitor.visit_borrowed_bytes(bytes)
|
||||||
} else if flags.contains(Flags::DOUBLE) {
|
} else if flags.contains(Flags::DOUBLE) {
|
||||||
visitor.visit_f64(value.nv())
|
visitor.visit_f64(value.nv())
|
||||||
} else if flags.contains(Flags::INTEGER) {
|
} else if flags.contains(Flags::INTEGER) {
|
||||||
|
@ -20,7 +20,7 @@ pub mod ffi;
|
|||||||
pub mod ser;
|
pub mod ser;
|
||||||
|
|
||||||
#[doc(inline)]
|
#[doc(inline)]
|
||||||
pub use de::from_value;
|
pub use de::{from_ref_value, from_value};
|
||||||
#[doc(inline)]
|
#[doc(inline)]
|
||||||
pub use ser::to_value;
|
pub use ser::to_value;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user