mirror of
https://git.proxmox.com/git/perlmod
synced 2025-10-04 22:07:05 +00:00
support deserializing borrowed strings
Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
This commit is contained in:
parent
0bab1226bb
commit
35b138f2c6
@ -31,7 +31,8 @@ where
|
|||||||
/// Deserialize a reference to a perl [`Value`](crate::Value).
|
/// Deserialize a reference to a perl [`Value`](crate::Value).
|
||||||
///
|
///
|
||||||
/// Note that this causes all the underlying data to be copied recursively, except for data
|
/// Note that this causes all the underlying data to be copied recursively, except for data
|
||||||
/// deserialized to `&[u8]`, which will reference the original value.
|
/// deserialized to `&[u8]` or `&str`, which will reference the "original" value (whatever that
|
||||||
|
/// means for perl).
|
||||||
pub fn from_ref_value<'de, T>(input: &'de Value) -> Result<T, Error>
|
pub fn from_ref_value<'de, T>(input: &'de Value) -> Result<T, Error>
|
||||||
where
|
where
|
||||||
T: Deserialize<'de>,
|
T: Deserialize<'de>,
|
||||||
@ -91,7 +92,8 @@ impl<'deserializer> Deserializer<'deserializer> {
|
|||||||
use crate::scalar::Flags;
|
use crate::scalar::Flags;
|
||||||
|
|
||||||
if flags.contains(Flags::STRING) {
|
if flags.contains(Flags::STRING) {
|
||||||
visitor.visit_str(value.pv_string_utf8())
|
let s = unsafe { str_set_wrong_lifetime(value.pv_string_utf8()) };
|
||||||
|
visitor.visit_borrowed_str(s)
|
||||||
} 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) {
|
||||||
@ -123,7 +125,8 @@ impl<'deserializer> Deserializer<'deserializer> {
|
|||||||
} 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::STRING) {
|
} else if flags.contains(Flags::STRING) {
|
||||||
visitor.visit_str(value.pv_string_utf8())
|
let s = unsafe { str_set_wrong_lifetime(value.pv_string_utf8()) };
|
||||||
|
visitor.visit_borrowed_str(s)
|
||||||
} else {
|
} else {
|
||||||
visitor.visit_unit()
|
visitor.visit_unit()
|
||||||
}
|
}
|
||||||
@ -151,7 +154,8 @@ impl<'deserializer> Deserializer<'deserializer> {
|
|||||||
} else if flags.contains(Flags::INTEGER) {
|
} else if flags.contains(Flags::INTEGER) {
|
||||||
visitor.visit_i64(value.iv() as i64)
|
visitor.visit_i64(value.iv() as i64)
|
||||||
} else if flags.contains(Flags::STRING) {
|
} else if flags.contains(Flags::STRING) {
|
||||||
visitor.visit_str(value.pv_string_utf8())
|
let s = unsafe { str_set_wrong_lifetime(value.pv_string_utf8()) };
|
||||||
|
visitor.visit_borrowed_str(s)
|
||||||
} else {
|
} else {
|
||||||
visitor.visit_unit()
|
visitor.visit_unit()
|
||||||
}
|
}
|
||||||
@ -165,6 +169,14 @@ impl<'deserializer> Deserializer<'deserializer> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// We use this only for `Value`s in our deserializer. We know this works because serde says the
|
||||||
|
/// lifetime needs to only live as long as the serializer, and we feed our serializer with the data
|
||||||
|
/// from a borrowed Value (keeping references to all the contained data within perl), which lives
|
||||||
|
/// longer than the deserializer.
|
||||||
|
unsafe fn str_set_wrong_lifetime<'a, 'b>(s: &'a str) -> &'b str {
|
||||||
|
std::str::from_utf8_unchecked(std::slice::from_raw_parts(s.as_ptr(), s.len()))
|
||||||
|
}
|
||||||
|
|
||||||
impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
|
impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
@ -291,7 +303,10 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
|
|||||||
let mut chars = s.chars();
|
let mut chars = s.chars();
|
||||||
match chars.next() {
|
match chars.next() {
|
||||||
Some(ch) if chars.next().is_none() => visitor.visit_char(ch),
|
Some(ch) if chars.next().is_none() => visitor.visit_char(ch),
|
||||||
_ => visitor.visit_str(value.pv_string_utf8()),
|
_ => {
|
||||||
|
let s = unsafe { str_set_wrong_lifetime(value.pv_string_utf8()) };
|
||||||
|
visitor.visit_borrowed_str(s)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
visitor.visit_unit()
|
visitor.visit_unit()
|
||||||
|
Loading…
Reference in New Issue
Block a user