diff --git a/lib/gps_pvt/asn1/asn1.rb b/lib/gps_pvt/asn1/asn1.rb index 60d84b6..779b60c 100644 --- a/lib/gps_pvt/asn1/asn1.rb +++ b/lib/gps_pvt/asn1/asn1.rb @@ -1,3 +1,5 @@ +require 'set' + module GPS_PVT end @@ -282,6 +284,23 @@ module GPS_PVT :UTCTime => 23, # @see 43.3 }[type[0]] } + + reorder_children = proc{|type_opts| + # reordering when automatic tagging transformation is not selected + tags = Set[] + [type_opts[:root], type_opts[:extension]].compact.each{|items| + items.collect!{|v| + tag = v[:type][1][:tag] + tag_class_num = case tag + when Array; [{"APPLICATION" => 1, "PRIVATE" => 3}[tag[0]], tag[1]] + when Integer; [2, tag] # (Context-specific) + else; [0, get_universal_class_number.call(v[:type])] # UNIVERSAL + end + raise unless tags.add?(tag_class_num) # Identical tag is already existed! + [v, tag_class_num] + }.sort!{|a, b| a[1] <=> b[1]}.collect!{|v| v[0]} + } + } prepare_coding = proc{|tree| next tree.each{|k, v| @@ -330,17 +349,7 @@ module GPS_PVT opts[:size_range] = find_range.call(opts, :size) prepare_coding.call(opts) when :CHOICE - [opts[:root], opts[:extension]].compact.each{|items| - # reordering when automatic tagging transformation is not selected - items.collect!{|v| - tag_class, tag_num = case v[:tag] - when Array; [{"APPLICATION" => 1, "PRIVATE" => 3}[v[:tag][0]], v[:tag][1]] - when Integer; [2, v[:tag]] # (Context-specific) - else; [0, get_universal_class_number.call(v[:type])] # UNIVERSAL - end - [v, [tag_class, tag_num]] - }.sort!{|a, b| a[1] <=> b[1]}.collect!{|v| v[0]} - } if (opts[:automatic_tagging] == false) + reorder_children.call(opts) if (opts[:automatic_tagging] == false) opts[:extension] = opts[:extension].collect{|v| v[:group] || [v] # 22. Note says "Version brackets have no effect" }.flatten(1) if opts[:extension] diff --git a/lib/gps_pvt/asn1/asn1.y b/lib/gps_pvt/asn1/asn1.y index fcc29d3..1351005 100644 --- a/lib/gps_pvt/asn1/asn1.y +++ b/lib/gps_pvt/asn1/asn1.y @@ -441,7 +441,9 @@ rule # 28.2 val[2].merge!({:automatic_tagging => false}) \ if (@tags != :AUTOMATIC) \ - || (val[2][:root] + (val[2][:extension] || [])).any?{|v| v[:tag]} + || (val[2][:root] + (val[2][:extension] || [])).any?{|v| + v[:type][1][:tag] rescue false + } result = {:type => [val[0], val[2]]} } /* @@ -488,9 +490,11 @@ rule | Tag EXPLICIT Type*/ TaggedType : Tag TaggingConstruction Type { - result = {:tag => val[0]}.merge(val[2]) + result = val[2] # => {} having :type or :typeref keys + result[:type] = [result[:type]].flatten(1) + (result[:type][1] ||= {}).merge!({:tag => val[0]}) # TODO 30.6 c) to check whether Type is an untagged CHOICE after extraction of ReferencedType - result.merge!({:tag_cnstr => val[1]}) if val[1] + result[:type][1].merge!({:tag_cnstr => val[1]}) if val[1] } TaggingConstruction : IMPLICIT {result = nil} diff --git a/lib/gps_pvt/upl/upl.json.gz b/lib/gps_pvt/upl/upl.json.gz index e089711..2de4755 100644 Binary files a/lib/gps_pvt/upl/upl.json.gz and b/lib/gps_pvt/upl/upl.json.gz differ diff --git a/spec/gps_pvt/asn1/per_spec.rb b/spec/gps_pvt/asn1/per_spec.rb index 9467c26..93461aa 100644 --- a/spec/gps_pvt/asn1/per_spec.rb +++ b/spec/gps_pvt/asn1/per_spec.rb @@ -72,24 +72,22 @@ [<<-'__JSON__', {"X691_A1": { "PersonnelRecord": { - "tag": ["APPLICATION", 0], "type": [ "SEQUENCE", {"root": [ {"name": "name", "typeref": "Name"}, {"name": "number", "typeref": "EmployeeNumber"}, - {"name": "title", "tag": 0, "type": "VisibleString"}, - {"name": "dateOfHire", "tag": 1, "typeref": "Date"}, - {"name": "nameOfSpouse", "tag": 2, "typeref": "Name"}, + {"name": "title", "type": ["VisibleString", {"tag": 0}]}, + {"name": "dateOfHire", "typeref": "Date", "type": [null, {"tag": 1}]}, + {"name": "nameOfSpouse", "typeref": "Name", "type": [null, {"tag": 2}]}, {"name": "children", - "tag": 3, "type": [ "SEQUENCE_OF", - {"typeref": "ChildInformation"} + {"typeref": "ChildInformation", "tag": 3} ], "default": [] } - ] } + ], "tag": ["APPLICATION", 0]} ] }, "ChildInformation": { @@ -97,46 +95,43 @@ "SEQUENCE", {"root": [ {"name": "name", "typeref": "Name"}, - {"name": "dateOfBirth", "tag": 0, "typeref": "Date"} + {"name": "dateOfBirth", "typeref": "Date", "type": [null, {"tag": 0}]} ] } ] }, "Name": { - "tag": ["APPLICATION", 1], "type": [ "SEQUENCE", {"root": [ {"name": "givenName", "type": "VisibleString"}, {"name": "initial", "type": "VisibleString"}, {"name": "familyName", "type": "VisibleString"} - ] } + ], "tag": ["APPLICATION", 1]} ] }, -"EmployeeNumber": {"tag": ["APPLICATION", 2], "type": "INTEGER"}, -"Date": {"tag": ["APPLICATION", 3], "type": "VisibleString"} +"EmployeeNumber": {"type": ["INTEGER", {"tag": ["APPLICATION", 2]}]}, +"Date": {"type": ["VisibleString", {"tag": ["APPLICATION", 3]}]} } } __JSON__ <<-'__JSON__', {"X691_A2": { "PersonnelRecord": { - "tag": ["APPLICATION", 0], "type": [ "SEQUENCE", {"root": [ {"name": "name", "typeref": "Name"}, {"name": "number", "typeref": "EmployeeNumber"}, - {"name": "title", "tag": 0, "type": "VisibleString"}, - {"name": "dateOfHire", "tag": 1, "typeref": "Date"}, - {"name": "nameOfSpouse", "tag": 2, "typeref": "Name"}, + {"name": "title", "type": ["VisibleString", {"tag": 0}]}, + {"name": "dateOfHire", "typeref": "Date", "type": [null, {"tag": 1}]}, + {"name": "nameOfSpouse", "typeref": "Name", "type": [null, {"tag": 2}]}, {"name": "children", - "tag": 3, "type": [ "SEQUENCE_OF", - {"typeref": "ChildInformation"} + {"typeref": "ChildInformation", "tag": 3} ], "default": [] } - ] } + ], "tag": ["APPLICATION", 0]} ] }, "ChildInformation": { @@ -144,25 +139,24 @@ "SEQUENCE", {"root": [ {"name": "name", "typeref": "Name"}, - {"name": "dateOfBirth", "tag": 0, "typeref": "Date"} + {"name": "dateOfBirth", "typeref": "Date", "type": [null, {"tag": 0}]} ] } ] }, "Name": { - "tag": ["APPLICATION", 1], "type": [ "SEQUENCE", {"root": [ {"name": "givenName", "typeref": "NameString"}, {"name": "initial", "typeref": "NameString", "type": [null, {"size": 1}]}, {"name": "familyName", "typeref": "NameString"} - ] } + ], "tag": ["APPLICATION", 1]} ] }, -"EmployeeNumber": {"tag": ["APPLICATION", 2], "type": "INTEGER"}, -"Date": {"tag": ["APPLICATION", 3], "type": [ +"EmployeeNumber": {"type": ["INTEGER", {"tag": ["APPLICATION", 2]}]}, +"Date": {"type": [ "VisibleString", - {"from": {"and": [[">=", "0"], ["<=", "9"]]}, "size": 8} + {"tag": ["APPLICATION", 3], "from": {"and": [[">=", "0"], ["<=", "9"]]}, "size": 8} ]}, "NameString": {"type": [ "VisibleString", { @@ -175,24 +169,22 @@ <<-'__JSON__', {"X691_A3": { "PersonnelRecord": { - "tag": ["APPLICATION", 0], "type": [ "SEQUENCE", {"root": [ {"name": "name", "typeref": "Name"}, {"name": "number", "typeref": "EmployeeNumber"}, - {"name": "title", "tag": 0, "type": "VisibleString"}, - {"name": "dateOfHire", "tag": 1, "typeref": "Date"}, - {"name": "nameOfSpouse", "tag": 2, "typeref": "Name"}, + {"name": "title", "type": ["VisibleString", {"tag": 0}]}, + {"name": "dateOfHire", "typeref": "Date", "type": [null, {"tag": 1}]}, + {"name": "nameOfSpouse", "typeref": "Name", "type": [null, {"tag": 2}]}, {"name": "children", - "tag": 3, "type": [ "SEQUENCE_OF", - {"typeref": "ChildInformation", "size": {"root": 2}} + {"typeref": "ChildInformation", "size": {"root": 2}, "tag": 3} ], "optional": true } - ], "extension": [] } + ], "extension": [], "tag": ["APPLICATION", 0]} ] }, "ChildInformation": { @@ -200,37 +192,36 @@ "SEQUENCE", {"root": [ {"name": "name", "typeref": "Name"}, - {"name": "dateOfBirth", "tag": 0, "typeref": "Date"} + {"name": "dateOfBirth", "typeref": "Date", "type": [null, {"tag": 0}]} ], "extension": [ - {"name": "sex", "tag": 1, "type": [ + {"name": "sex", "type": [ "ENUMERATED", - {"root": {"male": 1, "female": 2, "unknown": 3}}], + {"root": {"male": 1, "female": 2, "unknown": 3}, "tag": 1}], "optional": true } ] } ] }, "Name": { - "tag": ["APPLICATION", 1], "type": [ "SEQUENCE", {"root": [ {"name": "givenName", "typeref": "NameString"}, {"name": "initial", "typeref": "NameString", "type": [null, {"size": 1}]}, {"name": "familyName", "typeref": "NameString"} - ], "extension": [] } + ], "extension": [], "tag": ["APPLICATION", 1]} ] }, -"EmployeeNumber": {"tag": ["APPLICATION", 2], "type": [ +"EmployeeNumber": {"type": [ "INTEGER", - {"value": {"root": {"and": [[">=", 0], ["<=", 9999]]}}} + {"value": {"root": {"and": [[">=", 0], ["<=", 9999]]}}, "tag": ["APPLICATION", 2]} ] }, -"Date": {"tag": ["APPLICATION", 3], "type": [ +"Date": {"type": [ "VisibleString", {"from": {"and": [[">=", "0"], ["<=", "9"]]}, "size": { "root": 8, "additional": {"and": [[">=", 9], ["<=", 20]]} - }} + }, "tag": ["APPLICATION", 3]} ]}, "NameString": {"type": [ "VisibleString", {