hedl 1.2.0

HEDL - Hierarchical Entity Data Language
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
# hedl

**The unified HEDL API—parse, validate, convert, and canonicalize with a single, ergonomic interface.**

Production systems need simple APIs. Importing a dozen crates for basic operations creates cognitive overhead. Feature flags should work intuitively. Errors need rich context without boilerplate. The most common operations should be frictionless.

`hedl` is the facade crate providing the complete HEDL experience through 7 core functions and comprehensive error handling utilities. Zero default dependencies—only pay for features you enable. Full re-exports from 13 specialized crates beneath a unified API. Designed for developers who want results, not dependency management.

## What's Implemented

Unified API with zero-overhead ergonomics:

1. **7 Core Functions**: parse, parse_lenient, canonicalize, to_json, from_json, lint, validate
2. **8 Feature Flags**: serde, yaml, xml, csv, parquet, neo4j, toon, all-formats
3. **Zero Default Dependencies**: Core parsing only—enable formats as needed
4. **Error Context Extensions**: HedlResultExt trait with .context() and .with_context()
5. **Full Re-Exports**: 13 internal crates exposed through unified namespace
6. **Type Aliases**: Convenient Result<T> = std::result::Result<T, HedlError>
7. **130+ Error Extension Tests**: Comprehensive validation of context propagation
8. **Minimal Overhead**: < 1% compared to using crates directly
9. **Feature Composition**: Mix and match formats without conflicts
10. **Ergonomic Imports**: use hedl::*; gives you everything you need

## Installation

### Minimal (Core Only)

Parse, validate, and work with HEDL documents:

```toml
[dependencies]
hedl = "1.2"
```

**What you get**: Parsing, canonicalization, linting, validation
**What you don't get**: Format conversion (JSON/YAML/XML/etc.)

### With Specific Formats

Enable only the formats you need:

```toml
[dependencies]
hedl = { version = "1.2", features = ["yaml", "xml"] }
```

### All Features

Get everything (recommended for applications):

```toml
[dependencies]
hedl = { version = "1.2", features = ["all-formats"] }
```

**Includes**: JSON, YAML, XML, CSV, Parquet, Neo4j, TOON, Serde

## Core API

### parse(bytes: &[u8]) -> Result<Document>

Parse HEDL document with strict validation:

```rust
use hedl::parse;

let hedl = br#"
%VERSION: 1.0
%STRUCT: User: [id, name, age]
---
users: @User
  | alice, Alice Smith, 30
  | bob, Bob Jones, 25
"#;

let doc = parse(hedl)?;
println!("Version: {}.{}", doc.version.0, doc.version.1);
println!("Users: {}", doc.entities["User"].len());
```

**Behavior**:
- Strict parsing (all errors fatal)
- Schema validation
- Reference checking
- UTF-8 validation

**Use When**: Production parsing, CI/CD validation, strict correctness required

### parse_lenient(bytes: &[u8]) -> Result<Document>

Parse with relaxed validation:

```rust
let doc = parse_lenient(hedl_bytes)?;
// Tolerates some malformations:
// - Missing schemas (inferred from data)
// - Unresolved references (preserved as strings)
// - Inconsistent indentation (best-effort parse)
```

**Use When**: Parsing user-generated content, migration from other formats, exploratory analysis

### validate(bytes: &[u8]) -> Result<()>

Validate document without constructing AST:

```rust
use hedl::validate;

if validate(hedl_bytes).is_ok() {
    println!("Valid HEDL document");
}
```

**Performance**: Faster than `parse()` when you only need validation (no AST construction)

**Use Cases**: CI/CD checks, pre-commit hooks, batch validation

### canonicalize(doc: &Document) -> Result<String>

Convert to canonical form with ditto optimization:

```rust
use hedl::{parse, canonicalize};

let doc = parse(hedl_bytes)?;
let canonical = canonicalize(&doc)?;
// Same document always produces identical output
// Perfect for version control and content-addressable storage
```

**Output Characteristics**:
- Deterministic formatting (2-space indentation)
- Ditto operator for repeated values
- Count hints on matrix lists
- Normalized floats (no trailing zeros)
- Sorted keys (optional)

**Use When**: Git commits, content hashing, cache keys, comparing documents

### lint(doc: &Document) -> Vec<Diagnostic>

Run lint checks for best practices:

```rust
use hedl::{parse, lint};

let doc = parse(hedl_bytes)?;
let diagnostics = lint(&doc);

for diag in diagnostics {
    println!("[{}] Line {}: {}",
        diag.severity, diag.line, diag.message);
}
```

**Rules Checked** (default):
- id-naming: ID naming conventions
- unused-schema: Unused %STRUCT definitions
- empty-list: Empty matrix lists
- unqualified-kv-ref: Unqualified references in key-value context

