Class: RASN1::Model Abstract
- Inherits:
-
Object
- Object
- RASN1::Model
- Extended by:
- Accel
- Defined in:
- lib/rasn1/model.rb,
lib/rasn1/model/accel.rb
Overview
Model class is a base class to define ASN.1 models.
Create a simple ASN.1 model
Given this ASN.1 example: Record ::= SEQUENCE { id INTEGER, room [0] IMPLICIT INTEGER OPTIONAL, house [1] EXPLICIT INTEGER DEFAULT 0 }
You may create your model like this: class Record < RASN1::Model sequence(:record, content: [integer(:id), integer(:room, implicit: 0, optional: true), integer(:house, explicit: 1, default: 0)]) end
You may also use block style definition: class Record < RASN1::Model sequence :record do integer :id integer :room, implicit: 0, optional: true integer :house, explicit: 1, default: 0 end end
In a model, each element must have a unique name.
Parse a DER-encoded string
record = Record.parse(der_string) record # => RASN1::Types::Integer record.value # => Integer record.to_i # => Integer record.asn1_class # => Symbol record.optional? # => false record.default # => nil record.optional # => true record.default # => 0
You may also parse a BER-encoded string this way: record = Record.parse(der_string, ber: true)
Generate a DER-encoded string
record = Record.new(id: 12, room: 24) record.to_der
Create a more complex model
Models may be nested. For example: class Record2 < RASN1::Model sequence :record2 do boolean :rented, default: false) model :a_record, Record end end
Set values like this: record2 = Record2.new record2 = true record2[:id] = 65537 record2[:room] = 43 or like this: record2 = Record2.new(rented: true, a_record: { id: 65537, room: 43 })
Delegation
Model may delegate some methods to its root element. Thus, if root element
is, for example, a Types::Choice, model may delegate #chosen and #chosen_value.
All methods defined by root may be delegated by model, unless model also defines this method.
Defined Under Namespace
Modules: Accel Classes: BaseElem, ModelElem, WrapElem
Constant Summary collapse
Instance Attribute Summary collapse
- #root ⇒ Model, ... readonly
Attributes included from Accel
Class Method Summary collapse
- .bit_string(name, options) ⇒ Elem
- .bmp_string(name, options) ⇒ Elem
- .boolean(name, options) ⇒ Elem
- .choice(name, options) ⇒ Elem
- .enumerated(name, options) ⇒ Elem
- .ia5_string(name, options) ⇒ Elem
- .integer(name, options) ⇒ Elem
- .null(name, options) ⇒ Elem
- .numeric_string(name, options) ⇒ Elem
- .octet_string(name, options) ⇒ Elem
- .printable_string(name, options) ⇒ Elem
- .sequence(name, options) ⇒ Elem
- .sequence_of(name, type, options) ⇒ Elem
- .set(name, options) ⇒ Elem
- .set_of(name, type, options) ⇒ Elem
- .universal_string(name, options) ⇒ Elem
- .utf8_string(name, options) ⇒ Elem
- .visible_string(name, options) ⇒ Elem
Instance Method Summary collapse
-
#==(other) ⇒ Boolean
Objects are equal if they have same class AND same DER.
- #[](name_or_idx) ⇒ Object
-
#[]=(name, value) ⇒ Object
Set value of element
name. - #do_parse(der, ber: false) ⇒ Object
-
#initialize(args = {}) ⇒ Model
constructor
Create a new instance of a Model.
-
#initialize_copy ⇒ void
clone @elements and initialize @root from this new @element.
- #inspect(level = 0) ⇒ String
-
#keys ⇒ Array<Symbol,String>
Get elements names.
-
#method_missing(meth, *args, **kwargs) ⇒ Object
Delegate some methods to root element.
-
#name ⇒ String
Give model name (a.k.a root name).
-
#parse!(der, ber: false) ⇒ Integer
Parse a DER/BER encoded string, and modify object in-place.
- #respond_to_missing?(meth) ⇒ Boolean
- #to_der ⇒ String
-
#to_h ⇒ Hash
Return a hash image of model.
-
#type ⇒ String
Give type name (aka class name).
- #value(name = nil, *args) ⇒ Object?
Methods included from Accel
any, define_type_accel, define_type_accel_base, define_type_accel_container, define_type_accel_of, elements, generate_content, inherited, model, objectid, parse, push_element, root=, root_options, wrapper
Constructor Details
#initialize(args = {}) ⇒ Model
Create a new instance of a RASN1::Model
267 268 269 270 271 272 |
# File 'lib/rasn1/model.rb', line 267 def initialize(args={}) @elements = {} generate_root(args) args.delete(:name) lazy_initialize(args) unless args.empty? end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
Instance Attribute Details
Class Method Details
.bit_string(name, options) ⇒ Elem
255 256 257 258 259 260 |
# File 'lib/rasn1/model.rb', line 255 Types.primitives.each do |prim| next if prim == Types::ObjectId method_name = prim.type.gsub(/([a-z0-9])([A-Z])/, '\1_\2').downcase.gsub(/\s+/, '_') self.define_type_accel_base(method_name, prim) end |
.bmp_string(name, options) ⇒ Elem
255 256 257 258 259 260 |
# File 'lib/rasn1/model.rb', line 255 Types.primitives.each do |prim| next if prim == Types::ObjectId method_name = prim.type.gsub(/([a-z0-9])([A-Z])/, '\1_\2').downcase.gsub(/\s+/, '_') self.define_type_accel_base(method_name, prim) end |
.boolean(name, options) ⇒ Elem
255 256 257 258 259 260 |
# File 'lib/rasn1/model.rb', line 255 Types.primitives.each do |prim| next if prim == Types::ObjectId method_name = prim.type.gsub(/([a-z0-9])([A-Z])/, '\1_\2').downcase.gsub(/\s+/, '_') self.define_type_accel_base(method_name, prim) end |
.choice(name, options) ⇒ Elem
155 156 157 |
# File 'lib/rasn1/model.rb', line 155 %w[sequence set choice].each do |type| self.define_type_accel_container(type, Types.const_get(type.capitalize)) end |
.enumerated(name, options) ⇒ Elem
255 256 257 258 259 260 |
# File 'lib/rasn1/model.rb', line 255 Types.primitives.each do |prim| next if prim == Types::ObjectId method_name = prim.type.gsub(/([a-z0-9])([A-Z])/, '\1_\2').downcase.gsub(/\s+/, '_') self.define_type_accel_base(method_name, prim) end |
.ia5_string(name, options) ⇒ Elem
255 256 257 258 259 260 |
# File 'lib/rasn1/model.rb', line 255 Types.primitives.each do |prim| next if prim == Types::ObjectId method_name = prim.type.gsub(/([a-z0-9])([A-Z])/, '\1_\2').downcase.gsub(/\s+/, '_') self.define_type_accel_base(method_name, prim) end |
.integer(name, options) ⇒ Elem
255 256 257 258 259 260 |
# File 'lib/rasn1/model.rb', line 255 Types.primitives.each do |prim| next if prim == Types::ObjectId method_name = prim.type.gsub(/([a-z0-9])([A-Z])/, '\1_\2').downcase.gsub(/\s+/, '_') self.define_type_accel_base(method_name, prim) end |
.null(name, options) ⇒ Elem
255 256 257 258 259 260 |
# File 'lib/rasn1/model.rb', line 255 Types.primitives.each do |prim| next if prim == Types::ObjectId method_name = prim.type.gsub(/([a-z0-9])([A-Z])/, '\1_\2').downcase.gsub(/\s+/, '_') self.define_type_accel_base(method_name, prim) end |
.numeric_string(name, options) ⇒ Elem
255 256 257 258 259 260 |
# File 'lib/rasn1/model.rb', line 255 Types.primitives.each do |prim| next if prim == Types::ObjectId method_name = prim.type.gsub(/([a-z0-9])([A-Z])/, '\1_\2').downcase.gsub(/\s+/, '_') self.define_type_accel_base(method_name, prim) end |
.octet_string(name, options) ⇒ Elem
255 256 257 258 259 260 |
# File 'lib/rasn1/model.rb', line 255 Types.primitives.each do |prim| next if prim == Types::ObjectId method_name = prim.type.gsub(/([a-z0-9])([A-Z])/, '\1_\2').downcase.gsub(/\s+/, '_') self.define_type_accel_base(method_name, prim) end |
.printable_string(name, options) ⇒ Elem
255 256 257 258 259 260 |
# File 'lib/rasn1/model.rb', line 255 Types.primitives.each do |prim| next if prim == Types::ObjectId method_name = prim.type.gsub(/([a-z0-9])([A-Z])/, '\1_\2').downcase.gsub(/\s+/, '_') self.define_type_accel_base(method_name, prim) end |
.sequence(name, options) ⇒ Elem
155 156 157 |
# File 'lib/rasn1/model.rb', line 155 %w[sequence set choice].each do |type| self.define_type_accel_container(type, Types.const_get(type.capitalize)) end |
.sequence_of(name, type, options) ⇒ Elem
173 174 175 |
# File 'lib/rasn1/model.rb', line 173 %w[sequence set].each do |type| define_type_accel_of(type, Types.const_get(:"#{type.capitalize}Of")) end |
.set(name, options) ⇒ Elem
155 156 157 |
# File 'lib/rasn1/model.rb', line 155 %w[sequence set choice].each do |type| self.define_type_accel_container(type, Types.const_get(type.capitalize)) end |
.set_of(name, type, options) ⇒ Elem
173 174 175 |
# File 'lib/rasn1/model.rb', line 173 %w[sequence set].each do |type| define_type_accel_of(type, Types.const_get(:"#{type.capitalize}Of")) end |
.universal_string(name, options) ⇒ Elem
255 256 257 258 259 260 |
# File 'lib/rasn1/model.rb', line 255 Types.primitives.each do |prim| next if prim == Types::ObjectId method_name = prim.type.gsub(/([a-z0-9])([A-Z])/, '\1_\2').downcase.gsub(/\s+/, '_') self.define_type_accel_base(method_name, prim) end |
.utf8_string(name, options) ⇒ Elem
255 256 257 258 259 260 |
# File 'lib/rasn1/model.rb', line 255 Types.primitives.each do |prim| next if prim == Types::ObjectId method_name = prim.type.gsub(/([a-z0-9])([A-Z])/, '\1_\2').downcase.gsub(/\s+/, '_') self.define_type_accel_base(method_name, prim) end |
.visible_string(name, options) ⇒ Elem
255 256 257 258 259 260 |
# File 'lib/rasn1/model.rb', line 255 Types.primitives.each do |prim| next if prim == Types::ObjectId method_name = prim.type.gsub(/([a-z0-9])([A-Z])/, '\1_\2').downcase.gsub(/\s+/, '_') self.define_type_accel_base(method_name, prim) end |
Instance Method Details
#==(other) ⇒ Boolean
Objects are equal if they have same class AND same DER
424 425 426 |
# File 'lib/rasn1/model.rb', line 424 def ==(other) (other.class == self.class) && (other.to_der == self.to_der) end |
#[](name) ⇒ Model, ... #[](idx) ⇒ Model, ...
282 283 284 285 286 287 288 289 290 291 292 |
# File 'lib/rasn1/model.rb', line 282 def [](name_or_idx) case name_or_idx when Symbol elt = @elements[name_or_idx] return elt unless elt.is_a?(Proc) @elements[name_or_idx] = elt.call when Integer root[name_or_idx] end end |
#[]=(name, value) ⇒ Object
Set value of element name. Element should be a Types::Base.
298 299 300 301 302 303 |
# File 'lib/rasn1/model.rb', line 298 def []=(name, value) # Here, use #[] to force generation for lazy elements raise Error, 'cannot set value for a Model' if self[name].is_a?(Model) self[name].value = value end |
#do_parse(der, ber: false) ⇒ Object
353 354 355 |
# File 'lib/rasn1/model.rb', line 353 def do_parse(der, ber: false) root.do_parse(der, ber: ber) end |
#initialize_copy ⇒ void
This method returns an undefined value.
clone @elements and initialize @root from this new @element.
307 308 309 310 |
# File 'lib/rasn1/model.rb', line 307 def initialize_copy(*) @elements = @elements.clone @root = @elements[@root_name] end |
#inspect(level = 0) ⇒ String
417 418 419 |
# File 'lib/rasn1/model.rb', line 417 def inspect(level=0) "#{' ' * level}(#{type}) #{root.inspect(-level)}" end |
#keys ⇒ Array<Symbol,String>
Get elements names
320 321 322 |
# File 'lib/rasn1/model.rb', line 320 def keys @elements.keys end |
#name ⇒ String
Give model name (a.k.a root name)
314 315 316 |
# File 'lib/rasn1/model.rb', line 314 def name @root_name end |
#parse!(der, ber: false) ⇒ Integer
Parse a DER/BER encoded string, and modify object in-place.
346 347 348 |
# File 'lib/rasn1/model.rb', line 346 def parse!(der, ber: false) root.parse!(der, ber: ber) end |
#respond_to_missing?(meth) ⇒ Boolean
411 412 413 |
# File 'lib/rasn1/model.rb', line 411 def respond_to_missing?(meth, *) root.respond_to?(meth) || super end |
#to_h ⇒ Hash
Return a hash image of model
326 327 328 |
# File 'lib/rasn1/model.rb', line 326 def to_h private_to_h end |
#type ⇒ String
Give type name (aka class name)
337 338 339 |
# File 'lib/rasn1/model.rb', line 337 def type self.class.type end |
#value ⇒ Object? #value(name, *args) ⇒ Object?
378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 |
# File 'lib/rasn1/model.rb', line 378 def value(name=nil, *args) if name.nil? root.value else elt = by_name(name) return nil if elt.nil? unless args.empty? args.each do |arg| elt = elt.root if elt.is_a?(Model) elt = elt[arg] end end elt.value end end |