1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
#[allow(unused_imports)]
use crate::{Error, Raw, Value};

/// Base trait for values that can be encoded using serde
pub trait Codec<T: serde::Serialize + serde::de::DeserializeOwned>:
    Value + AsRef<T> + AsMut<T>
{
    /// Convert back into inner value
    fn into_inner(self) -> T;
}

#[macro_export]
/// Define a codec type and implement the Codec trait
macro_rules! codec {
    ($x:ident) => {
        /// Codec implementation
        pub struct $x<T: serde::Serialize + serde::de::DeserializeOwned>(pub T);

        impl<T: serde::Serialize + serde::de::DeserializeOwned> AsRef<T> for $x<T> {
            fn as_ref(&self) -> &T {
                &self.0
            }
        }

        impl<T: serde::Serialize + serde::de::DeserializeOwned> AsMut<T> for $x<T> {
            fn as_mut(&mut self) -> &mut T {
                &mut self.0
            }
        }

        impl<T: serde::Serialize + serde::de::DeserializeOwned> Codec<T> for $x<T> {
            fn into_inner(self) -> T {
                self.0
            }
        }

        impl<T: Clone + serde::Serialize + serde::de::DeserializeOwned> Clone for $x<T> {
            fn clone(&self) -> Self {
                $x(self.0.clone())
            }
        }
    };

    ($x:ident, {$ser:expr, $de:expr}) => {
        codec!($x);

        impl<T: serde::Serialize + serde::de::DeserializeOwned> Value for $x<T> {
            fn to_raw_value(&self) -> Result<Raw, Error> {
                let x = $ser(&self.0)?;
                Ok(x.into())
            }

            fn from_raw_value(r: Raw) -> Result<Self, Error> {
                let x = $de(&r)?;
                Ok($x(x))
            }
        }
    };
}

#[cfg(feature = "msgpack-value")]
mod msgpack_value {
    use super::*;

    codec!(Msgpack, {rmp_serde::to_vec, rmp_serde::from_slice});
}

#[cfg(feature = "json-value")]
mod json_value {
    use super::*;

    codec!(Json, {serde_json::to_vec, serde_json::from_slice});

    impl<T: serde::Serialize + serde::de::DeserializeOwned> std::fmt::Display for Json<T> {
        fn fmt(&self, w: &mut std::fmt::Formatter) -> std::fmt::Result {
            let s = match serde_json::to_string_pretty(&self.0) {
                Ok(s) => s,
                Err(_) => return Err(std::fmt::Error),
            };
            write!(w, "{}", s)?;
            Ok(())
        }
    }
}

#[cfg(feature = "bincode-value")]
mod bincode_value {
    use super::*;

    codec!(Bincode, {bincode::serialize, bincode::deserialize});
}

#[cfg(feature = "lexpr-value")]
mod lexpr_value {
    use super::*;

    codec!(Lexpr, {serde_lexpr::to_vec, serde_lexpr::from_slice});
}

#[cfg(feature = "json-value")]
pub use json_value::Json;

#[cfg(feature = "msgpack-value")]
pub use msgpack_value::Msgpack;

#[cfg(feature = "bincode-value")]
pub use bincode_value::Bincode;

#[cfg(feature = "lexpr-value")]
pub use lexpr_value::Lexpr;