Expand description

This library provides a simple procedural macro for fast and easy implementing serialize methods in serde::Serializer trait.

Example

use impl_serialize::impl_serialize;
use serde::ser;
use thiserror::Error;

#[derive(Debug, Error)]
enum SerializationError {
    #[error("Other error")]
    OtherError,
    #[error("Cannot serialize value from {0}")]
    CannotSerializeFrom(String),
    #[error("Custom({0})")]
    Custom(String)
}

impl serde::ser::Error for SerializationError {
    fn custom<T>(msg:T) -> Self
    where T: std::fmt::Display
    {
        SerializationError::Custom(msg.to_string())
    }
}

struct MySerializer;

impl ser::Serializer for MySerializer {
    type Ok = ();
    type Error = SerializationError;

    type SerializeMap = ser::Impossible<Self::Ok, Self::Error>;
    type SerializeSeq = ser::Impossible<Self::Ok, Self::Error>;
    type SerializeStruct = ser::Impossible<Self::Ok, Self::Error>;
    type SerializeStructVariant = ser::Impossible<Self::Ok, Self::Error>;
    type SerializeTuple = ser::Impossible<Self::Ok, Self::Error>;
    type SerializeTupleStruct = ser::Impossible<Self::Ok, Self::Error>;
    type SerializeTupleVariant = ser::Impossible<Self::Ok, Self::Error>;

    //value_type is metavariable (&str) what represents any serializing value type.
    //for example, value_type will be "i8" when seializing i8 or "bytes" when &[u8] (bytes);

    //with value_type
    impl_serialize!(
        Err(SerializationError::CannotSerializeFrom(value_type.to_string())),
        bool
    );
    
    //without value_type
    impl_serialize!(
        Err(SerializationError::OtherError),
        char
    );

    //for many types
    impl_serialize!(
        Err(SerializationError::CannotSerializeFrom(value_type.to_string())),
        [
            bytes,
            i8, i16, i32, i64,
            u8, u16, u32, u64,
            f32, f64,
            str,
            none, some, unit,
            unit_struct, unit_variant,
            newtype_struct, newtype_variant,
            seq, map,
            tuple, tuple_struct, tuple_variant,
            struct, struct_variant
        ]
    );
}

Function’s args

Every generated function have input arguments. And you can use this args inside your expression.

For details of specific input args see serde::Serializer.

Example

use thiserror::Error;
use serde::ser;
use ser::Serializer;
use impl_serialize::impl_serialize;

#[derive(Debug, Error, PartialEq)]
enum SerializationError {
    #[error("Expected value higher {than}. Found {current_value}")]
    ExpectedValueHigher {
        than: i64,
        current_value: i64
    },
    #[error("Cannot serialize")]
    CannotSerialize,
    #[error("Custom({0})")]
    Custom(String),
}

impl serde::ser::Error for SerializationError {
    fn custom<T>(msg: T) -> Self
    where
        T: std::fmt::Display,
    {
        SerializationError::Custom(msg.to_string())
    }
}
#[derive(Clone, Copy)]
struct MoreThanOneSerializer;

impl ser::Serializer for MoreThanOneSerializer {
    type Error = SerializationError;
    type Ok = i64;

    type SerializeMap = ser::Impossible<Self::Ok, Self::Error>;
    type SerializeSeq = ser::Impossible<Self::Ok, Self::Error>;
    type SerializeStruct = ser::Impossible<Self::Ok, Self::Error>;
    type SerializeStructVariant = ser::Impossible<Self::Ok, Self::Error>;
    type SerializeTuple = ser::Impossible<Self::Ok, Self::Error>;
    type SerializeTupleStruct = ser::Impossible<Self::Ok, Self::Error>;
    type SerializeTupleVariant = ser::Impossible<Self::Ok, Self::Error>;

    impl_serialize!(
        {
            let v = v as i64;
            if v > 1 {
                Ok(v)
            } else {
                Err(SerializationError::ExpectedValueHigher {
                    than: 1,
                    current_value: v,
                })
            }
        },
        [i8, i16, i32, i64, u8, u16, u32, u64, f32, f64]
    );

