noml 0.9.0

High-performance dynamic configuration language with format preservation, environment variables, native types, string interpolation, and TOML compatibility. Blazing-fast parsing at 25ยตs with zero-copy architecture.
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
533
534
535
536
<div align="center">
    <h1>
        <span>NOML +&nbsp; RUST</span>
        <br>
        <sub><sup>HIGH-PERFORMANCE DYNAMIC CONFIGURATION</sup></sub>
    </h1>
</div>

<div align="center">
    <div>
        <a href="https://crates.io/crates/noml" alt="NOML on Crates.io"><img alt="Crates.io" src="https://img.shields.io/crates/v/noml"></a>
        <span>&nbsp;</span>
        <a href="https://crates.io/crates/noml" alt="Download NOML"><img alt="Crates.io Downloads" src="https://img.shields.io/crates/d/noml?color=%230099ff"></a>
        <span>&nbsp;</span>
        <a href="https://docs.rs/noml" title="NOML Documentation"><img alt="docs.rs" src="https://img.shields.io/docsrs/noml"></a>
        <span>&nbsp;</span>
        <a href="https://github.com/noml-lang/noml-rust/actions/workflows/ci.yml" title="CI Status"><img alt="CI" src="https://img.shields.io/github/actions/workflow/status/noml-lang/noml-rust/ci.yml?branch=main&label=CI&logo=github"></a>
        <span>&nbsp;</span>
        <img alt="MSRV" src="https://img.shields.io/badge/MSRV-1.82.0-blue?logo=rust" title="Minimum Supported Rust Version">
    </div>
</div>
<br><br>

**NOML** (Nested Object Markup Language) is a **blazing-fast dynamic configuration language** that revolutionizes how you handle configuration files. With **industry-leading format preservation**, **zero-copy architecture**, and **25ยตs parsing performance**, NOML delivers both speed and power.

Unlike static markup languages, NOML is a **markup/scripting hybrid** that combines the simplicity of TOML with dynamic capabilities that traditional config formats simply cannot match.

## ๐Ÿš€ **Performance That Matters**

- **โšก 25ยตs parsing** - Legitimately high-performance by industry standards
- **โšก 37ns reads** - Blazing-fast value access with path-based navigation  
- **โšก Zero-copy architecture** - Optimized for real-world performance
- **โšก 47% faster** - Massive optimization improvements over previous versions

## ๐ŸŽฏ **Revolutionary Features**

### **๐Ÿ”ฅ Format Preservation**
**Industry-first complete format preservation** - maintain exact whitespace, comments, indentation, and styling during parsing and round-trip editing. Perfect for configuration management tools and IDEs.

### **๐ŸŒ Dynamic Configuration**
- **Environment Variables**: `env("DATABASE_URL", "default")`  
- **String Interpolation**: `"Welcome ${user.name}!"` 
- **File Inclusion**: `include "database.noml"`
- **Native Types**: `@duration("30s")`, `@size("10MB")`, `@url("https://api.com")`

### **๐Ÿ“„ TOML Compatibility**
Parse most TOML files with **full format preservation** - get advanced features while maintaining compatibility with existing TOML configurations.

## ๐Ÿ’ช **Key Advantages**

**NOML vs Static Config Languages:**
- **146% more features** than TOML for only 2x performance cost
- **Path-based access** - `config.get("server.database.port")` vs manual navigation
- **Type system** - Native parsing of sizes, durations, URLs, IPs
- **Dynamic resolution** - Runtime environment integration  
- **Format preservation** - Perfect for editing tools and automation
## ๐Ÿš€ **Quick Start**

Add NOML to your `Cargo.toml`:

```toml
[dependencies]
noml = "0.9"
```

### **Basic Usage**

```rust
use noml::parse;

let config = parse(r#"
    app_name = "my-service"
    debug = env("DEBUG", "false")
    
    [server]
    host = "0.0.0.0" 
    port = env("PORT", "8080")
    timeout = @duration("30s")
    
    [database]
    url = "postgresql://localhost/mydb"
    max_connections = 100
    pool_timeout = @duration("5m")
"#)?;

// Fast path-based access
let app_name = config.get("app_name")?.as_string()?;
let port = config.get("server.port")?.as_integer()?;
let timeout = config.get("server.timeout")?.as_duration()?;
```

