Skip to content

Commit 3322cd4

Browse files
bors[bot]Brendan Molloy
and
Brendan Molloy
authored
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 <[email protected]>
2 parents 2df9502 + 0bf0169 commit 3322cd4

File tree

3 files changed

+163
-12
lines changed

3 files changed

+163
-12
lines changed

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,15 @@ authors = ["Aleksey Kladov <[email protected]>"]
55
repository = "https://github.com/matklad/smol_str"
66
description = "small-string optimized string type with O(1) clone"
77
license = "MIT OR Apache-2.0"
8+
edition = "2018"
89

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

1213
[dev-dependencies]
1314
proptest = "0.8.3"
1415
serde_json = "1"
16+
serde = { version = "1", features = [ "derive" ] }
1517
criterion = "0.2"
1618

1719
[[bench]]

src/lib.rs

Lines changed: 75 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -408,9 +408,81 @@ impl Repr {
408408

409409
#[cfg(feature = "serde")]
410410
mod serde {
411-
extern crate serde;
411+
use ::serde::de::{Deserializer, Error, Unexpected, Visitor};
412+
use std::fmt;
413+
use super::SmolStr;
412414

413-
use SmolStr;
415+
// https://github.com/serde-rs/serde/blob/629802f2abfd1a54a6072992888fea7ca5bc209f/serde/src/private/de.rs#L56-L125
416+
fn smol_str<'de: 'a, 'a, D>(deserializer: D) -> Result<SmolStr, D::Error>
417+
where
418+
D: Deserializer<'de>,
419+
{
420+
struct SmolStrVisitor;
421+
422+
impl<'a> Visitor<'a> for SmolStrVisitor {
423+
type Value = SmolStr;
424+
425+
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
426+
formatter.write_str("a string")
427+
}
428+
429+
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
430+
where
431+
E: Error,
432+
{
433+
Ok(SmolStr::from(v))
434+
}
435+
436+
fn visit_borrowed_str<E>(self, v: &'a str) -> Result<Self::Value, E>
437+
where
438+
E: Error,
439+
{
440+
Ok(SmolStr::from(v))
441+
}
442+
443+
fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
444+
where
445+
E: Error,
446+
{
447+
Ok(SmolStr::from(v))
448+
}
449+
450+
fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
451+
where
452+
E: Error,
453+
{
454+
match std::str::from_utf8(v) {
455+
Ok(s) => Ok(SmolStr::from(s)),
456+
Err(_) => Err(Error::invalid_value(Unexpected::Bytes(v), &self)),
457+
}
458+
}
459+
460+
fn visit_borrowed_bytes<E>(self, v: &'a [u8]) -> Result<Self::Value, E>
461+
where
462+
E: Error,
463+
{
464+
match std::str::from_utf8(v) {
465+
Ok(s) => Ok(SmolStr::from(s)),
466+
Err(_) => Err(Error::invalid_value(Unexpected::Bytes(v), &self)),
467+
}
468+
}
469+
470+
fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E>
471+
where
472+
E: Error,
473+
{
474+
match String::from_utf8(v) {
475+
Ok(s) => Ok(SmolStr::from(s)),
476+
Err(e) => Err(Error::invalid_value(
477+
Unexpected::Bytes(&e.into_bytes()),
478+
&self,
479+
)),
480+
}
481+
}
482+
}
483+
484+
deserializer.deserialize_str(SmolStrVisitor)
485+
}
414486

415487
impl serde::Serialize for SmolStr {
416488
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
@@ -426,7 +498,7 @@ mod serde {
426498
where
427499
D: serde::Deserializer<'de>,
428500
{
429-
<&'de str>::deserialize(deserializer).map(SmolStr::from)
501+
smol_str(deserializer)
430502
}
431503
}
432504
}

tests/test.rs

Lines changed: 86 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
extern crate serde_json;
2-
extern crate smol_str;
31
#[macro_use]
42
extern crate proptest;
53

@@ -87,13 +85,92 @@ proptest! {
8785
}
8886

8987
#[cfg(feature = "serde")]
90-
#[test]
91-
fn test_serde() {
92-
let s = SmolStr::new("Hello, World");
93-
let s = serde_json::to_string(&s).unwrap();
94-
assert_eq!(s, "\"Hello, World\"");
95-
let s: SmolStr = serde_json::from_str(&s).unwrap();
96-
assert_eq!(s, "Hello, World");
88+
mod serde_tests {
89+
use super::*;
90+
use serde::{Serialize, Deserialize};
91+
use std::collections::HashMap;
92+
93+
#[derive(Serialize, Deserialize)]
94+
struct SmolStrStruct {
95+
pub(crate) s: SmolStr,
96+
pub(crate) vec: Vec<SmolStr>,
97+
pub(crate) map: HashMap<SmolStr, SmolStr>,
98+
}
99+
100+
#[test]
101+
fn test_serde() {
102+
let s = SmolStr::new("Hello, World");
103+
let s = serde_json::to_string(&s).unwrap();
104+
assert_eq!(s, "\"Hello, World\"");
105+
let s: SmolStr = serde_json::from_str(&s).unwrap();
106+
assert_eq!(s, "Hello, World");
107+
}
108+
109+
#[test]
110+
fn test_serde_reader() {
111+
let s = SmolStr::new("Hello, World");
112+
let s = serde_json::to_string(&s).unwrap();
113+
assert_eq!(s, "\"Hello, World\"");
114+
let s: SmolStr = serde_json::from_reader(std::io::Cursor::new(s)).unwrap();
115+
assert_eq!(s, "Hello, World");
116+
}
117+
118+
#[test]
119+
fn test_serde_struct() {
120+
let mut map = HashMap::new();
121+
map.insert(SmolStr::new("a"), SmolStr::new("ohno"));
122+
let struct_ = SmolStrStruct {
123+
s: SmolStr::new("Hello, World"),
124+
vec: vec![SmolStr::new("Hello, World"), SmolStr::new("Hello, World")],
125+
map,
126+
};
127+
let s = serde_json::to_string(&struct_).unwrap();
128+
let _new_struct: SmolStrStruct = serde_json::from_str(&s).unwrap();
129+
}
130+
131+
#[test]
132+
fn test_serde_struct_reader() {
133+
let mut map = HashMap::new();
134+
map.insert(SmolStr::new("a"), SmolStr::new("ohno"));
135+
let struct_ = SmolStrStruct {
136+
s: SmolStr::new("Hello, World"),
137+
vec: vec![SmolStr::new("Hello, World"), SmolStr::new("Hello, World")],
138+
map,
139+
};
140+
let s = serde_json::to_string(&struct_).unwrap();
141+
let _new_struct: SmolStrStruct = serde_json::from_reader(std::io::Cursor::new(s)).unwrap();
142+
}
143+
144+
#[test]
145+
fn test_serde_hashmap() {
146+
let mut map = HashMap::new();
147+
map.insert(SmolStr::new("a"), SmolStr::new("ohno"));
148+
let s = serde_json::to_string(&map).unwrap();
149+
let _s: HashMap<SmolStr, SmolStr> = serde_json::from_str(&s).unwrap();
150+
}
151+
152+
#[test]
153+
fn test_serde_hashmap_reader() {
154+
let mut map = HashMap::new();
155+
map.insert(SmolStr::new("a"), SmolStr::new("ohno"));
156+
let s = serde_json::to_string(&map).unwrap();
157+
let _s: HashMap<SmolStr, SmolStr> =
158+
serde_json::from_reader(std::io::Cursor::new(s)).unwrap();
159+
}
160+
161+
#[test]
162+
fn test_serde_vec() {
163+
let vec = vec![SmolStr::new(""), SmolStr::new("b")];
164+
let s = serde_json::to_string(&vec).unwrap();
165+
let _s: Vec<SmolStr> = serde_json::from_str(&s).unwrap();
166+
}
167+
168+
#[test]
169+
fn test_serde_vec_reader() {
170+
let vec = vec![SmolStr::new(""), SmolStr::new("b")];
171+
let s = serde_json::to_string(&vec).unwrap();
172+
let _s: Vec<SmolStr> = serde_json::from_reader(std::io::Cursor::new(s)).unwrap();
173+
}
97174
}
98175

99176
#[test]

0 commit comments

Comments
 (0)