1use crate::*;
2
3#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, ParseAsInline)]
4pub struct U63(u64);
5
6impl U63 {
7 pub fn from_u64(n: u64) -> crate::Result<Self> {
8 if n < ((1 << 63) + 128) {
9 Ok(Self(n))
10 } else {
11 Err(Error::UnsupportedLength)
12 }
13 }
14
15 pub fn as_usize(self) -> crate::Result<usize> {
16 self.0.try_into().map_err(|_| Error::UnsupportedLength)
17 }
18
19 pub fn len_of<T>(v: &[T]) -> Self {
20 Self::from_u64(v.len() as _).expect("this is unreasonable to store in memory")
21 }
22}
23
24impl ToOutput for U63 {
25 fn to_output(&self, output: &mut impl Output) {
26 if self.0 < 128 {
27 (self.0 as u8).to_output(output);
28 } else {
29 let mut bytes = (self.0 - 128).to_be_bytes();
30 bytes[0] ^= 128;
31 bytes.to_output(output);
32 }
33 }
34}
35
36impl InlineOutput for U63 {}
37impl Tagged for U63 {}
38impl ListHashes for U63 {}
39impl Topological for U63 {}
40
41impl<I: ParseInput> ParseInline<I> for U63 {
42 fn parse_inline(input: &mut I) -> crate::Result<Self> {
43 let mut bytes = [0; 8];
44 input.read(&mut bytes[..1])?;
45 Ok(Self(if bytes[0] & 128 == 0 {
46 bytes[0] as u64
47 } else {
48 bytes[0] ^= 128;
49 input.read(&mut bytes[1..])?;
50 u64::from_be_bytes(bytes) + 128
51 }))
52 }
53}