diff options
Diffstat (limited to 'lib/asn1kit/types/sequence.rb')
-rw-r--r-- | lib/asn1kit/types/sequence.rb | 121 |
1 files changed, 121 insertions, 0 deletions
diff --git a/lib/asn1kit/types/sequence.rb b/lib/asn1kit/types/sequence.rb new file mode 100644 index 0000000..2fbf530 --- /dev/null +++ b/lib/asn1kit/types/sequence.rb @@ -0,0 +1,121 @@ +# coding: ASCII-8BIT + +class ASN1Kit::Sequence < ASN1Kit::Type + asn1_tag :IMPLICIT, :UNIVERSAL, 16 + asn1_alias "SEQUENCE" + + class ComponentType + attr_reader :name, :type, :default + + def optional? + @optional + end + + def initialize(name, type, default: nil, optional: false) + @name = name + @type = type + @default = default + @optional = optional + end + + def inspect + str = "#{name} #{type.inspect_abbrev}" + str << " DEFAULT #{default.inspect_abbrev}" if default + str << " OPTIONAL" if optional? + str + end + end + + class << self + def [](*component_types) + ret = Class.new(self) + hash = component_types.map { |c| [c.name, c] }.to_h + ret.const_set(:COMPONENT_TYPES, hash) + ret + end + + def component_types + self::COMPONENT_TYPES.keys + end + + def component_type(name) + self::COMPONENT_TYPES[name]&.type + end + + private def inspect_inner + ctypes = self::COMPONENT_TYPES.values.map { |c| c.inspect }.join(", ") + "{ #{ctypes} }" + end + + # def pretty_print(q) + # nil + # end + + def from_ber(str) + ssize = str.bytesize + , pos = check_ber_header(str, constructed: true) + hash = {} + last = nil + self::COMPONENT_TYPES.each do |c| + last ||= str.get_object(pos) + if c.optional? + next if a + end + end + end + end + + def initialize(value) + unless defined?(self.class::COMPONENT_TYPES) + raise "unable to instantiate uninitialized SEQUENCE" + end + @value = value + end + + def [](name) + unless self.class::COMPONENT_TYPES[name] + raise ArgumentError, "invalid component type name: %p" % name + end + @value[name] + end + + def to_der + content = self.class::COMPONENT_TYPES.map { |name, type, opts| + next nil unless @value[name] + @value[name].to_der + }.compact.join + der_header(content.bytesize, :constructed) << content + end +end + +module ASN1Kit::Internal::CompileSequence + refine ASN1Kit::Sequence::ComponentType do + attr_writer :name, :type, :default, :optional + end + + refine ASN1Kit::Sequence.singleton_class do + def _compile_fixup(state) + self::COMPONENT_TYPES.each do |name, c| + if c.type.is_a?(ASN1Kit::Internal::TypeReference) + c.type = c.type.unwrap(state) + end + state.resolve(c.type) + if c.default + c.default.type = c.type # opts[:default] may be still TypeReference at this time + c.default = c.default.unwrap(state) + state.resolve(c.default) + end + end + end + end + + refine ASN1Kit::Sequence do + def _compile_fixup(state) + @value.transform_values! do |value| + value = value.unwrap(state) + state.resolve(value) + value + end + end + end +end |