tx2-link 0.1.1

Binary protocol for syncing ECS worlds with field-level delta compression
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
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
# tx2-link

**Binary protocol for syncing ECS worlds between runtimes with field-level delta compression.**

tx2-link is the bridge/protocol layer of the TX-2 ecosystem, enabling efficient synchronization of Entity-Component-System state across web, native, and CLI environments. It defines the "wire format" for transmitting world snapshots and deltas with minimal bandwidth overhead.

## Features

### Delta Compression
- **Field-level change detection** - Only transmit changed component fields
- **1171× compression ratio** - Benchmarked: 1.2MB full snapshot → 1KB delta (10% entity churn)
- **Automatic delta generation** - Compare snapshots and extract minimal diff
- **Delta application** - Reconstruct full state from base + delta

### Multiple Serialization Formats
- **MessagePack** - Compact binary format (default, best compression)
- **Bincode** - Fast Rust-native serialization (lowest latency)
- **JSON** - Human-readable debugging format

### Transport Abstractions
- **WebSocket** - Server ↔ browser sync (async)
- **IPC** - Inter-process communication for native ↔ webview
- **Stdio** - Pipe-based communication for CLI tools
- **Memory** - In-process channels for testing

### Rate Limiting
- **Token bucket** - Burst handling with sustained rate limits
- **Sliding window** - Precise message/byte rate enforcement
- **Per-connection limits** - Individual rate limiters per client
- **357k checks/sec** - Benchmarked throughput while enforcing 1k msg/sec cap

### Schema Versioning
- **Component schema registry** - Type definitions with version tracking
- **Schema validation** - Ensure client/server compatibility
- **Migration support** - Handle schema evolution gracefully

### Streaming Protocol
- **Length-prefixed framing** - Parse messages from byte streams
- **Zero-copy deserialization** - Direct memory mapping where possible
- **Backpressure support** - Flow control for slow consumers

### Debug Mode
- **JSON logging** - Pretty-print all messages and deltas for inspection
- **Human-readable traces** - Operation summaries with timing and sizes
- **Environment variable control** - Enable with `TX2_DEBUG=1` or `TX2_TRACE=1`
- **Zero runtime overhead** - Debug checks compile out when disabled

## Quick Start

### Delta Compression

```rust
use tx2_link::{WorldSnapshot, DeltaCompressor};

let mut compressor = DeltaCompressor::new();

// Create two snapshots
let snapshot1 = WorldSnapshot { /* ... */ };
let snapshot2 = WorldSnapshot { /* ... */ };

// Generate delta (only changed fields)
let delta = compressor.create_delta(&snapshot1, &snapshot2)?;

// Apply delta to reconstruct snapshot2
let reconstructed = compressor.apply_delta(&snapshot1, &delta)?;

assert_eq!(snapshot2, reconstructed);
```

### Serialization

```rust
use tx2_link::{Message, Serializer, SerializationFormat};

// Create message
let message = Message::Snapshot(snapshot);

// Serialize to MessagePack
let mut serializer = Serializer::new(SerializationFormat::MessagePack);
let bytes = serializer.serialize(&message)?;

// Deserialize
let deserialized: Message = serializer.deserialize(&bytes)?;
```

### Transport

```rust
use tx2_link::{Transport, WebSocketTransport};

// Create WebSocket transport
let transport = WebSocketTransport::connect("ws://localhost:8080").await?;

// Send message
transport.send(&message).await?;

// Receive message
let received = transport.receive().await?;
```

### Rate Limiting

```rust
use tx2_link::{RateLimiter, TokenBucketLimiter};

// Create rate limiter: 100 msg/sec, burst of 10
let mut limiter = TokenBucketLimiter::new(100.0, 10);

// Check if message can be sent
if limiter.check_message(1)? {
    transport.send(&message).await?;
}
```

## Performance

Benchmarked on 10,000 entities with Position, Velocity, Health components:

### Delta Compression
- **Full snapshot**: 1,232,875 bytes
- **Delta (10% churn)**: 1,052 bytes
- **Compression ratio**: 1171×
- **Delta generation**: ~2ms
- **Delta application**: ~1.5ms

### Serialization Performance
| Format | Serialize | Deserialize | Size |
|--------|-----------|-------------|------|
| MessagePack | 180µs | 250µs | 1.05MB |
| Bincode | 140µs | 195µs | 1.12MB |
| JSON | 420µs | 350µs | 2.28MB |

### Rate Limiting
- **Check throughput**: 357k checks/sec
- **Overhead**: ~3µs per check
- **Memory**: ~200 bytes per limiter

## Architecture

### Protocol Messages

```rust
pub enum Message {
    Snapshot(WorldSnapshot),          // Full world state
    Delta(DeltaSnapshot),             // Incremental update
    EntityCreated { id, components }, // New entity
    EntityDeleted { id },             // Entity removed
    ComponentAdded { entity, data },  // Component attached
    ComponentRemoved { entity, id },  // Component detached
    SchemaUpdate(ComponentSchema),    // Type definition
}
```

