scte35 0.2.0

A Rust library for creating and parsing SCTE-35 (Society of Cable Telecommunications Engineers) messages with zero-dependency.
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
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
# SCTE-35 Library

A Rust library for creating and parsing SCTE-35 (Society of Cable Telecommunications Engineers) messages with built-in CRC validation. SCTE-35 is a standard for inserting cue messages into video streams, commonly used for ad insertion points in broadcast television.

## Features

- **Builder Pattern API** - Type-safe builder pattern for creating SCTE-35 messages from scratch with validation
- **Serde support** - Serialize/deserialize SCTE-35 messages to/from JSON and other formats (enabled by default)
- **CRC validation** - Built-in CRC-32 validation using MPEG-2 algorithm (enabled by default)
- **Human-readable UPID parsing** - Full support for 18 standard UPID types with intelligent formatting
- **Human-readable segmentation types** - Complete set of 48 standard segmentation types with descriptive names
- **Segmentation descriptor parsing** - Complete parsing of segmentation descriptors including UPID data
- **Minimal dependencies** - Only the `crc` crate for validation (optional) and `serde` for serialization (optional)
- **Full SCTE-35 parsing** - Supports all major SCTE-35 command types
- **Bit-level precision** - Accurate parsing of bit-packed SCTE-35 messages
- **Optional CLI tool** - Command-line interface for parsing base64-encoded messages with text and JSON output formats
- **Type-safe** - Strongly typed representations of all SCTE-35 structures
- **Data integrity** - Detects corrupted or tampered SCTE-35 messages

## Installation

### With All Features (Default)

Add this to your `Cargo.toml`:

```toml
[dependencies]
scte35 = "0.2.0"
```

This includes both CRC validation and serde support.

### Without Serde Support

If you don't need JSON serialization:

```toml
[dependencies]
scte35 = { version = "0.2.0", default-features = false, features = ["crc-validation"] }
```

### Minimal (No CRC or Serde)

For a minimal library without CRC validation or serde:

```toml
[dependencies]
scte35 = { version = "0.2.0", default-features = false }
```

### With CLI Tool (Automatically includes CRC validation)

To include the command-line tool, enable the `cli` feature:

```toml
[dependencies]
scte35 = { version = "0.2.0", features = ["cli"] }
```

Or install the CLI tool directly:

```bash
cargo install scte35 --features cli
```

**Note**: The CLI feature automatically enables CRC validation to provide complete message diagnostics.

## Usage

### Library Usage

```rust
use scte35::{parse_splice_info_section, SpliceCommand, SpliceDescriptor};
use std::time::Duration;

// Your SCTE-35 message as bytes (example message)
let scte35_bytes = vec![
    0xFC, 0x30, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xF0, 0x05, 0x06, 0xFE, 
    0x42, 0x3A, 0x35, 0xBD, 0x00, 0x00, 0xBB, 0x0C, 0x73, 0xF4
];

match parse_splice_info_section(&scte35_bytes) {
Ok(section) => {
    println!("Table ID: {}", section.table_id);
    println!("Command Type: {}", section.splice_command_type);
    
    match section.splice_command {
        SpliceCommand::SpliceInsert(insert) => {
            println!("Splice Event ID: 0x{:08x}", insert.splice_event_id);
            
            // Convert break duration to std::time::Duration
            if let Some(break_duration) = &insert.break_duration {
                let duration: Duration = break_duration.into();
                println!("Break Duration: {:?}", duration);
                println!("Break Duration: {:.3} seconds", duration.as_secs_f64());
            }
            
            // Convert splice time to Duration
            if let Some(duration) = insert.splice_time.as_ref()
                .and_then(|st| st.to_duration()) {
                println!("Splice Time: {:?}", duration);
            }
        }
        SpliceCommand::TimeSignal(signal) => {
            if let Some(duration) = signal.splice_time.to_duration() {
                println!("Time Signal: {:?}", duration);
            }
        }
        _ => println!("Other command type"),
    }
    
    // Parse segmentation descriptors with UPID information
    for descriptor in &section.splice_descriptors {
        if let SpliceDescriptor::Segmentation(seg_desc) = descriptor {
            println!("Segmentation Event ID: 0x{:08x}", seg_desc.segmentation_event_id);
            println!("UPID Type: {}", seg_desc.upid_type_description());
            println!("Segmentation Type: {}", seg_desc.segmentation_type_description());
            
            if let Some(upid_str) = seg_desc.upid_as_string() {
                println!("UPID: {}", upid_str);
            }
        }
    }
}
Err(e) => eprintln!("Error parsing SCTE-35: {}", e),
}
```