**Use When**: Code review automation, CI/CD quality gates, pre-commit hooks

### to_json(doc: &Document) -> Result<String>

Convert to JSON (requires "json" feature, enabled by default):

```rust
use hedl::{parse, to_json};

let doc = parse(hedl_bytes)?;
let json = to_json(&doc)?;
// Use with existing JSON APIs
```

**Configuration**: Use `hedl_json::to_json_with_config()` for custom options (pretty-printing, type preservation)

### from_json(json: &str) -> Result<Document>

Convert from JSON to HEDL:

```rust
use hedl::from_json;

let json = r#"{"users": [{"id": "alice", "name": "Alice"}]}"#;
let doc = from_json(json)?;
// Now use HEDL's structured API
```

**Type Inference**: Automatically detects arrays-of-objects → matrix lists

## Error Handling with Context

### The Problem

Standard Rust errors lose context during propagation:

```rust
fn load_config() -> Result<Config> {
    let data = std::fs::read("config.hedl")?;
    let doc = parse(&data)?;
    // Error: "Parse error at line 42: unexpected token"
    // Missing: WHICH file? WHAT operation?
}
```

### The Solution: HedlResultExt

Add context at error boundaries:

```rust
use hedl::{parse, HedlResultExt};

fn load_config(path: &str) -> Result<Config> {
    let data = std::fs::read(path)
        .context("Failed to read config file")?;

    let doc = parse(&data)
        .with_context(|| format!("Failed to parse config: {}", path))?;

    Ok(/* ... */)
}
```

**Output**:
```
Failed to parse config: config.hedl
  caused by: Parse error at line 42: unexpected token ':'
```

### HedlResultExt Methods

#### .context(msg: &str)

Add static context:

```rust
parse(data).context("Failed to parse HEDL document")?;
```

#### .with_context<F: FnOnce() -> String>(f: F)

Add computed context (lazily evaluated):

```rust
parse(data)
    .with_context(|| format!("Failed to parse file: {}", filename))?;
```

**Benefits**:
- Lazy: Closure only evaluated on error (zero cost on success path)
- Flexible: Capture variables, format strings, complex logic

#### .map_err_to_hedl()

Convert external errors to HedlError:

```rust
std::fs::read("file.hedl")
    .map_err_to_hedl()
    .context("Failed to read input")?;
```

**Use Cases**:
- Wrapping std::io::Error
- Converting serde errors
- Unifying error types

## Feature Flags

### serde

Enable Serde serialization for Document type:

```toml
hedl = { version = "1.2", features = ["serde"] }
```

**Provides**: Serialize/Deserialize impls for Document, Value, Reference

**Use Cases**: Storing parsed documents in databases, IPC, caching

### yaml

Enable YAML format conversion:

```toml
hedl = { version = "1.2", features = ["yaml"] }
```

**Adds**:
- `hedl::to_yaml(doc) -> Result<String>`
- `hedl::from_yaml(yaml) -> Result<Document>`

**Dependencies**: serde_yaml 0.9

### xml

Enable XML format conversion:

```toml
hedl = { version = "1.2", features = ["xml"] }
```

**Adds**:
- `hedl::to_xml(doc) -> Result<String>`
- `hedl::from_xml(xml) -> Result<Document>`

**Dependencies**: quick-xml 0.31

### csv

Enable CSV format conversion:

```toml
hedl = { version = "1.2", features = ["csv"] }
```

**Adds**:
- `hedl::to_csv(doc) -> Result<String>` (exports first entity list)
- `hedl::from_csv(csv, type_name) -> Result<Document>`

**Dependencies**: csv 1.3

### parquet

Enable Apache Parquet columnar format:

```toml
hedl = { version = "1.2", features = ["parquet"] }
```

**Adds**:
- `hedl::to_parquet(doc, writer) -> Result<()>`
- `hedl::from_parquet(reader) -> Result<Document>`

**Dependencies**: arrow 57.0, parquet 57.0

### neo4j

Enable Neo4j Cypher generation:

```toml
hedl = { version = "1.2", features = ["neo4j"] }
```

**Adds**:
- `hedl::to_cypher(doc) -> Result<String>`
- Cypher CREATE/MERGE statements for Neo4j import

**Dependencies**: None (pure Cypher generation)

### toon

Enable TOON format (token-optimized for LLMs):

```toml
hedl = { version = "1.2", features = ["toon"] }
```

**Adds**:
- `hedl::to_toon(doc) -> Result<String>`
- `hedl::from_toon(toon) -> Result<Document>`

**Use Case**: Maximum token efficiency for LLM contexts

### all-formats

Enable all format converters:

```toml
hedl = { version = "1.2", features = ["all-formats"] }
```

