hexga_encoding 0.0.11-beta.53

Encoding and I/O abstraction for loading, saving, and converting data with custom extensions and media types, with optional Serde integration.
use super::*;

pub(crate) mod prelude
{
    pub use super::{Save, SaveAs, SaveExtension};
}

pub trait SaveExtension: CfgSerialize
{
    fn save_custom_extensions() -> impl Iterator<Item = &'static extension> { std::iter::empty() }
    fn save_to_writer_with_custom_extension<W>(
        &self,
        writer: W,
        extension: &extension,
    ) -> EncodeResult
    where
        W: Write,
    {
        let _ = (writer, extension);
        Err(EncodeError::Unimplemented)
    }
}

pub trait SaveExtensionBytes: SaveExtension
{
    fn save_to_bytes_with_custom_extension(&self, extension: &extension) -> EncodeResult<Vec<u8>>
    {
        self.save_to_bytes_with_custom_extension_in(
            Vec::with_capacity(DEFAULT_WRITER_CAPACITY),
            extension,
        )
    }
    fn save_to_bytes_with_custom_extension_in(
        &self,
        mut bytes: Vec<u8>,
        extension: &extension,
    ) -> EncodeResult<Vec<u8>>
    {
        self.save_to_writer_with_custom_extension(&mut bytes, extension)?;
        Ok(bytes)
    }
}
impl<T> SaveExtensionBytes for T where T: SaveExtension {}

const DEFAULT_WRITER_CAPACITY: usize = 1024;

pub trait Save: SaveExtension
{
    fn save_extensions() -> impl Iterator<Item = &'static extension>
    {
        #[cfg(feature = "serde")]
        return Self::save_custom_extensions()
            .chain(AnyFormat::ALL.into_iter().map(|v| v.extension()));

        #[cfg(not(feature = "serde"))]
        return Self::save_custom_extensions();
    }
    fn save_prefered_extension() -> Option<&'static extension>
    {
        Self::save_custom_extensions().next()
    }

    fn save_to_bytes<'ext>(
        &self,
        extension: &'ext extension,
    ) -> EncodeResult<(Vec<u8>, DeducedExtension<'ext>)>
    {
        self.save_to_bytes_in(Vec::with_capacity(DEFAULT_WRITER_CAPACITY), extension)
    }
    fn save_to_bytes_in<'ext>(
        &self,
        mut bytes: Vec<u8>,
        extension: &'ext extension,
    ) -> EncodeResult<(Vec<u8>, DeducedExtension<'ext>)>
    {
        let r = self.save_to_writer(&mut bytes, extension)?;
        Ok((bytes, r))
    }
    fn save_to_writer<'ext, W>(
        &self,
        writer: &mut W,
        extension: &'ext extension,
    ) -> EncodeResult<DeducedExtension<'ext>>
    where
        W: Write,
    {
        if Self::save_custom_extensions().any(|e| e == extension)
        {
            return self
                .save_to_writer_with_custom_extension(writer, extension)
                .map(|_| extension.into());
        }
        if extension.is_empty()
            && let Some(ext) = Self::save_prefered_extension()
        {
            return self
                .save_to_writer_with_custom_extension(writer, ext)
                .map(|_| ext.into());
        }

        #[cfg(feature = "serde")]
        {
            let format = AnyFormat::try_from(extension).unwrap_or_default();
            format.encode_with_writer(&self, writer)?;
            return Ok(format.extension().into());
        }

        #[allow(unreachable_code)]
        Err(EncodeError::save_unsupported_extension::<Self>(
            extension.to_owned(),
        ))
    }
}
impl<T> Save for T where T: SaveExtension + ?Sized {}

pub trait SaveAs
{
    type Output: SaveExtension + for<'a> From<&'a Self>;
}
impl<S> SaveExtension for S
where
    S: SaveAs + CfgSerialize,
{
    fn save_custom_extensions() -> impl Iterator<Item = &'static extension>
    {
        S::Output::save_custom_extensions()
    }
    fn save_to_writer_with_custom_extension<W>(
        &self,
        writer: W,
        extension: &extension,
    ) -> EncodeResult
    where
        W: Write,
    {
        S::Output::save_to_writer_with_custom_extension(&self.into(), writer, extension)
    }
}