### World Snapshot

```rust
pub struct WorldSnapshot {
    pub timestamp: u64,
    pub entities: Vec<EntitySnapshot>,
}

pub struct EntitySnapshot {
    pub id: EntityId,
    pub components: Vec<ComponentSnapshot>,
}

pub struct ComponentSnapshot {
    pub id: ComponentId,
    pub data: ComponentData,
}
```

### Component Data Formats

```rust
pub enum ComponentData {
    Binary(Vec<u8>),                           // Raw bytes
    Json(String),                              // JSON string
    Structured(HashMap<FieldId, FieldValue>),  // Field-level access
}
```

## Delta Algorithm

tx2-link uses field-level diffing for maximum compression:

1. **Compare entities** - Match entities between snapshots by ID
2. **Detect additions/removals** - Track created/deleted entities
3. **Compare components** - Match components by type within each entity
4. **Field-level diff** - Extract only changed fields within components
5. **Generate delta** - Encode minimal changeset

For structured components:
```rust
// Previous: { x: 10.0, y: 20.0, z: 30.0 }
// Current:  { x: 10.0, y: 25.0, z: 30.0 }
// Delta:    { y: 25.0 }  // Only y changed
```

## Transport Layer

All transports implement the `Transport` trait:

```rust
#[async_trait]
pub trait Transport: Send + Sync {
    async fn send(&self, message: &Message) -> Result<()>;
    async fn receive(&self) -> Result<Message>;
    async fn close(&self) -> Result<()>;
}
```

### WebSocket Transport

```rust
use tx2_link::WebSocketTransport;

// Server
let transport = WebSocketTransport::bind("127.0.0.1:8080").await?;

// Client
let transport = WebSocketTransport::connect("ws://localhost:8080").await?;
```

### IPC Transport

```rust
use tx2_link::IpcTransport;

// Create named pipe/socket
let transport = IpcTransport::new("tx2-world")?;
```

### Stdio Transport

```rust
use tx2_link::StdioTransport;

// Use stdin/stdout
let transport = StdioTransport::new();
```

### Memory Transport

```rust
use tx2_link::MemoryTransport;

// In-process channels (for testing)
let (tx, rx) = MemoryTransport::create_pair();
```

## Rate Limiting

### Token Bucket

Allows bursts up to a capacity, refilling at a steady rate:

```rust
use tx2_link::TokenBucketLimiter;

// 1000 msg/sec, burst of 100
let limiter = TokenBucketLimiter::new(1000.0, 100);

// Check and consume tokens
if limiter.check_message(1)? {
    // Send message
}
```

### Sliding Window

Enforces strict limits over a time window:

```rust
use tx2_link::SlidingWindowLimiter;

// 1000 msg/sec, 1MB/sec, 60-second window
let limiter = SlidingWindowLimiter::new(
    1000,     // max messages
    1_000_000, // max bytes
    60.0,     // window seconds
);

if limiter.check(1, message_size)? {
    // Send message
}
```

## Schema Versioning

```rust
use tx2_link::{SchemaRegistry, ComponentSchema};

let mut registry = SchemaRegistry::new();

// Register component type
let schema = ComponentSchema::new("Position")
    .with_field("x", FieldType::F32)
    .with_field("y", FieldType::F32)
    .with_field("z", FieldType::F32)
    .with_version(1);

registry.register(schema)?;

// Validate incoming data
if registry.validate("Position", &component_data)? {
    // Apply update
}
```

## Integration with TX-2 Ecosystem

tx2-link bridges the TX-2 stack:

- **tx2-ecs** (TypeScript/Node): Web runtime using tx2-link for server sync
- **tx2-core** (Rust): Native engine using tx2-link for client sync
- **tx2-pack**: Uses tx2-link's snapshot format for save/load

### Use Cases

1. **Server ↔ Browser** - Sync game state over WebSocket
2. **Native ↔ Webview** - IPC between Rust engine and web UI
3. **CLI Tools** - Stream world state over stdio pipes
4. **Multi-process** - Distribute simulation across processes
5. **Debugging** - Inspect live world state with JSON transport

## Examples

### Full Client-Server Sync

```rust
use tx2_link::*;

// Server
let transport = WebSocketTransport::bind("127.0.0.1:8080").await?;
let limiter = TokenBucketLimiter::new(100.0, 10);
let mut compressor = DeltaCompressor::new();

let mut last_snapshot = world.create_snapshot();

loop {
    tokio::time::sleep(Duration::from_millis(16)).await; // 60 FPS

    let snapshot = world.create_snapshot();
    let delta = compressor.create_delta(&last_snapshot, &snapshot)?;

    if limiter.check_message(1)? {
        transport.send(&Message::Delta(delta)).await?;
    }

    last_snapshot = snapshot;
}

// Client
let transport = WebSocketTransport::connect("ws://localhost:8080").await?;
let mut compressor = DeltaCompressor::new();
let mut snapshot = WorldSnapshot::empty();

loop {
    let message = transport.receive().await?;

    match message {
        Message::Snapshot(full) => {
            snapshot = full;
            world.restore_from_snapshot(&snapshot)?;
        }
        Message::Delta(delta) => {
            snapshot = compressor.apply_delta(&snapshot, &delta)?;
            world.restore_from_snapshot(&snapshot)?;
        }
        _ => {}
    }
}
```

