Struct FeoxStore

Source
pub struct FeoxStore { /* private fields */ }
Expand description

High-performance embedded key-value store.

FeoxStore provides ultra-fast key-value storage with optional persistence. It uses lock-free data structures for concurrent access and achieves sub-microsecond latencies for most operations.

§Thread Safety

All methods are thread-safe and can be called concurrently from multiple threads.

Implementations§

Source§

impl FeoxStore

Source

pub fn new(device_path: Option<String>) -> Result<Self>

Create a new FeoxStore with default configuration

Source

pub fn with_config(config: StoreConfig) -> Result<Self>

Create a new FeoxStore with custom configuration

Source

pub fn builder() -> StoreBuilder

Create a builder for configuring FeoxStore.

§Example
use feoxdb::FeoxStore;

let store = FeoxStore::builder()
    .max_memory(2_000_000_000)
    .build()?;
Source

pub fn insert(&self, key: &[u8], value: &[u8]) -> Result<()>

Insert or update a key-value pair.

§Arguments
  • key - The key to insert (max 65KB)
  • value - The value to store (max 4GB)
  • timestamp - Optional timestamp for conflict resolution. If None, uses current time.
§Returns

Returns Ok(()) if successful.

§Errors
  • InvalidKey - Key is empty or too large
  • InvalidValue - Value is too large
  • OlderTimestamp - Timestamp is not newer than existing record
  • OutOfMemory - Memory limit exceeded
§Example
store.insert(b"user:123", b"{\"name\":\"Mehran\"}")?;
§Performance
  • Memory mode: ~800ns
  • Persistent mode: ~1µs (buffered write)
Source

pub fn insert_with_timestamp( &self, key: &[u8], value: &[u8], timestamp: Option<u64>, ) -> Result<()>

Insert or update a key-value pair with explicit timestamp.

This is the advanced version that allows manual timestamp control for conflict resolution. Most users should use insert() instead.

§Arguments
  • key - The key to insert (max 65KB)
  • value - The value to store (max 4GB)
  • timestamp - Optional timestamp for conflict resolution. If None, uses current time.
§Errors
  • OlderTimestamp - Timestamp is not newer than existing record
Source

pub fn get(&self, key: &[u8]) -> Result<Vec<u8>>

Retrieve a value by key.

§Arguments
  • key - The key to look up
  • expected_size - Optional expected value size for validation
§Returns

Returns the value as a Vec<u8> if found.

§Errors
  • KeyNotFound - Key does not exist
  • InvalidKey - Key is invalid
  • SizeMismatch - Value size doesn’t match expected size
  • IoError - Failed to read from disk (persistent mode)
§Example
let value = store.get(b"key")?;
assert_eq!(value, b"value");
§Performance
  • Memory mode: ~100ns
  • Persistent mode (cached): ~150ns
  • Persistent mode (disk read): ~500ns
Source

pub fn delete(&self, key: &[u8]) -> Result<()>

Delete a key-value pair.

§Arguments
  • key - The key to delete
  • timestamp - Optional timestamp for conflict resolution
§Returns

Returns Ok(()) if the key was deleted.

§Errors
  • KeyNotFound - Key does not exist
  • OlderTimestamp - Timestamp is not newer than existing record
§Example
store.delete(b"temp")?;
§Performance
  • Memory mode: ~300ns
  • Persistent mode: ~400ns
Source

pub fn delete_with_timestamp( &self, key: &[u8], timestamp: Option<u64>, ) -> Result<()>

Delete a key-value pair with explicit timestamp.

This is the advanced version that allows manual timestamp control. Most users should use delete() instead.

§Arguments
  • key - The key to delete
  • timestamp - Optional timestamp. If None, uses current time.
§Errors
  • OlderTimestamp - Timestamp is not newer than existing record
Source

pub fn json_patch(&self, key: &[u8], patch: &[u8]) -> Result<()>

Apply a JSON patch to a value.

Uses RFC 6902 JSON Patch format to modify specific fields in a JSON document. Both the existing value and the patch must be valid JSON.

§Arguments
  • key - The key containing the JSON document to patch
  • patch - JSON Patch operations in RFC 6902 format
  • timestamp - Optional timestamp for conflict resolution
§Returns

Returns Ok(()) if the update was applied.

§Errors
  • KeyNotFound - Key does not exist
  • OlderTimestamp - Timestamp is not newer than existing record
  • JsonPatchError - Invalid JSON document or patch format
§Example
// Insert initial JSON value
let initial = br#"{"name":"Alice","age":30}"#;
store.insert(b"user:1", initial)?;

// Apply JSON patch to update age
let patch = br#"[{"op":"replace","path":"/age","value":31}]"#;
store.json_patch(b"user:1", patch)?;

// Value now has age updated to 31
let updated = store.get(b"user:1")?;
assert_eq!(updated.len(), initial.len()); // Same length, just age changed
Source

