Class: RASN1::Types::Choice

Inherits:
Base
  • Object
show all
Defined in:
lib/rasn1/types/choice.rb,
lib/rasn1/tracer.rb

Overview

A ASN.1 CHOICE is a choice between different types.

Examples:

Create a CHOICE

choice = Choice.new
choice.value = [Integer.new(implicit: 0, class: :context),
                Integer.new(implicit: 1, class: :context),
                OctetString.new(implicit: 2, class: :context)]
# Choose an element
choice.chosen = 0   # choose int1
# Set chosen value
choise.value[choice.chosen].value = 1
# Also set chosen value
choise.set_chosen_value(1)
# Got chosen value
choise.value[choice.chosen].value # => 1
choice.chosen_value               # => 1

Encode a CHOICE

choice = Choice.new
choice.value = [Integer.new(implicit: 0, class: :context, value: 1),
                Integer.new(implicit: 1, class: :context),
                OctetString.new(implicit: 2, class: :context, value: "a")]
# to_der only encodes the chosen value
choice.chosen = 0   # choose int1
choice.to_der   # => "\x80\x01\x01"
# another choice, another encoding string
choice.chosen_value = 2
choice.to_der   # => "\x82\x01a"

Parse a CHOICE

choice = Choice.new
choice.value = [Integer.new(implicit: 0, class: :context, value: 1),
                Integer.new(implicit: 1, class: :context),
                OctetString.new(implicit: 2, class: :context, value: "a")]
# Parse an octet string
choice.parse!("\x82\x03abc")
choice.chosen        # => 2
choice.chosen_value  # => "abc"
# Parse an unexpected value
choice.parse!("\x04\x03abc") # => RASN1::ASN1Error

Author:

  • Sylvain Daubert

Constant Summary

Constants inherited from Base

Base::CLASSES, Base::CLASS_MASK, Base::INDEFINITE_LENGTH, Base::MULTI_OCTETS_ID

Instance Attribute Summary collapse

Attributes inherited from Base

#asn1_class, #default, #name, #options

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Base

#==, #can_build?, constrained?, #constructed?, #do_parse_explicit, #do_parse_explicit_with_tracing, #do_parse_with_tracing, encoded_type, #explicit?, #id, #implicit?, #initialize, #initialize_copy, #optional?, parse, #primitive?, #specific_initializer, #tagged?, #type, type, #value, #value=, #value?, #value_size

Constructor Details

This class inherits a constructor from RASN1::Types::Base

Instance Attribute Details

#chosenInteger

Chosen type



55
56
57
# File 'lib/rasn1/types/choice.rb', line 55

def chosen
  @chosen
end

Class Method Details

.start_tracingvoid

This method returns an undefined value.

Patch #parse! to add tracing ability



121
122
123
124
# File 'lib/rasn1/tracer.rb', line 121

def start_tracing
  alias_method :parse_without_tracing, :parse!
  alias_method :parse!, :parse_with_tracing
end

.stop_tracingvoid

This method returns an undefined value.

Unpatch #parse! to remove tracing ability



129
130
131
# File 'lib/rasn1/tracer.rb', line 129

def stop_tracing
  alias_method :parse!, :parse_without_tracing
end

Instance Method Details

#chosen_valueObject

Note:

#chosen MUST be set before calling this method

Get chosen value

Raises:



71
72
73
74
75
76
77
78
79
80
81
# File 'lib/rasn1/types/choice.rb', line 71

def chosen_value
  check_chosen
  case @value[@chosen]
  when Base
    @value[@chosen].value
  when Model
    @value[@chosen]
  when Wrapper
    @value[@chosen].element
  end
end

#der_to_value(der, ber: false) ⇒ void

This method returns an undefined value.

Make choice value from DER/BER string.

Since:

  • 0.15.0 Specific #der_to_value to handle recursivity



136
137
138
139
140
141
142
143
144
145
# File 'lib/rasn1/types/choice.rb', line 136

def der_to_value(der, ber: false)
  @value.each_with_index do |element, i|
    @chosen = i
    element.parse!(der, ber: ber)
    break
  rescue ASN1Error
    @chosen = nil
    next
  end
end

#do_parse(der, ber: false) ⇒ Array(::Integer, String)

Raises:

See Also:

Since:

  • 0.15.0 Specific #do_parse to handle recursivity



115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
# File 'lib/rasn1/types/choice.rb', line 115

def do_parse(der, ber: false)
  @value.each_with_index do |element, i|
    @chosen = i
    return element.do_parse(der, ber: ber)
  rescue ASN1Error
    @chosen = nil
    next
  end

  @no_value = true
  @value = void_value
  raise ASN1Error, "CHOICE #{@name}: no type matching #{der.inspect}" unless optional?

  [0, ''.b]
end

#inspect(level = 0) ⇒ String



149
150
151
152
153
154
155
156
# File 'lib/rasn1/types/choice.rb', line 149

def inspect(level=0)
  str = common_inspect(level)
  str << if defined?(@chosen) && value?
           "\n#{@value[@chosen].inspect(level + 1)}"
         else
           ' not chosen!'
         end
end

#parse!(der, ber: false) ⇒ Integer

Parse a DER string. This method updates object by setting #chosen and chosen value.

Raises:



98
99
100
101
102
103
104
105
106
107
108
109
# File 'lib/rasn1/types/choice.rb', line 98

def parse!(der, ber: false)
  len, data = do_parse(der, ber: ber)
  return 0 if len.zero?

  element = @value[@chosen]
  if element.explicit?
    element.do_parse_explicit(data)
  else
    element.der_to_value(data, ber: ber)
  end
  len
end

#parse_with_tracing(der, ber: false) ⇒ Object

Parse der with tracing abillity

See Also:



138
139
140
141
# File 'lib/rasn1/tracer.rb', line 138

def parse_with_tracing(der, ber: false)
  RASN1.tracer.trace(self.trace)
  parse_without_tracing(der, ber: ber)
end

#set_chosen_value(value) ⇒ Object

Note:

#chosen MUST be set before calling this method

Set chosen value.

Raises:



62
63
64
65
# File 'lib/rasn1/types/choice.rb', line 62

def set_chosen_value(value) # rubocop:disable Naming/AccessorMethodName
  check_chosen
  @value[@chosen].value = value
end

#to_derString

Note:

#chosen MUST be set before calling this method

Encode Choice into DER encoding

Raises:



87
88
89
90
# File 'lib/rasn1/types/choice.rb', line 87

def to_der
  check_chosen
  @value[@chosen].to_der
end

#traceString



160
161
162
# File 'lib/rasn1/types/choice.rb', line 160

def trace
  msg_type(no_id: true)
end

#void_valueArray

Return empty array

Since:

  • 0.15.0



167
168
169
# File 'lib/rasn1/types/choice.rb', line 167

def void_value
  []
end