1use super::{Tag, BerReader, BerWriter};
4use crate::error::Result;
5
6#[derive(Debug, Clone, PartialEq)]
8pub enum BerValue {
9 Boolean(bool),
11 Integer(i64),
13 Real(f64),
15 String(String),
17 OctetString(Vec<u8>),
19 Null,
21 Sequence(Vec<BerValue>),
23 Context { tag: u32, value: Box<BerValue> },
25 Application { tag: u32, value: Box<BerValue> },
27 Raw { tag: Tag, data: Vec<u8> },
29}
30
31impl BerValue {
32 pub fn as_boolean(&self) -> Option<bool> {
34 match self {
35 BerValue::Boolean(v) => Some(*v),
36 _ => None,
37 }
38 }
39
40 pub fn as_integer(&self) -> Option<i64> {
42 match self {
43 BerValue::Integer(v) => Some(*v),
44 _ => None,
45 }
46 }
47
48 pub fn as_real(&self) -> Option<f64> {
50 match self {
51 BerValue::Real(v) => Some(*v),
52 BerValue::Integer(v) => Some(*v as f64),
53 _ => None,
54 }
55 }
56
57 pub fn as_string(&self) -> Option<&str> {
59 match self {
60 BerValue::String(v) => Some(v),
61 _ => None,
62 }
63 }
64
65 pub fn as_octet_string(&self) -> Option<&[u8]> {
67 match self {
68 BerValue::OctetString(v) => Some(v),
69 _ => None,
70 }
71 }
72
73 pub fn as_sequence(&self) -> Option<&[BerValue]> {
75 match self {
76 BerValue::Sequence(v) => Some(v),
77 _ => None,
78 }
79 }
80
81 pub fn is_null(&self) -> bool {
83 matches!(self, BerValue::Null)
84 }
85
86 pub fn decode(data: &[u8]) -> Result<Self> {
88 let mut reader = BerReader::new(data);
89 Self::decode_from_reader(&mut reader)
90 }
91
92 pub fn decode_from_reader(reader: &mut BerReader) -> Result<Self> {
94 let (tag, value_bytes) = reader.read_tlv()?;
95
96 if tag.is_universal() {
97 match tag.number {
98 1 => {
99 Ok(BerValue::Boolean(value_bytes.first().map(|&b| b != 0).unwrap_or(false)))
101 }
102 2 => {
103 let mut inner = BerReader::new(value_bytes);
105 let value = decode_integer_bytes(value_bytes)?;
107 Ok(BerValue::Integer(value))
108 }
109 5 => {
110 Ok(BerValue::Null)
112 }
113 9 => {
114 let value = decode_real_bytes(value_bytes)?;
116 Ok(BerValue::Real(value))
117 }
118 12 => {
119 Ok(BerValue::String(String::from_utf8(value_bytes.to_vec())?))
121 }
122 4 => {
123 Ok(BerValue::OctetString(value_bytes.to_vec()))
125 }
126 16 => {
127 let mut items = Vec::new();
129 let mut inner = BerReader::new(value_bytes);
130 while inner.has_more() {
131 items.push(Self::decode_from_reader(&mut inner)?);
132 }
133 Ok(BerValue::Sequence(items))
134 }
135 _ => {
136 Ok(BerValue::Raw { tag, data: value_bytes.to_vec() })
138 }
139 }
140 } else if tag.is_context() {
141 let inner_value = if tag.is_constructed() && !value_bytes.is_empty() {
142 Self::decode(value_bytes)?
143 } else {
144 BerValue::OctetString(value_bytes.to_vec())
145 };
146 Ok(BerValue::Context {
147 tag: tag.number,
148 value: Box::new(inner_value),
149 })
150 } else if tag.is_application() {
151 let inner_value = if tag.is_constructed() && !value_bytes.is_empty() {
152 Self::decode(value_bytes)?
153 } else {
154 BerValue::OctetString(value_bytes.to_vec())
155 };
156 Ok(BerValue::Application {
157 tag: tag.number,
158 value: Box::new(inner_value),
159 })
160 } else {
161 Ok(BerValue::Raw { tag, data: value_bytes.to_vec() })
162 }
163 }
164
165 pub fn encode(&self) -> Result<Vec<u8>> {
167 let mut writer = BerWriter::new();
168 self.encode_to_writer(&mut writer)?;
169 Ok(writer.into_bytes())
170 }
171
172 pub fn encode_to_writer(&self, writer: &mut BerWriter) -> Result<()> {
174 match self {
175 BerValue::Boolean(v) => writer.write_boolean(*v),
176 BerValue::Integer(v) => writer.write_integer(*v),
177 BerValue::Real(v) => writer.write_real(*v),
178 BerValue::String(v) => writer.write_utf8_string(v),
179 BerValue::OctetString(v) => writer.write_octet_string(v),
180 BerValue::Null => writer.write_null(),
181 BerValue::Sequence(items) => {
182 writer.write_sequence(|w| {
183 for item in items {
184 item.encode_to_writer(w)?;
185 }
186 Ok(())
187 })
188 }
189 BerValue::Context { tag, value } => {
190 writer.write_context(*tag, |w| value.encode_to_writer(w))
191 }
192 BerValue::Application { tag, value } => {
193 writer.write_application(*tag, |w| value.encode_to_writer(w))
194 }
195 BerValue::Raw { tag, data } => {
196 writer.write_tlv(tag, data);
197 Ok(())
198 }
199 }
200 }
201}
202
203fn decode_integer_bytes(value: &[u8]) -> Result<i64> {
205 use crate::error::BerError;
206
207 if value.is_empty() {
208 return Err(BerError::invalid_value("INTEGER", "empty value").into());
209 }
210
211 if value.len() > 8 {
212 return Err(BerError::invalid_value(
213 "INTEGER",
214 format!("value too large: {} bytes", value.len())
215 ).into());
216 }
217
218 let negative = (value[0] & 0x80) != 0;
219 let mut result: i64 = if negative { -1 } else { 0 };
220
221 for &byte in value {
222 result = (result << 8) | (byte as i64);
223 }
224
225 Ok(result)
226}
227
228fn decode_real_bytes(value: &[u8]) -> Result<f64> {
230 use crate::error::BerError;
231
232 if value.is_empty() {
233 return Ok(0.0);
234 }
235
236 let first_byte = value[0];
237
238 if first_byte == 0x40 {
240 return Ok(f64::INFINITY);
241 }
242 if first_byte == 0x41 {
243 return Ok(f64::NEG_INFINITY);
244 }
245 if first_byte == 0x42 {
246 return Ok(f64::NAN);
247 }
248 if first_byte == 0x43 {
249 return Ok(-0.0);
250 }
251
252 if (first_byte & 0x80) != 0 {
254 let sign = if (first_byte & 0x40) != 0 { -1.0 } else { 1.0 };
255 let base: f64 = match (first_byte >> 4) & 0x03 {
256 0 => 2.0,
257 1 => 8.0,
258 2 => 16.0,
259 _ => return Err(BerError::invalid_value("REAL", "invalid base").into()),
260 };
261 let scale_factor = (first_byte >> 2) & 0x03;
262 let exponent_length = match first_byte & 0x03 {
263 0 => 1,
264 1 => 2,
265 2 => 3,
266 3 => value.get(1).copied().unwrap_or(0) as usize,
267 _ => unreachable!(),
268 };
269
270 let exp_start = if (first_byte & 0x03) == 3 { 2 } else { 1 };
271 if value.len() < exp_start + exponent_length {
272 return Err(BerError::invalid_value("REAL", "truncated exponent").into());
273 }
274
275 let exp_bytes = &value[exp_start..exp_start + exponent_length];
276 let mut exponent: i64 = if !exp_bytes.is_empty() && (exp_bytes[0] & 0x80) != 0 {
277 -1
278 } else {
279 0
280 };
281 for &b in exp_bytes {
282 exponent = (exponent << 8) | (b as i64);
283 }
284
285 let mantissa_start = exp_start + exponent_length;
286 let mantissa_bytes = &value[mantissa_start..];
287 let mut mantissa: u64 = 0;
288 for &b in mantissa_bytes {
289 mantissa = (mantissa << 8) | (b as u64);
290 }
291
292 let scaled_mantissa = (mantissa as f64) * (1 << scale_factor) as f64;
293 let result = sign * scaled_mantissa * base.powi(exponent as i32);
294
295 return Ok(result);
296 }
297
298 Err(BerError::invalid_value("REAL", "unsupported encoding").into())
299}
300
301impl From<bool> for BerValue {
302 fn from(v: bool) -> Self {
303 BerValue::Boolean(v)
304 }
305}
306
307impl From<i64> for BerValue {
308 fn from(v: i64) -> Self {
309 BerValue::Integer(v)
310 }
311}
312
313impl From<i32> for BerValue {
314 fn from(v: i32) -> Self {
315 BerValue::Integer(v as i64)
316 }
317}
318
319impl From<f64> for BerValue {
320 fn from(v: f64) -> Self {
321 BerValue::Real(v)
322 }
323}
324
325impl From<String> for BerValue {
326 fn from(v: String) -> Self {
327 BerValue::String(v)
328 }
329}
330
331impl From<&str> for BerValue {
332 fn from(v: &str) -> Self {
333 BerValue::String(v.to_string())
334 }
335}
336
337impl From<Vec<u8>> for BerValue {
338 fn from(v: Vec<u8>) -> Self {
339 BerValue::OctetString(v)
340 }
341}
342
343#[cfg(test)]
344mod tests {
345 use super::*;
346
347 #[test]
348 fn test_value_roundtrip() {
349 let values = vec![
350 BerValue::Boolean(true),
351 BerValue::Boolean(false),
352 BerValue::Integer(0),
353 BerValue::Integer(42),
354 BerValue::Integer(-1),
355 BerValue::String("Hello".to_string()),
356 BerValue::OctetString(vec![1, 2, 3]),
357 BerValue::Null,
358 BerValue::Sequence(vec![
359 BerValue::Integer(1),
360 BerValue::String("test".to_string()),
361 ]),
362 ];
363
364 for value in values {
365 let encoded = value.encode().unwrap();
366 let decoded = BerValue::decode(&encoded).unwrap();
367 assert_eq!(value, decoded);
368 }
369 }
370}