serde-xdr 0.6.0

XDR serialization and deserialization for Serde
Documentation
use {
    self::type_name::TypeName,
    super::super::{
        errors::{CompatSerializationError, Result, SerializationError},
        Serializer,
    },
    byteorder::WriteBytesExt,
    serde::ser::{self, Serialize},
};

pub struct StructSerializer<'w, W>
where
    W: WriteBytesExt + 'w,
{
    struct_name: TypeName,
    serializer: Option<Serializer<'w, W>>,
}

impl<'w, W> StructSerializer<'w, W>
where
    W: WriteBytesExt + 'w,
{
    pub fn start_struct(
        struct_name: &'static str,
        serializer: Serializer<'w, W>,
    ) -> Self {
        Self {
            struct_name: TypeName::Struct(struct_name),
            serializer: Some(serializer),
        }
    }

    pub fn start_struct_variant(
        type_name: &'static str,
        variant_name: &'static str,
        serializer: Serializer<'w, W>,
    ) -> Self {
        Self {
            struct_name: TypeName::StructVariant(type_name, variant_name),
            serializer: Some(serializer),
        }
    }

    fn common_serialize_field<T>(
        &mut self,
        key: &'static str,
        value: &T,
    ) -> Result<()>
    where
        T: ?Sized + Serialize,
    {
        if let Some(serializer) = self.serializer.take() {
            let serializer = value.serialize(serializer).map_err(|error| {
                serialization_error(&self.struct_name, key, error)
            })?;

            self.serializer = Some(serializer);

            Ok(())
        } else {
            Err(fatal_error(&self.struct_name)).map_err(|error| {
                serialization_error(&self.struct_name, key, error).into()
            })
        }
    }

    fn common_end(self) -> Result<Serializer<'w, W>> {
        if let Some(serializer) = self.serializer {
            Ok(serializer)
        } else {
            Err(fatal_error(&self.struct_name))
        }
    }
}

impl<'w, W> ser::SerializeStruct for StructSerializer<'w, W>
where
    W: WriteBytesExt + 'w,
{
    type Ok = Serializer<'w, W>;
    type Error = CompatSerializationError;

    fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<()>
    where
        T: ?Sized + Serialize,
    {
        self.common_serialize_field(key, value)
    }

    fn end(self) -> Result<Serializer<'w, W>> {
        self.common_end()
    }
}

impl<'w, W> ser::SerializeStructVariant for StructSerializer<'w, W>
where
    W: WriteBytesExt + 'w,
{
    type Ok = Serializer<'w, W>;
    type Error = CompatSerializationError;

    fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<()>
    where
        T: ?Sized + Serialize,
    {
        self.common_serialize_field(key, value)
    }

    fn end(self) -> Result<Serializer<'w, W>> {
        self.common_end()
    }
}

fn fatal_error(struct_name: &TypeName) -> CompatSerializationError {
    let name = struct_name.to_string();

    SerializationError::StructFatalError { name }.into()
}

fn serialization_error<E>(
    struct_name: &TypeName,
    field_name: &str,
    error: E,
) -> SerializationError
where
    E: Into<CompatSerializationError>,
{
    SerializationError::Failure {
        what: format!("struct field {}::{}", struct_name, field_name),
        cause: Box::new(error.into()),
    }
}

mod type_name;

#[cfg(test)]
mod tests;