Further simplify deserialization

This commit is contained in:
Jonas Platte 2019-12-10 22:42:46 +01:00
parent d120f77635
commit 32733cf782
No known key found for this signature in database
GPG Key ID: 7D261D771D915378
7 changed files with 41 additions and 104 deletions

View File

@ -7,13 +7,10 @@ use std::{
#[cfg(feature = "diesel")]
use diesel::sql_types::Text;
use serde::{
de::{Error as SerdeError, Expected, Unexpected},
Deserialize, Deserializer, Serialize, Serializer,
};
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use url::Host;
use crate::{display, error::Error, generate_localpart, parse_id};
use crate::{deserialize_id, display, error::Error, generate_localpart, parse_id};
/// A Matrix event ID.
///
@ -155,10 +152,7 @@ impl<'de> Deserialize<'de> for EventId {
where
D: Deserializer<'de>,
{
String::deserialize(deserializer).and_then(|v| {
EventId::try_from(&v as &str)
.map_err(|_| SerdeError::invalid_value(Unexpected::Str(&v), &ExpectedEventId))
})
deserialize_id(deserializer, "a Matrix event ID as a string")
}
}
@ -189,14 +183,6 @@ impl<'a> TryFrom<&'a str> for EventId {
}
}
struct ExpectedEventId;
impl Expected for ExpectedEventId {
fn fmt(&self, formatter: &mut Formatter<'_>) -> FmtResult {
write!(formatter, "a Matrix event ID as a string")
}
}
#[cfg(test)]
mod tests {
use std::convert::TryFrom;

View File

@ -14,9 +14,13 @@
#[cfg_attr(feature = "diesel", macro_use)]
extern crate diesel;
use std::fmt::{Formatter, Result as FmtResult};
use std::{
convert::TryFrom,
fmt::{Formatter, Result as FmtResult},
};
use rand::{distributions::Alphanumeric, thread_rng, Rng};
use serde::de::{self, Deserialize as _, Deserializer, Unexpected};
use url::Url;
pub use url::Host;
@ -112,3 +116,16 @@ fn parse_id(required_sigil: char, id: &str) -> Result<(&str, Host, u16), Error>
Ok((localpart, host, port))
}
/// Deserializes any type of id using the provided TryFrom implementation.
///
/// This is a helper function to reduce the boilerplate of the Deserialize implementations.
fn deserialize_id<'de, D, T>(deserializer: D, expected_str: &str) -> Result<T, D::Error>
where
D: Deserializer<'de>,
T: for<'a> TryFrom<&'a str>,
{
String::deserialize(deserializer).and_then(|v| {
T::try_from(&v).map_err(|_| de::Error::invalid_value(Unexpected::Str(&v), &expected_str))
})
}

View File

