Skip to content

Remove YAML support, use JSON (state) and TOML (configs) #10

@lucas-labs

Description

@lucas-labs

Overview

Remove support for YAML configuration files and state persistence. Migrate to JSON and TOML formats for better performance, smaller dependencies, and clearer semantics.

Current State

Config Files (eggs):

  • Accepts YAML
  • Loaded via: src/kurv/egg/load.rs using serde_saphyr::from_reader()
  • Example: fastapi.kurv, s2t.egg

State File (.kurv):

  • Current format: JSON (primary), YAML (backward compatibility)
  • Location: <KURV_HOME>/.kurv
  • Loading logic: src/kurv/state/mod.rs:load()
  • Currently tries JSON first, falls back to YAML:
let mut state: KurvState = match serde_json::from_reader(&rdr) {
    Ok(state) => {
        debug!("loaded state from JSON format");
        state
    }
    Err(json_err) => {
        debug!("failed to parse as JSON, trying YAML format: {}", json_err);
        // Falls back to YAML...
    }
};

Dependencies (from Cargo.toml):

serde-saphyr = "0.0.7"  # YAML - TO REMOVE
serde_json = "1.0.145"  # Keep
# Need to add: toml crate for egg configs

Problems with YAML

  1. Performance: YAML parsing is slower than JSON/TOML
  2. Binary Size: serde-saphyr adds ~50KB to the release binary
  3. Ambiguity: YAML has complex parsing rules (e.g., name: yes vs name: "yes")
  4. Maintenance: Extra dependency to maintain
  5. Complexity: Unnecessary for simple key-value configs

Proposed Migration

1. State File (.kurv)

Keep JSON - Already the primary format, well-suited for programmatic state:

  • Fast serialization/deserialization
  • Compact format
  • Already implemented

Remove YAML fallback:

// src/kurv/state/mod.rs
pub fn load(path: PathBuf) -> Result<KurvState> {
    if !path.exists() {
        return Ok(KurvState { eggs: BTreeMap::new() });
    }

    let rdr = File::open(&path)
        .with_context(|| format!("failed to open state file: {}", path.display()))?;

    let state: KurvState = serde_json::from_reader(&rdr)
        .with_context(|| format!("failed to parse state file as JSON: {}", path.display()))?;
    
    // ... rest of logic
}

2. Egg Config Files

Switch from YAML to TOML with JSON fallback - Better for human-edited configuration:

  • Clear syntax, no ambiguity
  • Widely used in Rust ecosystem (Cargo.toml)
  • Smaller dependency footprint
  • Type-safe parsing
  • JSON fallback, because why not? It's already installed and easy to implement.

Example transformation:

Before (fastapi.egg - YAML):

name: fastapi
command: poetry
args:
  - run
  - serve
cwd: /home/user/my-fastapi-app
env:
  FASTAPI_PORT: 8080

After (fastapi.kurv - TOML):

name = "fastapi"
command = "poetry"
args = ["run", "serve"]
cwd = "/home/user/my-fastapi-app"

[env]
FASTAPI_PORT = "8080"

Loading logic (src/kurv/egg/load.rs):

use {
    super::Egg,
    anyhow::{Context, Result, anyhow},
    log::debug,
    serde::Deserialize,
    std::{fs::File, path::PathBuf},
};

impl Egg {
    pub fn load(path: PathBuf) -> Result<Egg> {
        if !path.exists() {
            return Err(anyhow!(format!("file {} not found", path.display())));
        }

        let content = std::fs::read_to_string(&path)
            .with_context(|| format!("failed to read egg file: {}", path.display()))?;

        let mut egg: Egg = toml::from_str(&content)
            .context(format!("failed to parse egg file as TOML: {}", path.display()))?;

        egg.id = None; // Server assigns ID
        Ok(egg)
    }
}

Implementation Checklist

1: Update Dependencies

  • Add toml to Cargo.toml
  • Remove serde-saphyr from Cargo.toml

2: Update State Loading

  • Remove YAML fallback in src/kurv/state/mod.rs:load()
  • Keep JSON-only state persistence

3: Update Egg Loading

  • Rewrite src/kurv/egg/load.rs to use TOML
  • Update error messages to reference TOML
  • Test with various egg configs

4: Documentation & Examples

  • Update README.md with TOML examples
  • Convert example files (fastapi.kurv, s2t.egg) to TOML
  • Add migration guide to release notes

5: Testing

  • Test loading eggs from TOML configs
  • Test state persistence (JSON)
  • Verify binary size reduction
  • Test error handling for invalid TOML

Keep tests in dedicated /test, avoid same-file tests as is common in rust.

Breaking Changes

⚠️ Users will need to convert their *.egg files to TOML format.

Since user is probably just me.... no problem LOL.

Migration is simple - structure remains the same, just syntax changes:

  • key: valuekey = "value"
  • Lists: - item["item"]
  • Nested objects: use [section] headers

References

  • Current egg loading: src/kurv/egg/load.rs
  • Current state loading: src/kurv/state/mod.rs:load()
  • TOML crate: https://crates.io/crates/toml
  • Example configs: fastapi.kurv, s2t.egg

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions