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}