serde_dyn/
lib.rs

1extern crate fnv;
2extern crate serde;
3extern crate type_uuid;
4
5use fnv::FnvHashMap as HashMap;
6use serde::de::{DeserializeOwned, Deserializer};
7use type_uuid::TypeUuid;
8
9use std::any::Any;
10use std::error::Error as StdError;
11use std::fmt::{Debug, Display, Error as FmtError, Formatter};
12
13/// TUSM aka Type Uuid Serde Mapper
14///
15/// This structure maps Type Uuids to Serde functions
16#[derive(Clone, Debug, PartialEq, Eq)]
17pub struct TUSM<'de, D>
18where
19    D: Deserializer<'de>,
20{
21    mapping: HashMap<type_uuid::Bytes, fn(D) -> Result<Box<dyn Any>, D::Error>>,
22}
23
24impl<'de, D> TUSM<'de, D>
25where
26    D: Deserializer<'de>,
27{
28    pub fn new() -> Self {
29        Self {
30            mapping: HashMap::default(),
31        }
32    }
33
34    /// Adds the provided type to the list of types this `TUSM` can deserialize.
35    pub fn register<T: DeserializeOwned + Any + TypeUuid>(&mut self) {
36        self.manually_register(T::UUID, |deserializer| {
37            T::deserialize(deserializer).map(|i| Box::new(i) as Box<dyn Any>)
38        });
39    }
40
41    /// Adds a mapping entry between the provided UUID and the provided deserialization function.
42    ///
43    /// Please only use this if absolutely necessary, `register` is the preferred alternative.
44    pub fn manually_register(
45        &mut self,
46        uuid: type_uuid::Bytes,
47        function: fn(D) -> Result<Box<dyn Any>, D::Error>,
48    ) {
49        self.mapping.insert(uuid, function);
50    }
51
52    /// Using the provided UUID, attempt to deserialize the next value according to previously
53    /// registered mappings.
54    pub fn deserialize_with_uuid(
55        &self,
56        uuid: &type_uuid::Bytes,
57        deserializer: D,
58    ) -> Result<Box<dyn Any>, SerdeDynError<'de, D>> {
59        match self.mapping.get(uuid) {
60            Some(f) => f(deserializer).map_err(SerdeDynError::DeserializerError),
61            None => Err(SerdeDynError::UuidNotFound),
62        }
63    }
64}
65
66#[derive(Clone, PartialEq, Eq)]
67pub enum SerdeDynError<'de, D: Deserializer<'de>> {
68    /// A Uuid was passed in and we didn't have a mapping for it.
69    UuidNotFound,
70    /// The deserialization function returned an error.
71    DeserializerError(D::Error),
72}
73
74impl<'de, D: Deserializer<'de>> Debug for SerdeDynError<'de, D> {
75    fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> {
76        match *self {
77            SerdeDynError::UuidNotFound => write!(f, "UuidNotFound"),
78            SerdeDynError::DeserializerError(ref e) => write!(f, "DeserializerError({:?})", e),
79        }
80    }
81}
82
83impl<'de, D: Deserializer<'de>> Display for SerdeDynError<'de, D> {
84    fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> {
85        match *self {
86            SerdeDynError::UuidNotFound => write!(f, "Uuid requested not found in TUSM."),
87            SerdeDynError::DeserializerError(ref e) => write!(f, "Deserialization error: {}", e),
88        }
89    }
90}
91
92impl<'de, D: Deserializer<'de>> StdError for SerdeDynError<'de, D> {}
93
94#[cfg(test)]
95mod tests {
96    extern crate ron;
97
98    use super::*;
99
100    #[test]
101    fn deser_test() {
102        let mut deserializer = ron::de::Deserializer::from_str("5").unwrap();
103        let mut tusm = TUSM::new();
104
105        tusm.register::<i32>();
106
107        let new_value = *tusm
108            .deserialize_with_uuid(&i32::UUID, &mut deserializer)
109            .unwrap()
110            .downcast::<i32>()
111            .unwrap();
112        assert_eq!(new_value, 5);
113    }
114}