Skip to main content

object_rainbow/
u63.rs

1use std::fmt::Display;
2
3use crate::*;
4
5#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, ParseAsInline)]
6pub struct U63(u64);
7
8impl U63 {
9    pub fn from_u64(n: u64) -> crate::Result<Self> {
10        if n < (1 << 63) {
11            Ok(Self(n))
12        } else {
13            Err(Error::UnsupportedLength)
14        }
15    }
16
17    pub fn as_usize(self) -> crate::Result<usize> {
18        self.0.try_into().map_err(|_| Error::UnsupportedLength)
19    }
20
21    pub fn len_of<T>(v: &[T]) -> Self {
22        Self::from_u64(v.len() as _).expect("this is unreasonable to store in memory")
23    }
24}
25
26impl ToOutput for U63 {
27    fn to_output(&self, output: &mut impl Output) {
28        if self.0 < 128 {
29            (self.0 as u8).to_output(output);
30        } else {
31            let mut bytes = self.0.to_be_bytes();
32            bytes[0] ^= 128;
33            bytes.to_output(output);
34        }
35    }
36}
37
38impl InlineOutput for U63 {}
39impl Tagged for U63 {}
40impl ListHashes for U63 {}
41impl Topological for U63 {}
42
43impl<I: ParseInput> ParseInline<I> for U63 {
44    fn parse_inline(input: &mut I) -> crate::Result<Self> {
45        let mut bytes = [0; 8];
46        input.read(&mut bytes[..1])?;
47        Ok(Self(if bytes[0] & 128 == 0 {
48            bytes[0] as u64
49        } else {
50            bytes[0] ^= 128;
51            input.read(&mut bytes[1..])?;
52            let n = u64::from_be_bytes(bytes);
53            if n < 128 {
54                return Err(Error::OutOfBounds);
55            }
56            n
57        }))
58    }
59}
60
61impl ByteOrd for U63 {
62    fn bytes_cmp(&self, other: &Self) -> Ordering {
63        self.cmp(other)
64    }
65}
66
67impl SignificantLength for U63 {}
68
69#[test]
70fn reparse_u63_100_000() -> crate::Result<()> {
71    (0..100_000).try_for_each(|n| {
72        assert_eq!(U63::from_u64(n)?.reparse()?.0, n);
73        Ok(())
74    })
75}
76
77impl Display for U63 {
78    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
79        self.0.fmt(f)
80    }
81}