use std::convert::{TryFrom, From}; #[derive(Debug, PartialEq, Eq)] pub enum Tag { False, True, Float, Double, End, Annotation, Embedded, SmallInteger(i8), MediumInteger(u8), SignedInteger, String, ByteString, Symbol, Record, Sequence, Set, Dictionary, } #[derive(Debug, PartialEq, Eq)] pub struct InvalidTag(u8); impl From for std::io::Error { fn from(v: InvalidTag) -> Self { std::io::Error::new(std::io::ErrorKind::InvalidData, format!("Invalid Preserves tag {}", v.0)) } } impl From for crate::error::Error { fn from(v: InvalidTag) -> Self { crate::error::Error::Io(v.into()) } } impl TryFrom for Tag { type Error = InvalidTag; fn try_from(v: u8) -> Result { match v { 0x80 => Ok(Self::False), 0x81 => Ok(Self::True), 0x82 => Ok(Self::Float), 0x83 => Ok(Self::Double), 0x84 => Ok(Self::End), 0x85 => Ok(Self::Annotation), 0x86 => Ok(Self::Embedded), 0x90..=0x9c => Ok(Self::SmallInteger((v - 0x90) as i8)), 0x9d..=0x9f => Ok(Self::SmallInteger((v - 0x90) as i8 - 16)), 0xa0..=0xaf => Ok(Self::MediumInteger(v - 0xa0 + 1)), 0xb0 => Ok(Self::SignedInteger), 0xb1 => Ok(Self::String), 0xb2 => Ok(Self::ByteString), 0xb3 => Ok(Self::Symbol), 0xb4 => Ok(Self::Record), 0xb5 => Ok(Self::Sequence), 0xb6 => Ok(Self::Set), 0xb7 => Ok(Self::Dictionary), _ => Err(InvalidTag(v)) } } } impl From for u8 { fn from(v: Tag) -> Self { match v { Tag::False => 0x80, Tag::True => 0x81, Tag::Float => 0x82, Tag::Double => 0x83, Tag::End => 0x84, Tag::Annotation => 0x85, Tag::Embedded => 0x86, Tag::SmallInteger(v) => if v < 0 { (v + 16) as u8 + 0x90 } else { v as u8 + 0x90 }, Tag::MediumInteger(count) => count - 1 + 0xa0, Tag::SignedInteger => 0xb0, Tag::String => 0xb1, Tag::ByteString => 0xb2, Tag::Symbol => 0xb3, Tag::Record => 0xb4, Tag::Sequence => 0xb5, Tag::Set => 0xb6, Tag::Dictionary => 0xb7, } } }