Factor the custom Serde Visitor out into a generic type.

This commit is contained in:
Jimmy Cuadra 2016-07-29 17:37:08 -07:00
parent 01d22eb526
commit d11ef217a2
6 changed files with 56 additions and 106 deletions

View File

@ -5,8 +5,9 @@
use std::fmt::{Display, Formatter, Error as FmtError};
use std::str::FromStr;
use serde::{Deserialize, Deserializer, Error as SerdeError, Serialize, Serializer};
use serde::de::Visitor;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use {ParseError, Visitor};
pub mod answer;
pub mod candidates;
@ -31,9 +32,6 @@ pub enum SessionDescriptionType {
Offer,
}
/// An error when attempting to parse an invalid `SessionDescriptionType` from a string.
pub struct SessionDescriptionTypeParseError;
impl Display for SessionDescriptionType {
fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> {
let session_description_type_str = match *self {
@ -46,13 +44,13 @@ impl Display for SessionDescriptionType {
}
impl FromStr for SessionDescriptionType {
type Err = SessionDescriptionTypeParseError;
type Err = ParseError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"answer" => Ok(SessionDescriptionType::Answer),
"offer" => Ok(SessionDescriptionType::Offer),
_ => Err(SessionDescriptionTypeParseError),
_ => Err(ParseError),
}
}
}
@ -65,19 +63,7 @@ impl Serialize for SessionDescriptionType {
impl Deserialize for SessionDescriptionType {
fn deserialize<D>(deserializer: &mut D) -> Result<Self, D::Error> where D: Deserializer {
struct SessionDescriptionTypeVisitor;
impl Visitor for SessionDescriptionTypeVisitor {
type Value = SessionDescriptionType;
fn visit_str<E>(&mut self, v: &str) -> Result<Self::Value, E> where E: SerdeError {
v.parse().map_err(|_| {
E::invalid_value(v)
})
}
}
deserializer.deserialize_str(SessionDescriptionTypeVisitor)
deserializer.deserialize_str(Visitor::new())
}
}

View File

@ -10,10 +10,12 @@ extern crate serde;
extern crate serde_json;
use std::fmt::{Display, Formatter, Error as FmtError};
use std::marker::PhantomData;
use std::str::FromStr;
use ruma_identifiers::{EventId, RoomId, UserId};
use serde::{Deserialize, Deserializer, Error as SerdeError, Serialize, Serializer};
use serde::de::Visitor;
use serde::de::Visitor as SerdeVisitor;
use serde_json::Value;
pub mod call;
@ -152,6 +154,14 @@ pub struct StateEvent<C, E> where C: Deserialize + Serialize, E: Deserialize + S
pub user_id: UserId,
}
/// An error when attempting to convert a string to an enum that only accepts certain values.
pub struct ParseError;
/// A Serde `Visitor` for deserializing various ruma-events enums.
struct Visitor<T> where T: Deserialize + FromStr {
_phantom: PhantomData<T>,
}
impl Display for EventType {
fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> {
let event_type_str = match *self {
@ -224,7 +234,7 @@ impl Deserialize for EventType {
fn deserialize<D>(deserializer: &mut D) -> Result<Self, D::Error> where D: Deserializer {
struct EventTypeVisitor;
impl Visitor for EventTypeVisitor {
impl SerdeVisitor for EventTypeVisitor {
type Value = EventType;
fn visit_str<E>(&mut self, v: &str) -> Result<Self::Value, E> where E: SerdeError {
@ -236,6 +246,24 @@ impl Deserialize for EventType {
}
}
impl<T> Visitor<T> where T: Deserialize + FromStr {
pub fn new() -> Visitor<T> {
Visitor {
_phantom: PhantomData,
}
}
}
impl<T> SerdeVisitor for Visitor<T> where T: Deserialize + FromStr {
type Value = T;
fn visit_str<E>(&mut self, v: &str) -> Result<Self::Value, E> where E: SerdeError {
v.parse().map_err(|_| {
E::invalid_value(v)
})
}
}
#[cfg(test)]
mod tests {
use serde_json::{from_str, to_string};

View File

@ -4,10 +4,9 @@ use std::fmt::{Display, Formatter, Error as FmtError};
use std::str::FromStr;
use ruma_identifiers::{EventId, UserId};
use serde::{Deserialize, Deserializer, Error as SerdeError, Serialize, Serializer};
use serde::de::Visitor;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use Event;
use {Event, ParseError, Visitor};
/// Informs the client of a user's presence state change.
pub type PresenceEvent = Event<PresenceEventContent, PresenceEventExtraContent>;
@ -54,9 +53,6 @@ pub struct PresenceEventExtraContent {
pub event_id: EventId,
}
/// An error when attempting to parse an invalid `PresenceState` from a string.
pub struct PresenceStateParseError;
impl Display for PresenceState {
fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> {
let presence_state_str = match *self {
@ -70,14 +66,14 @@ impl Display for PresenceState {
}
impl FromStr for PresenceState {
type Err = PresenceStateParseError;
type Err = ParseError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"offline" => Ok(PresenceState::Offline),
"online" => Ok(PresenceState::Online),
"unavailable" => Ok(PresenceState::Unavailable),
_ => Err(PresenceStateParseError),
_ => Err(ParseError),
}
}
}
@ -90,19 +86,7 @@ impl Serialize for PresenceState {
impl Deserialize for PresenceState {
fn deserialize<D>(deserializer: &mut D) -> Result<Self, D::Error> where D: Deserializer {
struct PresenceStateVisitor;
impl Visitor for PresenceStateVisitor {
type Value = PresenceState;
fn visit_str<E>(&mut self, v: &str) -> Result<Self::Value, E> where E: SerdeError {
v.parse().map_err(|_| {
E::invalid_value(v)
})
}
}
deserializer.deserialize_str(PresenceStateVisitor)
deserializer.deserialize_str(Visitor::new())
}
}

View File

@ -3,10 +3,9 @@
use std::fmt::{Display, Formatter, Error as FmtError};
use std::str::FromStr;
use serde::{Deserialize, Deserializer, Error as SerdeError, Serialize, Serializer};
use serde::de::Visitor;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use StateEvent;
use {StateEvent, ParseError, Visitor};
/// Controls whether guest users are allowed to join rooms.
///
@ -31,9 +30,6 @@ pub enum GuestAccess {
Forbidden,
}
/// An error when attempting to parse an invalid `PresenceState` from a string.
pub struct GuestAccessParseError;
impl Display for GuestAccess {
fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> {
let guest_access_str = match *self {
@ -46,13 +42,13 @@ impl Display for GuestAccess {
}
impl FromStr for GuestAccess {
type Err = GuestAccessParseError;
type Err = ParseError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"can_join" => Ok(GuestAccess::CanJoin),
"forbidden" => Ok(GuestAccess::Forbidden),
_ => Err(GuestAccessParseError),
_ => Err(ParseError),
}
}
}
@ -65,19 +61,7 @@ impl Serialize for GuestAccess {
impl Deserialize for GuestAccess {
fn deserialize<D>(deserializer: &mut D) -> Result<Self, D::Error> where D: Deserializer {
struct GuestAccessVisitor;
impl Visitor for GuestAccessVisitor {
type Value = GuestAccess;
fn visit_str<E>(&mut self, v: &str) -> Result<Self::Value, E> where E: SerdeError {
v.parse().map_err(|_| {
E::invalid_value(v)
})
}
}
deserializer.deserialize_str(GuestAccessVisitor)
deserializer.deserialize_str(Visitor::new())
}
}

View File

@ -3,10 +3,9 @@
use std::fmt::{Display, Formatter, Error as FmtError};
use std::str::FromStr;
use serde::{Deserialize, Deserializer, Error as SerdeError, Serialize, Serializer};
use serde::de::Visitor;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use StateEvent;
use {StateEvent, ParseError, Visitor};
/// This event controls whether a member of a room can see the events that happened in a room from
/// before they joined.
@ -41,9 +40,6 @@ pub enum HistoryVisibility {
WorldReadable,
}
/// An error when attempting to parse an invalid `HistoryVisibility` from a string.
pub struct HistoryVisibilityParseError;
impl Display for HistoryVisibility {
fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> {
let history_visibility_str = match *self {
@ -58,7 +54,7 @@ impl Display for HistoryVisibility {
}
impl FromStr for HistoryVisibility {
type Err = HistoryVisibilityParseError;
type Err = ParseError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
@ -66,7 +62,7 @@ impl FromStr for HistoryVisibility {
"joined" => Ok(HistoryVisibility::Joined),
"shared" => Ok(HistoryVisibility::Shared),
"world_readable" => Ok(HistoryVisibility::WorldReadable),
_ => Err(HistoryVisibilityParseError),
_ => Err(ParseError),
}
}
}
@ -79,19 +75,7 @@ impl Serialize for HistoryVisibility {
impl Deserialize for HistoryVisibility {
fn deserialize<D>(deserializer: &mut D) -> Result<Self, D::Error> where D: Deserializer {
struct HistoryVisibilityVisitor;
impl Visitor for HistoryVisibilityVisitor {
type Value = HistoryVisibility;
fn visit_str<E>(&mut self, v: &str) -> Result<Self::Value, E> where E: SerdeError {
v.parse().map_err(|_| {
E::invalid_value(v)
})
}
}
deserializer.deserialize_str(HistoryVisibilityVisitor)
deserializer.deserialize_str(Visitor::new())
}
}

View File

@ -3,10 +3,9 @@
use std::fmt::{Display, Formatter, Error as FmtError};
use std::str::FromStr;
use serde::{Deserialize, Deserializer, Error as SerdeError, Serialize, Serializer};
use serde::de::Visitor;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use StateEvent;
use {StateEvent, ParseError, Visitor};
/// Describes how users are allowed to join the room.
pub type JoinRulesEvent = StateEvent<JoinRulesEventContent, ()>;
@ -35,9 +34,6 @@ pub enum JoinRule {
Public,
}
/// An error when attempting to parse an invalid `JoinRule` from a string.
pub struct JoinRuleParseError;
impl Display for JoinRule {
fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> {
let join_rule_str = match *self {
@ -52,7 +48,7 @@ impl Display for JoinRule {
}
impl FromStr for JoinRule {
type Err = JoinRuleParseError;
type Err = ParseError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
@ -60,7 +56,7 @@ impl FromStr for JoinRule {
"knock" => Ok(JoinRule::Knock),
"private" => Ok(JoinRule::Private),
"public" => Ok(JoinRule::Public),
_ => Err(JoinRuleParseError),
_ => Err(ParseError),
}
}
}
@ -73,19 +69,7 @@ impl Serialize for JoinRule {
impl Deserialize for JoinRule {
fn deserialize<D>(deserializer: &mut D) -> Result<Self, D::Error> where D: Deserializer {
struct JoinRuleVisitor;
impl Visitor for JoinRuleVisitor {
type Value = JoinRule;
fn visit_str<E>(&mut self, v: &str) -> Result<Self::Value, E> where E: SerdeError {
v.parse().map_err(|_| {
E::invalid_value(v)
})
}
}
deserializer.deserialize_str(JoinRuleVisitor)
deserializer.deserialize_str(Visitor::new())
}
}