    impl_serialize!(Err(SerializationError::CannotSerialize), [
        bool, bytes, char, str,
        none, some, unit,
        unit_struct, unit_variant,
        newtype_struct, newtype_variant,
        seq, map,
        tuple, tuple_struct, tuple_variant,
        struct, struct_variant
    ]);
}

let more_than_one_serializer = MoreThanOneSerializer;

assert_eq!(
    more_than_one_serializer.serialize_i32(4).ok().unwrap(),
    4
);

assert_eq!(
    more_than_one_serializer.serialize_i32(71).ok().unwrap(),
    71
);

assert_eq!(
    more_than_one_serializer.serialize_i32(0).err().unwrap(),
    SerializationError::ExpectedValueHigher {
        than: 1,
        current_value: 0,
    }
);

Special value_type metavariable

Every generated function have variable value_type: &str inside it. You can use it as well. value_type equals to type after fn serialize_.

function namevalue_type
serialize_boolbool
serialize_i8i8
serialize_i16i16
serialize_i32i32
serialize_i64i64
serialize_u8u8
serialize_u16u16
serialize_u32u32
serialize_u64u64
serialize_f32f32
serialize_f64f64
serialize_charchar
serialize_strstr
serialize_bytesbytes
serialize_nonenone
serialize_somesome
serialize_unitunit
serialize_unit_structunit_struct
serialize_unit_variantunit_variant
serialize_newtype_structnewtype_struct
serialize_newtype_variantnewtype_variant
serialize_seqseq
serialize_tupletuple
serialize_tuple_structtuple_struct
serialize_tuple_varianttuple_variant
serialize_mapmap
serialize_structstruct
serialize_struct_variantstruct_variant

Example

use thiserror::Error;
use serde::ser;
use ser::Serializer;
use impl_serialize::impl_serialize;

#[derive(Debug, Error, PartialEq)]
enum SerializationError {
    #[error("Cannot serialize from({0})")]
    CannotSerializeFrom(String),
    #[error("Custom({0})")]
    Custom(String),
}

impl serde::ser::Error for SerializationError {
    fn custom<T>(msg: T) -> Self
    where
        T: std::fmt::Display,
    {
        SerializationError::Custom(msg.to_string())
    }
}

#[derive(Clone, Copy)]
struct CharSerializer;

impl ser::Serializer for CharSerializer {
    type Error = SerializationError;
    type Ok = char;

    type SerializeMap = ser::Impossible<Self::Ok, Self::Error>;
    type SerializeSeq = ser::Impossible<Self::Ok, Self::Error>;
    type SerializeStruct = ser::Impossible<Self::Ok, Self::Error>;
    type SerializeStructVariant = ser::Impossible<Self::Ok, Self::Error>;
    type SerializeTuple = ser::Impossible<Self::Ok, Self::Error>;
    type SerializeTupleStruct = ser::Impossible<Self::Ok, Self::Error>;
    type SerializeTupleVariant = ser::Impossible<Self::Ok, Self::Error>;

    impl_serialize!(Ok(v), char);

    impl_serialize!(Err(SerializationError::CannotSerializeFrom(value_type.to_string())), [
        i8, i16, i32, i64,
        u8, u16, u32, u64,
        f32, f64,
        bool,
        bytes,
        str,
        none, some, unit,
        unit_struct, unit_variant,
        newtype_struct, newtype_variant,
        seq, map,
        tuple, tuple_struct, tuple_variant,
        struct, struct_variant
    ]);
}

let char_serializer = CharSerializer;

assert_eq!(
    CharSerializer.serialize_char('k').ok().unwrap(),
    'k'
);

assert_eq!(
    char_serializer.serialize_char('h').ok().unwrap(),
    'h'
);

assert_eq!(
    char_serializer.serialize_i8(0).err().unwrap(),
    SerializationError::CannotSerializeFrom("i8".to_string())
);

assert_eq!(
    char_serializer.serialize_none().err().unwrap(),
    SerializationError::CannotSerializeFrom("none".to_string())
);

More examples…

Macros

Macro for fast and easy implementing serialize methods in serde::Serializer trait.
Macro to erase macro hygiene.