esl 0.3.1

A library for reading, writing and processing ESM/ESP/ESS files.
Documentation
use std::char::{self};
use std::fmt::{self, Debug, Display};
use std::str::{FromStr};

#[derive(Ord, PartialOrd, Eq, PartialEq, Hash, Copy, Clone)]
pub struct Tag {
    pub dword: u32
}

impl Tag {
    pub const fn from(dword: u32) -> Tag {
        Tag { dword }
    }
}

impl From<u32> for Tag {
    fn from(dword: u32) -> Tag {
        Tag { dword }
    }
}

impl Debug for Tag {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        Display::fmt(self, f)
    }
}

impl Display for Tag {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let c0 = char::from(self.dword as u8);
        let c1 = char::from((self.dword >> 8) as u8);
        let c2 = char::from((self.dword >> 16) as u8);
        let c3 = char::from((self.dword >> 24) as u8);
        write!(f, "{}{}{}{}", c0, c1, c2, c3)
    }
}

impl FromStr for Tag {
    type Err = ();

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        let mut dword = 0;
        let mut i = 0;
        for byte in s.bytes() {
            if i == 4 { return Err(()); }
            dword = dword | (byte as u32) << (8 * i);
            i += 1;
        }
        if i != 4 { return Err(()); }
        Ok(Tag { dword })
    }
}

