taproot_assets_types/
tlv.rs1use alloc::{string::String, vec, vec::Vec};
2use bitcoin::io::{self as bitcoin_io, Read};
3
4#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
5pub struct Type(pub u64);
6
7impl Type {
8 pub fn is_odd(self) -> bool {
9 self.0 % 2 != 0
10 }
11 pub fn is_even(self) -> bool {
12 self.0 % 2 == 0
13 }
14}
15
16#[derive(Debug, Clone, PartialEq, Eq)]
17pub struct Record {
18 tlv_type: Type,
19 value: Vec<u8>,
20}
21
22impl Record {
23 pub fn tlv_type(&self) -> Type {
24 self.tlv_type
25 }
26
27 pub fn value(&self) -> &[u8] {
28 &self.value
29 }
30
31 pub fn value_reader(&self) -> bitcoin_io::Cursor<&[u8]> {
32 bitcoin_io::Cursor::new(&self.value)
33 }
34}
35
36pub struct Stream<R: Read> {
37 reader: R,
38}
39
40impl<R: Read> Stream<R> {
41 pub fn new(reader: R) -> Self {
42 Stream { reader }
43 }
44
45 fn read_u8_manual(&mut self) -> Result<u8, crate::error::Error> {
46 let mut buf = [0; 1];
47 self.reader
48 .read_exact(&mut buf)
49 .map_err(crate::error::Error::Io)?;
50 Ok(buf[0])
51 }
52
53 fn read_u16_manual_be(&mut self) -> Result<u16, crate::error::Error> {
54 let mut buf = [0; 2];
55 self.reader
56 .read_exact(&mut buf)
57 .map_err(crate::error::Error::Io)?;
58 Ok(u16::from_be_bytes(buf))
59 }
60
61 fn read_u32_manual_be(&mut self) -> Result<u32, crate::error::Error> {
62 let mut buf = [0; 4];
63 self.reader
64 .read_exact(&mut buf)
65 .map_err(crate::error::Error::Io)?;
66 Ok(u32::from_be_bytes(buf))
67 }
68
69 fn read_u64_manual_be(&mut self) -> Result<u64, crate::error::Error> {
70 let mut buf = [0; 8];
71 self.reader
72 .read_exact(&mut buf)
73 .map_err(crate::error::Error::Io)?;
74 Ok(u64::from_be_bytes(buf))
75 }
76
77 fn read_var_int(&mut self) -> Result<u64, crate::error::Error> {
79 let first_byte = self.read_u8_manual()?;
80 match first_byte {
81 0..=0xFC => Ok(first_byte as u64),
82 0xFD => Ok(self.read_u16_manual_be()? as u64),
83 0xFE => Ok(self.read_u32_manual_be()? as u64),
84 0xFF => Ok(self.read_u64_manual_be()?),
85 }
86 }
87
88 pub fn next_record(&mut self) -> Result<Option<Record>, String> {
89 let tlv_type = match self.read_var_int() {
90 Ok(val) => Type(val),
91 Err(crate::error::Error::Io(_)) => return Ok(None), Err(e) => return Err(alloc::format!("Failed to read TLV type: {:?}", e)),
94 };
95
96 let length = match self.read_var_int() {
97 Ok(val) => val,
98 Err(e) => {
99 return Err(alloc::format!(
100 "Failed to read TLV length for type {:?}: {:?}",
101 tlv_type,
102 e
103 ));
104 }
105 };
106
107 if length > (1_i32 << 20) as u64 {
108 return Err(alloc::format!(
110 "TLV record too large: {} bytes for type {:?}",
111 length,
112 tlv_type
113 ));
114 }
115
116 let mut value = vec![0; length as usize];
117 match self.reader.read_exact(&mut value) {
118 Ok(_) => Ok(Some(Record { tlv_type, value })),
119 Err(e) => Err(alloc::format!(
120 "Failed to read TLV value for type {:?} (length {}): {:?}",
121 tlv_type,
122 length,
123 e
124 )),
125 }
126 }
127}
128
129pub type Value<'a> = &'a [u8];