@ -7,13 +7,10 @@ use std::{
#[cfg(feature = "diesel")]
use diesel::sql_types::Text;
use serde::{
de::{Error as SerdeError, Expected, Unexpected},
Deserialize, Deserializer, Serialize, Serializer,
};
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use url::Host;
use crate::{display, error::Error, parse_id};
use crate::{deserialize_id, display, error::Error, parse_id};
/// A Matrix room alias ID.
///
@ -80,10 +77,7 @@ impl<'de> Deserialize<'de> for RoomAliasId {
where
D: Deserializer<'de>,
{
String::deserialize(deserializer).and_then(|v| {
RoomAliasId::try_from(&v as &str)
.map_err(|_| SerdeError::invalid_value(Unexpected::Str(&v), &ExpectedRoomAliasId))
})
deserialize_id(deserializer, "a Matrix room alias ID as a string")
}
}
@ -105,14 +99,6 @@ impl<'a> TryFrom<&'a str> for RoomAliasId {
}
}
struct ExpectedRoomAliasId;
impl Expected for ExpectedRoomAliasId {
fn fmt(&self, formatter: &mut Formatter<'_>) -> FmtResult {
write!(formatter, "a Matrix room alias ID as a string")
}
}
#[cfg(test)]
mod tests {
use std::convert::TryFrom;

View File

@ -7,13 +7,10 @@ use std::{
#[cfg(feature = "diesel")]
use diesel::sql_types::Text;
use serde::{
de::{Error as SerdeError, Expected, Unexpected},
Deserialize, Deserializer, Serialize, Serializer,
};
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use url::Host;
use crate::{display, error::Error, generate_localpart, parse_id};
use crate::{deserialize_id, display, error::Error, generate_localpart, parse_id};
/// A Matrix room ID.
///
@ -95,10 +92,7 @@ impl<'de> Deserialize<'de> for RoomId {
where
D: Deserializer<'de>,
{
String::deserialize(deserializer).and_then(|v| {
RoomId::try_from(&v as &str)
.map_err(|_| SerdeError::invalid_value(Unexpected::Str(&v), &ExpectedRoomId))
})
deserialize_id(deserializer, "a Matrix room ID as a string")
}
}
@ -120,14 +114,6 @@ impl<'a> TryFrom<&'a str> for RoomId {
}
}
struct ExpectedRoomId;
impl Expected for ExpectedRoomId {
fn fmt(&self, formatter: &mut Formatter<'_>) -> FmtResult {
write!(formatter, "a Matrix room ID as a string")
}
}
#[cfg(test)]
mod tests {
use std::convert::TryFrom;

View File

@ -7,12 +7,11 @@ use std::{
#[cfg(feature = "diesel")]
use diesel::sql_types::Text;
use serde::{
de::{Error as SerdeError, Expected, Unexpected},
Deserialize, Deserializer, Serialize, Serializer,
};
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use crate::{display, error::Error, room_alias_id::RoomAliasId, room_id::RoomId, validate_id};
use crate::{
deserialize_id, display, error::Error, room_alias_id::RoomAliasId, room_id::RoomId, validate_id,
};
/// A Matrix room ID or a Matrix room alias ID.
///
@ -83,11 +82,10 @@ impl<'de> Deserialize<'de> for RoomIdOrAliasId {
where
D: Deserializer<'de>,
{
String::deserialize(deserializer).and_then(|v| {
RoomIdOrAliasId::try_from(&v as &str).map_err(|_| {
SerdeError::invalid_value(Unexpected::Str(&v), &ExpectedRoomIdOrAliasId)
})
})
deserialize_id(
deserializer,
"a Matrix room ID or room alias ID as a string",
)
}
}
@ -120,14 +118,6 @@ impl<'a> TryFrom<&'a str> for RoomIdOrAliasId {
}
}
struct ExpectedRoomIdOrAliasId;
impl Expected for ExpectedRoomIdOrAliasId {
fn fmt(&self, formatter: &mut Formatter<'_>) -> FmtResult {
write!(formatter, "a Matrix room ID or room alias ID as a string")
}
}
#[cfg(test)]
mod tests {
use std::convert::TryFrom;

View File

@ -7,12 +7,9 @@ use std::{
#[cfg(feature = "diesel")]
use diesel::sql_types::Text;
use serde::{
de::{Error as SerdeError, Expected, Unexpected},
Deserialize, Deserializer, Serialize, Serializer,
};
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use crate::error::Error;
use crate::{deserialize_id, error::Error};
/// Room version identifiers cannot be more than 32 code points.
const MAX_CODE_POINTS: usize = 32;
@ -154,10 +151,7 @@ impl<'de> Deserialize<'de> for RoomVersionId {
where
D: Deserializer<'de>,
{
String::deserialize(deserializer).and_then(|v| {
RoomVersionId::try_from(&v as &str)
.map_err(|_| SerdeError::invalid_value(Unexpected::Str(&v), &ExpectedRoomVersionId))
})
deserialize_id(deserializer, "a Matrix room version ID as a string")
}
}
@ -187,14 +181,6 @@ impl<'a> TryFrom<&'a str> for RoomVersionId {
}
}
struct ExpectedRoomVersionId;
impl Expected for ExpectedRoomVersionId {
fn fmt(&self, formatter: &mut Formatter<'_>) -> FmtResult {
write!(formatter, "a Matrix room version ID as a string")
}
}
#[cfg(test)]
mod tests {
use std::convert::TryFrom;

View File

@ -7,13 +7,10 @@ use std::{
#[cfg(feature = "diesel")]
use diesel::sql_types::Text;
use serde::{
de::{Error as SerdeError, Expected, Unexpected},
Deserialize, Deserializer, Serialize, Serializer,
};
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use url::Host;
use crate::{display, error::Error, generate_localpart, parse_id};
use crate::{deserialize_id, display, error::Error, generate_localpart, parse_id};
/// A Matrix user ID.
///
@ -99,10 +96,7 @@ impl<'de> Deserialize<'de> for UserId {
where
D: Deserializer<'de>,
{
String::deserialize(deserializer).and_then(|v| {
UserId::try_from(&v as &str)
.map_err(|_| SerdeError::invalid_value(Unexpected::Str(&v), &ExpectedUserId))
})
deserialize_id(deserializer, "a Matrix user ID as a string")
}
}
@ -133,14 +127,6 @@ impl<'a> TryFrom<&'a str> for UserId {
}
}
struct ExpectedUserId;
impl Expected for ExpectedUserId {
fn fmt(&self, formatter: &mut Formatter<'_>) -> FmtResult {
write!(formatter, "a Matrix user ID as a string")
}
}
#[cfg(test)]
mod tests {
use std::convert::TryFrom;