object-rainbow 0.0.0-a.62

distributed object model
Documentation
use crate::*;

#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, ParseAsInline)]
pub struct U63(u64);

impl U63 {
    pub fn from_u64(n: u64) -> crate::Result<Self> {
        if n < ((1 << 63) + 128) {
            Ok(Self(n))
        } else {
            Err(Error::UnsupportedLength)
        }
    }

    pub fn as_usize(self) -> crate::Result<usize> {
        self.0.try_into().map_err(|_| Error::UnsupportedLength)
    }

    pub fn len_of<T>(v: &[T]) -> Self {
        Self::from_u64(v.len() as _).unwrap()
    }
}

impl ToOutput for U63 {
    fn to_output(&self, output: &mut impl Output) {
        if self.0 < 128 {
            (self.0 as u8).to_output(output);
        } else {
            let mut bytes = (self.0 - 128).to_be_bytes();
            bytes[0] ^= 128;
            bytes.to_output(output);
        }
    }
}

impl InlineOutput for U63 {}
impl Tagged for U63 {}
impl ListHashes for U63 {}
impl Topological for U63 {}

impl<I: ParseInput> ParseInline<I> for U63 {
    fn parse_inline(input: &mut I) -> crate::Result<Self> {
        let mut bytes = [0; 8];
        input.read(&mut bytes[..1])?;
        Ok(Self(if bytes[0] & 128 == 0 {
            bytes[0] as u64
        } else {
            bytes[0] ^= 128;
            input.read(&mut bytes[1..])?;
            u64::from_be_bytes(bytes) + 128
        }))
    }
}