lnmp-core 0.5.4

Core type definitions for LNMP (LLM Native Minimal Protocol)
Documentation
# lnmp-core

Core type definitions for LNMP (LLM Native Minimal Protocol) v0.4.

## Overview

This crate provides the fundamental data structures for representing LNMP data:

- `FieldId` - Type alias for field identifiers (u16, range 0-65535)
- `LnmpValue` - Enum representing all supported value types (including nested structures in v0.3)
- `LnmpField` - A field ID and value pair
- `LnmpRecord` - A collection of fields representing a complete record
- `SemanticChecksum` - SC32 checksum computation for semantic fidelity (v0.3)
- `TypeHint` - Type annotations for explicit typing (including nested types in v0.3)

## Usage

Add to your `Cargo.toml`:

```toml
[dependencies]
lnmp-core = { path = "path/to/lnmp-core" }
```

## Example

```rust
use lnmp_core::{LnmpField, LnmpRecord, LnmpValue};

// Create a new record
let mut record = LnmpRecord::new();

// Add fields with different value types
record.add_field(LnmpField {
    fid: 12,
    value: LnmpValue::Int(14532),
});

record.add_field(LnmpField {
    fid: 7,
    value: LnmpValue::Bool(true),
});

record.add_field(LnmpField {
    fid: 20,
    value: LnmpValue::String("Halil".to_string()),
});

record.add_field(LnmpField {
    fid: 23,
    value: LnmpValue::StringArray(vec![
        "admin".to_string(),
        "dev".to_string(),
    ]),
});

// Access fields
if let Some(field) = record.get_field(12) {
    println!("User ID: {:?}", field.value);
}

// Iterate over all fields
for field in record.fields() {
    println!("F{} = {:?}", field.fid, field.value);
}

// Get field count
println!("Total fields: {}", record.fields().len());
```

## Types

### LnmpValue

Represents all supported value types in LNMP v0.3:

```rust
pub enum LnmpValue {
    Int(i64),                      // Integer values
    Float(f64),                    // Floating-point values
    Bool(bool),                    // Boolean values (true/false)
    String(String),                // String values
    StringArray(Vec<String>),      // Arrays of strings
    NestedRecord(Box<LnmpRecord>), // Nested records (v0.3)
    NestedArray(Vec<LnmpRecord>),  // Arrays of records (v0.3)
}
```

**v0.3 Nested Structure Support:**

```rust
use lnmp_core::{LnmpField, LnmpRecord, LnmpValue};

// Create a nested record
let mut inner_record = LnmpRecord::new();
inner_record.add_field(LnmpField {
    fid: 10,
    value: LnmpValue::String("nested".to_string()),
});

let mut outer_record = LnmpRecord::new();
outer_record.add_field(LnmpField {
    fid: 50,
    value: LnmpValue::NestedRecord(Box::new(inner_record)),
});

// Create a nested array
let mut record1 = LnmpRecord::new();
record1.add_field(LnmpField { fid: 1, value: LnmpValue::Int(1) });

let mut record2 = LnmpRecord::new();
record2.add_field(LnmpField { fid: 1, value: LnmpValue::Int(2) });

let mut parent = LnmpRecord::new();
parent.add_field(LnmpField {
    fid: 60,
    value: LnmpValue::NestedArray(vec![record1, record2]),
});
```

### LnmpField

A single field assignment consisting of a field ID and value:

```rust
pub struct LnmpField {
    pub fid: FieldId,      // Field identifier (0-65535)
    pub value: LnmpValue,  // Field value
}
```

### LnmpRecord

A collection of fields representing a complete LNMP record:

```rust
impl LnmpRecord {
    pub fn new() -> Self;
    pub fn add_field(&mut self, field: LnmpField);
    pub fn get_field(&self, fid: FieldId) -> Option<&LnmpField>;
    pub fn fields(&self) -> &[LnmpField];
    pub fn into_fields(self) -> Vec<LnmpField>;
}
```

### TypeHint

