Skip to content

Commit

Permalink
Add ASN.1 SET/SET_OF support
Browse files Browse the repository at this point in the history
  • Loading branch information
fenrir-naru committed Apr 2, 2024
1 parent 4b80022 commit 2766baf
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 27 deletions.
19 changes: 11 additions & 8 deletions lib/gps_pvt/asn1/asn1.rb
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,8 @@ module GPS_PVT
:ENUMERATED => 10,
:SEQUENCE => 16,
:SEQUENCE_OF => 16,
:SET => 17,
:SET_OF => 17,
:NumericString => 18, # @see Table.6
:PrintableString => 19, # @see Table.6
:IA5String => 22, # @see Table.6
Expand Down Expand Up @@ -333,7 +335,8 @@ module GPS_PVT
}
when :BIT_STRING, :OCTET_STRING
opts[:size_range] = find_range.call(opts, :size)
when :SEQUENCE
when :SEQUENCE, :SET
reorder_children.call(opts) if (opts[:automatic_tagging] == false) # only for SET
(opts[:root] + (opts[:extension] || [])).each.with_index{|v, i|
v[:name] = v[:name] ? v[:name].to_sym : i
v[:type][1][:typename] ||= v[:name] if v[:name].kind_of?(Symbol) && v[:type] # for debugger
Expand All @@ -345,7 +348,7 @@ module GPS_PVT
v2[:name]
} if v[:group]
}
when :SEQUENCE_OF
when :SEQUENCE_OF, :SET_OF
opts[:size_range] = find_range.call(opts, :size)
prepare_coding.call(opts)
when :CHOICE
Expand Down Expand Up @@ -392,7 +395,7 @@ module GPS_PVT
when :BIT_STRING, :OCTET_STRING
data || ({:BIT_STRING => [0], :OCTET_STRING => [0xFF]}[type] \
* (opts[:size_range][:root].first rescue 0))
when :SEQUENCE
when :SEQUENCE, :SET
data ||= {}
Hash[*((opts[:root] + (opts[:extension] || [])).collect{|v|
if v[:group] then
Expand All @@ -406,7 +409,7 @@ module GPS_PVT
end
end
}.compact.flatten(2))]
when :SEQUENCE_OF
when :SEQUENCE_OF, :SET_OF
next data.collect{|v| generate_skeleton.call(opts, v)} if data
v = Marshal::dump(generate_skeleton.call(opts))
(opts[:size_range][:root].first rescue 0).times.collect{
Expand Down Expand Up @@ -508,7 +511,7 @@ module GPS_PVT
end
end
res += data.collect{|v| "%0#{bits}b"%[v]}.join
when :SEQUENCE
when :SEQUENCE, :SET
opt_def_flags, root_encoded = opts[:root].collect{|v| # 18.2
has_elm = data.include?(v[:name])
elm = data[v[:name]]
Expand Down Expand Up @@ -552,7 +555,7 @@ module GPS_PVT
end

"#{ext_bit}#{opt_def_flags.join}#{root_encoded.join}#{ext_encoded}"
when :SEQUENCE_OF
when :SEQUENCE_OF, :SET_OF
ext_bit, len_enc = case (cat = opts[:size_range].belong_to(data.size))
when :additional
# 19.4 -> 10.9.4.2(semi_constrained_whole_number)
Expand Down Expand Up @@ -711,7 +714,7 @@ module GPS_PVT
end
end
str.slice!(0, bits * len).scan(/.{#{bits}}/).collect{|chunk| chunk.to_i(2)}
when :SEQUENCE
when :SEQUENCE, :SET
has_extension = (opts[:extension] && (str.slice!(0) == '1'))
data = Hash[*(
opts[:root].collect{|v| [v[:name], v[:default]] if v[:default]}.compact.flatten(1)
Expand All @@ -729,7 +732,7 @@ module GPS_PVT
v[:group] ? decoded.to_a : [[v[:name], decoded]]
}.compact.flatten(2))]) if has_extension
data
when :SEQUENCE_OF
when :SEQUENCE_OF, :SET_OF
len_dec = if opts[:size_range][:additional] && (str.slice!(0) == '1') then
# 19.4 -> 10.9.4.2(semi_constrained_whole_number)
:length_otherwise
Expand Down
33 changes: 29 additions & 4 deletions lib/gps_pvt/asn1/asn1.y
Original file line number Diff line number Diff line change
Expand Up @@ -179,8 +179,8 @@ rule
#| RelativeOIDType
| SequenceType
| SequenceOfType
#| SetType
#| SetOfType
| SetType
| SetOfType
| TaggedType
| UTCTime # 43. Universal time

Expand Down Expand Up @@ -215,8 +215,8 @@ rule
#| RelativeOIDValue
| SequenceValue # Hash
| SequenceOfValue # Array, Hash
#| SetValue
#| SetOfValue
| SetValue # Hash
| SetOfValue # Array, Hash
#| TaggedValue

#ReferencedValue : DefinedValue | ValueFromObject # 16.11
Expand Down Expand Up @@ -436,6 +436,31 @@ rule
NamedValue {result = val[0]}
| NamedValueList COMMA NamedValue {result = val[0].merge(val[2])}

# 26. Notation for set types
SetType :
/*SET LBRACE RBRACE
| SET LBRACE ExtensionAndException OptionalExtensionMarker RBRACE
|*/ SET LBRACE ComponentTypeLists RBRACE {
# 26.3
val[2].merge!({:automatic_tagging => false}) \
if (@tags != :AUTOMATIC) \
|| (val[2][:root] + (val[2][:extension] || [])).any?{|v|
v[:type][1][:tag] rescue false
}
result = {:type => [val[0], val[2]]}
}

SetValue : SequenceValue # returning Hash

# 27. Notation for set-of types
SetOfType :
SET OF SetOfType_t {
result = {:type => ["#{val[0]}_#{val[1]}".to_sym, val[2]]}
}
SetOfType_t : Type | NamedType

SetOfValue : SequenceOfValue # returning Array or Hash

# 28. Notation for choice types
ChoiceType : CHOICE LBRACE AlternativeTypeLists RBRACE {
# 28.2
Expand Down
30 changes: 15 additions & 15 deletions spec/gps_pvt/asn1/per_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -73,11 +73,11 @@
{"X691_A1": {
"PersonnelRecord": {
"type": [
"SEQUENCE",
"SET",
{"root": [
{"name": "name", "typeref": "Name"},
{"name": "number", "typeref": "EmployeeNumber"},
{"name": "title", "type": ["VisibleString", {"tag": 0}]},
{"name": "number", "typeref": "EmployeeNumber"},
{"name": "dateOfHire", "typeref": "Date", "type": [null, {"tag": 1}]},
{"name": "nameOfSpouse", "typeref": "Name", "type": [null, {"tag": 2}]},
{"name": "children",
Expand All @@ -87,16 +87,16 @@
],
"default": []
}
], "tag": ["APPLICATION", 0]}
], "automatic_tagging": false, "tag": ["APPLICATION", 0]}
]
},
"ChildInformation": {
"type": [
"SEQUENCE",
"SET",
{"root": [
{"name": "name", "typeref": "Name"},
{"name": "dateOfBirth", "typeref": "Date", "type": [null, {"tag": 0}]}
] }
], "automatic_tagging": false}
]
},
"Name": {
Expand All @@ -117,11 +117,11 @@
{"X691_A2": {
"PersonnelRecord": {
"type": [
"SEQUENCE",
"SET",
{"root": [
{"name": "name", "typeref": "Name"},
{"name": "number", "typeref": "EmployeeNumber"},
{"name": "title", "type": ["VisibleString", {"tag": 0}]},
{"name": "number", "typeref": "EmployeeNumber"},
{"name": "dateOfHire", "typeref": "Date", "type": [null, {"tag": 1}]},
{"name": "nameOfSpouse", "typeref": "Name", "type": [null, {"tag": 2}]},
{"name": "children",
Expand All @@ -131,16 +131,16 @@
],
"default": []
}
], "tag": ["APPLICATION", 0]}
], "automatic_tagging": false, "tag": ["APPLICATION", 0]}
]
},
"ChildInformation": {
"type": [
"SEQUENCE",
"SET",
{"root": [
{"name": "name", "typeref": "Name"},
{"name": "dateOfBirth", "typeref": "Date", "type": [null, {"tag": 0}]}
] }
], "automatic_tagging": false}
]
},
"Name": {
Expand Down Expand Up @@ -170,11 +170,11 @@
{"X691_A3": {
"PersonnelRecord": {
"type": [
"SEQUENCE",
"SET",
{"root": [
{"name": "name", "typeref": "Name"},
{"name": "number", "typeref": "EmployeeNumber"},
{"name": "title", "type": ["VisibleString", {"tag": 0}]},
{"name": "number", "typeref": "EmployeeNumber"},
{"name": "dateOfHire", "typeref": "Date", "type": [null, {"tag": 1}]},
{"name": "nameOfSpouse", "typeref": "Name", "type": [null, {"tag": 2}]},
{"name": "children",
Expand All @@ -184,12 +184,12 @@
],
"optional": true
}
], "extension": [], "tag": ["APPLICATION", 0]}
], "extension": [], "automatic_tagging": false, "tag": ["APPLICATION", 0]}
]
},
"ChildInformation": {
"type": [
"SEQUENCE",
"SET",
{"root": [
{"name": "name", "typeref": "Name"},
{"name": "dateOfBirth", "typeref": "Date", "type": [null, {"tag": 0}]}
Expand All @@ -199,7 +199,7 @@
{"root": {"male": 1, "female": 2, "unknown": 3}, "tag": 1}],
"optional": true
}
] }
], "automatic_tagging": false}
]
},
"Name": {
Expand Down

0 comments on commit 2766baf

Please sign in to comment.