macro_rules! enum_serde {
    ($name:ty, $exp:literal, $bits:ty, $to:ident, as $from:ident, $signed:ident, $big:ident) => {
        impl ::serde::Serialize for $name {
            fn serialize<S>(&self, serializer: S) -> ::std::result::Result<S::Ok, S::Error> where
                S: ::serde::Serializer {
        
                if serializer.is_human_readable() {
                    serializer.serialize_str(&format!("{}", self))
                } else {
                    <$bits as ::serde::Serialize>::serialize(
                        &::num_traits::cast::ToPrimitive::$to(self).unwrap(),
                        serializer
                    )
                }
            }
        }
        
        impl<'de> ::serde::Deserialize<'de> for $name {
            fn deserialize<D>(deserializer: D) -> ::std::result::Result<Self, D::Error> where
                D: ::serde::Deserializer<'de> {
        
                struct HRDeserializer;
                
                impl<'de> ::serde::de::Visitor<'de> for HRDeserializer {
                    type Value = $name;
                
                    fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, $exp) }
                
                    fn visit_str<E>(self, s: &str) -> Result<Self::Value, E> where E: ::serde::de::Error {
                        ::std::str::FromStr::from_str(s).map_err(|_| E::invalid_value(::serde::de::Unexpected::Str(s), &self))
                    }
                }
        
                if deserializer.is_human_readable() {
                    deserializer.deserialize_str(HRDeserializer)
                } else {
                    let b = <$bits as ::serde::Deserialize>::deserialize(deserializer)?;
                    ::num_traits::cast::FromPrimitive::$from(b).ok_or_else(|| <D::Error as ::serde::de::Error>::invalid_value(::serde::de::Unexpected::$signed(b as $big), &$exp))
                }
            }
        }
    };
    ($name:ty, $exp:literal, $bits:ty, $to:ident, $from:ident) => {
        impl ::serde::Serialize for $name {
            fn serialize<S>(&self, serializer: S) -> ::std::result::Result<S::Ok, S::Error> where
                S: ::serde::Serializer {
        
                if serializer.is_human_readable() {
                    serializer.serialize_str(&format!("{}", self))
                } else {
                    <$bits as ::serde::Serialize>::serialize(&self.$to, serializer)
                }
            }
        }
        
        impl<'de> ::serde::Deserialize<'de> for $name {
            fn deserialize<D>(deserializer: D) -> ::std::result::Result<Self, D::Error> where
                D: ::serde::Deserializer<'de> {
        
                struct HRDeserializer;
                
                impl<'de> ::serde::de::Visitor<'de> for HRDeserializer {
                    type Value = $name;
                
                    fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, $exp) }
                
                    fn visit_str<E>(self, s: &str) -> Result<Self::Value, E> where E: ::serde::de::Error {
                        ::std::str::FromStr::from_str(s).map_err(|_| E::invalid_value(::serde::de::Unexpected::Str(s), &self))
                    }
                }
        
                if deserializer.is_human_readable() {
                    deserializer.deserialize_str(HRDeserializer)
                } else {
                    let b = <$bits as ::serde::Deserialize>::deserialize(deserializer)?;
                    Ok(<$name>::$from(b))
                }
            }
        }
    };
    ($name:ty, $exp:literal, $bits:ty, $to:ident, try $from:ident, $signed:ident, $big:ident $(, ^$xor:literal)?) => {
        impl ::serde::Serialize for $name {
            fn serialize<S>(&self, serializer: S) -> ::std::result::Result<S::Ok, S::Error> where
                S: ::serde::Serializer {
        
                if serializer.is_human_readable() {
                    serializer.serialize_str(&format!("{}", self))
                } else {
                    <$bits as ::serde::Serialize>::serialize(&(self.$to $(^ $xor)?), serializer)
                }
            }
        }
        
        impl<'de> ::serde::Deserialize<'de> for $name {
            fn deserialize<D>(deserializer: D) -> ::std::result::Result<Self, D::Error> where
                D: ::serde::Deserializer<'de> {
        
                struct HRDeserializer;
                
                impl<'de> ::serde::de::Visitor<'de> for HRDeserializer {
                    type Value = $name;
                
                    fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, $exp) }
                
                    fn visit_str<E>(self, s: &str) -> Result<Self::Value, E> where E: ::serde::de::Error {
                        ::std::str::FromStr::from_str(s).map_err(|_| E::invalid_value(::serde::de::Unexpected::Str(s), &self))
                    }
                }
        
                if deserializer.is_human_readable() {
                    deserializer.deserialize_str(HRDeserializer)
                } else {
                    let b = <$bits as ::serde::Deserialize>::deserialize(deserializer)? $(^ $xor)?;
                    let v = <$name>::$from(b).ok_or_else(|| <D::Error as ::serde::de::Error>::invalid_value(::serde::de::Unexpected::$signed(b as $big), &$exp))?;
                    Ok(v)
                }
            }
        }
    };
    ($name:ty, $exp:literal, $bits:ty, $to:ident (), try $from:ident, $signed:ident, $big:ident $(, ^$xor:literal)?) => {
        impl ::serde::Serialize for $name {
            fn serialize<S>(&self, serializer: S) -> ::std::result::Result<S::Ok, S::Error> where
                S: ::serde::Serializer {
        
                if serializer.is_human_readable() {
                    serializer.serialize_str(&format!("{}", self))
                } else {
                    <$bits as ::serde::Serialize>::serialize(&(self.$to() $(^ $xor)?), serializer)
                }
            }
        }
        
        impl<'de> ::serde::Deserialize<'de> for $name {
            fn deserialize<D>(deserializer: D) -> ::std::result::Result<Self, D::Error> where
                D: ::serde::Deserializer<'de> {
        
                struct HRDeserializer;
                
                impl<'de> ::serde::de::Visitor<'de> for HRDeserializer {
                    type Value = $name;
                
                    fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, $exp) }
                
                    fn visit_str<E>(self, s: &str) -> Result<Self::Value, E> where E: ::serde::de::Error {
                        ::std::str::FromStr::from_str(s).map_err(|_| E::invalid_value(::serde::de::Unexpected::Str(s), &self))
                    }
                }
        
                if deserializer.is_human_readable() {
                    deserializer.deserialize_str(HRDeserializer)
                } else {
                    let b = <$bits as ::serde::Deserialize>::deserialize(deserializer)? $(^ $xor)?;
                    let v = <$name>::$from(b).ok_or_else(|| <D::Error as ::serde::de::Error>::invalid_value(::serde::de::Unexpected::$signed(b as $big), &$exp))?;
                    Ok(v)
                }
            }
        }
    }
}

enum_serde!(Tag, "four-byte tag", u32, dword, from);