pub fn json_patch_with_timestamp( &self, key: &[u8], patch: &[u8], timestamp: Option<u64>, ) -> Result<()>

Apply JSON patch with explicit timestamp.

This is the advanced version that allows manual timestamp control. Most users should use json_patch() instead.

§Arguments
  • key - The key whose value to patch
  • patch - JSON Patch array (RFC 6902)
  • timestamp - Optional timestamp. If None, uses current time.
§Errors
  • OlderTimestamp - Timestamp is not newer than existing record
Source

pub fn range_query( &self, start_key: &[u8], end_key: &[u8], limit: usize, ) -> Result<Vec<(Vec<u8>, Vec<u8>)>>

Perform a range query on the store.

Returns all key-value pairs where the key is >= start_key and <= end_key. Both bounds are inclusive.

§Arguments
  • start_key - Inclusive lower bound
  • end_key - Inclusive upper bound
  • limit - Maximum number of results to return
§Returns

Returns a vector of (key, value) pairs in sorted order.

§Example
store.insert(b"user:001", b"Alice")?;
store.insert(b"user:002", b"Bob")?;
store.insert(b"user:003", b"Charlie")?;
store.insert(b"user:004", b"David")?;

// Get users 001 through 003 (inclusive)
let results = store.range_query(b"user:001", b"user:003", 10)?;
assert_eq!(results.len(), 3);
Source

pub fn atomic_increment(&self, key: &[u8], delta: i64) -> Result<i64>

Atomically increment a numeric counter.

The value must be stored as an 8-byte little-endian i64. If the key doesn’t exist, it will be created with the given delta value. If it exists, the value will be incremented atomically.

§Value Format

The value MUST be exactly 8 bytes representing a little-endian i64. Use i64::to_le_bytes() to create the initial value:

let zero: i64 = 0;
store.insert(b"counter", &zero.to_le_bytes())?;
§Arguments
  • key - The key of the counter
  • delta - The amount to increment by (can be negative for decrement)
  • timestamp - Optional timestamp for conflict resolution
§Returns

Returns the new value after incrementing.

§Errors
  • InvalidOperation - Existing value is not exactly 8 bytes (not a valid i64)
  • OlderTimestamp - Timestamp is not newer than existing record
§Example
// Initialize counter with proper binary format
let initial: i64 = 0;
store.insert(b"visits", &initial.to_le_bytes())?;

// Increment atomically
let val = store.atomic_increment(b"visits", 1)?;
assert_eq!(val, 1);

// Increment by 5
let val = store.atomic_increment(b"visits", 5)?;
assert_eq!(val, 6);

// Decrement by 2
let val = store.atomic_increment(b"visits", -2)?;
assert_eq!(val, 4);

// Or create new counter directly (starts at delta value)
let downloads = store.atomic_increment(b"downloads", 100)?;
assert_eq!(downloads, 100);
Source

pub fn atomic_increment_with_timestamp( &self, key: &[u8], delta: i64, timestamp: Option<u64>, ) -> Result<i64>

Atomically increment/decrement with explicit timestamp.

This is the advanced version that allows manual timestamp control. Most users should use atomic_increment() instead.

§Arguments
  • key - The key to increment/decrement
  • delta - Amount to add (negative to decrement)
  • timestamp - Optional timestamp. If None, uses current time.
§Errors
  • OlderTimestamp - Timestamp is not newer than existing record
Source

pub fn get_size(&self, key: &[u8]) -> Result<usize>

Get the size of a value without loading it.

Useful for checking value size before loading large values from disk.

§Arguments
  • key - The key to check
§Returns

Returns the size in bytes of the value.

§Errors
  • KeyNotFound - Key does not exist
§Example
store.insert(b"large_file", &vec![0u8; 1_000_000])?;

// Check size before loading
let size = store.get_size(b"large_file")?;
assert_eq!(size, 1_000_000);
Source

pub fn flush_all(&self)

Force flush all pending writes to disk.

In persistent mode, ensures all buffered writes are flushed to disk. In memory-only mode, this is a no-op.

§Example
let store = FeoxStore::new(Some("/path/to/data.feox".to_string()))?;
store.insert(b"important", b"data")?;
store.flush_all();  // Ensure data is persisted
Source

pub fn contains_key(&self, key: &[u8]) -> bool

Check if a key exists

Source

pub fn len(&self) -> usize

Get the number of records in the store

Source

pub fn is_empty(&self) -> bool

Check if the store is empty

Source

pub fn memory_usage(&self) -> usize

Get memory usage statistics

Source

pub fn stats(&self) -> StatsSnapshot

Get statistics snapshot

Source

pub fn flush(&self)

Flush all pending writes to disk (for persistent mode)

Trait Implementations§

Source§

impl Drop for FeoxStore

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

§

impl<T> Pointable for T

§

const ALIGN: usize

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

§

fn vzip(self) -> V