### CRC Validation

By default, the library validates CRC-32 checksums in SCTE-35 messages to ensure data integrity:

```rust
use scte35::{parse_splice_info_section, validate_scte35_crc, CrcValidatable};

// Example SCTE-35 message bytes
let scte35_bytes = vec![
    0xFC, 0x30, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xF0, 0x05, 0x06, 0xFE, 
    0x42, 0x3A, 0x35, 0xBD, 0x00, 0x00, 0xBB, 0x0C, 0x73, 0xF4
];

// Parse with automatic CRC validation (default behavior)
match parse_splice_info_section(&scte35_bytes) {
Ok(section) => {
    println!("Valid SCTE-35 message parsed successfully");
    println!("CRC-32: 0x{:08X}", section.get_crc());
}
Err(e) => {
    if e.to_string().contains("CRC validation failed") {
        eprintln!("Message corrupted or tampered: {}", e);
    } else {
        eprintln!("Parse error: {}", e);
    }
}
}

// Validate CRC independently
match validate_scte35_crc(&scte35_bytes) {
    Ok(true) => println!("CRC validation passed"),
    Ok(false) => println!("CRC validation failed or not available"),
    Err(e) => eprintln!("Validation error: {}", e),
}

// Validate using the parsed section
if let Ok(section) = parse_splice_info_section(&scte35_bytes) {
    match section.validate_crc(&scte35_bytes) {
        Ok(true) => println!("Message integrity verified"),
        Ok(false) => println!("Message integrity check failed"),
        Err(e) => eprintln!("Validation error: {}", e),
    }
}
```

### Duration Conversion

SCTE-35 time values are represented as 90kHz clock ticks. This library provides convenient conversion to Rust's `std::time::Duration`:

```rust
use scte35::BreakDuration;
use std::time::Duration;

// Create a break duration of 30 seconds (30 * 90000 ticks)
let break_duration = BreakDuration {
    auto_return: 1,
    reserved: 0,
    duration: 2_700_000,
};

// Convert using Into trait  
let duration: Duration = (&break_duration).into();
assert_eq!(duration.as_secs(), 30);

// Or use the method directly
let duration2 = break_duration.to_duration();
assert_eq!(duration2.as_secs(), 30);
```

### Serde Support (JSON Serialization)

The library includes built-in serde support for serializing/deserializing SCTE-35 messages:

```rust
use scte35::parse_splice_info_section;
use serde_json;

// Parse SCTE-35 message
let scte35_bytes = vec![
    0xFC, 0x30, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xF0, 0x05, 0x06, 0xFE, 
    0x42, 0x3A, 0x35, 0xBD, 0x00, 0x00, 0xBB, 0x0C, 0x73, 0xF4
];

if let Ok(section) = parse_splice_info_section(&scte35_bytes) {
    // Serialize to JSON
    let json = serde_json::to_string_pretty(&section).unwrap();
    println!("{}", json);
    
    // Deserialize from JSON
    let deserialized: scte35::SpliceInfoSection = 
        serde_json::from_str(&json).unwrap();
    assert_eq!(section, deserialized);
}
```

The serde implementation includes:

- **Binary data as base64**: All raw bytes (private commands, UPID data, alignment bits) are encoded as base64 strings
- **Human-readable enums**: Segmentation types and UPID types include both numeric values and descriptions
- **Time duration info**: PTS times and durations include both raw ticks and human-readable formats
- **Computed fields**: Segmentation descriptors include parsed UPID strings when available

