module RASN1 module Types # ASN.1 sequence # # A sequence is a collection of another ASN.1 types. # # To encode this ASN.1 example: # Record ::= SEQUENCE { # id INTEGER, # room [0] INTEGER OPTIONAL, # house [1] IMPLICIT INTEGER DEFAULT 0 # } # do: # seq = RASN1::Types::Sequence.new(:record) # seq.value = [ # RASN1::Types::Integer(:id), # RASN1::Types::Integer(:id, explicit: 0, optional: true), # RASN1::Types::Integer(:id, implicit: 1, default: 0) # ] # # A sequence may also be used without value to not parse sequence content: # seq = RASN1::Types::Sequence.new(:seq) # seq.parse!(der_string) # seq.value # => String # @author Sylvain Daubert class Sequence < Constructed TAG = 0x10 # @param [Symbol, String] name name for this tag in grammar # @param [Hash] options # @option options [Symbol] :class ASN.1 tag class. Default value is +:universal+. # If +:explicit+ or +:implicit:+ is defined, default value is +:context+. # @option options [::Boolean] :optional define this tag as optional. Default # is +false+ # @option options [Object] :default default value for DEFAULT tag # @option options [Object] :value value to set (default is +[]+) # @option options [::Integer] :implicit define an IMPLICIT tagged type # @option options [::Integer] :explicit define an EXPLICIT tagged type # @option options [::Boolean] :constructed if +true+, set type as constructed. # May only be used when +:explicit+ is defined, else it is discarded. def initialize(name, options={}) super(name, { value: [] }.merge(options)) end def initialize_copy(other) super @value.map! { |v| v.dup } end private def value_to_der case @value when Array @value.map { |element| element.to_der }.join else @value.to_s end end def der_to_value(der, ber:false) if @value.is_a?(Array) and !@value.empty? nb_bytes = 0 @value.each do |element| nb_bytes += element.parse!(der[nb_bytes..-1]) end else @value = der der.length end end end end end