Something went wrong. Try again.
A user-space CRDT filesystem
Something went wrong. Try again.
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980//! [`Transducer`] — the conversion strategy used by//! [`crate::host_store::HostStore`] on content-bearing methods.//!//! A transducer maps between a file's logical (user-visible) bytes and the//! bytes actually persisted on disk. The persistence layer invokes it inside//! the few [`fskit_rs::Filesystem`] methods that handle user content//! (currently `read` and `write`); every other method bypasses it.//!//! "Transducer" is borrowed from automata theory: a state machine that//! converts an input stream into an output stream. The current trait shape is//! whole-payload `bytes -> bytes` and our two impls happen to be pure, but//! the name leaves room for stateful, side-effecting implementations later//! (e.g. a CRDT transducer that records local edits as operations and//! rematerializes them on read).
/// Maps file content between its logical (user-visible) form and the bytes/// actually written to disk. Whole-file: implementations get the full/// payload and return the full transformed payload; the persistence layer/// handles all offset/splice math.////// Implementations may be stateful and side-effecting; the `&self` receiver/// is intentional — anything mutable should live behind interior mutability/// (e.g. `Mutex`) so the transducer can be cloned across connections.pub trait Transducer: Send + Sync + Clone + 'static { /// Logical bytes -> bytes to persist on disk. fn encode(&self, logical: &[u8]) -> Vec<u8>;
/// Persisted bytes -> logical bytes to return to the caller. fn decode(&self, on_disk: &[u8]) -> Vec<u8>;}
/// Pass-through transducer: on-disk bytes equal logical bytes.#[derive(Clone, Copy, Debug, Default)]pub struct Identity;
impl Transducer for Identity { fn encode(&self, logical: &[u8]) -> Vec<u8> { logical.to_vec() } fn decode(&self, on_disk: &[u8]) -> Vec<u8> { on_disk.to_vec() }}
/// Reverses every byte sequence passing through it. `encode == decode`,/// since reversing twice yields the original.#[derive(Clone, Copy, Debug, Default)]pub struct Reverse;
impl Transducer for Reverse { fn encode(&self, logical: &[u8]) -> Vec<u8> { logical.iter().rev().copied().collect() } fn decode(&self, on_disk: &[u8]) -> Vec<u8> { on_disk.iter().rev().copied().collect() }}
#[cfg(test)]mod tests { use super::*;
#[test] fn identity_round_trip() { let t = Identity; let bytes: &[u8] = b"hello world"; assert_eq!(t.decode(&t.encode(bytes)), bytes); assert_eq!(t.encode(bytes), bytes); }
#[test] fn reverse_round_trip() { let t = Reverse; let bytes: &[u8] = b"hello"; assert_eq!(t.encode(bytes), b"olleh"); assert_eq!(t.decode(b"olleh"), b"hello"); assert_eq!(t.decode(&t.encode(bytes)), bytes); }}