rasn1 0.10.0 → 0.12.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/rasn1/errors.rb +54 -0
- data/lib/rasn1/model.rb +251 -123
- data/lib/rasn1/types/any.rb +4 -0
- data/lib/rasn1/types/base.rb +47 -27
- data/lib/rasn1/types/bit_string.rb +11 -8
- data/lib/rasn1/types/bmp_string.rb +30 -0
- data/lib/rasn1/types/choice.rb +8 -10
- data/lib/rasn1/types/constrained.rb +55 -0
- data/lib/rasn1/types/constructed.rb +17 -1
- data/lib/rasn1/types/generalized_time.rb +29 -42
- data/lib/rasn1/types/ia5string.rb +2 -2
- data/lib/rasn1/types/integer.rb +2 -1
- data/lib/rasn1/types/null.rb +4 -0
- data/lib/rasn1/types/numeric_string.rb +1 -1
- data/lib/rasn1/types/printable_string.rb +1 -1
- data/lib/rasn1/types/sequence_of.rb +1 -1
- data/lib/rasn1/types/utc_time.rb +3 -7
- data/lib/rasn1/types/utf8_string.rb +2 -2
- data/lib/rasn1/types.rb +41 -6
- data/lib/rasn1/version.rb +1 -1
- data/lib/rasn1/wrapper.rb +201 -0
- data/lib/rasn1.rb +5 -27
- metadata +10 -34
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 552859c3f49caec5374c8db4459ad23e1f9c43e930b0d6511cab8f997c798d20
|
4
|
+
data.tar.gz: 29eaf2fc529b470c9bc6283efbaf82e580d5b4b86d5c46920ee4a882a18b0d72
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9e5df0e417db7e1f02accae9cc4f17b4a49975d1dc17b716dbf587bb3f5e8ca68ed842d22358d7de037041255c164df5a92c6ada52adba944f0ac635793a64b1
|
7
|
+
data.tar.gz: e193284ea13ca5f80a460b8b390839a0283a8424ca8201f24cbd6113919399fcd5b83a2fc39dd5b26925187e19930a1aceccb1485255de8301435e20a2c82761
|
data/lib/rasn1/errors.rb
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RASN1
|
4
|
+
# Base error class
|
5
|
+
class Error < StandardError; end
|
6
|
+
|
7
|
+
# ASN.1 encoding/decoding error
|
8
|
+
class ASN1Error < Error; end
|
9
|
+
|
10
|
+
# ASN.1 class error
|
11
|
+
class ClassError < Error
|
12
|
+
# @return [String]
|
13
|
+
def message
|
14
|
+
"Tag class should be a symbol among: #{Types::Base::CLASSES.keys.join(', ')}"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# Enumerated error
|
19
|
+
class EnumeratedError < Error; end
|
20
|
+
|
21
|
+
# CHOICE error: #chosen not set
|
22
|
+
class ChoiceError < RASN1::Error
|
23
|
+
# @param [Types::Base] object
|
24
|
+
def initialize(object)
|
25
|
+
@object = object
|
26
|
+
super()
|
27
|
+
end
|
28
|
+
|
29
|
+
def message
|
30
|
+
"CHOICE #{@object.name}: #chosen not set"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# Exception raised when a constraint is not verified on a constrained type.
|
35
|
+
# @version 0.11.0
|
36
|
+
# @author Sylvain Daubert
|
37
|
+
class ConstraintError < Error
|
38
|
+
# @param [Types::Base] object
|
39
|
+
def initialize(object)
|
40
|
+
@object = object
|
41
|
+
super()
|
42
|
+
end
|
43
|
+
|
44
|
+
# @return [String]
|
45
|
+
def message
|
46
|
+
"Constraint not verified on #{@object.inspect}"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# Exception raised when model validation fails
|
51
|
+
# @since 0.12.0
|
52
|
+
class ModelValidationError < Error
|
53
|
+
end
|
54
|
+
end
|
data/lib/rasn1/model.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative 'types/constrained'
|
4
|
+
|
3
5
|
module RASN1
|
4
6
|
# @abstract
|
5
7
|
# {Model} class is a base class to define ASN.1 models.
|
@@ -18,6 +20,8 @@ module RASN1
|
|
18
20
|
# integer(:house, explicit: 1, default: 0)])
|
19
21
|
# end
|
20
22
|
#
|
23
|
+
# In a model, each element must have a unique name.
|
24
|
+
#
|
21
25
|
# === Parse a DER-encoded string
|
22
26
|
# record = Record.parse(der_string)
|
23
27
|
# record[:id] # => RASN1::Types::Integer
|
@@ -58,11 +62,38 @@ module RASN1
|
|
58
62
|
# All methods defined by root may be delegated by model, unless model also defines
|
59
63
|
# this method.
|
60
64
|
# @author Sylvain Daubert
|
65
|
+
# @author adfoster-r7 ModelValidationError, track source location for dynamic class methods
|
61
66
|
class Model # rubocop:disable Metrics/ClassLength
|
62
67
|
# @private
|
63
|
-
Elem = Struct.new(:name, :proc_or_class, :content)
|
68
|
+
Elem = Struct.new(:name, :proc_or_class, :content) do
|
69
|
+
def initialize(name, proc_or_class, content)
|
70
|
+
if content.is_a?(Array)
|
71
|
+
duplicate_names = find_all_duplicate_names(content.map(&:name) + [name])
|
72
|
+
raise ModelValidationError, "Duplicate name #{duplicate_names.first} found" if duplicate_names.any?
|
73
|
+
end
|
74
|
+
|
75
|
+
super
|
76
|
+
end
|
64
77
|
|
65
|
-
|
78
|
+
private
|
79
|
+
|
80
|
+
# @param [Array<String>] names
|
81
|
+
# @return [Array<String>] The duplicate names found in the array
|
82
|
+
def find_all_duplicate_names(names)
|
83
|
+
names.group_by { |name| name }
|
84
|
+
.select { |_name, values| values.length > 1 }
|
85
|
+
.keys
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
# @private
|
90
|
+
WrapElem = Struct.new(:element, :options) do
|
91
|
+
def name
|
92
|
+
"#{element.name}_wrapper"
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
module Accel
|
66
97
|
# @return [Hash]
|
67
98
|
attr_reader :options
|
68
99
|
|
@@ -74,6 +105,15 @@ module RASN1
|
|
74
105
|
@root = Elem.new(name, model_klass, nil)
|
75
106
|
end
|
76
107
|
|
108
|
+
# Use a {Wrapper} around a {Types::Base} or a {Model} object
|
109
|
+
# @param [Types::Base,Model] element
|
110
|
+
# @param [Hash] options
|
111
|
+
# @return [WrapElem]
|
112
|
+
# @since 0.12
|
113
|
+
def wrapper(element, options={})
|
114
|
+
@root = WrapElem.new(element, options)
|
115
|
+
end
|
116
|
+
|
77
117
|
# Update options of root element.
|
78
118
|
# May be used when subclassing.
|
79
119
|
# class Model1 < RASN1::Model
|
@@ -87,8 +127,13 @@ module RASN1
|
|
87
127
|
# end
|
88
128
|
# @param [Hash] options
|
89
129
|
# @return [void]
|
130
|
+
# @since 0.12.0 may change name through +:name+
|
90
131
|
def root_options(options)
|
91
132
|
@options = options
|
133
|
+
return unless options.key?(:name)
|
134
|
+
|
135
|
+
@root = @root.dup
|
136
|
+
@root.name = options[:name]
|
92
137
|
end
|
93
138
|
|
94
139
|
# On inheritance, create +@root+ class variable
|
@@ -100,120 +145,44 @@ module RASN1
|
|
100
145
|
klass.class_eval { @root = root }
|
101
146
|
end
|
102
147
|
|
103
|
-
# @
|
104
|
-
#
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
# @param [Hash] options
|
116
|
-
# @return [Elem]
|
117
|
-
# @see Types::Choice#initialize
|
118
|
-
%w[sequence set choice].each do |type|
|
119
|
-
class_eval "def #{type}(name, options={})\n" \
|
120
|
-
" options.merge!(name: name)\n" \
|
121
|
-
" proc = proc do |opts|\n" \
|
122
|
-
" Types::#{type.capitalize}.new(options.merge(opts))\n" \
|
123
|
-
" end\n" \
|
124
|
-
" @root = Elem.new(name, proc, options[:content])\n" \
|
125
|
-
'end'
|
148
|
+
# @since 0.11.0
|
149
|
+
# @since 0.12.0 track source location on error (adfoster-r7)
|
150
|
+
def define_type_accel_base(accel_name, klass)
|
151
|
+
singleton_class.class_eval <<-EVAL, __FILE__, __LINE__ + 1
|
152
|
+
def #{accel_name}(name, options={}) # def sequence(name, type, options)
|
153
|
+
options[:name] = name
|
154
|
+
proc = proc do |opts|
|
155
|
+
#{klass}.new(options.merge(opts)) # Sequence.new(options.merge(opts))
|
156
|
+
end
|
157
|
+
@root = Elem.new(name, proc, options[:content])
|
158
|
+
end
|
159
|
+
EVAL
|
126
160
|
end
|
127
161
|
|
128
|
-
# @
|
129
|
-
#
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
%w[sequence set].each do |type|
|
141
|
-
klass_name = "Types::#{type.capitalize}Of"
|
142
|
-
class_eval "def #{type}_of(name, type, options={})\n" \
|
143
|
-
" options.merge!(name: name)\n" \
|
144
|
-
" proc = proc do |opts|\n" \
|
145
|
-
" #{klass_name}.new(type, options.merge(opts))\n" \
|
146
|
-
" end\n" \
|
147
|
-
" @root = Elem.new(name, proc, nil)\n" \
|
148
|
-
'end'
|
162
|
+
# @since 0.11.0
|
163
|
+
# @since 0.12.0 track source location on error (adfoster-r7)
|
164
|
+
def define_type_accel_of(accel_name, klass)
|
165
|
+
singleton_class.class_eval <<-EVAL, __FILE__, __LINE__ + 1
|
166
|
+
def #{accel_name}_of(name, type, options={}) # def sequence_of(name, type, options)
|
167
|
+
options[:name] = name
|
168
|
+
proc = proc do |opts|
|
169
|
+
#{klass}.new(type, options.merge(opts)) # SequenceOf.new(type, options.merge(opts))
|
170
|
+
end
|
171
|
+
@root = Elem.new(name, proc, nil)
|
172
|
+
end
|
173
|
+
EVAL
|
149
174
|
end
|
150
175
|
|
151
|
-
#
|
152
|
-
#
|
153
|
-
#
|
154
|
-
#
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
# @method bit_string(name, options)
|
162
|
-
# @param [Symbol,String] name name of object in model
|
163
|
-
# @param [Hash] options
|
164
|
-
# @return [Elem]
|
165
|
-
# @see Types::BitString#initialize
|
166
|
-
# @method octet_string(name, options)
|
167
|
-
# @param [Symbol,String] name name of object in model
|
168
|
-
# @param [Hash] options
|
169
|
-
# @return [Elem]
|
170
|
-
# @see Types::OctetString#initialize
|
171
|
-
# @method null(name, options)
|
172
|
-
# @param [Symbol,String] name name of object in model
|
173
|
-
# @param [Hash] options
|
174
|
-
# @return [Elem]
|
175
|
-
# @see Types::Null#initialize
|
176
|
-
# @method enumerated(name, options)
|
177
|
-
# @param [Symbol,String] name name of object in model
|
178
|
-
# @param [Hash] options
|
179
|
-
# @return [Elem]
|
180
|
-
# @see Types::Enumerated#initialize
|
181
|
-
# @method utf8_string(name, options)
|
182
|
-
# @param [Symbol,String] name name of object in model
|
183
|
-
# @param [Hash] options
|
184
|
-
# @return [Elem]
|
185
|
-
# @see Types::Utf8String#initialize
|
186
|
-
# @method numeric_string(name, options)
|
187
|
-
# @param [Symbol,String] name name of object in model
|
188
|
-
# @param [Hash] options
|
189
|
-
# @return [Elem]
|
190
|
-
# @see Types::NumericString#initialize
|
191
|
-
# @method printable_string(name, options)
|
192
|
-
# @param [Symbol,String] name name of object in model
|
193
|
-
# @param [Hash] options
|
194
|
-
# @return [Elem]
|
195
|
-
# @see Types::PrintableString#initialize
|
196
|
-
# @method visible_string(name, options)
|
197
|
-
# @param [Symbol,String] name name of object in model
|
198
|
-
# @param [Hash] options
|
199
|
-
# @return [Elem]
|
200
|
-
# @see Types::VisibleString#initialize
|
201
|
-
# @method ia5_string(name, options)
|
202
|
-
# @param [Symbol,String] name name of object in model
|
203
|
-
# @param [Hash] options
|
204
|
-
# @return [Elem]
|
205
|
-
# @see Types::IA5String#initialize
|
206
|
-
Types.primitives.each do |prim|
|
207
|
-
next if prim == Types::ObjectId
|
208
|
-
|
209
|
-
method_name = prim.type.gsub(/([a-z0-9])([A-Z])/, '\1_\2').downcase.gsub(/\s+/, '_')
|
210
|
-
class_eval "def #{method_name}(name, options={})\n" \
|
211
|
-
" options.merge!(name: name)\n" \
|
212
|
-
" proc = proc do |opts|\n" \
|
213
|
-
" #{prim}.new(options.merge(opts))\n" \
|
214
|
-
" end\n" \
|
215
|
-
" @root = Elem.new(name, proc, nil)\n" \
|
216
|
-
'end'
|
176
|
+
# Define an accelarator to access a type in a model definition
|
177
|
+
# @param [String] accel_name
|
178
|
+
# @param [Class] klass
|
179
|
+
# @since 0.11.0
|
180
|
+
def define_type_accel(accel_name, klass)
|
181
|
+
if klass < Types::SequenceOf
|
182
|
+
define_type_accel_of(accel_name, klass)
|
183
|
+
else
|
184
|
+
define_type_accel_base(accel_name, klass)
|
185
|
+
end
|
217
186
|
end
|
218
187
|
|
219
188
|
# @param [Symbol,String] name name of object in model
|
@@ -258,11 +227,126 @@ module RASN1
|
|
258
227
|
end
|
259
228
|
end
|
260
229
|
|
230
|
+
extend Accel
|
231
|
+
|
232
|
+
# @!method sequence(name, options)
|
233
|
+
# @!scope class
|
234
|
+
# @param [Symbol,String] name name of object in model
|
235
|
+
# @param [Hash] options
|
236
|
+
# @return [Elem]
|
237
|
+
# @see Types::Sequence#initialize
|
238
|
+
# @!method set(name, options)
|
239
|
+
# @!scope class
|
240
|
+
# @param [Symbol,String] name name of object in model
|
241
|
+
# @param [Hash] options
|
242
|
+
# @return [Elem]
|
243
|
+
# @see Types::Set#initialize
|
244
|
+
# @!method choice(name, options)
|
245
|
+
# @!scope class
|
246
|
+
# @param [Symbol,String] name name of object in model
|
247
|
+
# @param [Hash] options
|
248
|
+
# @return [Elem]
|
249
|
+
# @see Types::Choice#initialize
|
250
|
+
%w[sequence set choice].each do |type|
|
251
|
+
self.define_type_accel_base(type, Types.const_get(type.capitalize))
|
252
|
+
end
|
253
|
+
|
254
|
+
# @!method sequence_of(name, type, options)
|
255
|
+
# @!scope class
|
256
|
+
# @param [Symbol,String] name name of object in model
|
257
|
+
# @param [Model, Types::Base] type type for SEQUENCE OF
|
258
|
+
# @param [Hash] options
|
259
|
+
# @return [Elem]
|
260
|
+
# @see Types::SequenceOf#initialize
|
261
|
+
# @!method set_of(name, type, options)
|
262
|
+
# @!scope class
|
263
|
+
# @param [Symbol,String] name name of object in model
|
264
|
+
# @param [Model, Types::Base] type type for SET OF
|
265
|
+
# @param [Hash] options
|
266
|
+
# @return [Elem]
|
267
|
+
# @see Types::SetOf#initialize
|
268
|
+
%w[sequence set].each do |type|
|
269
|
+
define_type_accel_of(type, Types.const_get("#{type.capitalize}Of"))
|
270
|
+
end
|
271
|
+
|
272
|
+
# @!method boolean(name, options)
|
273
|
+
# @!scope class
|
274
|
+
# @param [Symbol,String] name name of object in model
|
275
|
+
# @param [Hash] options
|
276
|
+
# @return [Elem]
|
277
|
+
# @see Types::Boolean#initialize
|
278
|
+
# @!method integer(name, options)
|
279
|
+
# @!scope class
|
280
|
+
# @param [Symbol,String] name name of object in model
|
281
|
+
# @param [Hash] options
|
282
|
+
# @return [Elem]
|
283
|
+
# @see Types::Integer#initialize
|
284
|
+
# @!method bit_string(name, options)
|
285
|
+
# @!scope class
|
286
|
+
# @param [Symbol,String] name name of object in model
|
287
|
+
# @param [Hash] options
|
288
|
+
# @return [Elem]
|
289
|
+
# @see Types::BitString#initialize
|
290
|
+
# @!method octet_string(name, options)
|
291
|
+
# @!scope class
|
292
|
+
# @param [Symbol,String] name name of object in model
|
293
|
+
# @param [Hash] options
|
294
|
+
# @return [Elem]
|
295
|
+
# @see Types::OctetString#initialize
|
296
|
+
# @!method null(name, options)
|
297
|
+
# @!scope class
|
298
|
+
# @param [Symbol,String] name name of object in model
|
299
|
+
# @param [Hash] options
|
300
|
+
# @return [Elem]
|
301
|
+
# @see Types::Null#initialize
|
302
|
+
# @!method enumerated(name, options)
|
303
|
+
# @!scope class
|
304
|
+
# @param [Symbol,String] name name of object in model
|
305
|
+
# @param [Hash] options
|
306
|
+
# @return [Elem]
|
307
|
+
# @see Types::Enumerated#initialize
|
308
|
+
# @!method utf8_string(name, options)
|
309
|
+
# @!scope class
|
310
|
+
# @param [Symbol,String] name name of object in model
|
311
|
+
# @param [Hash] options
|
312
|
+
# @return [Elem]
|
313
|
+
# @see Types::Utf8String#initialize
|
314
|
+
# @!method numeric_string(name, options)
|
315
|
+
# @!scope class
|
316
|
+
# @param [Symbol,String] name name of object in model
|
317
|
+
# @param [Hash] options
|
318
|
+
# @return [Elem]
|
319
|
+
# @see Types::NumericString#initialize
|
320
|
+
# @!method printable_string(name, options)
|
321
|
+
# @!scope class
|
322
|
+
# @param [Symbol,String] name name of object in model
|
323
|
+
# @param [Hash] options
|
324
|
+
# @return [Elem]
|
325
|
+
# @see Types::PrintableString#initialize
|
326
|
+
# @!method visible_string(name, options)
|
327
|
+
# @!scope class
|
328
|
+
# @param [Symbol,String] name name of object in model
|
329
|
+
# @param [Hash] options
|
330
|
+
# @return [Elem]
|
331
|
+
# @see Types::VisibleString#initialize
|
332
|
+
# @!method ia5_string(name, options)
|
333
|
+
# @!scope class
|
334
|
+
# @param [Symbol,String] name name of object in model
|
335
|
+
# @param [Hash] options
|
336
|
+
# @return [Elem]
|
337
|
+
# @see Types::IA5String#initialize
|
338
|
+
Types.primitives.each do |prim|
|
339
|
+
next if prim == Types::ObjectId
|
340
|
+
|
341
|
+
method_name = prim.type.gsub(/([a-z0-9])([A-Z])/, '\1_\2').downcase.gsub(/\s+/, '_')
|
342
|
+
self.define_type_accel_base(method_name, prim)
|
343
|
+
end
|
344
|
+
|
261
345
|
# Create a new instance of a {Model}
|
262
346
|
# @param [Hash] args
|
263
347
|
def initialize(args={})
|
264
348
|
root = generate_root
|
265
|
-
|
349
|
+
generate_elements(root)
|
266
350
|
initialize_elements(self, args)
|
267
351
|
end
|
268
352
|
|
@@ -273,7 +357,7 @@ module RASN1
|
|
273
357
|
@elements[name]
|
274
358
|
end
|
275
359
|
|
276
|
-
# Set value of element +name+. Element should be a {Base}.
|
360
|
+
# Set value of element +name+. Element should be a {Types::Base}.
|
277
361
|
# @param [String,Symbol] name
|
278
362
|
# @param [Object] value
|
279
363
|
# @return [Object] value
|
@@ -425,7 +509,7 @@ module RASN1
|
|
425
509
|
when Proc
|
426
510
|
proc_or_class.call(options)
|
427
511
|
when Class
|
428
|
-
proc_or_class.new
|
512
|
+
proc_or_class.new(options)
|
429
513
|
end
|
430
514
|
end
|
431
515
|
|
@@ -437,14 +521,33 @@ module RASN1
|
|
437
521
|
class_element
|
438
522
|
end
|
439
523
|
|
440
|
-
def
|
524
|
+
def generate_elements(element)
|
525
|
+
if element.is_a?(WrapElem)
|
526
|
+
generate_wrapper(element)
|
527
|
+
return
|
528
|
+
end
|
441
529
|
return unless element.content.is_a? Array
|
442
530
|
|
443
531
|
@elements[name].value = element.content.map do |another_element|
|
444
|
-
|
445
|
-
|
446
|
-
|
532
|
+
add_subelement(another_element)
|
533
|
+
end
|
534
|
+
end
|
535
|
+
|
536
|
+
def generate_wrapper(wrap_elem)
|
537
|
+
inner_elem = wrap_elem.element
|
538
|
+
subel = add_subelement(inner_elem)
|
539
|
+
Wrapper.new(subel, wrap_elem.options)
|
540
|
+
end
|
541
|
+
|
542
|
+
def add_subelement(subelement)
|
543
|
+
case subelement
|
544
|
+
when Elem
|
545
|
+
subel = get_type(subelement.proc_or_class)
|
546
|
+
@elements[subelement.name] = subel
|
547
|
+
generate_elements(subelement) if composed?(subel) && subelement.content.is_a?(Array)
|
447
548
|
subel
|
549
|
+
when WrapElem
|
550
|
+
generate_wrapper(subelement)
|
448
551
|
end
|
449
552
|
end
|
450
553
|
|
@@ -454,7 +557,7 @@ module RASN1
|
|
454
557
|
|
455
558
|
case value
|
456
559
|
when Hash
|
457
|
-
raise ArgumentError, "element #{name}: may only pass a Hash for Model elements" unless obj[name].is_a?
|
560
|
+
raise ArgumentError, "element #{name}: may only pass a Hash for Model elements" unless obj[name].is_a?(Model)
|
458
561
|
|
459
562
|
initialize_elements obj[name], value
|
460
563
|
when Array
|
@@ -476,7 +579,7 @@ module RASN1
|
|
476
579
|
end
|
477
580
|
end
|
478
581
|
|
479
|
-
def private_to_h(element=nil)
|
582
|
+
def private_to_h(element=nil) # rubocop:disable Metrics/CyclomaticComplexity
|
480
583
|
my_element = element || root
|
481
584
|
my_element = my_element.root if my_element.is_a?(Model)
|
482
585
|
value = case my_element
|
@@ -484,6 +587,13 @@ module RASN1
|
|
484
587
|
sequence_of_to_h(my_element)
|
485
588
|
when Types::Sequence
|
486
589
|
sequence_to_h(my_element)
|
590
|
+
# @author adfoster-r7
|
591
|
+
when Types::Choice
|
592
|
+
raise ChoiceError.new(my_element) if my_element.chosen.nil?
|
593
|
+
|
594
|
+
private_to_h(my_element.value[my_element.chosen])
|
595
|
+
when Wrapper
|
596
|
+
wrapper_to_h(my_element)
|
487
597
|
else
|
488
598
|
my_element.value
|
489
599
|
end
|
@@ -506,11 +616,29 @@ module RASN1
|
|
506
616
|
ary = seq.value.map do |el|
|
507
617
|
next if el.optional? && el.value.nil?
|
508
618
|
|
509
|
-
|
510
|
-
|
619
|
+
case el
|
620
|
+
when Model
|
621
|
+
hsh = el.to_h
|
622
|
+
hsh = hsh[hsh.keys.first]
|
623
|
+
[@elements.key(el), hsh]
|
624
|
+
when Wrapper
|
625
|
+
[@elements.key(el.element), wrapper_to_h(el)]
|
626
|
+
else
|
627
|
+
[el.name, private_to_h(el)]
|
628
|
+
end
|
511
629
|
end
|
512
630
|
ary.compact!
|
513
631
|
ary.to_h
|
514
632
|
end
|
633
|
+
|
634
|
+
def wrapper_to_h(wrap)
|
635
|
+
case wrap.element
|
636
|
+
when Model
|
637
|
+
hsh = wrap.element.to_h
|
638
|
+
hsh[hsh.keys.first]
|
639
|
+
else
|
640
|
+
private_to_h(wrap.element)
|
641
|
+
end
|
642
|
+
end
|
515
643
|
end
|
516
644
|
end
|