Example JSON output:
```json
{
  "table_id": 252,
  "section_syntax_indicator": 0,
  "private_indicator": 0,
  "section_length": 22,
  "protocol_version": 0,
  "encrypted_packet": 0,
  "encryption_algorithm": 0,
  "pts_adjustment": 0,
  "cw_index": 255,
  "tier": 4095,
  "splice_command_length": 5,
  "splice_command_type": 6,
  "splice_command": {
    "type": "TimeSignal",
    "splice_time": {
      "time_specified_flag": 1,
      "pts_time": 900000,
      "duration_info": {
        "ticks": 900000,
        "seconds": 10.0,
        "human_readable": "10.0s"
      }
    }
  },
  "descriptor_loop_length": 0,
  "splice_descriptors": [],
  "alignment_stuffing_bits": "",
  "e_crc_32": null,
  "crc_32": 0
}
```

### Segmentation Types

The library provides human-readable segmentation types that correspond to the numeric IDs in SCTE-35 messages:

```rust
use scte35::{SegmentationType, parse_splice_info_section, SpliceDescriptor};

// Work with segmentation types directly
let seg_type = SegmentationType::ProviderAdvertisementStart;
println!("Type: {} (ID: 0x{:02X})", seg_type, seg_type.id());

// Convert from numeric ID (useful when parsing)
let seg_type = SegmentationType::from_id(0x30);
assert_eq!(seg_type, SegmentationType::ProviderAdvertisementStart);
assert_eq!(seg_type.to_string(), "Provider Advertisement Start");

// Example: Parse a message and check segmentation descriptors
let scte35_bytes = vec![
    0xFC, 0x30, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xF0, 0x05, 0x06, 0xFE, 
    0x42, 0x3A, 0x35, 0xBD, 0x00, 0x00, 0xBB, 0x0C, 0x73, 0xF4
];

if let Ok(section) = parse_splice_info_section(&scte35_bytes) {
    // Segmentation descriptors automatically populate both fields
    // The numeric ID and human-readable type are always consistent
    for descriptor in &section.splice_descriptors {
        if let SpliceDescriptor::Segmentation(seg_desc) = descriptor {
            println!("Segmentation Type ID: 0x{:02X}", seg_desc.segmentation_type_id);
            println!("Segmentation Type: {:?}", seg_desc.segmentation_type);
            println!("Description: {}", seg_desc.segmentation_type_description());
        }
    }
}
```

#### Supported Segmentation Types

The library supports all standard SCTE-35 segmentation types including:

**Program Boundaries:**
- Program Start/End
- Program Early Termination
- Program Breakaway/Resumption
- Program Runover (Planned/Unplanned)
- Program Overlap Start
- Program Blackout Override
- Program Join

**Content Segments:**
- Chapter Start/End
- Break Start/End
- Content Identification

**Advertisement Opportunities:**
- Provider/Distributor Advertisement Start/End
- Provider/Distributor Placement Opportunity Start/End
- Provider/Distributor Overlay Placement Opportunity Start/End
- Provider/Distributor Promo Start/End
- Provider/Distributor Ad Block Start/End

**Special Events:**
- Unscheduled Event Start/End
- Alternate Content Opportunity Start/End
- Network Start/End

### Builder Pattern API (Creating SCTE-35 Messages)

The library includes a comprehensive builder pattern API for creating SCTE-35 messages from scratch with type safety and validation:

```rust
# use scte35::builders::*;
# use scte35::types::SegmentationType;
# use std::time::Duration;
# fn main() -> BuilderResult<()> {
// Example 1: Creating a 30-second ad break starting at 20 seconds
let splice_insert = SpliceInsertBuilder::new(12345)
    .at_pts(Duration::from_secs(20))?
    .duration(Duration::from_secs(30))
    .unique_program_id(0x1234)
    .avail(1, 4)  // First of 4 avails
    .build()?;

let section = SpliceInfoSectionBuilder::new()
    .pts_adjustment(0)
    .splice_insert(splice_insert)
    .build()?;

println!("Created SCTE-35 message with {} byte payload", section.section_length);
# Ok(())
# }
```

