From f3c21f2245c10e86c228d6778d13509b4ceeec10 Mon Sep 17 00:00:00 2001 From: Trangar Date: Mon, 17 Jan 2022 17:16:14 +0100 Subject: [PATCH] Made SerdeDecoder attempt to allocate a string before complaining about being able to decode borrowed data (#475) --- Cargo.toml | 2 + src/features/serde/de_owned.rs | 20 ++++++- tests/issues.rs | 3 ++ tests/issues/issue_474.rs | 97 ++++++++++++++++++++++++++++++++++ 4 files changed, 121 insertions(+), 1 deletion(-) create mode 100644 tests/issues/issue_474.rs diff --git a/Cargo.toml b/Cargo.toml index d1a6bd9..4f5ef21 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -45,6 +45,8 @@ serde_json = "1.0.68" tempfile = "3.2.0" criterion = "0.3" rand = "0.8" +uuid = { version = "0.8", features = ["serde"] } +chrono = { version = "0.4", features = ["serde"] } [[bench]] name = "varint" diff --git a/src/features/serde/de_owned.rs b/src/features/serde/de_owned.rs index 45c13d3..b838ba9 100644 --- a/src/features/serde/de_owned.rs +++ b/src/features/serde/de_owned.rs @@ -121,7 +121,16 @@ impl<'a, 'de, DE: Decoder> Deserializer<'de> for SerdeDecoder<'a, DE> { visitor.visit_char(Decode::decode(&mut self.de)?) } - fn deserialize_str(self, _visitor: V) -> Result + #[cfg(feature = "alloc")] + fn deserialize_str(mut self, visitor: V) -> Result + where + V: serde_incl::de::Visitor<'de>, + { + visitor.visit_string(Decode::decode(&mut self.de)?) + } + + #[cfg(not(feature = "alloc"))] + fn deserialize_str(mut self, visitor: V) -> Result where V: serde_incl::de::Visitor<'de>, { @@ -135,6 +144,15 @@ impl<'a, 'de, DE: Decoder> Deserializer<'de> for SerdeDecoder<'a, DE> { visitor.visit_string(Decode::decode(&mut self.de)?) } + #[cfg(feature = "alloc")] + fn deserialize_bytes(mut self, visitor: V) -> Result + where + V: serde_incl::de::Visitor<'de>, + { + visitor.visit_byte_buf(Decode::decode(&mut self.de)?) + } + + #[cfg(not(feature = "alloc"))] fn deserialize_bytes(self, _visitor: V) -> Result where V: serde_incl::de::Visitor<'de>, diff --git a/tests/issues.rs b/tests/issues.rs index 564410e..40c5342 100644 --- a/tests/issues.rs +++ b/tests/issues.rs @@ -11,3 +11,6 @@ mod issue_467; #[path = "issues/issue_459.rs"] mod issue_459; + +#[path = "issues/issue_474.rs"] +mod issue_474; diff --git a/tests/issues/issue_474.rs b/tests/issues/issue_474.rs new file mode 100644 index 0000000..84252ed --- /dev/null +++ b/tests/issues/issue_474.rs @@ -0,0 +1,97 @@ +#![cfg(all(feature = "serde", feature = "std"))] + +extern crate std; + +use bincode::config::Configuration; +use chrono::{DateTime, Utc}; +use serde_incl::de::DeserializeOwned; +use std::collections::HashMap; +use std::prelude::rust_2021::*; +use uuid::Uuid; + +#[derive(serde_derive::Serialize, serde_derive::Deserialize, PartialEq, Debug)] +#[serde(crate = "serde_incl")] +pub struct MyStruct { + name: String, +} + +#[derive(serde_derive::Serialize, serde_derive::Deserialize, PartialEq, Debug)] +#[serde(crate = "serde_incl")] +pub struct CustomerTest { + pub id: Option, + pub email_address: Option, + pub is_active: Option, + pub date_stamp: Option>, +} + +#[test] +fn test() { + let test = MyStruct { + name: "Test Value".into(), + }; + let cache_id = Uuid::nil(); + let cache = MemCache::default(); + + cache.set_data::(&cache_id, &test, 5).unwrap(); + let model = cache.get_data::(&cache_id).unwrap(); + assert_eq!(test, model); + + let test = CustomerTest { + id: Some(Uuid::nil()), + email_address: Some("foo@bar".into()), + is_active: None, + date_stamp: Some(Utc::now()), + }; + + cache.set_data::(&cache_id, &test, 5).unwrap(); + let model = cache.get_data::(&cache_id).unwrap(); + assert_eq!(test, model); +} + +#[derive(Default)] +struct MemCache { + cache: std::sync::RwLock>, +} + +impl MemCache { + fn set_data( + &self, + key: &Uuid, + cache_data: &T, + expire_seconds: i64, + ) -> Result<(), bincode::error::EncodeError> + where + T: Send + Sync + serde_incl::Serialize, + { + let config = Configuration::standard(); + let mut guard = self.cache.write().unwrap(); + + let encoded = bincode::serde::encode_to_vec(&cache_data, config)?; + let cache_item = CacheItem::new(encoded, expire_seconds); + + guard.insert(key.clone(), cache_item); + Ok(()) + } + + fn get_data(&self, key: &Uuid) -> Result + where + T: Send + Sync + DeserializeOwned, + { + let config = Configuration::standard(); + let guard = self.cache.read().unwrap(); + let cache_item = guard.get(key).unwrap(); + let (decoded, _len): (T, usize) = + bincode::serde::decode_from_slice(&cache_item.payload[..], config)?; + Ok(decoded) + } +} + +struct CacheItem { + payload: Vec, +} + +impl CacheItem { + fn new(payload: Vec, _expire_seconds: i64) -> Self { + Self { payload } + } +}