Skip to content

fungal-lang/desert

Repository files navigation

Desert

CI codecov

Desert (DEserialize SERialize Traits) is a lightweight and extendable serialization and deserialization framework for Rust, inspired by serde. It aims to provide a modular and type-safe way to serialize and deserialize data structures without relying on runtime reflection, making it ideal for use in projects with strong type systems like Fungal.

Why Not serde?

While serde is a mature and highly efficient serialization framework in Rust, there are a few reasons why we chose to create desert as a simpler, custom alternative:

  1. Alignment with Fungal's Future Goals: desert is designed with Fungal's type system and language philosophy in mind. The goal is to eventually self-host Fungal's compiler, which means all supporting libraries and tools, including serialization, should be built natively in Fungal itself. By creating a stripped-down version now, we can more easily port desert to Fungal in the future.

  2. Minimalism and Extendability: desert starts with a minimal core that focuses only on the functionality currently needed. Unlike serde, which supports a wide variety of formats and complex features, desert provides a lightweight and straightforward base that can be extended incrementally as the project evolves. This makes it easier to understand, maintain, and adapt to Fungal's unique requirements.

  3. Control and Customization: By implementing our own serialization framework, we maintain full control over its design and behavior. This allows us to add domain-specific optimizations or features tailored to Fungal's needs without being constrained by the design decisions or complexity of a third-party library.

  4. Procedural Macros and Future Integration: While serde uses procedural macros for deriving traits like Serialize and Deserialize, desert takes a similar but simplified approach. This allows us to experiment with different ways of implementing serialization in Rust and prepare for deeper integration into Fungal's compilation and macro system.

  5. Zero External Serialization Dependencies: desert has zero dependencies on external serialization libraries (serde, toml, etc.), ensuring complete independence. The only external dependency is the im crate for immutable collections, which aligns with Fungal's immutable-first philosophy. All serialization logic is custom-built and self-contained.

Features

  • Binary Serialization: Efficient binary format with magic bytes, version headers, and varint encoding
    • 35 type implementations: primitives, collections, tuples (2-12 elements), smart pointers
    • Cross-platform safe (usize/isize handled correctly)
    • Security features: collection size limits, UTF-8 validation
    • Returns im::Vector<u8> for immutability (Fungal-aligned)
  • TOML Support: Human-readable configuration format
    • NEW: Complete TOML deserialization (parsing)
    • TOML serialization (writing)
    • Ready for Cap package manager integration
  • Trait-based Serialization and Deserialization: Define Serialize and Deserialize traits that can be implemented for various types
  • Procedural Macros for Auto-Derivation: Automatically derive serialization and deserialization implementations using procedural macros
  • Extensible Serialization Formats: JSON, TOML, and binary formats with the ability to add more as needed
  • Pure Core + Imperative Shell: Efficient internal mutation with immutable external interface
  • Portable to Fungal: No proc macros, unsafe code, or complex lifetimes in core implementation

Getting Started

Installation

Add desert to your Cargo.toml:

[dependencies]
desert = { git = "https://github.com/fungal-lang/desert" }
desert_macros = { git = "https://github.com/fungal-lang/desert", package = "desert_macros" }

Usage

Binary Serialization

use desert::binary::{serialize_binary, deserialize_binary};

// Serialize a value
let value = vec![1, 2, 3, 4, 5];
let bytes = serialize_binary(&value)?;

// Deserialize it back
let decoded: Vec<i32> = deserialize_binary(&bytes.iter().copied().collect::<Vec<_>>())?;
assert_eq!(value, decoded);

JSON Serialization

use desert::{Serialize, JsonSerializer};
use std::sync::Arc;

#[derive(Serialize)]
struct MyStruct {
    name: String,
    age: i32,
}

fn main() {
    let my_struct = MyStruct {
        name: "Alice".to_string(),
        age: 30,
    };

    let serializer = Arc::new(JsonSerializer::new());
    let serialized = my_struct.serialize(&serializer);

    println!("Serialized JSON: {}", serialized);
}

TOML Deserialization (NEW!) - No Serde Required!

use desert::parse_toml;

fn main() {
    let toml_str = r#"
        [package]
        name = "my-project"
        version = "0.1.0"
    "#;

    // Parse TOML without needing serde derives!
    let value = parse_toml(toml_str).unwrap();
    let package = value.get_required("package").unwrap();

    let name = package.get_string("name").unwrap();
    let version = package.get_string("version").unwrap();

    println!("Project: {} v{}", name, version);
}

For more examples, see examples/binary_serialization_examples.rs and the Binary Serialization Guide.

Contributing

We welcome contributions! Please check out How to Contribute for more details on how to get started.

About

No description, website, or topics provided.

Resources

License

Contributing

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages