Something went wrong. Try again.
STreaming ARchive format: simpler, stricter, smaller than CARs for a subset of use-cases. forked from microcosm.blue/star
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116use crate::error::{Result, StarError};use cid::Cid;use serde::{Deserialize, Serialize};use serde_bytes::ByteBuf;use sha2::{Digest, Sha256};
// --- STAR Types (Wire Format) ---
/// The STAR Commit object#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]pub struct StarCommit { pub did: String, pub version: i64, #[serde(default, skip_serializing_if = "Option::is_none")] pub data: Option<Cid>, pub rev: String, #[serde(default, skip_serializing_if = "Option::is_none")] pub prev: Option<Cid>, #[serde(default, skip_serializing_if = "Option::is_none")] pub sig: Option<ByteBuf>,}
/// The STAR MST Node object#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]pub struct StarMstNode { #[serde(default, skip_serializing_if = "Option::is_none")] pub l: Option<Cid>, #[serde(rename = "L", default, skip_serializing_if = "Option::is_none")] pub l_archived: Option<bool>, pub e: Vec<StarMstEntry>,}
/// The STAR MST Entry object#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]pub struct StarMstEntry { pub p: u32, pub k: ByteBuf, #[serde(default, skip_serializing_if = "Option::is_none")] pub v: Option<Cid>, #[serde(rename = "V", default, skip_serializing_if = "Option::is_none")] pub v_archived: Option<bool>, #[serde(default, skip_serializing_if = "Option::is_none")] pub t: Option<Cid>, #[serde(rename = "T", default, skip_serializing_if = "Option::is_none")] pub t_archived: Option<bool>,}
// --- CAR Repo Types (Canonical / Hashing Format) ---
/// The Canonical MST Node object (for CID calculation)#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]pub struct RepoMstNode { pub l: Option<Cid>, pub e: Vec<RepoMstEntry>,}
/// The Canonical MST Entry object#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]pub struct RepoMstEntry { pub p: u32, pub k: ByteBuf, pub v: Cid, // Required in Repo spec pub t: Option<Cid>,}
// --- Conversion ---
impl StarMstNode { pub fn to_repo(&self) -> Result<RepoMstNode> { let mut entries = Vec::with_capacity(self.e.len()); for e in &self.e { entries.push(RepoMstEntry { p: e.p, k: e.k.clone(), v: e.v.ok_or_else(|| { StarError::InvalidState( "Cannot convert implicit STAR entry to Repo entry: missing 'v'".into(), ) })?, t: e.t, }); } Ok(RepoMstNode { l: self.l, e: entries, }) }}
/// Calculates the MST height of a key (number of leading zero bits in SHA256 / 2).pub fn calculate_height(key: &[u8]) -> u32 { let digest = Sha256::digest(key); let mut zeros = 0; for &byte in digest.iter() { if byte == 0 { zeros += 8; } else { zeros += byte.leading_zeros(); break; } } zeros / 2}
/// A parsed item from the STAR stream#[derive(Debug, Clone)]pub enum StarItem { Commit(StarCommit), Node(StarMstNode), Record { key: Vec<u8>, cid: Cid, content: Option<Vec<u8>>, },}