rasn1 0.14.0 → 0.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +13 -6
- data/lib/rasn1/model.rb +186 -146
- data/lib/rasn1/tracer.rb +4 -4
- data/lib/rasn1/types/any.rb +5 -3
- data/lib/rasn1/types/base.rb +49 -32
- data/lib/rasn1/types/bit_string.rb +12 -7
- data/lib/rasn1/types/bmp_string.rb +3 -11
- data/lib/rasn1/types/boolean.rb +16 -9
- data/lib/rasn1/types/choice.rb +43 -3
- data/lib/rasn1/types/constrained.rb +5 -2
- data/lib/rasn1/types/generalized_time.rb +32 -24
- data/lib/rasn1/types/ia5string.rb +3 -11
- data/lib/rasn1/types/integer.rb +13 -9
- data/lib/rasn1/types/null.rb +11 -6
- data/lib/rasn1/types/numeric_string.rb +13 -6
- data/lib/rasn1/types/object_id.rb +33 -21
- data/lib/rasn1/types/octet_string.rb +26 -0
- data/lib/rasn1/types/printable_string.rb +13 -6
- data/lib/rasn1/types/sequence.rb +16 -12
- data/lib/rasn1/types/sequence_of.rb +15 -11
- data/lib/rasn1/types/universal_string.rb +3 -11
- data/lib/rasn1/types/utc_time.rb +17 -7
- data/lib/rasn1/types/utf8_string.rb +3 -11
- data/lib/rasn1/types/visible_string.rb +14 -2
- data/lib/rasn1/types.rb +6 -5
- data/lib/rasn1/version.rb +2 -1
- data/lib/rasn1/wrapper.rb +72 -18
- data/lib/rasn1.rb +5 -2
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f4b0dda0fa6e06b6371e74782ecc5b5cc5f9d30dab886a759aa5b9345bd80908
|
4
|
+
data.tar.gz: cfad20040d45598fffda3132bb9c417cdf4fca9dd78dda9616a4b7a0a6a98b97
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a99c4ee238423b561470182c3ac415d9a9ff8f11d626af843d203d5c6aedff6969ec0e4b47f68844e4c62153dd238ba4d852f3855e63a091e8c2cf0643d39d89
|
7
|
+
data.tar.gz: 9614d3434f7b05fe01e80bb36cbd82914b565a6e5087e48bc5e44aa7f47d70076ac3b1f542062bf9bc203d8101f4afd21f2ad5b9865011cdff1359e8178c8b19
|
data/README.md
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
[](https://badge.fury.io/rb/rasn1)
|
2
|
-
[](https://github.com/lemontree55/rasn1/actions/workflows/ci.yml)
|
3
3
|
|
4
4
|
# Rasn1
|
5
5
|
|
@@ -15,11 +15,15 @@ gem 'rasn1'
|
|
15
15
|
|
16
16
|
And then execute:
|
17
17
|
|
18
|
-
|
18
|
+
```bash
|
19
|
+
bundle install
|
20
|
+
```
|
19
21
|
|
20
22
|
Or install it yourself as:
|
21
23
|
|
22
|
-
|
24
|
+
```bash
|
25
|
+
gem install rasn1
|
26
|
+
```
|
23
27
|
|
24
28
|
## Simple usage
|
25
29
|
|
@@ -31,9 +35,10 @@ decoded_ber = RASN1.parse(ber_string, ber: true)
|
|
31
35
|
```
|
32
36
|
|
33
37
|
## Advanced usage
|
38
|
+
|
34
39
|
All examples below will be based on:
|
35
40
|
|
36
|
-
```
|
41
|
+
```text
|
37
42
|
Record ::= SEQUENCE {
|
38
43
|
id INTEGER,
|
39
44
|
room [0] INTEGER OPTIONAL,
|
@@ -70,6 +75,7 @@ end
|
|
70
75
|
```
|
71
76
|
|
72
77
|
### Parse a DER-encoded string
|
78
|
+
|
73
79
|
```ruby
|
74
80
|
record = Record.parse(der_string)
|
75
81
|
record[:id] # => RASN1::Types::Integer
|
@@ -92,6 +98,7 @@ cplx_record[:a_record] # => Record
|
|
92
98
|
```
|
93
99
|
|
94
100
|
### Generate a DER-encoded string
|
101
|
+
|
95
102
|
```ruby
|
96
103
|
record = Record.new(id: 12)
|
97
104
|
record[:id].to_i # => 12
|
@@ -110,8 +117,8 @@ record.to_der # => String
|
|
110
117
|
|
111
118
|
### More information
|
112
119
|
|
113
|
-
see https://github.com/sdaubert/rasn1/wiki
|
120
|
+
see <https://github.com/sdaubert/rasn1/wiki>
|
114
121
|
|
115
122
|
## Contributing
|
116
123
|
|
117
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/sdaubert/rasn1
|
124
|
+
Bug reports and pull requests are welcome on GitHub at <https://github.com/sdaubert/rasn1>.
|
data/lib/rasn1/model.rb
CHANGED
@@ -1,7 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative 'types/constrained'
|
4
|
-
|
5
3
|
module RASN1
|
6
4
|
# @abstract
|
7
5
|
# {Model} class is a base class to define ASN.1 models.
|
@@ -64,39 +62,45 @@ module RASN1
|
|
64
62
|
# @author Sylvain Daubert
|
65
63
|
# @author adfoster-r7 ModelValidationError, track source location for dynamic class methods
|
66
64
|
class Model # rubocop:disable Metrics/ClassLength
|
67
|
-
# @private
|
68
|
-
|
65
|
+
# @private Base Element
|
66
|
+
BaseElem = Struct.new(:name, :proc, :content) do
|
69
67
|
# @param [String,Symbol] name
|
70
|
-
# @param [Proc
|
68
|
+
# @param [Proc] proc
|
71
69
|
# @param [Array,nil] content
|
72
|
-
def initialize(name,
|
73
|
-
|
74
|
-
duplicate_names = find_all_duplicate_names(content.map(&:name) + [name])
|
75
|
-
raise ModelValidationError, "Duplicate name #{duplicate_names.first} found" if duplicate_names.any?
|
76
|
-
end
|
77
|
-
|
70
|
+
def initialize(name, proc, content)
|
71
|
+
check_duplicates(content.map(&:name) + [name]) unless content.nil?
|
78
72
|
super
|
79
73
|
end
|
80
74
|
|
81
75
|
private
|
82
76
|
|
83
|
-
# @param [Array<String>] names
|
84
77
|
# @return [Array<String>] The duplicate names found in the array
|
85
78
|
def find_all_duplicate_names(names)
|
86
79
|
names.group_by { |name| name }
|
87
80
|
.select { |_name, values| values.length > 1 }
|
88
81
|
.keys
|
89
82
|
end
|
83
|
+
|
84
|
+
def check_duplicates(names)
|
85
|
+
duplicates = find_all_duplicate_names(names)
|
86
|
+
raise ModelValidationError, "Duplicate name #{duplicates.first} found" if duplicates.any?
|
87
|
+
end
|
90
88
|
end
|
91
89
|
|
92
|
-
# @private
|
90
|
+
# @private Model Element
|
91
|
+
ModelElem = Struct.new(:name, :klass)
|
92
|
+
|
93
|
+
# @private Wrapper Element
|
93
94
|
WrapElem = Struct.new(:element, :options) do
|
94
|
-
# @return [
|
95
|
+
# @return [Symbol]
|
95
96
|
def name
|
96
|
-
"#{element.name}_wrapper"
|
97
|
+
:"#{element.name}_wrapper"
|
97
98
|
end
|
98
99
|
end
|
99
100
|
|
101
|
+
# @private Sequence types
|
102
|
+
SEQUENCE_TYPES = [Types::Sequence, Types::SequenceOf, Types::Set, Types::SetOf].freeze
|
103
|
+
|
100
104
|
# Define helper methods to define models
|
101
105
|
module Accel
|
102
106
|
# @return [Hash]
|
@@ -107,7 +111,7 @@ module RASN1
|
|
107
111
|
# @param [Class] model_klass
|
108
112
|
# @return [Elem]
|
109
113
|
def model(name, model_klass)
|
110
|
-
@root =
|
114
|
+
@root = ModelElem.new(name, model_klass)
|
111
115
|
end
|
112
116
|
|
113
117
|
# Use a {Wrapper} around a {Types::Base} or a {Model} object
|
@@ -162,7 +166,7 @@ module RASN1
|
|
162
166
|
proc = proc do |opts|
|
163
167
|
#{klass}.new(options.merge(opts)) # Sequence.new(options.merge(opts))
|
164
168
|
end
|
165
|
-
@root =
|
169
|
+
@root = BaseElem.new(name, proc, options[:content])
|
166
170
|
end
|
167
171
|
EVAL
|
168
172
|
end
|
@@ -179,7 +183,7 @@ module RASN1
|
|
179
183
|
proc = proc do |opts|
|
180
184
|
#{klass}.new(type, options.merge(opts)) # SequenceOf.new(type, options.merge(opts))
|
181
185
|
end
|
182
|
-
@root =
|
186
|
+
@root = BaseElem.new(name, proc, nil)
|
183
187
|
end
|
184
188
|
EVAL
|
185
189
|
end
|
@@ -206,7 +210,7 @@ module RASN1
|
|
206
210
|
def objectid(name, options={})
|
207
211
|
options[:name] = name
|
208
212
|
proc = proc { |opts| Types::ObjectId.new(options.merge(opts)) }
|
209
|
-
@root =
|
213
|
+
@root = BaseElem.new(name, proc, nil)
|
210
214
|
end
|
211
215
|
|
212
216
|
# @param [Symbol,String] name name of object in model
|
@@ -216,7 +220,7 @@ module RASN1
|
|
216
220
|
def any(name, options={})
|
217
221
|
options[:name] = name
|
218
222
|
proc = proc { |opts| Types::Any.new(options.merge(opts)) }
|
219
|
-
@root =
|
223
|
+
@root = BaseElem.new(name, proc, nil)
|
220
224
|
end
|
221
225
|
|
222
226
|
# Give type name (aka class name)
|
@@ -366,19 +370,35 @@ module RASN1
|
|
366
370
|
self.define_type_accel_base(method_name, prim)
|
367
371
|
end
|
368
372
|
|
373
|
+
# @return [Model, Wrapper, Types::Base]
|
374
|
+
attr_reader :root
|
375
|
+
|
369
376
|
# Create a new instance of a {Model}
|
370
377
|
# @param [Hash] args
|
371
378
|
def initialize(args={})
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
end
|
376
|
-
|
377
|
-
#
|
378
|
-
#
|
379
|
-
#
|
380
|
-
|
381
|
-
|
379
|
+
@elements = {}
|
380
|
+
generate_root(args)
|
381
|
+
lazy_initialize(args) unless args.empty?
|
382
|
+
end
|
383
|
+
|
384
|
+
# @overload [](name)
|
385
|
+
# Access an element of the model by its name
|
386
|
+
# @param [Symbol] name
|
387
|
+
# @return [Model, Types::Base, Wrapper]
|
388
|
+
# @overload [](idx)
|
389
|
+
# Access an element of root element by its index. Root element must be a {Sequence} or {SequenceOf}.
|
390
|
+
# @param [Integer] idx
|
391
|
+
# @return [Model, Types::Base, Wrapper]
|
392
|
+
def [](name_or_idx)
|
393
|
+
case name_or_idx
|
394
|
+
when Symbol
|
395
|
+
elt = @elements[name_or_idx]
|
396
|
+
return elt unless elt.is_a?(Proc)
|
397
|
+
|
398
|
+
@elements[name_or_idx] = elt.call
|
399
|
+
when Integer
|
400
|
+
root[name_or_idx]
|
401
|
+
end
|
382
402
|
end
|
383
403
|
|
384
404
|
# Set value of element +name+. Element should be a {Types::Base}.
|
@@ -386,13 +406,20 @@ module RASN1
|
|
386
406
|
# @param [Object] value
|
387
407
|
# @return [Object] value
|
388
408
|
def []=(name, value)
|
389
|
-
|
409
|
+
# Here, use #[] to force generation for lazy elements
|
410
|
+
raise Error, 'cannot set value for a Model' if self[name].is_a?(Model)
|
411
|
+
|
412
|
+
self[name].value = value
|
413
|
+
end
|
390
414
|
|
391
|
-
|
415
|
+
# clone @elements and initialize @root from this new @element.
|
416
|
+
def initialize_copy(_other)
|
417
|
+
@elements = @elements.clone
|
418
|
+
@root = @elements[@root_name]
|
392
419
|
end
|
393
420
|
|
394
|
-
#
|
395
|
-
# @return [String
|
421
|
+
# Give model name (a.k.a root name)
|
422
|
+
# @return [String]
|
396
423
|
def name
|
397
424
|
@root_name
|
398
425
|
end
|
@@ -409,12 +436,6 @@ module RASN1
|
|
409
436
|
private_to_h
|
410
437
|
end
|
411
438
|
|
412
|
-
# Get root element from model
|
413
|
-
# @return [Types::Base,Model]
|
414
|
-
def root
|
415
|
-
@elements[@root_name]
|
416
|
-
end
|
417
|
-
|
418
439
|
# @return [String]
|
419
440
|
def to_der
|
420
441
|
root.to_der
|
@@ -427,12 +448,18 @@ module RASN1
|
|
427
448
|
end
|
428
449
|
|
429
450
|
# Parse a DER/BER encoded string, and modify object in-place.
|
430
|
-
# @param [String]
|
451
|
+
# @param [String] der
|
431
452
|
# @param [Boolean] ber accept BER encoding or not
|
432
453
|
# @return [Integer] number of parsed bytes
|
433
454
|
# @raise [ASN1Error] error on parsing
|
434
|
-
def parse!(
|
435
|
-
root.parse!(
|
455
|
+
def parse!(der, ber: false)
|
456
|
+
root.parse!(der, ber: ber)
|
457
|
+
end
|
458
|
+
|
459
|
+
# @private
|
460
|
+
# @see Types::Base#do_parse
|
461
|
+
def do_parse(der, ber: false)
|
462
|
+
root.do_parse(der, ber: ber)
|
436
463
|
end
|
437
464
|
|
438
465
|
# @overload value
|
@@ -474,11 +501,13 @@ module RASN1
|
|
474
501
|
end
|
475
502
|
end
|
476
503
|
|
504
|
+
# Return a hash image of model
|
505
|
+
# @return [Hash]
|
477
506
|
# Delegate some methods to root element
|
478
507
|
# @param [Symbol] meth
|
479
|
-
def method_missing(meth, *args)
|
480
|
-
if root.respond_to?
|
481
|
-
root.send
|
508
|
+
def method_missing(meth, *args, **kwargs)
|
509
|
+
if root.respond_to?(meth)
|
510
|
+
root.send(meth, *args, **kwargs)
|
482
511
|
else
|
483
512
|
super
|
484
513
|
end
|
@@ -491,7 +520,7 @@ module RASN1
|
|
491
520
|
|
492
521
|
# @return [String]
|
493
522
|
def inspect(level=0)
|
494
|
-
' ' * level
|
523
|
+
"#{' ' * level}(#{type}) #{root.inspect(-level)}"
|
495
524
|
end
|
496
525
|
|
497
526
|
# Objects are equal if they have same class AND same DER
|
@@ -503,127 +532,121 @@ module RASN1
|
|
503
532
|
|
504
533
|
protected
|
505
534
|
|
506
|
-
#
|
507
|
-
# @param [
|
508
|
-
# @return [
|
509
|
-
def
|
510
|
-
|
511
|
-
|
535
|
+
# Initialize model elements from +args+
|
536
|
+
# @param [Hash,Array] args
|
537
|
+
# @return [void]
|
538
|
+
def lazy_initialize(args)
|
539
|
+
case args
|
540
|
+
when Hash
|
541
|
+
lazy_initialize_hash(args)
|
542
|
+
when Array
|
543
|
+
lazy_initialize_array(args)
|
544
|
+
end
|
545
|
+
end
|
512
546
|
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
547
|
+
# Initialize an element from a hash
|
548
|
+
# @param [Hash] args
|
549
|
+
# @return [void]
|
550
|
+
def lazy_initialize_hash(args)
|
551
|
+
args.each do |name, value|
|
552
|
+
element = self[name]
|
553
|
+
case element
|
554
|
+
when Model
|
555
|
+
element.lazy_initialize(value)
|
556
|
+
when nil
|
557
|
+
else
|
558
|
+
element.value = value
|
518
559
|
end
|
519
560
|
end
|
520
|
-
|
521
|
-
nil
|
522
561
|
end
|
523
562
|
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
|
563
|
+
# Initialize an sequence element from an array
|
564
|
+
# @param [Array] args
|
565
|
+
# @return [void]
|
566
|
+
def lazy_initialize_array(ary)
|
567
|
+
raise Error, 'Only sequence types may be initialized with an array' unless SEQUENCE_TYPES.any? { |klass| root.is_a?(klass) }
|
529
568
|
|
530
|
-
|
531
|
-
|
532
|
-
# * class: a model
|
533
|
-
def get_type(proc_or_class, options={})
|
534
|
-
case proc_or_class
|
535
|
-
when Proc
|
536
|
-
proc_or_class.call(options)
|
537
|
-
when Class
|
538
|
-
proc_or_class.new(options)
|
569
|
+
ary.each do |initializer|
|
570
|
+
root << initializer
|
539
571
|
end
|
540
572
|
end
|
541
573
|
|
542
|
-
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
generate_wrapper(class_element)
|
549
|
-
else
|
550
|
-
get_type(class_element.proc_or_class, self.class.options || {})
|
551
|
-
end
|
552
|
-
class_element
|
553
|
-
end
|
554
|
-
|
555
|
-
def generate_elements(element)
|
556
|
-
if element.is_a?(WrapElem)
|
557
|
-
generate_wrapper(element)
|
558
|
-
return
|
559
|
-
end
|
560
|
-
return unless element.content.is_a? Array
|
574
|
+
# Give a (nested) element from its name
|
575
|
+
# @param [String, Symbol] name
|
576
|
+
# @return [Model, Types::Base, nil]
|
577
|
+
def by_name(name)
|
578
|
+
elt = self[name]
|
579
|
+
return elt unless elt.nil?
|
561
580
|
|
562
|
-
@elements
|
563
|
-
|
581
|
+
@elements.each_value do |subelt|
|
582
|
+
next unless subelt.is_a?(Model)
|
583
|
+
|
584
|
+
value = subelt.by_name(name)
|
585
|
+
return value unless value.nil?
|
564
586
|
end
|
565
|
-
end
|
566
587
|
|
567
|
-
|
568
|
-
inner_elem = wrap_elem.element
|
569
|
-
subel = add_subelement(inner_elem)
|
570
|
-
Wrapper.new(subel, wrap_elem.options)
|
588
|
+
nil
|
571
589
|
end
|
572
590
|
|
573
|
-
|
574
|
-
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
591
|
+
private
|
592
|
+
|
593
|
+
def generate_root(args)
|
594
|
+
opts = args.slice(:name, :explicit, :implicit, :optional, :class, :default, :constructed, :tag_value)
|
595
|
+
root = self.class.class_eval { @root }
|
596
|
+
root_options = self.class.options || {}
|
597
|
+
root_options.merge!(opts)
|
598
|
+
@root_name = args[:name] || root.name
|
599
|
+
@root = generate_element(root, root_options)
|
600
|
+
@elements[@root_name] = @root
|
601
|
+
end
|
602
|
+
|
603
|
+
def generate_element(elt, opts={})
|
604
|
+
case elt
|
605
|
+
when BaseElem
|
606
|
+
generate_base_element(elt, opts)
|
607
|
+
when ModelElem
|
608
|
+
opts[:name] ||= elt.name
|
609
|
+
elt.klass.new(opts)
|
580
610
|
when WrapElem
|
581
|
-
|
611
|
+
generate_wrapper_element(elt, opts)
|
582
612
|
end
|
583
613
|
end
|
584
614
|
|
585
|
-
def
|
586
|
-
|
587
|
-
|
588
|
-
|
589
|
-
|
590
|
-
|
591
|
-
|
592
|
-
|
593
|
-
|
594
|
-
initialize_elements(subobj, value)
|
595
|
-
when Array
|
596
|
-
initialize_element_from_array(subobj, value)
|
597
|
-
else
|
598
|
-
subobj.value = value
|
599
|
-
end
|
600
|
-
end
|
615
|
+
def generate_wrapper_element(elt, opts)
|
616
|
+
wrapped = elt.element.is_a?(ModelElem) ? elt.element.klass : generate_element(elt.element)
|
617
|
+
options = elt.options.merge(opts)
|
618
|
+
options[:name] = elt.element.name if elt.element.is_a?(ModelElem)
|
619
|
+
wrapper = Wrapper.new(wrapped, options)
|
620
|
+
# Use a proc as wrapper may be lazy
|
621
|
+
@elements[elt.element.name] = proc { wrapper.element }
|
622
|
+
wrapper
|
601
623
|
end
|
602
624
|
|
603
|
-
def
|
604
|
-
|
605
|
-
if
|
606
|
-
|
607
|
-
|
608
|
-
|
609
|
-
|
610
|
-
value.each { |el| composed << el }
|
625
|
+
def generate_base_element(elt, opts)
|
626
|
+
element = elt.proc.call(opts)
|
627
|
+
return element if elt.content.nil?
|
628
|
+
|
629
|
+
element.value = elt.content.map do |subel|
|
630
|
+
generated = generate_element(subel)
|
631
|
+
@elements[subel.name] = generated
|
611
632
|
end
|
633
|
+
element
|
612
634
|
end
|
613
635
|
|
636
|
+
# @author sdaubert
|
637
|
+
# @author lemontree55
|
638
|
+
# @author adfoster-r7
|
614
639
|
def private_to_h(element=nil) # rubocop:disable Metrics/CyclomaticComplexity
|
615
640
|
my_element = element || root
|
616
|
-
my_element = my_element.root if my_element.is_a?(Model)
|
617
641
|
value = case my_element
|
642
|
+
when Model
|
643
|
+
model_to_h(my_element)
|
618
644
|
when Types::SequenceOf
|
619
645
|
sequence_of_to_h(my_element)
|
620
646
|
when Types::Sequence
|
621
647
|
sequence_to_h(my_element)
|
622
|
-
# @author adfoster-r7
|
623
648
|
when Types::Choice
|
624
|
-
|
625
|
-
|
626
|
-
private_to_h(my_element.value[my_element.chosen])
|
649
|
+
choice_to_h(my_element)
|
627
650
|
when Wrapper
|
628
651
|
wrapper_to_h(my_element)
|
629
652
|
else
|
@@ -636,31 +659,48 @@ module RASN1
|
|
636
659
|
end
|
637
660
|
end
|
638
661
|
|
662
|
+
def model_to_h(elt)
|
663
|
+
hsh = elt.to_h
|
664
|
+
if root.is_a?(Types::Choice)
|
665
|
+
hsh[hsh.keys.first]
|
666
|
+
else
|
667
|
+
{ @elements.key(elt) => hsh[hsh.keys.first] }
|
668
|
+
end
|
669
|
+
end
|
670
|
+
|
639
671
|
def sequence_of_to_h(elt)
|
640
672
|
if elt.of_type < Model
|
641
|
-
elt.value
|
673
|
+
elt.value&.map { |el| el.to_h.values.first }
|
642
674
|
else
|
643
|
-
elt.value
|
675
|
+
elt.value&.map { |el| private_to_h(el) }
|
644
676
|
end
|
645
677
|
end
|
646
678
|
|
647
679
|
def sequence_to_h(seq)
|
648
|
-
ary = seq.value
|
680
|
+
ary = seq.value&.map do |el|
|
649
681
|
next if el.optional? && el.value.nil?
|
650
682
|
|
651
683
|
case el
|
652
684
|
when Model
|
653
|
-
|
654
|
-
hsh = hsh[hsh.keys.first]
|
655
|
-
[@elements.key(el), hsh]
|
685
|
+
model_to_h(el).to_a[0]
|
656
686
|
when Wrapper
|
657
|
-
[@elements.key(el
|
687
|
+
[unwrap_keyname(@elements.key(el)), wrapper_to_h(el)]
|
658
688
|
else
|
659
689
|
[el.name, private_to_h(el)]
|
660
690
|
end
|
661
691
|
end
|
662
|
-
ary.compact
|
663
|
-
|
692
|
+
ary.compact.to_h
|
693
|
+
end
|
694
|
+
|
695
|
+
def choice_to_h(elt)
|
696
|
+
raise ChoiceError.new(elt) if elt.chosen.nil?
|
697
|
+
|
698
|
+
chosen = elt.value[elt.chosen]
|
699
|
+
{ chosen.name => private_to_h(chosen) }
|
700
|
+
end
|
701
|
+
|
702
|
+
def unwrap_keyname(key)
|
703
|
+
key.to_s.delete_suffix('_wrapper').to_sym
|
664
704
|
end
|
665
705
|
|
666
706
|
def wrapper_to_h(wrap)
|
data/lib/rasn1/tracer.rb
CHANGED
@@ -83,8 +83,8 @@ module RASN1
|
|
83
83
|
# @private
|
84
84
|
# Parse +der+ with tracing abillity
|
85
85
|
# @see #parse!
|
86
|
-
def do_parse_with_tracing(der, ber)
|
87
|
-
ret = do_parse_without_tracing(der, ber)
|
86
|
+
def do_parse_with_tracing(der, ber:)
|
87
|
+
ret = do_parse_without_tracing(der, ber: ber)
|
88
88
|
RASN1.tracer.trace(self.trace)
|
89
89
|
ret
|
90
90
|
end
|
@@ -131,7 +131,7 @@ module RASN1
|
|
131
131
|
end
|
132
132
|
|
133
133
|
# @private
|
134
|
-
# Unpatch {#der_to_value
|
134
|
+
# Unpatch {#der_to_value} to remove tracing ability
|
135
135
|
def stop_tracing
|
136
136
|
alias_method :der_to_value, :der_to_value_without_tracing
|
137
137
|
end
|
@@ -156,7 +156,7 @@ module RASN1
|
|
156
156
|
end
|
157
157
|
|
158
158
|
# @private
|
159
|
-
# Unpatch {#der_to_value
|
159
|
+
# Unpatch {#der_to_value} to remove tracing ability
|
160
160
|
def stop_tracing
|
161
161
|
alias_method :der_to_value, :der_to_value_without_tracing
|
162
162
|
end
|
data/lib/rasn1/types/any.rb
CHANGED
@@ -31,7 +31,7 @@ module RASN1
|
|
31
31
|
# @param [Boolean] ber if +true+, accept BER encoding
|
32
32
|
# @return [Integer] total number of parsed bytes
|
33
33
|
def parse!(der, ber: false)
|
34
|
-
total_length, _data = do_parse(der, ber)
|
34
|
+
total_length, _data = do_parse(der, ber: ber)
|
35
35
|
total_length
|
36
36
|
end
|
37
37
|
|
@@ -70,7 +70,9 @@ module RASN1
|
|
70
70
|
str << '(ANY) '
|
71
71
|
end
|
72
72
|
|
73
|
-
|
73
|
+
# @private
|
74
|
+
# @see Types::Base#do_parse
|
75
|
+
def do_parse(der, ber: false)
|
74
76
|
if der.empty?
|
75
77
|
return [0, ''] if optional?
|
76
78
|
|
@@ -78,7 +80,7 @@ module RASN1
|
|
78
80
|
end
|
79
81
|
|
80
82
|
id_size = Types.decode_identifier_octets(der).last
|
81
|
-
total_length, = get_data(der[id_size
|
83
|
+
total_length, = get_data(der[id_size..], ber)
|
82
84
|
total_length += id_size
|
83
85
|
|
84
86
|
@no_value = false
|