### **Format Preservation** 

```rust
use noml::{parse_preserving, modify_preserving, save_preserving};

// Parse with complete format preservation
let mut doc = parse_preserving_from_file("config.noml")?;

// Modify values while preserving formatting
doc = modify_preserving(doc, |config| {
    config.set("server.port", 9090)?;
    config.set("debug", true)?;
    Ok(())
})?;

// Save with perfect format fidelity
save_preserving(&doc, "config.noml")?;
```

### **Advanced Configuration Management**

```rust
use noml::Config;

let mut config = Config::from_file("app.noml")?;

// Merge multiple configs
config.merge_from_file("local-overrides.noml")?;

// Type-safe access with defaults
let port: u16 = config.get_or("server.port", 8080)?;
let debug: bool = config.get_or("debug", false)?;

// Dynamic updates
config.set("last_updated", chrono::Utc::now())?;
config.save_to_file("app.noml")?;
```

## ๐Ÿ“– **NOML Syntax**

### **Environment Variables & Native Types**
```noml
# Environment integration
database_url = env("DATABASE_URL", "sqlite:memory:")
api_key = env("API_KEY")  # Required - will error if missing

# Native type parsing
max_file_size = @size("100MB")     # Bytes: 104857600
cache_timeout = @duration("1h30m") # Seconds: 5400  
api_endpoint = @url("https://api.example.com/v1")
server_ip = @ip("192.168.1.100")
```

### **String Interpolation & File Includes**
```noml
app_name = "my-service"
log_file = "/var/log/${app_name}.log"

# Include other configuration files
database = include "database.noml"
secrets = include "secrets.noml" 
```

### **Advanced Nesting & Arrays**
```noml
[server.ssl]
enabled = true
cert_file = "/etc/ssl/cert.pem"
key_file = "/etc/ssl/private.key"

[[workers]]
name = "background-processor"
threads = 4
memory_limit = @size("512MB")

[[workers]]
name = "api-handler" 
threads = 8
memory_limit = @size("1GB")
## ๐Ÿ“Š **Performance Comparison**

NOML delivers **high-performance parsing** while providing **146% more features** than static alternatives:

| Parser | Parse Time | Features | Format Preservation |
|--------|------------|----------|-------------------|
| **NOML** | **25ยตs** | **32** | **โœ… Complete** |
| TOML | 16ยตs | 13 | โŒ None |
| JSON | 10ยตs | 8 | โŒ None |
| YAML | 125ยตs | 15 | โŒ None |

**Real-world usage** (parse once + 10,000 reads): **NOML is only 1.95x slower than TOML** while delivering exponentially more functionality.

## ๐Ÿ›  **Command-Line Interface**

Install and use the NOML CLI:

```bash
cargo install noml

# Validate configuration files
noml validate config.noml

# Parse and display structure  
noml parse app.noml

# Check version
noml version
```

## ๐Ÿ”ง **Features & Compatibility**

### **Cargo Features**
```toml
[dependencies]
noml = { version = "0.9", features = ["chrono", "async"] }
```

- **`chrono`** - DateTime support with timezone handling
- **`async`** - Async file operations and HTTP includes

### **TOML Compatibility**
NOML can parse **most TOML files** with full format preservation:
```rust
// Parse TOML files with NOML for advanced features
let config = noml::parse_from_file("config.toml")?;
let port = config.get("server.port")?.as_integer()?;  // Path-based access
```
*Note: ISO date formats (`1979-05-27T15:32:00-08:00`) are not supported*

## ๐ŸŽฏ **Why Choose NOML?**

**For Configuration Management:**
- **Format Preservation** - Perfect for automated configuration tools
- **Environment Integration** - Runtime environment variable resolution
- **Type Safety** - Native parsing eliminates custom conversion code
- **Path Access** - Clean dot-notation navigation

**For Performance:**
- **25ยตs parsing** - Legitimately fast by industry standards
- **37ns reads** - Blazing-fast value access
- **Zero-copy architecture** - Optimized for real-world usage
- **Production ready** - 124 comprehensive tests

**For Developer Experience:**
- **Rich error messages** - Precise source locations and helpful context
- **Complete API** - Covers all real-world configuration use cases  
- **TOML compatibility** - Drop-in replacement for many TOML files
- **Async support** - Modern Rust patterns with tokio integration

## Examples

Here are some examples of how to use the `noml` library in your Rust code.

### **Basic Parsing**

You can easily parse a NOML string and access its values.

```rust
## ๐Ÿ“š **Documentation & Resources**

