1use crate::{Decode, Encode, EncodedSize, Error, Result, VarInt};
9
10#[derive(Debug, Clone, Default, PartialEq)]
20pub struct OpaqueBytes(pub Vec<u8>);
21
22impl OpaqueBytes {
23 pub fn new() -> Self {
25 Self(Vec::new())
26 }
27
28 pub fn from_bytes(bytes: Vec<u8>) -> Self {
30 Self(bytes)
31 }
32
33 pub fn as_bytes(&self) -> &[u8] {
35 &self.0
36 }
37
38 pub fn len(&self) -> usize {
40 self.0.len()
41 }
42
43 pub fn is_empty(&self) -> bool {
45 self.0.is_empty()
46 }
47}
48
49impl Encode for OpaqueBytes {
50 fn encode(&self, buf: &mut Vec<u8>) -> Result<()> {
52 VarInt(self.0.len() as i32).encode(buf)?;
53 buf.extend_from_slice(&self.0);
54 Ok(())
55 }
56}
57
58impl Decode for OpaqueBytes {
59 fn decode(buf: &mut &[u8]) -> Result<Self> {
61 let raw_len = VarInt::decode(buf)?.0;
62 if raw_len < 0 {
63 return Err(Error::InvalidData(format!(
64 "negative opaque length: {raw_len}"
65 )));
66 }
67 let len = raw_len as usize;
68 if buf.len() < len {
69 return Err(Error::BufferUnderflow {
70 needed: len,
71 available: buf.len(),
72 });
73 }
74 let (bytes, rest) = buf.split_at(len);
75 let value = bytes.to_vec();
76 *buf = rest;
77 Ok(Self(value))
78 }
79}
80
81impl EncodedSize for OpaqueBytes {
82 fn encoded_size(&self) -> usize {
83 VarInt(self.0.len() as i32).encoded_size() + self.0.len()
84 }
85}
86
87#[cfg(test)]
88mod tests {
89 use super::*;
90
91 #[test]
92 fn empty_roundtrip() {
93 let original = OpaqueBytes::new();
94 let mut buf = Vec::new();
95 original.encode(&mut buf).unwrap();
96 assert_eq!(buf.len(), 1); let mut cursor = buf.as_slice();
99 let decoded = OpaqueBytes::decode(&mut cursor).unwrap();
100 assert!(cursor.is_empty());
101 assert_eq!(decoded, original);
102 }
103
104 #[test]
105 fn data_roundtrip() {
106 let original = OpaqueBytes::from_bytes(vec![1, 2, 3, 4, 5]);
107 let mut buf = Vec::with_capacity(original.encoded_size());
108 original.encode(&mut buf).unwrap();
109 assert_eq!(buf.len(), original.encoded_size());
110
111 let mut cursor = buf.as_slice();
112 let decoded = OpaqueBytes::decode(&mut cursor).unwrap();
113 assert!(cursor.is_empty());
114 assert_eq!(decoded, original);
115 }
116
117 #[test]
118 fn accessors() {
119 let opaque = OpaqueBytes::from_bytes(vec![0xAB, 0xCD]);
120 assert_eq!(opaque.len(), 2);
121 assert!(!opaque.is_empty());
122 assert_eq!(opaque.as_bytes(), &[0xAB, 0xCD]);
123 }
124}