Skip to content

Commit

Permalink
Merge rust-lang#15
Browse files Browse the repository at this point in the history
15: Fix from_reader breaking in serde r=matklad a=bbqsrc

Had to move the `extern crate` outside as otherwise the compiler wouldn't have it.

Co-authored-by: Brendan Molloy <brendan@technocreatives.com>
  • Loading branch information
bors[bot] and Brendan Molloy authored Sep 26, 2019
2 parents 2df9502 + 0bf0169 commit 3322cd4
Show file tree
Hide file tree
Showing 3 changed files with 163 additions and 12 deletions.
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@ authors = ["Aleksey Kladov <aleksey.kladov@gmail.com>"]
repository = "https://github.com/matklad/smol_str"
description = "small-string optimized string type with O(1) clone"
license = "MIT OR Apache-2.0"
edition = "2018"

[dependencies]
serde = { version = "1", optional = true, default_features = false }

[dev-dependencies]
proptest = "0.8.3"
serde_json = "1"
serde = { version = "1", features = [ "derive" ] }
criterion = "0.2"

[[bench]]
Expand Down
78 changes: 75 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -408,9 +408,81 @@ impl Repr {

#[cfg(feature = "serde")]
mod serde {
extern crate serde;
use ::serde::de::{Deserializer, Error, Unexpected, Visitor};
use std::fmt;
use super::SmolStr;

use SmolStr;
// https://github.com/serde-rs/serde/blob/629802f2abfd1a54a6072992888fea7ca5bc209f/serde/src/private/de.rs#L56-L125
fn smol_str<'de: 'a, 'a, D>(deserializer: D) -> Result<SmolStr, D::Error>
where
D: Deserializer<'de>,
{
struct SmolStrVisitor;

impl<'a> Visitor<'a> for SmolStrVisitor {
type Value = SmolStr;

fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("a string")
}

fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where
E: Error,
{
Ok(SmolStr::from(v))
}

fn visit_borrowed_str<E>(self, v: &'a str) -> Result<Self::Value, E>
where
E: Error,
{
Ok(SmolStr::from(v))
}

fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
where
E: Error,
{
Ok(SmolStr::from(v))
}

fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
where
E: Error,
{
match std::str::from_utf8(v) {
Ok(s) => Ok(SmolStr::from(s)),
Err(_) => Err(Error::invalid_value(Unexpected::Bytes(v), &self)),
}
}

fn visit_borrowed_bytes<E>(self, v: &'a [u8]) -> Result<Self::Value, E>
where
E: Error,
{
match std::str::from_utf8(v) {
Ok(s) => Ok(SmolStr::from(s)),
Err(_) => Err(Error::invalid_value(Unexpected::Bytes(v), &self)),
}
}

fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E>
where
E: Error,
{
match String::from_utf8(v) {
Ok(s) => Ok(SmolStr::from(s)),
Err(e) => Err(Error::invalid_value(
Unexpected::Bytes(&e.into_bytes()),
&self,
)),
}
}
}

deserializer.deserialize_str(SmolStrVisitor)
}

impl serde::Serialize for SmolStr {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
Expand All @@ -426,7 +498,7 @@ mod serde {
where
D: serde::Deserializer<'de>,
{
<&'de str>::deserialize(deserializer).map(SmolStr::from)
smol_str(deserializer)
}
}
}
95 changes: 86 additions & 9 deletions tests/test.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
extern crate serde_json;
extern crate smol_str;
#[macro_use]
extern crate proptest;

Expand Down Expand Up @@ -87,13 +85,92 @@ proptest! {
}

#[cfg(feature = "serde")]
#[test]
fn test_serde() {
let s = SmolStr::new("Hello, World");
let s = serde_json::to_string(&s).unwrap();
assert_eq!(s, "\"Hello, World\"");
let s: SmolStr = serde_json::from_str(&s).unwrap();
assert_eq!(s, "Hello, World");
mod serde_tests {
use super::*;
use serde::{Serialize, Deserialize};
use std::collections::HashMap;

#[derive(Serialize, Deserialize)]
struct SmolStrStruct {
pub(crate) s: SmolStr,
pub(crate) vec: Vec<SmolStr>,
pub(crate) map: HashMap<SmolStr, SmolStr>,
}

#[test]
fn test_serde() {
let s = SmolStr::new("Hello, World");
let s = serde_json::to_string(&s).unwrap();
assert_eq!(s, "\"Hello, World\"");
let s: SmolStr = serde_json::from_str(&s).unwrap();
assert_eq!(s, "Hello, World");
}

#[test]
fn test_serde_reader() {
let s = SmolStr::new("Hello, World");
let s = serde_json::to_string(&s).unwrap();
assert_eq!(s, "\"Hello, World\"");
let s: SmolStr = serde_json::from_reader(std::io::Cursor::new(s)).unwrap();
assert_eq!(s, "Hello, World");
}

#[test]
fn test_serde_struct() {
let mut map = HashMap::new();
map.insert(SmolStr::new("a"), SmolStr::new("ohno"));
let struct_ = SmolStrStruct {
s: SmolStr::new("Hello, World"),
vec: vec![SmolStr::new("Hello, World"), SmolStr::new("Hello, World")],
map,
};
let s = serde_json::to_string(&struct_).unwrap();
let _new_struct: SmolStrStruct = serde_json::from_str(&s).unwrap();
}

#[test]
fn test_serde_struct_reader() {
let mut map = HashMap::new();
map.insert(SmolStr::new("a"), SmolStr::new("ohno"));
let struct_ = SmolStrStruct {
s: SmolStr::new("Hello, World"),
vec: vec![SmolStr::new("Hello, World"), SmolStr::new("Hello, World")],
map,
};
let s = serde_json::to_string(&struct_).unwrap();
let _new_struct: SmolStrStruct = serde_json::from_reader(std::io::Cursor::new(s)).unwrap();
}

#[test]
fn test_serde_hashmap() {
let mut map = HashMap::new();
map.insert(SmolStr::new("a"), SmolStr::new("ohno"));
let s = serde_json::to_string(&map).unwrap();
let _s: HashMap<SmolStr, SmolStr> = serde_json::from_str(&s).unwrap();
}

#[test]
fn test_serde_hashmap_reader() {
let mut map = HashMap::new();
map.insert(SmolStr::new("a"), SmolStr::new("ohno"));
let s = serde_json::to_string(&map).unwrap();
let _s: HashMap<SmolStr, SmolStr> =
serde_json::from_reader(std::io::Cursor::new(s)).unwrap();
}

#[test]
fn test_serde_vec() {
let vec = vec![SmolStr::new(""), SmolStr::new("b")];
let s = serde_json::to_string(&vec).unwrap();
let _s: Vec<SmolStr> = serde_json::from_str(&s).unwrap();
}

#[test]
fn test_serde_vec_reader() {
let vec = vec![SmolStr::new(""), SmolStr::new("b")];
let s = serde_json::to_string(&vec).unwrap();
let _s: Vec<SmolStr> = serde_json::from_reader(std::io::Cursor::new(s)).unwrap();
}
}

#[test]
Expand Down

0 comments on commit 3322cd4

Please sign in to comment.