# Rust Guidelines for StemeDB **When to use:** Writing Rust code for any StemeDB crate. ## Framework All code MUST follow patterns in [Coding Guidelines](../coding-guidelines.md). ## Core Principles ### 1. Append-Only Everything ```rust // Good: Append new assertion pub fn put(&self, assertion: &Assertion) -> Result { let hash = assertion.hash(); self.store.insert(hash.as_bytes(), assertion.to_bytes())?; Ok(hash) } // Bad: Mutation pub fn update(&mut self, hash: &Hash, new_value: Value) { // NEVER DO THIS } ``` ### 2. Content-Addressed Storage ```rust use blake3::Hasher; impl Assertion { pub fn hash(&self) -> Hash { let mut hasher = Hasher::new(); hasher.update(&self.subject.0.as_bytes()); hasher.update(&self.predicate.0.as_bytes()); hasher.update(&self.object.to_bytes()); hasher.update(&self.timestamp.to_le_bytes()); Hash(hasher.finalize().into()) } } ``` ### 3. Defensive Error Handling ```rust // Good: Explicit error handling pub fn get(&self, hash: &Hash) -> Result { let bytes = self.store .get(hash.as_bytes()) .context("storage read failed")? .ok_or(StemeError::NotFound(*hash))?; rkyv::from_bytes(&bytes) .map_err(|e| StemeError::Deserialization(e.to_string())) } // Bad: Panic on failure pub fn get(&self, hash: &Hash) -> Assertion { let bytes = self.store.get(hash.as_bytes()).unwrap().unwrap(); rkyv::from_bytes(&bytes).unwrap() } ``` ### 4. Zero-Copy Serialization ```rust use rkyv::{Archive, Deserialize, Serialize}; #[derive(Archive, Deserialize, Serialize)] pub struct Assertion { pub subject: EntityId, pub predicate: RelationId, pub object: ObjectValue, // ... } // Read without copying let archived = rkyv::check_archived_root::(&bytes)?; println!("Subject: {}", archived.subject.0); ``` ## Module Patterns ### Public API in lib.rs ```rust // crates/stemedb-core/src/lib.rs mod assertion; mod error; mod store; mod types; // Re-export public API pub use assertion::Assertion; pub use error::StemeError; pub use store::{Store, MemoryStore}; pub use types::{EntityId, RelationId, Hash, AgentId, ObjectValue}; ``` ### Error Types ```rust // crates/stemedb-core/src/error.rs use thiserror::Error; #[derive(Debug, Error)] pub enum StemeError { #[error("assertion not found: {0:?}")] NotFound(Hash), #[error("invalid signature for agent {agent:?}")] InvalidSignature { agent: AgentId }, #[error("serialization failed: {0}")] Serialization(String), #[error("deserialization failed: {0}")] Deserialization(String), #[error("storage error: {0}")] Storage(#[from] sled::Error), } pub type Result = std::result::Result; ``` ## Quality Gate Before commit: ```bash # All must pass cargo build --workspace cargo test --workspace cargo clippy --workspace -- -D warnings cargo fmt --check ``` ## Related - [Testing Guide](../local/testing.md) - [stemedb-core skill](.claude/skills/stemedb-core/SKILL.md) - [Architecture](../../../architecture.md)