···11+pub mod error;
22+pub mod parser;
33+pub mod ser;
44+pub mod types;
55+66+#[cfg(feature = "blocking")]
77+pub mod blocking;
88+99+#[cfg(feature = "async")]
1010+pub mod async_io;
1111+1212+pub use error::{Result, StarError};
1313+pub use parser::StarParser;
1414+pub use ser::StarEncoder;
1515+pub use types::{Commit, MstEntry, MstNode, StarItem};
1616+1717+#[cfg(feature = "blocking")]
1818+pub use blocking::StarIterator;
+286
src/parser.rs
···11+use crate::error::{Result, StarError};
22+use crate::types::{Commit, MstNode, StarItem};
33+use bytes::{Buf, BytesMut};
44+use cid::Cid;
55+use sha2::{Digest, Sha256};
66+use std::io::Cursor;
77+88+#[derive(Debug)]
99+enum State {
1010+ Header,
1111+ Body {
1212+ stack: Vec<StackItem>,
1313+ current_len: Option<usize>,
1414+ },
1515+ Done,
1616+}
1717+1818+#[derive(Debug)]
1919+enum StackItem {
2020+ Node {
2121+ expected: Option<Cid>,
2222+ },
2323+ Record {
2424+ key: Vec<u8>,
2525+ expected: Option<Cid>,
2626+ implicit_index: Option<usize>,
2727+ },
2828+ VerifyLayer0 {
2929+ node: MstNode,
3030+ parent_expected: Option<Cid>,
3131+ pending_records: Vec<(usize, Cid)>,
3232+ },
3333+}
3434+3535+pub struct StarParser {
3636+ state: State,
3737+}
3838+3939+impl StarParser {
4040+ pub fn new() -> Self {
4141+ Self {
4242+ state: State::Header,
4343+ }
4444+ }
4545+4646+ pub fn input(&mut self, buf: &mut BytesMut) -> Result<Option<StarItem>> {
4747+ loop {
4848+ match self.state {
4949+ State::Done => return Ok(None),
5050+ State::Header => {
5151+ if buf.is_empty() {
5252+ return Ok(None);
5353+ }
5454+ if buf[0] != 0x2A {
5555+ return Err(StarError::InvalidHeader);
5656+ }
5757+5858+ let mut cursor = Cursor::new(&buf[1..]);
5959+6060+ let _ver = match leb128::read::unsigned(&mut cursor) {
6161+ Ok(v) => v,
6262+ Err(_) => return Ok(None),
6363+ };
6464+6565+ let len = match leb128::read::unsigned(&mut cursor) {
6666+ Ok(l) => l,
6767+ Err(_) => return Ok(None),
6868+ };
6969+7070+ let header_len = 1 + cursor.position() as usize;
7171+ let total_len = header_len + len as usize;
7272+7373+ if buf.len() < total_len {
7474+ return Ok(None);
7575+ }
7676+7777+ buf.advance(header_len);
7878+ let commit_bytes = buf.split_to(len as usize);
7979+ let commit: Commit = serde_ipld_dagcbor::from_slice(&commit_bytes)
8080+ .map_err(|e| StarError::Cbor(e.to_string()))?;
8181+8282+ self.state = State::Body {
8383+ stack: commit
8484+ .data
8585+ .map(|root_cid| {
8686+ vec![StackItem::Node {
8787+ expected: Some(root_cid),
8888+ }]
8989+ })
9090+ .unwrap_or(vec![]),
9191+ current_len: None,
9292+ };
9393+ return Ok(Some(StarItem::Commit(commit)));
9494+ }
9595+ State::Body {
9696+ ref mut stack,
9797+ mut current_len,
9898+ } => {
9999+ if stack.is_empty() {
100100+ self.state = State::Done;
101101+ return Ok(None);
102102+ }
103103+104104+ // Check for verification task
105105+ if let Some(StackItem::VerifyLayer0 { .. }) = stack.last()
106106+ && let Some(StackItem::VerifyLayer0 {
107107+ mut node,
108108+ parent_expected,
109109+ pending_records,
110110+ }) = stack.pop()
111111+ {
112112+ for (idx, cid) in pending_records {
113113+ if idx < node.e.len() {
114114+ node.e[idx].v = Some(cid);
115115+ }
116116+ }
117117+118118+ let bytes = serde_ipld_dagcbor::to_vec(&node)
119119+ .map_err(|e| StarError::Cbor(e.to_string()))?;
120120+ let hash = Sha256::digest(&bytes);
121121+ // CIDv1 DAG-CBOR SHA2-256
122122+ let cid = Cid::new_v1(0x71, cid::multihash::Multihash::wrap(0x12, &hash)?);
123123+124124+ if let Some(expected) = parent_expected
125125+ && cid != expected
126126+ {
127127+ return Err(StarError::VerificationFailed {
128128+ expected: expected.to_string(),
129129+ computed: cid.to_string(),
130130+ });
131131+ }
132132+ continue;
133133+ }
134134+135135+ // Read Length
136136+ let len = if let Some(l) = current_len { l } else {
137137+ let mut cursor = Cursor::new(&buf[..]);
138138+ match leb128::read::unsigned(&mut cursor) {
139139+ Ok(l) => {
140140+ current_len.replace(l as usize);
141141+ buf.advance(cursor.position() as usize);
142142+ l as usize
143143+ }
144144+ Err(_) => return Ok(None),
145145+ }
146146+ };
147147+148148+ if buf.len() < len {
149149+ return Ok(None);
150150+ }
151151+152152+ let block_bytes = buf.split_to(len);
153153+ current_len.take();
154154+155155+ match stack.pop().unwrap() {
156156+ StackItem::Node { expected } => {
157157+ let node: MstNode = serde_ipld_dagcbor::from_slice(&block_bytes)
158158+ .map_err(|e| StarError::Cbor(e.to_string()))?;
159159+160160+ // Check for implicit records
161161+ let mut has_implicit = false;
162162+ for e in &node.e {
163163+ if e.v_archived == Some(true) && e.v.is_none() {
164164+ has_implicit = true;
165165+ break;
166166+ }
167167+ }
168168+169169+ if !has_implicit {
170170+ let hash = Sha256::digest(&block_bytes);
171171+ let cid = Cid::new_v1(
172172+ 0x71,
173173+ cid::multihash::Multihash::wrap(0x12, &hash)?,
174174+ );
175175+ if let Some(exp) = expected
176176+ && cid != exp
177177+ {
178178+ return Err(StarError::VerificationFailed {
179179+ expected: exp.to_string(),
180180+ computed: cid.to_string(),
181181+ });
182182+ }
183183+ } else {
184184+ stack.push(StackItem::VerifyLayer0 {
185185+ node: node.clone(),
186186+ parent_expected: expected,
187187+ pending_records: Vec::new(),
188188+ });
189189+ }
190190+191191+ // Reconstruct keys
192192+ let mut prev_key_bytes = Vec::new();
193193+ let mut entry_keys = Vec::new();
194194+ for e in &node.e {
195195+ let mut key = if e.p as usize <= prev_key_bytes.len() {
196196+ prev_key_bytes[..e.p as usize].to_vec()
197197+ } else {
198198+ // Should not happen in valid MST
199199+ prev_key_bytes.clone()
200200+ };
201201+ key.extend_from_slice(&e.k);
202202+ entry_keys.push(key.clone());
203203+ prev_key_bytes = key;
204204+ }
205205+206206+ // Push children in reverse
207207+ for i in (0..node.e.len()).rev() {
208208+ let e = &node.e[i];
209209+ let key = entry_keys[i].clone();
210210+211211+ if e.t_archived == Some(true) {
212212+ stack.push(StackItem::Node { expected: e.t });
213213+ }
214214+215215+ if e.v_archived == Some(true) {
216216+ let implicit_index = if e.v.is_none() { Some(i) } else { None };
217217+ stack.push(StackItem::Record {
218218+ key,
219219+ expected: e.v,
220220+ implicit_index,
221221+ });
222222+ }
223223+ }
224224+225225+ if node.l_archived == Some(true) {
226226+ stack.push(StackItem::Node { expected: node.l });
227227+ }
228228+229229+ return Ok(Some(StarItem::Node(node)));
230230+ }
231231+ StackItem::Record {
232232+ key,
233233+ expected,
234234+ implicit_index,
235235+ } => {
236236+ let hash = Sha256::digest(&block_bytes);
237237+ let cid =
238238+ Cid::new_v1(0x71, cid::multihash::Multihash::wrap(0x12, &hash)?);
239239+240240+ if let Some(exp) = expected
241241+ && cid != exp
242242+ {
243243+ return Err(StarError::VerificationFailed {
244244+ expected: exp.to_string(),
245245+ computed: cid.to_string(),
246246+ });
247247+ }
248248+249249+ if let Some(idx) = implicit_index {
250250+ let mut found = false;
251251+ for item in stack.iter_mut().rev() {
252252+ if let StackItem::VerifyLayer0 {
253253+ pending_records, ..
254254+ } = item
255255+ {
256256+ pending_records.push((idx, cid));
257257+ found = true;
258258+ break;
259259+ }
260260+ }
261261+ if !found {
262262+ return Err(StarError::InvalidState(
263263+ "Implicit record verification context missing".into(),
264264+ ));
265265+ }
266266+ }
267267+268268+ return Ok(Some(StarItem::Record {
269269+ key,
270270+ cid,
271271+ content: Some(block_bytes.to_vec()),
272272+ }));
273273+ }
274274+ _ => return Err(StarError::InvalidState("Unexpected stack item".into())),
275275+ }
276276+ }
277277+ }
278278+ }
279279+ }
280280+}
281281+282282+impl Default for StarParser {
283283+ fn default() -> Self {
284284+ Self::new()
285285+ }
286286+}