#state #json #persistence #storage

json_state

A simple Rust library for managing states using json with file persistence

1 unstable release

Uses new Rust 2024

new 0.1.0 May 7, 2025

#682 in Filesystem

MIT license

29KB
267 lines

JSON_STATE

A lightweight, flexible Rust module for managing application state persistence across memory and filesystem.

Description

The JSON_STATE provides a simple and efficient way to store, retrieve, and manage application states. It enables seamless persistence of JSON-based state data both in memory and on the filesystem, making it ideal for applications that need to maintain state between sessions or require robust state handling.

Features

  • Dual Persistence: States are stored both in memory for fast access and on disk for persistence
  • JSON-based Payload: Store any data that can be serialized to JSON
  • Unique State IDs: Each state has a unique identifier for reliable retrieval
  • Memory & Filesystem Operations: Save, load, and delete states from both memory and filesystem
  • Error Handling: Robust error handling for filesystem operations
  • Directory-based Storage: States are organized in a configurable directory
  • Safe File Loading: Validates files based on UUID format and content integrity
  • Directory Management: Utilities for clearing state directories and ensuring clean environments

Installation

Add the following to your Cargo.toml:

[dependencies]
state = "0.1.0"
serde_json = "1.0"
uuid = "1.0"
serde = { version = "1.0", features = ["derive"] }

Usage

Here's a simple example demonstrating how to use the State Management module:

use serde_json::{Value, json};
use state::{State, StateManager};

fn main() -> std::io::Result<()> {
    // Create a StateManager with the directory path
    let mut manager = StateManager::new("states".to_string());

    // Create a new state with some payload
    let payload = json!({ "name": "John", "age": 30 });
    let state = State::new(payload);
    let state_id = state.get_id().clone();

    // Save the state to memory and file system
    manager.save(state.clone())?;
    println!("Saved state with ID: {}", state_id);

    // Load the manager from the directory to verify saved state
    let loaded_manager = StateManager::load_from_dir("states")?;
    println!("Loaded states: {:?}", loaded_manager.states.keys());

    // Load the specific state using the public load method
    match manager.load(&state_id) {
        Ok(Some(loaded_state)) => {
            println!("Loaded state: {:?}", loaded_state);
        }
        Ok(None) => {
            println!("State with ID {} not found.", state_id);
        }
        Err(e) => {
            println!("Error loading state: {}", e);
        }
    }

    // Delete the state from memory and file system
    manager.delete(&state_id)?;
    println!("Deleted state with ID: {}", state_id);

    // Try loading the deleted state to verify deletion
    match manager.load(&state_id) {
        Ok(Some(loaded_state)) => {
            println!("State still exists: {:?}", loaded_state);
        }
        Ok(None) => {
            println!("State with ID {} has been deleted.", state_id);
        }
        Err(e) => {
            println!("Error loading state: {}", e);
        }
    }

    // Clear all states from a directory
    StateManager::clear_dir("states")?;
    println!("Cleared all states from directory");

    Ok(())
}

API Reference

State

A structure representing a single state item with a unique ID and JSON payload.

// Create a new state with a JSON payload
let state = State::new(json!({ "key": "value" }));

// Get the state's unique ID
let id = state.get_id();

// Get the state's payload
let payload = state.get_payload();

StateManager

Manages multiple states, providing operations for saving, loading, and deleting states.

// Create a new StateManager with a storage directory
let mut manager = StateManager::new("states".to_string());

// Load an existing StateManager from a directory
let manager = StateManager::load_from_dir("states")?;

// Save a state (to memory and filesystem)
manager.save(state)?;

// Load a state by ID
let loaded_state = manager.load(&state_id)?;

// Delete a state by ID
manager.delete(&state_id)?;

// Clear all states from a directory
StateManager::clear_dir("states")?;

Error Handling

The module uses Rust's standard std::io::Result for error handling, making it straightforward to integrate with existing error handling approaches.

Best Practices

  • Use meaningful JSON payloads that reflect your application's state
  • Handle filesystem errors appropriately
  • Create a new StateManager instance for each logical group of states
  • Use separate directories for different components to prevent state collisions
  • Clear state directories when needed to ensure a clean environment
  • Consider implementing serialization for your custom types to store them in states

Testing

The library includes comprehensive tests that demonstrate proper usage and validate functionality:

// Run the tests
cargo test

Test isolation is achieved by using unique directories for each test case, preventing cross-test interference.

License

This project is licensed under the MIT License - see the LICENSE file for details.

Dependencies

~0.8–1.7MB
~36K SLoC