Class: RASN2::Model Abstract
- Inherits:
-
Object
- Object
- RASN2::Model
- Extended by:
- Accel
- Includes:
- Helpers::Colorize
- Defined in:
- lib/rasn2/model.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 < RASN2::Model sequence(:record, content: [integer(:id), integer(:room, implicit: 0, optional: true), integer(:house, explicit: 1, default: 0)]) end
Since 0.17.0, content may also be defined through a block. This is strictly
equivalent to the :content option:
class Record < RASN2::Model
sequence :record do
integer :id
integer :room, implicit: 0, optional: true
integer :house, explicit: 1, default: 0
end
end
Blocks may be nested, and may use all model helpers (+#model+, #wrapper, #sequence_of, ...):
class PersonnelRecord < RASN2::Model
sequence :personnelRecord do
utf8_string :name
utf8_string :title
integer :age
boolean :employed
end
end
When both :content option and a block are given, block elements are appended to
those defined by the option.
In a model, each element must have a unique name.
Parse a DER-encoded string
record = Record.parse(der_string) record # => RASN2::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 < RASN2::Model sequence(:record2, content: [boolean(:rented, default: false), model(:a_record, Record)]) 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 }) Same model, using a block: class Record2 < RASN2::Model sequence :record2 do boolean :rented, default: false model :a_record, Record end end
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(_other) ⇒ Object
clone @elements and initialize @root from this new @element.
- #inspect(level = 0, color: true) ⇒ 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_asn1(name: nil, type_name: nil) ⇒ String
Generate ASN.1 value notation text from this model instance.
- #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, capture_content, define_type_accel, define_type_accel_base, define_type_accel_of, inherited, model, objectid, parse, push_element, root_options, wrapper
Methods included from Helpers::Colorize
#begin_colorizer, #brace_surround, #colorize, #colorize_attribute, #colorize_bool, #colorize_class, #colorize_default, #colorize_enum, #colorize_id, #colorize_name, #colorize_nil, #colorize_value, #colorizer, #colorizer=, #end_colorizer, #int_with_hex, #length_specifier, #parens_hex
Constructor Details
#initialize(args = {}) ⇒ Model
Create a new instance of a RASN2::Model
485 486 487 488 489 |
# File 'lib/rasn2/model.rb', line 485 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
473 474 475 476 477 478 |
# File 'lib/rasn2/model.rb', line 473 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
473 474 475 476 477 478 |
# File 'lib/rasn2/model.rb', line 473 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
473 474 475 476 477 478 |
# File 'lib/rasn2/model.rb', line 473 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
373 374 375 |
# File 'lib/rasn2/model.rb', line 373 %w[sequence set choice tag].each do |type| self.define_type_accel_base(type, Types.const_get(type.capitalize)) end |
.enumerated(name, options) ⇒ Elem
473 474 475 476 477 478 |
# File 'lib/rasn2/model.rb', line 473 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
473 474 475 476 477 478 |
# File 'lib/rasn2/model.rb', line 473 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
473 474 475 476 477 478 |
# File 'lib/rasn2/model.rb', line 473 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
473 474 475 476 477 478 |
# File 'lib/rasn2/model.rb', line 473 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
473 474 475 476 477 478 |
# File 'lib/rasn2/model.rb', line 473 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
473 474 475 476 477 478 |
# File 'lib/rasn2/model.rb', line 473 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
473 474 475 476 477 478 |
# File 'lib/rasn2/model.rb', line 473 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
373 374 375 |
# File 'lib/rasn2/model.rb', line 373 %w[sequence set choice tag].each do |type| self.define_type_accel_base(type, Types.const_get(type.capitalize)) end |
.sequence_of(name, type, options) ⇒ Elem
391 392 393 |
# File 'lib/rasn2/model.rb', line 391 %w[sequence set].each do |type| define_type_accel_of(type, Types.const_get(:"#{type.capitalize}Of")) end |
.set(name, options) ⇒ Elem
373 374 375 |
# File 'lib/rasn2/model.rb', line 373 %w[sequence set choice tag].each do |type| self.define_type_accel_base(type, Types.const_get(type.capitalize)) end |
.set_of(name, type, options) ⇒ Elem
391 392 393 |
# File 'lib/rasn2/model.rb', line 391 %w[sequence set].each do |type| define_type_accel_of(type, Types.const_get(:"#{type.capitalize}Of")) end |
.universal_string(name, options) ⇒ Elem
473 474 475 476 477 478 |
# File 'lib/rasn2/model.rb', line 473 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
473 474 475 476 477 478 |
# File 'lib/rasn2/model.rb', line 473 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
473 474 475 476 477 478 |
# File 'lib/rasn2/model.rb', line 473 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
647 648 649 |
# File 'lib/rasn2/model.rb', line 647 def ==(other) (other.class == self.class) && (other.to_der == self.to_der) end |
#[](name) ⇒ Model, ... #[](idx) ⇒ Model, ...
499 500 501 502 503 504 505 506 507 508 509 |
# File 'lib/rasn2/model.rb', line 499 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.
515 516 517 518 519 520 |
# File 'lib/rasn2/model.rb', line 515 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
579 580 581 |
# File 'lib/rasn2/model.rb', line 579 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.
523 524 525 526 |
# File 'lib/rasn2/model.rb', line 523 def initialize_copy(_other) @elements = @elements.clone @root = @elements[@root_name] end |
#inspect(level = 0, color: true) ⇒ String
640 641 642 |
# File 'lib/rasn2/model.rb', line 640 def inspect(level=0, color: true) root.inspect(level, color: color, kind: type) end |
#keys ⇒ Array<Symbol,String>
Get elements names
536 537 538 |
# File 'lib/rasn2/model.rb', line 536 def keys @elements.keys end |
#name ⇒ String
Give model name (a.k.a root name)
530 531 532 |
# File 'lib/rasn2/model.rb', line 530 def name @root_name end |
#parse!(der, ber: false) ⇒ Integer
Parse a DER/BER encoded string, and modify object in-place.
571 572 573 574 575 |
# File 'lib/rasn2/model.rb', line 571 def parse!(der, ber: false) result = root.parse!(der, ber: ber) result.model = self if result.respond_to? :model= result end |
#respond_to_missing?(meth) ⇒ Boolean
635 636 637 |
# File 'lib/rasn2/model.rb', line 635 def respond_to_missing?(meth, *) root.respond_to?(meth) || super end |
#to_asn1(name: nil, type_name: nil) ⇒ String
Generate ASN.1 value notation text from this model instance.
556 557 558 |
# File 'lib/rasn2/model.rb', line 556 def to_asn1(name: nil, type_name: nil) ValueNotation.emit(self, name: name, type_name: type_name) end |
#to_h ⇒ Hash
Return a hash image of model
542 543 544 |
# File 'lib/rasn2/model.rb', line 542 def to_h private_to_h end |
#type ⇒ String
Give type name (aka class name)
562 563 564 |
# File 'lib/rasn2/model.rb', line 562 def type self.class.type end |
#value ⇒ Object? #value(name, *args) ⇒ Object?
604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 |
# File 'lib/rasn2/model.rb', line 604 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 |