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::{
            SerializeSeq, SerializeTuple, SerializeTupleStruct,
            SerializeTupleVariant,
        },
        Serialize, Serializer as SerdeSerializer,
    },
};

pub struct SequenceSerializer<'w, W>
where
    W: WriteBytesExt + 'w,
{
    type_name: TypeName,
    serializer: Option<Serializer<'w, W>>,
    current_index: usize,
}

impl<'w, W> SequenceSerializer<'w, W>
where
    W: WriteBytesExt + 'w,
{
    pub fn new(type_name: TypeName, serializer: Serializer<'w, W>) -> Self {
        SequenceSerializer {
            type_name,
            serializer: Some(serializer),
            current_index: 0,
        }
    }

    pub fn start_sequence(
        length: Option<usize>,
        mut serializer: Serializer<'w, W>,
    ) -> Result<Self> {
        if let Some(length) = length {
            serializer = Self::serialize_length(length, serializer)?;
        } else {
            bail!(SerializationError::SequenceWithUnknownLength);
        }

        Ok(SequenceSerializer::new(TypeName::Sequence, serializer))
    }

    pub fn start_tuple(serializer: Serializer<'w, W>) -> Self {
        SequenceSerializer::new(TypeName::Tuple, serializer)
    }

    pub fn start_tuple_struct(
        name: &'static str,
        serializer: Serializer<'w, W>,
    ) -> Self {
        SequenceSerializer::new(TypeName::TupleStruct(name), serializer)
    }

    pub fn start_tuple_variant(
        type_name: &'static str,
        variant_name: &'static str,
        serializer: Serializer<'w, W>,
    ) -> Self {
        SequenceSerializer::new(
            TypeName::TupleVariant(type_name, variant_name),
            serializer,
        )
    }

    fn serialize_length(
        length: usize,
        serializer: Serializer<'w, W>,
    ) -> Result<Serializer<'w, W>> {
        Self::ensure_length_is_valid(length)?;

        serializer.serialize_u32(length as u32).map_err(|error| {
            SerializationError::Failure {
                what: format!("sequence length: {}", length),
                cause: Box::new(error.into()),
            }
            .into()
        })
    }

    fn ensure_length_is_valid(length: usize) -> Result<()> {
        let max_length = u32::max_value() as usize;

        ensure!(
            length <= max_length,
            SerializationError::SequenceTooLong { length }
        );

        Ok(())
    }

    fn common_serialize_element<T>(&mut self, value: &T) -> Result<()>
    where
        T: ?Sized + Serialize,
    {
        if let Some(serializer) = self.serializer.take() {
            let serializer = value
                .serialize(serializer)
                .map_err(|error| self.failure(error))?;

            self.current_index += 1;
            self.serializer = Some(serializer);

            Ok(())
        } else {
            bail!(fatal_error(&self.type_name));
        }
    }

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

    fn failure<E>(&self, error: E) -> SerializationError
    where
        E: Into<CompatSerializationError>,
    {
        let index = self.current_index;
        let type_name = &self.type_name;

        SerializationError::Failure {
            what: format!("element {} of the type {}", index, type_name),
            cause: Box::new(error.into()),
        }
    }
}

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

    fn serialize_element<T>(&mut self, value: &T) -> Result<()>
    where
        T: ?Sized + Serialize,
    {
        self.common_serialize_element(value)
    }

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

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

    fn serialize_element<T>(&mut self, value: &T) -> Result<()>
    where
        T: ?Sized + Serialize,
    {
        self.common_serialize_element(value)
    }

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

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

    fn serialize_field<T>(&mut self, value: &T) -> Result<()>
    where
        T: ?Sized + Serialize,
    {
        self.common_serialize_element(value)
    }

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

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

    fn serialize_field<T>(&mut self, value: &T) -> Result<()>
    where
        T: ?Sized + Serialize,
    {
        self.common_serialize_element(value)
    }

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

fn fatal_error(type_name: &TypeName) -> SerializationError {
    let type_name = type_name.to_string();

    SerializationError::SequenceOrTupleFatalError { type_name }
}

mod type_name;

#[cfg(test)]
mod tests;