#### Creating Time Signals with Segmentation Descriptors

```rust
# use scte35::builders::*;
# use scte35::types::SegmentationType;
# use std::time::Duration;
# fn example() -> BuilderResult<()> {
// Example 2: Program start boundary with UPID
let segmentation = SegmentationDescriptorBuilder::new(
        5678, 
        SegmentationType::ProgramStart
    )
    .upid(Upid::AdId("ABC123456789".to_string()))?
    .duration(Duration::from_secs(1800))?  // 30-minute program
    .build()?;

let section = SpliceInfoSectionBuilder::new()
    .time_signal(TimeSignalBuilder::new().immediate().build()?)
    .add_segmentation_descriptor(segmentation)
    .build()?;
# Ok(())
# }
```

#### Component-Level Splice Operations

```rust
# use scte35::builders::*;
# use std::time::Duration;
# fn example() -> BuilderResult<()> {
// Example 3: Component-level splice for specific audio/video streams
let splice_insert = SpliceInsertBuilder::new(3333)
    .component_splice(vec![
        (0x01, Some(Duration::from_secs(10))),  // Video component
        (0x02, Some(Duration::from_secs(10))),  // Audio component 1
        (0x03, Some(Duration::from_secs(10))),  // Audio component 2
    ])?
    .duration(Duration::from_secs(15))
    .build()?;
# Ok(())
# }
```

#### Advanced Segmentation with Delivery Restrictions

```rust
# use scte35::builders::*;
# use scte35::types::SegmentationType;
# fn example() -> BuilderResult<()> {
// Example 4: Complex segmentation with delivery restrictions
let restrictions = DeliveryRestrictions {
    web_delivery_allowed: false,
    no_regional_blackout: false,
    archive_allowed: true,
    device_restrictions: DeviceRestrictions::RestrictGroup1,
};

let uuid_bytes = [0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0,
                 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0];

let segmentation = SegmentationDescriptorBuilder::new(
        7777,
        SegmentationType::DistributorAdvertisementStart
    )
    .delivery_restrictions(restrictions)
    .upid(Upid::Uuid(uuid_bytes))?
    .segment(2, 6)  // 2nd of 6 segments
    .build()?;
# Ok(())
# }
```

#### Comprehensive UPID Support

The builder API supports all SCTE-35 UPID types with validation:

```rust
# use scte35::builders::*;
# fn example() -> BuilderResult<()> {
# let mut builder = SegmentationDescriptorBuilder::new(1, scte35::types::SegmentationType::ProgramStart);
// Ad ID (12 ASCII characters)
builder = builder.upid(Upid::AdId("ABC123456789".to_string()))?;

// UUID (16 bytes)
let uuid_bytes = [0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0,
                 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0];
builder = builder.upid(Upid::Uuid(uuid_bytes))?;

// URI (variable length)
builder = builder.upid(Upid::Uri("https://example.com/content/123".to_string()))?;

// ISAN (12 bytes)
let isan_bytes = [0x00, 0x00, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01, 0x23];
builder = builder.upid(Upid::Isan(isan_bytes))?;

// And many more: UMID, EIDR, TID, AiringID, etc.
# Ok(())
# }
```

#### Error Handling and Validation

The builder API provides comprehensive validation with clear error messages:

```rust
# use scte35::builders::*;
# use scte35::types::SegmentationType;
# use std::time::Duration;
# fn example() -> BuilderResult<()> {
// Invalid UPID length
let result = SegmentationDescriptorBuilder::new(1234, SegmentationType::ProgramStart)
    .upid(Upid::AdId("TOO_SHORT".to_string()));

match result {
    Err(BuilderError::InvalidUpidLength { expected, actual }) => {
        println!("UPID validation failed: expected {} chars, got {}", expected, actual);
    }
    _ => {}
}

// Duration too large for 33-bit PTS
let result = SpliceInsertBuilder::new(1234)
    .at_pts(Duration::from_secs(u64::MAX / 90_000 + 1))?
    .build();

match result {
    Err(BuilderError::DurationTooLarge { field, duration }) => {
        println!("Duration {} is too large for field {}", duration.as_secs(), field);
    }
    _ => {}
}
# Ok(())
# }
```