## Running Tests

```bash
cargo test
```

All 22 tests should pass, covering:
- Delta compression accuracy
- Serialization roundtrips (all formats)
- Rate limiter behavior
- Schema validation
- Transport abstractions

## Running Benchmarks

```bash
cargo bench
```

Benchmarks measure:
- Delta compression performance
- Serialization/deserialization speed
- Rate limiter throughput
- Field-level diff overhead

## Debug Mode

tx2-link includes a comprehensive debug system for inspecting protocol operations without modifying code.

### Environment Variables

Enable debug features using environment variables:

- **`TX2_DEBUG=1`** or **`TX2_DEBUG_JSON=1`** - Enable JSON pretty-printing of all messages, snapshots, and deltas
- **`TX2_TRACE=1`** - Enable human-readable trace logging with operation timings and sizes

Both can be combined: `TX2_DEBUG=1 TX2_TRACE=1`

### Debug Mode Features

When `TX2_DEBUG=1` is set:
- All serialized/deserialized messages are logged as pretty-printed JSON
- World snapshots are logged with entity counts
- Deltas are logged showing all changes in readable JSON format

When `TX2_TRACE=1` is set:
- Delta summaries showing entities added/removed/modified
- Serialization performance (format, size, duration)
- Delta compression ratios and timing
- Rate limiter decisions (allowed/blocked, current rate)
- Transport operations (bytes sent/received)

### Usage

```bash
# Run with JSON debug logging
TX2_DEBUG=1 cargo run

# Run with human-readable traces
TX2_TRACE=1 cargo run

# Run with both
TX2_DEBUG=1 TX2_TRACE=1 cargo run
```

### Example Output

With `TX2_TRACE=1`:
```
[TX2-LINK] Delta Summary:
  Timestamp: 2.0 (base: 1.0)
  Total changes: 5
  + 1 entities added
  ~ 2 components modified

[TX2-LINK] Delta compression: 1232875 bytes → 1052 bytes (1171.79× reduction) in 2134µs
[TX2-LINK] Serialized 1052 bytes using MessagePack in 250µs
```

With `TX2_DEBUG=1`:
```
[TX2-LINK] Serialized Message:
{
  "header": {
    "msg_type": "Delta",
    "sequence": 42,
    "timestamp": 1234567890
  },
  "payload": {
    "changes": [
      {
        "EntityAdded": { "entity_id": 123 }
      },
      {
        "ComponentAdded": {
          "entity_id": 123,
          "component_id": "Position",
          "data": { "x": 10.0, "y": 20.0 }
        }
      }
    ]
  }
}
```

### Programmatic Access

You can also enable debug mode programmatically:

```rust
use tx2_link::init_debug_mode;

fn main() {
    // Reads TX2_DEBUG and TX2_TRACE environment variables
    init_debug_mode();

    // Your code here - debug logging happens automatically
}
```

### Why Debug Mode?

Binary protocols like MessagePack and Bincode are efficient but opaque. Without debug mode, inspecting what's being sent over the wire requires:
- Packet capture tools
- Manual deserialization
- Custom logging code

With debug mode, you get instant visibility into:
- What data is changing between snapshots
- How effective delta compression is
- Serialization format efficiency
- Rate limiting behavior
- Network traffic patterns

This makes tx2-link extremely "vibe coding friendly" - you can see exactly what's happening without writing debugging code.

## Development Status

- [x] Core protocol messages
- [x] Delta compression with field-level diffing
- [x] Multi-format serialization (MessagePack, Bincode, JSON)
- [x] Transport abstractions (WebSocket, IPC, stdio, memory)
- [x] Rate limiting (token bucket, sliding window)
- [x] Schema versioning and validation
- [x] Streaming serializer/deserializer
- [x] Comprehensive benchmarks
- [x] Debug mode with JSON logging and traces
- [ ] Compression (zstd/lz4) for large snapshots
- [ ] Encryption support
- [ ] Reconnection handling with state recovery
- [ ] Binary diff algorithms for large binary components

## Dependencies

- `serde` - Serialization framework
- `rmp-serde` - MessagePack format
- `bincode` - Bincode format
- `serde_json` - JSON format
- `tokio` - Async runtime
- `bytes` - Efficient byte buffers
- `ahash` - Fast hashing
- `thiserror` - Error handling

## License

MIT

## Contributing

Contributions are welcome! This is part of the broader TX-2 project for building isomorphic applications with a unified world model.

## Learn More

- [TX-2 Framework Outline]../frameworkoutline.md
- [tx2-core Native Engine]../tx2-core
- [tx2-pack Snapshot Format]../tx2-pack
- [tx2-ecs TypeScript Runtime]https://github.com/IreGaddr/tx2-ecs