@@ -46,13 +46,32 @@ func Marshal(v any) ([]byte, error) {
4646 }
4747
4848 switch kind {
49+ case reflect .Slice :
50+ return appendSlice (nil , value )
4951 case reflect .Struct :
5052 return appendStruct (nil , value )
5153 }
5254
5355 return nil , errors .New ("tlv8: not implemented: " + kind .String ())
5456}
5557
58+ // separator the most confusing meaning in the documentation.
59+ // It can have a value of 0x00 or 0xFF or even 0x05.
60+ const separator = 0xFF
61+
62+ func appendSlice (b []byte , value reflect.Value ) ([]byte , error ) {
63+ for i := 0 ; i < value .Len (); i ++ {
64+ if i > 0 {
65+ b = append (b , separator , 0 )
66+ }
67+ var err error
68+ if b , err = appendStruct (b , value .Index (i )); err != nil {
69+ return nil , err
70+ }
71+ }
72+ return b , nil
73+ }
74+
5675func appendStruct (b []byte , value reflect.Value ) ([]byte , error ) {
5776 valueType := value .Type ()
5877
@@ -121,7 +140,7 @@ func appendValue(b []byte, tag byte, value reflect.Value) ([]byte, error) {
121140 case reflect .Slice :
122141 for i := 0 ; i < value .Len (); i ++ {
123142 if i > 0 {
124- b = append (b , 0 , 0 )
143+ b = append (b , separator , 0 )
125144 }
126145 if b , err = appendValue (b , tag , value .Index (i )); err != nil {
127146 return nil , err
@@ -179,64 +198,86 @@ func Unmarshal(data []byte, v any) error {
179198 kind = value .Kind ()
180199 }
181200
182- if kind != reflect .Struct {
183- return errors .New ("tlv8: not implemented: " + kind .String ())
201+ switch kind {
202+ case reflect .Slice :
203+ return unmarshalSlice (data , value )
204+ case reflect .Struct :
205+ return unmarshalStruct (data , value )
184206 }
185207
186- return unmarshalStruct ( data , value )
208+ return errors . New ( "tlv8: not implemented: " + kind . String () )
187209}
188210
189- func unmarshalStruct (b []byte , value reflect.Value ) error {
190- var waitSlice bool
211+ // unmarshalTLV can return two types of errors:
212+ // - critical and then the value of []byte will be nil
213+ // - not critical and then []byte will contain the value
214+ func unmarshalTLV (b []byte , value reflect.Value ) ([]byte , error ) {
215+ if len (b ) < 2 {
216+ return nil , errors .New ("tlv8: wrong size: " + value .Type ().Name ())
217+ }
191218
192- for len (b ) >= 2 {
193- t := b [0 ]
194- l := int (b [1 ])
219+ t := b [0 ]
220+ l := int (b [1 ])
195221
196- // array item divider
197- if t == 0 && l == 0 {
198- b = b [2 :]
199- waitSlice = true
200- continue
222+ // array item divider (t == 0x00 || t == 0xFF)
223+ if l == 0 {
224+ return b [2 :], errors .New ("tlv8: zero item" )
225+ }
226+
227+ var v []byte
228+
229+ for {
230+ if len (b ) < 2 + l {
231+ return nil , errors .New ("tlv8: wrong size: " + value .Type ().Name ())
201232 }
202233
203- var v []byte
234+ v = append (v , b [2 :2 + l ]... )
235+ b = b [2 + l :]
204236
205- for {
206- if len (b ) < 2 + l {
207- return errors . New ( "tlv8: wrong size: " + value . Type (). Name ())
208- }
237+ // if size == 255 and same tag - continue read big payload
238+ if l < 255 || len (b ) < 2 || b [ 0 ] != t {
239+ break
240+ }
209241
210- v = append ( v , b [ 2 : 2 + l ] ... )
211- b = b [ 2 + l :]
242+ l = int ( b [ 1 ] )
243+ }
212244
213- // if size == 255 and same tag - continue read big payload
214- if l < 255 || len (b ) < 2 || b [0 ] != t {
215- break
216- }
245+ tag := strconv .Itoa (int (t ))
217246
218- l = int (b [1 ])
219- }
247+ valueField , ok := getStructField (value , tag )
248+ if ! ok {
249+ return b , fmt .Errorf ("tlv8: can't find T=%d,L=%d,V=%x for: %s" , t , l , v , value .Type ().Name ())
250+ }
220251
221- tag := strconv .Itoa (int (t ))
252+ if err := unmarshalValue (v , valueField ); err != nil {
253+ return nil , err
254+ }
222255
223- valueField , ok := getStructField (value , tag )
224- if ! ok {
225- return fmt .Errorf ("tlv8: can't find T=%d,L=%d,V=%x for: %s" , t , l , v , value .Type ().Name ())
226- }
256+ return b , nil
257+ }
227258
228- if waitSlice {
229- if valueField .Kind () != reflect .Slice {
230- return fmt .Errorf ("tlv8: should be slice T=%d,L=%d,V=%x for: %s" , t , l , v , value .Type ().Name ())
259+ func unmarshalSlice (b []byte , value reflect.Value ) error {
260+ valueIndex := value .Index (growSlice (value ))
261+ for len (b ) > 0 {
262+ var err error
263+ if b , err = unmarshalTLV (b , valueIndex ); err != nil {
264+ if b != nil {
265+ valueIndex = value .Index (growSlice (value ))
266+ continue
231267 }
232- waitSlice = false
268+ return err
233269 }
270+ }
271+ return nil
272+ }
234273
235- if err := unmarshalValue (v , valueField ); err != nil {
274+ func unmarshalStruct (b []byte , value reflect.Value ) error {
275+ for len (b ) > 0 {
276+ var err error
277+ if b , err = unmarshalTLV (b , value ); b == nil && err != nil {
236278 return err
237279 }
238280 }
239-
240281 return nil
241282}
242283
0 commit comments