···11-use std::io::Read;
11+use crate::error::Result;
22use crate::parser::StarParser;
33-use crate::error::Result;
43use crate::types::StarItem;
54use cid::Cid;
65use std::collections::VecDeque;
66+use std::io::Read;
7788pub struct StarIterator<R> {
99 reader: R,
···5555 // make_contiguous() allows us to get a single slice, but might involve a memory copy/move
5656 // if the buffer is wrapped. This is amortized O(1) in many cases but can be O(N).
5757 // However, it solves the "head removal" problem perfectly (pop_front is O(1)).
5858-5858+5959 self.buffer.make_contiguous();
6060 let (slice, _) = self.buffer.as_slices();
6161-6161+6262 match self.parser.parse(slice) {
6363 Ok((consumed, Some(item))) => {
6464 self.buffer.drain(..consumed);
···6666 }
6767 Ok((consumed, None)) => {
6868 self.buffer.drain(..consumed);
6969-6969+7070 // Read more
7171 // We can't read directly into VecDeque easily without temporary buffer
7272 // because it doesn't expose a mutable slice to uninitialized memory.
···7676 Ok(n) => self.buffer.extend(&temp[..n]),
7777 Err(e) => return Some(Err(e.into())),
7878 }
7979- },
7979+ }
8080 Err(e) => return Some(Err(e)),
8181 }
8282 }
+44-31
src/parser.rs
···77#[derive(Debug)]
88enum State {
99 Header,
1010- Body {
1010+ Body {
1111 stack: Vec<StackItem>,
1212 current_len: Option<usize>,
1313 },
···46464747 pub fn parse(&mut self, buf: &[u8]) -> Result<(usize, Option<StarItem>)> {
4848 let mut consumed = 0;
4949-4949+5050 loop {
5151 let is_body_done = if let State::Body { stack, .. } = &self.state {
5252 stack.is_empty()
···8080 Some((n, len)) => (n, len),
8181 None => return Ok((consumed, None)),
8282 };
8383-8383+8484 let body_buf = ¤t_buf[len_consumed..];
8585 if body_buf.len() < len {
8686 consumed += len_consumed;
···89899090 let block_bytes = &body_buf[..len];
9191 *current_len = None;
9292-9292+9393 let item = stack.pop().unwrap();
9494 let result_item = match item {
9595- StackItem::Node { expected, expected_height } => {
9696- Self::process_node(block_bytes, expected, expected_height, stack)?
9797- },
9898- StackItem::Record { key, expected, implicit_index } => {
9595+ StackItem::Node {
9696+ expected,
9797+ expected_height,
9898+ } => Self::process_node(block_bytes, expected, expected_height, stack)?,
9999+ StackItem::Record {
100100+ key,
101101+ expected,
102102+ implicit_index,
103103+ } => {
99104 Self::process_record(block_bytes, key, expected, implicit_index, stack)?
100100- },
105105+ }
101106 _ => return Err(StarError::InvalidState("Unexpected stack item".into())),
102107 };
103108···117122 }
118123119124 let slice = &buf[1..];
120120-125125+121126 let (ver, remaining1) = match unsigned_varint::decode::usize(slice) {
122127 Ok(res) => res,
123128 Err(unsigned_varint::decode::Error::Insufficient) => return Ok(None),
124129 Err(e) => return Err(StarError::InvalidState(format!("Varint error: {}", e))),
125130 };
126126-131131+127132 let (len, remaining2) = match unsigned_varint::decode::usize(remaining1) {
128133 Ok(res) => res,
129134 Err(unsigned_varint::decode::Error::Insufficient) => return Ok(None),
130135 Err(e) => return Err(StarError::InvalidState(format!("Varint error: {}", e))),
131136 };
132137133133- let header_varints_len = buf.len() - 1 - remaining2.len();
134134- let total_header_len = 1 + header_varints_len;
138138+ let header_varints_len = buf.len() - 1 - remaining2.len();
139139+ let total_header_len = 1 + header_varints_len;
135140 let total_len = total_header_len + len;
136141137142 if buf.len() < total_len {
···141146 let commit_bytes = &buf[total_header_len..total_len];
142147 let commit: StarCommit = serde_ipld_dagcbor::from_slice(commit_bytes)
143148 .map_err(|e| StarError::Cbor(e.to_string()))?;
144144-145145- let _ = ver;
149149+150150+ let _ = ver;
146151147152 let mut stack = Vec::new();
148153 if let Some(root_cid) = commit.data {
···152157 });
153158 }
154159155155- self.state = State::Body {
160160+ self.state = State::Body {
156161 stack,
157157- current_len: None
162162+ current_len: None,
158163 };
159164 Ok(Some((total_len, StarItem::Commit(commit))))
160165 }
···205210 let consumed = buf.len() - remaining.len();
206211 *current_len = Some(l);
207212 Ok(Some((consumed, l)))
208208- },
213213+ }
209214 Err(unsigned_varint::decode::Error::Insufficient) => Ok(None),
210215 Err(e) => Err(StarError::InvalidState(format!("Varint error: {}", e))),
211216 }
212217 }
213218214214- fn process_node(block_bytes: &[u8], expected: Option<Cid>, expected_height: Option<u32>, stack: &mut Vec<StackItem>) -> Result<Option<StarItem>> {
219219+ fn process_node(
220220+ block_bytes: &[u8],
221221+ expected: Option<Cid>,
222222+ expected_height: Option<u32>,
223223+ stack: &mut Vec<StackItem>,
224224+ ) -> Result<Option<StarItem>> {
215225 let node: StarMstNode = serde_ipld_dagcbor::from_slice(block_bytes)
216226 .map_err(|e| StarError::Cbor(e.to_string()))?;
217227···237247 .map_err(|e| StarError::Cbor(e.to_string()))?;
238248239249 let hash = Sha256::digest(&bytes);
240240- let cid = Cid::new_v1(
241241- 0x71,
242242- cid::multihash::Multihash::wrap(0x12, &hash)?,
243243- );
250250+ let cid = Cid::new_v1(0x71, cid::multihash::Multihash::wrap(0x12, &hash)?);
244251 if let Some(exp) = expected {
245252 if cid != exp {
246253 return Err(StarError::VerificationFailed {
···260267261268 // Push children in reverse
262269 let child_expected_height = height.checked_sub(1);
263263-270270+264271 if height > 0 {
265272 let next_h = child_expected_height.unwrap();
266266-273273+267274 for i in (0..node.e.len()).rev() {
268275 let e = &node.e[i];
269276 let key = entry_keys[i].clone();
270277271278 if e.t_archived == Some(true) {
272272- stack.push(StackItem::Node {
279279+ stack.push(StackItem::Node {
273280 expected: e.t,
274274- expected_height: Some(next_h),
281281+ expected_height: Some(next_h),
275282 });
276283 }
277284···286293 }
287294288295 if node.l_archived == Some(true) {
289289- stack.push(StackItem::Node {
296296+ stack.push(StackItem::Node {
290297 expected: node.l,
291298 expected_height: Some(next_h),
292299 });
293300 }
294301 } else {
295302 // Height 0: Push records only
296296- for i in (0..node.e.len()).rev() {
303303+ for i in (0..node.e.len()).rev() {
297304 let e = &node.e[i];
298305 let key = entry_keys[i].clone();
299299-306306+300307 if e.v_archived == Some(true) {
301308 let implicit_index = if e.v.is_none() { Some(i) } else { None };
302309 stack.push(StackItem::Record {
···311318 Ok(Some(StarItem::Node(node)))
312319 }
313320314314- fn process_record(block_bytes: &[u8], key: Vec<u8>, expected: Option<Cid>, implicit_index: Option<usize>, stack: &mut Vec<StackItem>) -> Result<Option<StarItem>> {
321321+ fn process_record(
322322+ block_bytes: &[u8],
323323+ key: Vec<u8>,
324324+ expected: Option<Cid>,
325325+ implicit_index: Option<usize>,
326326+ stack: &mut Vec<StackItem>,
327327+ ) -> Result<Option<StarItem>> {
315328 let hash = Sha256::digest(block_bytes);
316329 let cid = Cid::new_v1(0x71, cid::multihash::Multihash::wrap(0x12, &hash)?);
317330
···11use crate::error::{Result, StarError};
22-use crate::types::{calculate_height, StarMstNode};
22+use crate::types::{StarMstNode, calculate_height};
3344/// Validates the structure of a STAR MST node.
55-///
55+///
66/// Checks:
77/// - Key height consistency (all keys must have same height)
88/// - Height matching against expectation