Skip to main content

ember_plus/codec/
decoder.rs

1//! Glow decoder - converts BER bytes to Glow structures.
2
3use crate::error::{GlowError, Result};
4use crate::ber::{BerReader, Tag};
5use crate::glow::{
6    GlowRoot, GlowElement, GlowNode, GlowParameter, GlowFunction,
7    GlowMatrix, GlowConnection, GlowCommand, GlowTemplate,
8    InvocationResult, StreamEntry, EmberPath, EmberValue, 
9    ParameterType, ParameterAccess, MatrixType, 
10    MatrixAddressingMode, ConnectionOperation, ConnectionDisposition,
11};
12
13/// Decoder for Glow messages.
14pub struct GlowDecoder;
15
16impl GlowDecoder {
17    /// Decode BER bytes to a GlowRoot.
18    pub fn decode(data: &[u8]) -> Result<GlowRoot> {
19        if data.is_empty() {
20            return Ok(GlowRoot::new());
21        }
22
23        let mut reader = BerReader::new(data);
24        Self::decode_root(&mut reader)
25    }
26
27    /// Decode the root element.
28    fn decode_root(reader: &mut BerReader) -> Result<GlowRoot> {
29        let mut root = GlowRoot::new();
30
31        let tag = reader.peek_tag()?;
32        
33        // Application tag 0 = Root
34        if tag.is_application() && tag.number == 0 {
35            let mut inner = reader.read_application(0)?;
36            
37            while inner.has_more() {
38                let child_tag = inner.peek_tag()?;
39                
40                if child_tag.is_application() {
41                    match child_tag.number {
42                        11 => {
43                            // RootElementCollection
44                            let mut coll = inner.read_application(11)?;
45                            while coll.has_more() {
46                                if let Some(element) = Self::decode_element(&mut coll)? {
47                                    root.elements.push(element);
48                                }
49                            }
50                        }
51                        4 => {
52                            // ElementCollection (legacy)
53                            let mut coll = inner.read_application(4)?;
54                            while coll.has_more() {
55                                if let Some(element) = Self::decode_element(&mut coll)? {
56                                    root.elements.push(element);
57                                }
58                            }
59                        }
60                        6 => {
61                            // StreamCollection
62                            let mut coll = inner.read_application(6)?;
63                            while coll.has_more() {
64                                if let Some(entry) = Self::decode_stream_entry(&mut coll)? {
65                                    root.streams.push(entry);
66                                }
67                            }
68                        }
69                        23 => {
70                            // InvocationResult
71                            if let Some(result) = Self::decode_invocation_result(&mut inner)? {
72                                root.invocation_results.push(result);
73                            }
74                        }
75                        _ => {
76                            // Try to decode as element
77                            if let Some(element) = Self::decode_element(&mut inner)? {
78                                root.elements.push(element);
79                            }
80                        }
81                    }
82                } else {
83                    inner.skip()?;
84                }
85            }
86        } else {
87            // Try direct element decoding
88            while reader.has_more() {
89                if let Some(element) = Self::decode_element(reader)? {
90                    root.elements.push(element);
91                }
92            }
93        }
94
95        Ok(root)
96    }
97
98    /// Decode an element.
99    fn decode_element(reader: &mut BerReader) -> Result<Option<GlowElement>> {
100        if !reader.has_more() {
101            return Ok(None);
102        }
103
104        let tag = reader.peek_tag()?;
105
106        // Handle context-tagged elements (NumberedTreeNode wrappers)
107        if tag.is_context() {
108            let mut inner = reader.read_context(tag.number)?;
109            // Inside the context wrapper, look for the actual element
110            if inner.has_more() {
111                return Self::decode_element(&mut inner);
112            }
113            return Ok(None);
114        }
115
116        if !tag.is_application() {
117            reader.skip()?;
118            return Ok(None);
119        }
120
121        match tag.number {
122            1 => Ok(Some(Self::decode_parameter(reader)?)),
123            2 => Ok(Some(Self::decode_command(reader)?)),
124            3 => Ok(Some(Self::decode_node(reader)?)),
125            9 => Ok(Some(Self::decode_qualified_parameter(reader)?)),
126            10 => Ok(Some(Self::decode_qualified_node(reader)?)),
127            13 => Ok(Some(Self::decode_matrix(reader)?)),
128            17 => Ok(Some(Self::decode_qualified_matrix(reader)?)),
129            19 => Ok(Some(Self::decode_function(reader)?)),
130            20 => Ok(Some(Self::decode_qualified_function(reader)?)),
131            24 => Ok(Some(Self::decode_template(reader)?)),
132            _ => {
133                reader.skip()?;
134                Ok(None)
135            }
136        }
137    }
138
139    /// Decode a node.
140    fn decode_node(reader: &mut BerReader) -> Result<GlowElement> {
141        let mut inner = reader.read_application(3)?;
142        let mut node = GlowNode::new(0);
143
144        while inner.has_more() {
145            let tag = inner.peek_tag()?;
146            
147            if tag.is_context() {
148                match tag.number {
149                    0 => {
150                        node.number = inner.read_context_integer(0)? as i32;
151                    }
152                    1 => {
153                        let mut contents = inner.read_context(1)?;
154                        Self::decode_node_contents(&mut contents, &mut node)?;
155                    }
156                    2 => {
157                        let mut children_ctx = inner.read_context(2)?;
158                        if children_ctx.has_more() {
159                            let child_tag = children_ctx.peek_tag()?;
160                            if child_tag.is_application() && child_tag.number == 4 {
161                                let mut coll = children_ctx.read_application(4)?;
162                                while coll.has_more() {
163                                    if let Some(child) = Self::decode_element(&mut coll)? {
164                                        node.children.push(child);
165                                    }
166                                }
167                            }
168                        }
169                    }
170                    _ => { inner.skip()?; }
171                }
172            } else {
173                inner.skip()?;
174            }
175        }
176
177        Ok(GlowElement::Node(node))
178    }
179
180    /// Decode node contents.
181    fn decode_node_contents(reader: &mut BerReader, node: &mut GlowNode) -> Result<()> {
182        // Server may wrap contents in a SET (0x31) or SEQUENCE (0x30)
183        let tag = reader.peek_tag()?;
184        if tag.is_universal() && (tag.number == 17 || tag.number == 16) {
185            // SET or SEQUENCE - read the TLV and create inner reader
186            let (_, value) = reader.read_tlv()?;
187            let mut inner = BerReader::new(value);
188            Self::decode_node_contents_inner(&mut inner, node)?;
189        } else {
190            // Direct contents
191            Self::decode_node_contents_inner(reader, node)?;
192        }
193        Ok(())
194    }
195    
196    /// Decode node contents inner.
197    fn decode_node_contents_inner(reader: &mut BerReader, node: &mut GlowNode) -> Result<()> {
198        while reader.has_more() {
199            let tag = reader.peek_tag()?;
200            
201            if tag.is_context() {
202                match tag.number {
203                    0 => node.identifier = Some(Self::read_context_string(reader, 0)?),
204                    1 => node.description = Some(Self::read_context_string(reader, 1)?),
205                    2 => node.is_root = Some(Self::read_context_bool(reader, 2)?),
206                    3 => node.is_online = Some(Self::read_context_bool(reader, 3)?),
207                    4 => node.schema_identifiers = Some(Self::read_context_string(reader, 4)?),
208                    _ => { reader.skip()?; }
209                }
210            } else {
211                reader.skip()?;
212            }
213        }
214        Ok(())
215    }
216
217    /// Decode a parameter.
218    fn decode_parameter(reader: &mut BerReader) -> Result<GlowElement> {
219        let mut inner = reader.read_application(1)?;
220        let mut param = GlowParameter::new(0);
221
222        while inner.has_more() {
223            let tag = inner.peek_tag()?;
224            
225            if tag.is_context() {
226                match tag.number {
227                    0 => {
228                        param.number = inner.read_context_integer(0)? as i32;
229                    }
230                    1 => {
231                        let mut contents = inner.read_context(1)?;
232                        Self::decode_parameter_contents(&mut contents, &mut param)?;
233                    }
234                    2 => {
235                        let mut children_ctx = inner.read_context(2)?;
236                        if children_ctx.has_more() {
237                            let child_tag = children_ctx.peek_tag()?;
238                            if child_tag.is_application() && child_tag.number == 4 {
239                                let mut coll = children_ctx.read_application(4)?;
240                                while coll.has_more() {
241                                    if let Some(child) = Self::decode_element(&mut coll)? {
242                                        param.children.push(child);
243                                    }
244                                }
245                            }
246                        }
247                    }
248                    _ => { inner.skip()?; }
249                }
250            } else {
251                inner.skip()?;
252            }
253        }
254
255        Ok(GlowElement::Parameter(param))
256    }
257
258    /// Decode parameter contents.
259    fn decode_parameter_contents(reader: &mut BerReader, param: &mut GlowParameter) -> Result<()> {
260        while reader.has_more() {
261            let tag = reader.peek_tag()?;
262            
263            if tag.is_context() {
264                match tag.number {
265                    0 => param.identifier = Some(Self::read_context_string(reader, 0)?),
266                    1 => param.description = Some(Self::read_context_string(reader, 1)?),
267                    2 => param.value = Some(Self::read_context_value(reader, 2)?),
268                    3 => param.minimum = Some(Self::read_context_value(reader, 3)?),
269                    4 => param.maximum = Some(Self::read_context_value(reader, 4)?),
270                    5 => param.access = Some(ParameterAccess::try_from(reader.read_context_integer(5)?)?),
271                    6 => param.format = Some(Self::read_context_string(reader, 6)?),
272                    7 => param.enumeration = Some(Self::read_context_string(reader, 7)?),
273                    8 => param.factor = Some(reader.read_context_integer(8)? as i32),
274                    9 => param.is_online = Some(Self::read_context_bool(reader, 9)?),
275                    10 => param.formula = Some(Self::read_context_string(reader, 10)?),
276                    11 => param.step = Some(reader.read_context_integer(11)? as i32),
277                    12 => param.default = Some(Self::read_context_value(reader, 12)?),
278                    13 => param.parameter_type = Some(ParameterType::try_from(reader.read_context_integer(13)?)?),
279                    14 => param.stream_identifier = Some(reader.read_context_integer(14)? as i32),
280                    _ => { reader.skip()?; }
281                }
282            } else {
283                reader.skip()?;
284            }
285        }
286        Ok(())
287    }
288
289    /// Decode a function.
290    fn decode_function(reader: &mut BerReader) -> Result<GlowElement> {
291        let mut inner = reader.read_application(19)?;
292        let mut func = GlowFunction::new(0);
293
294        while inner.has_more() {
295            let tag = inner.peek_tag()?;
296            
297            if tag.is_context() {
298                match tag.number {
299                    0 => func.number = inner.read_context_integer(0)? as i32,
300                    1 => {
301                        let mut contents = inner.read_context(1)?;
302                        while contents.has_more() {
303                            let ctag = contents.peek_tag()?;
304                            if ctag.is_context() {
305                                match ctag.number {
306                                    0 => func.identifier = Some(Self::read_context_string(&mut contents, 0)?),
307                                    1 => func.description = Some(Self::read_context_string(&mut contents, 1)?),
308                                    _ => { contents.skip()?; }
309                                }
310                            } else {
311                                contents.skip()?;
312                            }
313                        }
314                    }
315                    _ => { inner.skip()?; }
316                }
317            } else {
318                inner.skip()?;
319            }
320        }
321
322        Ok(GlowElement::Function(func))
323    }
324
325    /// Decode a matrix.
326    fn decode_matrix(reader: &mut BerReader) -> Result<GlowElement> {
327        let mut inner = reader.read_application(13)?;
328        let mut matrix = GlowMatrix::new(0);
329
330        while inner.has_more() {
331            let tag = inner.peek_tag()?;
332            
333            if tag.is_context() {
334                match tag.number {
335                    0 => matrix.number = inner.read_context_integer(0)? as i32,
336                    1 => {
337                        let mut contents = inner.read_context(1)?;
338                        Self::decode_matrix_contents(&mut contents, &mut matrix)?;
339                    }
340                    5 => {
341                        let mut conns = inner.read_context(5)?;
342                        while conns.has_more() {
343                            if let Some(conn) = Self::decode_connection(&mut conns)? {
344                                matrix.connections.push(conn);
345                            }
346                        }
347                    }
348                    _ => { inner.skip()?; }
349                }
350            } else {
351                inner.skip()?;
352            }
353        }
354
355        Ok(GlowElement::Matrix(matrix))
356    }
357
358    /// Decode matrix contents.
359    fn decode_matrix_contents(reader: &mut BerReader, matrix: &mut GlowMatrix) -> Result<()> {
360        while reader.has_more() {
361            let tag = reader.peek_tag()?;
362            
363            if tag.is_context() {
364                match tag.number {
365                    0 => matrix.identifier = Some(Self::read_context_string(reader, 0)?),
366                    1 => matrix.description = Some(Self::read_context_string(reader, 1)?),
367                    2 => matrix.matrix_type = Some(MatrixType::try_from(reader.read_context_integer(2)?)?),
368                    3 => matrix.addressing_mode = Some(MatrixAddressingMode::try_from(reader.read_context_integer(3)?)?),
369                    4 => matrix.target_count = Some(reader.read_context_integer(4)? as i32),
370                    5 => matrix.source_count = Some(reader.read_context_integer(5)? as i32),
371                    6 => matrix.max_connections_per_target = Some(reader.read_context_integer(6)? as i32),
372                    7 => matrix.max_total_connections = Some(reader.read_context_integer(7)? as i32),
373                    _ => { reader.skip()?; }
374                }
375            } else {
376                reader.skip()?;
377            }
378        }
379        Ok(())
380    }
381
382    /// Decode a connection.
383    fn decode_connection(reader: &mut BerReader) -> Result<Option<GlowConnection>> {
384        let tag = reader.peek_tag()?;
385        if !tag.is_application() || tag.number != 16 {
386            reader.skip()?;
387            return Ok(None);
388        }
389
390        let mut inner = reader.read_application(16)?;
391        let mut conn = GlowConnection::default();
392
393        while inner.has_more() {
394            let ctag = inner.peek_tag()?;
395            if ctag.is_context() {
396                match ctag.number {
397                    0 => conn.target = inner.read_context_integer(0)? as i32,
398                    1 => {
399                        let mut sources = inner.read_context(1)?;
400                        while sources.has_more() {
401                            conn.sources.push(sources.read_integer()? as i32);
402                        }
403                    }
404                    2 => conn.operation = Some(ConnectionOperation::try_from(inner.read_context_integer(2)?)?),
405                    3 => conn.disposition = Some(ConnectionDisposition::try_from(inner.read_context_integer(3)?)?),
406                    _ => { inner.skip()?; }
407                }
408            } else {
409                inner.skip()?;
410            }
411        }
412
413        Ok(Some(conn))
414    }
415
416    /// Decode a command.
417    fn decode_command(reader: &mut BerReader) -> Result<GlowElement> {
418        let mut inner = reader.read_application(2)?;
419        let mut cmd_number = 0i32;
420        let mut invocation_id = 0i32;
421        let mut arguments = Vec::new();
422
423        while inner.has_more() {
424            let tag = inner.peek_tag()?;
425            
426            if tag.is_context() {
427                match tag.number {
428                    0 => cmd_number = inner.read_context_integer(0)? as i32,
429                    2 => {
430                        let mut inv = inner.read_context(2)?;
431                        while inv.has_more() {
432                            let itag = inv.peek_tag()?;
433                            if itag.is_context() {
434                                match itag.number {
435                                    0 => invocation_id = inv.read_context_integer(0)? as i32,
436                                    1 => {
437                                        let mut args = inv.read_context(1)?;
438                                        while args.has_more() {
439                                            arguments.push(Self::decode_value(&mut args)?);
440                                        }
441                                    }
442                                    _ => { inv.skip()?; }
443                                }
444                            } else {
445                                inv.skip()?;
446                            }
447                        }
448                    }
449                    _ => { inner.skip()?; }
450                }
451            } else {
452                inner.skip()?;
453            }
454        }
455
456        let command = match cmd_number {
457            1 => GlowCommand::Subscribe,
458            2 => GlowCommand::Unsubscribe,
459            32 => GlowCommand::GetDirectory,
460            33 => GlowCommand::Invoke { invocation_id, arguments },
461            _ => GlowCommand::GetDirectory, // Default
462        };
463
464        Ok(GlowElement::Command(command))
465    }
466
467    /// Decode a qualified node.
468    fn decode_qualified_node(reader: &mut BerReader) -> Result<GlowElement> {
469        let mut inner = reader.read_application(10)?;
470        let mut path = Vec::new();
471        let mut node = GlowNode::new(0);
472
473        while inner.has_more() {
474            let tag = inner.peek_tag()?;
475            
476            if tag.is_context() {
477                match tag.number {
478                    0 => path = Self::read_context_path(&mut inner, 0)?,
479                    1 => {
480                        let mut contents = inner.read_context(1)?;
481                        Self::decode_node_contents(&mut contents, &mut node)?;
482                    }
483                    2 => {
484                        let mut children_ctx = inner.read_context(2)?;
485                        if children_ctx.has_more() {
486                            let child_tag = children_ctx.peek_tag()?;
487                            if child_tag.is_application() && child_tag.number == 4 {
488                                let mut coll = children_ctx.read_application(4)?;
489                                while coll.has_more() {
490                                    if let Some(child) = Self::decode_element(&mut coll)? {
491                                        node.children.push(child);
492                                    }
493                                }
494                            }
495                        }
496                    }
497                    _ => { inner.skip()?; }
498                }
499            } else {
500                inner.skip()?;
501            }
502        }
503
504        if let Some(&last) = path.last() {
505            node.number = last;
506        }
507
508        Ok(GlowElement::QualifiedNode(path, node))
509    }
510
511    /// Decode a qualified parameter.
512    fn decode_qualified_parameter(reader: &mut BerReader) -> Result<GlowElement> {
513        let mut inner = reader.read_application(9)?;
514        let mut path = Vec::new();
515        let mut param = GlowParameter::new(0);
516
517        while inner.has_more() {
518            let tag = inner.peek_tag()?;
519            
520            if tag.is_context() {
521                match tag.number {
522                    0 => path = Self::read_context_path(&mut inner, 0)?,
523                    1 => {
524                        let mut contents = inner.read_context(1)?;
525                        Self::decode_parameter_contents(&mut contents, &mut param)?;
526                    }
527                    _ => { inner.skip()?; }
528                }
529            } else {
530                inner.skip()?;
531            }
532        }
533
534        if let Some(&last) = path.last() {
535            param.number = last;
536        }
537
538        Ok(GlowElement::QualifiedParameter(path, param))
539    }
540
541    /// Decode a qualified function.
542    fn decode_qualified_function(reader: &mut BerReader) -> Result<GlowElement> {
543        let mut inner = reader.read_application(20)?;
544        let mut path = Vec::new();
545        let mut func = GlowFunction::new(0);
546
547        while inner.has_more() {
548            let tag = inner.peek_tag()?;
549            
550            if tag.is_context() {
551                match tag.number {
552                    0 => path = Self::read_context_path(&mut inner, 0)?,
553                    1 => {
554                        let mut contents = inner.read_context(1)?;
555                        while contents.has_more() {
556                            let ctag = contents.peek_tag()?;
557                            if ctag.is_context() {
558                                match ctag.number {
559                                    0 => func.identifier = Some(Self::read_context_string(&mut contents, 0)?),
560                                    1 => func.description = Some(Self::read_context_string(&mut contents, 1)?),
561                                    _ => { contents.skip()?; }
562                                }
563                            } else {
564                                contents.skip()?;
565                            }
566                        }
567                    }
568                    _ => { inner.skip()?; }
569                }
570            } else {
571                inner.skip()?;
572            }
573        }
574
575        if let Some(&last) = path.last() {
576            func.number = last;
577        }
578
579        Ok(GlowElement::QualifiedFunction(path, func))
580    }
581
582    /// Decode a qualified matrix.
583    fn decode_qualified_matrix(reader: &mut BerReader) -> Result<GlowElement> {
584        let mut inner = reader.read_application(17)?;
585        let mut path = Vec::new();
586        let mut matrix = GlowMatrix::new(0);
587
588        while inner.has_more() {
589            let tag = inner.peek_tag()?;
590            
591            if tag.is_context() {
592                match tag.number {
593                    0 => path = Self::read_context_path(&mut inner, 0)?,
594                    1 => {
595                        let mut contents = inner.read_context(1)?;
596                        Self::decode_matrix_contents(&mut contents, &mut matrix)?;
597                    }
598                    _ => { inner.skip()?; }
599                }
600            } else {
601                inner.skip()?;
602            }
603        }
604
605        if let Some(&last) = path.last() {
606            matrix.number = last;
607        }
608
609        Ok(GlowElement::QualifiedMatrix(path, matrix))
610    }
611
612    /// Decode a template.
613    fn decode_template(reader: &mut BerReader) -> Result<GlowElement> {
614        let mut inner = reader.read_application(24)?;
615        let mut template = GlowTemplate::default();
616
617        while inner.has_more() {
618            let tag = inner.peek_tag()?;
619            
620            if tag.is_context() {
621                match tag.number {
622                    0 => template.number = inner.read_context_integer(0)? as i32,
623                    2 => template.description = Some(Self::read_context_string(&mut inner, 2)?),
624                    _ => { inner.skip()?; }
625                }
626            } else {
627                inner.skip()?;
628            }
629        }
630
631        Ok(GlowElement::Template(template))
632    }
633
634    /// Decode an invocation result.
635    fn decode_invocation_result(reader: &mut BerReader) -> Result<Option<InvocationResult>> {
636        let mut inner = reader.read_application(23)?;
637        let mut invocation_id = 0;
638        let mut success = false;
639        let mut result = Vec::new();
640
641        while inner.has_more() {
642            let tag = inner.peek_tag()?;
643            
644            if tag.is_context() {
645                match tag.number {
646                    0 => invocation_id = inner.read_context_integer(0)? as i32,
647                    1 => success = Self::read_context_bool(&mut inner, 1)?,
648                    2 => {
649                        let mut res = inner.read_context(2)?;
650                        while res.has_more() {
651                            result.push(Self::decode_value(&mut res)?);
652                        }
653                    }
654                    _ => { inner.skip()?; }
655                }
656            } else {
657                inner.skip()?;
658            }
659        }
660
661        Ok(Some(InvocationResult { invocation_id, success, result }))
662    }
663
664    /// Decode a stream entry.
665    fn decode_stream_entry(reader: &mut BerReader) -> Result<Option<StreamEntry>> {
666        let tag = reader.peek_tag()?;
667        if !tag.is_application() || tag.number != 5 {
668            reader.skip()?;
669            return Ok(None);
670        }
671
672        let mut inner = reader.read_application(5)?;
673        let mut stream_identifier = 0;
674        let mut value = EmberValue::Null;
675
676        while inner.has_more() {
677            let ctag = inner.peek_tag()?;
678            if ctag.is_context() {
679                match ctag.number {
680                    0 => stream_identifier = inner.read_context_integer(0)? as i32,
681                    1 => value = Self::read_context_value(&mut inner, 1)?,
682                    _ => { inner.skip()?; }
683                }
684            } else {
685                inner.skip()?;
686            }
687        }
688
689        Ok(Some(StreamEntry { stream_identifier, value }))
690    }
691
692    /// Read a context-tagged string.
693    fn read_context_string(reader: &mut BerReader, _tag: u32) -> Result<String> {
694        let (_, data) = reader.read_tlv()?;
695        // The context tag contains a UTF8String (0x0C) or other string type
696        // Parse the inner TLV to get the actual string
697        if data.len() >= 2 {
698            let mut inner = BerReader::new(data);
699            let (inner_tag, inner_data) = inner.read_tlv()?;
700            // UTF8String (0x0C) or other string types
701            if inner_tag.is_universal() {
702                return Ok(String::from_utf8_lossy(inner_data).to_string());
703            }
704        }
705        // Fallback: treat as raw string
706        Ok(String::from_utf8_lossy(data).to_string())
707    }
708
709    /// Read a context-tagged boolean.
710    fn read_context_bool(reader: &mut BerReader, _tag: u32) -> Result<bool> {
711        let (_, data) = reader.read_tlv()?;
712        Ok(data.first().map(|&b| b != 0).unwrap_or(false))
713    }
714
715    /// Read a context-tagged path.
716    fn read_context_path(reader: &mut BerReader, _tag: u32) -> Result<EmberPath> {
717        let mut ctx = reader.read_context(0)?;
718        let oid = ctx.read_relative_oid()?;
719        Ok(oid.into_iter().map(|n| n as i32).collect())
720    }
721
722    /// Read a context-tagged value.
723    fn read_context_value(reader: &mut BerReader, _tag: u32) -> Result<EmberValue> {
724        let mut ctx = reader.read_context(_tag)?;
725        Self::decode_value(&mut ctx)
726    }
727
728    /// Decode a value.
729    fn decode_value(reader: &mut BerReader) -> Result<EmberValue> {
730        let (tag, data) = reader.read_tlv()?;
731
732        if tag.is_universal() {
733            match tag.number {
734                1 => Ok(EmberValue::Boolean(data.first().map(|&b| b != 0).unwrap_or(false))),
735                2 => {
736                    let value = Self::decode_integer(data)?;
737                    Ok(EmberValue::Integer(value))
738                }
739                4 => Ok(EmberValue::Octets(data.to_vec())),
740                5 => Ok(EmberValue::Null),
741                9 => {
742                    let value = Self::decode_real(data)?;
743                    Ok(EmberValue::Real(value))
744                }
745                12 => Ok(EmberValue::String(String::from_utf8_lossy(data).to_string())),
746                _ => Ok(EmberValue::Null),
747            }
748        } else {
749            Ok(EmberValue::Octets(data.to_vec()))
750        }
751    }
752
753    /// Decode an integer from bytes.
754    fn decode_integer(data: &[u8]) -> Result<i64> {
755        if data.is_empty() {
756            return Ok(0);
757        }
758
759        let negative = (data[0] & 0x80) != 0;
760        let mut result: i64 = if negative { -1 } else { 0 };
761
762        for &byte in data {
763            result = (result << 8) | (byte as i64);
764        }
765
766        Ok(result)
767    }
768
769    /// Decode a real from bytes.
770    fn decode_real(data: &[u8]) -> Result<f64> {
771        if data.is_empty() {
772            return Ok(0.0);
773        }
774
775        let first = data[0];
776        
777        if first == 0x40 { return Ok(f64::INFINITY); }
778        if first == 0x41 { return Ok(f64::NEG_INFINITY); }
779        if first == 0x42 { return Ok(f64::NAN); }
780        if first == 0x43 { return Ok(-0.0); }
781
782        // Binary encoding
783        if (first & 0x80) != 0 {
784            let sign = if (first & 0x40) != 0 { -1.0 } else { 1.0 };
785            let exp_len = match first & 0x03 {
786                0 => 1, 1 => 2, 2 => 3,
787                _ => data.get(1).copied().unwrap_or(0) as usize,
788            };
789            let exp_start = if (first & 0x03) == 3 { 2 } else { 1 };
790            
791            if data.len() < exp_start + exp_len {
792                return Ok(0.0);
793            }
794
795            let exp_bytes = &data[exp_start..exp_start + exp_len];
796            let mut exp: i64 = if !exp_bytes.is_empty() && (exp_bytes[0] & 0x80) != 0 { -1 } else { 0 };
797            for &b in exp_bytes { exp = (exp << 8) | (b as i64); }
798
799            let mant_bytes = &data[exp_start + exp_len..];
800            let mut mant: u64 = 0;
801            for &b in mant_bytes { mant = (mant << 8) | (b as u64); }
802
803            return Ok(sign * (mant as f64) * 2.0_f64.powi(exp as i32));
804        }
805
806        Ok(0.0)
807    }
808}