#### Builder Features

- **Type Safety**: Compile-time prevention of invalid message states
- **Validation**: Runtime validation with descriptive error messages  
- **Ergonomic API**: Fluent interface with sensible defaults
- **Spec Compliance**: Automatic handling of reserved fields and constraints
- **Complete Coverage**: Builders for all major SCTE-35 structures

See the [builder_demo example](examples/builder_demo.rs) for more comprehensive usage examples.

### CLI Usage

When built with the `cli` feature, you can parse base64-encoded SCTE-35 messages with multiple output formats:

```bash
# Text output (default)
cargo run --features cli -- "/DAvAAAAAAAA///wFAVIAACPf+/+c2nALv4AUsz1AAAAAAAKAAhDVUVJAAABNWLbowo="

# JSON output
cargo run --features cli -- -o json "/DAvAAAAAAAA///wFAVIAACPf+/+c2nALv4AUsz1AAAAAAAKAAhDVUVJAAABNWLbowo="

# Or with long flag
cargo run --features cli -- --output json "/DAvAAAAAAAA///wFAVIAACPf+/+c2nALv4AUsz1AAAAAAAKAAhDVUVJAAABNWLbowo="

# Get help
cargo run --features cli -- --help
```

Example output with splice insert command and break duration:
```text
Successfully parsed SpliceInfoSection:
  Table ID: 252
  Section Length: 47
  Protocol Version: 0
  Splice Command Type: 5
  Splice Command Length: 20
  Splice Command: SpliceInsert
    Splice Event ID: 0x4800008f
    Splice Event Cancel: 0
    Out of Network: 1
    Program Splice Flag: 1
    Duration Flag: 1
    Splice Immediate Flag: 0
    Splice Time PTS: 0x07369c02e
    Splice Time: 21514.559089 seconds
    Break Duration:
      Auto Return: 1
      Duration: 0x00052ccf5 (60.293567 seconds)
    Unique Program ID: 0
    Avail Num: 0
    Avails Expected: 0
  Descriptor Loop Length: 10
  Number of Descriptors: 1
    Unknown Descriptor:
      Tag: 0x00
      Length: 8
      Content: "CUEI  5"
  CRC-32: 0x62DBA30A ✓ (Valid)
```

#### CLI Output Formats

The CLI supports two output formats:

- **Text format** (default): Human-readable format with detailed field descriptions
- **JSON format**: Structured JSON output for programmatic use

JSON output includes the complete parsed structure with CRC validation results:

```bash
cargo run --features cli -- -o json "/DAvAAAAAAAA///wFAVIAACPf+/+c2nALv4AUsz1AAAAAAAKAAhDVUVJAAABNWLbowo="
```

```json
{
  "status": "success",
  "data": {
    "table_id": 252,
    "section_length": 47,
    "protocol_version": 0,
    "splice_command_type": 5,
    "splice_command_length": 20,
    "splice_command": {
      "type": "SpliceInsert",
      "splice_event_id": 1207959695,
      "splice_event_cancel_indicator": 0,
      "out_of_network_indicator": 1,
      "program_splice_flag": 1,
      "duration_flag": 1,
      "splice_immediate_flag": 0,
      "splice_time": {
        "time_specified_flag": 1,
        "pts_time": 1936310318,
        "duration_info": {
          "ticks": 1936310318,
          "seconds": 21514.559088888887,
          "human_readable": "5h 58m 34.6s"
        }
      },
      "break_duration": {
        "auto_return": 1,
        "duration": 5426421,
        "duration_info": {
          "ticks": 5426421,
          "seconds": 60.29356666666666,
          "human_readable": "1m 0.3s"
        }
      },
      "unique_program_id": 0,
      "avail_num": 0,
      "avails_expected": 0
    },
    "descriptor_loop_length": 10,
    "splice_descriptors": [
      {
        "descriptor_type": "Unknown",
        "tag": 0,
        "length": 8,
        "data": "Q1VFSQAAATU="
      }
    ],
    "crc_32": 1658561290
  },
  "crc_validation": {
    "valid": true,
    "error": null
  }
}
```

