Class: RASN1::Model Abstract
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
In a model, each element must have a unique name.
Parse a DER-encoded string
record = Record.parse(der_string)
record[:id] # => RASN1::Types::Integer
record[:id].value # => Integer
record[:id].to_i # => Integer
record[:id].asn1_class # => Symbol
record[:id].optional? # => false
record[:id].default # => nil
record[:room].optional # => true
record[:house].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,
content: [boolean(:rented, default: false),
model(:a_record, Record)])
end
Set values like this:
record2 = Record2.new
record2[:rented] = true
record2[:a_record][:id] = 65537
record2[:a_record][: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) ⇒ Model, ...
Access an element of the model by its name.
-
#[]=(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(_other) ⇒ Object
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) ⇒ Hash
Return a hash image of model 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_of, inherited, model, objectid, parse, root_options, wrapper
Constructor Details
#initialize(args = {}) ⇒ Model
Create a new instance of a RASN1::Model
378 379 380 381 382 |
# File 'lib/rasn1/model.rb', line 378 def initialize(args={}) @elements = {} generate_root(args) 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
366 367 368 369 370 371 |
# File 'lib/rasn1/model.rb', line 366 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
366 367 368 369 370 371 |
# File 'lib/rasn1/model.rb', line 366 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
366 367 368 369 370 371 |
# File 'lib/rasn1/model.rb', line 366 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
266 267 268 |
# File 'lib/rasn1/model.rb', line 266 %w[sequence set choice].each do |type| self.define_type_accel_base(type, Types.const_get(type.capitalize)) end |
.enumerated(name, options) ⇒ Elem
366 367 368 369 370 371 |
# File 'lib/rasn1/model.rb', line 366 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
366 367 368 369 370 371 |
# File 'lib/rasn1/model.rb', line 366 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
366 367 368 369 370 371 |
# File 'lib/rasn1/model.rb', line 366 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
366 367 368 369 370 371 |
# File 'lib/rasn1/model.rb', line 366 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
366 367 368 369 370 371 |
# File 'lib/rasn1/model.rb', line 366 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
366 367 368 369 370 371 |
# File 'lib/rasn1/model.rb', line 366 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
366 367 368 369 370 371 |
# File 'lib/rasn1/model.rb', line 366 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
266 267 268 |
# File 'lib/rasn1/model.rb', line 266 %w[sequence set choice].each do |type| self.define_type_accel_base(type, Types.const_get(type.capitalize)) end |
.sequence_of(name, type, options) ⇒ Elem
284 285 286 |
# File 'lib/rasn1/model.rb', line 284 %w[sequence set].each do |type| define_type_accel_of(type, Types.const_get(:"#{type.capitalize}Of")) end |
.set(name, options) ⇒ Elem
266 267 268 |
# File 'lib/rasn1/model.rb', line 266 %w[sequence set choice].each do |type| self.define_type_accel_base(type, Types.const_get(type.capitalize)) end |
.set_of(name, type, options) ⇒ Elem
284 285 286 |
# File 'lib/rasn1/model.rb', line 284 %w[sequence set].each do |type| define_type_accel_of(type, Types.const_get(:"#{type.capitalize}Of")) end |
.universal_string(name, options) ⇒ Elem
366 367 368 369 370 371 |
# File 'lib/rasn1/model.rb', line 366 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
366 367 368 369 370 371 |
# File 'lib/rasn1/model.rb', line 366 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
366 367 368 369 370 371 |
# File 'lib/rasn1/model.rb', line 366 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
520 521 522 |
# File 'lib/rasn1/model.rb', line 520 def ==(other) (other.class == self.class) && (other.to_der == self.to_der) end |
#[](name) ⇒ Model, ...
Access an element of the model by its name
387 388 389 390 391 392 393 |
# File 'lib/rasn1/model.rb', line 387 def [](name) elt = @elements[name] return elt unless elt.is_a?(Proc) # Lazy element -> generate it @elements[name] = elt.call end |
#[]=(name, value) ⇒ Object
Set value of element name
. Element should be a Types::Base.
399 400 401 402 403 404 |
# File 'lib/rasn1/model.rb', line 399 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
452 453 454 |
# File 'lib/rasn1/model.rb', line 452 def do_parse(der, ber: false) root.do_parse(der, ber: ber) end |
#initialize_copy(_other) ⇒ Object
clone @elements and initialize @root from this new @element.
407 408 409 410 |
# File 'lib/rasn1/model.rb', line 407 def initialize_copy(_other) @elements = @elements.clone @root = @elements[@root_name] end |
#inspect(level = 0) ⇒ String
513 514 515 |
# File 'lib/rasn1/model.rb', line 513 def inspect(level=0) "#{' ' * level}(#{type}) #{root.inspect(-level)}" end |
#keys ⇒ Array<Symbol,String>
Get elements names
420 421 422 |
# File 'lib/rasn1/model.rb', line 420 def keys @elements.keys end |
#name ⇒ String
Give model name (a.k.a root name)
414 415 416 |
# File 'lib/rasn1/model.rb', line 414 def name @root_name end |
#parse!(der, ber: false) ⇒ Integer
Parse a DER/BER encoded string, and modify object in-place.
446 447 448 |
# File 'lib/rasn1/model.rb', line 446 def parse!(der, ber: false) root.parse!(der, ber: ber) end |
#respond_to_missing?(meth) ⇒ Boolean
508 509 510 |
# File 'lib/rasn1/model.rb', line 508 def respond_to_missing?(meth, *) root.respond_to?(meth) || super end |
#to_h ⇒ Hash
Return a hash image of model
426 427 428 |
# File 'lib/rasn1/model.rb', line 426 def to_h private_to_h end |
#type ⇒ String
Give type name (aka class name)
437 438 439 |
# File 'lib/rasn1/model.rb', line 437 def type self.class.type end |
#value ⇒ Object? #value(name, *args) ⇒ Object?
477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 |
# File 'lib/rasn1/model.rb', line 477 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 |