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
//! Signal reading and decoding.
//!
//! This module provides low-level signal format decoders that work with any
//! `BufRead` source. Each format decoder is responsible for reading raw bytes
//! and converting them to `Sample` values according to the WFDB specification.
//!
//! # Hybrid APIs
//!
//! The module provides three levels of API for different use cases:
//!
//! 1. **Low-level buffer API** - [`FormatDecoder::decode_buf()`]
//! - Zero-copy performance
//! - Caller manages buffer allocation
//! - Best for tight loops or custom allocation strategies
//!
//! 2. **High-level ergonomic API** - [`FormatDecoder::decode()`]
//! - Returns `Vec<Sample>`
//! - Simple and idiomatic Rust
//! - Best for most use cases
//!
//! 3. **Iterator API** - [`FormatDecoder::samples()`]
//! - Lazy evaluation
//! - Integrates with Rust's iterator ecosystem
//! - Best for streaming, filtering, or processing one sample at a time
//!
//! # Format Support
//!
//! Each WFDB signal format has a dedicated decoder:
//! - Format 0: Null signals (no data)
//! - Format 8: 8-bit first differences
//! - Format 16: 16-bit two's complement (little-endian)
//! - Format 24: 24-bit two's complement (little-endian)
//! - Format 32: 32-bit two's complement (little-endian)
//! - Format 61: 16-bit two's complement (big-endian)
//! - Format 80: 8-bit offset binary
//! - Format 160: 16-bit offset binary
//! - Format 212: Packed 12-bit samples (2 samples in 3 bytes)
//! - Format 310: Packed 10-bit samples (3 samples in 4 bytes)
//! - Format 311: Packed 10-bit samples (alternative layout)
//!
//! > _FLAC-based formats are not supported yet._
//!
//! # Examples
//!
//! ## Buffer API
//!
//! ```no_run
//! use wfdb::signal::{Format16Decoder, FormatDecoder};
//! use std::io::BufReader;
//! use std::fs::File;
//!
//! # fn main() -> wfdb::Result<()> {
//! let file = File::open("data/100.dat")?;
//! let mut reader = BufReader::new(file);
//! let mut decoder = Format16Decoder::new();
//!
//! // Reuse buffer for performance
//! let mut buffer = vec![0i32; 1000];
//! loop {
//! let n = decoder.decode_buf(&mut reader, &mut buffer)?;
//! if n == 0 { break; }
//! // Process samples in buffer[..n]
//! }
//! # Ok(())
//! # }
//! ```
//!
//! ## Ergonomic API
//!
//! ```no_run
//! use wfdb::signal::{Format16Decoder, FormatDecoder};
//! use std::io::BufReader;
//! use std::fs::File;
//!
//! # fn main() -> wfdb::Result<()> {
//! let file = File::open("data/100.dat")?;
//! let mut reader = BufReader::new(file);
//! let mut decoder = Format16Decoder::new();
//!
//! // Simple and clean
//! let samples = decoder.decode(&mut reader, 1000)?;
//! println!("Read {} samples", samples.len());
//! # Ok(())
//! # }
//! ```
//!
//! ## Iterator API
//!
//! ```no_run
//! use wfdb::signal::{Format16Decoder, FormatDecoder};
//! use std::io::BufReader;
//! use std::fs::File;
//!
//! # fn main() -> wfdb::Result<()> {
//! let file = File::open("data/100.dat")?;
//! let reader = BufReader::new(file);
//! let mut decoder = Format16Decoder::new();
//!
//! // Use iterator
//! let positive_samples: Vec<_> = decoder.samples(reader)
//! .take(1000)
//! .filter_map(Result::ok)
//! .filter(|&s| s > 0)
//! .collect();
//! # Ok(())
//! # }
//! ```
pub use ;
pub use Format0Decoder;
pub use Format8Decoder;
pub use Format16Decoder;
pub use Format24Decoder;
pub use Format32Decoder;
pub use Format61Decoder;
pub use Format80Decoder;
pub use Format160Decoder;
pub use Format212Decoder;
pub use Format310Decoder;
pub use Format311Decoder;
use crate::;
/// Create a decoder for given signal format.
///
/// # Errors
///
/// Returns `Error::UnsupportedSignalFormat` if the format is not supported.