## Supported SCTE-35 Commands

- **SpliceNull** - Null command
- **SpliceSchedule** - Scheduled splice events
- **SpliceInsert** - Immediate or scheduled ad insertion points
- **TimeSignal** - Time synchronization signals
- **BandwidthReservation** - Bandwidth allocation commands
- **PrivateCommand** - Private/custom commands

## CRC Validation

By default, the library validates CRC-32 checksums in SCTE-35 messages to ensure data integrity. This feature can be disabled if needed:

### With CRC Validation (Default)
```toml
[dependencies]
scte35 = "0.2.0"
```

### Without CRC Validation (Library only)
```toml
[dependencies]
scte35 = { version = "0.2.0", default-features = false }
```

### With CLI Tool (Automatically includes CRC validation)
```toml
[dependencies]
scte35 = { version = "0.2.0", features = ["cli"] }
```

**Note**: The CLI feature automatically enables CRC validation to provide complete message diagnostics.

### Benefits of CRC Validation

1. **Data Integrity**: Ensures SCTE-35 messages haven't been corrupted during transmission
2. **Security**: Helps detect tampered messages
3. **Debugging**: Identifies parsing issues vs. data corruption
4. **Standards Compliance**: Follows SCTE-35 specification requirements
5. **Flexibility**: Optional feature allows users to choose performance vs. validation trade-offs

## API Documentation

Full API documentation is available at [docs.rs](https://docs.rs/scte35) or can be generated locally:

```bash
cargo doc --no-deps --open
```

### Main Functions

#### `parse_splice_info_section(buffer: &[u8]) -> Result<SpliceInfoSection, io::Error>`

Parses a complete SCTE-35 splice information section from a byte buffer. Automatically validates CRC-32 when the `crc-validation` feature is enabled.

#### `validate_scte35_crc(buffer: &[u8]) -> Result<bool, io::Error>`

Validates the CRC-32 checksum of an SCTE-35 message independently. Returns `Ok(true)` if valid, `Ok(false)` if invalid or CRC validation is disabled.

### Data Structures

#### `SpliceInfoSection`
The top-level structure containing all SCTE-35 message fields:
- `table_id`: Table identifier (should be 0xFC for SCTE-35)
- `section_length`: Length of the section
- `protocol_version`: SCTE-35 protocol version
- `splice_command_type`: Type of splice command
- `splice_command`: The actual command data (enum)
- `descriptor_loop_length`: Length of descriptors
- `splice_descriptors`: List of splice descriptors
- `crc_32`: CRC32 checksum

#### `SpliceCommand`
An enum representing different SCTE-35 command types:
- `SpliceNull`
- `SpliceSchedule(SpliceSchedule)`
- `SpliceInsert(SpliceInsert)`
- `TimeSignal(TimeSignal)`
- `BandwidthReservation(BandwidthReservation)`
- `PrivateCommand(PrivateCommand)`
- `Unknown`

## Building from Source

### Build Library Only
```bash
git clone https://github.com/yourusername/scte35
cd scte35
cargo build --release
```

### Build with CLI Tool
```bash
cargo build --release --features cli
```

### Run Tests
```bash
cargo test
```

## License

This project is licensed under the MIT License - see the LICENSE file for details.

## Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

## References

- [SCTE-35 2023r1 Specification]https://www.scte.org/standards/
- [Digital Program Insertion Cueing Message]https://en.wikipedia.org/wiki/SCTE-35