1 unstable release
| 0.1.16 | Sep 18, 2025 |
|---|
#614 in Database implementations
Used in 6 crates
175KB
3.5K
SLoC
KotobaDB Core
Core traits, data structures, and transaction logic for KotobaDB. This crate provides the foundational types and interfaces that all KotobaDB implementations must satisfy.
Overview
kotoba-db-core defines the fundamental abstractions that make KotobaDB work:
- Data Types:
Value,Block,NodeBlock,EdgeBlock,Cid - Storage Engine:
StorageEnginetrait for pluggable backends - Serialization: CBOR-based binary serialization with content addressing
Data Types
Value
The fundamental data type for all properties and values:
pub enum Value {
String(String),
Int(i64),
Float(f64),
Bool(bool),
Bytes(Vec<u8>),
Link(Cid), // Reference to another block
}
Block
Content-addressed data blocks:
pub enum Block {
Node(NodeBlock),
Edge(EdgeBlock),
}
CID (Content Identifier)
Cryptographic content identifier using BLAKE3:
#[derive(Clone, PartialEq, Eq, Hash)]
pub struct Cid([u8; 32]);
Storage Engine Trait
The core abstraction for pluggable storage backends:
#[async_trait]
pub trait StorageEngine: Send + Sync {
/// Store a key-value pair
async fn put(&mut self, key: &[u8], value: &[u8]) -> Result<()>;
/// Retrieve a value by key
async fn get(&self, key: &[u8]) -> Result<Option<Vec<u8>>>;
/// Delete a key-value pair
async fn delete(&mut self, key: &[u8]) -> Result<()>;
/// Scan keys with a prefix
async fn scan(&self, prefix: &[u8]) -> Result<Vec<(Vec<u8>, Vec<u8>)>>;
}
Extension Methods
The trait provides convenient methods for working with content-addressed blocks:
impl dyn StorageEngine {
/// Store a content-addressed block
pub async fn put_block(&mut self, block: &Block) -> Result<Cid>
/// Retrieve a content-addressed block
pub async fn get_block(&self, cid: &Cid) -> Result<Option<Block>>
}
Node and Edge Structures
NodeBlock
Represents a graph node with properties:
pub struct NodeBlock {
pub properties: BTreeMap<String, Value>,
}
EdgeBlock
Represents a graph edge between nodes:
pub struct EdgeBlock {
pub source: Cid,
pub target: Cid,
pub properties: BTreeMap<String, Value>,
}
Content Addressing
All blocks are content-addressed using CID:
impl Block {
/// Compute the CID for this block
pub fn cid(&self) -> Result<Cid>
/// Serialize to CBOR bytes
pub fn to_bytes(&self) -> Result<Vec<u8>>
/// Deserialize from CBOR bytes
pub fn from_bytes(bytes: &[u8]) -> Result<Self>
}
Usage Examples
Implementing a Storage Engine
use kotoba_db_core::{StorageEngine, Block, Cid};
pub struct MyStorageEngine {
// Your storage implementation
}
#[async_trait::async_trait]
impl StorageEngine for MyStorageEngine {
async fn put(&mut self, key: &[u8], value: &[u8]) -> Result<()> {
// Your put implementation
Ok(())
}
async fn get(&self, key: &[u8]) -> Result<Option<Vec<u8>>> {
// Your get implementation
Ok(None)
}
async fn delete(&mut self, key: &[u8]) -> Result<()> {
// Your delete implementation
Ok(())
}
async fn scan(&self, prefix: &[u8]) -> Result<Vec<(Vec<u8>, Vec<u8>)>> {
// Your scan implementation
Ok(vec![])
}
}
Working with Blocks
use kotoba_db_core::{Block, NodeBlock, Value};
use std::collections::BTreeMap;
// Create a node
let mut properties = BTreeMap::new();
properties.insert("name".to_string(), Value::String("Alice".to_string()));
properties.insert("age".to_string(), Value::Int(30));
let node = NodeBlock { properties };
let block = Block::Node(node);
// Compute CID
let cid = block.cid()?;
// Serialize
let bytes = block.to_bytes()?;
// Deserialize
let restored_block = Block::from_bytes(&bytes)?;
Architecture
This crate is designed to be:
- Minimal: Only essential types and traits
- Extensible: Easy to implement custom storage engines
- Performance-oriented: Efficient serialization and content addressing
- Safe: Memory-safe Rust with comprehensive error handling
Dependencies
serde: Serialization frameworkciborium: CBOR serializationblake3: Cryptographic hashingasync-trait: Async trait supportanyhow: Error handling
Testing
cargo test --package kotoba-db-core
License
Licensed under the MIT License.
Dependencies
~18MB
~340K SLoC