- **[API Documentation]https://docs.rs/noml** - Complete API reference with examples
- **[NOML Language Specification]https://github.com/noml-lang/spec** - Official language specification
- **[Examples]examples/** - Real-world usage examples and benchmarks
- **[GitHub Repository]https://github.com/noml-lang/noml-rust** - Source code and issue tracking

## ๐Ÿค **Contributing**

We welcome contributions! Please see our [Contributing Guidelines](CONTRIBUTING.md) for details.

## ๐Ÿ“„ **License**

Licensed under the Apache License, Version 2.0. See [LICENSE](LICENSE) for details.

---

<div align="center">
    <strong>NOML 0.9.0 - High-Performance Dynamic Configuration</strong><br>
    <em>Blazing-fast โ€ข Feature-rich โ€ข Format-preserving</em>
</div>

<br>

### **HTTP Includes (Async Feature)**

With the `async` feature enabled, you can include configuration from remote HTTP/HTTPS URLs:

```rust
use noml::parse_from_file_async;

// config.noml content:
// base_config = include "https://config.example.com/app-defaults.noml"
// api_key = env("API_KEY")
// debug = true

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let config = parse_from_file_async("config.noml").await?;
    
    // The remote config is automatically fetched and merged
    println!("Loaded config with remote includes: {:?}", config);
    Ok(())
}
```

**HTTP Includes Features:**
- โœ… **Secure HTTPS Support**: Full support for HTTPS URLs with proper certificate validation
- โšก **Automatic Caching**: Remote configs are cached to improve performance and reduce network requests
- ๐Ÿ”’ **Timeout Protection**: Configurable request timeouts prevent hanging operations
- ๐Ÿ”„ **Error Handling**: Clear error messages for network issues, HTTP errors, and parse failures
- ๐Ÿ“ฆ **No Nested HTTP**: HTTP includes cannot contain other HTTP includes (prevents security issues)

```toml
[dependencies]
noml = { version = "0.9.0", features = ["async"] }
tokio = { version = "1.0", features = ["full"] }
```

-----

<br>

### **Working with Native Types**

`noml` supports special native types for common configuration values like file sizes, durations, IP addresses, and more.

```rust
use noml::parse;

let source = r#"
    # File sizes and durations
    max_upload_size = @size("256MB")
    request_timeout = @duration("90s")
    
    # Network and web
    website = @url("https://example.com")
    server_ip = @ip("192.168.1.100")
    
    # Data formats
    app_version = @semver("2.1.0")
    secret_data = @base64("SGVsbG8gV29ybGQ=")
    user_id = @uuid("550e8400-e29b-41d4-a716-446655440000")
"#;

let config = parse(source)?;

// The values are parsed and validated
assert_eq!(config.get("max_upload_size").unwrap().as_integer()?, 256 * 1024 * 1024);
assert_eq!(config.get("request_timeout").unwrap().as_float()?, 90.0);
assert_eq!(config.get("website").unwrap().as_string()?, "https://example.com");
assert_eq!(config.get("server_ip").unwrap().as_string()?, "192.168.1.100");
assert_eq!(config.get("app_version").unwrap().as_string()?, "2.1.0");
```

**Available Native Types:**
- `@size("10MB")` - File/memory sizes (KB, MB, GB, etc.)
- `@duration("30s")` - Time durations (s, m, h, d)
- `@url("https://...")` - URL validation
- `@ip("192.168.1.1")` - IP address validation (IPv4/IPv6)
- `@semver("1.2.3")` - Semantic version parsing
- `@base64("SGVsbG8=")` - Base64 encoded data
- `@uuid("550e8400-...")` - UUID format validation

-----

<br>

### **Working with Arrays and Tables**

`noml` fully supports arrays, inline tables, and arrays of tables, similar to TOML.

```rust
use noml::parse;

let source = r#"
    # An array of strings
    allowed_roles = ["admin", "editor", "viewer"]

    # An inline table
    point = { x = 1.0, y = -1.0 }

    # An array of tables
    [[users]]
    name = "Alice"
    email = "alice@example.com"

    [[users]]
    name = "Bob"
    email = "bob@example.com"
"#;

let config = parse(source)?;

// Access array elements
let roles = config.get("allowed_roles").unwrap().as_array()?;
assert_eq!(roles.len(), 3);
assert_eq!(roles[0].as_string()?, "admin");

// Access inline table values
assert_eq!(config.get("point.x").unwrap().as_float()?, 1.0);

// Access values from an array of tables
let users = config.get("users").unwrap().as_array()?;
assert_eq!(users[0].get("name").unwrap().as_string()?, "Alice");
assert_eq!(users[1].get("name").unwrap().as_string()?, "Bob");
```

-----

<br>

### **High-Level Configuration Management**

For more advanced use cases, the `Config` struct provides a high-level API for loading, modifying, and saving configurations.

```rust
use noml::Config;
use std::fs;

// Create a temporary file for the example
let temp_dir = tempfile::tempdir()?;
let file_path = temp_dir.path().join("config.noml");
fs::write(&file_path, "version = \"1.0.0\"")?;

// Load the configuration from a file
let mut config = Config::from_file(&file_path)?;
assert_eq!(config.get("version").unwrap().as_string()?, "1.0.0");

// Modify the configuration
config.set("debug", true)?;
config.set("database.port", 5432)?;

// Save the changes back to the file
config.save()?;

// Verify the changes
let updated_config = Config::from_file(&file_path)?;
assert_eq!(updated_config.get("debug").unwrap().as_bool()?, true);
assert_eq!(updated_config.get("database.port").unwrap().as_integer()?, 5432);
```

-----

<br>

### **Async Support** ๐Ÿš€

`noml` supports async operations for modern Rust applications! Enable the `async` feature:

```toml
[dependencies]
noml = { version = "0.9.0", features = ["async"] }
tokio = { version = "1.0", features = ["full"] }
```

All parsing and file operations are available in async variants:

```rust
use noml::{parse_async, Config};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Parse configurations asynchronously
    let config = parse_async(r#"
        app_name = "AsyncApp"
        port = env("PORT", "8080")
        
        [database]
        url = env("DATABASE_URL", "sqlite:memory:")
    "#).await?;
    
    println!("App: {}", config.get("app_name")?.as_string()?);

    // Load, modify, and save configurations asynchronously
    let mut config = Config::load_async("config.noml").await?;
    config.set("last_started", "2025-09-19T12:00:00Z")?;
    config.save_async("config.noml").await?;
    
    // Reload to get latest changes
    config.reload_async().await?;
    
    Ok(())
}
```

**Thread Safety**: All NOML types (`Value`, `Config`) are `Send + Sync`, making them safe to share between async tasks and threads. Perfect for concurrent applications and microservices!

**Performance**: Async operations are non-blocking and integrate seamlessly with `tokio`, `async-std`, and other async runtimes.

Run the async demo: `cargo run --example async_demo --features async`

-----

<br>

### **Schema Validation** โœ…

`noml` includes built-in schema validation to catch configuration errors early:

```rust
use noml::{Config, Schema, FieldType, SchemaBuilder};

// Load your configuration
let config = Config::from_string(r#"
    app_name = "MyApp"
    port = 8080
    debug = true
    
    [database]
    host = "localhost"
    max_connections = 100
"#)?;

// Define expected schema
let schema = SchemaBuilder::new()
    .require_string("app_name")
    .require_integer("port")
    .optional_bool("debug")
    .build();

// Validate configuration against schema
config.validate_schema(&schema)?;

// Or create more complex schemas
let db_schema = Schema::new()
    .required_field("host", FieldType::String)
    .required_field("max_connections", FieldType::Integer)
    .allow_additional(false);

let app_schema = Schema::new()
    .required_field("app_name", FieldType::String)
    .required_field("port", FieldType::Integer)
    .required_field("database", FieldType::Table(db_schema));

config.validate_schema(&app_schema)?;
```

**Benefits:**
- ๐Ÿ›ก๏ธ **Early Error Detection**: Catch configuration issues before runtime
- ๐ŸŽฏ **Type Safety**: Ensure values are the expected types
- ๐Ÿ“‹ **Required Fields**: Validate that critical configuration is present
- ๐Ÿ” **Clear Error Messages**: Detailed validation failure reports



<br>