rasn1 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 66f3cf5edaaabbd17a920296e943f8e46f5de81c
4
- data.tar.gz: a83fb189ba31da35c1dc1743a01675fb3ac270d1
3
+ metadata.gz: 379d5a61021e3b58ffb46317f72905e9e3972044
4
+ data.tar.gz: 60bb0d280cccd6c999744045fb45f334863d46f4
5
5
  SHA512:
6
- metadata.gz: fa8459ba40745b387cdde298ff577707c63fd41ee4a2646b639878fcbb695638050910b94ec638ce7f010b8053140e30aa305a0634f3508c6fb8e6c7a8a337c7
7
- data.tar.gz: a7bc698f83d23585dfd75b27cc46429c9f2ec84b6c36d77980fbb3d0423b8ead411cd9a700a4700b2164e117d247837d54771e66a5f8aaf03fa198b1336cb9b7
6
+ metadata.gz: beb7960cfdef060b22f81dea31d7b93ece7781afad2b0a7db92606b860e8ff00ab1ae7991a86d5594b97b18b53c2888d6d83f11e4fe6e84abb33cfdddb491d75
7
+ data.tar.gz: 2fe8288bb99e4c21ead959855e3b0611c182abc6f2e23a8a60ff0babe7ebe62ef9a7795ec8f0512d50792f2e02278b192e8d62879c6f7815836ebb3c2c3287a0
data/README.md CHANGED
@@ -1,3 +1,5 @@
1
+ [![Gem Version](https://badge.fury.io/rb/rasn1.svg)](https://badge.fury.io/rb/rasn1)
2
+
1
3
  # Rasn1
2
4
 
3
5
  Rasn1 will be a ruby ASN.1 library to encode, parse and decode ASN.1 data in DER format.
@@ -47,7 +49,7 @@ class ComplexRecord < RASN1::Model
47
49
  sequence :cplx_record,
48
50
  content: [boolean(:bool),
49
51
  octet_string(:data, explicit: 0),
50
- Record]
52
+ model(:a_record, Record)]
51
53
  end
52
54
  ```
53
55
 
data/lib/rasn1/model.rb CHANGED
@@ -40,41 +40,94 @@ module RASN1
40
40
  # class Record2 < RASN1::Model
41
41
  # sequence(:record2,
42
42
  # content: [boolean(:rented, default: false),
43
- # Record])
43
+ # model(:a_record, Record)])
44
44
  # end
45
45
  # Set values like this:
46
46
  # record2 = Record2.new
47
47
  # record2[:rented] = true
48
- # record2[:record][:id] = 65537
49
- # record2[:record][:room] = 43
48
+ # record2[:a_record][:id] = 65537
49
+ # record2[:a_record][:room] = 43
50
50
  # or like this:
51
- # record2 = Record2.new(rented: true, record: { id: 65537, room: 43 })
51
+ # record2 = Record2.new(rented: true, a_record: { id: 65537, room: 43 })
52
52
  # @author Sylvain Daubert
53
53
  class Model
54
54
 
55
55
  class << self
56
56
 
57
- # Define a SEQUENCE type. Should be used to define a new subclass of {Model}.
58
- # @param [Hash] options
59
- # @option options [Array] :content
60
- # @see Types::Sequence#initialize
61
- # @return [Types::Sequence]
62
- def sequence(name, options={})
63
- @records ||= {}
64
- @records[name] = Proc.new do
65
- seq = Types::Sequence.new(name, options)
66
- seq.value = options[:content] if options[:content]
67
- seq
68
- end
57
+ # Use another model in this model
58
+ # @param [String,Symbol] name
59
+ # @param [Class] model_klass
60
+ def model(name, model_klass)
61
+ @root = [name, model_klass]
62
+ end
63
+
64
+ # @method sequence(name, options)
65
+ # @see Types::Sequence#initialize
66
+ # @method set(name, options)
67
+ # @see Types::Set#initialize
68
+ # @method choice(name, options)
69
+ # @see Types::Choice#initialize
70
+ %w(sequence set choice).each do |type|
71
+ class_eval "def #{type}(name, options={})\n" \
72
+ " proc = Proc.new do\n" \
73
+ " Types::#{type.capitalize}.new(name, options)\n" \
74
+ " end\n" \
75
+ " @root = [name, proc]\n" \
76
+ " @root << options[:content] unless options[:content].nil?\n" \
77
+ " @root\n" \
78
+ "end"
69
79
  end
70
80
 
71
- # define all class methods to instance a ASN.1 TAG
81
+ # @method sequence_of(name, type, options)
82
+ # @see Types::SequenceOf#initialize
83
+ # @method set_of(name, type, options)
84
+ # @see Types::SetOf#initialize
85
+ %w(sequence set).each do |type|
86
+ klass_name = "Types::#{type.capitalize}Of"
87
+ class_eval "def #{type}_of(name, type, options={})\n" \
88
+ " proc = Proc.new do\n" \
89
+ " #{klass_name}.new(name, type, options)\n" \
90
+ " end\n" \
91
+ " @root = [name, proc]\n" \
92
+ "end"
93
+ end
94
+
95
+ # @method boolean(name, options)
96
+ # @see Types::Boolean#initialize
97
+ # @method integer(name, options)
98
+ # @see Types::Integer#initialize
99
+ # @method bit_string(name, options)
100
+ # @see Types::BitString#initialize
101
+ # @method octet_string(name, options)
102
+ # @see Types::OctetString#initialize
103
+ # @method null(name, options)
104
+ # @see Types::Null#initialize
105
+ # @method enumerated(name, options)
106
+ # @see Types::Enumerated#initialize
107
+ # @method utf8_string(name, options)
108
+ # @see Types::Utf8String#initialize
72
109
  Types.primitives.each do |prim|
110
+ next if prim == Types::ObjectId
73
111
  class_eval "def #{prim.type.downcase.gsub(/\s+/, '_')}(name, options={})\n" \
74
- " Proc.new { #{prim.to_s}.new(name, options) }\n" \
112
+ " proc = Proc.new { #{prim.to_s}.new(name, options) }\n" \
113
+ " @root = [name, proc]\n" \
75
114
  "end"
76
115
  end
77
116
 
117
+ # @note This method is named +objectid+ and not +object_id+ to not override
118
+ # +Object#object_id+.
119
+ # @see Types::ObjectId#initialize
120
+ def objectid(name, options={})
121
+ proc = Proc.new { Types::ObjectId.new(name, options) }
122
+ @root = [name, proc]
123
+ end
124
+
125
+ # @see Types::Any#initialize
126
+ def any(name, options={})
127
+ proc = Proc.new { Types::Any.new(name, options) }
128
+ @root = [name, proc]
129
+ end
130
+
78
131
  # Parse a DER/BER encoded string
79
132
  # @param [String] str
80
133
  # @param [Boolean] ber accept BER encoding or not
@@ -89,7 +142,8 @@ module RASN1
89
142
  # Create a new instance of a {Model}
90
143
  # @param [Hash] args
91
144
  def initialize(args={})
92
- set_elements
145
+ root = generate_root
146
+ set_elements *root
93
147
  initialize_elements self, args
94
148
  end
95
149
 
@@ -106,6 +160,12 @@ module RASN1
106
160
  @elements[@root].name
107
161
  end
108
162
 
163
+ # Get elements names
164
+ # @return [Array<Symbol,String>]
165
+ def keys
166
+ @elements.keys
167
+ end
168
+
109
169
  # Return a hash image of model
110
170
  # @return [Hash]
111
171
  def to_h
@@ -117,46 +177,56 @@ module RASN1
117
177
  @elements[@root].to_der
118
178
  end
119
179
 
180
+ # Get root element from model
181
+ # @return [Types::Base,Model]
182
+ def root
183
+ @elements[@root]
184
+ end
185
+
120
186
  # Parse a DER/BER encoded string, and modify object in-place.
121
187
  # @param [String] str
122
188
  # @param [Boolean] ber accept BER encoding or not
123
189
  # @return [Integer] number of parsed bytes
124
190
  def parse!(str, ber: false)
125
- @elements[@root].parse!(str, ber: ber)
191
+ @elements[@root].parse!(str.dup.force_encoding('BINARY'), ber: ber)
126
192
  end
127
193
 
128
194
  private
129
195
 
130
- def set_elements(element=nil)
131
- if element.nil?
132
- records = self.class.class_eval { @records }
133
- @root = records.keys.first
134
- @elements = {}
135
- @elements[@root] = records[@root].call
136
- if @elements[@root].value.is_a? Array
137
- @elements[@root].value = @elements[@root].value.map do |subel|
138
- se = case subel
139
- when Proc
140
- subel.call
141
- when Class
142
- subel.new
143
- end
144
- @elements[se.name] = se
145
- set_elements se if se.is_a? Types::Sequence
146
- se
196
+ def is_composed?(el)
197
+ [Types::Sequence, Types::Set].include? el.class
198
+ end
199
+
200
+ def is_of?(el)
201
+ [Types::SequenceOf, Types::SetOf].include? el.class
202
+ end
203
+
204
+ def get_type(proc_or_class, name=nil)
205
+ case proc_or_class
206
+ when Proc
207
+ proc_or_class.call
208
+ when Class
209
+ proc_or_class.new
210
+ end
211
+ end
212
+
213
+ def generate_root
214
+ root = self.class.class_eval { @root }
215
+ @root = root[0]
216
+ @elements = {}
217
+ @elements[@root] = get_type(root[1])
218
+ root
219
+ end
220
+
221
+ def set_elements(name, el, content=nil)
222
+ if content.is_a? Array
223
+ @elements[name].value = content.map do |name2, proc_or_class, content2|
224
+ subel = get_type(proc_or_class, name2)
225
+ @elements[name2] = subel
226
+ if is_composed?(subel) and content2.is_a? Array
227
+ set_elements(name2, proc_or_class, content2)
147
228
  end
148
- end
149
- else
150
- element.value.map! do |subel|
151
- se = case subel
152
- when Proc
153
- subel.call
154
- when Class
155
- subel.new
156
- end
157
- @elements[se.name] = se
158
- set_elements se if se.is_a? Types::Sequence
159
- se
229
+ subel
160
230
  end
161
231
  end
162
232
  end
@@ -168,7 +238,7 @@ module RASN1
168
238
  if obj[name].is_a? Model
169
239
  initialize_elements obj[name], value
170
240
  else
171
- raise ArgumentError, "element #{name}: may only pass a Hash for Sequence elements"
241
+ raise ArgumentError, "element #{name}: may only pass a Hash for Model elements"
172
242
  end
173
243
  else
174
244
  obj[name].value = value
@@ -178,20 +248,27 @@ module RASN1
178
248
  end
179
249
 
180
250
  def private_to_h(element)
181
- h = {}
182
- element.value.each do |subel|
183
- h[subel.name] = case subel
184
- when Types::Sequence
185
- private_to_h(subel)
186
- when Model
187
- subel.to_h[subel.name]
188
- else
189
- next if subel.value.nil? and subel.optional?
190
- subel.value
191
- end
251
+ if element.value.is_a? Array
252
+ h = {}
253
+ element.value.each do |subel|
254
+ case subel
255
+ when Types::Sequence, Types::Set
256
+ h[subel.name] = private_to_h(subel)
257
+ when Model
258
+ h[@elements.key(subel)] = subel.to_h[subel.name]
259
+ when Hash, Array
260
+ # Array of Hash for SequenceOf and SetOf
261
+ # Array of Array of... of Hash are nested SequenceOf or SetOf
262
+ return element.value
263
+ else
264
+ next if subel.value.nil? and subel.optional?
265
+ h[subel.name] = subel.value
266
+ end
267
+ end
268
+ h
269
+ else
270
+ element.value
192
271
  end
193
-
194
- h
195
272
  end
196
273
  end
197
274
  end
data/lib/rasn1/types.rb CHANGED
@@ -35,3 +35,4 @@ require_relative 'types/sequence_of'
35
35
  require_relative 'types/set'
36
36
  require_relative 'types/set_of'
37
37
  require_relative 'types/choice'
38
+ require_relative 'types/any'
@@ -0,0 +1,29 @@
1
+ module RASN1
2
+ module Types
3
+
4
+ # ASN.1 ANY: accpets any types
5
+ # @author Sylvain Daubert
6
+ class Any < Base
7
+
8
+ # @return [String] DER-formated string
9
+ def to_der
10
+ case @value
11
+ when Base, Model
12
+ @value.to_der
13
+ else
14
+ @value.to_s
15
+ end
16
+ end
17
+
18
+ # Parse a DER string. This method updates object: {#value} will a DER string.
19
+ # @param [String] der DER string
20
+ # @param [Boolean] ber if +true+, accept BER encoding
21
+ # @return [Integer] total number of parsed bytes
22
+ def parse!(der, ber: false)
23
+ total_length, = get_data(der, ber)
24
+ @value = der[0, total_length]
25
+ total_length
26
+ end
27
+ end
28
+ end
29
+ end
@@ -36,6 +36,9 @@ module RASN1
36
36
  # ctype = RASN1::Types::Integer.new(:ctype, explicit: 0) # with explicit, default #asn1_class is :context
37
37
  # atype = RASN1::Types::Integer.new(:atype, explicit: 1, class: :application)
38
38
  # ptype = RASN1::Types::Integer.new(:ptype, explicit: 2, class: :private)
39
+ # Sometimes, an EXPLICIT type should be CONSTRUCTED. To do that, use +:constructed+
40
+ # option:
41
+ # ptype = RASN1::Types::Integer.new(:ptype, explicit: 2, class: :private, constructed: true)
39
42
  #
40
43
  # Implicit tagged values may also be defined:
41
44
  # ctype_implicit = RASN1::Types::Integer.new(:ctype, implicit: 0)
@@ -56,7 +59,7 @@ module RASN1
56
59
  INDEFINITE_LENGTH = 0x80
57
60
 
58
61
  # @return [Symbol, String]
59
- attr_reader :name
62
+ attr_accessor :name
60
63
  # @return [Symbol]
61
64
  attr_reader :asn1_class
62
65
  # @return [Object,nil] default value, if defined
@@ -74,13 +77,19 @@ module RASN1
74
77
 
75
78
  # @param [Symbol, String] name name for this tag in grammar
76
79
  # @param [Hash] options
77
- # @option options [Symbol] :class ASN.1 tag class. Default value is +:universal+
80
+ # @option options [Symbol] :class ASN.1 tag class. Default value is +:universal+.
81
+ # If +:explicit+ or +:implicit:+ is defined, default value is +:context+.
78
82
  # @option options [::Boolean] :optional define this tag as optional. Default
79
83
  # is +false+
80
84
  # @option options [Object] :default default value for DEFAULT tag
81
85
  # @option options [Object] :value value to set
86
+ # @option options [::Integer] :implicit define an IMPLICIT tagged type
87
+ # @option options [::Integer] :explicit define an EXPLICIT tagged type
88
+ # @option options [::Boolean] :constructed if +true+, set type as constructed.
89
+ # May only be used when +:explicit+ is defined, else it is discarded.
82
90
  def initialize(name, options={})
83
91
  @name = name
92
+ @constructed = nil
84
93
 
85
94
  set_options options
86
95
  end
@@ -137,20 +146,12 @@ module RASN1
137
146
 
138
147
  # @return [::Boolean] +true+ if this is a primitive type
139
148
  def primitive?
140
- if self.class < Primitive
141
- true
142
- else
143
- false
144
- end
149
+ (self.class < Primitive) && !@constructed
145
150
  end
146
151
 
147
152
  # @return [::Boolean] +true+ if this is a constructed type
148
153
  def constructed?
149
- if self.class < Constructed
150
- true
151
- else
152
- false
153
- end
154
+ !!((self.class < Constructed) || @constructed)
154
155
  end
155
156
 
156
157
  # Get ASN.1 type
@@ -162,7 +163,12 @@ module RASN1
162
163
  # Get tag value
163
164
  # @return [Integer]
164
165
  def tag
165
- (@tag_value || self.class::TAG) | CLASSES[@asn1_class] | self.class::ASN1_PC
166
+ pc = if @constructed.nil?
167
+ self.class::ASN1_PC
168
+ else
169
+ Constructed::ASN1_PC
170
+ end
171
+ (@tag_value || self.class::TAG) | CLASSES[@asn1_class] | pc
166
172
  end
167
173
 
168
174
  # @abstract This method SHOULD be partly implemented by subclasses to parse
@@ -177,7 +183,8 @@ module RASN1
177
183
 
178
184
  total_length, data = get_data(der, ber)
179
185
  if explicit?
180
- type = self.class.new(@name)
186
+ # Delegate to #explicit type to generate sub-tag
187
+ type = explicit_type
181
188
  type.parse!(data)
182
189
  @value = type.value
183
190
  else
@@ -225,6 +232,7 @@ module RASN1
225
232
  if options[:explicit]
226
233
  @tag = :explicit
227
234
  @tag_value = options[:explicit]
235
+ @constructed = options[:constructed]
228
236
  elsif options[:implicit]
229
237
  @tag = :implicit
230
238
  @tag_value = options[:implicit]
@@ -241,7 +249,7 @@ module RASN1
241
249
  def build_tag
242
250
  if build_tag?
243
251
  if explicit?
244
- v = self.class.new(nil)
252
+ v = explicit_type
245
253
  v.value = @value
246
254
  encoded_value = v.to_der
247
255
  else
@@ -325,8 +333,12 @@ module RASN1
325
333
  [total_length, data]
326
334
  end
327
335
 
336
+ def explicit_type
337
+ self.class.new(@name)
338
+ end
339
+
328
340
  def raise_tag_error(expected_tag, tag)
329
- msg = "Expected tag #{tag2name(expected_tag)} but get #{tag2name(tag)}"
341
+ msg = "Expected #{tag2name(expected_tag)} but get #{tag2name(tag)}"
330
342
  msg << " for #@name"
331
343
  raise ASN1Error, msg
332
344
  end
@@ -18,6 +18,8 @@ module RASN1
18
18
  # A {EnumeratedError} is raised when set value is not in enumeration.
19
19
  # @author Sylvain Daubert
20
20
  class Enumerated < Integer
21
+ # @return [Hash]
22
+ attr_reader :enum
21
23
 
22
24
  # @param [Symbol, String] name name for this tag in grammar
23
25
  # @param [Hash] options
@@ -114,6 +116,10 @@ module RASN1
114
116
  @value = @enum.key(v)
115
117
  raise EnumeratedError, "TAG #@name: value #{v} not in enumeration" if @value.nil?
116
118
  end
119
+
120
+ def explicit_type
121
+ self.class.new(@name, enum: self.enum)
122
+ end
117
123
  end
118
124
  end
119
125
  end
@@ -18,6 +18,11 @@ module RASN1
18
18
  # RASN1::Types::Integer(:id, explicit: 0, optional: true),
19
19
  # RASN1::Types::Integer(:id, implicit: 1, default: 0)
20
20
  # ]
21
+ #
22
+ # A sequence may also be used without value to not parse sequence content:
23
+ # seq = RASN1::Types::Sequence.new(:seq)
24
+ # seq.parse!(der_string)
25
+ # seq.value # => String
21
26
  # @author Sylvain Daubert
22
27
  class Sequence < Constructed
23
28
  TAG = 0x10
@@ -25,14 +30,25 @@ module RASN1
25
30
  private
26
31
 
27
32
  def value_to_der
28
- @value.map { |element| element.to_der }.join
33
+ case @value
34
+ when Array
35
+ @value.map { |element| element.to_der }.join
36
+ else
37
+ @value.to_s
38
+ end
29
39
  end
30
40
 
31
41
  def der_to_value(der, ber:false)
32
- nb_bytes = 0
33
- @value.each do |element|
34
- nb_bytes += element.parse!(der[nb_bytes..-1])
35
- end
42
+ case @value
43
+ when Array
44
+ nb_bytes = 0
45
+ @value.each do |element|
46
+ nb_bytes += element.parse!(der[nb_bytes..-1])
47
+ end
48
+ else
49
+ @value = der
50
+ der.length
51
+ end
36
52
  end
37
53
  end
38
54
  end
@@ -5,6 +5,7 @@ module RASN1
5
5
  #
6
6
  # A SEQUENCE OF is an array of one ASN.1 type.
7
7
  #
8
+ # == Use with {Primitive} types
8
9
  # To encode this ASN.1 example:
9
10
  # Integers ::= SEQUENCE OF INTEGER
10
11
  # do:
@@ -13,6 +14,7 @@ module RASN1
13
14
  # # Set integer values
14
15
  # seqof.value = [1, 2, 3, 4]
15
16
  #
17
+ # == Use with {Constructed} types
16
18
  # SEQUENCE OF may be used to create sequence of composed types. For example:
17
19
  # composed_type = RASN1::Sequence.new(:comp)
18
20
  # commposed_type.value = [RASN1::Types::Integer(:id),
@@ -20,38 +22,54 @@ module RASN1
20
22
  # seqof = RASN1::SequenceOf.new(:comp, composed_type)
21
23
  # seqof.value << [0, 'data0']
22
24
  # seqof.value << [1, 'data1']
25
+ #
26
+ # == Use with {Model}
27
+ # SEQUENCE OF may also be used with a Model type:
28
+ # class MyModel < RASN1::Model
29
+ # sequence :seq,
30
+ # content: [boolean(:bool), integer(:int)]
31
+ # end
32
+ #
33
+ # seqof = RASN1::Types::SequenceOf.new(:record, MyModel)
34
+ # # set values
35
+ # seqof.value << { bool: true, int: 12 }
36
+ # seqof.value << { bool: false, int: 65535 }
37
+ # # Generate DER string
38
+ # der = seqof.to_der # => String
39
+ # # parse
40
+ # seqof.parse! der
23
41
  # @author Sylvain Daubert
24
42
  class SequenceOf < Constructed
25
43
  TAG = Sequence::TAG
26
44
 
27
45
  # @return [Class, Base]
28
- attr_reader :type
46
+ attr_reader :of_type
29
47
 
30
48
  # @param [Symbol, String] name name for this tag in grammar
31
- # @param [Class, Base] type base type for sequence of
49
+ # @param [Class, Base] of_type base type for sequence of
32
50
  # @see Base#initialize
33
- def initialize(name, type, options={})
51
+ def initialize(name, of_type, options={})
34
52
  super(name, options)
35
- @type = type
53
+ @of_type = of_type
36
54
  @value = []
37
55
  end
38
56
 
39
57
  private
40
58
 
41
- def type_class
42
- type.is_a?(Class) ? type : type.class
59
+ def of_type_class
60
+ @of_type.is_a?(Class) ? @of_type : @of_type.class
43
61
  end
44
62
 
45
- def composed_type?
46
- [Sequence, Set].include? type_class
63
+ def composed_of_type?
64
+ [Sequence, Set].include? of_type_class
47
65
  end
48
66
 
49
67
  def value_to_der
50
- if composed_type?
68
+ if composed_of_type?
51
69
  @value.map do |ary|
52
- s = type_class.new(@type.name)
70
+ s = of_type_class.new(@of_type.name)
53
71
  sval = []
54
- @type.value.each_with_index do |type, i|
72
+ @of_type.value.each_with_index do |type, i|
55
73
  type2 = type.dup
56
74
  type2.value = ary[i]
57
75
  sval << type2
@@ -59,8 +77,21 @@ module RASN1
59
77
  s.value = sval
60
78
  s.to_der
61
79
  end.join
80
+ elsif of_type_class < Model
81
+ if of_type_class.new.root.is_a? SequenceOf
82
+ @value.map do |ary|
83
+ model = of_type_class.new
84
+ model.root.value = ary
85
+ model.to_der
86
+ end.join
87
+ else
88
+ @value.map do |hsh|
89
+ model = of_type_class.new(hsh)
90
+ model.to_der
91
+ end.join
92
+ end
62
93
  else
63
- @value.map { |v| t = type_class.new(:t, value: v).to_der }.join
94
+ @value.map { |v| of_type_class.new(:t, value: v).to_der }.join
64
95
  end
65
96
  end
66
97
 
@@ -69,16 +100,28 @@ module RASN1
69
100
  nb_bytes = 0
70
101
 
71
102
  while nb_bytes < der.length
72
- of_type = composed_type? ? type.dup : type_class.new(:t)
73
- nb_bytes += of_type.parse!(der[nb_bytes, der.length])
74
- value = if composed_type?
75
- of_type.value.map { |obj| obj.value }
103
+ type = if composed_of_type?
104
+ @of_type.dup
105
+ elsif of_type_class < Model
106
+ of_type_class.new
107
+ else
108
+ of_type_class.new(:t)
109
+ end
110
+ nb_bytes += type.parse!(der[nb_bytes, der.length])
111
+ value = if composed_of_type?
112
+ type.value.map { |obj| obj.value }
113
+ elsif of_type_class < Model
114
+ type.to_h[type.to_h.keys.first]
76
115
  else
77
- of_type.value
116
+ type.value
78
117
  end
79
118
  @value << value
80
119
  end
81
120
  end
121
+
122
+ def explicit_type
123
+ self.class.new(@name, self.of_type)
124
+ end
82
125
  end
83
126
  end
84
127
  end
data/lib/rasn1/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module RASN1
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0"
3
3
  end
data/rasn1.gemspec CHANGED
@@ -20,6 +20,8 @@ Gem::Specification.new do |spec|
20
20
  #spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
21
21
  spec.require_paths = ['lib']
22
22
 
23
+ spec.required_ruby_version = '>= 2.1.0'
24
+
23
25
  spec.add_dependency 'yard', '~>0.9'
24
26
 
25
27
  spec.add_development_dependency 'bundler', '~> 1.13'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rasn1
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sylvain Daubert
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-08-06 00:00:00.000000000 Z
11
+ date: 2017-08-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: yard
@@ -95,6 +95,7 @@ files:
95
95
  - lib/rasn1.rb
96
96
  - lib/rasn1/model.rb
97
97
  - lib/rasn1/types.rb
98
+ - lib/rasn1/types/any.rb
98
99
  - lib/rasn1/types/base.rb
99
100
  - lib/rasn1/types/bit_string.rb
100
101
  - lib/rasn1/types/boolean.rb
@@ -125,7 +126,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
125
126
  requirements:
126
127
  - - ">="
127
128
  - !ruby/object:Gem::Version
128
- version: '0'
129
+ version: 2.1.0
129
130
  required_rubygems_version: !ruby/object:Gem::Requirement
130
131
  requirements:
131
132
  - - ">="