serde_klv/
lib.rs

1//! # Serde KLV
2//!
3//! KLV(Key-Length-Value) is a data encoding standard,
4//! often used to embed information in video feeds.
5//!
6//! This is provide KLV serialier and deserializer for struct.
7//!
8//! [KLV(Wikipedia)]: https://en.wikipedia.org/wiki/KLV
9//!
10//! Examples
11//!
12//! ```rust
13//! use serde_klv::{from_bytes, to_bytes};
14//! use serde::{Deserialize, Serialize};
15//!
16//! #[derive(Debug, Serialize, Deserialize, PartialEq)]
17//! // Set Universal Key string or byte-literal
18//! #[serde(rename = "TESTDATA00000000")]
19//! // #[serde(rename = "\x06\x0e\x2b\x34\x02\x0b\x01\x01\x0e\x01\x03\x01\x01\x00\x00\x00")]
20//! struct TestStruct<'a> {
21//!     // rename to u8 range number
22//!     #[serde(rename = "10")]
23//!     u8: u8,
24//!     #[serde(rename = "11")]
25//!     u64: u64,
26//!     // can use Option
27//!     #[serde(rename = "120", skip_serializing_if = "Option::is_none")]
28//!     none_skip_some: Option<u16>,
29//!     #[serde(rename = "121", skip_serializing_if = "Option::is_none")]
30//!     none_skip_none: Option<u16>,
31//!     #[serde(rename = "60")]
32//!     str: &'a str,
33//!     #[serde(rename = "70")]
34//!     child: TestChild,
35//! }
36//!
37//! #[derive(Debug, Serialize, Deserialize, PartialEq)]
38//! struct TestChild {
39//!     #[serde(rename = "10")]
40//!     x: i8,
41//!     #[serde(rename = "11")]
42//!     y: f32,
43//! }
44//!
45//! let t = TestStruct {
46//!     u8: 127,
47//!     u64: u32::MAX as u64 + 1,
48//!     none_skip_some: Some(2016),
49//!     none_skip_none: None,
50//!     str: "this is string",
51//!     child: TestChild{x: -64, y: 1.23}
52//! };
53//! let buf = to_bytes(&t).unwrap();
54//! let x = from_bytes::<TestStruct>(&buf).unwrap();
55//! assert_eq!(&t, &x);
56//!
57//! // with checksum
58//! use serde_klv::{from_bytes_with_checksum, to_bytes_with_checksum, WrappedCRC};
59//!
60//! let buf = to_bytes_with_checksum(&t, WrappedCRC::default()).unwrap();
61//! let x: TestStruct = from_bytes_with_checksum(&buf, WrappedCRC::default()).unwrap();
62//! assert_eq!(&t, &x);
63//! ```
64
65use std::fmt::Debug;
66
67use byteorder::ByteOrder;
68
69mod checksum;
70mod de;
71pub mod error;
72mod ser;
73
74#[cfg(feature = "uasdls")]
75pub mod uasdls;
76
77pub use checksum::{CheckSumCalc, WrappedCRC};
78pub use de::{from_bytes, from_bytes_with_checksum, KLVMap, KLVRaw};
79pub use ser::{to_bytes, to_bytes_with_checksum};
80
81type LengthByteSize = usize;
82type ContentByteSize = usize;
83
84/// parse length rule by BER
85pub fn parse_length(buf: &[u8]) -> Result<(LengthByteSize, ContentByteSize), String> {
86    use byteorder::BigEndian;
87    match LengthOctet::from_u8(buf[0]) {
88        LengthOctet::Short(x) => Ok((1, x as usize)),
89        LengthOctet::Long(x) => match x {
90            1 => Ok((2, buf[1] as usize)),
91            2 => Ok((3, BigEndian::read_u16(&buf[1..3]) as usize)),
92            4 => Ok((4, BigEndian::read_u32(&buf[1..5]) as usize)),
93            8 => Ok((4, BigEndian::read_u64(&buf[1..9]) as usize)),
94            x => Err(format!(
95                "Unsupported length [{}], supported only {{1,2,4,8}}",
96                x
97            )),
98        },
99        LengthOctet::Indefinite => Err("length is Indefinete".to_string()),
100        LengthOctet::Reserved => Err("Reserved octet".to_string()),
101    }
102}
103
104/// LengthはBERの仕様に従う
105#[derive(Debug, PartialEq, Eq)]
106enum LengthOctet {
107    /// 7bit(127)以下の長さは1byteで表される
108    Short(u8),
109    /// 不定長でマーカオクテット\x00までの読み続ける
110    Indefinite,
111    /// 続くn Byteで数値を表現する。BigEndians
112    Long(u8),
113    /// 予約済みで到達しないはずの値
114    Reserved,
115}
116
117impl LengthOctet {
118    const FIRST_BIT: u8 = 0b1000_0000;
119    const BIT_MASK: u8 = 0b0111_1111;
120    fn from_u8(b: u8) -> Self {
121        if b & Self::FIRST_BIT != Self::FIRST_BIT {
122            Self::Short(b & Self::BIT_MASK)
123        } else if b == 255 {
124            Self::Reserved
125        } else if b == 128 {
126            Self::Indefinite
127        } else {
128            Self::Long(b & Self::BIT_MASK)
129        }
130    }
131
132    pub fn length_to_buf(buf: &mut dyn std::io::Write, size: usize) -> std::io::Result<usize> {
133        use byteorder::BigEndian;
134        if size <= 127 {
135            buf.write(&[size as u8])
136        } else if size <= u8::MAX as usize {
137            buf.write(&[0b1000_0001, size as u8])
138        } else if size <= u16::MAX as usize {
139            let mut r = [0b1000_0010, 0, 0];
140            BigEndian::write_u16(&mut r[1..], size as u16);
141            buf.write(&r)
142        } else {
143            let mut r = [0b1000_0100, 0, 0, 0, 0];
144            BigEndian::write_u32(&mut r[1..], size as u32);
145            buf.write(&r)
146        }
147    }
148}
149
150fn check_universal_key_len(name: &str) -> Result<usize, error::Error> {
151    match name.len() {
152        1 | 2 | 4 | 16 => Ok(name.len()),
153        _ => Err(error::Error::Key(format!(
154            "universal key support length only {{1,2,4,16}} got {}",
155            name
156        ))),
157    }
158}
159
160#[cfg(test)]
161mod tests {
162
163    use crate::LengthOctet;
164
165    #[test]
166    fn test_length_octets() {
167        use LengthOctet::*;
168        let td = [
169            (0, Short(0)),
170            (0b0000_0001, Short(1)),
171            (0b0111_1111, Short(127)),
172            (0b1000_0000, Indefinite),
173            (0b1000_0001, Long(1)),
174            (0b1000_0010, Long(2)),
175            (0b1111_1111, Reserved),
176        ];
177
178        for (b, expect) in td {
179            let lo = LengthOctet::from_u8(b);
180            assert_eq!(lo, expect);
181        }
182    }
183}