**Equivalent to**: `["serde", "yaml", "xml", "csv", "parquet", "neo4j", "toon"]`

**Recommended for**: Applications (not libraries)

## Re-Exported Modules

Full access to specialized crates through unified namespace:

```rust
use hedl::{
    // Core types
    Document, Value, Reference, HedlError,

    // Sub-modules (explicit opt-in)
    core,      // hedl-core (parsing, AST)
    c14n,      // hedl-c14n (canonicalization)
    json,      // hedl-json (always available)
    lint,      // hedl-lint (linting)

    // Feature-gated modules
    yaml,      // hedl-yaml (requires "yaml")
    xml,       // hedl-xml (requires "xml")
    csv,       // hedl-csv (requires "csv")
    parquet,   // hedl-parquet (requires "parquet")
    neo4j,     // hedl-neo4j (requires "neo4j")
    toon,      // hedl-toon (requires "toon")
};
```

**Use When**: Need advanced configuration beyond core API (e.g., `hedl::json::JsonConfig` for custom JSON options)

## Common Patterns

### Parse and Convert

```rust
use hedl::{parse, to_json};

let doc = parse(hedl_bytes)?;
let json = to_json(&doc)?;
// Send JSON to REST API
```

### Validate Before Processing

```rust
use hedl::{validate, parse};

if validate(hedl_bytes).is_err() {
    return Err("Invalid HEDL document");
}

let doc = parse(hedl_bytes)?; // Safe to unwrap
```

### Multi-Format Pipeline

```rust
use hedl::{from_json, to_yaml, to_xml};

let doc = from_json(json_str)?;
let yaml = to_yaml(&doc)?;
let xml = to_xml(&doc)?;
```

### Error Context Chaining

```rust
use hedl::{parse, HedlResultExt};

fn process_file(path: &str) -> Result<()> {
    let data = std::fs::read(path)
        .context("Failed to read input file")?;

    let doc = parse(&data)
        .with_context(|| format!("Failed to parse: {}", path))?;

    let canonical = canonicalize(&doc)
        .context("Failed to canonicalize document")?;

    std::fs::write(format!("{}.canonical", path), canonical)
        .context("Failed to write canonical output")?;

    Ok(())
}
```

## Type Aliases

Convenient Result type with HedlError:

```rust
pub type Result<T> = std::result::Result<T, HedlError>;

// Use in function signatures
fn my_function() -> Result<Document> {
    parse(input)?
}
```

## Performance Characteristics

**Zero Overhead**: Facade adds < 1% overhead vs using crates directly

**Feature Gating**: Unused features don't bloat binary (tree-shaking works)

**Compile Time**: Minimal—most work delegated to specialized crates

**Binary Size**: Core-only build ~200 KB, all-formats ~800 KB (compressed)

## Use Cases

**Application Development**: Use `features = ["all-formats"]` for maximum flexibility without managing individual crate versions.

**Library Development**: Minimize dependencies—only enable formats your library needs. Let downstream users add more formats via their own dependencies.

**CLI Tools**: Import hedl with all-formats for comprehensive format support in user-facing tools.

**Embedded Systems**: Use core-only (no features) for minimal binary size. Add formats selectively based on constraints.

**Microservices**: Enable only formats you consume/produce (e.g., JSON for REST APIs, Parquet for analytics export).

## What This Crate Doesn't Do

**Streaming Parsing**: Use `hedl-stream` directly for memory-efficient streaming of multi-GB files.

**LSP/MCP Servers**: Use `hedl-lsp` or `hedl-mcp` directly for server applications.

**C/WASM Bindings**: Use `hedl-ffi` or `hedl-wasm` directly for non-Rust integrations.

**Benchmarking**: Use `hedl-bench` directly for performance measurement and regression detection.

**Testing Utilities**: Use `hedl-test` directly for shared test fixtures and builders.

## Dependencies

### Core (Zero Features)

- `hedl-core` 1.0 - Parsing and AST
- `hedl-c14n` 1.0 - Canonicalization
- `hedl-json` 1.0 - JSON (always included)
- `hedl-lint` 1.0 - Linting
- `thiserror` 1.0 - Error types

### Optional (Feature-Gated)

- `hedl-yaml` 1.0 - YAML conversion (feature: yaml)
- `hedl-xml` 1.0 - XML conversion (feature: xml)
- `hedl-csv` 1.0 - CSV conversion (feature: csv)
- `hedl-parquet` 1.0 - Parquet conversion (feature: parquet)
- `hedl-neo4j` 1.0 - Neo4j Cypher (feature: neo4j)
- `hedl-toon` 1.0 - TOON format (feature: toon)
- `serde` 1.0 - Serialization (feature: serde)

## License

Apache-2.0