Avoid creating owned strings in deserialization where not necessary
This commit is contained in:
parent
62d5108633
commit
f2a78babbd
@ -249,7 +249,7 @@ impl<'de> Deserialize<'de> for ErrCode {
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let s = Cow::<'de, str>::deserialize(deserializer)?;
|
||||
let s = ruma_serde::deserialize_cow_str(deserializer)?;
|
||||
Ok(s.into())
|
||||
}
|
||||
}
|
||||
|
@ -62,10 +62,9 @@ impl<'de> Deserialize<'de> for DeviceIdOrAllDevices {
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let value = &String::deserialize(deserializer)?;
|
||||
|
||||
DeviceIdOrAllDevices::try_from(&value[..]).map_err(|_| {
|
||||
de::Error::invalid_value(Unexpected::Str(&value), &"a valid device identifier or '*'")
|
||||
let s = ruma_serde::deserialize_cow_str(deserializer)?;
|
||||
DeviceIdOrAllDevices::try_from(s.as_ref()).map_err(|_| {
|
||||
de::Error::invalid_value(Unexpected::Str(&s), &"a valid device identifier or '*'")
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -151,7 +151,7 @@ impl<'de> Deserialize<'de> for RoomMemberCountIs {
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let s = String::deserialize(deserializer)?;
|
||||
let s = ruma_serde::deserialize_cow_str(deserializer)?;
|
||||
FromStr::from_str(&s).map_err(serde::de::Error::custom)
|
||||
}
|
||||
}
|
||||
|
@ -28,6 +28,7 @@ either = { version = "1.5.3", optional = true }
|
||||
rand = { version = "0.7.3", optional = true }
|
||||
ruma-identifiers-macros = { version = "=0.17.4", path = "../ruma-identifiers-macros" }
|
||||
ruma-identifiers-validation = { version = "0.1.1", path = "../ruma-identifiers-validation", default-features = false }
|
||||
ruma-serde = { version = "0.2.3", path = "../ruma-serde" }
|
||||
# Renamed so we can have a serde feature.
|
||||
serde1 = { package = "serde", version = "1.0.114", optional = true, features = ["derive"] }
|
||||
strum = { version = "0.19.2", features = ["derive"] }
|
||||
|
@ -17,7 +17,7 @@ extern crate serde1 as serde;
|
||||
use std::convert::TryFrom;
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
use serde::de::{self, Deserialize as _, Deserializer, Unexpected};
|
||||
use serde::de::{self, Deserializer, Unexpected};
|
||||
|
||||
#[doc(inline)]
|
||||
pub use crate::{
|
||||
@ -81,7 +81,7 @@ where
|
||||
D: Deserializer<'de>,
|
||||
T: for<'a> std::convert::TryFrom<&'a str>,
|
||||
{
|
||||
std::borrow::Cow::<'_, str>::deserialize(deserializer).and_then(|v| {
|
||||
ruma_serde::deserialize_cow_str(deserializer).and_then(|v| {
|
||||
T::try_from(&v).map_err(|_| de::Error::invalid_value(Unexpected::Str(&v), &expected_str))
|
||||
})
|
||||
}
|
||||
|
71
ruma-serde/src/cow.rs
Normal file
71
ruma-serde/src/cow.rs
Normal file
@ -0,0 +1,71 @@
|
||||
use std::{borrow::Cow, str};
|
||||
|
||||
use serde::de::{self, Deserializer, Unexpected, Visitor};
|
||||
|
||||
pub fn deserialize_cow_str<'de, D>(deserializer: D) -> Result<Cow<'de, str>, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
deserializer.deserialize_string(CowStrVisitor)
|
||||
}
|
||||
|
||||
struct CowStrVisitor;
|
||||
|
||||
impl<'de> Visitor<'de> for CowStrVisitor {
|
||||
type Value = Cow<'de, str>;
|
||||
|
||||
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
formatter.write_str("a string")
|
||||
}
|
||||
|
||||
fn visit_borrowed_str<E>(self, v: &'de str) -> Result<Self::Value, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
Ok(Cow::Borrowed(v))
|
||||
}
|
||||
|
||||
fn visit_borrowed_bytes<E>(self, v: &'de [u8]) -> Result<Self::Value, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
match str::from_utf8(v) {
|
||||
Ok(s) => Ok(Cow::Borrowed(s)),
|
||||
Err(_) => Err(de::Error::invalid_value(Unexpected::Bytes(v), &self)),
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
Ok(Cow::Owned(v.to_owned()))
|
||||
}
|
||||
|
||||
fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
Ok(Cow::Owned(v))
|
||||
}
|
||||
|
||||
fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
match str::from_utf8(v) {
|
||||
Ok(s) => Ok(Cow::Owned(s.to_owned())),
|
||||
Err(_) => Err(de::Error::invalid_value(Unexpected::Bytes(v), &self)),
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
match String::from_utf8(v) {
|
||||
Ok(s) => Ok(Cow::Owned(s)),
|
||||
Err(e) => Err(de::Error::invalid_value(Unexpected::Bytes(&e.into_bytes()), &self)),
|
||||
}
|
||||
}
|
||||
}
|
@ -2,7 +2,7 @@
|
||||
//! string.
|
||||
|
||||
use serde::{
|
||||
de::{Deserialize, DeserializeOwned, Deserializer, Error as _},
|
||||
de::{DeserializeOwned, Deserializer, Error as _},
|
||||
ser::{Error as _, Serialize, Serializer},
|
||||
};
|
||||
|
||||
@ -20,6 +20,6 @@ where
|
||||
T: DeserializeOwned,
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let s = String::deserialize(deserializer)?;
|
||||
let s = crate::deserialize_cow_str(deserializer)?;
|
||||
serde_json::from_str(&s).map_err(D::Error::custom)
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ use serde::de::{Deserialize, IntoDeserializer};
|
||||
|
||||
pub mod can_be_empty;
|
||||
mod canonical_json;
|
||||
mod cow;
|
||||
pub mod duration;
|
||||
pub mod empty;
|
||||
pub mod json_string;
|
||||
@ -16,6 +17,7 @@ pub use can_be_empty::{is_empty, CanBeEmpty};
|
||||
pub use canonical_json::{
|
||||
to_string as to_canonical_json_string, value::CanonicalJsonValue, Error as CanonicalJsonError,
|
||||
};
|
||||
pub use cow::deserialize_cow_str;
|
||||
pub use empty::vec_as_map_of_empty;
|
||||
|
||||
/// Check whether a value is equal to its default value.
|
||||
|
Loading…
x
Reference in New Issue
Block a user