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}