rasn1 0.10.0 → 0.12.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/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
|