Skip to content

Commit

Permalink
Made SerdeDecoder attempt to allocate a string before complaining abo…
Browse files Browse the repository at this point in the history
…ut being able to decode borrowed data (#475)
  • Loading branch information
VictorKoenders authored Jan 17, 2022
1 parent f33abb2 commit 447c4c7
Show file tree
Hide file tree
Showing 4 changed files with 121 additions and 1 deletion.
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
20 changes: 19 additions & 1 deletion src/features/serde/de_owned.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
#[cfg(feature = "alloc")]
fn deserialize_str<V>(mut self, visitor: V) -> Result<V::Value, Self::Error>
where
V: serde_incl::de::Visitor<'de>,
{
visitor.visit_string(Decode::decode(&mut self.de)?)
}

#[cfg(not(feature = "alloc"))]
fn deserialize_str<V>(mut self, visitor: V) -> Result<V::Value, Self::Error>
where
V: serde_incl::de::Visitor<'de>,
{
Expand All @@ -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<V>(mut self, visitor: V) -> Result<V::Value, Self::Error>
where
V: serde_incl::de::Visitor<'de>,
{
visitor.visit_byte_buf(Decode::decode(&mut self.de)?)
}

#[cfg(not(feature = "alloc"))]
fn deserialize_bytes<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
where
V: serde_incl::de::Visitor<'de>,
Expand Down
3 changes: 3 additions & 0 deletions tests/issues.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,6 @@ mod issue_467;

#[path = "issues/issue_459.rs"]
mod issue_459;

#[path = "issues/issue_474.rs"]
mod issue_474;
97 changes: 97 additions & 0 deletions tests/issues/issue_474.rs
Original file line number Diff line number Diff line change
@@ -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<Uuid>,
pub email_address: Option<String>,
pub is_active: Option<bool>,
pub date_stamp: Option<DateTime<Utc>>,
}

#[test]
fn test() {
let test = MyStruct {
name: "Test Value".into(),
};
let cache_id = Uuid::nil();
let cache = MemCache::default();

cache.set_data::<MyStruct>(&cache_id, &test, 5).unwrap();
let model = cache.get_data::<MyStruct>(&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::<CustomerTest>(&cache_id, &test, 5).unwrap();
let model = cache.get_data::<CustomerTest>(&cache_id).unwrap();
assert_eq!(test, model);
}

#[derive(Default)]
struct MemCache {
cache: std::sync::RwLock<HashMap<Uuid, CacheItem>>,
}

impl MemCache {
fn set_data<T>(
&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<T>(&self, key: &Uuid) -> Result<T, bincode::error::DecodeError>
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<u8>,
}

impl CacheItem {
fn new(payload: Vec<u8>, _expire_seconds: i64) -> Self {
Self { payload }
}
}

0 comments on commit 447c4c7

Please sign in to comment.