@@ -12,6 +12,9 @@ use alloc::{
12
12
} ;
13
13
use core:: { f64, num:: FpCategory , str:: FromStr } ;
14
14
15
+ #[ cfg( feature = "const-oid" ) ]
16
+ use const_oid:: ObjectIdentifier ;
17
+
15
18
use facet_core:: {
16
19
Def , Facet , NumberBits , ScalarAffinity , Shape , ShapeAttribute , StructKind , Type , UserType ,
17
20
} ;
@@ -21,7 +24,9 @@ mod tag;
21
24
22
25
const ASN1_TYPE_TAG_BOOLEAN : u8 = 0x01 ;
23
26
const ASN1_TYPE_TAG_INTEGER : u8 = 0x02 ;
27
+ const ASN1_TYPE_TAG_OCTET_STRING : u8 = 0x04 ;
24
28
const ASN1_TYPE_TAG_NULL : u8 = 0x05 ;
29
+ const ASN1_TYPE_TAG_OBJECT_IDENTIFIER : u8 = 0x06 ;
25
30
const ASN1_TYPE_TAG_REAL : u8 = 0x09 ;
26
31
const ASN1_TYPE_TAG_UTF8STRING : u8 = 0x0C ;
27
32
const ASN1_TYPE_TAG_SEQUENCE : u8 = 0x10 ;
@@ -272,19 +277,35 @@ fn serialize_der_recursive<'shape, 'w, W: Asn1Write>(
272
277
serializer. serialize_str ( tag. unwrap_or ( ASN1_TYPE_TAG_UTF8STRING ) , value) ;
273
278
Ok ( ( ) )
274
279
}
280
+ #[ cfg( feature = "const-oid" ) ]
281
+ ScalarAffinity :: OID ( _) => {
282
+ let value = pv. get :: < ObjectIdentifier > ( ) . unwrap ( ) ;
283
+ serializer. serialize_tlv (
284
+ tag. unwrap_or ( ASN1_TYPE_TAG_OBJECT_IDENTIFIER ) ,
285
+ value. as_bytes ( ) ,
286
+ ) ;
287
+ Ok ( ( ) )
288
+ }
275
289
_ => Err ( Asn1SerError :: UnsupportedShape ) ,
276
290
} ,
277
- ( Def :: List ( _) , _) => {
278
- let pv = pv. into_list ( ) . unwrap ( ) ;
279
- let mut value = Vec :: new ( ) ;
280
- for pv in pv. iter ( ) {
281
- let mut inner_serializer = DerSerializer { writer : & mut value } ;
282
- serialize_der_recursive ( pv, & mut inner_serializer, None ) ?;
291
+ ( Def :: List ( ld) , _) => {
292
+ if ld. t ( ) . is_type :: < u8 > ( ) && shape. is_type :: < Vec < u8 > > ( ) {
293
+ serializer. serialize_tlv (
294
+ tag. unwrap_or ( ASN1_TYPE_TAG_OCTET_STRING ) ,
295
+ pv. get :: < Vec < u8 > > ( ) . unwrap ( ) ,
296
+ ) ;
297
+ } else {
298
+ let pv = pv. into_list ( ) . unwrap ( ) ;
299
+ let mut value = Vec :: new ( ) ;
300
+ for pv in pv. iter ( ) {
301
+ let mut inner_serializer = DerSerializer { writer : & mut value } ;
302
+ serialize_der_recursive ( pv, & mut inner_serializer, None ) ?;
303
+ }
304
+ serializer. serialize_tlv (
305
+ tag. unwrap_or ( ASN1_TYPE_TAG_SEQUENCE | ASN1_FORM_CONSTRUCTED ) ,
306
+ & value,
307
+ ) ;
283
308
}
284
- serializer. serialize_tlv (
285
- tag. unwrap_or ( ASN1_TYPE_TAG_SEQUENCE | ASN1_FORM_CONSTRUCTED ) ,
286
- & value,
287
- ) ;
288
309
Ok ( ( ) )
289
310
}
290
311
( Def :: Option ( _) , _) => {
@@ -409,6 +430,14 @@ pub enum Asn1DeserError {
409
430
/// Underlying UTF-8 error
410
431
source : core:: str:: Utf8Error ,
411
432
} ,
433
+ #[ cfg( feature = "const-oid" ) ]
434
+ /// Invalid OID
435
+ InvalidOid {
436
+ /// Position of this error in bytes
437
+ position : usize ,
438
+ /// Underlying const-oid error
439
+ source : const_oid:: Error ,
440
+ } ,
412
441
/// Sequence length didn't match content length
413
442
SequenceSizeMismatch {
414
443
/// Position of the end of the sequence in bytes
@@ -446,6 +475,10 @@ impl core::fmt::Display for Asn1DeserError {
446
475
Asn1DeserError :: InvalidString { position, .. } => {
447
476
write ! ( f, "Invalid string at byte {}" , position)
448
477
}
478
+ #[ cfg( feature = "const-oid" ) ]
479
+ Asn1DeserError :: InvalidOid { position, .. } => {
480
+ write ! ( f, "Invalid OID at byte {}" , position)
481
+ }
449
482
Asn1DeserError :: SequenceSizeMismatch {
450
483
sequence_end,
451
484
content_end,
@@ -465,6 +498,8 @@ impl core::error::Error for Asn1DeserError {
465
498
match self {
466
499
Asn1DeserError :: TypeTag ( source) => Some ( source) ,
467
500
Asn1DeserError :: InvalidString { source, .. } => Some ( source) ,
501
+ #[ cfg( feature = "const-oid" ) ]
502
+ Asn1DeserError :: InvalidOid { source, .. } => Some ( source) ,
468
503
_ => None ,
469
504
}
470
505
}
@@ -518,11 +553,18 @@ fn ber_tag_for_shape(shape: &Shape<'_>) -> Result<Option<u8>, Asn1DeserError> {
518
553
_ => Err ( Asn1DeserError :: UnsupportedShape ) ,
519
554
} ,
520
555
ScalarAffinity :: String ( _) => Ok ( Some ( type_tag. unwrap_or ( ASN1_TYPE_TAG_UTF8STRING ) ) ) ,
556
+ ScalarAffinity :: OID ( _) => Ok ( Some ( type_tag. unwrap_or ( ASN1_TYPE_TAG_OBJECT_IDENTIFIER ) ) ) ,
521
557
_ => Err ( Asn1DeserError :: UnsupportedShape ) ,
522
558
} ,
523
- ( Def :: List ( _) , _) => Ok ( Some (
524
- type_tag. unwrap_or ( ASN1_TYPE_TAG_SEQUENCE ) | ASN1_FORM_CONSTRUCTED ,
525
- ) ) ,
559
+ ( Def :: List ( ld) , _) => {
560
+ if ld. t ( ) . is_type :: < u8 > ( ) && shape. is_type :: < Vec < u8 > > ( ) {
561
+ Ok ( Some ( type_tag. unwrap_or ( ASN1_TYPE_TAG_OCTET_STRING ) ) )
562
+ } else {
563
+ Ok ( Some (
564
+ type_tag. unwrap_or ( ASN1_TYPE_TAG_SEQUENCE ) | ASN1_FORM_CONSTRUCTED ,
565
+ ) )
566
+ }
567
+ }
526
568
( Def :: Option ( od) , _) => Ok ( type_tag. or ( ber_tag_for_shape ( od. t ) ?) ) ,
527
569
( _, Type :: User ( ut) ) => match ut {
528
570
UserType :: Struct ( st) => match st. kind {
@@ -730,14 +772,31 @@ impl<'shape, 'input> Asn1DeserializerStack<'input> {
730
772
wip. set ( value. to_string ( ) ) . unwrap ( ) ;
731
773
Ok ( wip)
732
774
}
775
+ #[ cfg( feature = "const-oid" ) ]
776
+ ScalarAffinity :: OID ( _) => {
777
+ let bytes = self . next_tlv ( tag_for_shape. unwrap ( ) ) ?;
778
+ let value = ObjectIdentifier :: from_bytes ( bytes) . map_err ( |source| {
779
+ Asn1DeserError :: InvalidOid {
780
+ position : self . pos ,
781
+ source,
782
+ }
783
+ } ) ?;
784
+ wip. set ( value) . unwrap ( ) ;
785
+ Ok ( wip)
786
+ }
733
787
_ => Err ( Asn1DeserError :: UnsupportedShape ) ,
734
788
} ,
735
789
( Def :: List ( _) , _) => {
736
- let len = self . next_tl ( tag_for_shape. unwrap ( ) ) ?;
737
- self . stack . push ( DeserializeTask :: Pop ( PopReason :: ListVal {
738
- end : self . pos + len,
739
- } ) ) ;
740
- self . stack . push ( DeserializeTask :: Value { with_tag : None } ) ;
790
+ if shape. is_type :: < Vec < u8 > > ( ) {
791
+ let bytes = self . next_tlv ( tag_for_shape. unwrap ( ) ) ?;
792
+ wip. set ( bytes. to_vec ( ) ) . unwrap ( ) ;
793
+ } else {
794
+ let len = self . next_tl ( tag_for_shape. unwrap ( ) ) ?;
795
+ self . stack . push ( DeserializeTask :: Pop ( PopReason :: ListVal {
796
+ end : self . pos + len,
797
+ } ) ) ;
798
+ self . stack . push ( DeserializeTask :: Value { with_tag : None } ) ;
799
+ }
741
800
Ok ( wip)
742
801
}
743
802
( Def :: Option ( od) , _) => {
0 commit comments