1use crate::{EntryKind, EntryLink, Error, MAX_NODE_DATA_SIZE, Version};
2
3pub const MAX_ENTRY_SIZE: usize = MAX_NODE_DATA_SIZE + 9;
5
6#[derive(Debug)]
8pub struct Entry<V: Version> {
9 pub(crate) kind: EntryKind,
10 pub(crate) data: V::NodeData,
11}
12
13impl<V: Version> Entry<V> {
14 pub fn new(data: V::NodeData, left: EntryLink, right: EntryLink) -> Self {
16 Entry {
17 kind: EntryKind::Node(left, right),
18 data,
19 }
20 }
21
22 pub fn data(&self) -> &V::NodeData {
24 &self.data
25 }
26
27 pub fn new_leaf(data: V::NodeData) -> Self {
29 Entry {
30 kind: EntryKind::Leaf,
31 data,
32 }
33 }
34
35 pub fn complete(&self) -> bool {
37 self.leaf_count().is_power_of_two()
38 }
39
40 pub fn leaf_count(&self) -> u64 {
48 V::end_height(&self.data)
49 .checked_sub(V::start_height(&self.data))
50 .and_then(|height_diff| height_diff.checked_add(1))
51 .expect("entry height range must contain a representable number of leaves")
52 }
53
54 pub fn leaf(&self) -> bool {
56 matches!(self.kind, EntryKind::Leaf)
57 }
58
59 pub fn left(&self) -> Result<EntryLink, Error> {
61 match self.kind {
62 EntryKind::Leaf => Err(Error::node_expected()),
63 EntryKind::Node(left, _) => Ok(left),
64 }
65 }
66
67 pub fn right(&self) -> Result<EntryLink, Error> {
69 match self.kind {
70 EntryKind::Leaf => Err(Error::node_expected()),
71 EntryKind::Node(_, right) => Ok(right),
72 }
73 }
74
75 pub fn read<R: corez::io::Read>(
77 consensus_branch_id: u32,
78 r: &mut R,
79 ) -> corez::io::Result<Self> {
80 let kind = {
81 let mut byte = [0u8; 1];
82 r.read_exact(&mut byte)?;
83 match byte[0] {
84 0 => {
85 let mut buf = [0u8; 4];
86 r.read_exact(&mut buf)?;
87 let left = u32::from_le_bytes(buf);
88 r.read_exact(&mut buf)?;
89 let right = u32::from_le_bytes(buf);
90 EntryKind::Node(EntryLink::Stored(left), EntryLink::Stored(right))
91 }
92 1 => EntryKind::Leaf,
93 _ => return Err(corez::io::Error::from(corez::io::ErrorKind::InvalidData)),
94 }
95 };
96
97 let data = V::read(consensus_branch_id, r)?;
98
99 Ok(Entry { kind, data })
100 }
101
102 pub fn write<W: corez::io::Write>(&self, w: &mut W) -> corez::io::Result<()> {
104 match self.kind {
105 EntryKind::Node(EntryLink::Stored(left), EntryLink::Stored(right)) => {
106 w.write_all(&[0])?;
107 w.write_all(&left.to_le_bytes())?;
108 w.write_all(&right.to_le_bytes())?;
109 }
110 EntryKind::Leaf => {
111 w.write_all(&[1])?;
112 }
113 _ => {
114 return Err(corez::io::Error::from(corez::io::ErrorKind::InvalidData));
115 }
116 }
117
118 V::write(&self.data, w)?;
119
120 Ok(())
121 }
122
123 pub fn from_bytes<T: AsRef<[u8]>>(consensus_branch_id: u32, buf: T) -> corez::io::Result<Self> {
125 let mut cursor = corez::io::Cursor::new(buf);
126 Self::read(consensus_branch_id, &mut cursor)
127 }
128}
129
130impl<V: Version> core::fmt::Display for Entry<V> {
131 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
132 match self.kind {
133 EntryKind::Node(l, r) => write!(f, "node({l}, {r}, ..)"),
134 EntryKind::Leaf => write!(f, "leaf(..)"),
135 }
136 }
137}