Type annotations for explicit typing (v0.2+):

```rust
pub enum TypeHint {
    Int,          // :i
    Float,        // :f
    Bool,         // :b
    String,       // :s
    StringArray,  // :sa
    Record,       // :r  (v0.3)
    RecordArray,  // :ra (v0.3)
}
```

### SemanticChecksum (v0.3)

Compute and validate semantic checksums (SC32) for drift prevention:

```rust
use lnmp_core::{SemanticChecksum, TypeHint, LnmpValue};

// Compute checksum
let checksum = SemanticChecksum::compute(
    12,  // field ID
    TypeHint::Int,
    &LnmpValue::Int(14532)
);

// Validate checksum
let is_valid = SemanticChecksum::validate(
    12,
    TypeHint::Int,
    &LnmpValue::Int(14532),
    checksum
);

// Format as hex string
let hex = SemanticChecksum::format(checksum);  // "36AAE667"
```

## v0.3 Features

### Nested Structures

Support for hierarchical data modeling:

- **Nested Records**: `F50={F12=1;F7=1}` - Records within records
- **Nested Arrays**: `F60=[{F1=1},{F1=2}]` - Arrays of records
- **Arbitrary Depth**: Limited only by available memory
- **Structural Validation**: `value.validate_structure()` ensures integrity

### Semantic Checksums (SC32)

32-bit checksums for preventing LLM input drift:

- **Deterministic**: Same value always produces same checksum
- **Semantic**: Based on FID + type hint + normalized value
- **Optional**: Can be enabled/disabled via configuration
- **Fast**: CRC32-based algorithm (<1μs per field)

### Value Normalization

Canonical transformations for semantic equivalence:

- **Booleans**: `true/false/yes/no/1/0``1` or `0`
- **Floats**: `-0.0``0.0`, `3.140``3.14`
- **Strings**: Configurable case normalization

## Features

- **Zero dependencies** - Pure Rust implementation (except CRC32 for checksums)
- **Type safety** - Strong typing for all value types
- **Efficient storage** - Fields stored in a Vec for cache-friendly access
- **Flexible access** - Get fields by ID or iterate over all fields
- **Nested structures** - Support for hierarchical data in text format (v0.3)
- **Semantic checksums** - Drift prevention with SC32 (v0.3)
- **Binary format support** - Compatible with v0.4 binary protocol (via lnmp-codec)

## Binary Format Support (v0.4)

The core types are fully compatible with the v0.4 binary protocol format:

- All primitive types (Int, Float, Bool, String, StringArray) can be encoded to binary
- Binary encoding provides 30-50% size reduction compared to text format
- Round-trip conversion (text ↔ binary) maintains data integrity
- **Note**: Nested structures (NestedRecord, NestedArray) are not yet supported in v0.4 binary format
  - Nested structures remain fully supported in text format
  - Binary support for nested structures is planned for v0.5

For binary encoding/decoding, use the `lnmp-codec` crate:

```rust
use lnmp_codec::binary::{BinaryEncoder, BinaryDecoder};
use lnmp_core::{LnmpRecord, LnmpField, LnmpValue};

let mut record = LnmpRecord::new();
record.add_field(LnmpField {
    fid: 12,
    value: LnmpValue::Int(14532),
});

// Encode to binary
let encoder = BinaryEncoder::new();
let binary = encoder.encode(&record).unwrap();

// Decode from binary
let decoder = BinaryDecoder::new();
let decoded_record = decoder.decode(&binary).unwrap();
```

## Migration from v0.2

v0.3 is backward compatible with v0.2. New features:

- `LnmpValue::NestedRecord` and `LnmpValue::NestedArray` variants
- `TypeHint::Record` and `TypeHint::RecordArray` variants
- `SemanticChecksum` module for checksum computation
- `depth()` and `validate_structure()` methods on `LnmpValue`

v0.4 adds binary protocol support (via lnmp-codec) with no changes to core types.

Existing v0.2 code continues to work without changes.

## License

MIT OR Apache-2.0