pax_global_header00006660000000000000000000000064151552260020014510gustar00rootroot0000000000000052 comment=cb0089901d6b01e68ed54f12f734f863c4bd9361 danini-the-panini-kdl-rb-56d7cf1/000077500000000000000000000000001515522600200165765ustar00rootroot00000000000000danini-the-panini-kdl-rb-56d7cf1/.github/000077500000000000000000000000001515522600200201365ustar00rootroot00000000000000danini-the-panini-kdl-rb-56d7cf1/.github/workflows/000077500000000000000000000000001515522600200221735ustar00rootroot00000000000000danini-the-panini-kdl-rb-56d7cf1/.github/workflows/ruby.yml000066400000000000000000000021051515522600200236750ustar00rootroot00000000000000# This workflow uses actions that are not certified by GitHub. # They are provided by a third-party and are governed by # separate terms of service, privacy policy, and support # documentation. # This workflow will download a prebuilt Ruby version, install dependencies and run tests with Rake # For more information see: https://github.com/marketplace/actions/setup-ruby-jruby-and-truffleruby name: Ruby on: push: branches: [ main ] pull_request: branches: [ main ] jobs: test: continue-on-error: ${{ matrix.ruby == 'head' }} strategy: matrix: ruby: [3.2, 3.3, 3.4, 4.0, head] runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 with: submodules: true - name: Set up Ruby uses: ruby/setup-ruby@v1 with: ruby-version: ${{ matrix.ruby }} bundler-cache: true # install and cache dependencies - name: Build parser run: bundle exec racc lib/kdl/kdl.yy - name: Run tests run: bundle exec rake test - name: Report Coveralls uses: coverallsapp/github-action@v2 danini-the-panini-kdl-rb-56d7cf1/.gitignore000066400000000000000000000002141515522600200205630ustar00rootroot00000000000000/.bundle/ /.yardoc /_yardoc/ /coverage/ /doc/ /pkg/ /spec/reports/ /tmp/ Gemfile.lock lib/kdl/kdl.tab.rb lib/kdl/v1/kdl.tab.rb kdl.output danini-the-panini-kdl-rb-56d7cf1/.gitmodules000066400000000000000000000002771515522600200207610ustar00rootroot00000000000000[submodule "test/kdl-org"] path = test/kdl-org url = git@github.com:kdl-org/kdl [submodule "test/v1/kdl-org"] path = test/v1/kdl-org url = git@github.com:kdl-org/kdl branch = release/v1 danini-the-panini-kdl-rb-56d7cf1/CODE_OF_CONDUCT.md000066400000000000000000000153051515522600200214010ustar00rootroot00000000000000# Code of Conduct ## When Something Happens If you see behavoir that makes you feel unsafe or unwelcome or otherwise uncomfortable, follow these steps: 1. Let the person know that what they did is not appropriate and ask them to stop and/or edit their message(s) or commits. 2. That person should immediately stop the behavior and correct the issue. 3. If this doesnโ€™t happen, or if you're uncomfortable speaking up, [contact the maintainers](#contacting-maintainers). 4. As soon as available, a maintainer will look into the issue, and take [further action (see below)](#further-enforcement), starting with a warning, then temporary block, then long-term repo or organization ban. **The maintainer team will prioritize the well-being and comfort of those affected over the comfort of the offending party.** See [some examples below](#enforcement-examples). ## Our Pledge In the interest of fostering an open and welcoming environment, we as contributors and maintainers of this project pledge to making participation in our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, technical preferences, nationality, personal appearance, race, religion, or sexual identity and orientation. This commitment means that inappropriate behavior can lead to intervention. This includes our intention to address issues with [missing stairs](https://en.wikipedia.org/wiki/Missing_stair) who may not have explicitly violated any written-down rules but might still be disrupting the community. ## Scope This Code of Conduct applies both within spaces involving this project and in other spaces involving community members. This includes the repository, its Pull Requests and Issue tracker, its Twitter community, private email communications in the context of the project, and any events where members of the project are participating, as well as adjacent communities and venues affecting the project's members. Depending on the violation, the maintainers may decide that violations of this code of conduct that have happened outside of the scope of the community may deem an individual unwelcome, and take appropriate action to maintain the comfort and safety of its members. ## Contacting Maintainers - [Dan Smith ](mailto:danini@hey.com) ## Further Enforcement If you've already followed the [initial enforcement steps](#enforcement), these are the steps maintainers will take for further enforcement, as needed: 1. Repeat the request to stop. 2. If the person doubles down, they will have offending messages removed or edited by a maintainers given an official warning. The PR or Issue may be locked. 3. If the behavior continues or is repeated later, the person will be blocked from participating for 24 hours. 4. If the behavior continues or is repeated after the temporary block, a long-term (6-12mo) ban will be used. On top of this, maintainers may remove any offending messages, images, contributions, etc, as they deem necessary. Maintainers reserve full rights to skip any of these steps, at their discretion, if the violation is considered to be a serious and/or immediate threat to the health and well-being of members of the community. These include any threats, serious physical or verbal attacks, and other such behavior that would be completely unacceptable in any social setting that puts our members at risk. Members expelled from events or venues with any sort of paid attendance will not be refunded. ## Who Watches the Watchers? Maintainers and other leaders who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. These may include anything from removal from the maintainer team to a permanent ban from the community. Additionally, as a project hosted on both GitHub, [their Community Guidielines may be applied to maintainers of this project](https://help.github.com/articles/github-community-guidelines/), externally of this project's procedures. ## Enforcement Examples ### The Best Case The vast majority of situations work out like this. This interaction is common, and generally positive. > Alex: "Yeah I used X and it was really crazy!" > Patt (not a maintainer): "Hey, could you not use that word? What about 'ridiculous' instead?" > Alex: "oh sorry, sure." -> edits old comment to say "it was really confusing!" ### The Maintainer Case Sometimes, though, you need to get maintainers involved. Maintainers will do their best to resolve conflicts, but people who were harmed by something **will take priority**. > Patt: "Honestly, sometimes I just really hate using $library and anyone who uses it probably sucks at their job." > Alex: "Whoa there, could you dial it back a bit? There's a CoC thing about attacking folks' tech use like that." > Patt: "I'm not attacking anyone, what's your problem?" > Alex: "@maintainers hey uh. Can someone look at this issue? Patt is getting a bit aggro. I tried to nudge them about it, but nope." > KeeperOfCommitBits: (on issue) "Hey Patt, maintainer here. Could you tone it down? This sort of attack is really not okay in this space." > Patt: "Leave me alone I haven't said anything bad wtf is wrong with you." > KeeperOfCommitBits: (deletes user's comment), "@patt I mean it. Please refer to the CoC over at (URL to this CoC) if you have questions, but you can consider this an actual warning. I'd appreciate it if you reworded your messages in this thread, since they made folks there uncomfortable. Let's try and be kind, yeah?" > Patt: "@keeperofbits Okay sorry. I'm just frustrated and I'm kinda burnt out and I guess I got carried away. I'll DM Alex a note apologizing and edit my messages. Sorry for the trouble." > KeeperOfCommitBits: "@patt Thanks for that. I hear you on the stress. Burnout sucks :/. Have a good one!" ### The Nope Case > PepeTheFrog๐Ÿธ: "Hi, I am a literal actual nazi and I think white supremacists are quite fashionable." > Patt: "NOOOOPE. OH NOPE NOPE." > Alex: "JFC NO. NOPE. @keeperofbits NOPE NOPE LOOK HERE" > KeeperOfCommitBits: "๐Ÿ‘€ Nope. NOPE NOPE NOPE. ๐Ÿ”ฅ" > PepeTheFrog๐Ÿธ has been banned from all organization or user repositories belonging to KeeperOfCommitBits. ## Attribution This Code of Conduct was generated using [WeAllJS Code of Conduct Generator](https://npm.im/weallbehave), which is based on the [WeAllJS Code of Conduct](https://wealljs.org/code-of-conduct), which is itself based on [Contributor Covenant](http://contributor-covenant.org), version 1.4, available at [http://contributor-covenant.org/version/1/4](http://contributor-covenant.org/version/1/4), and the LGBTQ in Technology Slack [Code of Conduct](http://lgbtq.technology/coc.html). danini-the-panini-kdl-rb-56d7cf1/Gemfile000066400000000000000000000003511515522600200200700ustar00rootroot00000000000000source "https://rubygems.org" # Specify your gem's dependencies in kdl.gemspec gemspec gem "rake", "~> 13.0" group :test do gem "minitest", "~> 6.0" gem "simplecov", require: false gem "coveralls_reborn", require: false end danini-the-panini-kdl-rb-56d7cf1/LICENSE.txt000066400000000000000000000020671515522600200204260ustar00rootroot00000000000000The MIT License (MIT) Copyright (c) 2020 Daniel Smith Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. danini-the-panini-kdl-rb-56d7cf1/README.md000066400000000000000000000073401515522600200200610ustar00rootroot00000000000000# KDL [![Gem Version](https://badge.fury.io/rb/kdl.svg)](https://badge.fury.io/rb/kdl) [![Actions Status](https://github.com/danini-the-panini/kdl-rb/workflows/Ruby/badge.svg)](https://github.com/danini-the-panini/kdl-rb/actions) [![Coverage Status](https://coveralls.io/repos/github/danini-the-panini/kdl-rb/badge.svg?branch=main)](https://coveralls.io/github/danini-the-panini/kdl-rb?branch=main) This is a Ruby implementation of the [KDL Document Language](https://kdl.dev) ## Installation Add this line to your application's Gemfile: ```ruby gem 'kdl' ``` And then execute: $ bundle install Or install it yourself as: $ gem install kdl ## Usage ```ruby require 'kdl' KDL.parse(a_string) #=> KDL::Document KDL.load_file('path/to/file') #=> KDL::Document ``` You can optionally provide your own type annotation handlers: ```ruby class Foo < KDL::Value::Custom end KDL.parse(a_string, type_parsers: { 'foo' => Foo }) ``` The `foo` custom type will be called with instances of Value or Node with the type annotation `(foo)`. Custom types are expected to have a `call` method that takes the Value or Node, and the type annotation itself, as arguments, and is expected to return either an instance of `KDL::Value::Custom` or `KDL::Node::Custom` (depending on the input type) or `nil` to return the original value as is. Take a look at [the built in custom types](lib/kdl/types) as a reference. You can also disable type annotation parsing entirely (including the built in ones): ```ruby KDL.parse(a_string, parse_types: false) ``` ## KDL v1 kdl-rb maintains backwards compatibility with the KDL v1 spec. By default, KDL will attempt to parse a file with the v1 parser if it fails to parse with v2. This behaviour can be changed by specifying the `version` option: ```ruby KDL.parse(a_string, version: 2) ``` The resulting document will also serialize back to the same version it was parsed as. For example, if you parse a v2 document and call `to_s` on it, it will output a v2 document, and similarly with v1. This behaviour can be changed by specifying the `output_version` option: ```ruby KDL.parse(a_string, output_version: 2) ``` This allows you to to convert documents between versions: ```ruby KDL.parse('foo "bar" true', version: 1, output_version: 2).to_s #=> 'foo bar #true' ``` You can also convert an already parsed document between versions with `to_v1` and `to_v2`: ```ruby doc = KDL.parse('foo "bar" true', version: 1) doc.version #=> 1 doc.to_v2.to_s #=> 'foo bar #true' ``` You can also set the default version globally: ```ruby KDL.default_version = 2 KDL.default_output_version = 2 ``` You can still force automatic version detection with `auto_parse`: ```ruby KDL.default_version = 2 KDL.parse('foo "bar" true') #=> Error KDL.auto_parse('foo "bar" true') #=> KDL::V1::Document ``` Version directives are also respected: ```ruby KDL.parse("/- kdl-version 2\nfoo bar", version: 1) #=> Version mismatch, document specified v2, but this is a v1 parser (Racc::ParseError) ``` ## Development After checking out the repo, run `bin/setup` to install dependencies. Then, run `bin/rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment. To install this gem onto your local machine, run `bin/rake install`. To release a new version, update the version number in `version.rb`, and then run `bin/rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org). ## Contributing Bug reports and pull requests are welcome on GitHub at https://github.com/danini-the-panini/kdl-rb. ## License The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT). danini-the-panini-kdl-rb-56d7cf1/Rakefile000066400000000000000000000011111515522600200202350ustar00rootroot00000000000000require 'bundler/gem_tasks' require 'rake/testtask' file 'lib/kdl/kdl.tab.rb' => ['lib/kdl/kdl.yy'] do raise "racc command failed" unless system 'bin/racc lib/kdl/kdl.yy' end task :racc => 'lib/kdl/kdl.tab.rb' file 'lib/kdl/v1/kdl.tab.rb' => ['lib/kdl/v1/kdl.yy'] do raise "racc command failed (v1)" unless system 'bin/racc lib/kdl/v1/kdl.yy' end task :racc_v1 => 'lib/kdl/v1/kdl.tab.rb' Rake::TestTask.new(:test => [:racc, :racc_v1]) do |t| t.libs << 'test' t.libs << 'lib' t.test_files = FileList['test/**/*_test.rb'] t.options = '--pride' end task :default => :test danini-the-panini-kdl-rb-56d7cf1/bin/000077500000000000000000000000001515522600200173465ustar00rootroot00000000000000danini-the-panini-kdl-rb-56d7cf1/bin/console000077500000000000000000000005521515522600200207400ustar00rootroot00000000000000#!/usr/bin/env ruby require "bundler/setup" require "kdl" # You can add fixtures and/or initialization code here to make experimenting # with your gem easier. You can also use a different console, if you like. # (If you use this, don't forget to add pry to your Gemfile!) # require "pry" # Pry.start system 'bin/rake racc' require "irb" IRB.start(__FILE__) danini-the-panini-kdl-rb-56d7cf1/bin/kdl000077500000000000000000000001631515522600200200460ustar00rootroot00000000000000#!/usr/bin/env ruby require "bundler/setup" require "kdl" system 'bin/rake racc' puts KDL.parse(ARGF.read).to_s danini-the-panini-kdl-rb-56d7cf1/bin/racc000077500000000000000000000014231515522600200202040ustar00rootroot00000000000000#!/usr/bin/env ruby # frozen_string_literal: true # # This file was generated by Bundler. # # The application 'racc' is installed as part of a gem, and # this file is here to facilitate running it. # require "pathname" ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", Pathname.new(__FILE__).realpath) bundle_binstub = File.expand_path("../bundle", __FILE__) if File.file?(bundle_binstub) if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ load(bundle_binstub) else abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") end end require "rubygems" require "bundler/setup" load Gem.bin_path("racc", "racc") danini-the-panini-kdl-rb-56d7cf1/bin/rake000077500000000000000000000014231515522600200202160ustar00rootroot00000000000000#!/usr/bin/env ruby # frozen_string_literal: true # # This file was generated by Bundler. # # The application 'rake' is installed as part of a gem, and # this file is here to facilitate running it. # require "pathname" ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", Pathname.new(__FILE__).realpath) bundle_binstub = File.expand_path("../bundle", __FILE__) if File.file?(bundle_binstub) if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ load(bundle_binstub) else abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") end end require "rubygems" require "bundler/setup" load Gem.bin_path("rake", "rake") danini-the-panini-kdl-rb-56d7cf1/bin/setup000077500000000000000000000002711515522600200204340ustar00rootroot00000000000000#!/usr/bin/env bash set -euo pipefail IFS=$'\n\t' set -vx bundle install # Do any other automated setup that you need to do here bin/rake racc git submodule update --init --recursive danini-the-panini-kdl-rb-56d7cf1/kdl.gemspec000066400000000000000000000024461515522600200207230ustar00rootroot00000000000000require_relative 'lib/kdl/version' Gem::Specification.new do |spec| spec.name = "kdl" spec.version = KDL::VERSION spec.authors = ["Danielle Smith"] spec.email = ["danini@hey.com"] spec.summary = %q{KDL Document Language} spec.description = %q{Ruby implementation of the KDL Document Language Spec} spec.homepage = "https://kdl.dev" spec.license = "MIT" spec.required_ruby_version = Gem::Requirement.new(">= 3.2.0") spec.metadata["homepage_uri"] = spec.homepage spec.metadata["source_code_uri"] = "https://github.com/danini-the-panini/kdl-rb" spec.metadata["changelog_uri"] = "https://github.com/danini-the-panini/kdl-rb/releases" # Specify which files should be added to the gem when it is released. # The `git ls-files -z` loads the files in the RubyGem that have been added into git. spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) } end + ['lib/kdl/kdl.tab.rb', 'lib/kdl/v1/kdl.tab.rb'] spec.bindir = "exe" spec.require_paths = ["lib"] spec.add_dependency 'racc', '~> 1.5' spec.add_dependency 'simpleidn', '~> 0.2.1' spec.add_dependency 'bigdecimal', '~> 3.1.6' spec.add_dependency 'base64', '~> 0.2.0' end danini-the-panini-kdl-rb-56d7cf1/lib/000077500000000000000000000000001515522600200173445ustar00rootroot00000000000000danini-the-panini-kdl-rb-56d7cf1/lib/kdl.rb000066400000000000000000000041101515522600200204370ustar00rootroot00000000000000# frozen_string_literal: true require "kdl/version" require "kdl/error" require "kdl/tokenizer" require "kdl/document" require "kdl/value" require "kdl/node" require "kdl/string_dumper" require "kdl/types" require "kdl/parser_common" require "kdl/kdl.tab" require "kdl/builder" require "kdl/v1" module KDL class << self attr_accessor :default_version attr_accessor :default_output_version end def self.parse_document(input, options = {}) warn "[DEPRECATION] `KDL.parse_document' is deprecated. Please use `KDL.parse' instead." parse(input, **options) end def self.parse(input, version: default_version, output_version: default_output_version, filename: nil, **options) case version when 2 Parser.new(output_module: output_module(output_version || 2), **options).parse(input, filename:) when 1 V1::Parser.new.parse(input, output_module: output_module(output_version || 1), filename:, **options) when nil auto_parse(input, output_version:, **options) else raise UnsupportedVersionError.new("unsupported version '#{version}'", version) end end def self.load_file(filespec, **options) File.open(filespec, 'r:BOM|UTF-8') do |file| parse(file.read, **options, filename: file.to_path) end end def self.auto_parse(input, output_version: default_output_version, **options) parse(input, version: 2, output_version: output_version || 2, **options) rescue VersionMismatchError => e parse(input, version: e.version, output_version: output_version || e.version, **options) rescue ParseError => e parse(input, version: 1, output_version: output_version || 1, **options) rescue raise e end def self.output_module(version) case version when 1 then KDL::V1 when 2 then KDL else warn "[WARNING] Unknown output_version '#{version}', defaulting to v2" KDL end end def self.build(&block) builder = Builder.new if block.arity >= 1 builder.document do yield builder end else builder.instance_exec(&block) builder.document end end end danini-the-panini-kdl-rb-56d7cf1/lib/kdl/000077500000000000000000000000001515522600200201165ustar00rootroot00000000000000danini-the-panini-kdl-rb-56d7cf1/lib/kdl/builder.rb000066400000000000000000000030021515522600200220640ustar00rootroot00000000000000# frozen_string_literal: true module KDL class Builder < BasicObject class Error < ::KDL::Error; end def initialize @nesting = [] @document = Document.new end def document(&block) yield if block @document end def node(name = nil, *args, type: nil, **props, &block) n = Node.new(name&.to_s || "node", type:) @nesting << n args.each do |value| case value when ::Hash value.each { |k, v| prop k, v } else arg value end end props.each do |key, value| prop key, value end yield if block @nesting.pop if parent = current_node parent.children << n else @document << n end n end alias _ node def arg(value, type: nil) if n = current_node val = Value.from(value) val = val.as_type(type) if type n.arguments << val val else raise Error, "Can't do argument, not inside Node" end end def prop(key, value, type: nil) key = key.to_s if n = current_node val = Value.from(value) val = val.as_type(type) if type n.properties[key] = val val else raise Error, "Can't do property, not inside Node" end end def method_missing(name, *args, **props, &block) node name, *args, **props, &block end private def current_node return nil if @nesting.empty? @nesting.last end end end danini-the-panini-kdl-rb-56d7cf1/lib/kdl/document.rb000066400000000000000000000024771515522600200222730ustar00rootroot00000000000000# frozen_string_literal: true module KDL class Document include Enumerable attr_accessor :nodes def initialize(nodes = []) @nodes = nodes end def [](key) case key when Integer nodes[key] when String, Symbol nodes.find { _1.name == key.to_s } else raise ArgumentError, "document can only be indexed by Integer, String, or Symbol" end end def <<(node) nodes << node end def arg(key) self[key]&.arguments&.first&.value end def args(key) self[key]&.arguments&.map(&:value) end def each_arg(key, &block) args(key)&.each(&block) end def dash_vals(key) self[key] &.children &.select { _1.name == "-" } &.map { _1.arguments.first&.value } end def each_dash_val(key, &block) dash_vals(key)&.each(&block) end def each(&block) nodes.each(&block) end def to_s nodes.map(&:to_s).join("\n") + "\n" end def inspect nodes.map(&:inspect).join("\n") + "\n" end def ==(other) return false unless other.is_a?(Document) nodes == other.nodes end def version 2 end def to_v2 self end def to_v1 KDL::V1::Document.new(nodes.map(&:to_v1)) end end end danini-the-panini-kdl-rb-56d7cf1/lib/kdl/error.rb000066400000000000000000000016551515522600200216030ustar00rootroot00000000000000# frozen_string_literal: true module KDL class Error < StandardError attr_reader :filename, :line, :column def initialize(message, filename = nil, line = nil, column = nil) message += " (#{line}:#{column})" if line message = "#{[filename, line, column].compact.join(':')}: #{message}" if filename super(message) @filename = filename @line = line @column = column end end class VersionMismatchError < Error attr_reader :version, :parser_version def initialize(message, version = nil, parser_version = nil, filename = nil) super(message, filename, 1, 1) @version = version @parser_version = parser_version end end class UnsupportedVersionError < Error attr_reader :version def initialize(message, version = nil, filename = nil) super(message, filename, 1, 1) @version = version end end class ParseError < Error; end end danini-the-panini-kdl-rb-56d7cf1/lib/kdl/kdl.yy000066400000000000000000000101341515522600200212520ustar00rootroot00000000000000class KDL::Parser options no_result_var token IDENT STRING RAWSTRING INTEGER FLOAT TRUE FALSE NULL WS NEWLINE LBRACE RBRACE LPAREN RPAREN EQUALS SEMICOLON EOF SLASHDASH rule document : nodes { @output_module::Document.new(val[0]) } | linespaces { @output_module::Document.new([]) } nodes : none { [] } | linespaces node { [val[1]] } | linespaces empty_node { [] } | nodes node { [*val[0], val[1]] } | nodes empty_node { val[0] } node : unterm_node node_term { val[0] } unterm_node : untyped_node { val[0] } | type untyped_node { val[1].as_type(val[0], @type_parsers.fetch(val[0], nil)) } untyped_node : node_decl { val[0].tap { |x| x.children = [] } } | node_decl ws_star node_children { val[0].tap { |x| x.children = val[2] } } | node_decl ws_star empty_childrens { val[0].tap { |x| x.children = [] } } | node_decl ws_star empty_childrens node_children { val[0].tap { |x| x.children = val[3] } } | node_decl ws_star node_children empty_childrens { val[0].tap { |x| x.children = val[2] } } | node_decl ws_star empty_childrens node_children empty_childrens { val[0].tap { |x| x.children = val[3] } } node_decl : identifier { @output_module::Node.new(val[0]) } | node_decl ws_plus value { val[0].tap { |x| x.arguments << val[2] } } | node_decl ws_star slashdash value { val[0] } | node_decl ws_plus property { val[0].tap { |x| x.properties[val[2][0]] = val[2][1] } } | node_decl ws_star slashdash property { val[0] } | node_decl ws_plus { val[0] } empty_node : slashdash node node_children : ws_star LBRACE nodes RBRACE { val[2] } | ws_star LBRACE linespaces RBRACE { [] } | ws_star LBRACE nodes unterm_node ws_star RBRACE { [*val[2], val[3]] } | ws_star LBRACE linespaces unterm_node ws_star RBRACE { [val[3]] } empty_children : slashdash node_children | ws_plus empty_children empty_childrens: empty_children | empty_childrens empty_children node_term: linespaces | semicolon_term semicolon_term: SEMICOLON | SEMICOLON linespaces slashdash: SLASHDASH | slashdash linespaces type : LPAREN ws_star identifier ws_star RPAREN ws_star { val[2] } identifier : IDENT { val[0].value } | STRING { val[0].value } | RAWSTRING { val[0].value } property : identifier EQUALS value { [val[0], val[2]] } value : untyped_value | type untyped_value { val[1].as_type(val[0], @type_parsers.fetch(val[0], nil)) } untyped_value : IDENT { @output_module::Value::String.new(val[0].value) } | STRING { @output_module::Value::String.new(val[0].value) } | RAWSTRING { @output_module::Value::String.new(val[0].value) } | INTEGER { @output_module::Value::Int.new(val[0].value) } | FLOAT { @output_module::Value::Float.new(val[0].value, format: val[0].meta[:format]) } | boolean { @output_module::Value::Boolean.new(val[0]) } | NULL { @output_module::Value::Null } boolean : TRUE { true } | FALSE { false } ws_plus: WS | WS ws_plus ws_star: none | ws_plus linespace: WS | NEWLINE | EOF linespaces: linespace | linespaces linespace none: { nil } ---- inner include KDL::ParserCommon def initialize(**options) init(**options) end def parser_version 2 end def parse(str, filename: nil) @tokenizer = ::KDL::Tokenizer.new(str, filename:) check_version do_parse end danini-the-panini-kdl-rb-56d7cf1/lib/kdl/node.rb000066400000000000000000000067631515522600200214040ustar00rootroot00000000000000# frozen_string_literal: true module KDL class Node class Custom < Node def self.call(node, type) new(node.name, arguments: node.arguments, properties: node.properties, children: node.children, type:) end def version nil end def to_v1 self end def to_v2 self end end include Enumerable attr_accessor :name, :arguments, :properties, :children, :type def initialize(name, _args = [], _props = {}, _children = [], arguments: _args, properties: _props, children: _children, type: nil ) @name = name @arguments = arguments @properties = properties.transform_keys(&:to_s) @children = children @type = type end def [](key) case key when Integer arguments[key]&.value when String, Symbol properties[key.to_s]&.value else raise ArgumentError, "node can only be indexed by Integer, String, or Symbol" end end def <<(node) children << node end def child(key) case key when Integer children[key] when String, Symbol children.find { _1.name == key.to_s } else raise ArgumentError, "node can only be indexed by Integer, String, or Symbol" end end def arg(key) child(key)&.arguments&.first&.value end def args(key) child(key)&.arguments&.map(&:value) end def each_arg(key, &block) args(key)&.each(&block) end def dash_vals(key) child(key) &.children &.select { _1.name == "-" } &.map { _1.arguments.first&.value } end def each_dash_val(key, &block) dash_vals(key)&.each(&block) end def each(&block) children.each(&block) end def <=>(other) name <=> other.name end def to_s(level = 0, m = :to_s) indent = ' ' * level s = "#{indent}#{type ? "(#{id_to_s type, m })" : ''}#{id_to_s name, m}" unless arguments.empty? s << " #{arguments.map(&m).join(' ')}" end unless properties.empty? s << " #{properties.map { |k, v| "#{id_to_s k, m}=#{v.public_send(m)}" }.join(' ')}" end unless children.empty? s << " {\n" s << children.map { |c| "#{c.public_send(m, level + 1)}" }.join("\n") s << "\n#{indent}}" end s end def inspect(level = 0) to_s(level, :inspect) end def ==(other) return false unless other.is_a?(Node) name == other.name && arguments == other.arguments && properties == other.properties && children == other.children end def as_type(type, parser = nil) if parser.nil? @type = type self else result = parser.call(self, type) return self.as_type(type) if result.nil? unless result.is_a?(::KDL::Node::Custom) raise ArgumentError, "expected parser to return an instance of ::KDL::Node::Custom, got `#{result.class}'" end result end end def version 2 end def to_v2 self end def to_v1 ::KDL::V1::Node.new(name, arguments: arguments.map(&:to_v1), properties: properties.transform_values(&:to_v1), children: children.map(&:to_v1), type: type ) end private def id_to_s(id, m = :to_s) return id.public_send(m) unless m == :to_s StringDumper.call(id.to_s) end end end danini-the-panini-kdl-rb-56d7cf1/lib/kdl/parser_common.rb000066400000000000000000000015561515522600200233160ustar00rootroot00000000000000# frozen_string_literal: true module KDL module ParserCommon private def init(parse_types: true, type_parsers: {}, output_module: ::KDL) @output_module = output_module if parse_types @type_parsers = ::KDL::Types::MAPPING.merge(type_parsers) else @type_parsers = {} end end def next_token @tokenizer.next_token end def check_version return unless doc_version = @tokenizer.version_directive if doc_version != parser_version raise VersionMismatchError.new("version mismatch, document specified v#{doc_version}, but this is a v#{parser_version} parser", doc_version, parser_version) end end def on_error(t, val, vstack) raise KDL::ParseError.new("unexpected #{token_to_str(t)} #{val&.value.inspect}", @tokenizer.filename, val&.line, val&.column) end end end danini-the-panini-kdl-rb-56d7cf1/lib/kdl/string_dumper.rb000066400000000000000000000015721515522600200233320ustar00rootroot00000000000000# frozen_string_literal: true module KDL module StringDumper def call(string) return string if bare_identifier?(string) %("#{string.each_char.map { |char| escape(char) }.join}") end private def escape(char) case char when "\n" then '\n' when "\r" then '\r' when "\t" then '\t' when '\\' then '\\\\' when '"' then '\"' when "\b" then '\b' when "\f" then '\f' else char end end FORBIDDEN = Tokenizer::SYMBOLS.keys + Tokenizer::WHITESPACE + Tokenizer::NEWLINES + "()[]/\\\"#".chars + ("\x0".."\x20").to_a def bare_identifier?(name) case name when '', 'true', 'false', 'null', '#true', '#false', '#null', /\A\.?\d/ false else !name.each_char.any? { |c| FORBIDDEN.include?(c) } end end extend self end end danini-the-panini-kdl-rb-56d7cf1/lib/kdl/tokenizer.rb000066400000000000000000000446621515522600200224710ustar00rootroot00000000000000# frozen_string_literal: true require 'bigdecimal' module KDL class Tokenizer class Token attr_reader :type, :value, :line, :column, :meta def initialize(type, value, line, column, meta = {}) @type = type @value = value @line = line @column = column @meta = meta end def ==(other) return false unless other.is_a?(Token) type == other.type && value == other.value && line == other.line && column == other.column end def to_s "#{value.inspect} (#{line}:#{column})" end end attr_reader :index, :filename SYMBOLS = { '{' => :LBRACE, '}' => :RBRACE, ';' => :SEMICOLON, '=' => :EQUALS } WHITESPACE = ["\u0009", "\u0020", "\u00A0", "\u1680", "\u2000", "\u2001", "\u2002", "\u2003", "\u2004", "\u2005", "\u2006", "\u2007", "\u2008", "\u2009", "\u200A", "\u202F", "\u205F", "\u3000"] WS = "[#{Regexp.escape(WHITESPACE.join)}]" WS_STAR = /\A#{WS}*\z/ WS_PLUS = /\A#{WS}+\z/ NEWLINES = ["\u000A", "\u0085", "\u000B", "\u000C", "\u2028", "\u2029"] NEWLINES_PATTERN = Regexp.new("(#{NEWLINES.map{Regexp.escape(_1)}.join('|')}|\r\n?)", Regexp::MULTILINE) OTHER_NON_IDENTIFIER_CHARS = ("\x0".."\x20").to_a - WHITESPACE NON_IDENTIFIER_CHARS = Regexp.escape "#{SYMBOLS.keys.join}()[]/\\\"##{WHITESPACE.join}#{OTHER_NON_IDENTIFIER_CHARS.join}" IDENTIFIER_CHARS = /[^#{NON_IDENTIFIER_CHARS}]/ INITIAL_IDENTIFIER_CHARS = /[^#{NON_IDENTIFIER_CHARS}0-9]/ FORBIDDEN = [ *"\u0000".."\u0008", *"\u000E".."\u001F", "\u007F", *"\u200E".."\u200F", *"\u202A".."\u202E", *"\u2066".."\u2069", "\uFEFF" ] VERSION_PATTERN = /\A\/-[#{WHITESPACE.join}]*kdl-version[#{WHITESPACE.join}]+(\d+)[#{WHITESPACE.join}]*[#{NEWLINES.join}]/ def initialize(str, start = 0, filename: nil) @str = debom(str) @start = start @index = start @buffer = +"" @filename = filename @context = nil @rawstring_hashes = nil @done = false @previous_context = nil @line = 1 @column = 1 @type_context = false @last_token = nil end def version_directive if m = @str.match(VERSION_PATTERN) m[1].to_i end end def done? @done end def [](i) @str[i].tap do |c| raise_error "Forbidden character: #{c.inspect}" if FORBIDDEN.include?(c) end end def tokens a = [] while !done? a << next_token end a end def next_token @context = nil @previous_context = nil @line_at_start = @line @column_at_start = @column loop do c = self[@index] case @context when nil case c when '"' if self[@index + 1] == '"' && self[@index + 2] == '"' nl = expect_newline(@index + 3) self.context = :multiline_string @buffer = +'' traverse(3 + nl.length) else self.context = :string @buffer = +'' traverse(1) end when '#' if self[@index + 1] == '"' if self[@index + 2] == '"' && self[@index + 3] == '"' nl = expect_newline(@index + 4) self.context = :multiline_rawstring @rawstring_hashes = 1 @buffer = +'' traverse(4 + nl.length) next else self.context = :rawstring traverse(2) @rawstring_hashes = 1 @buffer = +'' next end elsif self[@index + 1] == '#' i = @index + 2 @rawstring_hashes = 2 while self[i] == '#' @rawstring_hashes += 1 i += 1 end if self[i] == '"' if self[i + 1] == '"' && self[i + 2] == '"' nl = expect_newline(i + 3) self.context = :multiline_rawstring traverse(@rawstring_hashes + 3 + nl.length) @buffer = +'' next else self.context = :rawstring traverse(@rawstring_hashes + 1) @buffer = +'' next end end end self.context = :keyword @buffer = +c traverse(1) when '-' n = self[@index + 1] if n =~ /[0-9]/ n2 = self[@index + 2] if n == '0' && n2 =~ /[box]/ self.context = integer_context(n2) traverse(3) else self.context = :decimal traverse(1) end else self.context = :ident traverse(1) end @buffer = +c when /[0-9+]/ n = self[@index + 1] if c == '0' && n =~ /[box]/ traverse(2) @buffer = +'' self.context = integer_context(n) else self.context = :decimal @buffer = +c traverse(1) end when '\\' t = Tokenizer.new(@str, @index + 1, filename:) la = t.next_token if la[0] == :NEWLINE || la[0] == :EOF || (la[0] == :WS && (lan = t.next_token[0]) == :NEWLINE || lan == :EOF) traverse_to(t.index) @buffer = "#{c}#{la[1].value}" @buffer << "\n" if lan == :NEWLINE self.context = :whitespace else raise_error "Unexpected '\\' (#{la[0]})" end when '=' self.context = :equals @buffer = +c traverse(1) when *SYMBOLS.keys return token(SYMBOLS[c], -c).tap { traverse(1) } when *NEWLINES, "\r" nl = expect_newline return token(:NEWLINE, -nl).tap do traverse(nl.length) end when "/" if self[@index + 1] == '/' self.context = :single_line_comment traverse(2) elsif self[@index + 1] == '*' self.context = :multi_line_comment @comment_nesting = 1 traverse(2) elsif self[@index + 1] == '-' return token(:SLASHDASH, '/-').tap { traverse(2) } else self.context = :ident @buffer = +c traverse(1) end when *WHITESPACE self.context = :whitespace @buffer = +c traverse(1) when nil return [false, token(:EOF, :EOF)[1]] if @done @done = true return token(:EOF, :EOF) when INITIAL_IDENTIFIER_CHARS self.context = :ident @buffer = +c traverse(1) when '(' @type_context = true return token(:LPAREN, -c).tap { traverse(1) } when ')' @type_context = false return token(:RPAREN, -c).tap { traverse(1) } else raise_error "Unexpected character #{c.inspect}" end when :ident case c when IDENTIFIER_CHARS traverse(1) @buffer << c else case @buffer when 'true', 'false', 'null', 'inf', '-inf', 'nan' raise_error "Identifier cannot be a literal" when /\A\.\d/ raise_error "Identifier cannot look like an illegal float" else return token(:IDENT, -@buffer) end end when :keyword case c when /[a-z\-]/ traverse(1) @buffer << c else case @buffer when '#true' then return token(:TRUE, true) when '#false' then return token(:FALSE, false) when '#null' then return token(:NULL, nil) when '#inf' then return token(:FLOAT, Float::INFINITY) when '#-inf' then return token(:FLOAT, -Float::INFINITY) when '#nan' then return token(:FLOAT, Float::NAN) else raise_error "Unknown keyword #{@buffer.inspect}" end end when :string case c when '\\' @buffer << c c2 = self[@index + 1] @buffer << c2 if c2.match?(NEWLINES_PATTERN) i = 2 while self[@index + i]&.match?(NEWLINES_PATTERN) @buffer << self[@index + i] i+=1 end traverse(i) else traverse(2) end when '"' return token(:STRING, -unescape(@buffer)).tap { traverse(1) } when *NEWLINES, "\r" raise_error "Unexpected NEWLINE in string literal" when nil raise_error "Unterminated string literal" else @buffer << c traverse(1) end when :multiline_string case c when '\\' @buffer << c @buffer << self[@index + 1] traverse(2) when '"' if self[@index + 1] == '"' && self[@index + 2] == '"' return token(:STRING, -unescape_non_ws(dedent(unescape_ws(@buffer)))).tap { traverse(3) } end @buffer << c traverse(1) when nil raise_error "Unterminated multi-line string literal" else @buffer << c traverse(1) end when :rawstring raise_error "Unterminated rawstring literal" if c.nil? case c when '"' h = 0 h += 1 while self[@index + 1 + h] == '#' && h < @rawstring_hashes if h == @rawstring_hashes return token(:RAWSTRING, -@buffer).tap { traverse(1 + h) } end when *NEWLINES, "\r" raise_error "Unexpected NEWLINE in rawstring literal" end @buffer << c traverse(1) when :multiline_rawstring raise_error "Unterminated multi-line rawstring literal" if c.nil? if c == '"' && self[@index + 1] == '"' && self[@index + 2] == '"' && self[@index + 3] == '#' h = 1 h += 1 while self[@index + 3 + h] == '#' && h < @rawstring_hashes if h == @rawstring_hashes return token(:RAWSTRING, -dedent(@buffer)).tap { traverse(3 + h) } end end @buffer << c traverse(1) when :decimal case c when /[0-9.\-+_eE]/ traverse(1) @buffer << c else return parse_decimal(@buffer) end when :hexadecimal case c when /[0-9a-fA-F_]/ traverse(1) @buffer << c else return parse_hexadecimal(@buffer) end when :octal case c when /[0-7_]/ traverse(1) @buffer << c else return parse_octal(@buffer) end when :binary case c when /[01_]/ traverse(1) @buffer << c else return parse_binary(@buffer) end when :single_line_comment case c when *NEWLINES, "\r" self.context = nil @column_at_start = @column next when nil @done = true return token(:EOF, :EOF) else traverse(1) end when :multi_line_comment if c == '/' && self[@index + 1] == '*' @comment_nesting += 1 traverse(2) elsif c == '*' && self[@index + 1] == '/' @comment_nesting -= 1 traverse(2) if @comment_nesting == 0 revert_context end else traverse(1) end when :whitespace if WHITESPACE.include?(c) traverse(1) @buffer << c elsif c == '=' self.context = :equals @buffer << c traverse(1) elsif c == "/" && self[@index + 1] == '*' self.context = :multi_line_comment @comment_nesting = 1 traverse(2) elsif c == "\\" t = Tokenizer.new(@str, @index + 1, filename:) la = t.next_token if la[0] == :NEWLINE || la[0] == :EOF || (la[0] == :WS && (lan = t.next_token[0]) == :NEWLINE || lan == :EOF) traverse_to(t.index) @buffer << "#{c}#{la[1].value}" @buffer << "\n" if lan == :NEWLINE else raise_error "Unexpected '\\' (#{la[0]})" end else return token(:WS, -@buffer) end when :equals t = Tokenizer.new(@str, @index, filename:) la = t.next_token if la[0] == :WS @buffer << la[1].value traverse_to(t.index) end return token(:EQUALS, -@buffer) else # :nocov: raise_error "Unknown context `#{@context}'" # :nocov: end end end private def token(type, value, **meta) @last_token = [type, Token.new(type, value, @line_at_start, @column_at_start, meta)] end def traverse(n = 1) n.times do |i| case self[@index + i] when "\r" @column = 1 when *NEWLINES @line += 1 @column = 1 else @column += 1 end end @index += n end def traverse_to(i) traverse(i - @index) end def raise_error(error) case error when String then raise ParseError.new(error, @filename, @line, @column) when Error then raise error else raise ParseError.new(error.message, @filename, @line, @column) end end def context=(val) if @type_context && !allowed_in_type?(val) raise_error "#{val} context not allowed in type declaration" elsif @last_token && @last_token[0] == :RPAREN && !allowed_after_type?(val) raise_error 'Comments are not allowed after a type declaration' end @previous_context = @context @context = val end def allowed_in_type?(val) %i[ident string rawstring multi_line_comment whitespace].include?(val) end def allowed_after_type?(val) !%i[single_line_comment].include?(val) end def revert_context @context = @previous_context @previous_context = nil end def expect_newline(i = @index) c = self[i] case c when "\r" n = self[i + 1] if n == "\n" "#{c}#{n}" else c end when *NEWLINES c else raise_error "Expected NEWLINE, found '#{c}'" end end def integer_context(n) case n when 'b' then :binary when 'o' then :octal when 'x' then :hexadecimal end end def parse_decimal(s) return parse_float(s) if s =~ /[.E]/i token(:INTEGER, Integer(munch_underscores(s), 10), format: '%d') rescue => e if s[0] =~ INITIAL_IDENTIFIER_CHARS && s[1..-1].each_char.all? { |c| c =~ IDENTIFIER_CHARS } token(:IDENT, -s) else raise_error(e) end end def parse_float(s) match, _, fraction, exponent = *s.match(/^([-+]?[\d_]+)(?:\.([\d_]+))?(?:[eE]([-+]?[\d_]+))?$/) raise_error "Invalid floating point value #{s}" if match.nil? s = munch_underscores(s) decimals = fraction.nil? ? 0 : fraction.size value = Float(s) scientific = value.abs >= 100 || (exponent && exponent.to_i.abs >= 2) if value.infinite? || (value.zero? && exponent.to_i < 0) token(:FLOAT, BigDecimal(s)) else token(:FLOAT, value, format: scientific ? "%.#{decimals}E" : nil) end end def parse_hexadecimal(s) token(:INTEGER, Integer(munch_underscores(s), 16)) rescue ArgumentError => e raise_error(e) end def parse_octal(s) token(:INTEGER, Integer(munch_underscores(s), 8)) rescue ArgumentError => e raise_error(e) end def parse_binary(s) token(:INTEGER, Integer(munch_underscores(s), 2)) rescue ArgumentError => e raise_error(e) end def munch_underscores(s) s.chomp('_').squeeze('_') end def unescape_ws(string) string.gsub(/\\(\\|\s+)/) do |m| case m when '\\\\' then '\\\\' else '' end end end UNESCAPE = /\\(?:[#{WHITESPACE.join}#{NEWLINES.join}\r]+|[^u])/ UNESCAPE_NON_WS = /\\(?:[^u])/ def unescape_non_ws(string) unescape(string, UNESCAPE_NON_WS) end def unescape(string, rgx = UNESCAPE) string .gsub(rgx) { |m| replace_esc(m) } .gsub(/\\u\{[0-9a-fA-F]+\}/) do |m| digits = m[3..-2] raise_error "Invalid code point #{m}" if digits.length > 6 i = Integer(digits, 16) if i < 0 || i > 0x10FFFF || (0xD800..0xDFFF).include?(i) raise_error "Invalid code point #{m}" end i.chr(Encoding::UTF_8) end end def replace_esc(m) case m when '\n' then "\n" when '\r' then "\r" when '\t' then "\t" when '\\\\' then "\\" when '\"' then "\"" when '\b' then "\b" when '\f' then "\f" when '\s' then ' ' when /\\[#{WHITESPACE.join}#{NEWLINES.join}]+/ then '' else raise_error "Unexpected escape #{m.inspect}" end end def dedent(string) split = string.split(NEWLINES_PATTERN) return "" if split.empty? lines = split.partition.with_index { |_, i| i.even? }.first if split.last.match?(NEWLINES_PATTERN) indent = "" else *lines, indent = lines end return "" if lines.empty? raise_error "Invalid multiline string final line" unless indent.match?(WS_STAR) valid = /\A#{Regexp.escape(indent)}(.*)/ lines.map do |line| case line when WS_STAR then "" when valid then $1 else raise_error "Invalid multiline string indentation" end end.join("\n") end def debom(str) return str unless str.start_with?("\uFEFF") str[1..] end end end danini-the-panini-kdl-rb-56d7cf1/lib/kdl/types.rb000066400000000000000000000007561515522600200216170ustar00rootroot00000000000000# frozen_string_literal: true module KDL module Types MAPPING = {} end end require 'kdl/types/date_time' require 'kdl/types/duration' require 'kdl/types/currency' require 'kdl/types/country' require 'kdl/types/ip' require 'kdl/types/url' require 'kdl/types/uuid' require 'kdl/types/regex' require 'kdl/types/base64' require 'kdl/types/decimal' require 'kdl/types/hostname' require 'kdl/types/email' require 'kdl/types/irl' require 'kdl/types/url_template' KDL::Types::MAPPING.freeze danini-the-panini-kdl-rb-56d7cf1/lib/kdl/types/000077500000000000000000000000001515522600200212625ustar00rootroot00000000000000danini-the-panini-kdl-rb-56d7cf1/lib/kdl/types/base64.rb000066400000000000000000000007721515522600200227010ustar00rootroot00000000000000# frozen_string_literal: true require 'base64' module KDL module Types class Base64 < Value::Custom RGX = /^[A-Za-z0-9+\/=]+$/.freeze def self.call(value, type = 'base64') return nil unless value.is_a? ::KDL::Value::String unless RGX.match?(value.value) raise ArgumentError, "invalid base64: #{value.value}" end data = ::Base64.decode64(value.value) new(data, type: type) end end MAPPING['base64'] = Base64 end end danini-the-panini-kdl-rb-56d7cf1/lib/kdl/types/country.rb000066400000000000000000000041251515522600200233140ustar00rootroot00000000000000# frozen_string_literal: true require 'kdl/types/country/iso3166_countries' require 'kdl/types/country/iso3166_subdivisions' module KDL module Types class Country < Value::Custom attr_reader :name, :alpha2, :alpha3, :numeric_code def initialize(value, format: nil, type: 'country-3') super @name = value.fetch(:name, '') @alpha3 = value.fetch(:alpha3, nil) @alpha2 = value.fetch(:alpha2, nil) @numeric_code = value.fetch(:numeric_code, nil) end def self.call(value, type = 'country-3') return nil unless value.is_a? ::KDL::Value::String country = COUNTRIES3[value.value.upcase] raise ArgumentError, 'invalid country-3' if country.nil? new(country, type: type) end end Country3 = Country MAPPING['country-3'] = Country3 class Country2 < Country def initialize(value, format: nil, type: 'country-2') super end def self.call(value, type = 'country-2') return nil unless value.is_a? ::KDL::Value::String country = COUNTRIES2[value.value.upcase] raise ArgumentError, 'invalid country-3' if country.nil? new(country, type: type) end end MAPPING['country-2'] = Country2 class CountrySubdivision < Value::Custom attr_reader :country, :name def initialize(value, type: 'country-subdivision', country:, name:, **kwargs) super(value, type: type, **kwargs) @country = country @name = name end def self.call(value, type = 'country-subdivision') return nil unless value.is_a? ::KDL::Value::String country2 = value.value.split('-').first country = Country::COUNTRIES2[country2.upcase] raise ArgumentError, 'invalid country' unless country subdivision = COUNTRY_SUBDIVISIONS.dig(country2.upcase, value.value) raise ArgumentError, 'invalid country subdivision' unless subdivision new(value.value, type: type, name: subdivision, country: country) end end MAPPING['country-subdivision'] = CountrySubdivision end end danini-the-panini-kdl-rb-56d7cf1/lib/kdl/types/country/000077500000000000000000000000001515522600200227655ustar00rootroot00000000000000danini-the-panini-kdl-rb-56d7cf1/lib/kdl/types/country/iso3166_countries.rb000066400000000000000000001007221515522600200265210ustar00rootroot00000000000000# frozen_string_literal: true module KDL module Types class Country < Value::Custom # From: https://en.wikipedia.org/wiki/ISO_3166-1#Current_codes COUNTRIES3 = { 'AFG' => { alpha3: 'AFG', alpha2: 'AF', numeric_code: 4, name: 'Afghanistan' }.freeze, 'ALA' => { alpha3: 'ALA', alpha2: 'AX', numeric_code: 248, name: 'ร…land Islands' }.freeze, 'ALB' => { alpha3: 'ALB', alpha2: 'AL', numeric_code: 8, name: 'Albania' }.freeze, 'DZA' => { alpha3: 'DZA', alpha2: 'DZ', numeric_code: 12, name: 'Algeria' }.freeze, 'ASM' => { alpha3: 'ASM', alpha2: 'AS', numeric_code: 16, name: 'American Samoa' }.freeze, 'AND' => { alpha3: 'AND', alpha2: 'AD', numeric_code: 20, name: 'Andorra' }.freeze, 'AGO' => { alpha3: 'AGO', alpha2: 'AO', numeric_code: 24, name: 'Angola' }.freeze, 'AIA' => { alpha3: 'AIA', alpha2: 'AI', numeric_code: 660, name: 'Anguilla' }.freeze, 'ATA' => { alpha3: 'ATA', alpha2: 'AQ', numeric_code: 10, name: 'Antarctica' }.freeze, 'ATG' => { alpha3: 'ATG', alpha2: 'AG', numeric_code: 28, name: 'Antigua and Barbuda' }.freeze, 'ARG' => { alpha3: 'ARG', alpha2: 'AR', numeric_code: 32, name: 'Argentina' }.freeze, 'ARM' => { alpha3: 'ARM', alpha2: 'AM', numeric_code: 51, name: 'Armenia' }.freeze, 'ABW' => { alpha3: 'ABW', alpha2: 'AW', numeric_code: 533, name: 'Aruba' }.freeze, 'AUS' => { alpha3: 'AUS', alpha2: 'AU', numeric_code: 36, name: 'Australia' }.freeze, 'AUT' => { alpha3: 'AUT', alpha2: 'AT', numeric_code: 40, name: 'Austria' }.freeze, 'AZE' => { alpha3: 'AZE', alpha2: 'AZ', numeric_code: 31, name: 'Azerbaijan' }.freeze, 'BHS' => { alpha3: 'BHS', alpha2: 'BS', numeric_code: 44, name: 'Bahamas' }.freeze, 'BHR' => { alpha3: 'BHR', alpha2: 'BH', numeric_code: 48, name: 'Bahrain' }.freeze, 'BGD' => { alpha3: 'BGD', alpha2: 'BD', numeric_code: 50, name: 'Bangladesh' }.freeze, 'BRB' => { alpha3: 'BRB', alpha2: 'BB', numeric_code: 52, name: 'Barbados' }.freeze, 'BLR' => { alpha3: 'BLR', alpha2: 'BY', numeric_code: 112, name: 'Belarus' }.freeze, 'BEL' => { alpha3: 'BEL', alpha2: 'BE', numeric_code: 56, name: 'Belgium' }.freeze, 'BLZ' => { alpha3: 'BLZ', alpha2: 'BZ', numeric_code: 84, name: 'Belize' }.freeze, 'BEN' => { alpha3: 'BEN', alpha2: 'BJ', numeric_code: 204, name: 'Benin' }.freeze, 'BMU' => { alpha3: 'BMU', alpha2: 'BM', numeric_code: 60, name: 'Bermuda' }.freeze, 'BTN' => { alpha3: 'BTN', alpha2: 'BT', numeric_code: 64, name: 'Bhutan' }.freeze, 'BOL' => { alpha3: 'BOL', alpha2: 'BO', numeric_code: 68, name: 'Bolivia (Plurinational State of)' }.freeze, 'BES' => { alpha3: 'BES', alpha2: 'BQ', numeric_code: 535, name: 'Bonaire, Sint Eustatius and Saba[d]' }.freeze, 'BIH' => { alpha3: 'BIH', alpha2: 'BA', numeric_code: 70, name: 'Bosnia and Herzegovina' }.freeze, 'BWA' => { alpha3: 'BWA', alpha2: 'BW', numeric_code: 72, name: 'Botswana' }.freeze, 'BVT' => { alpha3: 'BVT', alpha2: 'BV', numeric_code: 74, name: 'Bouvet Island' }.freeze, 'BRA' => { alpha3: 'BRA', alpha2: 'BR', numeric_code: 76, name: 'Brazil' }.freeze, 'IOT' => { alpha3: 'IOT', alpha2: 'IO', numeric_code: 86, name: 'British Indian Ocean Territory' }.freeze, 'BRN' => { alpha3: 'BRN', alpha2: 'BN', numeric_code: 96, name: 'Brunei Darussalam' }.freeze, 'BGR' => { alpha3: 'BGR', alpha2: 'BG', numeric_code: 100, name: 'Bulgaria' }.freeze, 'BFA' => { alpha3: 'BFA', alpha2: 'BF', numeric_code: 854, name: 'Burkina Faso' }.freeze, 'BDI' => { alpha3: 'BDI', alpha2: 'BI', numeric_code: 108, name: 'Burundi' }.freeze, 'CPV' => { alpha3: 'CPV', alpha2: 'CV', numeric_code: 132, name: 'Cabo Verde' }.freeze, 'KHM' => { alpha3: 'KHM', alpha2: 'KH', numeric_code: 116, name: 'Cambodia' }.freeze, 'CMR' => { alpha3: 'CMR', alpha2: 'CM', numeric_code: 120, name: 'Cameroon' }.freeze, 'CAN' => { alpha3: 'CAN', alpha2: 'CA', numeric_code: 124, name: 'Canada' }.freeze, 'CYM' => { alpha3: 'CYM', alpha2: 'KY', numeric_code: 136, name: 'Cayman Islands' }.freeze, 'CAF' => { alpha3: 'CAF', alpha2: 'CF', numeric_code: 140, name: 'Central African Republic' }.freeze, 'TCD' => { alpha3: 'TCD', alpha2: 'TD', numeric_code: 148, name: 'Chad' }.freeze, 'CHL' => { alpha3: 'CHL', alpha2: 'CL', numeric_code: 152, name: 'Chile' }.freeze, 'CHN' => { alpha3: 'CHN', alpha2: 'CN', numeric_code: 156, name: 'China' }.freeze, 'CXR' => { alpha3: 'CXR', alpha2: 'CX', numeric_code: 162, name: 'Christmas Island' }.freeze, 'CCK' => { alpha3: 'CCK', alpha2: 'CC', numeric_code: 166, name: 'Cocos (Keeling) Islands' }.freeze, 'COL' => { alpha3: 'COL', alpha2: 'CO', numeric_code: 170, name: 'Colombia' }.freeze, 'COM' => { alpha3: 'COM', alpha2: 'KM', numeric_code: 174, name: 'Comoros' }.freeze, 'COG' => { alpha3: 'COG', alpha2: 'CG', numeric_code: 178, name: 'Congo' }.freeze, 'COD' => { alpha3: 'COD', alpha2: 'CD', numeric_code: 180, name: 'Congo, Democratic Republic of the' }.freeze, 'COK' => { alpha3: 'COK', alpha2: 'CK', numeric_code: 184, name: 'Cook Islands' }.freeze, 'CRI' => { alpha3: 'CRI', alpha2: 'CR', numeric_code: 188, name: 'Costa Rica' }.freeze, 'CIV' => { alpha3: 'CIV', alpha2: 'CI', numeric_code: 384, name: 'Cรดte d\'Ivoire' }.freeze, 'HRV' => { alpha3: 'HRV', alpha2: 'HR', numeric_code: 191, name: 'Croatia' }.freeze, 'CUB' => { alpha3: 'CUB', alpha2: 'CU', numeric_code: 192, name: 'Cuba' }.freeze, 'CUW' => { alpha3: 'CUW', alpha2: 'CW', numeric_code: 531, name: 'Curaรงao' }.freeze, 'CYP' => { alpha3: 'CYP', alpha2: 'CY', numeric_code: 196, name: 'Cyprus' }.freeze, 'CZE' => { alpha3: 'CZE', alpha2: 'CZ', numeric_code: 203, name: 'Czechia' }.freeze, 'DNK' => { alpha3: 'DNK', alpha2: 'DK', numeric_code: 208, name: 'Denmark' }.freeze, 'DJI' => { alpha3: 'DJI', alpha2: 'DJ', numeric_code: 262, name: 'Djibouti' }.freeze, 'DMA' => { alpha3: 'DMA', alpha2: 'DM', numeric_code: 212, name: 'Dominica' }.freeze, 'DOM' => { alpha3: 'DOM', alpha2: 'DO', numeric_code: 214, name: 'Dominican Republic' }.freeze, 'ECU' => { alpha3: 'ECU', alpha2: 'EC', numeric_code: 218, name: 'Ecuador' }.freeze, 'EGY' => { alpha3: 'EGY', alpha2: 'EG', numeric_code: 818, name: 'Egypt' }.freeze, 'SLV' => { alpha3: 'SLV', alpha2: 'SV', numeric_code: 222, name: 'El Salvador' }.freeze, 'GNQ' => { alpha3: 'GNQ', alpha2: 'GQ', numeric_code: 226, name: 'Equatorial Guinea' }.freeze, 'ERI' => { alpha3: 'ERI', alpha2: 'ER', numeric_code: 232, name: 'Eritrea' }.freeze, 'EST' => { alpha3: 'EST', alpha2: 'EE', numeric_code: 233, name: 'Estonia' }.freeze, 'SWZ' => { alpha3: 'SWZ', alpha2: 'SZ', numeric_code: 748, name: 'Eswatini' }.freeze, 'ETH' => { alpha3: 'ETH', alpha2: 'ET', numeric_code: 231, name: 'Ethiopia' }.freeze, 'FLK' => { alpha3: 'FLK', alpha2: 'FK', numeric_code: 238, name: 'Falkland Islands (Malvinas)' }.freeze, 'FRO' => { alpha3: 'FRO', alpha2: 'FO', numeric_code: 234, name: 'Faroe Islands' }.freeze, 'FJI' => { alpha3: 'FJI', alpha2: 'FJ', numeric_code: 242, name: 'Fiji' }.freeze, 'FIN' => { alpha3: 'FIN', alpha2: 'FI', numeric_code: 246, name: 'Finland' }.freeze, 'FRA' => { alpha3: 'FRA', alpha2: 'FR', numeric_code: 250, name: 'France' }.freeze, 'GUF' => { alpha3: 'GUF', alpha2: 'GF', numeric_code: 254, name: 'French Guiana' }.freeze, 'PYF' => { alpha3: 'PYF', alpha2: 'PF', numeric_code: 258, name: 'French Polynesia' }.freeze, 'ATF' => { alpha3: 'ATF', alpha2: 'TF', numeric_code: 260, name: 'French Southern Territories' }.freeze, 'GAB' => { alpha3: 'GAB', alpha2: 'GA', numeric_code: 266, name: 'Gabon' }.freeze, 'GMB' => { alpha3: 'GMB', alpha2: 'GM', numeric_code: 270, name: 'Gambia' }.freeze, 'GEO' => { alpha3: 'GEO', alpha2: 'GE', numeric_code: 268, name: 'Georgia' }.freeze, 'DEU' => { alpha3: 'DEU', alpha2: 'DE', numeric_code: 276, name: 'Germany' }.freeze, 'GHA' => { alpha3: 'GHA', alpha2: 'GH', numeric_code: 288, name: 'Ghana' }.freeze, 'GIB' => { alpha3: 'GIB', alpha2: 'GI', numeric_code: 292, name: 'Gibraltar' }.freeze, 'GRC' => { alpha3: 'GRC', alpha2: 'GR', numeric_code: 300, name: 'Greece' }.freeze, 'GRL' => { alpha3: 'GRL', alpha2: 'GL', numeric_code: 304, name: 'Greenland' }.freeze, 'GRD' => { alpha3: 'GRD', alpha2: 'GD', numeric_code: 308, name: 'Grenada' }.freeze, 'GLP' => { alpha3: 'GLP', alpha2: 'GP', numeric_code: 312, name: 'Guadeloupe' }.freeze, 'GUM' => { alpha3: 'GUM', alpha2: 'GU', numeric_code: 316, name: 'Guam' }.freeze, 'GTM' => { alpha3: 'GTM', alpha2: 'GT', numeric_code: 320, name: 'Guatemala' }.freeze, 'GGY' => { alpha3: 'GGY', alpha2: 'GG', numeric_code: 831, name: 'Guernsey' }.freeze, 'GIN' => { alpha3: 'GIN', alpha2: 'GN', numeric_code: 324, name: 'Guinea' }.freeze, 'GNB' => { alpha3: 'GNB', alpha2: 'GW', numeric_code: 624, name: 'Guinea-Bissau' }.freeze, 'GUY' => { alpha3: 'GUY', alpha2: 'GY', numeric_code: 328, name: 'Guyana' }.freeze, 'HTI' => { alpha3: 'HTI', alpha2: 'HT', numeric_code: 332, name: 'Haiti' }.freeze, 'HMD' => { alpha3: 'HMD', alpha2: 'HM', numeric_code: 334, name: 'Heard Island and McDonald Islands' }.freeze, 'VAT' => { alpha3: 'VAT', alpha2: 'VA', numeric_code: 336, name: 'Holy See' }.freeze, 'HND' => { alpha3: 'HND', alpha2: 'HN', numeric_code: 340, name: 'Honduras' }.freeze, 'HKG' => { alpha3: 'HKG', alpha2: 'HK', numeric_code: 344, name: 'Hong Kong' }.freeze, 'HUN' => { alpha3: 'HUN', alpha2: 'HU', numeric_code: 348, name: 'Hungary' }.freeze, 'ISL' => { alpha3: 'ISL', alpha2: 'IS', numeric_code: 352, name: 'Iceland' }.freeze, 'IND' => { alpha3: 'IND', alpha2: 'IN', numeric_code: 356, name: 'India' }.freeze, 'IDN' => { alpha3: 'IDN', alpha2: 'ID', numeric_code: 360, name: 'Indonesia' }.freeze, 'IRN' => { alpha3: 'IRN', alpha2: 'IR', numeric_code: 364, name: 'Iran (Islamic Republic of)' }.freeze, 'IRQ' => { alpha3: 'IRQ', alpha2: 'IQ', numeric_code: 368, name: 'Iraq' }.freeze, 'IRL' => { alpha3: 'IRL', alpha2: 'IE', numeric_code: 372, name: 'Ireland' }.freeze, 'IMN' => { alpha3: 'IMN', alpha2: 'IM', numeric_code: 833, name: 'Isle of Man' }.freeze, 'ISR' => { alpha3: 'ISR', alpha2: 'IL', numeric_code: 376, name: 'Israel' }.freeze, 'ITA' => { alpha3: 'ITA', alpha2: 'IT', numeric_code: 380, name: 'Italy' }.freeze, 'JAM' => { alpha3: 'JAM', alpha2: 'JM', numeric_code: 388, name: 'Jamaica' }.freeze, 'JPN' => { alpha3: 'JPN', alpha2: 'JP', numeric_code: 392, name: 'Japan' }.freeze, 'JEY' => { alpha3: 'JEY', alpha2: 'JE', numeric_code: 832, name: 'Jersey' }.freeze, 'JOR' => { alpha3: 'JOR', alpha2: 'JO', numeric_code: 400, name: 'Jordan' }.freeze, 'KAZ' => { alpha3: 'KAZ', alpha2: 'KZ', numeric_code: 398, name: 'Kazakhstan' }.freeze, 'KEN' => { alpha3: 'KEN', alpha2: 'KE', numeric_code: 404, name: 'Kenya' }.freeze, 'KIR' => { alpha3: 'KIR', alpha2: 'KI', numeric_code: 296, name: 'Kiribati' }.freeze, 'PRK' => { alpha3: 'PRK', alpha2: 'KP', numeric_code: 408, name: 'Korea (Democratic People\'s Republic of)' }.freeze, 'KOR' => { alpha3: 'KOR', alpha2: 'KR', numeric_code: 410, name: 'Korea, Republic of' }.freeze, 'KWT' => { alpha3: 'KWT', alpha2: 'KW', numeric_code: 414, name: 'Kuwait' }.freeze, 'KGZ' => { alpha3: 'KGZ', alpha2: 'KG', numeric_code: 417, name: 'Kyrgyzstan' }.freeze, 'LAO' => { alpha3: 'LAO', alpha2: 'LA', numeric_code: 418, name: 'Lao People\'s Democratic Republic' }.freeze, 'LVA' => { alpha3: 'LVA', alpha2: 'LV', numeric_code: 428, name: 'Latvia' }.freeze, 'LBN' => { alpha3: 'LBN', alpha2: 'LB', numeric_code: 422, name: 'Lebanon' }.freeze, 'LSO' => { alpha3: 'LSO', alpha2: 'LS', numeric_code: 426, name: 'Lesotho' }.freeze, 'LBR' => { alpha3: 'LBR', alpha2: 'LR', numeric_code: 430, name: 'Liberia' }.freeze, 'LBY' => { alpha3: 'LBY', alpha2: 'LY', numeric_code: 434, name: 'Libya' }.freeze, 'LIE' => { alpha3: 'LIE', alpha2: 'LI', numeric_code: 438, name: 'Liechtenstein' }.freeze, 'LTU' => { alpha3: 'LTU', alpha2: 'LT', numeric_code: 440, name: 'Lithuania' }.freeze, 'LUX' => { alpha3: 'LUX', alpha2: 'LU', numeric_code: 442, name: 'Luxembourg' }.freeze, 'MAC' => { alpha3: 'MAC', alpha2: 'MO', numeric_code: 446, name: 'Macao' }.freeze, 'MDG' => { alpha3: 'MDG', alpha2: 'MG', numeric_code: 450, name: 'Madagascar' }.freeze, 'MWI' => { alpha3: 'MWI', alpha2: 'MW', numeric_code: 454, name: 'Malawi' }.freeze, 'MYS' => { alpha3: 'MYS', alpha2: 'MY', numeric_code: 458, name: 'Malaysia' }.freeze, 'MDV' => { alpha3: 'MDV', alpha2: 'MV', numeric_code: 462, name: 'Maldives' }.freeze, 'MLI' => { alpha3: 'MLI', alpha2: 'ML', numeric_code: 466, name: 'Mali' }.freeze, 'MLT' => { alpha3: 'MLT', alpha2: 'MT', numeric_code: 470, name: 'Malta' }.freeze, 'MHL' => { alpha3: 'MHL', alpha2: 'MH', numeric_code: 584, name: 'Marshall Islands' }.freeze, 'MTQ' => { alpha3: 'MTQ', alpha2: 'MQ', numeric_code: 474, name: 'Martinique' }.freeze, 'MRT' => { alpha3: 'MRT', alpha2: 'MR', numeric_code: 478, name: 'Mauritania' }.freeze, 'MUS' => { alpha3: 'MUS', alpha2: 'MU', numeric_code: 480, name: 'Mauritius' }.freeze, 'MYT' => { alpha3: 'MYT', alpha2: 'YT', numeric_code: 175, name: 'Mayotte' }.freeze, 'MEX' => { alpha3: 'MEX', alpha2: 'MX', numeric_code: 484, name: 'Mexico' }.freeze, 'FSM' => { alpha3: 'FSM', alpha2: 'FM', numeric_code: 583, name: 'Micronesia (Federated States of)' }.freeze, 'MDA' => { alpha3: 'MDA', alpha2: 'MD', numeric_code: 498, name: 'Moldova, Republic of' }.freeze, 'MCO' => { alpha3: 'MCO', alpha2: 'MC', numeric_code: 492, name: 'Monaco' }.freeze, 'MNG' => { alpha3: 'MNG', alpha2: 'MN', numeric_code: 496, name: 'Mongolia' }.freeze, 'MNE' => { alpha3: 'MNE', alpha2: 'ME', numeric_code: 499, name: 'Montenegro' }.freeze, 'MSR' => { alpha3: 'MSR', alpha2: 'MS', numeric_code: 500, name: 'Montserrat' }.freeze, 'MAR' => { alpha3: 'MAR', alpha2: 'MA', numeric_code: 504, name: 'Morocco' }.freeze, 'MOZ' => { alpha3: 'MOZ', alpha2: 'MZ', numeric_code: 508, name: 'Mozambique' }.freeze, 'MMR' => { alpha3: 'MMR', alpha2: 'MM', numeric_code: 104, name: 'Myanmar' }.freeze, 'NAM' => { alpha3: 'NAM', alpha2: 'NA', numeric_code: 516, name: 'Namibia' }.freeze, 'NRU' => { alpha3: 'NRU', alpha2: 'NR', numeric_code: 520, name: 'Nauru' }.freeze, 'NPL' => { alpha3: 'NPL', alpha2: 'NP', numeric_code: 524, name: 'Nepal' }.freeze, 'NLD' => { alpha3: 'NLD', alpha2: 'NL', numeric_code: 528, name: 'Netherlands' }.freeze, 'NCL' => { alpha3: 'NCL', alpha2: 'NC', numeric_code: 540, name: 'New Caledonia' }.freeze, 'NZL' => { alpha3: 'NZL', alpha2: 'NZ', numeric_code: 554, name: 'New Zealand' }.freeze, 'NIC' => { alpha3: 'NIC', alpha2: 'NI', numeric_code: 558, name: 'Nicaragua' }.freeze, 'NER' => { alpha3: 'NER', alpha2: 'NE', numeric_code: 562, name: 'Niger' }.freeze, 'NGA' => { alpha3: 'NGA', alpha2: 'NG', numeric_code: 566, name: 'Nigeria' }.freeze, 'NIU' => { alpha3: 'NIU', alpha2: 'NU', numeric_code: 570, name: 'Niue' }.freeze, 'NFK' => { alpha3: 'NFK', alpha2: 'NF', numeric_code: 574, name: 'Norfolk Island' }.freeze, 'MKD' => { alpha3: 'MKD', alpha2: 'MK', numeric_code: 807, name: 'North Macedonia' }.freeze, 'MNP' => { alpha3: 'MNP', alpha2: 'MP', numeric_code: 580, name: 'Northern Mariana Islands' }.freeze, 'NOR' => { alpha3: 'NOR', alpha2: 'NO', numeric_code: 578, name: 'Norway' }.freeze, 'OMN' => { alpha3: 'OMN', alpha2: 'OM', numeric_code: 512, name: 'Oman' }.freeze, 'PAK' => { alpha3: 'PAK', alpha2: 'PK', numeric_code: 586, name: 'Pakistan' }.freeze, 'PLW' => { alpha3: 'PLW', alpha2: 'PW', numeric_code: 585, name: 'Palau' }.freeze, 'PSE' => { alpha3: 'PSE', alpha2: 'PS', numeric_code: 275, name: 'Palestine, State of' }.freeze, 'PAN' => { alpha3: 'PAN', alpha2: 'PA', numeric_code: 591, name: 'Panama' }.freeze, 'PNG' => { alpha3: 'PNG', alpha2: 'PG', numeric_code: 598, name: 'Papua New Guinea' }.freeze, 'PRY' => { alpha3: 'PRY', alpha2: 'PY', numeric_code: 600, name: 'Paraguay' }.freeze, 'PER' => { alpha3: 'PER', alpha2: 'PE', numeric_code: 604, name: 'Peru' }.freeze, 'PHL' => { alpha3: 'PHL', alpha2: 'PH', numeric_code: 608, name: 'Philippines' }.freeze, 'PCN' => { alpha3: 'PCN', alpha2: 'PN', numeric_code: 612, name: 'Pitcairn' }.freeze, 'POL' => { alpha3: 'POL', alpha2: 'PL', numeric_code: 616, name: 'Poland' }.freeze, 'PRT' => { alpha3: 'PRT', alpha2: 'PT', numeric_code: 620, name: 'Portugal' }.freeze, 'PRI' => { alpha3: 'PRI', alpha2: 'PR', numeric_code: 630, name: 'Puerto Rico' }.freeze, 'QAT' => { alpha3: 'QAT', alpha2: 'QA', numeric_code: 634, name: 'Qatar' }.freeze, 'REU' => { alpha3: 'REU', alpha2: 'RE', numeric_code: 638, name: 'Rรฉunion' }.freeze, 'ROU' => { alpha3: 'ROU', alpha2: 'RO', numeric_code: 642, name: 'Romania' }.freeze, 'RUS' => { alpha3: 'RUS', alpha2: 'RU', numeric_code: 643, name: 'Russian Federation' }.freeze, 'RWA' => { alpha3: 'RWA', alpha2: 'RW', numeric_code: 646, name: 'Rwanda' }.freeze, 'BLM' => { alpha3: 'BLM', alpha2: 'BL', numeric_code: 652, name: 'Saint Barthรฉlemy' }.freeze, 'SHN' => { alpha3: 'SHN', alpha2: 'SH', numeric_code: 654, name: 'Saint Helena, Ascension and Tristan da Cunha[e]' }.freeze, 'KNA' => { alpha3: 'KNA', alpha2: 'KN', numeric_code: 659, name: 'Saint Kitts and Nevis' }.freeze, 'LCA' => { alpha3: 'LCA', alpha2: 'LC', numeric_code: 662, name: 'Saint Lucia' }.freeze, 'MAF' => { alpha3: 'MAF', alpha2: 'MF', numeric_code: 663, name: 'Saint Martin (French part)' }.freeze, 'SPM' => { alpha3: 'SPM', alpha2: 'PM', numeric_code: 666, name: 'Saint Pierre and Miquelon' }.freeze, 'VCT' => { alpha3: 'VCT', alpha2: 'VC', numeric_code: 670, name: 'Saint Vincent and the Grenadines' }.freeze, 'WSM' => { alpha3: 'WSM', alpha2: 'WS', numeric_code: 882, name: 'Samoa' }.freeze, 'SMR' => { alpha3: 'SMR', alpha2: 'SM', numeric_code: 674, name: 'San Marino' }.freeze, 'STP' => { alpha3: 'STP', alpha2: 'ST', numeric_code: 678, name: 'Sao Tome and Principe' }.freeze, 'SAU' => { alpha3: 'SAU', alpha2: 'SA', numeric_code: 682, name: 'Saudi Arabia' }.freeze, 'SEN' => { alpha3: 'SEN', alpha2: 'SN', numeric_code: 686, name: 'Senegal' }.freeze, 'SRB' => { alpha3: 'SRB', alpha2: 'RS', numeric_code: 688, name: 'Serbia' }.freeze, 'SYC' => { alpha3: 'SYC', alpha2: 'SC', numeric_code: 690, name: 'Seychelles' }.freeze, 'SLE' => { alpha3: 'SLE', alpha2: 'SL', numeric_code: 694, name: 'Sierra Leone' }.freeze, 'SGP' => { alpha3: 'SGP', alpha2: 'SG', numeric_code: 702, name: 'Singapore' }.freeze, 'SXM' => { alpha3: 'SXM', alpha2: 'SX', numeric_code: 534, name: 'Sint Maarten (Dutch part)' }.freeze, 'SVK' => { alpha3: 'SVK', alpha2: 'SK', numeric_code: 703, name: 'Slovakia' }.freeze, 'SVN' => { alpha3: 'SVN', alpha2: 'SI', numeric_code: 705, name: 'Slovenia' }.freeze, 'SLB' => { alpha3: 'SLB', alpha2: 'SB', numeric_code: 90, name: 'Solomon Islands' }.freeze, 'SOM' => { alpha3: 'SOM', alpha2: 'SO', numeric_code: 706, name: 'Somalia' }.freeze, 'ZAF' => { alpha3: 'ZAF', alpha2: 'ZA', numeric_code: 710, name: 'South Africa' }.freeze, 'SGS' => { alpha3: 'SGS', alpha2: 'GS', numeric_code: 239, name: 'South Georgia and the South Sandwich Islands' }.freeze, 'SSD' => { alpha3: 'SSD', alpha2: 'SS', numeric_code: 728, name: 'South Sudan' }.freeze, 'ESP' => { alpha3: 'ESP', alpha2: 'ES', numeric_code: 724, name: 'Spain' }.freeze, 'LKA' => { alpha3: 'LKA', alpha2: 'LK', numeric_code: 144, name: 'Sri Lanka' }.freeze, 'SDN' => { alpha3: 'SDN', alpha2: 'SD', numeric_code: 729, name: 'Sudan' }.freeze, 'SUR' => { alpha3: 'SUR', alpha2: 'SR', numeric_code: 740, name: 'Suriname' }.freeze, 'SJM' => { alpha3: 'SJM', alpha2: 'SJ', numeric_code: 744, name: 'Svalbard and Jan Mayen[f]' }.freeze, 'SWE' => { alpha3: 'SWE', alpha2: 'SE', numeric_code: 752, name: 'Sweden' }.freeze, 'CHE' => { alpha3: 'CHE', alpha2: 'CH', numeric_code: 756, name: 'Switzerland' }.freeze, 'SYR' => { alpha3: 'SYR', alpha2: 'SY', numeric_code: 760, name: 'Syrian Arab Republic' }.freeze, 'TWN' => { alpha3: 'TWN', alpha2: 'TW', numeric_code: 158, name: 'Taiwan, Province of China' }.freeze, 'TJK' => { alpha3: 'TJK', alpha2: 'TJ', numeric_code: 762, name: 'Tajikistan' }.freeze, 'TZA' => { alpha3: 'TZA', alpha2: 'TZ', numeric_code: 834, name: 'Tanzania, United Republic of' }.freeze, 'THA' => { alpha3: 'THA', alpha2: 'TH', numeric_code: 764, name: 'Thailand' }.freeze, 'TLS' => { alpha3: 'TLS', alpha2: 'TL', numeric_code: 626, name: 'Timor-Leste' }.freeze, 'TGO' => { alpha3: 'TGO', alpha2: 'TG', numeric_code: 768, name: 'Togo' }.freeze, 'TKL' => { alpha3: 'TKL', alpha2: 'TK', numeric_code: 772, name: 'Tokelau' }.freeze, 'TON' => { alpha3: 'TON', alpha2: 'TO', numeric_code: 776, name: 'Tonga' }.freeze, 'TTO' => { alpha3: 'TTO', alpha2: 'TT', numeric_code: 780, name: 'Trinidad and Tobago' }.freeze, 'TUN' => { alpha3: 'TUN', alpha2: 'TN', numeric_code: 788, name: 'Tunisia' }.freeze, 'TUR' => { alpha3: 'TUR', alpha2: 'TR', numeric_code: 792, name: 'Turkey' }.freeze, 'TKM' => { alpha3: 'TKM', alpha2: 'TM', numeric_code: 795, name: 'Turkmenistan' }.freeze, 'TCA' => { alpha3: 'TCA', alpha2: 'TC', numeric_code: 796, name: 'Turks and Caicos Islands' }.freeze, 'TUV' => { alpha3: 'TUV', alpha2: 'TV', numeric_code: 798, name: 'Tuvalu' }.freeze, 'UGA' => { alpha3: 'UGA', alpha2: 'UG', numeric_code: 800, name: 'Uganda' }.freeze, 'UKR' => { alpha3: 'UKR', alpha2: 'UA', numeric_code: 804, name: 'Ukraine' }.freeze, 'ARE' => { alpha3: 'ARE', alpha2: 'AE', numeric_code: 784, name: 'United Arab Emirates' }.freeze, 'GBR' => { alpha3: 'GBR', alpha2: 'GB', numeric_code: 826, name: 'United Kingdom of Great Britain and Northern Ireland' }.freeze, 'USA' => { alpha3: 'USA', alpha2: 'US', numeric_code: 840, name: 'United States of America' }.freeze, 'UMI' => { alpha3: 'UMI', alpha2: 'UM', numeric_code: 581, name: 'United States Minor Outlying Islands[h]' }.freeze, 'URY' => { alpha3: 'URY', alpha2: 'UY', numeric_code: 858, name: 'Uruguay' }.freeze, 'UZB' => { alpha3: 'UZB', alpha2: 'UZ', numeric_code: 860, name: 'Uzbekistan' }.freeze, 'VUT' => { alpha3: 'VUT', alpha2: 'VU', numeric_code: 548, name: 'Vanuatu' }.freeze, 'VEN' => { alpha3: 'VEN', alpha2: 'VE', numeric_code: 862, name: 'Venezuela (Bolivarian Republic of)' }.freeze, 'VNM' => { alpha3: 'VNM', alpha2: 'VN', numeric_code: 704, name: 'Viet Nam' }.freeze, 'VGB' => { alpha3: 'VGB', alpha2: 'VG', numeric_code: 92, name: 'Virgin Islands (British)' }.freeze, 'VIR' => { alpha3: 'VIR', alpha2: 'VI', numeric_code: 850, name: 'Virgin Islands (U.S.)' }.freeze, 'WLF' => { alpha3: 'WLF', alpha2: 'WF', numeric_code: 876, name: 'Wallis and Futuna' }.freeze, 'ESH' => { alpha3: 'ESH', alpha2: 'EH', numeric_code: 732, name: 'Western Sahara' }.freeze, 'YEM' => { alpha3: 'YEM', alpha2: 'YE', numeric_code: 887, name: 'Yemen' }.freeze, 'ZMB' => { alpha3: 'ZMB', alpha2: 'ZM', numeric_code: 894, name: 'Zambia' }.freeze, 'ZWE' => { alpha3: 'ZWE', alpha2: 'ZW', numeric_code: 716, name: 'Zimbabwe' }.freeze }.freeze COUNTRIES2 = { 'AF' => COUNTRIES3['AFG'], 'AX' => COUNTRIES3['ALA'], 'AL' => COUNTRIES3['ALB'], 'DZ' => COUNTRIES3['DZA'], 'AS' => COUNTRIES3['ASM'], 'AD' => COUNTRIES3['AND'], 'AO' => COUNTRIES3['AGO'], 'AI' => COUNTRIES3['AIA'], 'AQ' => COUNTRIES3['ATA'], 'AG' => COUNTRIES3['ATG'], 'AR' => COUNTRIES3['ARG'], 'AM' => COUNTRIES3['ARM'], 'AW' => COUNTRIES3['ABW'], 'AU' => COUNTRIES3['AUS'], 'AT' => COUNTRIES3['AUT'], 'AZ' => COUNTRIES3['AZE'], 'BS' => COUNTRIES3['BHS'], 'BH' => COUNTRIES3['BHR'], 'BD' => COUNTRIES3['BGD'], 'BB' => COUNTRIES3['BRB'], 'BY' => COUNTRIES3['BLR'], 'BE' => COUNTRIES3['BEL'], 'BZ' => COUNTRIES3['BLZ'], 'BJ' => COUNTRIES3['BEN'], 'BM' => COUNTRIES3['BMU'], 'BT' => COUNTRIES3['BTN'], 'BO' => COUNTRIES3['BOL'], 'BQ' => COUNTRIES3['BES'], 'BA' => COUNTRIES3['BIH'], 'BW' => COUNTRIES3['BWA'], 'BV' => COUNTRIES3['BVT'], 'BR' => COUNTRIES3['BRA'], 'IO' => COUNTRIES3['IOT'], 'BN' => COUNTRIES3['BRN'], 'BG' => COUNTRIES3['BGR'], 'BF' => COUNTRIES3['BFA'], 'BI' => COUNTRIES3['BDI'], 'CV' => COUNTRIES3['CPV'], 'KH' => COUNTRIES3['KHM'], 'CM' => COUNTRIES3['CMR'], 'CA' => COUNTRIES3['CAN'], 'KY' => COUNTRIES3['CYM'], 'CF' => COUNTRIES3['CAF'], 'TD' => COUNTRIES3['TCD'], 'CL' => COUNTRIES3['CHL'], 'CN' => COUNTRIES3['CHN'], 'CX' => COUNTRIES3['CXR'], 'CC' => COUNTRIES3['CCK'], 'CO' => COUNTRIES3['COL'], 'KM' => COUNTRIES3['COM'], 'CG' => COUNTRIES3['COG'], 'CD' => COUNTRIES3['COD'], 'CK' => COUNTRIES3['COK'], 'CR' => COUNTRIES3['CRI'], 'CI' => COUNTRIES3['CIV'], 'HR' => COUNTRIES3['HRV'], 'CU' => COUNTRIES3['CUB'], 'CW' => COUNTRIES3['CUW'], 'CY' => COUNTRIES3['CYP'], 'CZ' => COUNTRIES3['CZE'], 'DK' => COUNTRIES3['DNK'], 'DJ' => COUNTRIES3['DJI'], 'DM' => COUNTRIES3['DMA'], 'DO' => COUNTRIES3['DOM'], 'EC' => COUNTRIES3['ECU'], 'EG' => COUNTRIES3['EGY'], 'SV' => COUNTRIES3['SLV'], 'GQ' => COUNTRIES3['GNQ'], 'ER' => COUNTRIES3['ERI'], 'EE' => COUNTRIES3['EST'], 'SZ' => COUNTRIES3['SWZ'], 'ET' => COUNTRIES3['ETH'], 'FK' => COUNTRIES3['FLK'], 'FO' => COUNTRIES3['FRO'], 'FJ' => COUNTRIES3['FJI'], 'FI' => COUNTRIES3['FIN'], 'FR' => COUNTRIES3['FRA'], 'GF' => COUNTRIES3['GUF'], 'PF' => COUNTRIES3['PYF'], 'TF' => COUNTRIES3['ATF'], 'GA' => COUNTRIES3['GAB'], 'GM' => COUNTRIES3['GMB'], 'GE' => COUNTRIES3['GEO'], 'DE' => COUNTRIES3['DEU'], 'GH' => COUNTRIES3['GHA'], 'GI' => COUNTRIES3['GIB'], 'GR' => COUNTRIES3['GRC'], 'GL' => COUNTRIES3['GRL'], 'GD' => COUNTRIES3['GRD'], 'GP' => COUNTRIES3['GLP'], 'GU' => COUNTRIES3['GUM'], 'GT' => COUNTRIES3['GTM'], 'GG' => COUNTRIES3['GGY'], 'GN' => COUNTRIES3['GIN'], 'GW' => COUNTRIES3['GNB'], 'GY' => COUNTRIES3['GUY'], 'HT' => COUNTRIES3['HTI'], 'HM' => COUNTRIES3['HMD'], 'VA' => COUNTRIES3['VAT'], 'HN' => COUNTRIES3['HND'], 'HK' => COUNTRIES3['HKG'], 'HU' => COUNTRIES3['HUN'], 'IS' => COUNTRIES3['ISL'], 'IN' => COUNTRIES3['IND'], 'ID' => COUNTRIES3['IDN'], 'IR' => COUNTRIES3['IRN'], 'IQ' => COUNTRIES3['IRQ'], 'IE' => COUNTRIES3['IRL'], 'IM' => COUNTRIES3['IMN'], 'IL' => COUNTRIES3['ISR'], 'IT' => COUNTRIES3['ITA'], 'JM' => COUNTRIES3['JAM'], 'JP' => COUNTRIES3['JPN'], 'JE' => COUNTRIES3['JEY'], 'JO' => COUNTRIES3['JOR'], 'KZ' => COUNTRIES3['KAZ'], 'KE' => COUNTRIES3['KEN'], 'KI' => COUNTRIES3['KIR'], 'KP' => COUNTRIES3['PRK'], 'KR' => COUNTRIES3['KOR'], 'KW' => COUNTRIES3['KWT'], 'KG' => COUNTRIES3['KGZ'], 'LA' => COUNTRIES3['LAO'], 'LV' => COUNTRIES3['LVA'], 'LB' => COUNTRIES3['LBN'], 'LS' => COUNTRIES3['LSO'], 'LR' => COUNTRIES3['LBR'], 'LY' => COUNTRIES3['LBY'], 'LI' => COUNTRIES3['LIE'], 'LT' => COUNTRIES3['LTU'], 'LU' => COUNTRIES3['LUX'], 'MO' => COUNTRIES3['MAC'], 'MG' => COUNTRIES3['MDG'], 'MW' => COUNTRIES3['MWI'], 'MY' => COUNTRIES3['MYS'], 'MV' => COUNTRIES3['MDV'], 'ML' => COUNTRIES3['MLI'], 'MT' => COUNTRIES3['MLT'], 'MH' => COUNTRIES3['MHL'], 'MQ' => COUNTRIES3['MTQ'], 'MR' => COUNTRIES3['MRT'], 'MU' => COUNTRIES3['MUS'], 'YT' => COUNTRIES3['MYT'], 'MX' => COUNTRIES3['MEX'], 'FM' => COUNTRIES3['FSM'], 'MD' => COUNTRIES3['MDA'], 'MC' => COUNTRIES3['MCO'], 'MN' => COUNTRIES3['MNG'], 'ME' => COUNTRIES3['MNE'], 'MS' => COUNTRIES3['MSR'], 'MA' => COUNTRIES3['MAR'], 'MZ' => COUNTRIES3['MOZ'], 'MM' => COUNTRIES3['MMR'], 'NA' => COUNTRIES3['NAM'], 'NR' => COUNTRIES3['NRU'], 'NP' => COUNTRIES3['NPL'], 'NL' => COUNTRIES3['NLD'], 'NC' => COUNTRIES3['NCL'], 'NZ' => COUNTRIES3['NZL'], 'NI' => COUNTRIES3['NIC'], 'NE' => COUNTRIES3['NER'], 'NG' => COUNTRIES3['NGA'], 'NU' => COUNTRIES3['NIU'], 'NF' => COUNTRIES3['NFK'], 'MK' => COUNTRIES3['MKD'], 'MP' => COUNTRIES3['MNP'], 'NO' => COUNTRIES3['NOR'], 'OM' => COUNTRIES3['OMN'], 'PK' => COUNTRIES3['PAK'], 'PW' => COUNTRIES3['PLW'], 'PS' => COUNTRIES3['PSE'], 'PA' => COUNTRIES3['PAN'], 'PG' => COUNTRIES3['PNG'], 'PY' => COUNTRIES3['PRY'], 'PE' => COUNTRIES3['PER'], 'PH' => COUNTRIES3['PHL'], 'PN' => COUNTRIES3['PCN'], 'PL' => COUNTRIES3['POL'], 'PT' => COUNTRIES3['PRT'], 'PR' => COUNTRIES3['PRI'], 'QA' => COUNTRIES3['QAT'], 'RE' => COUNTRIES3['REU'], 'RO' => COUNTRIES3['ROU'], 'RU' => COUNTRIES3['RUS'], 'RW' => COUNTRIES3['RWA'], 'BL' => COUNTRIES3['BLM'], 'SH' => COUNTRIES3['SHN'], 'KN' => COUNTRIES3['KNA'], 'LC' => COUNTRIES3['LCA'], 'MF' => COUNTRIES3['MAF'], 'PM' => COUNTRIES3['SPM'], 'VC' => COUNTRIES3['VCT'], 'WS' => COUNTRIES3['WSM'], 'SM' => COUNTRIES3['SMR'], 'ST' => COUNTRIES3['STP'], 'SA' => COUNTRIES3['SAU'], 'SN' => COUNTRIES3['SEN'], 'RS' => COUNTRIES3['SRB'], 'SC' => COUNTRIES3['SYC'], 'SL' => COUNTRIES3['SLE'], 'SG' => COUNTRIES3['SGP'], 'SX' => COUNTRIES3['SXM'], 'SK' => COUNTRIES3['SVK'], 'SI' => COUNTRIES3['SVN'], 'SB' => COUNTRIES3['SLB'], 'SO' => COUNTRIES3['SOM'], 'ZA' => COUNTRIES3['ZAF'], 'GS' => COUNTRIES3['SGS'], 'SS' => COUNTRIES3['SSD'], 'ES' => COUNTRIES3['ESP'], 'LK' => COUNTRIES3['LKA'], 'SD' => COUNTRIES3['SDN'], 'SR' => COUNTRIES3['SUR'], 'SJ' => COUNTRIES3['SJM'], 'SE' => COUNTRIES3['SWE'], 'CH' => COUNTRIES3['CHE'], 'SY' => COUNTRIES3['SYR'], 'TW' => COUNTRIES3['TWN'], 'TJ' => COUNTRIES3['TJK'], 'TZ' => COUNTRIES3['TZA'], 'TH' => COUNTRIES3['THA'], 'TL' => COUNTRIES3['TLS'], 'TG' => COUNTRIES3['TGO'], 'TK' => COUNTRIES3['TKL'], 'TO' => COUNTRIES3['TON'], 'TT' => COUNTRIES3['TTO'], 'TN' => COUNTRIES3['TUN'], 'TR' => COUNTRIES3['TUR'], 'TM' => COUNTRIES3['TKM'], 'TC' => COUNTRIES3['TCA'], 'TV' => COUNTRIES3['TUV'], 'UG' => COUNTRIES3['UGA'], 'UA' => COUNTRIES3['UKR'], 'AE' => COUNTRIES3['ARE'], 'GB' => COUNTRIES3['GBR'], 'US' => COUNTRIES3['USA'], 'UM' => COUNTRIES3['UMI'], 'UY' => COUNTRIES3['URY'], 'UZ' => COUNTRIES3['UZB'], 'VU' => COUNTRIES3['VUT'], 'VE' => COUNTRIES3['VEN'], 'VN' => COUNTRIES3['VNM'], 'VG' => COUNTRIES3['VGB'], 'VI' => COUNTRIES3['VIR'], 'WF' => COUNTRIES3['WLF'], 'EH' => COUNTRIES3['ESH'], 'YE' => COUNTRIES3['YEM'], 'ZM' => COUNTRIES3['ZMB'], 'ZW' => COUNTRIES3['ZWE'] }.freeze # TODO: iso3166-2 subdivision codes?? end end end danini-the-panini-kdl-rb-56d7cf1/lib/kdl/types/country/iso3166_subdivisions.rb000066400000000000000000004015651515522600200272400ustar00rootroot00000000000000# frozen_string_literal: true module KDL module Types class CountrySubdivision < Value::Custom # From: https://en.wikipedia.org/wiki/ISO_3166-2#Current_codes COUNTRY_SUBDIVISIONS = { "AD" => { "AD-07" => "Andorra la Vella", "AD-02" => "Canillo", "AD-03" => "Encamp", "AD-08" => "Escaldes-Engordany", "AD-04" => "La Massana", "AD-05" => "Ordino", "AD-06" => "Sant Juliร  de Lรฒria" }, "AE" => { "AE-AZ" => "Abลซ Zฬงaby", "AE-AJ" => "โ€˜Ajmฤn", "AE-FU" => "Al Fujayrah", "AE-SH" => "Ash Shฤriqah", "AE-DU" => "Dubayy", "AE-RK" => "Raโ€™s al Khaymah", "AE-UQ" => "Umm al Qaywayn" }, "AF" => { "AF-BDS" => "Badakhshฤn", "AF-BDG" => "Bฤdghฤซs", "AF-BGL" => "Baghlฤn", "AF-BAL" => "Balkh", "AF-BAM" => "Bฤmyฤn", "AF-DAY" => "Dฤykundฤซ", "AF-FRA" => "Farฤh", "AF-FYB" => "Fฤryฤb", "AF-GHA" => "Ghaznฤซ", "AF-GHO" => "Ghลr", "AF-HEL" => "Helmand", "AF-HER" => "Herฤt", "AF-JOW" => "Jowzjฤn", "AF-KAB" => "Kฤbul", "AF-KAN" => "Kandahฤr", "AF-KAP" => "Kฤpฤซsฤ", "AF-KHO" => "Khลst", "AF-KNR" => "KunaแนŸ", "AF-KDZ" => "Kunduz", "AF-LAG" => "Laghmฤn", "AF-LOG" => "Lลgar", "AF-NAN" => "Nangarhฤr", "AF-NIM" => "Nฤซmrลz", "AF-NUR" => "Nลซristฤn", "AF-PKA" => "Paktฤซkฤ", "AF-PIA" => "Paktiyฤ", "AF-PAN" => "Panjshayr", "AF-PAR" => "Parwฤn", "AF-SAM" => "Samangฤn", "AF-SAR" => "Sar-e Pul", "AF-TAK" => "Takhฤr", "AF-URU" => "Uruzgฤn", "AF-WAR" => "Wardak", "AF-ZAB" => "Zฤbul" }, "AG" => { "AG-03" => "Saint George", "AG-04" => "Saint John", "AG-05" => "Saint Mary", "AG-06" => "Saint Paul", "AG-07" => "Saint Peter", "AG-08" => "Saint Philip", "AG-10" => "Barbuda", "AG-11" => "Redonda" }, "AL" => { "AL-01" => "Berat", "AL-09" => "Dibรซr", "AL-02" => "Durrรซs", "AL-03" => "Elbasan", "AL-04" => "Fier", "AL-05" => "Gjirokastรซr", "AL-06" => "Korรงรซ", "AL-07" => "Kukรซs", "AL-08" => "Lezhรซ", "AL-10" => "Shkodรซr", "AL-11" => "Tiranรซ", "AL-12" => "Vlorรซ" }, "AM" => { "AM-ER" => "Erevan", "AM-AG" => "Aragacฬฃotn", "AM-AR" => "Ararat", "AM-AV" => "Armavir", "AM-GR" => "Geฤกark'unik'", "AM-KT" => "Kotayk'", "AM-LO" => "Loแน™i", "AM-SH" => "ล irak", "AM-SU" => "Syunik'", "AM-TV" => "Tavuลก", "AM-VD" => "Vayoฤ‡ Jor" }, "AO" => { "AO-BGO" => "Bengo", "AO-BGU" => "Benguela", "AO-BIE" => "Biรฉ", "AO-CAB" => "Cabinda", "AO-CNN" => "Cunene", "AO-HUA" => "Huambo", "AO-HUI" => "Huรญla", "AO-CCU" => "Cuando Cubango", "AO-CNO" => "Cuanza-Norte", "AO-CUS" => "Cuanza-Sul", "AO-LUA" => "Luanda", "AO-LNO" => "Lunda-Norte", "AO-LSU" => "Lunda-Sul", "AO-MAL" => "Malange", "AO-MOX" => "Moxico", "AO-NAM" => "Namibe", "AO-UIG" => "Uรญge", "AO-ZAI" => "Zaire" }, "AR" => { "AR-C" => "Ciudad Autรณnoma de Buenos Aires", "AR-B" => "Buenos Aires", "AR-K" => "Catamarca", "AR-H" => "Chaco", "AR-U" => "Chubut", "AR-X" => "Cรณrdoba", "AR-W" => "Corrientes", "AR-E" => "Entre Rรญos", "AR-P" => "Formosa", "AR-Y" => "Jujuy", "AR-L" => "La Pampa", "AR-F" => "La Rioja", "AR-M" => "Mendoza", "AR-N" => "Misiones", "AR-Q" => "Neuquรฉn", "AR-R" => "Rรญo Negro", "AR-A" => "Salta", "AR-J" => "San Juan", "AR-D" => "San Luis", "AR-Z" => "Santa Cruz", "AR-S" => "Santa Fe", "AR-G" => "Santiago del Estero", "AR-V" => "Tierra del Fuego", "AR-T" => "Tucumรกn" }, "AT" => { "AT-1" => "Burgenland", "AT-2" => "Kรคrnten", "AT-3" => "Niederรถsterreich", "AT-4" => "Oberรถsterreich", "AT-5" => "Salzburg", "AT-6" => "Steiermark", "AT-7" => "Tirol", "AT-8" => "Vorarlberg", "AT-9" => "Wien" }, "AU" => { "AU-NSW" => "New South Wales", "AU-QLD" => "Queensland", "AU-SA" => "South Australia", "AU-TAS" => "Tasmania", "AU-VIC" => "Victoria", "AU-WA" => "Western Australia", "AU-ACT" => "Australian Capital Territory", "AU-NT" => "Northern Territory" }, "AZ" => { "AZ-NX" => "Naxรงฤฑvan" }, "BA" => { "BA-BIH" => "Federacija Bosne i Hercegovine", "BA-SRP" => "Republika Srpska", "BA-BRC" => "Brฤko distrikt" }, "BB" => { "BB-01" => "Christ Church", "BB-02" => "Saint Andrew", "BB-03" => "Saint George", "BB-04" => "Saint James", "BB-05" => "Saint John", "BB-06" => "Saint Joseph", "BB-07" => "Saint Lucy", "BB-08" => "Saint Michael", "BB-09" => "Saint Peter", "BB-10" => "Saint Philip", "BB-11" => "Saint Thomas" }, "BD" => { "BD-A" => "Barishal", "BD-B" => "Chattogram", "BD-C" => "Dhaka", "BD-D" => "Khulna", "BD-H" => "Mymensingh", "BD-E" => "Rajshahi", "BD-F" => "Rangpur", "BD-G" => "Sylhet" }, "BE" => { "BE-BRU" => "Brussels Hoofdstedelijk Gewest", "BE-VLG" => "Vlaams Gewest", "BE-WAL" => "Waals Gewest [note 3]" }, "BF" => { "BF-01" => "Boucle du Mouhoun", "BF-02" => "Cascades", "BF-03" => "Centre", "BF-04" => "Centre-Est", "BF-05" => "Centre-Nord", "BF-06" => "Centre-Ouest", "BF-07" => "Centre-Sud", "BF-08" => "Est", "BF-09" => "Hauts-Bassins", "BF-10" => "Nord", "BF-11" => "Plateau-Central", "BF-12" => "Sahel", "BF-13" => "Sud-Ouest" }, "BG" => { "BG-01" => "Blagoevgrad", "BG-02" => "Burgas", "BG-08" => "Dobrich", "BG-07" => "Gabrovo", "BG-26" => "Haskovo", "BG-09" => "Kardzhali", "BG-10" => "Kyustendil", "BG-11" => "Lovech", "BG-12" => "Montana", "BG-13" => "Pazardzhik", "BG-14" => "Pernik", "BG-15" => "Pleven", "BG-16" => "Plovdiv", "BG-17" => "Razgrad", "BG-18" => "Ruse", "BG-27" => "Shumen", "BG-19" => "Silistra", "BG-20" => "Sliven", "BG-21" => "Smolyan", "BG-23" => "Sofia", "BG-22" => "Sofia (stolitsa)", "BG-24" => "Stara Zagora", "BG-25" => "Targovishte", "BG-03" => "Varna", "BG-04" => "Veliko Tarnovo", "BG-05" => "Vidin", "BG-06" => "Vratsa", "BG-28" => "Yambol" }, "BH" => { "BH-13" => "Al โ€˜ฤ€ลŸimah", "BH-14" => "Al Janลซbฤซyah", "BH-15" => "Al Muแธฉarraq", "BH-17" => "Ash Shamฤlฤซyah" }, "BI" => { "BI-BB" => "Bubanza", "BI-BM" => "Bujumbura Mairie", "BI-BL" => "Bujumbura Rural", "BI-BR" => "Bururi", "BI-CA" => "Cankuzo", "BI-CI" => "Cibitoke", "BI-GI" => "Gitega", "BI-KR" => "Karuzi", "BI-KY" => "Kayanza", "BI-KI" => "Kirundo", "BI-MA" => "Makamba", "BI-MU" => "Muramvya", "BI-MY" => "Muyinga", "BI-MW" => "Mwaro", "BI-NG" => "Ngozi", "BI-RM" => "Rumonge", "BI-RT" => "Rutana", "BI-RY" => "Ruyigi" }, "BJ" => { "BJ-AL" => "Alibori", "BJ-AK" => "Atacora", "BJ-AQ" => "Atlantique", "BJ-BO" => "Borgou", "BJ-CO" => "Collines", "BJ-KO" => "Couffo", "BJ-DO" => "Donga", "BJ-LI" => "Littoral", "BJ-MO" => "Mono", "BJ-OU" => "Ouรฉmรฉ", "BJ-PL" => "Plateau", "BJ-ZO" => "Zou" }, "BN" => { "BN-BE" => "Belait", "BN-BM" => "Brunei-Muara", "BN-TE" => "Temburong", "BN-TU" => "Tutong" }, "BO" => { "BO-C" => "Cochabamba", "BO-H" => "Chuquisaca", "BO-B" => "El Beni", "BO-L" => "La Paz", "BO-O" => "Oruro", "BO-N" => "Pando", "BO-P" => "Potosรญ", "BO-S" => "Santa Cruz", "BO-T" => "Tarija" }, "BQ" => { "BQ-BO" => "Bonaire", "BQ-SA" => "Saba", "BQ-SE" => "Sint Eustatius" }, "BR" => { "BR-AC" => "Acre", "BR-AL" => "Alagoas", "BR-AP" => "Amapรก", "BR-AM" => "Amazonas", "BR-BA" => "Bahia", "BR-CE" => "Cearรก", "BR-DF" => "Distrito Federal", "BR-ES" => "Espรญrito Santo", "BR-GO" => "Goiรกs", "BR-MA" => "Maranhรฃo", "BR-MT" => "Mato Grosso", "BR-MS" => "Mato Grosso do Sul", "BR-MG" => "Minas Gerais", "BR-PA" => "Parรก", "BR-PB" => "Paraรญba", "BR-PR" => "Paranรก", "BR-PE" => "Pernambuco", "BR-PI" => "Piauรญ", "BR-RJ" => "Rio de Janeiro", "BR-RN" => "Rio Grande do Norte", "BR-RS" => "Rio Grande do Sul", "BR-RO" => "Rondรดnia", "BR-RR" => "Roraima", "BR-SC" => "Santa Catarina", "BR-SP" => "Sรฃo Paulo", "BR-SE" => "Sergipe", "BR-TO" => "Tocantins" }, "BS" => { "BS-AK" => "Acklins", "BS-BY" => "Berry Islands", "BS-BI" => "Bimini", "BS-BP" => "Black Point", "BS-CI" => "Cat Island", "BS-CO" => "Central Abaco", "BS-CS" => "Central Andros", "BS-CE" => "Central Eleuthera", "BS-FP" => "City of Freeport", "BS-CK" => "Crooked Island and Long Cay", "BS-EG" => "East Grand Bahama", "BS-EX" => "Exuma", "BS-GC" => "Grand Cay", "BS-HI" => "Harbour Island", "BS-HT" => "Hope Town", "BS-IN" => "Inagua", "BS-LI" => "Long Island", "BS-MC" => "Mangrove Cay", "BS-MG" => "Mayaguana", "BS-MI" => "Moore's Island", "BS-NP" => "New Providence", "BS-NO" => "North Abaco", "BS-NS" => "North Andros", "BS-NE" => "North Eleuthera", "BS-RI" => "Ragged Island", "BS-RC" => "Rum Cay", "BS-SS" => "San Salvador", "BS-SO" => "South Abaco", "BS-SA" => "South Andros", "BS-SE" => "South Eleuthera", "BS-SW" => "Spanish Wells", "BS-WG" => "West Grand Bahama" }, "BT" => { "BT-33" => "Bumthang", "BT-12" => "Chhukha", "BT-22" => "Dagana", "BT-GA" => "Gasa", "BT-13" => "Haa", "BT-44" => "Lhuentse", "BT-42" => "Monggar", "BT-11" => "Paro", "BT-43" => "Pema Gatshel", "BT-23" => "Punakha", "BT-45" => "Samdrup Jongkhar", "BT-14" => "Samtse", "BT-31" => "Sarpang", "BT-15" => "Thimphu", "BT-41" => "Trashigang", "BT-TY" => "Trashi Yangtse", "BT-32" => "Trongsa", "BT-21" => "Tsirang", "BT-24" => "Wangdue Phodrang", "BT-34" => "Zhemgang" }, "BW" => { "BW-CE" => "Central", "BW-CH" => "Chobe", "BW-FR" => "Francistown", "BW-GA" => "Gaborone", "BW-GH" => "Ghanzi", "BW-JW" => "Jwaneng", "BW-KG" => "Kgalagadi", "BW-KL" => "Kgatleng", "BW-KW" => "Kweneng", "BW-LO" => "Lobatse", "BW-NE" => "North East", "BW-NW" => "North West", "BW-SP" => "Selibe Phikwe", "BW-SE" => "South East", "BW-SO" => "Southern", "BW-ST" => "Sowa Town" }, "BY" => { "BY-BR" => "Brestskaya voblasts'", "BY-HO" => "Homyel'skaya voblasts'", "BY-HR" => "Hrodzyenskaya voblasts'", "BY-MA" => "Mahilyowskaya voblasts'", "BY-MI" => "Minskaya voblasts'", "BY-VI" => "Vitsyebskaya voblasts'", "BY-HM" => "Horad Minsk" }, "BZ" => { "BZ-BZ" => "Belize", "BZ-CY" => "Cayo", "BZ-CZL" => "Corozal", "BZ-OW" => "Orange Walk", "BZ-SC" => "Stann Creek", "BZ-TOL" => "Toledo" }, "CA" => { "CA-AB" => "Alberta", "CA-BC" => "British Columbia", "CA-MB" => "Manitoba", "CA-NB" => "New Brunswick", "CA-NL" => "Newfoundland and Labrador", "CA-NS" => "Nova Scotia", "CA-ON" => "Ontario", "CA-PE" => "Prince Edward Island", "CA-QC" => "Quebec", "CA-SK" => "Saskatchewan", "CA-NT" => "Northwest Territories", "CA-NU" => "Nunavut", "CA-YT" => "Yukon" }, "CD" => { "CD-KN" => "Kinshasa", "CD-BC" => "Kongo Central", "CD-EQ" => "ร‰quateur", "CD-KE" => "Kasaรฏ Oriental", "CD-MA" => "Maniema", "CD-NK" => "Nord-Kivu", "CD-SK" => "Sud-Kivu", "CD-BU" => "Bas-Uรฉlรฉ", "CD-HK" => "Haut-Katanga", "CD-HL" => "Haut-Lomami", "CD-HU" => "Haut-Uรฉlรฉ", "CD-IT" => "Ituri", "CD-KC" => "Kasaรฏ Central", "CD-KG" => "Kwango", "CD-KL" => "Kwilu", "CD-KS" => "Kasaรฏ", "CD-LO" => "Lomami", "CD-LU" => "Lualaba", "CD-MN" => "Mai-Ndombe", "CD-MO" => "Mongala", "CD-NU" => "Nord-Ubangi", "CD-SA" => "Sankuru", "CD-SU" => "Sud-Ubangi", "CD-TA" => "Tanganyika", "CD-TO" => "Tshopo", "CD-TU" => "Tshuapa" }, "CF" => { "CF-BGF" => "Bangui", "CF-BB" => "Bamingui-Bangoran", "CF-BK" => "Basse-Kotto", "CF-HK" => "Haute-Kotto", "CF-HM" => "Haut-Mbomou", "CF-HS" => "Haute-Sangha/Mambรฉrรฉ-Kadรฉรฏ", "CF-KG" => "Kรฉmo-Gribingui", "CF-LB" => "Lobaye", "CF-MB" => "Mbomou", "CF-NM" => "Nana-Mambรฉrรฉ", "CF-MP" => "Ombella-Mpoko", "CF-UK" => "Ouaka", "CF-AC" => "Ouham", "CF-OP" => "Ouham-Pendรฉ", "CF-VK" => "Vakaga", "CF-KB" => "Gribingui", "CF-SE" => "Sangha" }, "CG" => { "CG-BZV" => "Brazzaville", "CG-11" => "Bouenza", "CG-8" => "Cuvette", "CG-15" => "Cuvette-Ouest", "CG-5" => "Kouilou", "CG-2" => "Lรฉkoumou", "CG-7" => "Likouala", "CG-9" => "Niari", "CG-14" => "Plateaux", "CG-16" => "Pointe-Noire", "CG-12" => "Pool", "CG-13" => "Sangha" }, "CH" => { "CH-AG" => "Aargau (de)", "CH-AR" => "Appenzell Ausserrhoden (de)", "CH-AI" => "Appenzell Innerrhoden (de)", "CH-BL" => "Basel-Landschaft (de)", "CH-BS" => "Basel-Stadt (de)", "CH-BE" => "Bern (de), Berne (fr)", "CH-FR" => "Fribourg (fr), Freiburg (de)", "CH-GE" => "Genรจve (fr)", "CH-GL" => "Glarus (de)", "CH-GR" => "Graubรผnden (de), Grigioni (it), Grischun (rm)", "CH-JU" => "Jura (fr)", "CH-LU" => "Luzern (de)", "CH-NE" => "Neuchรขtel (fr)", "CH-NW" => "Nidwalden (de)", "CH-OW" => "Obwalden (de)", "CH-SG" => "Sankt Gallen (de)", "CH-SH" => "Schaffhausen (de)", "CH-SZ" => "Schwyz (de)", "CH-SO" => "Solothurn (de)", "CH-TG" => "Thurgau (de)", "CH-TI" => "Ticino (it)", "CH-UR" => "Uri (de)", "CH-VS" => "Valais (fr), Wallis (de)", "CH-VD" => "Vaud (fr)", "CH-ZG" => "Zug (de)", "CH-ZH" => "Zรผrich (de)" }, "CI" => { "CI-AB" => "Abidjan", "CI-BS" => "Bas-Sassandra", "CI-CM" => "Comoรฉ", "CI-DN" => "Denguรฉlรฉ", "CI-GD" => "Gรดh-Djiboua", "CI-LC" => "Lacs", "CI-LG" => "Lagunes", "CI-MG" => "Montagnes", "CI-SM" => "Sassandra-Marahouรฉ", "CI-SV" => "Savanes", "CI-VB" => "Vallรฉe du Bandama", "CI-WR" => "Woroba", "CI-YM" => "Yamoussoukro", "CI-ZZ" => "Zanzan" }, "CL" => { "CL-AI" => "Aisรฉn del General Carlos Ibaรฑez del Campo", "CL-AN" => "Antofagasta", "CL-AP" => "Arica y Parinacota", "CL-AR" => "La Araucanรญa", "CL-AT" => "Atacama", "CL-BI" => "Biobรญo", "CL-CO" => "Coquimbo", "CL-LI" => "Libertador General Bernardo O'Higgins", "CL-LL" => "Los Lagos", "CL-LR" => "Los Rรญos", "CL-MA" => "Magallanes", "CL-ML" => "Maule", "CL-NB" => "ร‘uble", "CL-RM" => "Regiรณn Metropolitana de Santiago", "CL-TA" => "Tarapacรก", "CL-VS" => "Valparaรญso" }, "CM" => { "CM-AD" => "Adamaoua", "CM-CE" => "Centre", "CM-ES" => "East", "CM-EN" => "Far North", "CM-LT" => "Littoral", "CM-NO" => "North", "CM-NW" => "North-West", "CM-SU" => "South", "CM-SW" => "South-West", "CM-OU" => "West" }, "CN" => { "CN-AH" => "Anhui Sheng", "CN-BJ" => "Beijing Shi", "CN-CQ" => "Chongqing Shi", "CN-FJ" => "Fujian Sheng", "CN-GD" => "Guangdong Sheng", "CN-GS" => "Gansu Sheng", "CN-GX" => "Guangxi Zhuangzu Zizhiqu", "CN-GZ" => "Guizhou Sheng", "CN-HA" => "Henan Sheng", "CN-HB" => "Hubei Sheng", "CN-HE" => "Hebei Sheng", "CN-HI" => "Hainan Sheng", "CN-HK" => "Hong Kong SAR (en)Xianggang Tebiexingzhengqu (zh)", "CN-HL" => "Heilongjiang Sheng", "CN-HN" => "Hunan Sheng", "CN-JL" => "Jilin Sheng", "CN-JS" => "Jiangsu Sheng", "CN-JX" => "Jiangxi Sheng", "CN-LN" => "Liaoning Sheng", "CN-MO" => "Macao SAR (en)Macau SAR (pt)Aomen Tebiexingzhengqu (zh)", "CN-NM" => "Nei Mongol Zizhiqu", "CN-NX" => "Ningxia Huizi Zizhiqu", "CN-QH" => "Qinghai Sheng", "CN-SC" => "Sichuan Sheng", "CN-SD" => "Shandong Sheng", "CN-SH" => "Shanghai Shi", "CN-SN" => "Shaanxi Sheng", "CN-SX" => "Shanxi Sheng", "CN-TJ" => "Tianjin Shi", "CN-TW" => "Taiwan Sheng", "CN-XJ" => "Xinjiang Uygur Zizhiqu", "CN-XZ" => "Xizang Zizhiqu", "CN-YN" => "Yunnan Sheng", "CN-ZJ" => "Zhejiang Sheng" }, "CO" => { "CO-DC" => "Distrito Capital de Bogotรก", "CO-AMA" => "Amazonas", "CO-ANT" => "Antioquia", "CO-ARA" => "Arauca", "CO-ATL" => "Atlรกntico", "CO-BOL" => "Bolรญvar", "CO-BOY" => "Boyacรก", "CO-CAL" => "Caldas", "CO-CAQ" => "Caquetรก", "CO-CAS" => "Casanare", "CO-CAU" => "Cauca", "CO-CES" => "Cesar", "CO-COR" => "Cรณrdoba", "CO-CUN" => "Cundinamarca", "CO-CHO" => "Chocรณ", "CO-GUA" => "Guainรญa", "CO-GUV" => "Guaviare", "CO-HUI" => "Huila", "CO-LAG" => "La Guajira", "CO-MAG" => "Magdalena", "CO-MET" => "Meta", "CO-NAR" => "Nariรฑo", "CO-NSA" => "Norte de Santander", "CO-PUT" => "Putumayo", "CO-QUI" => "Quindรญo", "CO-RIS" => "Risaralda", "CO-SAP" => "San Andrรฉs, Providencia y Santa Catalina", "CO-SAN" => "Santander", "CO-SUC" => "Sucre", "CO-TOL" => "Tolima", "CO-VAC" => "Valle del Cauca", "CO-VAU" => "Vaupรฉs", "CO-VID" => "Vichada" }, "CR" => { "CR-A" => "Alajuela", "CR-C" => "Cartago", "CR-G" => "Guanacaste", "CR-H" => "Heredia", "CR-L" => "Limรณn", "CR-P" => "Puntarenas", "CR-SJ" => "San Josรฉ" }, "CU" => { "CU-15" => "Artemisa", "CU-09" => "Camagรผey", "CU-08" => "Ciego de รvila", "CU-06" => "Cienfuegos", "CU-12" => "Granma", "CU-14" => "Guantรกnamo", "CU-11" => "Holguรญn", "CU-03" => "La Habana", "CU-10" => "Las Tunas", "CU-04" => "Matanzas", "CU-16" => "Mayabeque", "CU-01" => "Pinar del Rรญo", "CU-07" => "Sancti Spรญritus", "CU-13" => "Santiago de Cuba", "CU-05" => "Villa Clara", "CU-99" => "Isla de la Juventud" }, "CV" => { "CV-B" => "Ilhas de Barlavento", "CV-S" => "Ilhas de Sotavento" }, "CY" => { "CY-04" => "Ammochostos", "CY-06" => "Keryneia", "CY-03" => "Larnaka", "CY-01" => "Lefkosia", "CY-02" => "Lemesos", "CY-05" => "Pafos" }, "CZ" => { "CZ-31" => "Jihoฤeskรฝ kraj", "CZ-64" => "Jihomoravskรฝ kraj", "CZ-41" => "Karlovarskรฝ kraj", "CZ-52" => "Krรกlovรฉhradeckรฝ kraj", "CZ-51" => "Libereckรฝ kraj", "CZ-80" => "Moravskoslezskรฝ kraj", "CZ-71" => "Olomouckรฝ kraj", "CZ-53" => "Pardubickรฝ kraj", "CZ-32" => "Plzeลˆskรฝ kraj", "CZ-10" => "Praha, Hlavnรญ mฤ›sto", "CZ-20" => "Stล™edoฤeskรฝ kraj", "CZ-42" => "รšsteckรฝ kraj", "CZ-63" => "Kraj Vysoฤina", "CZ-72" => "Zlรญnskรฝ kraj" }, "DE" => { "DE-BW" => "Baden-Wรผrttemberg", "DE-BY" => "Bayern", "DE-BE" => "Berlin", "DE-BB" => "Brandenburg", "DE-HB" => "Bremen", "DE-HH" => "Hamburg", "DE-HE" => "Hessen", "DE-MV" => "Mecklenburg-Vorpommern", "DE-NI" => "Niedersachsen", "DE-NW" => "Nordrhein-Westfalen", "DE-RP" => "Rheinland-Pfalz", "DE-SL" => "Saarland", "DE-SN" => "Sachsen", "DE-ST" => "Sachsen-Anhalt", "DE-SH" => "Schleswig-Holstein", "DE-TH" => "Thรผringen" }, "DJ" => { "DJ-AS" => "Ali Sabieh", "DJ-AR" => "Arta", "DJ-DI" => "Dikhil", "DJ-OB" => "Obock", "DJ-TA" => "Tadjourah", "DJ-DJ" => "Djibouti" }, "DK" => { "DK-84" => "Hovedstaden", "DK-82" => "Midtjylland", "DK-81" => "Nordjylland", "DK-85" => "Sjรฆlland", "DK-83" => "Syddanmark" }, "DM" => { "DM-02" => "Saint Andrew", "DM-03" => "Saint David", "DM-04" => "Saint George", "DM-05" => "Saint John", "DM-06" => "Saint Joseph", "DM-07" => "Saint Luke", "DM-08" => "Saint Mark", "DM-09" => "Saint Patrick", "DM-10" => "Saint Paul", "DM-11" => "Saint Peter" }, "DO" => { "DO-33" => "Cibao Nordeste", "DO-34" => "Cibao Noroeste", "DO-35" => "Cibao Norte", "DO-36" => "Cibao Sur", "DO-37" => "El Valle", "DO-38" => "Enriquillo", "DO-39" => "Higuamo", "DO-40" => "Ozama", "DO-41" => "Valdesia", "DO-42" => "Yuma" }, "DZ" => { "DZ-01" => "Adrar", "DZ-44" => "Aรฏn Defla", "DZ-46" => "Aรฏn Tรฉmouchent", "DZ-16" => "Alger", "DZ-23" => "Annaba", "DZ-05" => "Batna", "DZ-08" => "Bรฉchar", "DZ-06" => "Bรฉjaรฏa", "DZ-07" => "Biskra", "DZ-09" => "Blida", "DZ-34" => "Bordj Bou Arrรฉridj", "DZ-10" => "Bouira", "DZ-35" => "Boumerdรจs", "DZ-02" => "Chlef", "DZ-25" => "Constantine", "DZ-17" => "Djelfa", "DZ-32" => "El Bayadh", "DZ-39" => "El Oued", "DZ-36" => "El Tarf", "DZ-47" => "Ghardaรฏa", "DZ-24" => "Guelma", "DZ-33" => "Illizi", "DZ-18" => "Jijel", "DZ-40" => "Khenchela", "DZ-03" => "Laghouat", "DZ-28" => "M'sila", "DZ-29" => "Mascara", "DZ-26" => "Mรฉdรฉa", "DZ-43" => "Mila", "DZ-27" => "Mostaganem", "DZ-45" => "Naama", "DZ-31" => "Oran", "DZ-30" => "Ouargla", "DZ-04" => "Oum el Bouaghi", "DZ-48" => "Relizane", "DZ-20" => "Saรฏda", "DZ-19" => "Sรฉtif", "DZ-22" => "Sidi Bel Abbรจs", "DZ-21" => "Skikda", "DZ-41" => "Souk Ahras", "DZ-11" => "Tamanrasset", "DZ-12" => "Tรฉbessa", "DZ-14" => "Tiaret", "DZ-37" => "Tindouf", "DZ-42" => "Tipaza", "DZ-38" => "Tissemsilt", "DZ-15" => "Tizi Ouzou", "DZ-13" => "Tlemcen" }, "EC" => { "EC-A" => "Azuay", "EC-B" => "Bolรญvar", "EC-F" => "Caรฑar", "EC-C" => "Carchi", "EC-H" => "Chimborazo", "EC-X" => "Cotopaxi", "EC-O" => "El Oro", "EC-E" => "Esmeraldas", "EC-W" => "Galรกpagos", "EC-G" => "Guayas", "EC-I" => "Imbabura", "EC-L" => "Loja", "EC-R" => "Los Rรญos", "EC-M" => "Manabรญ", "EC-S" => "Morona Santiago", "EC-N" => "Napo", "EC-D" => "Orellana", "EC-Y" => "Pastaza", "EC-P" => "Pichincha", "EC-SE" => "Santa Elena", "EC-SD" => "Santo Domingo de los Tsรกchilas", "EC-U" => "Sucumbรญos", "EC-T" => "Tungurahua", "EC-Z" => "Zamora Chinchipe" }, "EE" => { "EE-37" => "Harjumaa", "EE-39" => "Hiiumaa", "EE-45" => "Ida-Virumaa", "EE-50" => "Jรตgevamaa", "EE-52" => "Jรคrvamaa", "EE-56" => "Lรครคnemaa", "EE-60" => "Lรครคne-Virumaa", "EE-64" => "Pรตlvamaa", "EE-68" => "Pรคrnumaa", "EE-71" => "Raplamaa", "EE-74" => "Saaremaa", "EE-79" => "Tartumaa", "EE-81" => "Valgamaa", "EE-84" => "Viljandimaa", "EE-87" => "Vรตrumaa" }, "EG" => { "EG-DK" => "Ad Daqahlฤซyah", "EG-BA" => "Al Baแธฉr al Aแธฉmar", "EG-BH" => "Al Buแธฉayrah", "EG-FYM" => "Al Fayyลซm", "EG-GH" => "Al Gharbฤซyah", "EG-ALX" => "Al Iskandarฤซyah", "EG-IS" => "Al Ismฤ'ฤซlฤซyah", "EG-GZ" => "Al Jฤซzah", "EG-MNF" => "Al Minลซfฤซyah", "EG-MN" => "Al Minyฤ", "EG-C" => "Al Qฤhirah", "EG-KB" => "Al Qalyลซbฤซyah", "EG-LX" => "Al UqลŸur", "EG-WAD" => "Al Wฤdฤซ al Jadฤซd", "EG-SUZ" => "As Suways", "EG-SHR" => "Ash Sharqฤซyah", "EG-ASN" => "Aswฤn", "EG-AST" => "Asyลซลฃ", "EG-BNS" => "Banฤซ Suwayf", "EG-PTS" => "Bลซr Saโ€˜ฤซd", "EG-DT" => "Dumyฤลฃ", "EG-JS" => "Janลซb Sฤซnฤ'", "EG-KFS" => "Kafr ash Shaykh", "EG-MT" => "Maลฃrลซแธฉ", "EG-KN" => "Qinฤ", "EG-SIN" => "Shamฤl Sฤซnฤ'", "EG-SHG" => "Sลซhฤj" }, "ER" => { "ER-MA" => "Al Awsaลฃ", "ER-DU" => "Al Janลซbฤซ", "ER-AN" => "Ansabฤ", "ER-DK" => "Janลซbฤซ al Baแธฉrฤซ al Aแธฉmar", "ER-GB" => "Qฤsh-Barkah", "ER-SK" => "Shimฤlฤซ al Baแธฉrฤซ al Aแธฉmar" }, "ES" => { "ES-AN" => "Andalucรญa", "ES-AR" => "Aragรณn", "ES-AS" => "Asturias, Principado de", "ES-CN" => "Canarias", "ES-CB" => "Cantabria", "ES-CL" => "Castilla y Leรณn", "ES-CM" => "Castilla-La Mancha", "ES-CT" => "Catalunya (ca) [Cataluรฑa]", "ES-CE" => "Ceuta", "ES-EX" => "Extremadura", "ES-GA" => "Galicia (gl) [Galicia]", "ES-IB" => "Illes Balears (ca) [Islas Baleares]", "ES-RI" => "La Rioja", "ES-MD" => "Madrid, Comunidad de", "ES-ML" => "Melilla", "ES-MC" => "Murcia, Regiรณn de", "ES-NC" => "Navarra, Comunidad Foral deNafarroako Foru Komunitatea (eu)", "ES-PV" => "Paรญs VascoEuskal Herria (eu)", "ES-VC" => "Valenciana, Comunitat (ca) [Valenciana, Comunidad]" }, "ET" => { "ET-AA" => "ฤ€dฤซs ฤ€beba", "ET-DD" => "Dirฤ“ Dawa", "ET-AF" => "ฤ€far", "ET-AM" => "ฤ€mara", "ET-BE" => "Bฤซnshangul Gumuz", "ET-GA" => "Gambฤ“la Hizboch", "ET-HA" => "Hฤrerฤซ Hizb", "ET-OR" => "Oromฤซya", "ET-SO" => "Sumalฤ“", "ET-TI" => "Tigray", "ET-SN" => "YeDebub Bihฤ“roch Bihฤ“reseboch na Hizboch" }, "FI" => { "FI-01" => "Ahvenanmaan maakunta", "FI-02" => "Etelรค-Karjala", "FI-03" => "Etelรค-Pohjanmaa", "FI-04" => "Etelรค-Savo", "FI-05" => "Kainuu", "FI-06" => "Kanta-Hรคme", "FI-07" => "Keski-Pohjanmaa", "FI-08" => "Keski-Suomi", "FI-09" => "Kymenlaakso", "FI-10" => "Lappi", "FI-11" => "Pirkanmaa", "FI-12" => "Pohjanmaa", "FI-13" => "Pohjois-Karjala", "FI-14" => "Pohjois-Pohjanmaa", "FI-15" => "Pohjois-Savo", "FI-16" => "Pรคijรคt-Hรคme", "FI-17" => "Satakunta", "FI-18" => "Uusimaa", "FI-19" => "Varsinais-Suomi" }, "FJ" => { "FJ-C" => "Central", "FJ-E" => "Eastern", "FJ-N" => "Northern", "FJ-W" => "Western", "FJ-R" => "Rotuma" }, "FM" => { "FM-TRK" => "Chuuk", "FM-KSA" => "Kosrae", "FM-PNI" => "Pohnpei", "FM-YAP" => "Yap" }, "FR" => { "FR-ARA" => "Auvergne-Rhรดne-Alpes", "FR-BFC" => "Bourgogne-Franche-Comtรฉ", "FR-BRE" => "Bretagne", "FR-CVL" => "Centre-Val de Loire", "FR-20R" => "Corse", "FR-GES" => "Grand-Est", "FR-GP" => "Guadeloupe", "FR-GF" => "Guyane (franรงaise)", "FR-HDF" => "Hauts-de-France", "FR-IDF" => "รŽle-de-France", "FR-MQ" => "Martinique", "FR-YT" => "Mayotte", "FR-NOR" => "Normandie", "FR-NAQ" => "Nouvelle-Aquitaine", "FR-OCC" => "Occitanie", "FR-PDL" => "Pays-de-la-Loire", "FR-PAC" => "Provence-Alpes-Cรดte-dโ€™Azur", "FR-RE" => "La Rรฉunion" }, "GA" => { "GA-1" => "Estuaire", "GA-2" => "Haut-Ogoouรฉ", "GA-3" => "Moyen-Ogoouรฉ", "GA-4" => "Ngouniรฉ", "GA-5" => "Nyanga", "GA-6" => "Ogoouรฉ-Ivindo", "GA-7" => "Ogoouรฉ-Lolo", "GA-8" => "Ogoouรฉ-Maritime", "GA-9" => "Woleu-Ntem" }, "GB" => { "GB-ENG" => "England", "GB-NIR" => "Northern Ireland", "GB-SCT" => "Scotland", "GB-WLS" => "Wales [Cymru GB-CYM]" }, "GD" => { "GD-01" => "Saint Andrew", "GD-02" => "Saint David", "GD-03" => "Saint George", "GD-04" => "Saint John", "GD-05" => "Saint Mark", "GD-06" => "Saint Patrick", "GD-10" => "Southern Grenadine Islands" }, "GE" => { "GE-AB" => "Abkhazia", "GE-AJ" => "Ajaria", "GE-TB" => "Tbilisi", "GE-GU" => "Guria", "GE-IM" => "Imereti", "GE-KA" => "K'akheti", "GE-KK" => "Kvemo Kartli", "GE-MM" => "Mtskheta-Mtianeti", "GE-RL" => "Rach'a-Lechkhumi-Kvemo Svaneti", "GE-SZ" => "Samegrelo-Zemo Svaneti", "GE-SJ" => "Samtskhe-Javakheti", "GE-SK" => "Shida Kartli" }, "GH" => { "GH-AF" => "Ahafo", "GH-AH" => "Ashanti", "GH-BO" => "Bono", "GH-BE" => "Bono East", "GH-CP" => "Central", "GH-EP" => "Eastern", "GH-AA" => "Greater Accra", "GH-NE" => "North East", "GH-NP" => "Northern", "GH-OT" => "Oti", "GH-SV" => "Savannah", "GH-UE" => "Upper East", "GH-UW" => "Upper West", "GH-TV" => "Volta", "GH-WP" => "Western", "GH-WN" => "Western North" }, "GL" => { "GL-AV" => "Avannaata Kommunia", "GL-KU" => "Kommune Kujalleq", "GL-QT" => "Kommune Qeqertalik", "GL-SM" => "Kommuneqarfik Sermersooq", "GL-QE" => "Qeqqata Kommunia" }, "GM" => { "GM-B" => "Banjul", "GM-M" => "Central River", "GM-L" => "Lower River", "GM-N" => "North Bank", "GM-U" => "Upper River", "GM-W" => "Western" }, "GN" => { "GN-B" => "Bokรฉ", "GN-F" => "Faranah", "GN-K" => "Kankan", "GN-D" => "Kindia", "GN-L" => "Labรฉ", "GN-M" => "Mamou", "GN-N" => "Nzรฉrรฉkorรฉ", "GN-C" => "Conakry" }, "GQ" => { "GQ-C" => "Regiรณn Continental", "GQ-I" => "Regiรณn Insular" }, "GR" => { "GR-A" => "Anatolikรญ Makedonรญa kai Thrรกki", "GR-I" => "Attikรญ", "GR-G" => "Dytikรญ Ellรกda", "GR-C" => "Dytikรญ Makedonรญa", "GR-F" => "Ionรญa Nรญsia", "GR-D" => "รpeiros", "GR-B" => "Kentrikรญ Makedonรญa", "GR-M" => "Krรญti", "GR-L" => "Nรณtio Aigaรญo", "GR-J" => "Pelopรณnnisos", "GR-H" => "Stereรก Ellรกda", "GR-E" => "Thessalรญa", "GR-K" => "Vรณreio Aigaรญo" }, "GT" => { "GT-AV" => "Alta Verapaz", "GT-BV" => "Baja Verapaz", "GT-CM" => "Chimaltenango", "GT-CQ" => "Chiquimula", "GT-PR" => "El Progreso", "GT-ES" => "Escuintla", "GT-GU" => "Guatemala", "GT-HU" => "Huehuetenango", "GT-IZ" => "Izabal", "GT-JA" => "Jalapa", "GT-JU" => "Jutiapa", "GT-PE" => "Petรฉn", "GT-QZ" => "Quetzaltenango", "GT-QC" => "Quichรฉ", "GT-RE" => "Retalhuleu", "GT-SA" => "Sacatepรฉquez", "GT-SM" => "San Marcos", "GT-SR" => "Santa Rosa", "GT-SO" => "Sololรก", "GT-SU" => "Suchitepรฉquez", "GT-TO" => "Totonicapรกn", "GT-ZA" => "Zacapa" }, "GW" => { "GW-L" => "Leste", "GW-N" => "Norte", "GW-S" => "Sul" }, "GY" => { "GY-BA" => "Barima-Waini", "GY-CU" => "Cuyuni-Mazaruni", "GY-DE" => "Demerara-Mahaica", "GY-EB" => "East Berbice-Corentyne", "GY-ES" => "Essequibo Islands-West Demerara", "GY-MA" => "Mahaica-Berbice", "GY-PM" => "Pomeroon-Supenaam", "GY-PT" => "Potaro-Siparuni", "GY-UD" => "Upper Demerara-Berbice", "GY-UT" => "Upper Takutu-Upper Essequibo" }, "HN" => { "HN-AT" => "Atlรกntida", "HN-CH" => "Choluteca", "HN-CL" => "Colรณn", "HN-CM" => "Comayagua", "HN-CP" => "Copรกn", "HN-CR" => "Cortรฉs", "HN-EP" => "El Paraรญso", "HN-FM" => "Francisco Morazรกn", "HN-GD" => "Gracias a Dios", "HN-IN" => "Intibucรก", "HN-IB" => "Islas de la Bahรญa", "HN-LP" => "La Paz", "HN-LE" => "Lempira", "HN-OC" => "Ocotepeque", "HN-OL" => "Olancho", "HN-SB" => "Santa Bรกrbara", "HN-VA" => "Valle", "HN-YO" => "Yoro" }, "HR" => { "HR-21" => "Grad Zagreb", "HR-07" => "Bjelovarsko-bilogorska ลพupanija", "HR-12" => "Brodsko-posavska ลพupanija", "HR-19" => "Dubrovaฤko-neretvanska ลพupanija", "HR-18" => "Istarska ลพupanija", "HR-04" => "Karlovaฤka ลพupanija", "HR-06" => "Koprivniฤko-kriลพevaฤka ลพupanija", "HR-02" => "Krapinsko-zagorska ลพupanija", "HR-09" => "Liฤko-senjska ลพupanija", "HR-20" => "Meฤ‘imurska ลพupanija", "HR-14" => "Osjeฤko-baranjska ลพupanija", "HR-11" => "Poลพeลกko-slavonska ลพupanija", "HR-08" => "Primorsko-goranska ลพupanija", "HR-03" => "Sisaฤko-moslavaฤka ลพupanija", "HR-17" => "Splitsko-dalmatinska ลพupanija", "HR-15" => "ล ibensko-kninska ลพupanija", "HR-05" => "Varaลพdinska ลพupanija", "HR-10" => "Virovitiฤko-podravska ลพupanija", "HR-16" => "Vukovarsko-srijemska ลพupanija", "HR-13" => "Zadarska ลพupanija", "HR-01" => "Zagrebaฤka ลพupanija" }, "HT" => { "HT-AR" => "Artibonite", "HT-CE" => "Centre", "HT-GA" => "Grandeโ€™Anse", "HT-NI" => "Nippes", "HT-ND" => "Nord", "HT-NE" => "Nord-Est", "HT-NO" => "Nord-Ouest", "HT-OU" => "Ouest", "HT-SD" => "Sud", "HT-SE" => "Sud-Est" }, "HU" => { "HU-BU" => "Budapest", "HU-BK" => "Bรกcs-Kiskun", "HU-BA" => "Baranya", "HU-BE" => "Bรฉkรฉs", "HU-BZ" => "Borsod-Abaรบj-Zemplรฉn", "HU-CS" => "Csongrรกd", "HU-FE" => "Fejรฉr", "HU-GS" => "Gyล‘r-Moson-Sopron", "HU-HB" => "Hajdรบ-Bihar", "HU-HE" => "Heves", "HU-JN" => "Jรกsz-Nagykun-Szolnok", "HU-KE" => "Komรกrom-Esztergom", "HU-NO" => "Nรณgrรกd", "HU-PE" => "Pest", "HU-SO" => "Somogy", "HU-SZ" => "Szabolcs-Szatmรกr-Bereg", "HU-TO" => "Tolna", "HU-VA" => "Vas", "HU-VE" => "Veszprรฉm", "HU-ZA" => "Zala", "HU-BC" => "Bรฉkรฉscsaba", "HU-DE" => "Debrecen", "HU-DU" => "Dunaรบjvรกros", "HU-EG" => "Eger", "HU-ER" => "ร‰rd", "HU-GY" => "Gyล‘r", "HU-HV" => "Hรณdmezล‘vรกsรกrhely", "HU-KV" => "Kaposvรกr", "HU-KM" => "Kecskemรฉt", "HU-MI" => "Miskolc", "HU-NK" => "Nagykanizsa", "HU-NY" => "Nyรญregyhรกza", "HU-PS" => "Pรฉcs", "HU-ST" => "Salgรณtarjรกn", "HU-SN" => "Sopron", "HU-SD" => "Szeged", "HU-SF" => "Szรฉkesfehรฉrvรกr", "HU-SS" => "Szekszรกrd", "HU-SK" => "Szolnok", "HU-SH" => "Szombathely", "HU-TB" => "Tatabรกnya", "HU-VM" => "Veszprรฉm", "HU-ZE" => "Zalaegerszeg" }, "ID" => { "ID-JW" => "Jawa", "ID-KA" => "Kalimantan", "ID-ML" => "Maluku", "ID-NU" => "Nusa Tenggara", "ID-PP" => "Papua", "ID-SL" => "Sulawesi", "ID-SM" => "Sumatera" }, "IE" => { "IE-C" => "Connaught", "IE-L" => "Leinster", "IE-M" => "Munster", "IE-U" => "Ulster" }, "IL" => { "IL-D" => "HaDarom", "IL-M" => "HaMerkaz", "IL-Z" => "HaTsafon", "IL-HA" => "Hฬฑefa", "IL-TA" => "Tel Aviv", "IL-JM" => "Yerushalayim" }, "IN" => { "IN-AP" => "Andhra Pradesh", "IN-AR" => "Arunฤchal Pradesh", "IN-AS" => "Assam", "IN-BR" => "Bihฤr", "IN-CT" => "Chhattฤซsgarh[note 1]", "IN-GA" => "Goa", "IN-GJ" => "Gujarฤt", "IN-HR" => "Haryฤna", "IN-HP" => "Himฤchal Pradesh", "IN-JH" => "Jhฤrkhand", "IN-KA" => "Karnฤtaka", "IN-KL" => "Kerala", "IN-MP" => "Madhya Pradesh", "IN-MH" => "Mahฤrฤshtra", "IN-MN" => "Manipur", "IN-ML" => "Meghฤlaya", "IN-MZ" => "Mizoram", "IN-NL" => "Nฤgฤland", "IN-OR" => "Odisha[note 2]", "IN-PB" => "Punjab", "IN-RJ" => "Rฤjasthฤn", "IN-SK" => "Sikkim", "IN-TN" => "Tamil Nฤdu", "IN-TG" => "Telangฤna[note 3]", "IN-TR" => "Tripura", "IN-UT" => "Uttarฤkhand[note 4]", "IN-UP" => "Uttar Pradesh", "IN-WB" => "West Bengal", "IN-AN" => "Andaman and Nicobar Islands", "IN-CH" => "Chandigarh", "IN-DH" => "Dฤdra and Nagar Haveli and Damฤn and Diu[note 5]", "IN-DL" => "Delhi", "IN-JK" => "Jammu and Kashmฤซr", "IN-LA" => "Ladฤkh", "IN-LD" => "Lakshadweep", "IN-PY" => "Puducherry" }, "IQ" => { "IQ-AN" => "Al Anbฤr", "IQ-BA" => "Al BaลŸrah", "IQ-MU" => "Al Muthannรก", "IQ-QA" => "Al Qฤdisฤซyah", "IQ-NA" => "An Najaf", "IQ-AR" => "Arbฤซl", "IQ-SU" => "As Sulaymฤnฤซyah", "IQ-BB" => "Bฤbil", "IQ-BG" => "Baghdฤd", "IQ-DA" => "Dahลซk", "IQ-DQ" => "Dhฤซ Qฤr", "IQ-DI" => "Diyฤlรก", "IQ-KA" => "Karbalฤโ€™", "IQ-KI" => "Kirkลซk", "IQ-MA" => "Maysฤn", "IQ-NI" => "Nฤซnawรก", "IQ-SD" => "ลžalฤแธฉ ad Dฤซn", "IQ-WA" => "Wฤsiลฃ", "IQ-HA" => "Halabja" }, "IR" => { "IR-30" => "Alborz", "IR-24" => "Ardabฤซl", "IR-04" => "ฤ€zฬ„ฤrbฤyjฤn-e Ghฤrbฤซ", "IR-03" => "ฤ€zฬ„ฤrbฤyjฤn-e Shฤrqฤซ", "IR-18" => "Bลซshehr", "IR-14" => "Chahฤr Maแธฉฤl va Bakhtฤซฤrฤซ", "IR-10" => "EลŸfahฤn", "IR-07" => "Fฤrs", "IR-01" => "Gฤซlฤn", "IR-27" => "Golestฤn", "IR-13" => "Hamadฤn", "IR-22" => "Hormozgฤn", "IR-16" => "ฤชlฤm", "IR-08" => "Kermฤn", "IR-05" => "Kermฤnshฤh", "IR-29" => "Khorฤsฤn-e Jonลซbฤซ", "IR-09" => "Khorฤsฤn-e Raแบ•avฤซ", "IR-28" => "Khorฤsฤn-e Shomฤlฤซ", "IR-06" => "Khลซzestฤn", "IR-17" => "Kohgฤซlลซyeh va Bowyer Aแธฉmad", "IR-12" => "Kordestฤn", "IR-15" => "Lorestฤn", "IR-00" => "Markazฤซ", "IR-02" => "Mฤzandarฤn", "IR-26" => "Qazvฤซn", "IR-25" => "Qom", "IR-20" => "Semnฤn", "IR-11" => "Sฤซstฤn va Balลซchestฤn", "IR-23" => "Tehrฤn", "IR-21" => "Yazd", "IR-19" => "Zanjฤn" }, "IS" => { "IS-1" => "Hรถfuรฐborgarsvรฆรฐi", "IS-2" => "Suรฐurnes", "IS-3" => "Vesturland", "IS-4" => "Vestfirรฐir", "IS-5" => "Norรฐurland vestra", "IS-6" => "Norรฐurland eystra", "IS-7" => "Austurland", "IS-8" => "Suรฐurland" }, "IT" => { "IT-65" => "Abruzzo", "IT-77" => "Basilicata", "IT-78" => "Calabria", "IT-72" => "Campania", "IT-45" => "Emilia-Romagna", "IT-62" => "Lazio", "IT-42" => "Liguria", "IT-25" => "Lombardia", "IT-57" => "Marche", "IT-67" => "Molise", "IT-21" => "Piemonte", "IT-75" => "Puglia", "IT-52" => "Toscana", "IT-55" => "Umbria", "IT-34" => "Veneto" }, "JM" => { "JM-13" => "Clarendon", "JM-09" => "Hanover", "JM-01" => "Kingston", "JM-12" => "Manchester", "JM-04" => "Portland", "JM-02" => "Saint Andrew", "JM-06" => "Saint Ann", "JM-14" => "Saint Catherine", "JM-11" => "Saint Elizabeth", "JM-08" => "Saint James", "JM-05" => "Saint Mary", "JM-03" => "Saint Thomas", "JM-07" => "Trelawny", "JM-10" => "Westmoreland" }, "JO" => { "JO-AJ" => "โ€˜Ajlลซn", "JO-AQ" => "Al โ€˜Aqabah", "JO-AM" => "Al โ€˜Aฬ…ลŸimah", "JO-BA" => "Al Balqฤโ€™", "JO-KA" => "Al Karak", "JO-MA" => "Al Mafraq", "JO-AT" => "Aลฃ ลขafฤซlah", "JO-AZ" => "Az Zarqฤโ€™", "JO-IR" => "Irbid", "JO-JA" => "Jarash", "JO-MN" => "Maโ€˜ฤn", "JO-MD" => "Mฤdabฤ" }, "JP" => { "JP-23" => "Aiti", "JP-05" => "Akita", "JP-02" => "Aomori", "JP-38" => "Ehime", "JP-21" => "Gihu", "JP-10" => "Gunma", "JP-34" => "Hirosima", "JP-01" => "Hokkaidรด", "JP-18" => "Hukui", "JP-40" => "Hukuoka", "JP-07" => "Hukusima", "JP-28" => "Hyรดgo", "JP-08" => "Ibaraki", "JP-17" => "Isikawa", "JP-03" => "Iwate", "JP-37" => "Kagawa", "JP-46" => "Kagosima", "JP-14" => "Kanagawa", "JP-39" => "Kรดti", "JP-43" => "Kumamoto", "JP-26" => "Kyรดto", "JP-24" => "Mie", "JP-04" => "Miyagi", "JP-45" => "Miyazaki", "JP-20" => "Nagano", "JP-42" => "Nagasaki", "JP-29" => "Nara", "JP-15" => "Niigata", "JP-44" => "ร”ita", "JP-33" => "Okayama", "JP-47" => "Okinawa", "JP-27" => "ร”saka", "JP-41" => "Saga", "JP-11" => "Saitama", "JP-25" => "Siga", "JP-32" => "Simane", "JP-22" => "Sizuoka", "JP-12" => "Tiba", "JP-09" => "Totigi", "JP-36" => "Tokusima", "JP-13" => "Tรดkyรด", "JP-31" => "Tottori", "JP-16" => "Toyama", "JP-30" => "Wakayama", "JP-06" => "Yamagata", "JP-35" => "Yamaguti", "JP-19" => "Yamanasi" }, "KE" => { "KE-01" => "Baringo", "KE-02" => "Bomet", "KE-03" => "Bungoma", "KE-04" => "Busia", "KE-05" => "Elgeyo/Marakwet", "KE-06" => "Embu", "KE-07" => "Garissa", "KE-08" => "Homa Bay", "KE-09" => "Isiolo", "KE-10" => "Kajiado", "KE-11" => "Kakamega", "KE-12" => "Kericho", "KE-13" => "Kiambu", "KE-14" => "Kilifi", "KE-15" => "Kirinyaga", "KE-16" => "Kisii", "KE-17" => "Kisumu", "KE-18" => "Kitui", "KE-19" => "Kwale", "KE-20" => "Laikipia", "KE-21" => "Lamu", "KE-22" => "Machakos", "KE-23" => "Makueni", "KE-24" => "Mandera", "KE-25" => "Marsabit", "KE-26" => "Meru", "KE-27" => "Migori", "KE-28" => "Mombasa", "KE-29" => "Murang'a", "KE-30" => "Nairobi City", "KE-31" => "Nakuru", "KE-32" => "Nandi", "KE-33" => "Narok", "KE-34" => "Nyamira", "KE-35" => "Nyandarua", "KE-36" => "Nyeri", "KE-37" => "Samburu", "KE-38" => "Siaya", "KE-39" => "Taita/Taveta", "KE-40" => "Tana River", "KE-41" => "Tharaka-Nithi", "KE-42" => "Trans Nzoia", "KE-43" => "Turkana", "KE-44" => "Uasin Gishu", "KE-45" => "Vihiga", "KE-46" => "Wajir", "KE-47" => "West Pokot" }, "KG" => { "KG-GB" => "Bishkek Shaary", "KG-GO" => "Osh Shaary", "KG-B" => "Batken", "KG-C" => "Chรผy", "KG-J" => "Jalal-Abad", "KG-N" => "Naryn", "KG-O" => "Osh", "KG-T" => "Talas", "KG-Y" => "Ysyk-Kรถl" }, "KH" => { "KH-12" => "Phnom Penh", "KH-2" => "Baat Dambang", "KH-1" => "Banteay Mean Choฤƒy", "KH-3" => "Kampong Chaam", "KH-4" => "Kampong Chhnang", "KH-5" => "Kampong Spueu", "KH-6" => "Kampong Thum", "KH-7" => "Kampot", "KH-8" => "Kandaal", "KH-9" => "Kaoh Kong", "KH-10" => "Kracheh", "KH-23" => "Kaeb", "KH-24" => "Pailin", "KH-18" => "Preah Sihanouk", "KH-11" => "Mondol Kiri", "KH-22" => "Otdar Mean Chey", "KH-15" => "Pousaat", "KH-13" => "Preah Vihear", "KH-14" => "Prey Veaeng", "KH-16" => "Rotanak Kiri", "KH-17" => "Siem Reab", "KH-19" => "Stueng Traeng", "KH-20" => "Svaay Rieng", "KH-21" => "Taakaev", "KH-25" => "Tbong Khmum" }, "KI" => { "KI-G" => "Gilbert Islands", "KI-L" => "Line Islands", "KI-P" => "Phoenix Islands" }, "KM" => { "KM-G" => "Grande Comore", "KM-A" => "Anjouan", "KM-M" => "Mohรฉli" }, "KN" => { "KN-K" => "Saint Kitts", "KN-N" => "Nevis" }, "KP" => { "KP-01" => "Pyongyang", "KP-13" => "Rason", "KP-14" => "Nampo", "KP-02" => "South Pyongan", "KP-03" => "North Pyongan", "KP-04" => "Chagang", "KP-05" => "South Hwanghae", "KP-06" => "North Hwanghae", "KP-07" => "Kangwon", "KP-08" => "South Hamgyong", "KP-09" => "North Hamgyong", "KP-10" => "Ryanggang" }, "KR" => { "KR-11" => "Seoul", "KR-26" => "Busan", "KR-27" => "Daegu", "KR-30" => "Daejeon", "KR-29" => "Gwangju", "KR-28" => "Incheon", "KR-31" => "Ulsan", "KR-43" => "North Chungcheong", "KR-44" => "South Chungcheong", "KR-42" => "Gangwon", "KR-41" => "Gyeonggi", "KR-47" => "North Gyeongsang", "KR-48" => "South Gyeongsang", "KR-45" => "North Jeolla", "KR-46" => "South Jeolla", "KR-49" => "Jeju", "KR-50" => "Sejong" }, "KW" => { "KW-AH" => "Al Aแธฉmadฤซ", "KW-FA" => "Al Farwฤnฤซyah", "KW-JA" => "Al Jahrฤโ€™", "KW-KU" => "Al โ€˜ฤ€ลŸimah", "KW-HA" => "แธจawallฤซ", "KW-MU" => "Mubฤrak al Kabฤซr" }, "KZ" => { "KZ-ALA" => "Almaty", "KZ-ALM" => "Almaty oblysy", "KZ-AKM" => "Aqmola oblysy", "KZ-AKT" => "Aqtรถbe oblysy", "KZ-ATY" => "Atyraลซ oblysy", "KZ-ZAP" => "Batys Qazaqstan oblysy", "KZ-MAN" => "Mangghystaลซ oblysy", "KZ-AST" => "Nur-Sultan", "KZ-PAV" => "Pavlodar oblysy", "KZ-KAR" => "Qaraghandy oblysy", "KZ-KUS" => "Qostanay oblysy", "KZ-KZY" => "Qyzylorda oblysy", "KZ-VOS" => "Shyghys Qazaqstan oblysy", "KZ-SHY" => "Shymkent", "KZ-SEV" => "Soltรผstik Qazaqstan oblysy", "KZ-YUZ" => "Tรผrkistan oblysy", "KZ-ZHA" => "Zhambyl oblysy" }, "LA" => { "LA-VT" => "Viangchan", "LA-AT" => "Attapu", "LA-BK" => "Bokรจo", "LA-BL" => "Bolikhamxai", "LA-CH" => "Champasak", "LA-HO" => "Houaphan", "LA-KH" => "Khammouan", "LA-LM" => "Louang Namtha", "LA-LP" => "Louangphabang", "LA-OU" => "Oudรดmxai", "LA-PH" => "Phรดngsali", "LA-SL" => "Salavan", "LA-SV" => "Savannakhรฉt", "LA-VI" => "Viangchan", "LA-XA" => "Xaignabouli", "LA-XE" => "Xรฉkong", "LA-XI" => "Xiangkhouang", "LA-XS" => "Xaisรดmboun" }, "LB" => { "LB-AK" => "Aakkรขr", "LB-BH" => "Baalbek-Hermel", "LB-BI" => "Bรฉqaa", "LB-BA" => "Beyrouth", "LB-AS" => "Liban-Nord", "LB-JA" => "Liban-Sud", "LB-JL" => "Mont-Liban", "LB-NA" => "Nabatรฎyรฉ" }, "LC" => { "LC-01" => "Anse la Raye", "LC-12" => "Canaries", "LC-02" => "Castries", "LC-03" => "Choiseul", "LC-05" => "Dennery", "LC-06" => "Gros Islet", "LC-07" => "Laborie", "LC-08" => "Micoud", "LC-10" => "Soufriรจre", "LC-11" => "Vieux Fort" }, "LI" => { "LI-01" => "Balzers", "LI-02" => "Eschen", "LI-03" => "Gamprin", "LI-04" => "Mauren", "LI-05" => "Planken", "LI-06" => "Ruggell", "LI-07" => "Schaan", "LI-08" => "Schellenberg", "LI-09" => "Triesen", "LI-10" => "Triesenberg", "LI-11" => "Vaduz" }, "LK" => { "LK-1" => "Western Province", "LK-2" => "Central Province", "LK-3" => "Southern Province", "LK-4" => "Northern Province", "LK-5" => "Eastern Province", "LK-6" => "North Western Province", "LK-7" => "North Central Province", "LK-8" => "Uva Province", "LK-9" => "Sabaragamuwa Province" }, "LR" => { "LR-BM" => "Bomi", "LR-BG" => "Bong", "LR-GP" => "Gbarpolu", "LR-GB" => "Grand Bassa", "LR-CM" => "Grand Cape Mount", "LR-GG" => "Grand Gedeh", "LR-GK" => "Grand Kru", "LR-LO" => "Lofa", "LR-MG" => "Margibi", "LR-MY" => "Maryland", "LR-MO" => "Montserrado", "LR-NI" => "Nimba", "LR-RI" => "River Cess(local variant is Rivercess)", "LR-RG" => "River Gee", "LR-SI" => "Sinoe" }, "LS" => { "LS-D" => "Berea", "LS-B" => "Botha-Bothe", "LS-C" => "Leribe", "LS-E" => "Mafeteng", "LS-A" => "Maseru", "LS-F" => "Mohale's Hoek", "LS-J" => "Mokhotlong", "LS-H" => "Qacha's Nek", "LS-G" => "Quthing", "LS-K" => "Thaba-Tseka" }, "LT" => { "LT-AL" => "Alytaus apskritis", "LT-KU" => "Kauno apskritis", "LT-KL" => "Klaipฤ—dos apskritis", "LT-MR" => "Marijampolฤ—s apskritis", "LT-PN" => "Panevฤ—ลพio apskritis", "LT-SA" => "ล iauliลณ apskritis", "LT-TA" => "Tauragฤ—s apskritis", "LT-TE" => "Telลกiลณ apskritis", "LT-UT" => "Utenos apskritis", "LT-VL" => "Vilniaus apskritis" }, "LU" => { "LU-CA" => "Capellen", "LU-CL" => "Clervaux", "LU-DI" => "Diekirch", "LU-EC" => "Echternach", "LU-ES" => "Esch-sur-Alzette", "LU-GR" => "Grevenmacher", "LU-LU" => "Luxembourg", "LU-ME" => "Mersch", "LU-RD" => "Redange", "LU-RM" => "Remich", "LU-VD" => "Vianden", "LU-WI" => "Wiltz" }, "LV" => { "LV-001" => "Aglonas novads", "LV-002" => "Aizkraukles novads", "LV-003" => "Aizputes novads", "LV-004" => "Aknฤซstes novads", "LV-005" => "Alojas novads", "LV-006" => "Alsungas novads", "LV-007" => "Alลซksnes novads", "LV-008" => "Amatas novads", "LV-009" => "Apes novads", "LV-010" => "Auces novads", "LV-011" => "ฤ€daลพu novads", "LV-012" => "Babฤซtes novads", "LV-013" => "Baldones novads", "LV-014" => "Baltinavas novads", "LV-015" => "Balvu novads", "LV-016" => "Bauskas novads", "LV-017" => "Beverฤซnas novads", "LV-018" => "Brocฤ“nu novads", "LV-019" => "Burtnieku novads", "LV-020" => "Carnikavas novads", "LV-021" => "Cesvaines novads", "LV-022" => "Cฤ“su novads", "LV-023" => "Ciblas novads", "LV-024" => "Dagdas novads", "LV-025" => "Daugavpils novads", "LV-026" => "Dobeles novads", "LV-027" => "Dundagas novads", "LV-028" => "Durbes novads", "LV-029" => "Engures novads", "LV-030" => "ฤ’rgฤผu novads", "LV-031" => "Garkalnes novads", "LV-032" => "Grobiล†as novads", "LV-033" => "Gulbenes novads", "LV-034" => "Iecavas novads", "LV-035" => "Ikลกฤทiles novads", "LV-036" => "Ilลซkstes novads", "LV-037" => "Inฤukalna novads", "LV-038" => "Jaunjelgavas novads", "LV-039" => "Jaunpiebalgas novads", "LV-040" => "Jaunpils novads", "LV-041" => "Jelgavas novads", "LV-042" => "Jฤ“kabpils novads", "LV-043" => "Kandavas novads", "LV-044" => "Kฤrsavas novads", "LV-045" => "Kocฤ“nu novads", "LV-046" => "Kokneses novads", "LV-047" => "Krฤslavas novads", "LV-048" => "Krimuldas novads", "LV-049" => "Krustpils novads", "LV-050" => "Kuldฤซgas novads", "LV-051" => "ฤถeguma novads", "LV-052" => "ฤถekavas novads", "LV-053" => "Lielvฤrdes novads", "LV-054" => "Limbaลพu novads", "LV-055" => "Lฤซgatnes novads", "LV-056" => "Lฤซvฤnu novads", "LV-057" => "Lubฤnas novads", "LV-058" => "Ludzas novads", "LV-059" => "Madonas novads", "LV-060" => "Mazsalacas novads", "LV-061" => "Mฤlpils novads", "LV-062" => "Mฤrupes novads", "LV-063" => "Mฤ“rsraga novads", "LV-064" => "Naukลกฤ“nu novads", "LV-065" => "Neretas novads", "LV-066" => "Nฤซcas novads", "LV-067" => "Ogres novads", "LV-068" => "Olaines novads", "LV-069" => "Ozolnieku novads", "LV-070" => "Pฤrgaujas novads", "LV-071" => "Pฤvilostas novads", "LV-072" => "Pฤผaviล†u novads", "LV-073" => "Preiฤผu novads", "LV-074" => "Priekules novads", "LV-075" => "Priekuฤผu novads", "LV-076" => "Raunas novads", "LV-077" => "Rฤ“zeknes novads", "LV-078" => "Riebiล†u novads", "LV-079" => "Rojas novads", "LV-080" => "Ropaลพu novads", "LV-081" => "Rucavas novads", "LV-082" => "Rugฤju novads", "LV-083" => "Rundฤles novads", "LV-084" => "Rลซjienas novads", "LV-085" => "Salas novads", "LV-086" => "Salacgrฤซvas novads", "LV-087" => "Salaspils novads", "LV-088" => "Saldus novads", "LV-089" => "Saulkrastu novads", "LV-090" => "Sฤ“jas novads", "LV-091" => "Siguldas novads", "LV-092" => "Skrฤซveru novads", "LV-093" => "Skrundas novads", "LV-094" => "Smiltenes novads", "LV-095" => "Stopiล†u novads", "LV-096" => "Strenฤu novads", "LV-097" => "Talsu novads", "LV-098" => "Tฤ“rvetes novads", "LV-099" => "Tukuma novads", "LV-100" => "Vaiล†odes novads", "LV-101" => "Valkas novads", "LV-102" => "Varakฤผฤnu novads", "LV-103" => "Vฤrkavas novads", "LV-104" => "Vecpiebalgas novads", "LV-105" => "Vecumnieku novads", "LV-106" => "Ventspils novads", "LV-107" => "Viesฤซtes novads", "LV-108" => "Viฤผakas novads", "LV-109" => "Viฤผฤnu novads", "LV-110" => "Zilupes novads", "LV-DGV" => "Daugavpils", "LV-JEL" => "Jelgava", "LV-JKB" => "Jฤ“kabpils", "LV-JUR" => "Jลซrmala", "LV-LPX" => "Liepฤja", "LV-REZ" => "Rฤ“zekne", "LV-RIX" => "Rฤซga", "LV-VMR" => "Valmiera", "LV-VEN" => "Ventspils" }, "LY" => { "LY-BU" => "Al Buลฃnฤn", "LY-JA" => "Al Jabal al Akhแธ‘ar", "LY-JG" => "Al Jabal al Gharbฤซ", "LY-JI" => "Al Jafฤrah", "LY-JU" => "Al Jufrah", "LY-KF" => "Al Kufrah", "LY-MJ" => "Al Marj", "LY-MB" => "Al Marqab", "LY-WA" => "Al Wฤแธฉฤt", "LY-NQ" => "An Nuqฤลฃ al Khams", "LY-ZA" => "Az Zฤwiyah", "LY-BA" => "Banghฤzฤซ", "LY-DR" => "Darnah", "LY-GT" => "Ghฤt", "LY-MI" => "MiลŸrฤtah", "LY-MQ" => "Murzuq", "LY-NL" => "Nฤlลซt", "LY-SB" => "Sabhฤ", "LY-SR" => "Surt", "LY-TB" => "ลขarฤbulus", "LY-WD" => "Wฤdฤซ al แธจayฤt", "LY-WS" => "Wฤdฤซ ash Shฤลฃiโ€™" }, "MA" => { "MA-05" => "Bรฉni Mellal-Khรฉnifra", "MA-06" => "Casablanca-Settat", "MA-12" => "Dakhla-Oued Ed-Dahab (EH)", "MA-08" => "Drรขa-Tafilalet", "MA-03" => "Fรจs-Meknรจs", "MA-10" => "Guelmim-Oued Noun (EH-partial)", "MA-11" => "Laรขyoune-Sakia El Hamra (EH-partial)", "MA-07" => "Marrakech-Safi", "MA-02" => "L'Oriental", "MA-04" => "Rabat-Salรฉ-Kรฉnitra", "MA-09" => "Souss-Massa", "MA-01" => "Tanger-Tรฉtouan-Al Hoceรฏma" }, "MC" => { "MC-FO" => "Fontvieille", "MC-JE" => "Jardin Exotique", "MC-CL" => "La Colle", "MC-CO" => "La Condamine", "MC-GA" => "La Gare", "MC-SO" => "La Source", "MC-LA" => "Larvotto", "MC-MA" => "Malbousquet", "MC-MO" => "Monaco-Ville", "MC-MG" => "Moneghetti", "MC-MC" => "Monte-Carlo", "MC-MU" => "Moulins", "MC-PH" => "Port-Hercule", "MC-SR" => "Saint-Roman", "MC-SD" => "Sainte-Dรฉvote", "MC-SP" => "Spรฉlugues", "MC-VR" => "Vallon de la Rousse" }, "MD" => { "MD-GA" => "Gฤƒgฤƒuzia, Unitatea teritorialฤƒ autonomฤƒ (UTAG)", "MD-BA" => "Bฤƒlศ›i", "MD-BD" => "Bender [Tighina]", "MD-CU" => "Chiศ™inฤƒu", "MD-AN" => "Anenii Noi", "MD-BS" => "Basarabeasca", "MD-BR" => "Briceni", "MD-CA" => "Cahul", "MD-CT" => "Cantemir", "MD-CL" => "Cฤƒlฤƒraศ™i", "MD-CS" => "Cฤƒuศ™eni", "MD-CM" => "Cimiศ™lia", "MD-CR" => "Criuleni", "MD-DO" => "Donduศ™eni", "MD-DR" => "Drochia", "MD-DU" => "Dubฤƒsari", "MD-ED" => "Edineศ›", "MD-FA" => "Fฤƒleศ™ti", "MD-FL" => "Floreศ™ti", "MD-GL" => "Glodeni", "MD-HI" => "Hรฎnceศ™ti", "MD-IA" => "Ialoveni", "MD-LE" => "Leova", "MD-NI" => "Nisporeni", "MD-OC" => "Ocniศ›a", "MD-OR" => "Orhei", "MD-RE" => "Rezina", "MD-RI" => "Rรฎศ™cani", "MD-SI" => "Sรฎngerei", "MD-SO" => "Soroca", "MD-ST" => "Strฤƒศ™eni", "MD-SD" => "ศ˜oldฤƒneศ™ti", "MD-SV" => "ศ˜tefan Vodฤƒ", "MD-TA" => "Taraclia", "MD-TE" => "Teleneศ™ti", "MD-UN" => "Ungheni", "MD-SN" => "Stรฎnga Nistrului, unitatea teritorialฤƒ din" }, "ME" => { "ME-01" => "Andrijevica", "ME-02" => "Bar", "ME-03" => "Berane", "ME-04" => "Bijelo Polje", "ME-05" => "Budva", "ME-06" => "Cetinje", "ME-07" => "Danilovgrad", "ME-08" => "Herceg-Novi", "ME-09" => "Kolaลกin", "ME-10" => "Kotor", "ME-11" => "Mojkovac", "ME-12" => "Nikลกiฤ‡", "ME-13" => "Plav", "ME-14" => "Pljevlja", "ME-15" => "Pluลพine", "ME-16" => "Podgorica", "ME-17" => "Roลพaje", "ME-18" => "ล avnik", "ME-19" => "Tivat", "ME-20" => "Ulcinj", "ME-21" => "ลฝabljak", "ME-22" => "Gusinje", "ME-23" => "Petnjica", "ME-24" => "Tuzi" }, "MG" => { "MG-T" => "Antananarivo", "MG-D" => "Antsiranana", "MG-F" => "Fianarantsoa", "MG-M" => "Mahajanga", "MG-A" => "Toamasina", "MG-U" => "Toliara" }, "MH" => { "MH-L" => "Ralik chain", "MH-T" => "Ratak chain" }, "MK" => { "MK-801" => "Aerodrom", "MK-802" => "Araฤinovo", "MK-201" => "Berovo", "MK-501" => "Bitola", "MK-401" => "Bogdanci", "MK-601" => "Bogovinje", "MK-402" => "Bosilovo", "MK-602" => "Brvenica", "MK-803" => "Butel", "MK-814" => "Centar", "MK-313" => "Centar ลฝupa", "MK-815" => "ฤŒair", "MK-109" => "ฤŒaลกka", "MK-210" => "ฤŒeลกinovo-Obleลกevo", "MK-816" => "ฤŒuฤer-Sandevo", "MK-303" => "Debar", "MK-304" => "Debarca", "MK-203" => "Delฤevo", "MK-502" => "Demir Hisar", "MK-103" => "Demir Kapija", "MK-406" => "Dojran", "MK-503" => "Dolneni", "MK-804" => "Gazi Baba", "MK-405" => "Gevgelija", "MK-805" => "Gjorฤe Petrov", "MK-604" => "Gostivar", "MK-102" => "Gradsko", "MK-807" => "Ilinden", "MK-606" => "Jegunovce", "MK-205" => "Karbinci", "MK-808" => "Karpoลก", "MK-104" => "Kavadarci", "MK-307" => "Kiฤevo", "MK-809" => "Kisela Voda", "MK-206" => "Koฤani", "MK-407" => "Konฤe", "MK-701" => "Kratovo", "MK-702" => "Kriva Palanka", "MK-504" => "Krivogaลกtani", "MK-505" => "Kruลกevo", "MK-703" => "Kumanovo", "MK-704" => "Lipkovo", "MK-105" => "Lozovo", "MK-207" => "Makedonska Kamenica", "MK-308" => "Makedonski Brod", "MK-607" => "Mavrovo i Rostuลกe", "MK-506" => "Mogila", "MK-106" => "Negotino", "MK-507" => "Novaci", "MK-408" => "Novo Selo", "MK-310" => "Ohrid", "MK-208" => "Pehฤevo", "MK-810" => "Petrovec", "MK-311" => "Plasnica", "MK-508" => "Prilep", "MK-209" => "Probiลกtip", "MK-409" => "Radoviลก", "MK-705" => "Rankovce", "MK-509" => "Resen", "MK-107" => "Rosoman", "MK-811" => "Saraj", "MK-812" => "Sopiลกte", "MK-706" => "Staro Nagoriฤane", "MK-312" => "Struga", "MK-410" => "Strumica", "MK-813" => "Studeniฤani", "MK-108" => "Sveti Nikole", "MK-211" => "ล tip", "MK-817" => "ล uto Orizari", "MK-608" => "Tearce", "MK-609" => "Tetovo", "MK-403" => "Valandovo", "MK-404" => "Vasilevo", "MK-101" => "Veles", "MK-301" => "Vevฤani", "MK-202" => "Vinica", "MK-603" => "Vrapฤiลกte", "MK-806" => "Zelenikovo", "MK-204" => "Zrnovci", "MK-605" => "ลฝelino" }, "ML" => { "ML-BKO" => "Bamako", "ML-7" => "Gao", "ML-1" => "Kayes", "ML-8" => "Kidal", "ML-2" => "Koulikoro", "ML-9" => "Mรฉnaka", "ML-5" => "Mopti", "ML-4" => "Sรฉgou", "ML-3" => "Sikasso", "ML-10" => "Taoudรฉnit(local variants are Taoudenni, Taoudรฉni)", "ML-6" => "Tombouctou" }, "MM" => { "MM-07" => "Ayeyarwady", "MM-02" => "Bago", "MM-03" => "Magway", "MM-04" => "Mandalay", "MM-01" => "Sagaing", "MM-05" => "Tanintharyi", "MM-06" => "Yangon", "MM-14" => "Chin", "MM-11" => "Kachin", "MM-12" => "Kayah", "MM-13" => "Kayin", "MM-15" => "Mon", "MM-16" => "Rakhine", "MM-17" => "Shan", "MM-18" => "Nay Pyi Taw" }, "MN" => { "MN-1" => "Ulaanbaatar", "MN-073" => "Arhangay", "MN-069" => "Bayanhongor", "MN-071" => "Bayan-ร–lgiy", "MN-067" => "Bulgan", "MN-037" => "Darhan uul", "MN-061" => "Dornod", "MN-063" => "Dornogovฤญ", "MN-059" => "Dundgovฤญ", "MN-057" => "Dzavhan", "MN-065" => "Govฤญ-Altay", "MN-064" => "Govฤญ-Sรผmber", "MN-039" => "Hentiy", "MN-043" => "Hovd", "MN-041" => "Hรถvsgรถl", "MN-053" => "ร–mnรถgovฤญ", "MN-035" => "Orhon", "MN-055" => "ร–vรถrhangay", "MN-049" => "Selenge", "MN-051" => "Sรผhbaatar", "MN-047" => "Tรถv", "MN-046" => "Uvs" }, "MR" => { "MR-07" => "Adrar", "MR-03" => "Assaba", "MR-05" => "Brakna", "MR-08" => "Dakhlet Nouรขdhibou", "MR-04" => "Gorgol", "MR-10" => "Guidimaka", "MR-01" => "Hodh ech Chargui", "MR-02" => "Hodh el Gharbi", "MR-12" => "Inchiri", "MR-09" => "Tagant", "MR-11" => "Tiris Zemmour", "MR-06" => "Trarza" }, "MT" => { "MT-01" => "Attard", "MT-02" => "Balzan", "MT-03" => "Birgu", "MT-04" => "Birkirkara", "MT-05" => "Birลผebbuฤกa", "MT-06" => "Bormla", "MT-07" => "Dingli", "MT-08" => "Fgura", "MT-09" => "Floriana", "MT-10" => "Fontana", "MT-11" => "Gudja", "MT-12" => "Gลผira", "MT-13" => "Gฤงajnsielem", "MT-14" => "Gฤงarb", "MT-15" => "Gฤงargฤงur", "MT-16" => "Gฤงasri", "MT-17" => "Gฤงaxaq", "MT-18" => "ฤฆamrun", "MT-19" => "Iklin", "MT-20" => "Isla", "MT-21" => "Kalkara", "MT-22" => "Kerฤ‹em", "MT-23" => "Kirkop", "MT-24" => "Lija", "MT-25" => "Luqa", "MT-26" => "Marsa", "MT-27" => "Marsaskala", "MT-28" => "Marsaxlokk", "MT-29" => "Mdina", "MT-30" => "Mellieฤงa", "MT-31" => "Mฤกarr", "MT-32" => "Mosta", "MT-33" => "Mqabba", "MT-34" => "Msida", "MT-35" => "Mtarfa", "MT-36" => "Munxar", "MT-37" => "Nadur", "MT-38" => "Naxxar", "MT-39" => "Paola", "MT-40" => "Pembroke", "MT-41" => "Pietร ", "MT-42" => "Qala", "MT-43" => "Qormi", "MT-44" => "Qrendi", "MT-45" => "Rabat Gozo", "MT-46" => "Rabat Malta", "MT-47" => "Safi", "MT-48" => "Saint Julian's", "MT-49" => "Saint John", "MT-50" => "Saint Lawrence", "MT-51" => "Saint Paul's Bay", "MT-52" => "Sannat", "MT-53" => "Saint Lucia's", "MT-54" => "Santa Venera", "MT-55" => "Siฤกฤกiewi", "MT-56" => "Sliema", "MT-57" => "Swieqi", "MT-58" => "Ta' Xbiex", "MT-59" => "Tarxien", "MT-60" => "Valletta", "MT-61" => "Xagฤงra", "MT-62" => "Xewkija", "MT-63" => "Xgฤงajra", "MT-64" => "ลปabbar", "MT-65" => "ลปebbuฤก Gozo", "MT-66" => "ลปebbuฤก Malta", "MT-67" => "ลปejtun", "MT-68" => "ลปurrieq" }, "MU" => { "MU-AG" => "Agalega Islands", "MU-CC" => "Cargados Carajos Shoals(local variant is Saint Brandon Islands)", "MU-RO" => "Rodrigues Island", "MU-BL" => "Black River", "MU-FL" => "Flacq", "MU-GP" => "Grand Port", "MU-MO" => "Moka", "MU-PA" => "Pamplemousses", "MU-PW" => "Plaines Wilhems", "MU-PL" => "Port Louis", "MU-RR" => "Riviรจre du Rempart", "MU-SA" => "Savanne" }, "MV" => { "MV-01" => "Addu City", "MV-MLE" => "Male" }, "MW" => { "MW-C" => "Central Region", "MW-N" => "Northern Region", "MW-S" => "Southern Region" }, "MX" => { "MX-CMX" => "Ciudad de Mรฉxico", "MX-AGU" => "Aguascalientes", "MX-BCN" => "Baja California", "MX-BCS" => "Baja California Sur", "MX-CAM" => "Campeche", "MX-COA" => "Coahuila de Zaragoza", "MX-COL" => "Colima", "MX-CHP" => "Chiapas", "MX-CHH" => "Chihuahua", "MX-DUR" => "Durango", "MX-GUA" => "Guanajuato", "MX-GRO" => "Guerrero", "MX-HID" => "Hidalgo", "MX-JAL" => "Jalisco", "MX-MEX" => "Mรฉxico", "MX-MIC" => "Michoacรกn de Ocampo", "MX-MOR" => "Morelos", "MX-NAY" => "Nayarit", "MX-NLE" => "Nuevo Leรณn", "MX-OAX" => "Oaxaca", "MX-PUE" => "Puebla", "MX-QUE" => "Querรฉtaro", "MX-ROO" => "Quintana Roo", "MX-SLP" => "San Luis Potosรญ", "MX-SIN" => "Sinaloa", "MX-SON" => "Sonora", "MX-TAB" => "Tabasco", "MX-TAM" => "Tamaulipas", "MX-TLA" => "Tlaxcala", "MX-VER" => "Veracruz de Ignacio de la Llave", "MX-YUC" => "Yucatรกn", "MX-ZAC" => "Zacatecas" }, "MY" => { "MY-14" => "Wilayah Persekutuan Kuala Lumpur", "MY-15" => "Wilayah Persekutuan Labuan", "MY-16" => "Wilayah Persekutuan Putrajaya", "MY-01" => "Johor", "MY-02" => "Kedah", "MY-03" => "Kelantan", "MY-04" => "Melaka", "MY-05" => "Negeri Sembilan", "MY-06" => "Pahang", "MY-08" => "Perak", "MY-09" => "Perlis", "MY-07" => "Pulau Pinang", "MY-12" => "Sabah", "MY-13" => "Sarawak", "MY-10" => "Selangor", "MY-11" => "Terengganu" }, "MZ" => { "MZ-MPM" => "Maputo", "MZ-P" => "Cabo Delgado", "MZ-G" => "Gaza", "MZ-I" => "Inhambane", "MZ-B" => "Manica", "MZ-L" => "Maputo", "MZ-N" => "Nampula", "MZ-A" => "Niassa", "MZ-S" => "Sofala", "MZ-T" => "Tete", "MZ-Q" => "Zambรฉzia" }, "NA" => { "NA-ER" => "Erongo", "NA-HA" => "Hardap", "NA-KA" => "//Karas(local variants are Karas and !Karas)", "NA-KE" => "Kavango East", "NA-KW" => "Kavango West", "NA-KH" => "Khomas", "NA-KU" => "Kunene", "NA-OW" => "Ohangwena", "NA-OH" => "Omaheke", "NA-OS" => "Omusati", "NA-ON" => "Oshana", "NA-OT" => "Oshikoto", "NA-OD" => "Otjozondjupa", "NA-CA" => "Zambezi" }, "NE" => { "NE-8" => "Niamey", "NE-1" => "Agadez", "NE-2" => "Diffa", "NE-3" => "Dosso", "NE-4" => "Maradi", "NE-5" => "Tahoua", "NE-6" => "Tillabรฉri", "NE-7" => "Zinder" }, "NG" => { "NG-FC" => "Abuja Federal Capital Territory", "NG-AB" => "Abia", "NG-AD" => "Adamawa", "NG-AK" => "Akwa Ibom", "NG-AN" => "Anambra", "NG-BA" => "Bauchi", "NG-BY" => "Bayelsa", "NG-BE" => "Benue", "NG-BO" => "Borno", "NG-CR" => "Cross River", "NG-DE" => "Delta", "NG-EB" => "Ebonyi", "NG-ED" => "Edo", "NG-EK" => "Ekiti", "NG-EN" => "Enugu", "NG-GO" => "Gombe", "NG-IM" => "Imo", "NG-JI" => "Jigawa", "NG-KD" => "Kaduna", "NG-KN" => "Kano", "NG-KT" => "Katsina", "NG-KE" => "Kebbi", "NG-KO" => "Kogi", "NG-KW" => "Kwara", "NG-LA" => "Lagos", "NG-NA" => "Nasarawa", "NG-NI" => "Niger", "NG-OG" => "Ogun", "NG-ON" => "Ondo", "NG-OS" => "Osun", "NG-OY" => "Oyo", "NG-PL" => "Plateau", "NG-RI" => "Rivers", "NG-SO" => "Sokoto", "NG-TA" => "Taraba", "NG-YO" => "Yobe", "NG-ZA" => "Zamfara" }, "NI" => { "NI-BO" => "Boaco", "NI-CA" => "Carazo", "NI-CI" => "Chinandega", "NI-CO" => "Chontales", "NI-ES" => "Estelรญ", "NI-GR" => "Granada", "NI-JI" => "Jinotega", "NI-LE" => "Leรณn", "NI-MD" => "Madriz", "NI-MN" => "Managua", "NI-MS" => "Masaya", "NI-MT" => "Matagalpa", "NI-NS" => "Nueva Segovia", "NI-SJ" => "Rรญo San Juan", "NI-RI" => "Rivas", "NI-AN" => "Costa Caribe Norte", "NI-AS" => "Costa Caribe Sur" }, "NL" => { "NL-DR" => "Drenthe", "NL-FL" => "Flevoland", "NL-FR" => "Fryslรขn (fy)", "NL-GE" => "Gelderland", "NL-GR" => "Groningen", "NL-LI" => "Limburg", "NL-NB" => "Noord-Brabant", "NL-NH" => "Noord-Holland", "NL-OV" => "Overijssel", "NL-UT" => "Utrecht", "NL-ZE" => "Zeeland", "NL-ZH" => "Zuid-Holland" }, "NO" => { "NO-42" => "Agder", "NO-34" => "Innlandet", "NO-15" => "Mรธre og Romsdal", "NO-18" => "Nordland", "NO-03" => "Oslo", "NO-11" => "Rogaland", "NO-54" => "Troms og Finnmark / Romsa ja Finnmรกrku (se) / Tromssan ja Finmarkun (-)", "NO-50" => "Trรธndelag / Trรถรถndelage (-)", "NO-38" => "Vestfold og Telemark", "NO-46" => "Vestland", "NO-30" => "Viken", "NO-22" => "Jan Mayen", "NO-21" => "Svalbard" }, "NP" => { "NP-1" => "Madhyamanchal", "NP-2" => "Madhya Pashchimanchal", "NP-3" => "Pashchimanchal", "NP-4" => "Purwanchal", "NP-5" => "Sudur Pashchimanchal" }, "NR" => { "NR-01" => "Aiwo", "NR-02" => "Anabar", "NR-03" => "Anetan", "NR-04" => "Anibare", "NR-05" => "Baitsi (local variant is Baiti)", "NR-06" => "Boe", "NR-07" => "Buada", "NR-08" => "Denigomodu", "NR-09" => "Ewa", "NR-10" => "Ijuw", "NR-11" => "Meneng", "NR-12" => "Nibok", "NR-13" => "Uaboe", "NR-14" => "Yaren" }, "NZ" => { "NZ-AUK" => "Auckland", "NZ-BOP" => "Bay of Plenty", "NZ-CAN" => "Canterbury", "NZ-GIS" => "Gisborne", "NZ-HKB" => "Hawke's Bay", "NZ-MBH" => "Marlborough", "NZ-MWT" => "Manawatu-Wanganui", "NZ-NSN" => "Nelson", "NZ-NTL" => "Northland", "NZ-OTA" => "Otago", "NZ-STL" => "Southland", "NZ-TAS" => "Tasman", "NZ-TKI" => "Taranaki", "NZ-WGN" => "Wellington", "NZ-WTC" => "West Coast", "NZ-CIT" => "Chatham Islands Territory" }, "OM" => { "OM-DA" => "Ad Dฤkhilฤซyah", "OM-BS" => "Shamฤl al Bฤลฃinah", "OM-BJ" => "Janลซb al Bฤลฃinah", "OM-WU" => "Al Wusลฃรก", "OM-SS" => "Shamฤl ash Sharqฤซyah", "OM-SJ" => "Janลซb ash Sharqฤซyah", "OM-ZA" => "Azฬง Zฬงฤhirah", "OM-BU" => "Al Buraymฤซ", "OM-MA" => "Masqaลฃ", "OM-MU" => "Musandam", "OM-ZU" => "Zฬงufฤr" }, "PA" => { "PA-1" => "Bocas del Toro", "PA-4" => "Chiriquรญ", "PA-2" => "Coclรฉ", "PA-3" => "Colรณn", "PA-5" => "Dariรฉn", "PA-EM" => "Emberรก", "PA-KY" => "Guna Yala(local variant is Kuna Yala)", "PA-6" => "Herrera", "PA-7" => "Los Santos", "PA-NB" => "Ngรถbe-Buglรฉ[note 1]", "PA-8" => "Panamรก", "PA-10" => "Panamรก Oeste", "PA-9" => "Veraguas" }, "PE" => { "PE-LMA" => "Municipalidad Metropolitana de Lima", "PE-AMA" => "Amazonas", "PE-ANC" => "Ancash", "PE-APU" => "Apurรญmac", "PE-ARE" => "Arequipa", "PE-AYA" => "Ayacucho", "PE-CAJ" => "Cajamarca", "PE-CUS" => "Cusco(local variant is Cuzco)", "PE-CAL" => "El Callao", "PE-HUV" => "Huancavelica", "PE-HUC" => "Huรกnuco", "PE-ICA" => "Ica", "PE-JUN" => "Junรญn", "PE-LAL" => "La Libertad", "PE-LAM" => "Lambayeque", "PE-LIM" => "Lima", "PE-LOR" => "Loreto", "PE-MDD" => "Madre de Dios", "PE-MOQ" => "Moquegua", "PE-PAS" => "Pasco", "PE-PIU" => "Piura", "PE-PUN" => "Puno", "PE-SAM" => "San Martรญn", "PE-TAC" => "Tacna", "PE-TUM" => "Tumbes", "PE-UCA" => "Ucayali" }, "PG" => { "PG-NCD" => "National Capital District (Port Moresby)", "PG-CPM" => "Central", "PG-CPK" => "Chimbu", "PG-EHG" => "Eastern Highlands", "PG-EBR" => "East New Britain", "PG-ESW" => "East Sepik", "PG-EPW" => "Enga", "PG-GPK" => "Gulf", "PG-HLA" => "Hela", "PG-JWK" => "Jiwaka", "PG-MPM" => "Madang", "PG-MRL" => "Manus", "PG-MBA" => "Milne Bay", "PG-MPL" => "Morobe", "PG-NIK" => "New Ireland", "PG-NPP" => "Northern", "PG-SAN" => "West Sepik", "PG-SHM" => "Southern Highlands", "PG-WPD" => "Western", "PG-WHM" => "Western Highlands", "PG-WBK" => "West New Britain", "PG-NSB" => "Bougainville" }, "PH" => { "PH-14" => "Autonomous Region in Muslim Mindanao[b]", "PH-05" => "Bicol", "PH-02" => "Cagayan Valley", "PH-40" => "Calabarzon", "PH-13" => "Caraga", "PH-03" => "Central Luzon", "PH-07" => "Central Visayas", "PH-15" => "Cordillera Administrative Region", "PH-11" => "Davao", "PH-08" => "Eastern Visayas", "PH-01" => "Ilocos", "PH-41" => "Mimaropa", "PH-00" => "National Capital Region", "PH-10" => "Northern Mindanao", "PH-12" => "Soccsksargen", "PH-06" => "Western Visayas", "PH-09" => "Zamboanga Peninsula" }, "PK" => { "PK-IS" => "Islamabad", "PK-BA" => "Balochistan", "PK-KP" => "Khyber Pakhtunkhwa", "PK-PB" => "Punjab", "PK-SD" => "Sindh", "PK-JK" => "Azad Jammu and Kashmir(local variant is AJ&K)", "PK-GB" => "Gilgit-Baltistan" }, "PL" => { "PL-02" => "Dolnoล›lฤ…skie", "PL-04" => "Kujawsko-pomorskie", "PL-06" => "Lubelskie", "PL-08" => "Lubuskie", "PL-10" => "ลรณdzkie", "PL-12" => "Maล‚opolskie", "PL-14" => "Mazowieckie", "PL-16" => "Opolskie", "PL-18" => "Podkarpackie", "PL-20" => "Podlaskie", "PL-22" => "Pomorskie", "PL-24" => "ลšlฤ…skie", "PL-26" => "ลšwiฤ™tokrzyskie", "PL-28" => "Warmiล„sko-mazurskie", "PL-30" => "Wielkopolskie", "PL-32" => "Zachodniopomorskie" }, "PS" => { "PS-BTH" => "Bethlehem", "PS-DEB" => "Deir El Balah", "PS-GZA" => "Gaza", "PS-HBN" => "Hebron", "PS-JEN" => "Jenin", "PS-JRH" => "Jericho and Al Aghwar", "PS-JEM" => "Jerusalem", "PS-KYS" => "Khan Yunis", "PS-NBS" => "Nablus", "PS-NGZ" => "North Gaza", "PS-QQA" => "Qalqilya", "PS-RFH" => "Rafah", "PS-RBH" => "Ramallah", "PS-SLT" => "Salfit", "PS-TBS" => "Tubas", "PS-TKM" => "Tulkarm" }, "PT" => { "PT-01" => "Aveiro", "PT-02" => "Beja", "PT-03" => "Braga", "PT-04" => "Braganรงa", "PT-05" => "Castelo Branco", "PT-06" => "Coimbra", "PT-07" => "ร‰vora", "PT-08" => "Faro", "PT-09" => "Guarda", "PT-10" => "Leiria", "PT-11" => "Lisboa", "PT-12" => "Portalegre", "PT-13" => "Porto", "PT-14" => "Santarรฉm", "PT-15" => "Setรบbal", "PT-16" => "Viana do Castelo", "PT-17" => "Vila Real", "PT-18" => "Viseu", "PT-20" => "Regiรฃo Autรณnoma dos Aรงores", "PT-30" => "Regiรฃo Autรณnoma da Madeira" }, "PW" => { "PW-002" => "[[{{{alias}}}|Aimeliik]]", "PW-004" => "Airai", "PW-010" => "[[{{{alias}}}|Angaur]]", "PW-050" => "Hatohobei", "PW-100" => "Kayangel", "PW-150" => "Koror", "PW-212" => "Melekeok", "PW-214" => "Ngaraard", "PW-218" => "Ngarchelong", "PW-222" => "Ngardmau", "PW-224" => "Ngatpang", "PW-226" => "Ngchesar", "PW-227" => "Ngeremlengui", "PW-228" => "Ngiwal", "PW-350" => "Peleliu", "PW-370" => "Sonsorol" }, "PY" => { "PY-ASU" => "Asunciรณn", "PY-16" => "Alto Paraguay", "PY-10" => "Alto Paranรก", "PY-13" => "Amambay", "PY-19" => "Boquerรณn", "PY-5" => "Caaguazรบ", "PY-6" => "Caazapรก", "PY-14" => "Canindeyรบ", "PY-11" => "Central", "PY-1" => "Concepciรณn", "PY-3" => "Cordillera", "PY-4" => "Guairรก", "PY-7" => "Itapรบa", "PY-8" => "Misiones", "PY-12" => "ร‘eembucรบ", "PY-9" => "Paraguarรญ", "PY-15" => "Presidente Hayes", "PY-2" => "San Pedro" }, "QA" => { "QA-DA" => "Ad Dawแธฉah", "QA-KH" => "Al Khawr wa adh Dhakhฤซrah", "QA-WA" => "Al Wakrah", "QA-RA" => "Ar Rayyฤn", "QA-MS" => "Ash Shamฤl", "QA-SH" => "Ash Shฤซแธฉฤnฤซyah", "QA-ZA" => "Azฬง Zฬงaโ€˜ฤyin", "QA-US" => "Umm ลžalฤl" }, "RO" => { "RO-AB" => "Alba", "RO-AR" => "Arad", "RO-AG" => "Argeศ™", "RO-BC" => "Bacฤƒu", "RO-BH" => "Bihor", "RO-BN" => "Bistriศ›a-Nฤƒsฤƒud", "RO-BT" => "Botoศ™ani", "RO-BV" => "Braศ™ov", "RO-BR" => "Brฤƒila", "RO-BZ" => "Buzฤƒu", "RO-CS" => "Caraศ™-Severin", "RO-CL" => "Cฤƒlฤƒraศ™i", "RO-CJ" => "Cluj", "RO-CT" => "Constanศ›a", "RO-CV" => "Covasna", "RO-DB" => "Dรขmboviศ›a", "RO-DJ" => "Dolj", "RO-GL" => "Galaศ›i", "RO-GR" => "Giurgiu", "RO-GJ" => "Gorj", "RO-HR" => "Harghita", "RO-HD" => "Hunedoara", "RO-IL" => "Ialomiศ›a", "RO-IS" => "Iaศ™i", "RO-IF" => "Ilfov", "RO-MM" => "Maramureศ™", "RO-MH" => "Mehedinศ›i", "RO-MS" => "Mureศ™", "RO-NT" => "Neamศ›", "RO-OT" => "Olt", "RO-PH" => "Prahova", "RO-SM" => "Satu Mare", "RO-SJ" => "Sฤƒlaj", "RO-SB" => "Sibiu", "RO-SV" => "Suceava", "RO-TR" => "Teleorman", "RO-TM" => "Timiศ™", "RO-TL" => "Tulcea", "RO-VS" => "Vaslui", "RO-VL" => "Vรขlcea", "RO-VN" => "Vrancea", "RO-B" => "Bucureศ™ti" }, "RS" => { "RS-KM" => "Kosovo-Metohija[a]", "RS-VO" => "Vojvodina" }, "RU" => { "RU-AD" => "Adygeya, Respublika", "RU-AL" => "Altay, Respublika", "RU-BA" => "Bashkortostan, Respublika", "RU-BU" => "Buryatiya, Respublika", "RU-CE" => "Chechenskaya Respublika", "RU-CU" => "Chuvashskaya Respublika", "RU-DA" => "Dagestan, Respublika", "RU-IN" => "Ingushetiya, Respublika", "RU-KB" => "Kabardino-Balkarskaya Respublika", "RU-KL" => "Kalmykiya, Respublika", "RU-KC" => "Karachayevo-Cherkesskaya Respublika", "RU-KR" => "Kareliya, Respublika", "RU-KK" => "Khakasiya, Respublika", "RU-KO" => "Komi, Respublika", "RU-ME" => "Mariy El, Respublika", "RU-MO" => "Mordoviya, Respublika", "RU-SA" => "Saha, Respublika(local variant is Jakutija)", "RU-SE" => "Severnaya Osetiya, Respublika(local variant is Alaniya [Respublika Severnaya Osetiya โ€“ Alaniya])", "RU-TA" => "Tatarstan, Respublika", "RU-TY" => "Tyva, Respublika(local variant is Tuva)", "RU-UD" => "Udmurtskaya Respublika", "RU-ALT" => "Altayskiy kray", "RU-KAM" => "Kamchatskiy kray", "RU-KHA" => "Khabarovskiy kray", "RU-KDA" => "Krasnodarskiy kray", "RU-KYA" => "Krasnoyarskiy kray", "RU-PER" => "Permskiy kray", "RU-PRI" => "Primorskiy kray", "RU-STA" => "Stavropol'skiy kray", "RU-ZAB" => "Zabaykal'skiy kray", "RU-AMU" => "Amurskaya oblast'", "RU-ARK" => "Arkhangel'skaya oblast'", "RU-AST" => "Astrakhanskaya oblast'", "RU-BEL" => "Belgorodskaya oblast'", "RU-BRY" => "Bryanskaya oblast'", "RU-CHE" => "Chelyabinskaya oblast'", "RU-IRK" => "Irkutskaya oblast'", "RU-IVA" => "Ivanovskaya oblast'", "RU-KGD" => "Kaliningradskaya oblast'", "RU-KLU" => "Kaluzhskaya oblast'", "RU-KEM" => "Kemerovskaya oblast'", "RU-KIR" => "Kirovskaya oblast'", "RU-KOS" => "Kostromskaya oblast'", "RU-KGN" => "Kurganskaya oblast'", "RU-KRS" => "Kurskaya oblast'", "RU-LEN" => "Leningradskaya oblast'", "RU-LIP" => "Lipetskaya oblast'", "RU-MAG" => "Magadanskaya oblast'", "RU-MOS" => "Moskovskaya oblast'", "RU-MUR" => "Murmanskaya oblast'", "RU-NIZ" => "Nizhegorodskaya oblast'", "RU-NGR" => "Novgorodskaya oblast'", "RU-NVS" => "Novosibirskaya oblast'", "RU-OMS" => "Omskaya oblast'", "RU-ORE" => "Orenburgskaya oblast'", "RU-ORL" => "Orlovskaya oblast'", "RU-PNZ" => "Penzenskaya oblast'", "RU-PSK" => "Pskovskaya oblast'", "RU-ROS" => "Rostovskaya oblast'", "RU-RYA" => "Ryazanskaya oblast'", "RU-SAK" => "Sakhalinskaya oblast'", "RU-SAM" => "Samarskaya oblast'", "RU-SAR" => "Saratovskaya oblast'", "RU-SMO" => "Smolenskaya oblast'", "RU-SVE" => "Sverdlovskaya oblast'", "RU-TAM" => "Tambovskaya oblast'", "RU-TOM" => "Tomskaya oblast'", "RU-TUL" => "Tul'skaya oblast'", "RU-TVE" => "Tverskaya oblast'", "RU-TYU" => "Tyumenskaya oblast'", "RU-ULY" => "Ul'yanovskaya oblast'", "RU-VLA" => "Vladimirskaya oblast'", "RU-VGG" => "Volgogradskaya oblast'", "RU-VLG" => "Vologodskaya oblast'", "RU-VOR" => "Voronezhskaya oblast'", "RU-YAR" => "Yaroslavskaya oblast'", "RU-MOW" => "Moskva", "RU-SPE" => "Sankt-Peterburg", "RU-YEV" => "Yevreyskaya avtonomnaya oblast'", "RU-CHU" => "Chukotskiy avtonomnyy okrug", "RU-KHM" => "Khanty-Mansiyskiy avtonomnyy okrug(local variant is Yugra)", "RU-NEN" => "Nenetskiy avtonomnyy okrug", "RU-YAN" => "Yamalo-Nenetskiy avtonomnyy okrug" }, "RW" => { "RW-01" => "City of Kigali", "RW-02" => "Eastern", "RW-03" => "Northern", "RW-04" => "Western", "RW-05" => "Southern" }, "SA" => { "SA-11" => "Al Bฤแธฉah", "SA-08" => "Al แธจudลซd ash Shamฤlฤซyah", "SA-12" => "Al Jawf", "SA-03" => "Al Madฤซnah al Munawwarah", "SA-05" => "Al QaลŸฤซm", "SA-01" => "Ar Riyฤแธ‘", "SA-04" => "Ash Sharqฤซyah", "SA-14" => "'Asฤซr", "SA-06" => "แธจฤ'il", "SA-09" => "Jฤzฤn", "SA-02" => "Makkah al Mukarramah", "SA-10" => "Najrฤn", "SA-07" => "Tabลซk" }, "SB" => { "SB-CT" => "Capital Territory (Honiara)", "SB-CE" => "Central", "SB-CH" => "Choiseul", "SB-GU" => "Guadalcanal", "SB-IS" => "Isabel", "SB-MK" => "Makira-Ulawa", "SB-ML" => "Malaita", "SB-RB" => "Rennell and Bellona", "SB-TE" => "Temotu", "SB-WE" => "Western" }, "SC" => { "SC-01" => "Anse aux Pins", "SC-02" => "Anse Boileau", "SC-03" => "Anse Etoile", "SC-05" => "Anse Royale", "SC-04" => "Au Cap", "SC-06" => "Baie Lazare", "SC-07" => "Baie Sainte Anne", "SC-08" => "Beau Vallon", "SC-09" => "Bel Air", "SC-10" => "Bel Ombre", "SC-11" => "Cascade", "SC-12" => "Glacis", "SC-13" => "Grand Anse Mahe", "SC-14" => "Grand Anse Praslin", "SC-15" => "La Digue", "SC-16" => "English River", "SC-26" => "Ile Perseverance I", "SC-27" => "Ile Perseverance II", "SC-24" => "Les Mamelles", "SC-17" => "Mont Buxton", "SC-18" => "Mont Fleuri", "SC-19" => "Plaisance", "SC-20" => "Pointe Larue", "SC-21" => "Port Glaud", "SC-25" => "Roche Caiman", "SC-22" => "Saint Louis", "SC-23" => "Takamaka" }, "SD" => { "SD-RS" => "Al Baแธฉr al Aแธฉmar", "SD-GZ" => "Al Jazฤซrah", "SD-KH" => "Al Kharลฃลซm", "SD-GD" => "Al Qaแธ‘ฤrif", "SD-NR" => "Nahr an Nฤซl", "SD-NW" => "An Nฤซl al Abyaแธ‘", "SD-NB" => "An Nฤซl al Azraq", "SD-NO" => "Ash Shamฤlฤซyah", "SD-DW" => "Gharb Dฤrfลซr", "SD-GK" => "Gharb Kurdufฤn", "SD-DS" => "Janลซb Dฤrfลซr", "SD-KS" => "Janลซb Kurdufฤn", "SD-KA" => "Kassalฤ", "SD-DN" => "Shamฤl Dฤrfลซr", "SD-KN" => "Shamฤl Kurdufฤn", "SD-DE" => "Sharq Dฤrfลซr", "SD-SI" => "Sinnฤr", "SD-DC" => "Wasaลฃ Dฤrfลซr(local variant is Zฤlinjay)" }, "SE" => { "SE-K" => "Blekinge lรคn", "SE-W" => "Dalarnas lรคn", "SE-I" => "Gotlands lรคn", "SE-X" => "Gรคvleborgs lรคn", "SE-N" => "Hallands lรคn", "SE-Z" => "Jรคmtlands lรคn", "SE-F" => "Jรถnkรถpings lรคn", "SE-H" => "Kalmar lรคn", "SE-G" => "Kronobergs lรคn", "SE-BD" => "Norrbottens lรคn", "SE-M" => "Skรฅne lรคn", "SE-AB" => "Stockholms lรคn", "SE-D" => "Sรถdermanlands lรคn", "SE-C" => "Uppsala lรคn", "SE-S" => "Vรคrmlands lรคn", "SE-AC" => "Vรคsterbottens lรคn", "SE-Y" => "Vรคsternorrlands lรคn", "SE-U" => "Vรคstmanlands lรคn", "SE-O" => "Vรคstra Gรถtalands lรคn", "SE-T" => "ร–rebro lรคn", "SE-E" => "ร–stergรถtlands lรคn" }, "SG" => { "SG-01" => "Central Singapore", "SG-02" => "North East", "SG-03" => "North West", "SG-04" => "South East", "SG-05" => "South West" }, "SH" => { "SH-AC" => "Ascension", "SH-HL" => "Saint Helena", "SH-TA" => "Tristan da Cunha" }, "SI" => { "SI-001" => "Ajdovลกฤina", "SI-213" => "Ankaran", "SI-195" => "Apaฤe", "SI-002" => "Beltinci", "SI-148" => "Benedikt", "SI-149" => "Bistrica ob Sotli", "SI-003" => "Bled", "SI-150" => "Bloke", "SI-004" => "Bohinj", "SI-005" => "Borovnica", "SI-006" => "Bovec", "SI-151" => "Braslovฤe", "SI-007" => "Brda", "SI-008" => "Brezovica", "SI-009" => "Breลพice", "SI-152" => "Cankova", "SI-011" => "Celje", "SI-012" => "Cerklje na Gorenjskem", "SI-013" => "Cerknica", "SI-014" => "Cerkno", "SI-153" => "Cerkvenjak", "SI-196" => "Cirkulane", "SI-015" => "ฤŒrenลกovci", "SI-016" => "ฤŒrna na Koroลกkem", "SI-017" => "ฤŒrnomelj", "SI-018" => "Destrnik", "SI-019" => "Divaฤa", "SI-154" => "Dobje", "SI-020" => "Dobrepolje", "SI-155" => "Dobrna", "SI-021" => "Dobrova-Polhov Gradec", "SI-156" => "Dobrovnik", "SI-022" => "Dol pri Ljubljani", "SI-157" => "Dolenjske Toplice", "SI-023" => "Domลพale", "SI-024" => "Dornava", "SI-025" => "Dravograd", "SI-026" => "Duplek", "SI-027" => "Gorenja vas-Poljane", "SI-028" => "Goriลกnica", "SI-207" => "Gorje", "SI-029" => "Gornja Radgona", "SI-030" => "Gornji Grad", "SI-031" => "Gornji Petrovci", "SI-158" => "Grad", "SI-032" => "Grosuplje", "SI-159" => "Hajdina", "SI-160" => "Hoฤe-Slivnica", "SI-161" => "Hodoลก", "SI-162" => "Horjul", "SI-034" => "Hrastnik", "SI-035" => "Hrpelje-Kozina", "SI-036" => "Idrija", "SI-037" => "Ig", "SI-038" => "Ilirska Bistrica", "SI-039" => "Ivanฤna Gorica", "SI-040" => "Izola", "SI-041" => "Jesenice", "SI-163" => "Jezersko", "SI-042" => "Jurลกinci", "SI-043" => "Kamnik", "SI-044" => "Kanal", "SI-045" => "Kidriฤevo", "SI-046" => "Kobarid", "SI-047" => "Kobilje", "SI-048" => "Koฤevje", "SI-049" => "Komen", "SI-164" => "Komenda", "SI-050" => "Koper", "SI-197" => "Kosanjevica na Krki", "SI-165" => "Kostel", "SI-051" => "Kozje", "SI-052" => "Kranj", "SI-053" => "Kranjska Gora", "SI-166" => "Kriลพevci", "SI-054" => "Krลกko", "SI-055" => "Kungota", "SI-056" => "Kuzma", "SI-057" => "Laลกko", "SI-058" => "Lenart", "SI-059" => "Lendava", "SI-060" => "Litija", "SI-061" => "Ljubljana", "SI-062" => "Ljubno", "SI-063" => "Ljutomer", "SI-208" => "Log-Dragomer", "SI-064" => "Logatec", "SI-065" => "Loลกka dolina", "SI-066" => "Loลกki Potok", "SI-167" => "Lovrenc na Pohorju", "SI-067" => "Luฤe", "SI-068" => "Lukovica", "SI-069" => "Majลกperk", "SI-198" => "Makole", "SI-070" => "Maribor", "SI-168" => "Markovci", "SI-071" => "Medvode", "SI-072" => "Mengeลก", "SI-073" => "Metlika", "SI-074" => "Meลพica", "SI-169" => "Miklavลพ na Dravskem polju", "SI-075" => "Miren-Kostanjevica", "SI-212" => "Mirna", "SI-170" => "Mirna Peฤ", "SI-076" => "Mislinja", "SI-199" => "Mokronog-Trebelno", "SI-077" => "Moravฤe", "SI-078" => "Moravske Toplice", "SI-079" => "Mozirje", "SI-080" => "Murska Sobota", "SI-081" => "Muta", "SI-082" => "Naklo", "SI-083" => "Nazarje", "SI-084" => "Nova Gorica", "SI-085" => "Novo Mesto", "SI-086" => "Odranci", "SI-171" => "Oplotnica", "SI-087" => "Ormoลพ", "SI-088" => "Osilnica", "SI-089" => "Pesnica", "SI-090" => "Piran", "SI-091" => "Pivka", "SI-092" => "Podฤetrtek", "SI-172" => "Podlehnik", "SI-093" => "Podvelka", "SI-200" => "Poljฤane", "SI-173" => "Polzela", "SI-094" => "Postojna", "SI-174" => "Prebold", "SI-095" => "Preddvor", "SI-175" => "Prevalje", "SI-096" => "Ptuj", "SI-097" => "Puconci", "SI-098" => "Raฤe-Fram", "SI-099" => "Radeฤe", "SI-100" => "Radenci", "SI-101" => "Radlje ob Dravi", "SI-102" => "Radovljica", "SI-103" => "Ravne na Koroลกkem", "SI-176" => "Razkriลพje", "SI-209" => "Reฤica ob Savinji", "SI-201" => "Renฤe-Vogrsko", "SI-104" => "Ribnica", "SI-177" => "Ribnica na Pohorju", "SI-106" => "Rogaลกka Slatina", "SI-105" => "Rogaลกovci", "SI-107" => "Rogatec", "SI-108" => "Ruลกe", "SI-178" => "Selnica ob Dravi", "SI-109" => "Semiฤ", "SI-110" => "Sevnica", "SI-111" => "Seลพana", "SI-112" => "Slovenj Gradec", "SI-113" => "Slovenska Bistrica", "SI-114" => "Slovenske Konjice", "SI-179" => "Sodraลพica", "SI-180" => "Solฤava", "SI-202" => "Srediลกฤe ob Dravi", "SI-115" => "Starลกe", "SI-203" => "Straลพa", "SI-181" => "Sveta Ana", "SI-204" => "Sveta Trojica v Slovenskih goricah", "SI-182" => "Sveti Andraลพ v Slovenskih goricah", "SI-116" => "Sveti Jurij ob ล ฤavnici", "SI-210" => "Sveti Jurij v Slovenskih goricah", "SI-205" => "Sveti Tomaลพ", "SI-033" => "ล alovci", "SI-183" => "ล empeter-Vrtojba", "SI-117" => "ล enฤur", "SI-118" => "ล entilj", "SI-119" => "ล entjernej", "SI-120" => "ล entjur", "SI-211" => "ล entrupert", "SI-121" => "ล kocjan", "SI-122" => "ล kofja Loka", "SI-123" => "ล kofljica", "SI-124" => "ล marje pri Jelลกah", "SI-206" => "ล marjeลกke Toplice", "SI-125" => "ล martno ob Paki", "SI-194" => "ล martno pri Litiji", "SI-126" => "ล oลกtanj", "SI-127" => "ล tore", "SI-184" => "Tabor", "SI-010" => "Tiลกina", "SI-128" => "Tolmin", "SI-129" => "Trbovlje", "SI-130" => "Trebnje", "SI-185" => "Trnovska Vas", "SI-186" => "Trzin", "SI-131" => "Trลพiฤ", "SI-132" => "Turniลกฤe", "SI-133" => "Velenje", "SI-187" => "Velika Polana", "SI-134" => "Velike Laลกฤe", "SI-188" => "Verลพej", "SI-135" => "Videm", "SI-136" => "Vipava", "SI-137" => "Vitanje", "SI-138" => "Vodice", "SI-139" => "Vojnik", "SI-189" => "Vransko", "SI-140" => "Vrhnika", "SI-141" => "Vuzenica", "SI-142" => "Zagorje ob Savi", "SI-143" => "Zavrฤ", "SI-144" => "Zreฤe", "SI-190" => "ลฝalec", "SI-146" => "ลฝelezniki", "SI-191" => "ลฝetale", "SI-147" => "ลฝiri", "SI-192" => "ลฝirovnica", "SI-193" => "ลฝuลพemberk" }, "SK" => { "SK-BC" => "Banskobystrickรฝ kraj", "SK-BL" => "Bratislavskรฝ kraj", "SK-KI" => "Koลกickรฝ kraj", "SK-NI" => "Nitriansky kraj", "SK-PV" => "Preลกovskรฝ kraj", "SK-TC" => "Trenฤiansky kraj", "SK-TA" => "Trnavskรฝ kraj", "SK-ZI" => "ลฝilinskรฝ kraj" }, "SL" => { "SL-W" => "Western Area (Freetown)", "SL-E" => "Eastern", "SL-N" => "Northern", "SL-NW" => "North Western", "SL-S" => "Southern" }, "SM" => { "SM-01" => "Acquaviva", "SM-06" => "Borgo Maggiore", "SM-02" => "Chiesanuova", "SM-07" => "Cittร  di San Marino(local variant is San Marino)", "SM-03" => "Domagnano", "SM-04" => "Faetano", "SM-05" => "Fiorentino", "SM-08" => "Montegiardino", "SM-09" => "Serravalle" }, "SN" => { "SN-DK" => "Dakar", "SN-DB" => "Diourbel", "SN-FK" => "Fatick", "SN-KA" => "Kaffrine", "SN-KL" => "Kaolack", "SN-KE" => "Kรฉdougou", "SN-KD" => "Kolda", "SN-LG" => "Louga", "SN-MT" => "Matam", "SN-SL" => "Saint-Louis", "SN-SE" => "Sรฉdhiou", "SN-TC" => "Tambacounda", "SN-TH" => "Thiรจs", "SN-ZG" => "Ziguinchor" }, "SO" => { "SO-AW" => "Awdal", "SO-BK" => "Bakool", "SO-BN" => "Banaadir", "SO-BR" => "Bari", "SO-BY" => "Bay", "SO-GA" => "Galguduud", "SO-GE" => "Gedo", "SO-HI" => "Hiiraan", "SO-JD" => "Jubbada Dhexe", "SO-JH" => "Jubbada Hoose", "SO-MU" => "Mudug", "SO-NU" => "Nugaal", "SO-SA" => "Sanaag", "SO-SD" => "Shabeellaha Dhexe", "SO-SH" => "Shabeellaha Hoose", "SO-SO" => "Sool", "SO-TO" => "Togdheer", "SO-WO" => "Woqooyi Galbeed" }, "SR" => { "SR-BR" => "Brokopondo", "SR-CM" => "Commewijne", "SR-CR" => "Coronie", "SR-MA" => "Marowijne", "SR-NI" => "Nickerie", "SR-PR" => "Para", "SR-PM" => "Paramaribo", "SR-SA" => "Saramacca", "SR-SI" => "Sipaliwini", "SR-WA" => "Wanica" }, "SS" => { "SS-EC" => "Central Equatoria", "SS-EE" => "Eastern Equatoria", "SS-JG" => "Jonglei", "SS-LK" => "Lakes", "SS-BN" => "Northern Bahr el Ghazal", "SS-UY" => "Unity", "SS-NU" => "Upper Nile", "SS-WR" => "Warrap", "SS-BW" => "Western Bahr el Ghazal", "SS-EW" => "Western Equatoria" }, "ST" => { "ST-01" => "รgua Grande", "ST-02" => "Cantagalo", "ST-03" => "Cauรฉ", "ST-04" => "Lembรก", "ST-05" => "Lobata", "ST-06" => "Mรฉ-Zรณchi", "ST-P" => "Prรญncipe" }, "SV" => { "SV-AH" => "Ahuachapรกn", "SV-CA" => "Cabaรฑas", "SV-CH" => "Chalatenango", "SV-CU" => "Cuscatlรกn", "SV-LI" => "La Libertad", "SV-PA" => "La Paz", "SV-UN" => "La Uniรณn", "SV-MO" => "Morazรกn", "SV-SM" => "San Miguel", "SV-SS" => "San Salvador", "SV-SV" => "San Vicente", "SV-SA" => "Santa Ana", "SV-SO" => "Sonsonate", "SV-US" => "Usulutรกn" }, "SY" => { "SY-HA" => "Al แธจasakah", "SY-LA" => "Al Lฤdhiqฤซyah", "SY-QU" => "Al Qunayลฃirah", "SY-RA" => "Ar Raqqah", "SY-SU" => "As Suwaydฤ'", "SY-DR" => "Dar'ฤ", "SY-DY" => "Dayr az Zawr", "SY-DI" => "Dimashq", "SY-HL" => "แธจalab", "SY-HM" => "แธจamฤh", "SY-HI" => "แธจimลŸ", "SY-ID" => "Idlib", "SY-RD" => "Rฤซf Dimashq", "SY-TA" => "ลขarลฃลซs" }, "SZ" => { "SZ-HH" => "Hhohho", "SZ-LU" => "Lubombo", "SZ-MA" => "Manzini", "SZ-SH" => "Shiselweni" }, "TD" => { "TD-BA" => "Al Baลฃแธฉฤโ€™", "TD-LC" => "Al Buแธฉayrah", "TD-BG" => "Baแธฉr al Ghazฤl", "TD-BO" => "Bลซrkลซ", "TD-HL" => "แธจajjar Lamฤซs", "TD-EO" => "Inฤซdฤซ al Gharbฤซ", "TD-EE" => "Inฤซdฤซ ash Sharqฤซ", "TD-KA" => "Kฤnim", "TD-LO" => "Lลซghลซn al Gharbฤซ", "TD-LR" => "Lลซghลซn ash Sharqฤซ", "TD-ND" => "Madฤซnat Injamฤซnฤ", "TD-MA" => "Mฤndลซl", "TD-MO" => "Mฤyลซ Kฤซbbฤซ al Gharbฤซ", "TD-ME" => "Mฤyลซ Kฤซbbฤซ ash Sharqฤซ", "TD-GR" => "Qฤซrฤ", "TD-SA" => "Salฤmฤt", "TD-MC" => "Shฤrฤซ al Awsaลฃ", "TD-CB" => "Shฤrฤซ Bฤqirmฤซ", "TD-SI" => "Sฤซlฤ", "TD-TA" => "Tฤnjฤซlฤซ", "TD-TI" => "Tibastฤซ", "TD-OD" => "Waddฤy", "TD-WF" => "Wฤdฤซ Fฤซrฤโ€™" }, "TG" => { "TG-C" => "Centrale", "TG-K" => "Kara", "TG-M" => "Maritime (Rรฉgion)", "TG-P" => "Plateaux", "TG-S" => "Savanes" }, "TH" => { "TH-10" => "Krung Thep Maha Nakhon(local variant is Bangkok)", "TH-S" => "Phatthaya", "TH-37" => "Amnat Charoen", "TH-15" => "Ang Thong", "TH-38" => "Bueng Kan", "TH-31" => "Buri Ram", "TH-24" => "Chachoengsao", "TH-18" => "Chai Nat", "TH-36" => "Chaiyaphum", "TH-22" => "Chanthaburi", "TH-50" => "Chiang Mai", "TH-57" => "Chiang Rai", "TH-20" => "Chon Buri", "TH-86" => "Chumphon", "TH-46" => "Kalasin", "TH-62" => "Kamphaeng Phet", "TH-71" => "Kanchanaburi", "TH-40" => "Khon Kaen", "TH-81" => "Krabi", "TH-52" => "Lampang", "TH-51" => "Lamphun", "TH-42" => "Loei", "TH-16" => "Lop Buri", "TH-58" => "Mae Hong Son", "TH-44" => "Maha Sarakham", "TH-49" => "Mukdahan", "TH-26" => "Nakhon Nayok", "TH-73" => "Nakhon Pathom", "TH-48" => "Nakhon Phanom", "TH-30" => "Nakhon Ratchasima", "TH-60" => "Nakhon Sawan", "TH-80" => "Nakhon Si Thammarat", "TH-55" => "Nan", "TH-96" => "Narathiwat", "TH-39" => "Nong Bua Lam Phu", "TH-43" => "Nong Khai", "TH-12" => "Nonthaburi", "TH-13" => "Pathum Thani", "TH-94" => "Pattani", "TH-82" => "Phangnga", "TH-93" => "Phatthalung", "TH-56" => "Phayao", "TH-67" => "Phetchabun", "TH-76" => "Phetchaburi", "TH-66" => "Phichit", "TH-65" => "Phitsanulok", "TH-54" => "Phrae", "TH-14" => "Phra Nakhon Si Ayutthaya", "TH-83" => "Phuket", "TH-25" => "Prachin Buri", "TH-77" => "Prachuap Khiri Khan", "TH-85" => "Ranong", "TH-70" => "Ratchaburi", "TH-21" => "Rayong", "TH-45" => "Roi Et", "TH-27" => "Sa Kaeo", "TH-47" => "Sakon Nakhon", "TH-11" => "Samut Prakan", "TH-74" => "Samut Sakhon", "TH-75" => "Samut Songkhram", "TH-19" => "Saraburi", "TH-91" => "Satun", "TH-17" => "Sing Buri", "TH-33" => "Si Sa Ket", "TH-90" => "Songkhla", "TH-64" => "Sukhothai", "TH-72" => "Suphan Buri", "TH-84" => "Surat Thani", "TH-32" => "Surin", "TH-63" => "Tak", "TH-92" => "Trang", "TH-23" => "Trat", "TH-34" => "Ubon Ratchathani", "TH-41" => "Udon Thani", "TH-61" => "Uthai Thani", "TH-53" => "Uttaradit", "TH-95" => "Yala", "TH-35" => "Yasothon" }, "TJ" => { "TJ-DU" => "Dushanbe", "TJ-GB" => "Kลญhistoni Badakhshon", "TJ-KT" => "Khatlon", "TJ-SU" => "Sughd", "TJ-RA" => "nohiyahoi tobei jumhurรญ" }, "TL" => { "TL-AL" => "Aileu", "TL-AN" => "Ainaro", "TL-BA" => "Baucau", "TL-BO" => "Bobonaro", "TL-CO" => "Cova Lima", "TL-DI" => "Dรญli", "TL-ER" => "Ermera", "TL-LA" => "Lautรฉm", "TL-LI" => "Liquiรงa", "TL-MT" => "Manatuto", "TL-MF" => "Manufahi", "TL-OE" => "Oรฉ-Cusse Ambeno(local variant is Oecussi)", "TL-VI" => "Viqueque" }, "TM" => { "TM-A" => "Ahal", "TM-B" => "Balkan", "TM-D" => "DaลŸoguz", "TM-L" => "Lebap", "TM-M" => "Mary", "TM-S" => "AลŸgabat" }, "TN" => { "TN-31" => "Bรฉja", "TN-13" => "Ben Arous", "TN-23" => "Bizerte", "TN-81" => "Gabรจs", "TN-71" => "Gafsa", "TN-32" => "Jendouba", "TN-41" => "Kairouan", "TN-42" => "Kasserine", "TN-73" => "Kรฉbili", "TN-12" => "L'Ariana", "TN-14" => "La Manouba", "TN-33" => "Le Kef", "TN-53" => "Mahdia", "TN-82" => "Mรฉdenine", "TN-52" => "Monastir", "TN-21" => "Nabeul", "TN-61" => "Sfax", "TN-43" => "Sidi Bouzid", "TN-34" => "Siliana", "TN-51" => "Sousse", "TN-83" => "Tataouine", "TN-72" => "Tozeur", "TN-11" => "Tunis", "TN-22" => "Zaghouan" }, "TO" => { "TO-01" => "'Eua", "TO-02" => "Ha'apai", "TO-03" => "Niuas", "TO-04" => "Tongatapu", "TO-05" => "Vava'u" }, "TR" => { "TR-01" => "Adana", "TR-02" => "Adฤฑyaman", "TR-03" => "Afyonkarahisar", "TR-04" => "AฤŸrฤฑ", "TR-68" => "Aksaray", "TR-05" => "Amasya", "TR-06" => "Ankara", "TR-07" => "Antalya", "TR-75" => "Ardahan", "TR-08" => "Artvin", "TR-09" => "Aydฤฑn", "TR-10" => "Balฤฑkesir", "TR-74" => "Bartฤฑn", "TR-72" => "Batman", "TR-69" => "Bayburt", "TR-11" => "Bilecik", "TR-12" => "Bingรถl", "TR-13" => "Bitlis", "TR-14" => "Bolu", "TR-15" => "Burdur", "TR-16" => "Bursa", "TR-17" => "ร‡anakkale", "TR-18" => "ร‡ankฤฑrฤฑ", "TR-19" => "ร‡orum", "TR-20" => "Denizli", "TR-21" => "Diyarbakฤฑr", "TR-81" => "Dรผzce", "TR-22" => "Edirne", "TR-23" => "ElazฤฑฤŸ", "TR-24" => "Erzincan", "TR-25" => "Erzurum", "TR-26" => "EskiลŸehir", "TR-27" => "Gaziantep", "TR-28" => "Giresun", "TR-29" => "GรผmรผลŸhane", "TR-30" => "Hakkรขri", "TR-31" => "Hatay", "TR-76" => "IฤŸdฤฑr", "TR-32" => "Isparta", "TR-34" => "ฤฐstanbul", "TR-35" => "ฤฐzmir", "TR-46" => "KahramanmaraลŸ", "TR-78" => "Karabรผk", "TR-70" => "Karaman", "TR-36" => "Kars", "TR-37" => "Kastamonu", "TR-38" => "Kayseri", "TR-71" => "Kฤฑrฤฑkkale", "TR-39" => "Kฤฑrklareli", "TR-40" => "KฤฑrลŸehir", "TR-79" => "Kilis", "TR-41" => "Kocaeli", "TR-42" => "Konya", "TR-43" => "Kรผtahya", "TR-44" => "Malatya", "TR-45" => "Manisa", "TR-47" => "Mardin", "TR-33" => "Mersin", "TR-48" => "MuฤŸla", "TR-49" => "MuลŸ", "TR-50" => "NevลŸehir", "TR-51" => "NiฤŸde", "TR-52" => "Ordu", "TR-80" => "Osmaniye", "TR-53" => "Rize", "TR-54" => "Sakarya", "TR-55" => "Samsun", "TR-56" => "Siirt", "TR-57" => "Sinop", "TR-58" => "Sivas", "TR-63" => "ลžanlฤฑurfa", "TR-73" => "ลžฤฑrnak", "TR-59" => "TekirdaฤŸ", "TR-60" => "Tokat", "TR-61" => "Trabzon", "TR-62" => "Tunceli", "TR-64" => "UลŸak", "TR-65" => "Van", "TR-77" => "Yalova", "TR-66" => "Yozgat", "TR-67" => "Zonguldak" }, "TT" => { "TT-ARI" => "Arima", "TT-CHA" => "Chaguanas", "TT-CTT" => "Couvaโ€“Tabaquiteโ€“Talparo", "TT-DMN" => "Diego Martin", "TT-MRC" => "Mayaro-Rio Claro", "TT-PED" => "Penal-Debe", "TT-POS" => "Port of Spain", "TT-PRT" => "Princes Town", "TT-PTF" => "Point Fortin", "TT-SFO" => "San Fernando", "TT-SGE" => "Sangre Grande", "TT-SIP" => "Siparia", "TT-SJL" => "San Juan-Laventille", "TT-TOB" => "Tobago", "TT-TUP" => "Tunapuna-Piarco" }, "TV" => { "TV-FUN" => "Funafuti", "TV-NMG" => "Nanumaga", "TV-NMA" => "Nanumea", "TV-NIT" => "Niutao", "TV-NUI" => "Nui", "TV-NKF" => "Nukufetau", "TV-NKL" => "Nukulaelae", "TV-VAI" => "Vaitupu" }, "TW" => { "TW-CHA" => "Changhua", "TW-CYI" => "Chiayi", "TW-CYQ" => "Chiayi", "TW-HSZ" => "Hsinchu", "TW-HSQ" => "Hsinchu", "TW-HUA" => "Hualien", "TW-KHH" => "Kaohsiung", "TW-KEE" => "Keelung", "TW-KIN" => "Kinmen", "TW-LIE" => "Lienchiang", "TW-MIA" => "Miaoli", "TW-NAN" => "Nantou", "TW-NWT" => "New Taipei", "TW-PEN" => "Penghu", "TW-PIF" => "Pingtung", "TW-TXG" => "Taichung", "TW-TNN" => "Tainan", "TW-TPE" => "Taipei", "TW-TTT" => "Taitung", "TW-TAO" => "Taoyuan", "TW-ILA" => "Yilan", "TW-YUN" => "Yunlin" }, "TZ" => { "TZ-01" => "Arusha", "TZ-02" => "Dar es Salaam", "TZ-03" => "Dodoma", "TZ-27" => "Geita", "TZ-04" => "Iringa", "TZ-05" => "Kagera", "TZ-06" => "Kaskazini Pemba", "TZ-07" => "Kaskazini Unguja", "TZ-28" => "Katavi", "TZ-08" => "Kigoma", "TZ-09" => "Kilimanjaro", "TZ-10" => "Kusini Pemba", "TZ-11" => "Kusini Unguja", "TZ-12" => "Lindi", "TZ-26" => "Manyara", "TZ-13" => "Mara", "TZ-14" => "Mbeya", "TZ-15" => "Mjini Magharibi", "TZ-16" => "Morogoro", "TZ-17" => "Mtwara", "TZ-18" => "Mwanza", "TZ-29" => "Njombe", "TZ-19" => "Pwani", "TZ-20" => "Rukwa", "TZ-21" => "Ruvuma", "TZ-22" => "Shinyanga", "TZ-30" => "Simiyu", "TZ-23" => "Singida", "TZ-31" => "Songwe", "TZ-24" => "Tabora", "TZ-25" => "Tanga" }, "UA" => { "UA-71" => "Cherkaska oblast", "UA-74" => "Chernihivska oblast", "UA-77" => "Chernivetska oblast", "UA-12" => "Dnipropetrovska oblast", "UA-14" => "Donetska oblast", "UA-26" => "Ivano-Frankivska oblast", "UA-63" => "Kharkivska oblast", "UA-65" => "Khersonska oblast", "UA-68" => "Khmelnytska oblast", "UA-35" => "Kirovohradska oblast", "UA-32" => "Kyivska oblast", "UA-09" => "Luhanska oblast", "UA-46" => "Lvivska oblast", "UA-48" => "Mykolaivska oblast", "UA-51" => "Odeska oblast", "UA-53" => "Poltavska oblast", "UA-56" => "Rivnenska oblast", "UA-59" => "Sumska oblast", "UA-61" => "Ternopilska oblast", "UA-05" => "Vinnytska oblast", "UA-07" => "Volynska oblast", "UA-21" => "Zakarpatska oblast", "UA-23" => "Zaporizka oblast", "UA-18" => "Zhytomyrska oblast", "UA-43" => "Avtonomna Respublika Krym", "UA-30" => "Kyiv", "UA-40" => "Sevastopol" }, "UG" => { "UG-C" => "Central", "UG-E" => "Eastern", "UG-N" => "Northern", "UG-W" => "Western" }, "UM" => { "UM-81" => "Baker Island", "UM-84" => "Howland Island", "UM-86" => "Jarvis Island", "UM-67" => "Johnston Atoll", "UM-89" => "Kingman Reef", "UM-71" => "Midway Islands", "UM-76" => "Navassa Island", "UM-95" => "Palmyra Atoll", "UM-79" => "Wake Island" }, "US" => { "US-AL" => "Alabama", "US-AK" => "Alaska", "US-AZ" => "Arizona", "US-AR" => "Arkansas", "US-CA" => "California", "US-CO" => "Colorado", "US-CT" => "Connecticut", "US-DE" => "Delaware", "US-FL" => "Florida", "US-GA" => "Georgia", "US-HI" => "Hawaii", "US-ID" => "Idaho", "US-IL" => "Illinois", "US-IN" => "Indiana", "US-IA" => "Iowa", "US-KS" => "Kansas", "US-KY" => "Kentucky", "US-LA" => "Louisiana", "US-ME" => "Maine", "US-MD" => "Maryland", "US-MA" => "Massachusetts", "US-MI" => "Michigan", "US-MN" => "Minnesota", "US-MS" => "Mississippi", "US-MO" => "Missouri", "US-MT" => "Montana", "US-NE" => "Nebraska", "US-NV" => "Nevada", "US-NH" => "New Hampshire", "US-NJ" => "New Jersey", "US-NM" => "New Mexico", "US-NY" => "New York", "US-NC" => "North Carolina", "US-ND" => "North Dakota", "US-OH" => "Ohio", "US-OK" => "Oklahoma", "US-OR" => "Oregon", "US-PA" => "Pennsylvania", "US-RI" => "Rhode Island", "US-SC" => "South Carolina", "US-SD" => "South Dakota", "US-TN" => "Tennessee", "US-TX" => "Texas", "US-UT" => "Utah", "US-VT" => "Vermont", "US-VA" => "Virginia", "US-WA" => "Washington", "US-WV" => "West Virginia", "US-WI" => "Wisconsin", "US-WY" => "Wyoming", "US-DC" => "District of Columbia", "US-AS" => "American Samoa", "US-GU" => "Guam", "US-MP" => "Northern Mariana Islands", "US-PR" => "Puerto Rico", "US-UM" => "United States Minor Outlying Islands", "US-VI" => "U.S. Virgin Islands" }, "UY" => { "UY-AR" => "Artigas", "UY-CA" => "Canelones", "UY-CL" => "Cerro Largo", "UY-CO" => "Colonia", "UY-DU" => "Durazno", "UY-FS" => "Flores", "UY-FD" => "Florida", "UY-LA" => "Lavalleja", "UY-MA" => "Maldonado", "UY-MO" => "Montevideo", "UY-PA" => "Paysandรบ", "UY-RN" => "Rรญo Negro", "UY-RV" => "Rivera", "UY-RO" => "Rocha", "UY-SA" => "Salto", "UY-SJ" => "San Josรฉ", "UY-SO" => "Soriano", "UY-TA" => "Tacuarembรณ", "UY-TT" => "Treinta y Tres" }, "UZ" => { "UZ-TK" => "Toshkent", "UZ-AN" => "Andijon", "UZ-BU" => "Buxoro", "UZ-FA" => "Fargโ€˜ona", "UZ-JI" => "Jizzax", "UZ-NG" => "Namangan", "UZ-NW" => "Navoiy", "UZ-QA" => "Qashqadaryo", "UZ-SA" => "Samarqand", "UZ-SI" => "Sirdaryo", "UZ-SU" => "Surxondaryo", "UZ-TO" => "Toshkent", "UZ-XO" => "Xorazm", "UZ-QR" => "Qoraqalpogโ€˜iston Respublikasi" }, "VC" => { "VC-01" => "Charlotte", "VC-06" => "Grenadines", "VC-02" => "Saint Andrew", "VC-03" => "Saint David", "VC-04" => "Saint George", "VC-05" => "Saint Patrick" }, "VE" => { "VE-W" => "Dependencias Federales", "VE-A" => "Distrito Capital", "VE-Z" => "Amazonas", "VE-B" => "Anzoรกtegui", "VE-C" => "Apure", "VE-D" => "Aragua", "VE-E" => "Barinas", "VE-F" => "Bolรญvar", "VE-G" => "Carabobo", "VE-H" => "Cojedes", "VE-Y" => "Delta Amacuro", "VE-I" => "Falcรณn", "VE-J" => "Guรกrico", "VE-K" => "Lara", "VE-L" => "Mรฉrida", "VE-M" => "Miranda", "VE-N" => "Monagas", "VE-O" => "Nueva Esparta", "VE-P" => "Portuguesa", "VE-R" => "Sucre", "VE-S" => "Tรกchira", "VE-T" => "Trujillo", "VE-X" => "Vargas", "VE-U" => "Yaracuy", "VE-V" => "Zulia" }, "VN" => { "VN-44" => "An Giang", "VN-43" => "Bร  Rแป‹a - Vลฉng Tร u", "VN-54" => "Bแบฏc Giang", "VN-53" => "Bแบฏc Kแบกn", "VN-55" => "Bแบกc Liรชu", "VN-56" => "Bแบฏc Ninh", "VN-50" => "Bแบฟn Tre", "VN-31" => "Bรฌnh ฤแป‹nh", "VN-57" => "Bรฌnh Dฦฐฦกng", "VN-58" => "Bรฌnh Phฦฐแป›c", "VN-40" => "Bรฌnh Thuแบญn", "VN-59" => "Cร  Mau", "VN-04" => "Cao Bแบฑng", "VN-33" => "ฤแบฏk Lแบฏk", "VN-72" => "ฤแบฏk Nรดng", "VN-71" => "ฤiแป‡n Biรชn", "VN-39" => "ฤแป“ng Nai", "VN-45" => "ฤแป“ng Thรกp", "VN-30" => "Gia Lai", "VN-03" => "Hร  Giang", "VN-63" => "Hร  Nam", "VN-23" => "Hร  Tฤฉnh", "VN-61" => "Hแบฃi Dฦฐฦกng", "VN-73" => "Hแบญu Giang", "VN-14" => "Hรฒa Bรฌnh", "VN-66" => "Hฦฐng Yรชn", "VN-34" => "Khรกnh Hรฒa", "VN-47" => "Kiแบฟn Giang", "VN-28" => "Kon Tum", "VN-01" => "Lai Chรขu", "VN-35" => "Lรขm ฤแป“ng", "VN-09" => "Lแบกng Sฦกn", "VN-02" => "Lร o Cai", "VN-41" => "Long An", "VN-67" => "Nam ฤแป‹nh", "VN-22" => "Nghแป‡ An", "VN-18" => "Ninh Bรฌnh", "VN-36" => "Ninh Thuแบญn", "VN-68" => "Phรบ Thแป", "VN-32" => "Phรบ Yรชn", "VN-24" => "Quแบฃng Bรฌnh", "VN-27" => "Quแบฃng Nam", "VN-29" => "Quแบฃng Ngรฃi", "VN-13" => "Quแบฃng Ninh", "VN-25" => "Quแบฃng Trแป‹", "VN-52" => "Sรณc Trฤƒng", "VN-05" => "Sฦกn La", "VN-37" => "Tรขy Ninh", "VN-20" => "Thรกi Bรฌnh", "VN-69" => "Thรกi Nguyรชn", "VN-21" => "Thanh Hรณa", "VN-26" => "Thแปซa Thiรชn-Huแบฟ", "VN-46" => "Tiแปn Giang", "VN-51" => "Trร  Vinh", "VN-07" => "Tuyรชn Quang", "VN-49" => "Vฤฉnh Long", "VN-70" => "Vฤฉnh Phรบc", "VN-06" => "Yรชn Bรกi", "VN-CT" => "Cแบงn Thฦก", "VN-DN" => "ฤร  Nแบตng", "VN-HN" => "Hร  Nแป™i", "VN-HP" => "Hแบฃi Phรฒng", "VN-SG" => "Hแป“ Chรญ Minh(local variant is Sai Gon)" }, "VU" => { "VU-MAP" => "Malampa", "VU-PAM" => "Pรฉnama", "VU-SAM" => "Sanma", "VU-SEE" => "Shรฉfa", "VU-TAE" => "Tafรฉa", "VU-TOB" => "Torba" }, "WF" => { "WF-AL" => "Alo", "WF-SG" => "Sigave", "WF-UV" => "Uvea" }, "WS" => { "WS-AA" => "A'ana", "WS-AL" => "Aiga-i-le-Tai", "WS-AT" => "Atua", "WS-FA" => "Fa'asaleleaga", "WS-GE" => "Gaga'emauga", "WS-GI" => "Gagaifomauga", "WS-PA" => "Palauli", "WS-SA" => "Satupa'itea", "WS-TU" => "Tuamasaga", "WS-VF" => "Va'a-o-Fonoti", "WS-VS" => "Vaisigano" }, "YE" => { "YE-SA" => "Amฤnat al โ€˜ฤ€ลŸimah [city]", "YE-AB" => "Abyan", "YE-AD" => "โ€˜Adan", "YE-DA" => "Aแธ‘ แธฤliโ€˜", "YE-BA" => "Al Bayแธ‘ฤโ€™", "YE-HU" => "Al แธจudaydah", "YE-JA" => "Al Jawf", "YE-MR" => "Al Mahrah", "YE-MW" => "Al Maแธฉwฤซt", "YE-AM" => "โ€˜Amrฤn", "YE-SU" => "Arkhabฤซl Suquลฃrรก", "YE-DH" => "Dhamฤr", "YE-HD" => "แธจaแธ‘ramawt", "YE-HJ" => "แธจajjah", "YE-IB" => "Ibb", "YE-LA" => "Laแธฉij", "YE-MA" => "Maโ€™rib", "YE-RA" => "Raymah", "YE-SD" => "ลžฤสปdah", "YE-SN" => "ลžanสปฤโ€™", "YE-SH" => "Shabwah", "YE-TA" => "Tฤสปizz" }, "ZA" => { "ZA-EC" => "Eastern Cape", "ZA-FS" => "Free State", "ZA-GP" => "Gauteng", "ZA-KZN" => "Kwazulu-Natal", "ZA-LP" => "Limpopo", "ZA-MP" => "Mpumalanga", "ZA-NC" => "Northern Cape", "ZA-NW" => "North-West", "ZA-WC" => "Western Cape" }, "ZM" => { "ZM-02" => "Central", "ZM-08" => "Copperbelt", "ZM-03" => "Eastern", "ZM-04" => "Luapula", "ZM-09" => "Lusaka", "ZM-05" => "Northern", "ZM-06" => "North-Western", "ZM-07" => "Southern", "ZM-01" => "Western", "ZM-10" => "Muchinga" }, "ZW" => { "ZW-BU" => "Bulawayo", "ZW-HA" => "Harare", "ZW-MA" => "Manicaland", "ZW-MC" => "Mashonaland Central", "ZW-ME" => "Mashonaland East", "ZW-MW" => "Mashonaland West", "ZW-MV" => "Masvingo", "ZW-MN" => "Matabeleland North", "ZW-MS" => "Matabeleland South", "ZW-MI" => "Midlands" } } end end end danini-the-panini-kdl-rb-56d7cf1/lib/kdl/types/currency.rb000066400000000000000000000013361515522600200234440ustar00rootroot00000000000000# frozen_string_literal: true require 'kdl/types/currency/iso4217_currencies' module KDL module Types class Currency < Value::Custom attr_reader :numeric_code, :minor_unit, :name def initialize(value, format: nil, type: 'currency') super @numeric = value.fetch(:numeric, nil) @minor_unit = value.fetch(:minor_unit, nil) @name = value.fetch(:name, '') end def self.call(value, type = 'currency') return nil unless value.is_a? ::KDL::Value::String currency = CURRENCIES[value.value.upcase] raise ArgumentError, 'invalid currency' if currency.nil? new(currency, type: type) end end MAPPING['currency'] = Currency end end danini-the-panini-kdl-rb-56d7cf1/lib/kdl/types/currency/000077500000000000000000000000001515522600200231145ustar00rootroot00000000000000danini-the-panini-kdl-rb-56d7cf1/lib/kdl/types/currency/iso4217_currencies.rb000066400000000000000000000400051515522600200267720ustar00rootroot00000000000000# frozen_string_literal: true module KDL module Types class Currency < Value::Custom # From https://en.wikipedia.org/wiki/ISO_4217#Active_codes CURRENCIES = { 'AED' => { numeric_code: 784, minor_unit: 2, name: 'United Arab Emirates dirham' }.freeze, 'AFN' => { numeric_code: 971, minor_unit: 2, name: 'Afghan afghani' }.freeze, 'ALL' => { numeric_code: 8, minor_unit: 2, name: 'Albanian lek' }.freeze, 'AMD' => { numeric_code: 51, minor_unit: 2, name: 'Armenian dram' }.freeze, 'ANG' => { numeric_code: 532, minor_unit: 2, name: 'Netherlands Antillean guilder' }.freeze, 'AOA' => { numeric_code: 973, minor_unit: 2, name: 'Angolan kwanza' }.freeze, 'ARS' => { numeric_code: 32, minor_unit: 2, name: 'Argentine peso' }.freeze, 'AUD' => { numeric_code: 36, minor_unit: 2, name: 'Australian dollar' }.freeze, 'AWG' => { numeric_code: 533, minor_unit: 2, name: 'Aruban florin' }.freeze, 'AZN' => { numeric_code: 944, minor_unit: 2, name: 'Azerbaijani manat' }.freeze, 'BAM' => { numeric_code: 977, minor_unit: 2, name: 'Bosnia and Herzegovina convertible mark' }.freeze, 'BBD' => { numeric_code: 52, minor_unit: 2, name: 'Barbados dollar' }.freeze, 'BDT' => { numeric_code: 50, minor_unit: 2, name: 'Bangladeshi taka' }.freeze, 'BGN' => { numeric_code: 975, minor_unit: 2, name: 'Bulgarian lev' }.freeze, 'BHD' => { numeric_code: 48, minor_unit: 3, name: 'Bahraini dinar' }.freeze, 'BIF' => { numeric_code: 108, minor_unit: 0, name: 'Burundian franc' }.freeze, 'BMD' => { numeric_code: 60, minor_unit: 2, name: 'Bermudian dollar' }.freeze, 'BND' => { numeric_code: 96, minor_unit: 2, name: 'Brunei dollar' }.freeze, 'BOB' => { numeric_code: 68, minor_unit: 2, name: 'Boliviano' }.freeze, 'BOV' => { numeric_code: 984, minor_unit: 2, name: 'Bolivian Mvdol (funds code)' }.freeze, 'BRL' => { numeric_code: 986, minor_unit: 2, name: 'Brazilian real' }.freeze, 'BSD' => { numeric_code: 44, minor_unit: 2, name: 'Bahamian dollar' }.freeze, 'BTN' => { numeric_code: 64, minor_unit: 2, name: 'Bhutanese ngultrum' }.freeze, 'BWP' => { numeric_code: 72, minor_unit: 2, name: 'Botswana pula' }.freeze, 'BYN' => { numeric_code: 933, minor_unit: 2, name: 'Belarusian ruble' }.freeze, 'BZD' => { numeric_code: 84, minor_unit: 2, name: 'Belize dollar' }.freeze, 'CAD' => { numeric_code: 124, minor_unit: 2, name: 'Canadian dollar' }.freeze, 'CDF' => { numeric_code: 976, minor_unit: 2, name: 'Congolese franc' }.freeze, 'CHE' => { numeric_code: 947, minor_unit: 2, name: 'WIR euro (complementary currency)' }.freeze, 'CHF' => { numeric_code: 756, minor_unit: 2, name: 'Swiss franc' }.freeze, 'CHW' => { numeric_code: 948, minor_unit: 2, name: 'WIR franc (complementary currency)' }.freeze, 'CLF' => { numeric_code: 990, minor_unit: 4, name: 'Unidad de Fomento (funds code)' }.freeze, 'CLP' => { numeric_code: 152, minor_unit: 0, name: 'Chilean peso' }.freeze, 'CNY' => { numeric_code: 156, minor_unit: 2, name: 'Chinese yuan[8]' }.freeze, 'COP' => { numeric_code: 170, minor_unit: 2, name: 'Colombian peso' }.freeze, 'COU' => { numeric_code: 970, minor_unit: 2, name: 'Unidad de Valor Real (UVR) (funds code)' }.freeze, 'CRC' => { numeric_code: 188, minor_unit: 2, name: 'Costa Rican colon' }.freeze, 'CUC' => { numeric_code: 931, minor_unit: 2, name: 'Cuban convertible peso' }.freeze, 'CUP' => { numeric_code: 192, minor_unit: 2, name: 'Cuban peso' }.freeze, 'CVE' => { numeric_code: 132, minor_unit: 2, name: 'Cape Verdean escudo' }.freeze, 'CZK' => { numeric_code: 203, minor_unit: 2, name: 'Czech koruna' }.freeze, 'DJF' => { numeric_code: 262, minor_unit: 0, name: 'Djiboutian franc' }.freeze, 'DKK' => { numeric_code: 208, minor_unit: 2, name: 'Danish krone' }.freeze, 'DOP' => { numeric_code: 214, minor_unit: 2, name: 'Dominican peso' }.freeze, 'DZD' => { numeric_code: 12, minor_unit: 2, name: 'Algerian dinar' }.freeze, 'EGP' => { numeric_code: 818, minor_unit: 2, name: 'Egyptian pound' }.freeze, 'ERN' => { numeric_code: 232, minor_unit: 2, name: 'Eritrean nakfa' }.freeze, 'ETB' => { numeric_code: 230, minor_unit: 2, name: 'Ethiopian birr' }.freeze, 'EUR' => { numeric_code: 978, minor_unit: 2, name: 'Euro' }.freeze, 'FJD' => { numeric_code: 242, minor_unit: 2, name: 'Fiji dollar' }.freeze, 'FKP' => { numeric_code: 238, minor_unit: 2, name: 'Falkland Islands pound' }.freeze, 'GBP' => { numeric_code: 826, minor_unit: 2, name: 'Pound sterling' }.freeze, 'GEL' => { numeric_code: 981, minor_unit: 2, name: 'Georgian lari' }.freeze, 'GHS' => { numeric_code: 936, minor_unit: 2, name: 'Ghanaian cedi' }.freeze, 'GIP' => { numeric_code: 292, minor_unit: 2, name: 'Gibraltar pound' }.freeze, 'GMD' => { numeric_code: 270, minor_unit: 2, name: 'Gambian dalasi' }.freeze, 'GNF' => { numeric_code: 324, minor_unit: 0, name: 'Guinean franc' }.freeze, 'GTQ' => { numeric_code: 320, minor_unit: 2, name: 'Guatemalan quetzal' }.freeze, 'GYD' => { numeric_code: 328, minor_unit: 2, name: 'Guyanese dollar' }.freeze, 'HKD' => { numeric_code: 344, minor_unit: 2, name: 'Hong Kong dollar' }.freeze, 'HNL' => { numeric_code: 340, minor_unit: 2, name: 'Honduran lempira' }.freeze, 'HRK' => { numeric_code: 191, minor_unit: 2, name: 'Croatian kuna' }.freeze, 'HTG' => { numeric_code: 332, minor_unit: 2, name: 'Haitian gourde' }.freeze, 'HUF' => { numeric_code: 348, minor_unit: 2, name: 'Hungarian forint' }.freeze, 'IDR' => { numeric_code: 360, minor_unit: 2, name: 'Indonesian rupiah' }.freeze, 'ILS' => { numeric_code: 376, minor_unit: 2, name: 'Israeli new shekel' }.freeze, 'INR' => { numeric_code: 356, minor_unit: 2, name: 'Indian rupee' }.freeze, 'IQD' => { numeric_code: 368, minor_unit: 3, name: 'Iraqi dinar' }.freeze, 'IRR' => { numeric_code: 364, minor_unit: 2, name: 'Iranian rial' }.freeze, 'ISK' => { numeric_code: 352, minor_unit: 0, name: 'Icelandic krรณna (plural: krรณnur)' }.freeze, 'JMD' => { numeric_code: 388, minor_unit: 2, name: 'Jamaican dollar' }.freeze, 'JOD' => { numeric_code: 400, minor_unit: 3, name: 'Jordanian dinar' }.freeze, 'JPY' => { numeric_code: 392, minor_unit: 0, name: 'Japanese yen' }.freeze, 'KES' => { numeric_code: 404, minor_unit: 2, name: 'Kenyan shilling' }.freeze, 'KGS' => { numeric_code: 417, minor_unit: 2, name: 'Kyrgyzstani som' }.freeze, 'KHR' => { numeric_code: 116, minor_unit: 2, name: 'Cambodian riel' }.freeze, 'KMF' => { numeric_code: 174, minor_unit: 0, name: 'Comoro franc' }.freeze, 'KPW' => { numeric_code: 408, minor_unit: 2, name: 'North Korean won' }.freeze, 'KRW' => { numeric_code: 410, minor_unit: 0, name: 'South Korean won' }.freeze, 'KWD' => { numeric_code: 414, minor_unit: 3, name: 'Kuwaiti dinar' }.freeze, 'KYD' => { numeric_code: 136, minor_unit: 2, name: 'Cayman Islands dollar' }.freeze, 'KZT' => { numeric_code: 398, minor_unit: 2, name: 'Kazakhstani tenge' }.freeze, 'LAK' => { numeric_code: 418, minor_unit: 2, name: 'Lao kip' }.freeze, 'LBP' => { numeric_code: 422, minor_unit: 2, name: 'Lebanese pound' }.freeze, 'LKR' => { numeric_code: 144, minor_unit: 2, name: 'Sri Lankan rupee' }.freeze, 'LRD' => { numeric_code: 430, minor_unit: 2, name: 'Liberian dollar' }.freeze, 'LSL' => { numeric_code: 426, minor_unit: 2, name: 'Lesotho loti' }.freeze, 'LYD' => { numeric_code: 434, minor_unit: 3, name: 'Libyan dinar' }.freeze, 'MAD' => { numeric_code: 504, minor_unit: 2, name: 'Moroccan dirham' }.freeze, 'MDL' => { numeric_code: 498, minor_unit: 2, name: 'Moldovan leu' }.freeze, 'MGA' => { numeric_code: 969, minor_unit: 2, name: 'Malagasy ariary' }.freeze, 'MKD' => { numeric_code: 807, minor_unit: 2, name: 'Macedonian denar' }.freeze, 'MMK' => { numeric_code: 104, minor_unit: 2, name: 'Myanmar kyat' }.freeze, 'MNT' => { numeric_code: 496, minor_unit: 2, name: 'Mongolian tรถgrรถg' }.freeze, 'MOP' => { numeric_code: 446, minor_unit: 2, name: 'Macanese pataca' }.freeze, 'MRU' => { numeric_code: 929, minor_unit: 2, name: 'Mauritanian ouguiya' }.freeze, 'MUR' => { numeric_code: 480, minor_unit: 2, name: 'Mauritian rupee' }.freeze, 'MVR' => { numeric_code: 462, minor_unit: 2, name: 'Maldivian rufiyaa' }.freeze, 'MWK' => { numeric_code: 454, minor_unit: 2, name: 'Malawian kwacha' }.freeze, 'MXN' => { numeric_code: 484, minor_unit: 2, name: 'Mexican peso' }.freeze, 'MXV' => { numeric_code: 979, minor_unit: 2, name: 'Mexican Unidad de Inversion (UDI) (funds code)' }.freeze, 'MYR' => { numeric_code: 458, minor_unit: 2, name: 'Malaysian ringgit' }.freeze, 'MZN' => { numeric_code: 943, minor_unit: 2, name: 'Mozambican metical' }.freeze, 'NAD' => { numeric_code: 516, minor_unit: 2, name: 'Namibian dollar' }.freeze, 'NGN' => { numeric_code: 566, minor_unit: 2, name: 'Nigerian naira' }.freeze, 'NIO' => { numeric_code: 558, minor_unit: 2, name: 'Nicaraguan cรณrdoba' }.freeze, 'NOK' => { numeric_code: 578, minor_unit: 2, name: 'Norwegian krone' }.freeze, 'NPR' => { numeric_code: 524, minor_unit: 2, name: 'Nepalese rupee' }.freeze, 'NZD' => { numeric_code: 554, minor_unit: 2, name: 'New Zealand dollar' }.freeze, 'OMR' => { numeric_code: 512, minor_unit: 3, name: 'Omani rial' }.freeze, 'PAB' => { numeric_code: 590, minor_unit: 2, name: 'Panamanian balboa' }.freeze, 'PEN' => { numeric_code: 604, minor_unit: 2, name: 'Peruvian sol' }.freeze, 'PGK' => { numeric_code: 598, minor_unit: 2, name: 'Papua New Guinean kina' }.freeze, 'PHP' => { numeric_code: 608, minor_unit: 2, name: 'Philippine peso' }.freeze, 'PKR' => { numeric_code: 586, minor_unit: 2, name: 'Pakistani rupee' }.freeze, 'PLN' => { numeric_code: 985, minor_unit: 2, name: 'Polish zล‚oty' }.freeze, 'PYG' => { numeric_code: 600, minor_unit: 0, name: 'Paraguayan guaranรญ' }.freeze, 'QAR' => { numeric_code: 634, minor_unit: 2, name: 'Qatari riyal' }.freeze, 'RON' => { numeric_code: 946, minor_unit: 2, name: 'Romanian leu' }.freeze, 'RSD' => { numeric_code: 941, minor_unit: 2, name: 'Serbian dinar' }.freeze, 'RUB' => { numeric_code: 643, minor_unit: 2, name: 'Russian ruble' }.freeze, 'RWF' => { numeric_code: 646, minor_unit: 0, name: 'Rwandan franc' }.freeze, 'SAR' => { numeric_code: 682, minor_unit: 2, name: 'Saudi riyal' }.freeze, 'SBD' => { numeric_code: 90, minor_unit: 2, name: 'Solomon Islands dollar' }.freeze, 'SCR' => { numeric_code: 690, minor_unit: 2, name: 'Seychelles rupee' }.freeze, 'SDG' => { numeric_code: 938, minor_unit: 2, name: 'Sudanese pound' }.freeze, 'SEK' => { numeric_code: 752, minor_unit: 2, name: 'Swedish krona (plural: kronor)' }.freeze, 'SGD' => { numeric_code: 702, minor_unit: 2, name: 'Singapore dollar' }.freeze, 'SHP' => { numeric_code: 654, minor_unit: 2, name: 'Saint Helena pound' }.freeze, 'SLL' => { numeric_code: 694, minor_unit: 2, name: 'Sierra Leonean leone' }.freeze, 'SOS' => { numeric_code: 706, minor_unit: 2, name: 'Somali shilling' }.freeze, 'SRD' => { numeric_code: 968, minor_unit: 2, name: 'Surinamese dollar' }.freeze, 'SSP' => { numeric_code: 728, minor_unit: 2, name: 'South Sudanese pound' }.freeze, 'STN' => { numeric_code: 930, minor_unit: 2, name: 'Sรฃo Tomรฉ and Prรญncipe dobra' }.freeze, 'SVC' => { numeric_code: 222, minor_unit: 2, name: 'Salvadoran colรณn' }.freeze, 'SYP' => { numeric_code: 760, minor_unit: 2, name: 'Syrian pound' }.freeze, 'SZL' => { numeric_code: 748, minor_unit: 2, name: 'Swazi lilangeni' }.freeze, 'THB' => { numeric_code: 764, minor_unit: 2, name: 'Thai baht' }.freeze, 'TJS' => { numeric_code: 972, minor_unit: 2, name: 'Tajikistani somoni' }.freeze, 'TMT' => { numeric_code: 934, minor_unit: 2, name: 'Turkmenistan manat' }.freeze, 'TND' => { numeric_code: 788, minor_unit: 3, name: 'Tunisian dinar' }.freeze, 'TOP' => { numeric_code: 776, minor_unit: 2, name: 'Tongan paสปanga' }.freeze, 'TRY' => { numeric_code: 949, minor_unit: 2, name: 'Turkish lira' }.freeze, 'TTD' => { numeric_code: 780, minor_unit: 2, name: 'Trinidad and Tobago dollar' }.freeze, 'TWD' => { numeric_code: 901, minor_unit: 2, name: 'New Taiwan dollar' }.freeze, 'TZS' => { numeric_code: 834, minor_unit: 2, name: 'Tanzanian shilling' }.freeze, 'UAH' => { numeric_code: 980, minor_unit: 2, name: 'Ukrainian hryvnia' }.freeze, 'UGX' => { numeric_code: 800, minor_unit: 0, name: 'Ugandan shilling' }.freeze, 'USD' => { numeric_code: 840, minor_unit: 2, name: 'United States dollar' }.freeze, 'USN' => { numeric_code: 997, minor_unit: 2, name: 'United States dollar (next day) (funds code)' }.freeze, 'UYI' => { numeric_code: 940, minor_unit: 0, name: 'Uruguay Peso en Unidades Indexadas (URUIURUI) (funds code)' }.freeze, 'UYU' => { numeric_code: 858, minor_unit: 2, name: 'Uruguayan peso' }.freeze, 'UYW' => { numeric_code: 927, minor_unit: 4, name: 'Unidad previsional' }.freeze, 'UZS' => { numeric_code: 860, minor_unit: 2, name: 'Uzbekistan som' }.freeze, 'VED' => { numeric_code: 926, minor_unit: 2, name: 'Venezuelan bolรญvar digital' }.freeze, 'VES' => { numeric_code: 928, minor_unit: 2, name: 'Venezuelan bolรญvar soberano' }.freeze, 'VND' => { numeric_code: 704, minor_unit: 0, name: 'Vietnamese ฤ‘แป“ng' }.freeze, 'VUV' => { numeric_code: 548, minor_unit: 0, name: 'Vanuatu vatu' }.freeze, 'WST' => { numeric_code: 882, minor_unit: 2, name: 'Samoan tala' }.freeze, 'XAF' => { numeric_code: 950, minor_unit: 0, name: 'CFA franc BEAC' }.freeze, 'XAG' => { numeric_code: 961, minor_unit: nil, name: 'Silver (one troy ounce)' }.freeze, 'XAU' => { numeric_code: 959, minor_unit: nil, name: 'Gold (one troy ounce)' }.freeze, 'XBA' => { numeric_code: 955, minor_unit: nil, name: 'European Composite Unit (EURCO) (bond market unit)' }.freeze, 'XBB' => { numeric_code: 956, minor_unit: nil, name: 'European Monetary Unit (E.M.U.-6) (bond market unit)' }.freeze, 'XBC' => { numeric_code: 957, minor_unit: nil, name: 'European Unit of Account 9 (E.U.A.-9) (bond market unit)' }.freeze, 'XBD' => { numeric_code: 958, minor_unit: nil, name: 'European Unit of Account 17 (E.U.A.-17) (bond market unit)' }.freeze, 'XCD' => { numeric_code: 951, minor_unit: 2, name: 'East Caribbean dollar' }.freeze, 'XDR' => { numeric_code: 960, minor_unit: nil, name: 'Special drawing rights' }.freeze, 'XOF' => { numeric_code: 952, minor_unit: 0, name: 'CFA franc BCEAO' }.freeze, 'XPD' => { numeric_code: 964, minor_unit: nil, name: 'Palladium (one troy ounce)' }.freeze, 'XPF' => { numeric_code: 953, minor_unit: 0, name: 'CFP franc (franc Pacifique)' }.freeze, 'XPT' => { numeric_code: 962, minor_unit: nil, name: 'Platinum (one troy ounce)' }.freeze, 'XSU' => { numeric_code: 994, minor_unit: nil, name: 'SUCRE' }.freeze, 'XTS' => { numeric_code: 963, minor_unit: nil, name: 'Code reserved for testing' }.freeze, 'XUA' => { numeric_code: 965, minor_unit: nil, name: 'ADB Unit of Account' }.freeze, 'XXX' => { numeric_code: 999, minor_unit: nil, name: 'No currency' }.freeze, 'YER' => { numeric_code: 886, minor_unit: 2, name: 'Yemeni rial' }.freeze, 'ZAR' => { numeric_code: 710, minor_unit: 2, name: 'South African rand' }.freeze, 'ZMW' => { numeric_code: 967, minor_unit: 2, name: 'Zambian kwacha' }.freeze, 'ZWL' => { numeric_code: 932, minor_unit: 2, name: 'Zimbabwean dollar' }.freeze }.freeze end end end danini-the-panini-kdl-rb-56d7cf1/lib/kdl/types/date_time.rb000066400000000000000000000021611515522600200235420ustar00rootroot00000000000000# frozen_string_literal: true require 'time' module KDL module Types class DateTime < Value::Custom def self.call(value, type = 'date-time') return nil unless value.is_a? ::KDL::Value::String time = ::Time.iso8601(value.value) new(time, type: type) end end MAPPING['date-time'] = DateTime class Time < Value::Custom # TODO: this is not a perfect ISO8601 time string REGEX = /^T?((?:2[0-3]|[01][0-9]):[0-5][0-9]:[0-5][0-9](?:\.[0-9]+)?(?:Z|[+-]\d\d:\d\d)?)$/ def self.call(value, type = 'time') return nil unless value.is_a? ::KDL::Value::String match = REGEX.match(value.value) raise ArgumentError, 'invalid time' if match.nil? time = ::Time.iso8601("#{::Date.today.iso8601}T#{match[1]}") new(time, type: type) end end MAPPING['time'] = Time class Date < Value::Custom def self.call(value, type = 'date') return nil unless value.is_a? ::KDL::Value::String date = ::Date.iso8601(value.value) new(date, type: type) end end MAPPING['date'] = Date end end danini-the-panini-kdl-rb-56d7cf1/lib/kdl/types/decimal.rb000066400000000000000000000005241515522600200232060ustar00rootroot00000000000000# frozen_string_literal: true module KDL module Types class Decimal < Value::Custom def self.call(value, type = 'decimal') return nil unless value.is_a? ::KDL::Value::String big_decimal = BigDecimal(value.value) new(big_decimal, type: type) end end MAPPING['decimal'] = Decimal end end danini-the-panini-kdl-rb-56d7cf1/lib/kdl/types/duration.rb000066400000000000000000000015161515522600200234370ustar00rootroot00000000000000# frozen_string_literal: true require 'kdl/types/duration/iso8601_parser' module KDL module Types class Duration < Value::Custom attr_reader :years, :months, :weeks, :days, :hours, :minutes, :seconds def initialize(parts = {}, format: nil, type: 'duration') super @years = parts.fetch(:years, 0) @months = parts.fetch(:months, 0) @weeks = parts.fetch(:weeks, 0) @days = parts.fetch(:days, 0) @hours = parts.fetch(:hours, 0) @minutes = parts.fetch(:minutes, 0) @seconds = parts.fetch(:seconds, 0) end def self.call(value, type = 'duration') return nil unless value.is_a? ::KDL::Value::String parts = ISO8601Parser.new(value.value).parse! new(parts, type: type) end end MAPPING['duration'] = Duration end end danini-the-panini-kdl-rb-56d7cf1/lib/kdl/types/duration/000077500000000000000000000000001515522600200231075ustar00rootroot00000000000000danini-the-panini-kdl-rb-56d7cf1/lib/kdl/types/duration/iso8601_parser.rb000066400000000000000000000114111515522600200261170ustar00rootroot00000000000000# frozen_string_literal: true # Shamelessly borrowed from https://github.com/rails/rails/tree/main/activesupport # # Copyright (c) 2005-2021 David Heinemeier Hansson # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. require 'strscan' module KDL module Types class Duration < Value::Custom # Parses a string formatted according to ISO 8601 Duration into the hash. # # See {ISO 8601}[https://en.wikipedia.org/wiki/ISO_8601#Durations] for more information. # # This parser allows negative parts to be present in pattern. class ISO8601Parser # :nodoc: class ParsingError < ::ArgumentError; end PERIOD_OR_COMMA = /\.|,/ PERIOD = '.' COMMA = ',' SIGN_MARKER = /\A-|\+|/ DATE_MARKER = /P/ TIME_MARKER = /T/ DATE_COMPONENT = /(-?\d+(?:[.,]\d+)?)(Y|M|D|W)/ TIME_COMPONENT = /(-?\d+(?:[.,]\d+)?)(H|M|S)/ DATE_TO_PART = { 'Y' => :years, 'M' => :months, 'W' => :weeks, 'D' => :days } TIME_TO_PART = { 'H' => :hours, 'M' => :minutes, 'S' => :seconds } DATE_COMPONENTS = %i[years months days] TIME_COMPONENTS = %i[hours minutes seconds] attr_reader :parts, :scanner attr_accessor :mode, :sign def initialize(string) @scanner = StringScanner.new(string) @parts = {} @mode = :start @sign = 1 end def parse! until finished? case mode when :start if scan(SIGN_MARKER) self.sign = scanner.matched == '-' ? -1 : 1 self.mode = :sign else raise_parsing_error end when :sign if scan(DATE_MARKER) self.mode = :date else raise_parsing_error end when :date if scan(TIME_MARKER) self.mode = :time elsif scan(DATE_COMPONENT) parts[DATE_TO_PART[scanner[2]]] = number * sign else raise_parsing_error end when :time if scan(TIME_COMPONENT) parts[TIME_TO_PART[scanner[2]]] = number * sign else raise_parsing_error end end end validate! parts end private def finished? scanner.eos? end # Parses number which can be a float with either comma or period. def number (PERIOD_OR_COMMA =~ scanner[1]) ? scanner[1].tr(COMMA, PERIOD).to_f : scanner[1].to_i end def scan(pattern) scanner.scan(pattern) end def raise_parsing_error(reason = nil) raise ParsingError, "Invalid ISO 8601 duration: #{scanner.string.inspect} #{reason}".strip end # Checks for various semantic errors as stated in ISO 8601 standard. def validate! raise_parsing_error('is empty duration') if parts.empty? # Mixing any of Y, M, D with W is invalid. if parts.key?(:weeks) && (parts.keys & DATE_COMPONENTS).any? raise_parsing_error('mixing weeks with other date parts not allowed') end # Specifying an empty T part is invalid. if mode == :time && (parts.keys & TIME_COMPONENTS).empty? raise_parsing_error('time part marker is present but time part is empty') end fractions = parts.values.reject(&:zero?).select { |a| (a % 1) != 0 } unless fractions.empty? || (fractions.size == 1 && fractions.last == @parts.values.reject(&:zero?).last) raise_parsing_error '(only last part can be fractional)' end true end end end end end danini-the-panini-kdl-rb-56d7cf1/lib/kdl/types/email.rb000066400000000000000000000022761515522600200227050ustar00rootroot00000000000000# frozen_string_literal: true require_relative './email/parser' module KDL module Types class Email < Value::Custom attr_reader :local, :domain def initialize(value, local:, domain:, **kwargs) super(value, **kwargs) @local = local @domain = domain end def self.call(value, type = 'email') return nil unless value.is_a? ::KDL::Value::String local, domain = Parser.new(value.value).parse new(value.value, type: type, local: local, domain: domain) end end MAPPING['email'] = Email class IDNEmail < Email attr_reader :unicode_domain def initialize(value, unicode_domain:, **kwargs) super(value, **kwargs) @unicode_domain = unicode_domain end def self.call(value, type = 'email') return nil unless value.is_a? ::KDL::Value::String local, domain, unicode_domain = Email::Parser.new(value.value, idn: true).parse new("#{local}@#{domain}", type: type, local: local, domain: domain, unicode_domain: unicode_domain) end def unicode_value "#{local}@#{unicode_domain}" end end MAPPING['idn-email'] = IDNEmail end end danini-the-panini-kdl-rb-56d7cf1/lib/kdl/types/email/000077500000000000000000000000001515522600200223515ustar00rootroot00000000000000danini-the-panini-kdl-rb-56d7cf1/lib/kdl/types/email/parser.rb000066400000000000000000000105461515522600200242000ustar00rootroot00000000000000# frozen_string_literal: true require_relative '../hostname/validator' module KDL module Types class Email < Value::Custom class Parser def initialize(string, idn: false) @string = string @idn = idn @tokenizer = Tokenizer.new(string, idn: idn) end def parse local = +'' unicode_domain = nil domain = nil context = :start loop do type, value = @tokenizer.next_token case type when :part case context when :start, :after_dot local << value context = :after_part else raise ArgumentError, "invalid email #{@string} (unexpected part #{value} at #{context})" end when :dot case context when :after_part local << value context = :after_dot else raise ArgumentError, "invalid email #{@string} (unexpected dot at #{context})" end when :at case context when :after_part context = :after_at end when :domain case context when :after_at validator = (@idn ? IDNHostname : Hostname)::Validator.new(value) raise ArgumentError, "invalid hostname #{value}" unless validator.valid? unicode_domain = validator.unicode domain = validator.ascii context = :after_domain else raise ArgumentError, "invalid email #{@string} (unexpected domain at #{context})" end when :end case context when :after_domain if local.size > 64 raise ArgumentError, "invalid email #{@string} (local part length #{local.size} exceeds maximaum of 64)" end return [local, domain, unicode_domain] else raise ArgumentError, "invalid email #{@string} (unexpected end at #{context})" end end end end end class Tokenizer LOCAL_PART_ASCII = %r{[a-zA-Z0-9!#$%&'*+\-/=?^_`{|}~]}.freeze LOCAL_PART_IDN = /[^\x00-\x1f ".@]/.freeze def initialize(string, idn: false) @string = string @idn = idn @index = 0 @after_at = false end def next_token if @after_at if @index < @string.size domain_start = @index @index = @string.size return [:domain, @string[domain_start..-1]] else return [:end, nil] end end @context = nil @buffer = +'' loop do c = @string[@index] return [:end, nil] if c.nil? case @context when nil case c when '.' @index += 1 return [:dot, '.'] when '@' @after_at = true @index += 1 return [:at, '@'] when '"' @context = :quote @index += 1 when local_part_chars @context = :part @buffer << c @index += 1 else raise ArgumentError, "invalid email #{@string} (unexpected #{c})" end when :part case c when local_part_chars @buffer << c @index += 1 when '.', '@' return [:part, @buffer] else raise ArgumentError, "invalid email #{@string} (unexpected #{c})" end when :quote case c when '"' n = @string[@index + 1] raise ArgumentError, "invalid email #{@string} (unexpected #{c})" unless n == '.' || n == '@' @index += 1 return [:part, @buffer] else @buffer << c @index += 1 end end end end def local_part_chars @idn ? LOCAL_PART_IDN : LOCAL_PART_ASCII end end end end end danini-the-panini-kdl-rb-56d7cf1/lib/kdl/types/hostname.rb000066400000000000000000000020251515522600200234240ustar00rootroot00000000000000# frozen_string_literal: true require_relative './hostname/validator' module KDL module Types class Hostname < Value::Custom def self.call(value, type = 'hostname') return nil unless value.is_a? ::KDL::Value::String validator = Validator.new(value.value) raise ArgumentError, "invalid hostname #{value}" unless validator.valid? new(value.value, type: type) end end MAPPING['hostname'] = Hostname class IDNHostname < Hostname attr_reader :unicode_value def initialize(value, unicode_value:, **kwargs) super(value, **kwargs) @unicode_value = unicode_value end def self.call(value, type = 'idn-hostname') return nil unless value.is_a? ::KDL::Value::String validator = Validator.new(value.value) raise ArgumentError, "invalid hostname #{value}" unless validator.valid? new(validator.ascii, type: type, unicode_value: validator.unicode) end end MAPPING['idn-hostname'] = IDNHostname end end danini-the-panini-kdl-rb-56d7cf1/lib/kdl/types/hostname/000077500000000000000000000000001515522600200231005ustar00rootroot00000000000000danini-the-panini-kdl-rb-56d7cf1/lib/kdl/types/hostname/validator.rb000066400000000000000000000022001515522600200254040ustar00rootroot00000000000000# frozen_string_literal: true require 'simpleidn' module KDL module Types class Hostname < Value::Custom class Validator PART_RGX = /^[a-z0-9_][a-z0-9_\-]{0,62}$/i attr_reader :string alias ascii string alias unicode string def initialize(string) @string = string end def valid? return false if @string.length > 253 @string.split('.').all? { |x| valid_part?(x) } end private def valid_part?(part) return false if part.empty? return false if part.start_with?('-') || part.end_with?('-') part =~ PART_RGX end end end class IDNHostname < Hostname class Validator < Hostname::Validator attr_reader :unicode def initialize(string) is_ascii = string.split('.').any? { |x| x.start_with?('xn--') } if is_ascii super(string) @unicode = SimpleIDN.to_unicode(string) else super(SimpleIDN.to_ascii(string)) @unicode = string end end end end end end danini-the-panini-kdl-rb-56d7cf1/lib/kdl/types/ip.rb000066400000000000000000000012101515522600200222110ustar00rootroot00000000000000# frozen_string_literal: true module KDL module Types class IP < Value::Custom def self.call(value, type = ip_type) return nil unless value.is_a? ::KDL::Value::String ip = ::IPAddr.new(value.value) raise ArgumentError, "invalid #{ip_type} address" unless valid_ip?(ip) new(ip, type: type) end def self.valid_ip?(ip) ip.__send__(:"#{ip_type}?") end end class IPV4 < IP def self.ip_type 'ipv4' end end MAPPING['ipv4'] = IPV4 class IPV6 < IP def self.ip_type 'ipv6' end end MAPPING['ipv6'] = IPV6 end end danini-the-panini-kdl-rb-56d7cf1/lib/kdl/types/irl.rb000066400000000000000000000023401515522600200223740ustar00rootroot00000000000000# frozen_string_literal: true require_relative './irl/parser' module KDL module Types class IRLReference < Value::Custom attr_reader :unicode_value, :unicode_domain, :unicode_path, :unicode_search, :unicode_hash def initialize(value, unicode_value:, unicode_domain:, unicode_path:, unicode_search:, unicode_hash:, **kwargs) super(value, **kwargs) @unicode_value = unicode_value @unicode_domain = unicode_domain @unicode_path = unicode_path @unicode_search = unicode_search @unicode_hash = unicode_hash end def self.call(value, type = 'irl-reference') return nil unless value.is_a? ::KDL::Value::String ascii_value, params = parser(value.value).parse new(URI.parse(ascii_value), type: type, **params) end def self.parser(string) IRLReference::Parser.new(string) end end MAPPING['irl-reference'] = IRLReference class IRL < IRLReference def self.call(value, type = 'irl') super(value, type) end def self.parser(string) IRL::Parser.new(string) end end MAPPING['irl'] = IRL end end danini-the-panini-kdl-rb-56d7cf1/lib/kdl/types/irl/000077500000000000000000000000001515522600200220505ustar00rootroot00000000000000danini-the-panini-kdl-rb-56d7cf1/lib/kdl/types/irl/parser.rb000066400000000000000000000076161515522600200237030ustar00rootroot00000000000000# frozen_string_literal: true module KDL module Types class IRLReference < Value::Custom class Parser RGX = /^(?:(?:([a-z][a-z0-9+.\-]+)):\/\/([^@]+@)?([^\/?#]+)?)?(\/?[^?#]*)?(?:\?([^#]*))?(?:#(.*))?$/i.freeze PERCENT_RGX = /%[a-f0-9]{2}/i.freeze RESERVED_URL_CHARS = %w[! # $ & ' ( ) * + , / : ; = ? @ \[ \] %] UNRESERVED_URL_CHARS = %w[A B C D E F G H I J K L M N O P Q R S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 8 9 - _ . ~].freeze URL_CHARS = RESERVED_URL_CHARS + UNRESERVED_URL_CHARS def initialize(string) @string = string end def parse scheme, auth, domain, path, search, hash = *parse_url if @string.ascii_only? unicode_path = Parser.decode(path) unicode_search = Parser.decode(search) unicode_hash = Parser.decode(hash) else unicode_path = path path = Parser.encode(unicode_path) unicode_search = search search_params = unicode_search ? unicode_search.split('&').map { |x| x.split('=') } : nil search = search_params ? search_params.map { |k, v| "#{Parser.encode(k)}=#{Parser.encode(v)}" }.join('&') : nil unicode_hash = hash hash = Parser.encode(hash) end if domain validator = IDNHostname::Validator.new(domain) domain = validator.ascii unicode_domain = validator.unicode else unicode_domain = domain end unicode_value = Parser.build_uri_string(scheme, auth, unicode_domain, unicode_path, unicode_search, unicode_hash) ascii_value = Parser.build_uri_string(scheme, auth, domain, path, search, hash) [ascii_value, { unicode_value: unicode_value, unicode_domain: unicode_domain, unicode_path: unicode_path, unicode_search: unicode_search, unicode_hash: unicode_hash }] end def parse_url match = RGX.match(@string) raise ArgumentError, "invalid IRL `#{@string}'" if match.nil? _, *parts = *match raise ArgumentError, "invalid IRL `#{@string}'" unless parts.all? { |part| Parser.valid_url_part?(part) } parts end def self.valid_url_part?(string) return true unless string string.chars.all? do |char| !char.ascii_only? || URL_CHARS.include?(char) end end def self.encode(string) return string unless string string.chars .map { |c| c.ascii_only? ? c : percent_encode(c) } .join .force_encoding('utf-8') end def self.decode(string) return string unless string string.gsub(PERCENT_RGX) do |match| char = match[1, 2].to_i(16).chr if RESERVED_URL_CHARS.include?(char) match else char end end.force_encoding('utf-8') end def self.percent_encode(c) c.bytes.map { |b| "%#{b.to_s(16)}" }.join.upcase end def self.build_uri_string(scheme, auth, domain, path, search, hash) string = +'' string << "#{scheme}://" if scheme string << auth if auth string << domain if domain string << path if path string << "?#{search}" if search string << "##{hash}" if hash string end end end class IRL < IRLReference class Parser < IRLReference::Parser def parse_url parts = super scheme, * = parts raise ArgumentError, "invalid IRL `#{@string}'" if scheme.nil? || scheme.empty? parts end end end end end danini-the-panini-kdl-rb-56d7cf1/lib/kdl/types/regex.rb000066400000000000000000000005021515522600200227160ustar00rootroot00000000000000# frozen_string_literal: true module KDL module Types class Regex < Value::Custom def self.call(value, type = 'regex') return nil unless value.is_a? ::KDL::Value::String regex = ::Regexp.new(value.value) new(regex, type: type) end end MAPPING['regex'] = Regex end end danini-the-panini-kdl-rb-56d7cf1/lib/kdl/types/url.rb000066400000000000000000000012601515522600200224100ustar00rootroot00000000000000# frozen_string_literal: true module KDL module Types class URLReference < Value::Custom def self.call(value, type = 'url-reference') return nil unless value.is_a? ::KDL::Value::String uri = parse_url(value.value) new(uri, type: type) end def self.parse_url(string) URI.parse(string) end end MAPPING['url-reference'] = URLReference class URL < URLReference def self.call(value, type = 'url') super(value, type) end def self.parse_url(string) super.tap do |uri| raise 'invalid URL' if uri.scheme.nil? end end end MAPPING['url'] = URL end end danini-the-panini-kdl-rb-56d7cf1/lib/kdl/types/url_template.rb000066400000000000000000000176071515522600200243170ustar00rootroot00000000000000# frozen_string_literal: true require 'uri' module KDL module Types class URLTemplate < Value::Custom UNRESERVED = /[a-zA-Z0-9\-._~]/.freeze RESERVED = %r{[:/?#\[\]@!$&'()*+,;=]}.freeze def self.call(value, type = 'url-template') return nil unless value.is_a? ::KDL::Value::String parts = Parser.parse(value.value) new(parts, type: type) end def expand(variables) result = value.map { |v| v.expand(variables) }.join parser = IRLReference::Parser.new(result) uri, * = parser.parse URI(uri) end class Parser def self.parse(string) new(string).parse end def initialize(string) @string = string @index = 0 end def parse result = [] until (token = next_token).nil? result << token end result end def next_token buffer = +'' context = nil expansion_type = nil loop do c = @string[@index] case context when nil case c when '{' context = :expansion buffer = +'' n = @string[@index + 1] expansion_type = case n when '+' then ReservedExpansion when '#' then FragmentExpansion when '.' then LabelExpansion when '/' then PathExpansion when ';' then ParameterExpansion when '?' then QueryExpansion when '&' then QueryContinuation else StringExpansion end @index += (expansion_type == StringExpansion ? 1 : 2) when nil then return nil else buffer = +c @index += 1 context = :literal end when :literal case c when '{', nil then return StringLiteral.new(buffer) else buffer << c @index += 1 end when :expansion case c when '}' @index += 1 return parse_expansion(buffer, expansion_type) when nil raise ArgumentError, 'unterminated expansion' else buffer << c @index += 1 end end end end def parse_expansion(string, type) variables = string.split(',').map do |str| case str when /(.*)\*$/ Variable.new(Regexp.last_match(1), explode: true, allow_reserved: type.allow_reserved?, with_name: type.with_name?, keep_empties: type.keep_empties?) when /(.*):(\d+)/ Variable.new(Regexp.last_match(1), limit: Regexp.last_match(2).to_i, allow_reserved: type.allow_reserved?, with_name: type.with_name?, keep_empties: type.keep_empties?) else Variable.new(str, allow_reserved: type.allow_reserved?, with_name: type.with_name?, keep_empties: type.keep_empties?) end end type.new(variables) end end class Variable attr_reader :name def initialize(name, limit: nil, explode: false, allow_reserved: false, with_name: false, keep_empties: false) @name = name.to_sym @limit = limit @explode = explode @allow_reserved = allow_reserved @with_name = with_name @keep_empties = keep_empties end def expand(value) if @explode case value when Array value.map { |v| prefix(encode(v)) } when Hash value.map { |k, v| prefix(encode(v), k) } else [prefix(encode(value))] end elsif @limit [prefix(limit(value))].compact else [prefix(flatten(value))].compact end end def limit(string) return nil unless string encode(string[0, @limit]) end def flatten(value) case value when String encode(value) when Array, Hash result = value.to_a .flatten .compact .map { |v| encode(v) } result.empty? ? nil : result.join(',') end end def encode(string) return nil unless string string.to_s .chars .map do |c| if UNRESERVED.match?(c) || (@allow_reserved && RESERVED.match?(c)) c else IRLReference::Parser.percent_encode(c) end end .join .force_encoding('utf-8') end def prefix(string, override = nil) return nil unless string key = override || @name if @with_name || override if string.empty? && !@keep_empties encode(key) else "#{encode(key)}=#{string}" end else string end end end class Part def expand_variables(values) @variables.reduce([]) do |list, variable| expanded = variable.expand(values[variable.name]) expanded ? list + expanded : list end end def separator ',' end def prefix '' end def self.allow_reserved? false end def self.with_name? false end def self.keep_empties? false end end class StringLiteral < Part def initialize(value) super() @value = value end def expand(*) @value end end class StringExpansion < Part def initialize(variables) super() @variables = variables end def expand(values) expanded = expand_variables(values) return '' if expanded.empty? prefix + expanded.join(separator) end end class ReservedExpansion < StringExpansion def self.allow_reserved? true end end class FragmentExpansion < StringExpansion def prefix '#' end def self.allow_reserved? true end end class LabelExpansion < StringExpansion def prefix '.' end def separator '.' end end class PathExpansion < StringExpansion def prefix '/' end def separator '/' end end class ParameterExpansion < StringExpansion def prefix ';' end def separator ';' end def self.with_name? true end end class QueryExpansion < StringExpansion def prefix '?' end def separator '&' end def self.with_name? true end def self.keep_empties? true end end class QueryContinuation < QueryExpansion def prefix '&' end end end MAPPING['url-template'] = URLTemplate end end danini-the-panini-kdl-rb-56d7cf1/lib/kdl/types/uuid.rb000066400000000000000000000007351515522600200225620ustar00rootroot00000000000000# frozen_string_literal: true module KDL module Types class UUID < Value::Custom RGX = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/ def self.call(value, type = 'uuid') return nil unless value.is_a? ::KDL::Value::String uuid = value.value.downcase raise ArgumentError, "`#{value.value}' is not a valid uuid" unless uuid =~ RGX new(uuid, type: type) end end MAPPING['uuid'] = UUID end end danini-the-panini-kdl-rb-56d7cf1/lib/kdl/v1.rb000066400000000000000000000003331515522600200207700ustar00rootroot00000000000000# frozen_string_literal: true require "kdl/v1/tokenizer" require "kdl/v1/document" require "kdl/v1/value" require "kdl/v1/node" require "kdl/v1/string_dumper" require "kdl/v1/kdl.tab" module KDL module V1 end end danini-the-panini-kdl-rb-56d7cf1/lib/kdl/v1/000077500000000000000000000000001515522600200204445ustar00rootroot00000000000000danini-the-panini-kdl-rb-56d7cf1/lib/kdl/v1/document.rb000066400000000000000000000004061515522600200226070ustar00rootroot00000000000000# frozen_string_literal: true module KDL module V1 class Document < ::KDL::Document def version 1 end def to_v1 self end def to_v2 ::KDL::Document.new(nodes.map(&:to_v2)) end end end end danini-the-panini-kdl-rb-56d7cf1/lib/kdl/v1/kdl.yy000066400000000000000000000077271515522600200216160ustar00rootroot00000000000000class KDL::V1::Parser options no_result_var token IDENT STRING RAWSTRING INTEGER FLOAT TRUE FALSE NULL WS NEWLINE LBRACE RBRACE LPAREN RPAREN EQUALS SEMICOLON EOF SLASHDASH rule document : nodes { @output_module::Document.new(val[0]) } | linespaces { @output_module::Document.new([]) } nodes : none { [] } | linespaces node { [val[1]] } | linespaces empty_node { [] } | nodes node { [*val[0], val[1]] } | nodes empty_node { val[0] } node : unterm_node node_term { val[0] } unterm_node : untyped_node { val[0] } | type untyped_node { val[1].as_type(val[0], @type_parsers.fetch(val[0], nil)) } untyped_node : node_decl { val[0].tap { |x| x.children = [] } } | node_decl node_children { val[0].tap { |x| x.children = val[1] } } | node_decl empty_childrens { val[0].tap { |x| x.children = [] } } | node_decl empty_childrens node_children { val[0].tap { |x| x.children = val[2] } } | node_decl node_children empty_childrens { val[0].tap { |x| x.children = val[1] } } | node_decl empty_childrens node_children empty_childrens { val[0].tap { |x| x.children = val[2] } } node_decl : identifier { @output_module::Node.new(val[0]) } | node_decl ws_plus value { val[0].tap { |x| x.arguments << val[2] } } | node_decl ws_plus slashdash value { val[0] } | node_decl ws_plus property { val[0].tap { |x| x.properties[val[2][0]] = val[2][1] } } | node_decl ws_plus slashdash property { val[0] } | node_decl ws_plus { val[0] } empty_node : slashdash node node_children : ws_star LBRACE nodes RBRACE { val[2] } | ws_star LBRACE linespaces RBRACE { [] } | ws_star LBRACE nodes unterm_node ws_star RBRACE { [*val[2], val[3]] } | ws_star LBRACE linespaces unterm_node ws_star RBRACE { [val[3]] } empty_children : slashdash node_children | ws_plus empty_children empty_childrens: empty_children | empty_childrens empty_children node_term: linespaces | semicolon_term semicolon_term: SEMICOLON | SEMICOLON linespaces slashdash: SLASHDASH | slashdash ws_plus | slashdash linespaces type : LPAREN ws_star identifier ws_star RPAREN { val[2] } identifier : IDENT { val[0].value } | STRING { val[0].value } | RAWSTRING { val[0].value } property : identifier EQUALS value { [val[0], val[2]] } value : untyped_value | type untyped_value { val[1].as_type(val[0], @type_parsers.fetch(val[0], nil)) } untyped_value : STRING { @output_module::Value::String.new(val[0].value) } | RAWSTRING { @output_module::Value::String.new(val[0].value) } | INTEGER { @output_module::Value::Int.new(val[0].value) } | FLOAT { @output_module::Value::Float.new(val[0].value, format: val[0].meta[:format]) } | boolean { @output_module::Value::Boolean.new(val[0]) } | NULL { @output_module::Value::Null } boolean : TRUE { true } | FALSE { false } ws_plus: WS | WS ws_plus ws_star: none | ws_plus linespace: WS | NEWLINE | EOF linespaces: linespace | linespaces linespace none: { nil } ---- inner include KDL::ParserCommon def parser_version 1 end def parse(str, filename: nil, **options) init(**options) @tokenizer = ::KDL::V1::Tokenizer.new(str, filename:) check_version do_parse end danini-the-panini-kdl-rb-56d7cf1/lib/kdl/v1/node.rb000066400000000000000000000010741515522600200217200ustar00rootroot00000000000000# frozen_string_literal: true module KDL module V1 class Node < ::KDL::Node def version 1 end def to_v1 self end def to_v2 ::KDL::Node.new(name, arguments: arguments.map(&:to_v2), properties: properties.transform_values(&:to_v2), children: children.map(&:to_v2), type: type ) end private def id_to_s(id, m = :to_s) return id.public_send(m) unless m == :to_s StringDumper.stringify_identifier(id) end end end end danini-the-panini-kdl-rb-56d7cf1/lib/kdl/v1/string_dumper.rb000066400000000000000000000011761515522600200236600ustar00rootroot00000000000000# frozen_string_literal: true module KDL module V1 module StringDumper include ::KDL::StringDumper def call(string) %("#{string.each_char.map { |char| escape(char) }.join}") end def stringify_identifier(ident) if bare_identifier?(ident) ident else call(ident) end end private def bare_identifier?(name) escape_chars = '\\\/(){}<>;\[\]=,"' name =~ /^([^0-9\-+\s#{escape_chars}][^\s#{escape_chars}]*|[\-+](?!true|false|null)[^0-9\s#{escape_chars}][^\s#{escape_chars}]*)$/ end extend self end end end danini-the-panini-kdl-rb-56d7cf1/lib/kdl/v1/tokenizer.rb000066400000000000000000000220511515522600200230030ustar00rootroot00000000000000# frozen_string_literal: true module KDL module V1 class Tokenizer < KDL::Tokenizer NON_IDENTIFIER_CHARS = Regexp.escape "#{SYMBOLS.keys.join}()/\\<>[]\",#{WHITESPACE.join}#{OTHER_NON_IDENTIFIER_CHARS.join}" IDENTIFIER_CHARS = /[^#{NON_IDENTIFIER_CHARS}]/ INITIAL_IDENTIFIER_CHARS = /[^#{NON_IDENTIFIER_CHARS}0-9]/ def next_token @context = nil @previous_context = nil @line_at_start = @line @column_at_start = @column loop do c = self[@index] case @context when nil case c when '"' self.context = :string @buffer = +'' traverse(1) when 'r' if @str[@index + 1] == '"' self.context = :rawstring traverse(2) @rawstring_hashes = 0 @buffer = +'' next elsif @str[@index + 1] == '#' i = @index + 1 @rawstring_hashes = 0 while @str[i] == '#' @rawstring_hashes += 1 i += 1 end if @str[i] == '"' self.context = :rawstring @index = i + 1 @buffer = +'' next end end self.context = :ident @buffer = +c traverse(1) when '-' n = self[@index + 1] if n =~ /[0-9]/ n2 = self[@index + 2] if n == '0' && n2 =~ /[box]/ self.context = integer_context(n2) traverse(3) else self.context = :decimal traverse(1) end else self.context = :ident traverse(1) end @buffer = +c when /[0-9+]/ n = self[@index + 1] if c == '0' && n =~ /[box]/ traverse(2) @buffer = +'' self.context = integer_context(n) else self.context = :decimal @buffer = +c traverse(1) end when '\\' t = Tokenizer.new(@str, @index + 1) la = t.next_token if la[0] == :NEWLINE || la[0] == :EOF || (la[0] == :WS && (lan = t.next_token[0]) == :NEWLINE || lan == :EOF) traverse_to(t.index) @buffer = "#{c}#{la[1].value}" @buffer << "\n" if lan == :NEWLINE self.context = :whitespace else raise_error "Unexpected '\\' (#{la[0]})" end when *SYMBOLS.keys return token(SYMBOLS[c], -c).tap { traverse(1) } when *NEWLINES, "\r" nl = expect_newline return token(:NEWLINE, -nl).tap do traverse(nl.length) end when "/" if self[@index + 1] == '/' self.context = :single_line_comment traverse(2) elsif self[@index + 1] == '*' self.context = :multi_line_comment @comment_nesting = 1 traverse(2) elsif self[@index + 1] == '-' return token(:SLASHDASH, '/-').tap { traverse(2) } else self.context = :ident @buffer = +c traverse(1) end when *WHITESPACE self.context = :whitespace @buffer = +c traverse(1) when nil return [false, token(:EOF, :EOF)[1]] if @done @done = true return token(:EOF, :EOF) when INITIAL_IDENTIFIER_CHARS self.context = :ident @buffer = +c traverse(1) when '(' @type_context = true return token(:LPAREN, -c).tap { traverse(1) } when ')' @type_context = false return token(:RPAREN, -c).tap { traverse(1) } else raise_error "Unexpected character #{c.inspect}" end when :ident case c when IDENTIFIER_CHARS traverse(1) @buffer << c else case @buffer when 'true' then return token(:TRUE, true) when 'false' then return token(:FALSE, false) when 'null' then return token(:NULL, nil) else return token(:IDENT, -@buffer) end end when :string case c when '\\' c2 = self[@index + 1] if c2.match?(NEWLINES_PATTERN) i = 2 while self[@index + i].match?(NEWLINES_PATTERN) i+=1 end traverse(i) else @buffer << c @buffer << c2 traverse(2) end when '"' return token(:STRING, -unescape(@buffer)).tap { traverse(1) } when nil raise_error "Unterminated string literal" else @buffer << c traverse(1) end when :rawstring raise_error "Unterminated rawstring literal" if c.nil? if c == '"' h = 0 h += 1 while self[@index + 1 + h] == '#' && h < @rawstring_hashes if h == @rawstring_hashes return token(:RAWSTRING, -@buffer).tap { traverse(1 + h) } end end @buffer << c traverse(1) when :decimal case c when /[0-9.\-+_eE]/ traverse(1) @buffer << c else return parse_decimal(@buffer) end when :hexadecimal case c when /[0-9a-fA-F_]/ traverse(1) @buffer << c else return parse_hexadecimal(@buffer) end when :octal case c when /[0-7_]/ traverse(1) @buffer << c else return parse_octal(@buffer) end when :binary case c when /[01_]/ traverse(1) @buffer << c else return parse_binary(@buffer) end when :single_line_comment case c when *NEWLINES, "\r" self.context = nil @column_at_start = @column next when nil @done = true return token(:EOF, :EOF) else traverse(1) end when :multi_line_comment if c == '/' && self[@index + 1] == '*' @comment_nesting += 1 traverse(2) elsif c == '*' && self[@index + 1] == '/' @comment_nesting -= 1 traverse(2) if @comment_nesting == 0 revert_context end else traverse(1) end when :whitespace if WHITESPACE.include?(c) traverse(1) @buffer << c elsif c == "/" && self[@index + 1] == '*' self.context = :multi_line_comment @comment_nesting = 1 traverse(2) elsif c == "\\" t = Tokenizer.new(@str, @index + 1) la = t.next_token if la[0] == :NEWLINE || la[0] == :EOF || (la[0] == :WS && (lan = t.next_token[0]) == :NEWLINE || lan == :EOF) traverse_to(t.index) @buffer << "#{c}#{la[1].value}" @buffer << "\n" if lan == :NEWLINE else raise_error "Unexpected '\\' (#{la[0]})" end else return token(:WS, -@buffer) end else # :nocov: raise_error "Unknown context `#{@context}'" # :nocov: end end end private def allowed_in_type?(val) %i[ident string rawstring].include?(val) end def allowed_after_type?(val) !%i[single_line_comment multi_line_comment].include?(val) end def unescape(string) string.gsub(/\\[^u]/) do |m| case m when '\n' then "\n" when '\r' then "\r" when '\t' then "\t" when '\\\\' then "\\" when '\"' then "\"" when '\b' then "\b" when '\f' then "\f" when '\/' then "/" else raise_error "Unexpected escape #{m.inspect}" end end.gsub(/\\u\{[0-9a-fA-F]{0,6}\}/) do |m| i = Integer(m[3..-2], 16) if i < 0 || i > 0x10FFFF raise_error "Invalid code point #{u}" end i.chr(Encoding::UTF_8) end end end end end danini-the-panini-kdl-rb-56d7cf1/lib/kdl/v1/value.rb000066400000000000000000000036041515522600200221100ustar00rootroot00000000000000# frozen_string_literal: true module KDL module V1 class Value < ::KDL::Value module Methods def to_s return stringify_value unless type "(#{StringDumper.stringify_identifier type})#{stringify_value}" end def ==(other) return self == other.value if other.is_a?(self.class.superclass) value == other end def version 1 end def to_v1 self end def to_v2 self.class.superclass.new(value, format:, type:) end end include Methods class Int < ::KDL::Value::Int include Methods end class Float < ::KDL::Value::Float include Methods def stringify_value if value.nan? || value.infinite? warn "[WARNING] Attempting to serialize non-finite Float using KDL v1" return Null.stringify_value end super end end class Boolean < ::KDL::Value::Boolean include Methods def stringify_value value.to_s end end class String < ::KDL::Value::String include Methods def stringify_value StringDumper.call(value) end end class NullImpl < ::KDL::Value::NullImpl include Methods def stringify_value "null" end def to_v2 type ? ::KDL::Value::NullImpl.new(type:) : ::KDL::Value::Null end end Null = NullImpl.new def self.from(value) case value when ::String then String.new(value) when Integer then Int.new(value) when ::Float then Float.new(value) when TrueClass, FalseClass then Boolean.new(value) when NilClass then Null else raise Error("unsupported value type: #{value.class}") end end end end end danini-the-panini-kdl-rb-56d7cf1/lib/kdl/value.rb000066400000000000000000000070721515522600200215650ustar00rootroot00000000000000# frozen_string_literal: true module KDL class Value attr_reader :value, :format, :type def initialize(value, format: nil, type: nil) @value = value @format = format @type = type end def as_type(type, parser = nil) if parser.nil? self.class.new(value, format: format, type: type) else result = parser.call(self, type) return self.as_type(type) if result.nil? unless result.is_a?(::KDL::Value::Custom) raise ArgumentError, "expected parser to return an instance of ::KDL::Value::Custom, got `#{result.class}'" end result end end def ==(other) return self == other.value if other.is_a?(self.class) value == other end def to_s return stringify_value unless type "(#{StringDumper.call type})#{stringify_value}" end def inspect return value.inspect unless type "(#{type.inspect})#{value.inspect}" end def stringify_value return format % value if format value.to_s end def version 2 end def to_v2 self end def method_missing(name, *args, **kwargs, &block) value.public_send(name, *args, **kwargs, &block) end def respond_to_missing?(name, include_all = false) value.respond_to?(name, include_all) end class Int < Value def to_v1 V1::Value::Int.new(value, format:, type:) end end class Float < Value def ==(other) return self == other.value if other.is_a?(Float) return other.nan? if value.nan? value == other end def stringify_value return '#nan' if value.nan? return '#inf' if value == ::Float::INFINITY return '#-inf' if value == -::Float::INFINITY return super.upcase unless value.is_a?(BigDecimal) sign, digits, _, exponent = value.split s = +'' s << '-' if sign.negative? s << "#{digits[0]}.#{digits[1..-1]}" s << "E#{exponent.negative? ? '' : '+'}#{exponent - 1}" s end def to_v1 if value.nan? || value.infinite? warn "[WARNING] Converting non-finite Float to KDL v1" end V1::Value::Float.new(value, format:, type:) end end class Boolean < Value def stringify_value "##{value}" end def to_v1 V1::Value::Boolean.new(value, format:, type:) end end class String < Value def stringify_value StringDumper.call(value) end def to_v1 V1::Value::String.new(value, format:, type:) end end class NullImpl < Value def initialize(_=nil, format: nil, type: nil) super(nil, type: type) end def stringify_value "#null" end def ==(other) other.is_a?(NullImpl) || other.nil? end def to_v1 type ? V1::Value::NullImpl.new(type:) : V1::Value::Null end end Null = NullImpl.new class Custom < Value attr_reader :oriinal_value def self.call(value, type) new(value, type:) end def version nil end def to_v1 self end def to_v2 self end end def self.from(value) case value when ::String then String.new(value) when Integer then Int.new(value) when ::Float then Float.new(value) when TrueClass, FalseClass then Boolean.new(value) when NilClass then Null else raise Error, "unsupported value type: #{value.class}" end end end end danini-the-panini-kdl-rb-56d7cf1/lib/kdl/version.rb000066400000000000000000000001021515522600200221210ustar00rootroot00000000000000# frozen_string_literal: true module KDL VERSION = "2.2.0" end danini-the-panini-kdl-rb-56d7cf1/test/000077500000000000000000000000001515522600200175555ustar00rootroot00000000000000danini-the-panini-kdl-rb-56d7cf1/test/builder_test.rb000066400000000000000000000033721515522600200225740ustar00rootroot00000000000000# frozen_string_literal: true require "test_helper" class BuilderTest < Minitest::Test def test_build doc = KDL.build do |kdl| kdl.node "foo" kdl.node "bar", type: "baz" kdl.node "qux" do kdl.arg 123 kdl.prop "norf", "wat" kdl.prop "when", "2025-01-30", type: "date" kdl.node "child" end end assert_equal <<~KDL, doc.to_s foo (baz)bar qux 123 norf=wat when=(date)"2025-01-30" { child } KDL end def test_shorthand doc = KDL.build do |kdl| kdl.node "pokemon", "snorlax", { "Pokemon type" => "normal" }, "jigglypuff", level: 10, trainer: "Sylphrena" end assert_equal <<~KDL, doc.to_s pokemon snorlax jigglypuff "Pokemon type"=normal level=10 trainer=Sylphrena KDL end def test_implicit_block doc = KDL.build do node "foo" node "bar", type: "baz" node "qux" do arg 123 prop "norf", "wat" prop "when", "2025-01-30", type: "date" node "child" end end assert_equal <<~KDL, doc.to_s foo (baz)bar qux 123 norf=wat when=(date)"2025-01-30" { child } KDL end def test_magic_nodes doc = KDL.build do foo bar type: "baz" qux do arg 123 prop "norf", "wat" prop "when", "2025-01-30", type: "date" _ "child" end end assert_equal <<~KDL, doc.to_s foo (baz)bar qux 123 norf=wat when=(date)"2025-01-30" { child } KDL end def test_failures assert_raises do KDL.build do |kdl| kdl.prop foo: "bar" end end assert_raises do KDL.build do |kdl| kdl.arg "asdf" end end end end danini-the-panini-kdl-rb-56d7cf1/test/document_test.rb000066400000000000000000000061061515522600200227620ustar00rootroot00000000000000# frozen_string_literal: true require "test_helper" class DocumentTest < Minitest::Test def test_ref doc = KDL::Document.new([ KDL::Node.new("foo"), KDL::Node.new("bar") ]) assert_equal doc.nodes[0], doc[0] assert_equal doc.nodes[1], doc[1] assert_equal doc.nodes[0], doc["foo"] assert_equal doc.nodes[0], doc[:foo] assert_equal doc.nodes[1], doc[:bar] assert_raises { doc[nil] } end def test_arg doc = KDL::Document.new([ KDL::Node.new("foo", arguments: [KDL::Value::String.new("bar")]), KDL::Node.new("baz", arguments: [KDL::Value::String.new("qux")]) ]) assert_equal "bar", doc.arg(0) assert_equal "bar", doc.arg("foo") assert_equal "bar", doc.arg(:foo) assert_equal "qux", doc.arg(1) assert_equal "qux", doc.arg(:baz) assert_nil doc.arg(:norf) assert_raises { doc.arg(nil) } end def test_args doc = KDL::Document.new([ KDL::Node.new("foo", arguments: [KDL::Value::String.new("bar"), KDL::Value::String.new("baz")]), KDL::Node.new("qux", arguments: [KDL::Value::String.new("norf")]) ]) assert_equal ["bar", "baz"], doc.args(0) assert_equal ["bar", "baz"], doc.args("foo") assert_equal ["bar", "baz"], doc.args(:foo) assert_equal ["norf"], doc.args(1) assert_equal ["norf"], doc.args(:qux) assert_nil doc.args(:wat) a = []; doc.each_arg("foo") { a << _1 } assert_equal ["bar", "baz"], a a = []; doc.each_arg(:wat) { a << _1 } assert_equal [], a assert_raises { doc.arg(nil) } end def test_dash_vals doc = KDL::Document.new([ KDL::Node.new("node", children: [ KDL::Node.new("-", arguments: [KDL::Value::String.new("foo")]), KDL::Node.new("-", arguments: [KDL::Value::String.new("bar")]), KDL::Node.new("-", arguments: [KDL::Value::String.new("baz")]) ]) ]) assert_equal ["foo", "bar", "baz"], doc.dash_vals(0) assert_equal ["foo", "bar", "baz"], doc.dash_vals("node") assert_equal ["foo", "bar", "baz"], doc.dash_vals(:node) assert_nil doc.dash_vals(:nope) a = []; doc.each_dash_val("node") { a << _1 } assert_equal ["foo", "bar", "baz"], a a = []; doc.each_dash_val(:nope) { a << _1 } assert_equal [], a assert_raises { doc.dash_vals(nil) } end def test_each doc = KDL::Document.new([ KDL::Node.new("foo"), KDL::Node.new("bar") ]) a = []; doc.each { a << _1.name } assert_equal ["foo", "bar"], a end def test_inspect doc = KDL::Document.new([]) assert_kind_of String, doc.inspect end def test_version assert_equal 2, KDL::Document.new([]).version end def test_to_v1 doc = KDL.parse <<~KDL, version: 2 foo lorem 1 #true #null { bar """ baz qux """ } KDL assert_equal 2, doc.version doc = doc.to_v1 assert_equal 1, doc.version assert_equal <<~KDL, doc.to_s foo "lorem" 1 true null { bar " baz\\n qux" } KDL end def test_to_v2 doc = KDL::Document.new([]) assert_same doc, doc.to_v2 end end danini-the-panini-kdl-rb-56d7cf1/test/examples_test.rb000066400000000000000000000055071515522600200227660ustar00rootroot00000000000000# frozen_string_literal: true require "test_helper" class ExamplesTest < Minitest::Test def example_path(name) File.join(__dir__, "kdl-org/examples/#{name}.kdl") end def test_ci doc = ::KDL.load_file(example_path('ci')) nodes = KDL.build { name "CI" on "push", "pull_request" env { RUSTFLAGS("-Dwarnings") } jobs { fmt_and_docs("Check fmt & build docs") { _ "runs-on", "ubuntu-latest" steps { step uses: "actions/checkout@v1" step("Install Rust", uses: "actions-rs/toolchain@v1") { profile "minimal" toolchain "stable" components "rustfmt" override true } step("rustfmt") { run "cargo", "fmt", "--all", "--", "--check" } step("docs") { run "cargo", "doc", "--no-deps" } } } build_and_test("Build & Test") { _ "runs-on", "${{ matrix.os }}" strategy { matrix { rust "1.46.0", "stable" os "ubuntu-latest", "macOS-latest", "windows-latest" } } steps { step uses: "actions/checkout@v1" step("Install Rust", uses: "actions-rs/toolchain@v1") { profile "minimal" toolchain "${{ matrix.rust }}" components "clippy" override true } step("Clippy") { run "cargo", "clippy", "--all", "--", "-D", "warnings" } step("Run tests") { run "cargo", "test", "--all", "--verbose" } step "Other Stuff", run: "echo foo\necho bar\necho baz" } } } } assert_equal nodes, doc end def test_cargo doc = ::KDL.load_file(example_path('Cargo')) nodes = KDL.build { package { name "kdl" version "0.0.0" description "The kdl document language" authors "Kat Marchรกn " _ "license-file", "LICENSE.md" edition "2018" } dependencies { nom "6.0.1" thiserror "1.0.22" } } assert_equal nodes, doc end def test_nuget doc = ::KDL.load_file(example_path('nuget')) # This file is particularly large. It would be nice to validate it, but for now # I'm just going to settle for making sure it parses. refute_nil doc end def test_kdl_schema doc = ::KDL.load_file(example_path('kdl-schema')) # This file is particularly large. It would be nice to validate it, but for now # I'm just going to settle for making sure it parses. refute_nil doc end def test_website doc = ::KDL.load_file(example_path('website')) # This file is particularly large. It would be nice to validate it, but for now # I'm just going to settle for making sure it parses. refute_nil doc end end danini-the-panini-kdl-rb-56d7cf1/test/kdl-org/000077500000000000000000000000001515522600200211145ustar00rootroot00000000000000danini-the-panini-kdl-rb-56d7cf1/test/kdl_test.rb000066400000000000000000000010271515522600200217130ustar00rootroot00000000000000# frozen_string_literal: true require "test_helper" class KDLTest < Minitest::Test def test_that_it_has_a_version_number refute_nil ::KDL::VERSION end def test_parse_document assert_equal KDL.parse('node 1 2 3'), KDL.parse_document('node 1 2 3') end def test_unsupported_version assert_raises(KDL::UnsupportedVersionError) { KDL.parse('node 1 2 3', version: 3) } assert_raises(KDL::UnsupportedVersionError) do KDL.parse <<~KDL /- kdl-version 3 node 1 2 3 KDL end end end danini-the-panini-kdl-rb-56d7cf1/test/node_test.rb000066400000000000000000000122101515522600200220620ustar00rootroot00000000000000# frozen_string_literal: true require "test_helper" class NodeTest < Minitest::Test def test_ref node = KDL::Node.new("node", arguments: [v(1), v("two")], properties: { "three" => v(3), "four" => v(4) }) assert_equal 1, node[0] assert_equal "two", node[1] assert_nil node[2] assert_equal 3, node["three"] assert_equal 3, node[:three] assert_equal 4, node[:four] assert_raises { node[nil] } end def test_child node = KDL::Node.new("node", children: [ KDL::Node.new("foo"), KDL::Node.new("bar") ]) assert_equal node.children[0], node.child(0) assert_equal node.children[1], node.child(1) assert_equal node.children[0], node.child("foo") assert_equal node.children[0], node.child(:foo) assert_equal node.children[1], node.child(:bar) a = []; node.each { a << _1.name } assert_equal ["foo", "bar"], a assert_raises { node.child(nil) } end def test_arg node = KDL::Node.new("node", children: [ KDL::Node.new("foo", arguments: [KDL::Value::String.new("bar")]), KDL::Node.new("baz", arguments: [KDL::Value::String.new("qux")]) ]) assert_equal "bar", node.arg(0) assert_equal "bar", node.arg("foo") assert_equal "bar", node.arg(:foo) assert_equal "qux", node.arg(1) assert_equal "qux", node.arg(:baz) assert_nil node.arg(:norf) assert_raises { node.arg(nil) } end def test_args node = KDL::Node.new("node", children: [ KDL::Node.new("foo", arguments: [KDL::Value::String.new("bar"), KDL::Value::String.new("baz")]), KDL::Node.new("qux", arguments: [KDL::Value::String.new("norf")]) ]) assert_equal ["bar", "baz"], node.args(0) assert_equal ["bar", "baz"], node.args("foo") assert_equal ["bar", "baz"], node.args(:foo) assert_equal ["norf"], node.args(1) assert_equal ["norf"], node.args(:qux) assert_nil node.args(:wat) a = []; node.each_arg(:foo) { a << _1 } assert_equal ["bar", "baz"], a a = []; node.each_arg(:wat) { a << _1 } assert_equal [], a assert_raises { node.args(nil) } end def test_dash_vals node = KDL::Node.new("node", children: [ KDL::Node.new("node", children: [ KDL::Node.new("-", arguments: [KDL::Value::String.new("foo")]), KDL::Node.new("-", arguments: [KDL::Value::String.new("bar")]), KDL::Node.new("-", arguments: [KDL::Value::String.new("baz")]) ]) ]) assert_equal ["foo", "bar", "baz"], node.dash_vals(0) assert_equal ["foo", "bar", "baz"], node.dash_vals("node") assert_equal ["foo", "bar", "baz"], node.dash_vals(:node) assert_nil node.dash_vals(:nope) a = []; node.each_dash_val(:node) { a << _1 } assert_equal ["foo", "bar", "baz"], a a = []; node.each_dash_val(:nope) { a << _1 } assert_equal [], a assert_raises { node.dash_vals(nil) } end def test_to_s node = ::KDL::Node.new("foo", arguments: [v(1), v("two")], properties: { "three" => v(3) }) assert_equal 'foo 1 two three=3', node.to_s end def test_nested_to_s node = ::KDL::Node.new("a1", arguments: [v("a"), v(1)], properties: { a: v(1) }, children: [ ::KDL::Node.new("b1", arguments: [v("b"), v(1, "foo")], children: [ ::KDL::Node.new("c1", arguments: [v("c"), v(1)]) ]), ::KDL::Node.new("b2", arguments: [v("b")], properties: { c: v(2, "bar") }, children: [ ::KDL::Node.new("c2", arguments: [v("c"), v(2)]) ]), ::KDL::Node.new("b3", type: "baz"), ]) assert_equal <<~KDL.strip, node.to_s a1 a 1 a=1 { b1 b (foo)1 { c1 c 1 } b2 b c=(bar)2 { c2 c 2 } (baz)b3 } KDL assert_equal <<~KDL.strip, node.inspect "a1" "a" 1 "a"=1 { "b1" "b" ("foo")1 { "c1" "c" 1 } "b2" "b" "c"=("bar")2 { "c2" "c" 2 } ("baz")"b3" } KDL end def test_compare a = KDL::Node.new("a") b = KDL::Node.new("b") assert_equal -1, a <=> b assert_equal 1, b <=> a assert_equal 0, a <=> a end class Something < KDL::Node::Custom end def test_as_type node = KDL::Node.new("foo") assert_equal "bar", node.as_type("bar").type assert_kind_of Something, node.as_type("bar", lambda { |n, type| Something.new(n) }) nil_parse = node.as_type("bar", lambda { |n, type| nil }) assert_equal node, nil_parse assert_equal "bar", nil_parse.type assert_raises { node.as_type("bar", lambda { |n, type| Object.new }) } end def test_version node = KDL::Node.new("foo") assert_equal 2, node.version end def test_to_v1 node = KDL::Node.new("foo", arguments: [v(true)], properties: { bar: v("baz") }, children: [KDL::Node.new("qux")] ) node = node.to_v1 assert_equal 1, node.version assert_equal 1, node.arguments[0].version assert_equal 1, node.properties['bar'].version assert_equal 1, node.child(0).version end def test_to_v2 node = KDL::Node.new("foo") assert_same node, node.to_v2 end private def v(x, t=nil) val = ::KDL::Value.from(x) return val.as_type(t) if t val end end danini-the-panini-kdl-rb-56d7cf1/test/parser_test.rb000066400000000000000000000545311515522600200224450ustar00rootroot00000000000000# frozen_string_literal: true require "test_helper" class ParserTest < Minitest::Test def setup @parser = ::KDL::Parser.new end def test_parse_empty_string assert_equal ::KDL::Document.new([]), @parser.parse('') assert_equal ::KDL::Document.new([]), @parser.parse(' ') assert_equal ::KDL::Document.new([]), @parser.parse("\n") end def test_nodes assert_equal ::KDL::Document.new([::KDL::Node.new('node')]), @parser.parse('node') assert_equal ::KDL::Document.new([::KDL::Node.new('node')]), @parser.parse("node\n") assert_equal ::KDL::Document.new([::KDL::Node.new('node')]), @parser.parse("\nnode\n") assert_equal ::KDL::Document.new([::KDL::Node.new('node1'), ::KDL::Node.new('node2')]), @parser.parse("node1\nnode2") end def test_node assert_equal ::KDL::Document.new([::KDL::Node.new('node')]), @parser.parse('node;') assert_equal ::KDL::Document.new([::KDL::Node.new('node', arguments: [::KDL::Value::Int.new(1)])]), @parser.parse('node 1') assert_equal ::KDL::Document.new([::KDL::Node.new('node', arguments: [::KDL::Value::Int.new(1), ::KDL::Value::Int.new(2), ::KDL::Value::String.new("3"), ::KDL::Value::Boolean.new(true), ::KDL::Value::Boolean.new(false), ::KDL::Value::Null])]), @parser.parse('node 1 2 "3" #true #false #null') assert_equal ::KDL::Document.new([::KDL::Node.new('node', children: [::KDL::Node.new('node2')])]), @parser.parse("node {\n node2\n}") assert_equal ::KDL::Document.new([::KDL::Node.new('node', children: [::KDL::Node.new('node2')])]), @parser.parse("node {\n node2 \n}") assert_equal ::KDL::Document.new([::KDL::Node.new('node', children: [::KDL::Node.new('node2')])]), @parser.parse("node { node2; }") assert_equal ::KDL::Document.new([::KDL::Node.new('node', children: [::KDL::Node.new('node2')])]), @parser.parse("node { node2 }") assert_equal ::KDL::Document.new([::KDL::Node.new('node', children: [::KDL::Node.new('node2'), ::KDL::Node.new('node3')])]), @parser.parse("node { node2; node3 }") end def test_node_slashdash_comment assert_equal ::KDL::Document.new([]), @parser.parse('/-node') assert_equal ::KDL::Document.new([]), @parser.parse('/- node') assert_equal ::KDL::Document.new([]), @parser.parse("/- node\n") assert_equal ::KDL::Document.new([]), @parser.parse('/-node 1 2 3') assert_equal ::KDL::Document.new([]), @parser.parse('/-node key=#false') assert_equal ::KDL::Document.new([]), @parser.parse("/-node {\nnode\n}") assert_equal ::KDL::Document.new([]), @parser.parse("/-node 1 2 3 key=\"value\" \\\n{\nnode\n}") end def test_arg_slashdash_comment assert_equal ::KDL::Document.new([::KDL::Node.new('node')]), @parser.parse('node /-1') assert_equal ::KDL::Document.new([::KDL::Node.new('node', arguments: [::KDL::Value::Int.new(2)])]), @parser.parse('node /-1 2') assert_equal ::KDL::Document.new([::KDL::Node.new('node', arguments: [::KDL::Value::Int.new(1), ::KDL::Value::Int.new(3)])]), @parser.parse('node 1 /- 2 3') assert_equal ::KDL::Document.new([::KDL::Node.new('node')]), @parser.parse('node /--1') assert_equal ::KDL::Document.new([::KDL::Node.new('node')]), @parser.parse('node /- -1') assert_equal ::KDL::Document.new([::KDL::Node.new('node')]), @parser.parse("node \\\n/- -1") end def test_prop_slashdash_comment assert_equal ::KDL::Document.new([::KDL::Node.new('node')]), @parser.parse('node /-key=1') assert_equal ::KDL::Document.new([::KDL::Node.new('node')]), @parser.parse('node /- key=1') assert_equal ::KDL::Document.new([::KDL::Node.new('node', properties: { 'key' => ::KDL::Value::Int.new(1) })]), @parser.parse('node key=1 /-key2=2') end def test_children_slashdash_comment assert_equal ::KDL::Document.new([::KDL::Node.new('node')]), @parser.parse('node /-{}') assert_equal ::KDL::Document.new([::KDL::Node.new('node')]), @parser.parse('node /- {}') assert_equal ::KDL::Document.new([::KDL::Node.new('node')]), @parser.parse("node /-{\nnode2\n}") end def test_empty_children assert_equal ::KDL::Document.new([::KDL::Node.new('node')]), @parser.parse('node {}') assert_equal ::KDL::Document.new([::KDL::Node.new('node')]), @parser.parse("node {\n /-node2\n}") assert_equal ::KDL::Document.new([::KDL::Node.new('node')]), @parser.parse("node /-{\n node2\n}") end def test_string assert_equal ::KDL::Document.new([::KDL::Node.new('node', arguments: [::KDL::Value::String.new("")])]), @parser.parse('node ""') assert_equal ::KDL::Document.new([::KDL::Node.new('node', arguments: [::KDL::Value::String.new("hello")])]), @parser.parse('node "hello"') assert_equal ::KDL::Document.new([::KDL::Node.new('node', arguments: [::KDL::Value::String.new("hello\nworld")])]), @parser.parse('node "hello\\nworld"') assert_equal ::KDL::Document.new([::KDL::Node.new('node', arguments: [::KDL::Value::String.new("-flag")])]), @parser.parse('node -flag') assert_equal ::KDL::Document.new([::KDL::Node.new('node', arguments: [::KDL::Value::String.new("--flagg")])]), @parser.parse('node --flagg') assert_equal ::KDL::Document.new([::KDL::Node.new('node', arguments: [::KDL::Value::String.new("\u{10FFF}")])]), @parser.parse('node "\\u{10FFF}"') assert_equal ::KDL::Document.new([::KDL::Node.new('node', arguments: [::KDL::Value::String.new("\"\\\u{08}\u{0C}\n\r\t")])]), @parser.parse('node "\"\\\\\b\f\n\r\t"') assert_equal ::KDL::Document.new([::KDL::Node.new('node', arguments: [::KDL::Value::String.new("\u{10}")])]), @parser.parse('node "\u{10}"') assert_raises { @parser.parse('node "\i"') } assert_raises { @parser.parse('node "\u{c0ffee}"') } assert_raises { @parser.parse('node "oops') } end def test_unindented_multiline_strings assert_equal ::KDL::Document.new([::KDL::Node.new('node', arguments: [::KDL::Value::String.new("foo\nbar\n baz\nqux")])]), @parser.parse(%Q(node """\n foo\n bar\n baz\n qux\n """)) assert_equal ::KDL::Document.new([::KDL::Node.new('node', arguments: [::KDL::Value::String.new("foo\nbar\n baz\nqux")])]), @parser.parse(%Q(node #"""\n foo\n bar\n baz\n qux\n """#)) assert_raises { @parser.parse(%Q(node """\n foo\n bar\n baz\n """))} assert_raises { @parser.parse(%Q(node #"""\n foo\n bar\n baz\n """#))} end def test_float assert_equal ::KDL::Document.new([::KDL::Node.new('node', arguments: [::KDL::Value::Float.new(1.0)])]), @parser.parse('node 1.0') assert_equal ::KDL::Document.new([::KDL::Node.new('node', arguments: [::KDL::Value::Float.new(0.0)])]), @parser.parse('node 0.0') assert_equal ::KDL::Document.new([::KDL::Node.new('node', arguments: [::KDL::Value::Float.new(-1.0)])]), @parser.parse('node -1.0') assert_equal ::KDL::Document.new([::KDL::Node.new('node', arguments: [::KDL::Value::Float.new(1.0)])]), @parser.parse('node +1.0') assert_equal ::KDL::Document.new([::KDL::Node.new('node', arguments: [::KDL::Value::Float.new(1.0e10)])]), @parser.parse('node 1.0e10') assert_equal ::KDL::Document.new([::KDL::Node.new('node', arguments: [::KDL::Value::Float.new(1.0e-10)])]), @parser.parse('node 1.0e-10') assert_equal ::KDL::Document.new([::KDL::Node.new('node', arguments: [::KDL::Value::Float.new(123456789.0)])]), @parser.parse('node 123_456_789.0') assert_equal ::KDL::Document.new([::KDL::Node.new('node', arguments: [::KDL::Value::Float.new(123456789.0)])]), @parser.parse('node 123_456_789.0') assert_raises { @parser.parse('node 1._0') } assert_raises { @parser.parse('node 1.') } assert_raises { @parser.parse('node 1.0v2') } assert_raises { @parser.parse('node -1em') } assert_raises { @parser.parse('node .0') } end def test_integer assert_equal ::KDL::Document.new([::KDL::Node.new('node', arguments: [::KDL::Value::Int.new(0)])]), @parser.parse('node 0') assert_equal ::KDL::Document.new([::KDL::Node.new('node', arguments: [::KDL::Value::Int.new(123456789)])]), @parser.parse('node 0123456789') assert_equal ::KDL::Document.new([::KDL::Node.new('node', arguments: [::KDL::Value::Int.new(123456789)])]), @parser.parse('node 0123_456_789') assert_equal ::KDL::Document.new([::KDL::Node.new('node', arguments: [::KDL::Value::Int.new(123456789)])]), @parser.parse('node 0123_456_789_') assert_equal ::KDL::Document.new([::KDL::Node.new('node', arguments: [::KDL::Value::Int.new(123456789)])]), @parser.parse('node +0123456789') assert_equal ::KDL::Document.new([::KDL::Node.new('node', arguments: [::KDL::Value::Int.new(-123456789)])]), @parser.parse('node -0123456789') end def test_hexadecimal assert_equal ::KDL::Document.new([::KDL::Node.new('node', arguments: [::KDL::Value::Int.new(0x0123456789abcdef)])]), @parser.parse('node 0x0123456789abcdef') assert_equal ::KDL::Document.new([::KDL::Node.new('node', arguments: [::KDL::Value::Int.new(0x0123456789abcdef)])]), @parser.parse('node 0x01234567_89abcdef') assert_equal ::KDL::Document.new([::KDL::Node.new('node', arguments: [::KDL::Value::Int.new(0x0123456789abcdef)])]), @parser.parse('node 0x01234567_89abcdef_') assert_raises { @parser.parse('node 0x_123') } assert_raises { @parser.parse('node 0xg') } assert_raises { @parser.parse('node 0xx') } end def test_octal assert_equal ::KDL::Document.new([::KDL::Node.new('node', arguments: [::KDL::Value::Int.new(0o01234567)])]), @parser.parse('node 0o01234567') assert_equal ::KDL::Document.new([::KDL::Node.new('node', arguments: [::KDL::Value::Int.new(0o01234567)])]), @parser.parse('node 0o0123_4567') assert_equal ::KDL::Document.new([::KDL::Node.new('node', arguments: [::KDL::Value::Int.new(0o01234567)])]), @parser.parse('node 0o01234567_') assert_raises { @parser.parse('node 0o_123') } assert_raises { @parser.parse('node 0o8') } assert_raises { @parser.parse('node 0oo') } end def test_binary assert_equal ::KDL::Document.new([::KDL::Node.new('node', arguments: [::KDL::Value::Int.new(0b0101)])]), @parser.parse('node 0b0101') assert_equal ::KDL::Document.new([::KDL::Node.new('node', arguments: [::KDL::Value::Int.new(0b0110)])]), @parser.parse('node 0b01_10') assert_equal ::KDL::Document.new([::KDL::Node.new('node', arguments: [::KDL::Value::Int.new(0b0110)])]), @parser.parse('node 0b01___10') assert_equal ::KDL::Document.new([::KDL::Node.new('node', arguments: [::KDL::Value::Int.new(0b0110)])]), @parser.parse('node 0b0110_') assert_raises { @parser.parse('node 0b_0110') } assert_raises { @parser.parse('node 0b20') } assert_raises { @parser.parse('node 0bb') } end def test_raw_string assert_equal ::KDL::Document.new([::KDL::Node.new('node', arguments: [::KDL::Value::String.new('foo')])]), @parser.parse('node #"foo"#') assert_equal ::KDL::Document.new([::KDL::Node.new('node', arguments: [::KDL::Value::String.new('foo\nbar')])]), @parser.parse('node #"foo\nbar"#') assert_equal ::KDL::Document.new([::KDL::Node.new('node', arguments: [::KDL::Value::String.new('foo')])]), @parser.parse('node #"foo"#') assert_equal ::KDL::Document.new([::KDL::Node.new('node', arguments: [::KDL::Value::String.new('foo')])]), @parser.parse('node ##"foo"##') assert_equal ::KDL::Document.new([::KDL::Node.new('node', arguments: [::KDL::Value::String.new('\nfoo\r')])]), @parser.parse('node #"\nfoo\r"#') assert_raises { @parser.parse('node ##"foo"#') } end def test_boolean assert_equal ::KDL::Document.new([::KDL::Node.new('node', arguments: [::KDL::Value::Boolean.new(true)])]), @parser.parse('node #true') assert_equal ::KDL::Document.new([::KDL::Node.new('node', arguments: [::KDL::Value::Boolean.new(false)])]), @parser.parse('node #false') assert_raises { @parser.parse('node true')} assert_raises { @parser.parse('node false')} end def test_null assert_equal ::KDL::Document.new([::KDL::Node.new('node', arguments: [::KDL::Value::Null])]), @parser.parse('node #null') assert_raises { @parser.parse('node null')} end def test_node_space assert_equal ::KDL::Document.new([::KDL::Node.new('node', arguments: [::KDL::Value::Int.new(1)])]), @parser.parse('node 1') assert_equal ::KDL::Document.new([::KDL::Node.new('node', arguments: [::KDL::Value::Int.new(1)])]), @parser.parse("node\t1") assert_equal ::KDL::Document.new([::KDL::Node.new('node', arguments: [::KDL::Value::Int.new(1)])]), @parser.parse("node\t \\ // hello\n 1") end def test_single_line_comment assert_equal ::KDL::Document.new([]), @parser.parse('//hello') assert_equal ::KDL::Document.new([]), @parser.parse("// \thello") assert_equal ::KDL::Document.new([]), @parser.parse("//hello\n") assert_equal ::KDL::Document.new([]), @parser.parse("//hello\r\n") assert_equal ::KDL::Document.new([]), @parser.parse("//hello\n\r") assert_equal ::KDL::Document.new([::KDL::Node.new('world')]), @parser.parse("//hello\rworld") assert_equal ::KDL::Document.new([::KDL::Node.new('world')]), @parser.parse("//hello\nworld\r\n") end def test_multi_line_comment assert_equal ::KDL::Document.new([]), @parser.parse("/*hello*/") assert_equal ::KDL::Document.new([]), @parser.parse("/*hello*/\n") assert_equal ::KDL::Document.new([]), @parser.parse("/*\nhello\r\n*/") assert_equal ::KDL::Document.new([]), @parser.parse("/*\nhello** /\n*/") assert_equal ::KDL::Document.new([]), @parser.parse("/**\nhello** /\n*/") assert_equal ::KDL::Document.new([::KDL::Node.new('world')]), @parser.parse('/*hello*/world') end def test_escline assert_equal ::KDL::Document.new([::KDL::Node.new('node', arguments: [::KDL::Value.from(1)])]), @parser.parse("node\\\n 1") assert_equal ::KDL::Document.new([::KDL::Node.new('node', arguments: [::KDL::Value.from(1)])]), @parser.parse("node\\ // comment\n 1") assert_equal ::KDL::Document.new([::KDL::Node.new('node')]), @parser.parse("node\\\n") assert_equal ::KDL::Document.new([::KDL::Node.new('node')]), @parser.parse("node\\ \n") assert_equal ::KDL::Document.new([::KDL::Node.new('node')]), @parser.parse("node\\\n ") assert_raises { @parser.parse("node \\foo") } assert_raises { @parser.parse("node\\\\\nnode2") } assert_raises { @parser.parse("node \\\\\nnode2") } end def test_whitespace assert_equal ::KDL::Document.new([::KDL::Node.new('node')]), @parser.parse(" node") assert_equal ::KDL::Document.new([::KDL::Node.new('node')]), @parser.parse("\tnode") assert_equal ::KDL::Document.new([::KDL::Node.new('etc')]), @parser.parse("/* \nfoo\r\n */ etc") end def test_newline assert_equal ::KDL::Document.new([::KDL::Node.new('node1'), ::KDL::Node.new('node2')]), @parser.parse("node1\nnode2") assert_equal ::KDL::Document.new([::KDL::Node.new('node1'), ::KDL::Node.new('node2')]), @parser.parse("node1\rnode2") assert_equal ::KDL::Document.new([::KDL::Node.new('node1'), ::KDL::Node.new('node2')]), @parser.parse("node1\r\nnode2") assert_equal ::KDL::Document.new([::KDL::Node.new('node1'), ::KDL::Node.new('node2')]), @parser.parse("node1\n\nnode2") end def test_basic doc = @parser.parse('title "Hello, World"') nodes = KDL.build { title "Hello, World" } assert_equal nodes, doc end def test_multiple_values doc = @parser.parse('bookmarks 12 15 188 1234') nodes = KDL.build { bookmarks 12, 15, 188, 1234 } assert_equal nodes, doc end def test_properties doc = @parser.parse <<~KDL author "Alex Monad" email="alex@example.com" active= #true foo bar =#true "baz" quux =\\ #false 1 2 3 KDL nodes = KDL.build { author "Alex Monad", email: "alex@example.com", active: true foo "baz", 1, 2, 3, bar: true, quux: false } assert_equal nodes, doc end def test_nested_child_nodes doc = @parser.parse <<~KDL contents { section "First section" { paragraph "This is the first paragraph" paragraph "This is the second paragraph" } } KDL nodes = KDL.build { contents { section("First section") { paragraph "This is the first paragraph" paragraph "This is the second paragraph" } } } assert_equal nodes, doc end def test_semicolon doc = @parser.parse('node1; node2; node3;') nodes = KDL.build { node1; node2; node3; } assert_equal nodes, doc end def test_optional_child_semicolon doc = @parser.parse('foo {bar;baz;qux}') nodes = KDL.build { foo { bar; baz; qux } } assert_equal nodes, doc end def test_raw_strings doc = @parser.parse <<~KDL foo "this\\nhas\\tescapes" bar #"C:\\Users\\zkat\\"# baz #"hello"world"# KDL nodes = KDL.build { foo "this\nhas\tescapes" bar "C:\\Users\\zkat\\" baz "hello\"world" } assert_equal nodes, doc end def test_multiline_strings doc = @parser.parse <<~KDL string """ my multiline value """ KDL nodes = KDL.build { string "my\nmultiline\nvalue" } assert_equal nodes, doc assert_raises do @parser.parse <<~KDL node """foo""" KDL end assert_raises do @parser.parse <<~KDL node #"""foo"bar"""# KDL end assert_raises do @parser.parse <<~KDL node """ oops KDL end assert_raises do @parser.parse <<~KDL node #""" oops KDL end end def test_numbers doc = @parser.parse <<~KDL num 1.234e-42 my-hex 0xdeadbeef my-octal 0o755 my-binary 0b10101101 bignum 1_000_000 KDL nodes = KDL.build { num 1.234e-42 _ 'my-hex', 0xdeadbeef _ 'my-octal', 0o755 _ 'my-binary', 0b10101101 bignum 1_000_000 } assert_equal nodes, doc end def test_comments doc = @parser.parse <<~KDL // C style /* C style multiline */ tag /*foo=#true*/ bar=#false /*/* hello */*/ KDL nodes = KDL.build { tag bar: false } assert_equal nodes, doc end def test_slash_dash doc = @parser.parse <<~KDL /-mynode "foo" key=1 { a b c } mynode /- "commented" "not commented" /-key="value" /-{ a b } KDL nodes = KDL.build { mynode("not commented") { } } assert_equal nodes, doc end def test_multiline_nodes doc = @parser.parse <<~KDL title \\ "Some title" my-node 1 2 \\ // comments are ok after \\ 3 4 KDL nodes = KDL.build { title "Some title" _ "my-node", 1, 2, 3, 4 } assert_equal nodes, doc end def test_utf8 doc = @parser.parse <<~KDL smile "๐Ÿ˜" ใƒŽใƒผใƒ‰ ใŠๅๅ‰="โ˜œ(๏พŸใƒฎ๏พŸโ˜œ)" KDL nodes = ::KDL::Document.new([ ::KDL::Node.new('smile', arguments: [::KDL::Value::String.new('๐Ÿ˜')]), ::KDL::Node.new('ใƒŽใƒผใƒ‰', properties: { 'ใŠๅๅ‰' => ::KDL::Value::String.new('โ˜œ(๏พŸใƒฎ๏พŸโ˜œ)') }) ]) assert_equal nodes, doc end def test_node_names doc = @parser.parse <<~KDL "!@$@$%Q$%~@!40" "1.2.3" "!!!!!"=#true foo123~!@$%^&*.:'|?+ "weeee" - 1 KDL nodes = KDL.build { _ "!@$@$%Q$%~@!40", "1.2.3", "!!!!!": true _ "foo123~!@$%^&*.:'|?+", "weeee" _ "-", 1 } assert_equal nodes, doc end def test_escaping doc = @parser.parse <<~KDL node1 "\\u{1f600}" node2 "\\n\\t\\r\\\\\\"\\f\\b" KDL nodes = KDL.build { node1 "๐Ÿ˜€" node2 "\n\t\r\\\"\f\b" } assert_equal nodes, doc end def test_node_type doc = @parser.parse <<~KDL (foo)node KDL nodes = ::KDL::Document.new([ ::KDL::Node.new('node', type: 'foo'), ]) assert_equal nodes, doc end def test_value_type doc = @parser.parse <<~KDL node (foo)"bar" KDL nodes = ::KDL::Document.new([ ::KDL::Node.new('node', arguments: [::KDL::Value::String.new('bar', type: 'foo')]), ]) assert_equal nodes, doc end def test_property_type doc = @parser.parse <<~KDL node baz=(foo)"bar" KDL nodes = ::KDL::Document.new([ ::KDL::Node.new('node', properties: { 'baz' => ::KDL::Value::String.new('bar', type: 'foo') }), ]) assert_equal nodes, doc end def test_child_type doc = @parser.parse <<~KDL node { (foo)bar } KDL nodes = ::KDL::Document.new([ ::KDL::Node.new('node', children: [ ::KDL::Node.new('bar', type: 'foo') ]), ]) assert_equal nodes, doc end def test_version_directive refute_nil @parser.parse <<~KDL /- kdl-version 2 node "foo" KDL assert_raises(KDL::VersionMismatchError) do @parser.parse <<~KDL /- kdl-version 1 node "foo" KDL end end end danini-the-panini-kdl-rb-56d7cf1/test/spec_test.rb000066400000000000000000000016631515522600200221010ustar00rootroot00000000000000# frozen_string_literal: true require 'test_helper' class SpecTest < Minitest::Test TEST_CASES_DIR = File.join(__dir__, 'kdl-org/tests/test_cases') INPUTS_DIR = File.join(TEST_CASES_DIR, 'input') EXPECTED_DIR = File.join(TEST_CASES_DIR, 'expected_kdl') Dir.glob(File.join(INPUTS_DIR, '*.kdl')).each do |input_path| input_name = File.basename(input_path, '.kdl') expected_path = File.join(EXPECTED_DIR, "#{input_name}.kdl") if File.exist?(expected_path) define_method "test_#{input_name}_matches_expected_output" do expected = File.read(expected_path, encoding: Encoding::UTF_8) assert_equal expected, ::KDL.load_file(input_path, version: 2).to_s end else define_method "test_#{input_name}_does_not_parse" do err = assert_raises { ::KDL.load_file(input_path, version: 2) } raise err unless err.is_a?(KDL::Error) || err.is_a?(Racc::ParseError) end end end end danini-the-panini-kdl-rb-56d7cf1/test/test_helper.rb000066400000000000000000000005071515522600200224220ustar00rootroot00000000000000# frozen_string_literal: true require "simplecov" require "coveralls" SimpleCov.formatters = [ SimpleCov::Formatter::HTMLFormatter, Coveralls::SimpleCov::Formatter ] SimpleCov.start $LOAD_PATH.unshift File.expand_path("../lib", __dir__) require "kdl" require 'minitest' Minitest.load_plugins require "minitest/autorun" danini-the-panini-kdl-rb-56d7cf1/test/tokenizer_test.rb000066400000000000000000000241431515522600200231570ustar00rootroot00000000000000# frozen_string_literal: true require "test_helper" class TokenizerTest < Minitest::Test def test_identifier assert_equal t(:IDENT, "foo"), ::KDL::Tokenizer.new("foo").next_token assert_equal t(:IDENT, "foo-bar123"), ::KDL::Tokenizer.new("foo-bar123").next_token assert_equal t(:IDENT, "-"), ::KDL::Tokenizer.new("-").next_token assert_equal t(:IDENT, "--"), ::KDL::Tokenizer.new("--").next_token end def test_string assert_equal t(:STRING, "foo"), ::KDL::Tokenizer.new('"foo"').next_token assert_equal t(:STRING, "foo\nbar"), ::KDL::Tokenizer.new('"foo\nbar"').next_token assert_equal t(:STRING, "foo"), ::KDL::V1::Tokenizer.new("\"\\\n\n\nfoo\"").next_token end def test_rawstring assert_equal t(:RAWSTRING, "foo\\nbar"), ::KDL::Tokenizer.new('#"foo\\nbar"#').next_token assert_equal t(:RAWSTRING, "foo\"bar"), ::KDL::Tokenizer.new('#"foo"bar"#').next_token assert_equal t(:RAWSTRING, "foo\"#bar"), ::KDL::Tokenizer.new('##"foo"#bar"##').next_token assert_equal t(:RAWSTRING, "\"foo\""), ::KDL::Tokenizer.new('#""foo""#').next_token tokenizer = ::KDL::Tokenizer.new('node #"C:\\Users\\zkat\\"#') assert_equal t(:IDENT, "node"), tokenizer.next_token assert_equal t(:WS, " ", 1, 5), tokenizer.next_token assert_equal t(:RAWSTRING, "C:\\Users\\zkat\\", 1, 6), tokenizer.next_token tokenizer = ::KDL::Tokenizer.new('other-node #"hello"world"#') assert_equal t(:IDENT, "other-node"), tokenizer.next_token assert_equal t(:WS, " ", 1, 11), tokenizer.next_token assert_equal t(:RAWSTRING, "hello\"world", 1, 12), tokenizer.next_token end def test_integer assert_equal t(:INTEGER, 123), ::KDL::Tokenizer.new("123").next_token assert_equal t(:INTEGER, 0x0123456789abcdef), ::KDL::Tokenizer.new("0x0123456789abcdef").next_token assert_equal t(:INTEGER, 0o01234567), ::KDL::Tokenizer.new("0o01234567").next_token assert_equal t(:INTEGER, 0b101001), ::KDL::Tokenizer.new("0b101001").next_token assert_equal t(:INTEGER, -0x0123456789abcdef), ::KDL::Tokenizer.new("-0x0123456789abcdef").next_token assert_equal t(:INTEGER, -0o01234567), ::KDL::Tokenizer.new("-0o01234567").next_token assert_equal t(:INTEGER, -0b101001), ::KDL::Tokenizer.new("-0b101001").next_token end def test_float assert_equal t(:FLOAT, 1.23), ::KDL::Tokenizer.new("1.23").next_token assert_equal t(:FLOAT, Float::INFINITY), ::KDL::Tokenizer.new("#inf").next_token assert_equal t(:FLOAT, -Float::INFINITY), ::KDL::Tokenizer.new("#-inf").next_token nan = ::KDL::Tokenizer.new("#nan").next_token assert_equal :FLOAT, nan[0] assert_predicate nan[1].value, :nan? end def test_boolean assert_equal t(:TRUE, true), ::KDL::Tokenizer.new("#true").next_token assert_equal t(:FALSE, false), ::KDL::Tokenizer.new("#false").next_token end def test_null assert_equal t(:NULL, nil), ::KDL::Tokenizer.new("#null").next_token end def test_symbols assert_equal t(:LBRACE, '{'), ::KDL::Tokenizer.new("{").next_token assert_equal t(:RBRACE, '}'), ::KDL::Tokenizer.new("}").next_token end def test_equals assert_equal t(:EQUALS, '='), ::KDL::Tokenizer.new("=").next_token assert_equal t(:EQUALS, ' ='), ::KDL::Tokenizer.new(" =").next_token assert_equal t(:EQUALS, '= '), ::KDL::Tokenizer.new("= ").next_token assert_equal t(:EQUALS, ' = '), ::KDL::Tokenizer.new(" = ").next_token assert_equal t(:EQUALS, ' ='), ::KDL::Tokenizer.new(" =foo").next_token end def test_whitespace assert_equal t(:WS, ' '), ::KDL::Tokenizer.new(" ").next_token assert_equal t(:WS, "\t"), ::KDL::Tokenizer.new("\t").next_token assert_equal t(:WS, " \t"), ::KDL::Tokenizer.new(" \t").next_token assert_equal t(:WS, "\\\n"), ::KDL::Tokenizer.new("\\\n").next_token assert_equal t(:WS, "\\\n"), ::KDL::Tokenizer.new("\\\n//some comment").next_token assert_equal t(:WS, "\\\n "), ::KDL::Tokenizer.new("\\\n //some comment").next_token assert_equal t(:WS, " \\\n"), ::KDL::Tokenizer.new(" \\\n").next_token assert_equal t(:WS, " \\\n"), ::KDL::Tokenizer.new(" \\\n//some comment").next_token assert_equal t(:WS, " \\\n "), ::KDL::Tokenizer.new(" \\\n //some comment").next_token assert_equal t(:WS, " \\\n \\\n "), ::KDL::Tokenizer.new(" \\\n \\\n ").next_token end def test_multiple_tokens tokenizer = ::KDL::Tokenizer.new("node 1 \"two\" a=3") assert_equal t(:IDENT, 'node'), tokenizer.next_token assert_equal t(:WS, ' ', 1, 5), tokenizer.next_token assert_equal t(:INTEGER, 1, 1, 6), tokenizer.next_token assert_equal t(:WS, ' ', 1, 7), tokenizer.next_token assert_equal t(:STRING, 'two', 1, 8), tokenizer.next_token assert_equal t(:WS, ' ', 1, 13), tokenizer.next_token assert_equal t(:IDENT, 'a', 1, 14), tokenizer.next_token assert_equal t(:EQUALS, '=', 1, 15), tokenizer.next_token assert_equal t(:INTEGER, 3, 1, 16), tokenizer.next_token assert_equal t(:EOF, :EOF, 1, 17), tokenizer.next_token assert_equal eof(1, 17), tokenizer.next_token end def test_single_line_comment assert_equal t(:EOF, :EOF), ::KDL::Tokenizer.new("// comment").next_token tokenizer = ::KDL::Tokenizer.new <<~KDL node1 // comment node2 KDL assert_equal t(:IDENT, 'node1'), tokenizer.next_token assert_equal t(:NEWLINE, "\n", 1, 6), tokenizer.next_token assert_equal t(:NEWLINE, "\n", 2, 11), tokenizer.next_token assert_equal t(:IDENT, 'node2', 3, 1), tokenizer.next_token assert_equal t(:NEWLINE, "\n", 3, 6), tokenizer.next_token assert_equal t(:EOF, :EOF, 4, 1), tokenizer.next_token assert_equal eof(4, 1), tokenizer.next_token end def test_multiline_comment tokenizer = ::KDL::Tokenizer.new("foo /*bar=1*/ baz=2") assert_equal t(:IDENT, 'foo'), tokenizer.next_token assert_equal t(:WS, ' ', 1, 4), tokenizer.next_token assert_equal t(:IDENT, 'baz', 1, 15), tokenizer.next_token assert_equal t(:EQUALS, '=', 1, 18), tokenizer.next_token assert_equal t(:INTEGER, 2, 1, 19), tokenizer.next_token assert_equal t(:EOF, :EOF, 1, 20), tokenizer.next_token assert_equal eof(1, 20), tokenizer.next_token end def test_utf8 assert_equal t(:IDENT, '๐Ÿ˜'), ::KDL::Tokenizer.new("๐Ÿ˜").next_token assert_equal t(:STRING, '๐Ÿ˜'), ::KDL::Tokenizer.new('"๐Ÿ˜"').next_token assert_equal t(:IDENT, 'ใƒŽใƒผใƒ‰'), ::KDL::Tokenizer.new('ใƒŽใƒผใƒ‰').next_token assert_equal t(:IDENT, 'ใŠๅๅ‰'), ::KDL::Tokenizer.new('ใŠๅๅ‰').next_token assert_equal t(:STRING, 'โ˜œ(๏พŸใƒฎ๏พŸโ˜œ)'), ::KDL::Tokenizer.new('"โ˜œ(๏พŸใƒฎ๏พŸโ˜œ)"').next_token tokenizer = ::KDL::Tokenizer.new <<~KDL smile "๐Ÿ˜" ใƒŽใƒผใƒ‰ ใŠๅๅ‰="โ˜œ(๏พŸใƒฎ๏พŸโ˜œ)" KDL assert_equal t(:IDENT, 'smile'), tokenizer.next_token assert_equal t(:WS, ' ', 1, 6), tokenizer.next_token assert_equal t(:STRING, '๐Ÿ˜', 1, 7), tokenizer.next_token assert_equal t(:NEWLINE, "\n", 1, 10), tokenizer.next_token assert_equal t(:IDENT, 'ใƒŽใƒผใƒ‰', 2, 1), tokenizer.next_token assert_equal t(:WS, ' ', 2, 4), tokenizer.next_token assert_equal t(:IDENT, 'ใŠๅๅ‰', 2, 5), tokenizer.next_token assert_equal t(:EQUALS, '=', 2, 8), tokenizer.next_token assert_equal t(:STRING, 'โ˜œ(๏พŸใƒฎ๏พŸโ˜œ)', 2, 9), tokenizer.next_token assert_equal t(:NEWLINE, "\n", 2, 18), tokenizer.next_token assert_equal t(:EOF, :EOF, 3, 1), tokenizer.next_token assert_equal eof(3, 1), tokenizer.next_token end def test_semicolon tokenizer = ::KDL::Tokenizer.new 'node1; node2' assert_equal t(:IDENT, 'node1'), tokenizer.next_token assert_equal t(:SEMICOLON, ';', 1, 6), tokenizer.next_token assert_equal t(:WS, ' ', 1, 7), tokenizer.next_token assert_equal t(:IDENT, 'node2', 1, 8), tokenizer.next_token assert_equal t(:EOF, :EOF, 1, 13), tokenizer.next_token assert_equal eof(1, 13), tokenizer.next_token end def test_slash_dash tokenizer = ::KDL::Tokenizer.new <<~KDL /-mynode /-"foo" /-key=1 /-{ a } KDL assert_equal t(:SLASHDASH, '/-'), tokenizer.next_token assert_equal t(:IDENT, 'mynode', 1, 3), tokenizer.next_token assert_equal t(:WS, ' ', 1, 9), tokenizer.next_token assert_equal t(:SLASHDASH, '/-', 1, 10), tokenizer.next_token assert_equal t(:STRING, 'foo', 1, 12), tokenizer.next_token assert_equal t(:WS, ' ', 1, 17), tokenizer.next_token assert_equal t(:SLASHDASH, '/-', 1, 18), tokenizer.next_token assert_equal t(:IDENT, 'key', 1, 20), tokenizer.next_token assert_equal t(:EQUALS, '=', 1, 23), tokenizer.next_token assert_equal t(:INTEGER, 1, 1, 24), tokenizer.next_token assert_equal t(:WS, ' ', 1, 25), tokenizer.next_token assert_equal t(:SLASHDASH, '/-', 1, 26), tokenizer.next_token assert_equal t(:LBRACE, '{', 1, 28), tokenizer.next_token assert_equal t(:NEWLINE, "\n", 1, 29), tokenizer.next_token assert_equal t(:WS, ' ', 2, 1), tokenizer.next_token assert_equal t(:IDENT, 'a', 2, 3), tokenizer.next_token assert_equal t(:NEWLINE, "\n", 2, 4), tokenizer.next_token assert_equal t(:RBRACE, '}', 3, 1), tokenizer.next_token assert_equal t(:NEWLINE, "\n", 3, 2), tokenizer.next_token assert_equal t(:EOF, :EOF, 4, 1), tokenizer.next_token assert_equal eof(4, 1), tokenizer.next_token end def test_multiline_nodes tokenizer = ::KDL::Tokenizer.new <<~KDL title \\ "Some title" KDL assert_equal t(:IDENT, 'title'), tokenizer.next_token assert_equal t(:WS, " \\\n ", 1, 6), tokenizer.next_token assert_equal t(:STRING, 'Some title', 2, 3), tokenizer.next_token assert_equal t(:NEWLINE, "\n", 2, 15), tokenizer.next_token assert_equal t(:EOF, :EOF, 3, 1), tokenizer.next_token assert_equal eof(3, 1), tokenizer.next_token end def test_tokens tokenizer = ::KDL::Tokenizer.new "node1 {\n foo\n bar\n}" assert_equal %i[IDENT WS LBRACE NEWLINE WS IDENT NEWLINE WS IDENT NEWLINE RBRACE EOF], tokenizer.tokens.map(&:first) end private def t(type, value, line = 1, col = 1) [type, ::KDL::Tokenizer::Token.new(type, value, line, col)] end def eof(line = 1, col = 1) [false, ::KDL::Tokenizer::Token.new(:EOF, :EOF, line, col)] end end danini-the-panini-kdl-rb-56d7cf1/test/types/000077500000000000000000000000001515522600200207215ustar00rootroot00000000000000danini-the-panini-kdl-rb-56d7cf1/test/types/base64_test.rb000066400000000000000000000005351515522600200233740ustar00rootroot00000000000000# frozen_string_literal: true require "test_helper" class Base64Test < Minitest::Test def test_base64 value = KDL::Types::Base64.call(::KDL::Value::String.new('U2VuZCByZWluZm9yY2VtZW50cw==')) assert_equal 'Send reinforcements', value.value assert_raises { KDL::Types::Base64.call(::KDL::Value::String.new('not base64')) } end end danini-the-panini-kdl-rb-56d7cf1/test/types/country_test.rb000066400000000000000000000024261515522600200240140ustar00rootroot00000000000000# frozen_string_literal: true require 'test_helper' class CountryTest < Minitest::Test def test_country3 value = KDL::Types::Country3.call(::KDL::Value::String.new('ZAF')) assert_equal({ alpha3: 'ZAF', alpha2: 'ZA', numeric_code: 710, name: 'South Africa' }, value.value) assert_raises { KDL::Types::Country3.call(::KDL::Value::String.new('ZZZ')) } end def test_country2 value = KDL::Types::Country2.call(::KDL::Value::String.new('ZA')) assert_equal({ alpha3: 'ZAF', alpha2: 'ZA', numeric_code: 710, name: 'South Africa' }, value.value) assert_raises { KDL::Types::Country2.call(::KDL::Value::String.new('ZZ')) } end def test_country_subdivision value = KDL::Types::CountrySubdivision.call(::KDL::Value::String.new('ZA-GP')) assert_equal('ZA-GP', value.value) assert_equal('Gauteng', value.name) assert_equal({ alpha3: 'ZAF', alpha2: 'ZA', numeric_code: 710, name: 'South Africa' }, value.country) assert_raises { KDL::Types::Country2.call(::KDL::Value::String.new('ZA-ZZ')) } assert_raises { KDL::Types::Country2.call(::KDL::Value::String.new('ZZ-GP')) } end end danini-the-panini-kdl-rb-56d7cf1/test/types/currency_test.rb000066400000000000000000000006271515522600200241440ustar00rootroot00000000000000# frozen_string_literal: true require 'test_helper' class CurrencyTest < Minitest::Test def test_currency value = KDL::Types::Currency.call(::KDL::Value::String.new('ZAR')) assert_equal({ numeric_code: 710, minor_unit: 2, name: 'South African rand' }, value.value) assert_raises { KDL::Types::Currency.call(::KDL::Value::String.new('ZZZ')) } end end danini-the-panini-kdl-rb-56d7cf1/test/types/date_time_test.rb000066400000000000000000000024711515522600200242440ustar00rootroot00000000000000# frozen_string_literal: true require "test_helper" class DateTimeTest < Minitest::Test def test_date_time value = KDL::Types::DateTime.call(::KDL::Value::String.new('2011-10-05T22:26:12-04:00')) assert_equal ::Time.iso8601('2011-10-05T22:26:12-04:00'), value.value assert_raises { KDL::Types::DateTime.call(::KDL::Value::String.new('not a date-time')) } end def test_time today = ::Date.today.iso8601 value = KDL::Types::Time.call(::KDL::Value::String.new('22:26:12')) assert_equal ::Time.parse("#{today}T22:26:12"), value.value value = KDL::Types::Time.call(::KDL::Value::String.new('T22:26:12Z')) assert_equal ::Time.parse("#{today}T22:26:12Z"), value.value value = KDL::Types::Time.call(::KDL::Value::String.new('22:26:12.000Z')) assert_equal ::Time.parse("#{today}T22:26:12Z"), value.value value = KDL::Types::Time.call(::KDL::Value::String.new('22:26:12-04:00')) assert_equal ::Time.parse("#{today}T22:26:12-04:00"), value.value assert_raises { KDL::Types::DateTime.call(::KDL::Value::String.new('not a time')) } end def test_date value = KDL::Types::Date.call(::KDL::Value::String.new('2011-10-05')) assert_equal ::Date.iso8601('2011-10-05'), value.value assert_raises { KDL::Types::DateTime.call(::KDL::Value::String.new('not a date')) } end end danini-the-panini-kdl-rb-56d7cf1/test/types/decimal_test.rb000066400000000000000000000005351515522600200237060ustar00rootroot00000000000000# frozen_string_literal: true require "test_helper" class DecimalTest < Minitest::Test def test_decimal value = KDL::Types::Decimal.call(::KDL::Value::String.new('10000000000000')) assert_equal(BigDecimal('10000000000000'), value.value) assert_raises { KDL::Types::Decimal.call(::KDL::Value::String.new('not a decimal')) } end end danini-the-panini-kdl-rb-56d7cf1/test/types/duration_test.rb000066400000000000000000000030051515522600200241300ustar00rootroot00000000000000# frozen_string_literal: true require "test_helper" class DurationTest < Minitest::Test def test_duration value = KDL::Types::Duration.call(::KDL::Value::String.new('P3Y6M4DT12H30M5S')) assert_equal({ years: 3, months: 6, days: 4, hours: 12, minutes: 30, seconds: 5 }, value.value) value = KDL::Types::Duration.call(::KDL::Value::String.new('P23DT23H')) assert_equal({ days: 23, hours: 23 }, value.value) value = KDL::Types::Duration.call(::KDL::Value::String.new('P4Y')) assert_equal({ years: 4 }, value.value) value = KDL::Types::Duration.call(::KDL::Value::String.new('PT0S')) assert_equal({ seconds: 0 }, value.value) value = KDL::Types::Duration.call(::KDL::Value::String.new('P0D')) assert_equal({ days: 0 }, value.value) value = KDL::Types::Duration.call(::KDL::Value::String.new('P0.5Y')) assert_equal({ years: 0.5 }, value.value) value = KDL::Types::Duration.call(::KDL::Value::String.new('P0,5Y')) assert_equal({ years: 0.5 }, value.value) value = KDL::Types::Duration.call(::KDL::Value::String.new('P1M')) assert_equal({ months: 1 }, value.value) value = KDL::Types::Duration.call(::KDL::Value::String.new('PT1M')) assert_equal({ minutes: 1 }, value.value) value = KDL::Types::Duration.call(::KDL::Value::String.new('P7W')) assert_equal({ weeks: 7 }, value.value) assert_raises { KDL::Types::Duration.call(::KDL::Value::String.new('not a duration')) } assert_raises { KDL::Types::Duration.call(::KDL::Value::String.new('P')) } end end danini-the-panini-kdl-rb-56d7cf1/test/types/email_test.rb000066400000000000000000000060401515522600200233740ustar00rootroot00000000000000# frozen_string_literal: true require "test_helper" class EmailTest < Minitest::Test def test_email value = KDL::Types::Email.call(::KDL::Value::String.new('danielle@example.com')) assert_equal 'danielle@example.com', value.value assert_equal 'danielle', value.local assert_equal 'example.com', value.domain assert_raises { KDL::Types::Email.call(::KDL::Value::String.new('not an email')) } end VALID_EMAILS = [ ['simple@example.com', 'simple', 'example.com'], ['very.common@example.com', 'very.common', 'example.com'], ['disposable.style.email.with+symbol@example.com', 'disposable.style.email.with+symbol', 'example.com'], ['other.email-with-hyphen@example.com', 'other.email-with-hyphen', 'example.com'], ['fully-qualified-domain@example.com', 'fully-qualified-domain', 'example.com'], ['user.name+tag+sorting@example.com', 'user.name+tag+sorting', 'example.com'], ['x@example.com', 'x', 'example.com'], ['example-indeed@strange-example.com', 'example-indeed', 'strange-example.com'], ['test/test@test.com', 'test/test', 'test.com'], ['admin@mailserver1', 'admin', 'mailserver1'], ['example@s.example', 'example', 's.example'], ['" "@example.org', ' ', 'example.org'], ['"john..doe"@example.org', 'john..doe', 'example.org'], ['mailhost!username@example.org', 'mailhost!username', 'example.org'], ['user%example.com@example.org', 'user%example.com', 'example.org'], ['user-@example.org', 'user-', 'example.org'] ] def test_valid_emails VALID_EMAILS.each do |email, local, domain| value = KDL::Types::Email.call(::KDL::Value::String.new(email)) assert_equal email, value.value assert_equal local, value.local assert_equal domain, value.domain end end INVALID_EMAILS = [ 'Abc.example.com', 'A@b@c@example.com', 'a"b(c)d,e:f;gi[j\k]l@example.com', 'just"not"right@example.com', 'this is"not\allowed@example.com', 'this\ still\"not\\allowed@example.com', '1234567890123456789012345678901234567890123456789012345678901234+x@example.com', '-some-user-@-example-.com', 'QA๐Ÿฆ„CHOCOLATE๐ŸŒˆ@test.com' ] def test_invalid_emails INVALID_EMAILS.each do |email| assert_raises { KDL::Types::Email.call(::KDL::Value::String.new(email)) } end end def test_idn_email value = KDL::Types::IDNEmail.call(::KDL::Value::String.new('๐ŸŒˆ@xn--9ckb.com')) assert_equal '๐ŸŒˆ@xn--9ckb.com', value.value assert_equal '๐ŸŒˆ@ใƒ„ใƒƒ.com', value.unicode_value assert_equal '๐ŸŒˆ', value.local assert_equal 'ใƒ„ใƒƒ.com', value.unicode_domain assert_equal 'xn--9ckb.com', value.domain value = KDL::Types::IDNEmail.call(::KDL::Value::String.new('๐ŸŒˆ@ใƒ„ใƒƒ.com')) assert_equal '๐ŸŒˆ@xn--9ckb.com', value.value assert_equal '๐ŸŒˆ@ใƒ„ใƒƒ.com', value.unicode_value assert_equal '๐ŸŒˆ', value.local assert_equal 'ใƒ„ใƒƒ.com', value.unicode_domain assert_equal 'xn--9ckb.com', value.domain assert_raises { KDL::Types::IDNEmail.call(::KDL::Value::String.new('not an email')) } end end danini-the-panini-kdl-rb-56d7cf1/test/types/hostname_test.rb000066400000000000000000000025301515522600200241230ustar00rootroot00000000000000# frozen_string_literal: true require "test_helper" class HostnameTest < Minitest::Test def test_hostname value = KDL::Types::Hostname.call(::KDL::Value::String.new('www.example.com')) assert_equal 'www.example.com', value.value refute_nil KDL::Types::Hostname.call(::KDL::Value::String.new('a'*63 + '.com')) refute_nil KDL::Types::Hostname.call(::KDL::Value::String.new([63, 63, 63, 61].map { |x| 'a' * x }.join('.'))) assert_raises { KDL::Types::Hostname.call(::KDL::Value::String.new('not a hostname')) } assert_raises { KDL::Types::Hostname.call(::KDL::Value::String.new('-starts-with-a-dash.com')) } assert_raises { KDL::Types::Hostname.call(::KDL::Value::String.new('a'*64 + '.com')) } assert_raises { KDL::Types::Hostname.call(::KDL::Value::String.new((['a' * 63] * 4).join('.'))) } end def test_idn_hostname value = KDL::Types::IDNHostname.call(::KDL::Value::String.new('xn--bcher-kva.example')) assert_equal 'xn--bcher-kva.example', value.value assert_equal 'bรผcher.example', value.unicode_value value = KDL::Types::IDNHostname.call(::KDL::Value::String.new('bรผcher.example')) assert_equal 'xn--bcher-kva.example', value.value assert_equal 'bรผcher.example', value.unicode_value assert_raises { KDL::Types::IDNHostname.call(::KDL::Value::String.new('not an idn hostname')) } end end danini-the-panini-kdl-rb-56d7cf1/test/types/ip_test.rb000066400000000000000000000015501515522600200227160ustar00rootroot00000000000000# frozen_string_literal: true require "test_helper" class IPTest < Minitest::Test def test_ipv4 value = KDL::Types::IPV4.call(::KDL::Value::String.new('127.0.0.1')) assert_equal ::IPAddr.new('127.0.0.1'), value.value assert_raises { KDL::Types::IPV4.call(::KDL::Value::String.new('not an ipv4 address')) } assert_raises { KDL::Types::IPV4.call(::KDL::Value::String.new('3ffe:505:2::1')) } end def test_ipv6 value = KDL::Types::IPV6.call(::KDL::Value::String.new('::')) assert_equal ::IPAddr.new('::'), value.value value = KDL::Types::IPV6.call(::KDL::Value::String.new('3ffe:505:2::1')) assert_equal ::IPAddr.new('3ffe:505:2::1'), value.value assert_raises { KDL::Types::IPV6.call(::KDL::Value::String.new('not an ipv6 address')) } assert_raises { KDL::Types::IPV6.call(::KDL::Value::String.new('127.0.0.1')) } end end danini-the-panini-kdl-rb-56d7cf1/test/types/irl_test.rb000066400000000000000000000046531515522600200231030ustar00rootroot00000000000000# frozen_string_literal: true require "test_helper" class IRLTest < Minitest::Test def test_irl value = KDL::Types::IRL.call(::KDL::Value::String.new('https://bรผcher.example/foo/แฟฌฯŒฮดฮฟฯ‚')) assert_equal URI('https://xn--bcher-kva.example/foo/%E1%BF%AC%CF%8C%CE%B4%CE%BF%CF%82'), value.value assert_equal 'https://bรผcher.example/foo/แฟฌฯŒฮดฮฟฯ‚', value.unicode_value value = KDL::Types::IRL.call(::KDL::Value::String.new('https://xn--bcher-kva.example/foo/%E1%BF%AC%CF%8C%CE%B4%CE%BF%CF%82')) assert_equal URI('https://xn--bcher-kva.example/foo/%E1%BF%AC%CF%8C%CE%B4%CE%BF%CF%82'), value.value assert_equal 'https://bรผcher.example/foo/แฟฌฯŒฮดฮฟฯ‚', value.unicode_value value = KDL::Types::IRL.call(::KDL::Value::String.new('https://bรผcher.example/foo/แฟฌฯŒฮดฮฟฯ‚?๐ŸŒˆ=โœ”๏ธ#๐Ÿฆ„')) assert_equal URI('https://xn--bcher-kva.example/foo/%E1%BF%AC%CF%8C%CE%B4%CE%BF%CF%82?%F0%9F%8C%88=%E2%9C%94%EF%B8%8F#%F0%9F%A6%84'), value.value assert_equal 'https://bรผcher.example/foo/แฟฌฯŒฮดฮฟฯ‚?๐ŸŒˆ=โœ”๏ธ#๐Ÿฆ„', value.unicode_value assert_raises { KDL::Types::IRL.call(::KDL::Value::String.new('not a url')) } assert_raises { KDL::Types::IRL.call(::KDL::Value::String.new('/reference/to/something')) } end def test_irl_reference value = KDL::Types::IRLReference.call(::KDL::Value::String.new('https://bรผcher.example/foo/แฟฌฯŒฮดฮฟฯ‚')) assert_equal URI('https://xn--bcher-kva.example/foo/%E1%BF%AC%CF%8C%CE%B4%CE%BF%CF%82'), value.value assert_equal 'https://bรผcher.example/foo/แฟฌฯŒฮดฮฟฯ‚', value.unicode_value value = KDL::Types::IRLReference.call(::KDL::Value::String.new('https://xn--bcher-kva.example/foo/%E1%BF%AC%CF%8C%CE%B4%CE%BF%CF%82')) assert_equal URI('https://xn--bcher-kva.example/foo/%E1%BF%AC%CF%8C%CE%B4%CE%BF%CF%82'), value.value assert_equal 'https://bรผcher.example/foo/แฟฌฯŒฮดฮฟฯ‚', value.unicode_value value = KDL::Types::IRLReference.call(::KDL::Value::String.new('/foo/แฟฌฯŒฮดฮฟฯ‚')) assert_equal URI('/foo/%E1%BF%AC%CF%8C%CE%B4%CE%BF%CF%82'), value.value assert_equal '/foo/แฟฌฯŒฮดฮฟฯ‚', value.unicode_value value = KDL::Types::IRLReference.call(::KDL::Value::String.new('/foo/%E1%BF%AC%CF%8C%CE%B4%CE%BF%CF%82')) assert_equal URI('/foo/%E1%BF%AC%CF%8C%CE%B4%CE%BF%CF%82'), value.value assert_equal '/foo/แฟฌฯŒฮดฮฟฯ‚', value.unicode_value assert_raises { KDL::Types::IRLReference.call(::KDL::Value::String.new('not a url reference')) } end end danini-the-panini-kdl-rb-56d7cf1/test/types/regex_test.rb000066400000000000000000000004671515522600200234260ustar00rootroot00000000000000# frozen_string_literal: true require "test_helper" class RegexTest < Minitest::Test def test_regex value = KDL::Types::Regex.call(::KDL::Value::String.new('asdf')) assert_equal(/asdf/, value.value) assert_raises { KDL::Types::Regex.call(::KDL::Value::String.new('invalid(regex]')) } end end danini-the-panini-kdl-rb-56d7cf1/test/types/url_template_test.rb000066400000000000000000000203411515522600200250020ustar00rootroot00000000000000# frozen_string_literal: true require "test_helper" class URLTemplateTest < Minitest::Test def setup @variables = { count: ['one', 'two', 'three'], dom: ['example', 'com'], dub: 'me/too', hello: 'Hello World!', half: '50%', var: 'value', who: 'fred', base: 'http://example.com/home/', path: '/foo/bar', list: ['red', 'green', 'blue'], keys: { semi: ';', dot: '.', comma: ',' }, v: '6', x: '1024', y: '768', empty: '', empty_keys: {}, undef: nil, } end def test_no_variables value = KDL::Types::URLTemplate.call(::KDL::Value::String.new('https://www.example.com/foo/bar')) assert_equal URI('https://www.example.com/foo/bar'), value.expand({}) end def test_variable value = KDL::Types::URLTemplate.call(::KDL::Value::String.new('https://www.example.com/{foo}/bar')) assert_equal URI('https://www.example.com/lorem/bar'), value.expand({ foo: 'lorem' }) end def test_multiple_variables value = KDL::Types::URLTemplate.call(::KDL::Value::String.new('https://www.example.com/{foo}/{bar}')) assert_equal URI('https://www.example.com/lorem/ipsum'), value.expand({ foo: 'lorem', bar: 'ipsum' }) end def test_list_expansion assert_expansion_equal '{count}', 'one,two,three' assert_expansion_equal '{count*}', 'one,two,three' assert_expansion_equal '{/count}', '/one,two,three' assert_expansion_equal '{/count*}', '/one/two/three' assert_expansion_equal '{;count}', ';count=one,two,three' assert_expansion_equal '{;count*}', ';count=one;count=two;count=three' assert_expansion_equal '{?count}', '?count=one,two,three' assert_expansion_equal '{?count*}', '?count=one&count=two&count=three' assert_expansion_equal '{&count*}', '&count=one&count=two&count=three' end def test_simple_string assert_expansion_equal '{var}', 'value' assert_expansion_equal '{hello}', 'Hello%20World%21' assert_expansion_equal '{half}', '50%25' assert_expansion_equal 'O{empty}X', 'OX' assert_expansion_equal 'O{undef}X', 'OX' assert_expansion_equal '{x,y}', '1024,768' assert_expansion_equal '{x,hello,y}', '1024,Hello%20World%21,768' assert_expansion_equal '?{x,empty}', '?1024,' assert_expansion_equal '?{x,undef}', '?1024' assert_expansion_equal '?{undef,y}', '?768' assert_expansion_equal '{var:3}', 'val' assert_expansion_equal '{var:30}', 'value' assert_expansion_equal '{list}', 'red,green,blue' assert_expansion_equal '{list*}', 'red,green,blue' assert_expansion_equal '{keys}', 'semi,%3B,dot,.,comma,%2C' assert_expansion_equal '{keys*}', 'semi=%3B,dot=.,comma=%2C' end def test_reserved_expansion assert_expansion_equal '{+var}', 'value' assert_expansion_equal '{+hello}', 'Hello%20World!' assert_expansion_equal '{+half}', '50%25' assert_expansion_equal '{base}index', 'http%3A%2F%2Fexample.com%2Fhome%2Findex' assert_expansion_equal '{+base}index', 'http://example.com/home/index' assert_expansion_equal 'O{+empty}X', 'OX' assert_expansion_equal 'O{+undef}X', 'OX' assert_expansion_equal '{+path}/here', '/foo/bar/here' assert_expansion_equal 'here?ref={+path}', 'here?ref=/foo/bar' assert_expansion_equal 'up{+path}{var}/here', 'up/foo/barvalue/here' assert_expansion_equal '{+x,hello,y}', '1024,Hello%20World!,768' assert_expansion_equal '{+path,x}/here', '/foo/bar,1024/here' assert_expansion_equal '{+path:6}/here', '/foo/b/here' assert_expansion_equal '{+list}', 'red,green,blue' assert_expansion_equal '{+list*}', 'red,green,blue' assert_expansion_equal '{+keys}', 'semi,;,dot,.,comma,,' assert_expansion_equal '{+keys*}', 'semi=;,dot=.,comma=,' end def test_fragment_expansion assert_expansion_equal '{#var}', '#value' assert_expansion_equal '{#hello}', '#Hello%20World!' assert_expansion_equal '{#half}', '#50%25' assert_expansion_equal 'foo{#empty}', 'foo#' assert_expansion_equal 'foo{#undef}', 'foo' assert_expansion_equal '{#x,hello,y}', '#1024,Hello%20World!,768' assert_expansion_equal '{#path,x}/here', '#/foo/bar,1024/here' assert_expansion_equal '{#path:6}/here', '#/foo/b/here' assert_expansion_equal '{#list}', '#red,green,blue' assert_expansion_equal '{#list*}', '#red,green,blue' assert_expansion_equal '{#keys}', '#semi,;,dot,.,comma,,' assert_expansion_equal '{#keys*}', '#semi=;,dot=.,comma=,' end def test_label_expansion assert_expansion_equal '{.who}', '.fred' assert_expansion_equal '{.who,who}', '.fred.fred' assert_expansion_equal '{.half,who}', '.50%25.fred' assert_expansion_equal 'www{.dom*}', 'www.example.com' assert_expansion_equal 'X{.var}', 'X.value' assert_expansion_equal 'X{.empty}', 'X.' assert_expansion_equal 'X{.undef}', 'X' assert_expansion_equal 'X{.var:3}', 'X.val' assert_expansion_equal 'X{.list}', 'X.red,green,blue' assert_expansion_equal 'X{.list*}', 'X.red.green.blue' assert_expansion_equal 'X{.keys}', 'X.semi,%3B,dot,.,comma,%2C' assert_expansion_equal 'X{.keys*}', 'X.semi=%3B.dot=..comma=%2C' assert_expansion_equal 'X{.empty_keys}', 'X' assert_expansion_equal 'X{.empty_keys*}', 'X' end def test_path_expansion assert_expansion_equal '{/who}', '/fred' assert_expansion_equal '{/who,who}', '/fred/fred' assert_expansion_equal '{/half,who}', '/50%25/fred' assert_expansion_equal '{/who,dub}', '/fred/me%2Ftoo' assert_expansion_equal '{/var}', '/value' assert_expansion_equal '{/var,empty}', '/value/' assert_expansion_equal '{/var,undef}', '/value' assert_expansion_equal '{/var,x}/here', '/value/1024/here' assert_expansion_equal '{/var:1,var}', '/v/value' assert_expansion_equal '{/list}', '/red,green,blue' assert_expansion_equal '{/list*}', '/red/green/blue' assert_expansion_equal '{/list*,path:4}', '/red/green/blue/%2Ffoo' assert_expansion_equal '{/keys}', '/semi,%3B,dot,.,comma,%2C' assert_expansion_equal '{/keys*}', '/semi=%3B/dot=./comma=%2C' end def test_parameter_expansion assert_expansion_equal '{;who}', ';who=fred' assert_expansion_equal '{;half}', ';half=50%25' assert_expansion_equal '{;empty}', ';empty' assert_expansion_equal '{;v,empty,who}', ';v=6;empty;who=fred' assert_expansion_equal '{;v,bar,who}', ';v=6;who=fred' assert_expansion_equal '{;x,y}', ';x=1024;y=768' assert_expansion_equal '{;x,y,empty}', ';x=1024;y=768;empty' assert_expansion_equal '{;x,y,undef}', ';x=1024;y=768' assert_expansion_equal '{;hello:5}', ';hello=Hello' assert_expansion_equal '{;list}', ';list=red,green,blue' assert_expansion_equal '{;list*}', ';list=red;list=green;list=blue' assert_expansion_equal '{;keys}', ';keys=semi,%3B,dot,.,comma,%2C' assert_expansion_equal '{;keys*}', ';semi=%3B;dot=.;comma=%2C' end def test_query_expansion assert_expansion_equal '{?who}', '?who=fred' assert_expansion_equal '{?half}', '?half=50%25' assert_expansion_equal '{?x,y}', '?x=1024&y=768' assert_expansion_equal '{?x,y,empty}', '?x=1024&y=768&empty=' assert_expansion_equal '{?x,y,undef}', '?x=1024&y=768' assert_expansion_equal '{?var:3}', '?var=val' assert_expansion_equal '{?list}', '?list=red,green,blue' assert_expansion_equal '{?list*}', '?list=red&list=green&list=blue' assert_expansion_equal '{?keys}', '?keys=semi,%3B,dot,.,comma,%2C' assert_expansion_equal '{?keys*}', '?semi=%3B&dot=.&comma=%2C' end def test_query_continuation assert_expansion_equal '{&who}', '&who=fred' assert_expansion_equal '{&half}', '&half=50%25' assert_expansion_equal '?fixed=yes{&x}', '?fixed=yes&x=1024' assert_expansion_equal '{&x,y,empty}', '&x=1024&y=768&empty=' assert_expansion_equal '{&x,y,undef}', '&x=1024&y=768' assert_expansion_equal '{&var:3}', '&var=val' assert_expansion_equal '{&list}', '&list=red,green,blue' assert_expansion_equal '{&list*}', '&list=red&list=green&list=blue' assert_expansion_equal '{&keys}', '&keys=semi,%3B,dot,.,comma,%2C' assert_expansion_equal '{&keys*}', '&semi=%3B&dot=.&comma=%2C' end private def assert_expansion_equal(template, expected) value = KDL::Types::URLTemplate.call(::KDL::Value::String.new(template)) assert_equal(URI(expected), value.expand(@variables)) end end danini-the-panini-kdl-rb-56d7cf1/test/types/url_test.rb000066400000000000000000000015641515522600200231150ustar00rootroot00000000000000# frozen_string_literal: true require "test_helper" class URLTest < Minitest::Test def test_url value = KDL::Types::URL.call(::KDL::Value::String.new('https://www.example.com/foo/bar')) assert_equal URI('https://www.example.com/foo/bar'), value.value assert_raises { KDL::Types::URL.call(::KDL::Value::String.new('not a url')) } assert_raises { KDL::Types::URL.call(::KDL::Value::String.new('/reference/to/something')) } end def test_url_reference value = KDL::Types::URLReference.call(::KDL::Value::String.new('https://www.example.com/foo/bar')) assert_equal URI('https://www.example.com/foo/bar'), value.value value = KDL::Types::URLReference.call(::KDL::Value::String.new('/foo/bar')) assert_equal URI('/foo/bar'), value.value assert_raises { KDL::Types::URLReference.call(::KDL::Value::String.new('not a url reference')) } end end danini-the-panini-kdl-rb-56d7cf1/test/types/uuid_test.rb000066400000000000000000000010271515522600200232530ustar00rootroot00000000000000# frozen_string_literal: true require "test_helper" class UUIDTest < Minitest::Test def test_uuid value = KDL::Types::UUID.call(::KDL::Value::String.new('f81d4fae-7dec-11d0-a765-00a0c91e6bf6')) assert_equal 'f81d4fae-7dec-11d0-a765-00a0c91e6bf6', value.value value = KDL::Types::UUID.call(::KDL::Value::String.new('F81D4FAE-7DEC-11D0-A765-00A0C91E6BF6')) assert_equal 'f81d4fae-7dec-11d0-a765-00a0c91e6bf6', value.value assert_raises { KDL::Types::UUID.call(::KDL::Value::String.new('not a uuid')) } end end danini-the-panini-kdl-rb-56d7cf1/test/types_test.rb000066400000000000000000000074621515522600200223160ustar00rootroot00000000000000# frozen_string_literal: true require 'test_helper' class TypesTest < Minitest::Test def test_types doc = KDL.parse <<-KDL node (date-time)"2021-01-01T12:12:12" \\ (date)"2021-01-01" \\ (time)"22:23:12" \\ (duration)"P3Y6M4DT12H30M5S" \\ (currency)"ZAR" \\ (country-3)"ZAF" \\ (country-2)"ZA" \\ (country-subdivision)"ZA-GP" \\ (ipv4)"127.0.0.1" \\ (ipv6)"3ffe:505:2::1" \\ (url)"https://kdl.dev" \\ (url-reference)"/foo/bar" \\ (uuid)"f81d4fae-7dec-11d0-a765-00a0c91e6bf6" \\ (regex)"asdf" \\ (base64)"U2VuZCByZWluZm9yY2VtZW50cw==" \\ (decimal)"10000000000000" \\ (hostname)"www.example.com" \\ (idn-hostname)"xn--bcher-kva.example" \\ (email)"simple@example.com" \\ (idn-email)"๐ŸŒˆ@xn--9ckb.com" \\ (irl)"https://kdl.dev/๐Ÿฆ„" \\ (irl-reference)"/๐ŸŒˆ/๐Ÿฆ„" \\ (url-template)"https://kdl.dev/{foo}" KDL refute_nil doc i = -1 assert_kind_of ::KDL::Types::DateTime, doc.nodes.first.arguments[i += 1] assert_kind_of ::KDL::Types::Date, doc.nodes.first.arguments[i += 1] assert_kind_of ::KDL::Types::Time, doc.nodes.first.arguments[i += 1] assert_kind_of ::KDL::Types::Duration, doc.nodes.first.arguments[i += 1] assert_kind_of ::KDL::Types::Currency, doc.nodes.first.arguments[i += 1] assert_kind_of ::KDL::Types::Country3, doc.nodes.first.arguments[i += 1] assert_kind_of ::KDL::Types::Country2, doc.nodes.first.arguments[i += 1] assert_kind_of ::KDL::Types::CountrySubdivision, doc.nodes.first.arguments[i += 1] assert_kind_of ::KDL::Types::IPV4, doc.nodes.first.arguments[i += 1] assert_kind_of ::KDL::Types::IPV6, doc.nodes.first.arguments[i += 1] assert_kind_of ::KDL::Types::URL, doc.nodes.first.arguments[i += 1] assert_kind_of ::KDL::Types::URLReference, doc.nodes.first.arguments[i += 1] assert_kind_of ::KDL::Types::UUID, doc.nodes.first.arguments[i += 1] assert_kind_of ::KDL::Types::Regex, doc.nodes.first.arguments[i += 1] assert_kind_of ::KDL::Types::Base64, doc.nodes.first.arguments[i += 1] assert_kind_of ::KDL::Types::Decimal, doc.nodes.first.arguments[i += 1] assert_kind_of ::KDL::Types::Hostname, doc.nodes.first.arguments[i += 1] assert_kind_of ::KDL::Types::IDNHostname, doc.nodes.first.arguments[i += 1] assert_kind_of ::KDL::Types::Email, doc.nodes.first.arguments[i += 1] assert_kind_of ::KDL::Types::IDNEmail, doc.nodes.first.arguments[i += 1] assert_kind_of ::KDL::Types::IRL, doc.nodes.first.arguments[i += 1] assert_kind_of ::KDL::Types::IRLReference, doc.nodes.first.arguments[i += 1] assert_kind_of ::KDL::Types::URLTemplate, doc.nodes.first.arguments[i += 1] end def test_custom_types parsers = { 'foo' => lambda { |value, type| Foo.new(value.value, type: type) if value.is_a?(KDL::Value) }, 'bar' => lambda { |node, type| Bar.new(node, type: type) if node.is_a?(KDL::Node) } } doc = KDL.parse <<-KDL, type_parsers: parsers (bar)barnode (foo)"foovalue" (foo)foonode (bar)"barvalue" KDL refute_nil doc assert_kind_of Bar, doc.nodes.first assert_kind_of Foo, doc.nodes.first.arguments.first assert_kind_of KDL::Node, doc.nodes[1] assert_kind_of KDL::Value, doc.nodes[1].arguments.first end def test_parse_false doc = KDL.parse <<-KDL, parse_types: false node (date-time)"2021-01-01T12:12:12" KDL refute_nil doc assert_kind_of ::KDL::Value::String, doc.nodes.first.arguments.first end class Foo < KDL::Value::Custom end class Bar < KDL::Node::Custom def initialize(node, type: nil) super(node.name, arguments: node.arguments, properties: node.properties, children: node.children, type: type) end end end danini-the-panini-kdl-rb-56d7cf1/test/v1/000077500000000000000000000000001515522600200201035ustar00rootroot00000000000000danini-the-panini-kdl-rb-56d7cf1/test/v1/document_test.rb000066400000000000000000000012121515522600200233010ustar00rootroot00000000000000# frozen_string_literal: true require "test_helper" class KDL::V1::DocumentTest < Minitest::Test def test_version assert_equal 1, KDL::V1::Document.new([]).version end def test_to_v2 doc = KDL.parse <<~KDL, version: 1 foo "lorem" 1 true null { bar " baz qux " } KDL assert_equal 1, doc.version doc = doc.to_v2 assert_equal 2, doc.version assert_equal <<~KDL, doc.to_s foo lorem 1 #true #null { bar "\\n baz\\n qux\\n " } KDL end def test_to_v1 doc = KDL::V1::Document.new([]) assert_same doc, doc.to_v1 end end danini-the-panini-kdl-rb-56d7cf1/test/v1/examples_test.rb000066400000000000000000000053231515522600200233100ustar00rootroot00000000000000# frozen_string_literal: true require "test_helper" class KDL::V1::ExamplesTest < Minitest::Test def example_path(name) File.join(__dir__, "kdl-org/examples/#{name}.kdl") end def test_ci doc = ::KDL.load_file(example_path('ci')) nodes = KDL.build { name "CI" on "push", "pull_request" env { RUSTFLAGS "-Dwarnings" } jobs { fmt_and_docs("Check fmt & build docs") { _ "runs-on", "ubuntu-latest" steps { step uses: "actions/checkout@v1" step("Install Rust", uses: "actions-rs/toolchain@v1") { profile "minimal" toolchain "stable" components "rustfmt" override true } step "rustfmt", run: "cargo fmt --all -- --check" step "docs", run: "cargo doc --no-deps" } } build_and_test("Build & Test") { _ "runs-on", "${{ matrix.os }}" strategy { matrix { rust "1.46.0", "stable" os "ubuntu-latest", "macOS-latest", "windows-latest" } } steps { step uses: "actions/checkout@v1" step("Install Rust", uses: "actions-rs/toolchain@v1") { profile "minimal" toolchain "${{ matrix.rust }}" components "clippy" override true } step "Clippy", run: "cargo clippy --all -- -D warnings" step "Run tests", run: "cargo test --all --verbose" } } } } assert_equal nodes, doc end def test_cargo doc = ::KDL.load_file(example_path('Cargo')) nodes = KDL.build { package { name "kdl" version "0.0.0" description "kat's document language" authors "Kat Marchรกn " _ "license-file", "LICENSE.md" edition "2018" } dependencies { nom "6.0.1" thiserror "1.0.22" } } assert_equal nodes, doc end def test_nuget doc = ::KDL.load_file(example_path('nuget')) # This file is particularly large. It would be nice to validate it, but for now # I'm just going to settle for making sure it parses. refute_nil doc end def test_kdl_schema doc = ::KDL.load_file(example_path('kdl-schema')) # This file is particularly large. It would be nice to validate it, but for now # I'm just going to settle for making sure it parses. refute_nil doc end def test_website doc = ::KDL.load_file(example_path('website')) # This file is particularly large. It would be nice to validate it, but for now # I'm just going to settle for making sure it parses. refute_nil doc end end danini-the-panini-kdl-rb-56d7cf1/test/v1/kdl-org/000077500000000000000000000000001515522600200214425ustar00rootroot00000000000000danini-the-panini-kdl-rb-56d7cf1/test/v1/node_test.rb000066400000000000000000000014111515522600200224110ustar00rootroot00000000000000# frozen_string_literal: true require "test_helper" class KDL::V1::NodeTest < Minitest::Test def test_version node = KDL::V1::Node.new("foo") assert_equal 1, node.version end def test_to_v2 node = KDL::V1::Node.new("foo", arguments: [v(true)], properties: { bar: v("baz") }, children: [KDL::V1::Node.new("qux")] ) node = node.to_v2 assert_equal 2, node.version assert_equal 2, node.arguments[0].version assert_equal 2, node.properties['bar'].version assert_equal 2, node.child(0).version end def test_to_v1 node = KDL::V1::Node.new("foo") assert_same node, node.to_v1 end private def v(x, t=nil) val = ::KDL::V1::Value.from(x) return val.as_type(t) if t val end end danini-the-panini-kdl-rb-56d7cf1/test/v1/parser_test.rb000066400000000000000000000465231515522600200227750ustar00rootroot00000000000000# frozen_string_literal: true require "test_helper" class KDL::V1::ParserTest < Minitest::Test def setup @parser = ::KDL::V1::Parser.new end def test_parse_empty_string assert_equal ::KDL::Document.new([]), @parser.parse('') assert_equal ::KDL::Document.new([]), @parser.parse(' ') assert_equal ::KDL::Document.new([]), @parser.parse("\n") end def test_nodes assert_equal ::KDL::Document.new([::KDL::Node.new('node')]), @parser.parse('node') assert_equal ::KDL::Document.new([::KDL::Node.new('node')]), @parser.parse("node\n") assert_equal ::KDL::Document.new([::KDL::Node.new('node')]), @parser.parse("\nnode\n") assert_equal ::KDL::Document.new([::KDL::Node.new('node1'), ::KDL::Node.new('node2')]), @parser.parse("node1\nnode2") end def test_node assert_equal ::KDL::Document.new([::KDL::Node.new('node')]), @parser.parse('node;') assert_equal ::KDL::Document.new([::KDL::Node.new('node', [::KDL::Value::Int.new(1)])]), @parser.parse('node 1') assert_equal ::KDL::Document.new([::KDL::Node.new('node', [::KDL::Value::Int.new(1), ::KDL::Value::Int.new(2), ::KDL::Value::String.new("3"), ::KDL::Value::Boolean.new(true), ::KDL::Value::Boolean.new(false), ::KDL::Value::Null])]), @parser.parse('node 1 2 "3" true false null') assert_equal ::KDL::Document.new([::KDL::Node.new('node', [], {}, [::KDL::Node.new('node2')])]), @parser.parse("node {\n node2\n}") assert_equal ::KDL::Document.new([::KDL::Node.new('node', [], {}, [::KDL::Node.new('node2')])]), @parser.parse("node { node2; }") end def test_node_slashdash_comment assert_equal ::KDL::Document.new([]), @parser.parse('/-node') assert_equal ::KDL::Document.new([]), @parser.parse('/- node') assert_equal ::KDL::Document.new([]), @parser.parse("/- node\n") assert_equal ::KDL::Document.new([]), @parser.parse('/-node 1 2 3') assert_equal ::KDL::Document.new([]), @parser.parse('/-node key=false') assert_equal ::KDL::Document.new([]), @parser.parse("/-node{\nnode\n}") assert_equal ::KDL::Document.new([]), @parser.parse("/-node 1 2 3 key=\"value\" \\\n{\nnode\n}") end def test_arg_slashdash_comment assert_equal ::KDL::Document.new([::KDL::Node.new('node')]), @parser.parse('node /-1') assert_equal ::KDL::Document.new([::KDL::Node.new('node', [::KDL::Value::Int.new(2)])]), @parser.parse('node /-1 2') assert_equal ::KDL::Document.new([::KDL::Node.new('node', [::KDL::Value::Int.new(1), ::KDL::Value::Int.new(3)])]), @parser.parse('node 1 /- 2 3') assert_equal ::KDL::Document.new([::KDL::Node.new('node')]), @parser.parse('node /--1') assert_equal ::KDL::Document.new([::KDL::Node.new('node')]), @parser.parse('node /- -1') assert_equal ::KDL::Document.new([::KDL::Node.new('node')]), @parser.parse("node \\\n/- -1") end def test_prop_slashdash_comment assert_equal ::KDL::Document.new([::KDL::Node.new('node')]), @parser.parse('node /-key=1') assert_equal ::KDL::Document.new([::KDL::Node.new('node')]), @parser.parse('node /- key=1') assert_equal ::KDL::Document.new([::KDL::Node.new('node', [], { 'key' => ::KDL::Value::Int.new(1) })]), @parser.parse('node key=1 /-key2=2') end def test_children_slashdash_comment assert_equal ::KDL::Document.new([::KDL::Node.new('node')]), @parser.parse('node /-{}') assert_equal ::KDL::Document.new([::KDL::Node.new('node')]), @parser.parse('node /- {}') assert_equal ::KDL::Document.new([::KDL::Node.new('node')]), @parser.parse("node /-{\nnode2\n}") end def test_empty_children assert_equal ::KDL::Document.new([::KDL::Node.new('node')]), @parser.parse('node {}') assert_equal ::KDL::Document.new([::KDL::Node.new('node')]), @parser.parse("node {\n /-node2\n}") assert_equal ::KDL::Document.new([::KDL::Node.new('node')]), @parser.parse("node /-{\n node2\n}") end def test_string assert_equal ::KDL::Document.new([::KDL::Node.new('node', [::KDL::Value::String.new("")])]), @parser.parse('node ""') assert_equal ::KDL::Document.new([::KDL::Node.new('node', [::KDL::Value::String.new("hello")])]), @parser.parse('node "hello"') assert_equal ::KDL::Document.new([::KDL::Node.new('node', [::KDL::Value::String.new("hello\nworld")])]), @parser.parse('node "hello\\nworld"') assert_equal ::KDL::Document.new([::KDL::Node.new('node', [::KDL::Value::String.new("\u{10FFF}")])]), @parser.parse('node "\\u{10FFF}"') assert_equal ::KDL::Document.new([::KDL::Node.new('node', [::KDL::Value::String.new("\"\\/\u{08}\u{0C}\n\r\t")])]), @parser.parse('node "\"\\\\\/\b\f\n\r\t"') assert_equal ::KDL::Document.new([::KDL::Node.new('node', [::KDL::Value::String.new("\u{10}")])]), @parser.parse('node "\u{10}"') assert_raises { @parser.parse('node "\i"') } assert_raises { @parser.parse('node "\u{c0ffee}"') } assert_raises { @parser.parse('node "oops') } end def test_float assert_equal ::KDL::Document.new([::KDL::Node.new('node', [::KDL::Value::Float.new(1.0)])]), @parser.parse('node 1.0') assert_equal ::KDL::Document.new([::KDL::Node.new('node', [::KDL::Value::Float.new(0.0)])]), @parser.parse('node 0.0') assert_equal ::KDL::Document.new([::KDL::Node.new('node', [::KDL::Value::Float.new(-1.0)])]), @parser.parse('node -1.0') assert_equal ::KDL::Document.new([::KDL::Node.new('node', [::KDL::Value::Float.new(1.0)])]), @parser.parse('node +1.0') assert_equal ::KDL::Document.new([::KDL::Node.new('node', [::KDL::Value::Float.new(1.0e10)])]), @parser.parse('node 1.0e10') assert_equal ::KDL::Document.new([::KDL::Node.new('node', [::KDL::Value::Float.new(1.0e-10)])]), @parser.parse('node 1.0e-10') assert_equal ::KDL::Document.new([::KDL::Node.new('node', [::KDL::Value::Float.new(123456789.0)])]), @parser.parse('node 123_456_789.0') assert_equal ::KDL::Document.new([::KDL::Node.new('node', [::KDL::Value::Float.new(123456789.0)])]), @parser.parse('node 123_456_789.0') assert_raises { @parser.parse('node ?1.0') } assert_raises { @parser.parse('node _1.0') } assert_raises { @parser.parse('node 1._0') } assert_raises { @parser.parse('node 1.') } assert_raises { @parser.parse('node .0') } end def test_integer assert_equal ::KDL::Document.new([::KDL::Node.new('node', [::KDL::Value::Int.new(0)])]), @parser.parse('node 0') assert_equal ::KDL::Document.new([::KDL::Node.new('node', [::KDL::Value::Int.new(123456789)])]), @parser.parse('node 0123456789') assert_equal ::KDL::Document.new([::KDL::Node.new('node', [::KDL::Value::Int.new(123456789)])]), @parser.parse('node 0123_456_789') assert_equal ::KDL::Document.new([::KDL::Node.new('node', [::KDL::Value::Int.new(123456789)])]), @parser.parse('node 0123_456_789_') assert_equal ::KDL::Document.new([::KDL::Node.new('node', [::KDL::Value::Int.new(123456789)])]), @parser.parse('node +0123456789') assert_equal ::KDL::Document.new([::KDL::Node.new('node', [::KDL::Value::Int.new(-123456789)])]), @parser.parse('node -0123456789') assert_raises { @parser.parse('node ?0123456789') } assert_raises { @parser.parse('node _0123456789') } assert_raises { @parser.parse('node a') } assert_raises { @parser.parse('node --') } end def test_hexadecimal assert_equal ::KDL::Document.new([::KDL::Node.new('node', [::KDL::Value::Int.new(0x0123456789abcdef)])]), @parser.parse('node 0x0123456789abcdef') assert_equal ::KDL::Document.new([::KDL::Node.new('node', [::KDL::Value::Int.new(0x0123456789abcdef)])]), @parser.parse('node 0x01234567_89abcdef') assert_equal ::KDL::Document.new([::KDL::Node.new('node', [::KDL::Value::Int.new(0x0123456789abcdef)])]), @parser.parse('node 0x01234567_89abcdef_') assert_raises { @parser.parse('node 0x_123') } assert_raises { @parser.parse('node 0xg') } assert_raises { @parser.parse('node 0xx') } end def test_octal assert_equal ::KDL::Document.new([::KDL::Node.new('node', [::KDL::Value::Int.new(0o01234567)])]), @parser.parse('node 0o01234567') assert_equal ::KDL::Document.new([::KDL::Node.new('node', [::KDL::Value::Int.new(0o01234567)])]), @parser.parse('node 0o0123_4567') assert_equal ::KDL::Document.new([::KDL::Node.new('node', [::KDL::Value::Int.new(0o01234567)])]), @parser.parse('node 0o01234567_') assert_raises { @parser.parse('node 0o_123') } assert_raises { @parser.parse('node 0o8') } assert_raises { @parser.parse('node 0oo') } end def test_binary assert_equal ::KDL::Document.new([::KDL::Node.new('node', [::KDL::Value::Int.new(0b0101)])]), @parser.parse('node 0b0101') assert_equal ::KDL::Document.new([::KDL::Node.new('node', [::KDL::Value::Int.new(0b0110)])]), @parser.parse('node 0b01_10') assert_equal ::KDL::Document.new([::KDL::Node.new('node', [::KDL::Value::Int.new(0b0110)])]), @parser.parse('node 0b01___10') assert_equal ::KDL::Document.new([::KDL::Node.new('node', [::KDL::Value::Int.new(0b0110)])]), @parser.parse('node 0b0110_') assert_raises { @parser.parse('node 0b_0110') } assert_raises { @parser.parse('node 0b20') } assert_raises { @parser.parse('node 0bb') } end def test_raw_string assert_equal ::KDL::Document.new([::KDL::Node.new('node', [::KDL::Value::String.new('foo')])]), @parser.parse('node r"foo"') assert_equal ::KDL::Document.new([::KDL::Node.new('node', [::KDL::Value::String.new('foo\nbar')])]), @parser.parse('node r"foo\nbar"') assert_equal ::KDL::Document.new([::KDL::Node.new('node', [::KDL::Value::String.new('foo')])]), @parser.parse('node r#"foo"#') assert_equal ::KDL::Document.new([::KDL::Node.new('node', [::KDL::Value::String.new('foo')])]), @parser.parse('node r##"foo"##') assert_equal ::KDL::Document.new([::KDL::Node.new('node', [::KDL::Value::String.new('\nfoo\r')])]), @parser.parse('node r"\nfoo\r"') assert_raises { @parser.parse('node r##"foo"#') } end def test_boolean assert_equal ::KDL::Document.new([::KDL::Node.new('node', [::KDL::Value::Boolean.new(true)])]), @parser.parse('node true') assert_equal ::KDL::Document.new([::KDL::Node.new('node', [::KDL::Value::Boolean.new(false)])]), @parser.parse('node false') end def test_node_space assert_equal ::KDL::Document.new([::KDL::Node.new('node', [::KDL::Value::Int.new(1)])]), @parser.parse('node 1') assert_equal ::KDL::Document.new([::KDL::Node.new('node', [::KDL::Value::Int.new(1)])]), @parser.parse("node\t1") assert_equal ::KDL::Document.new([::KDL::Node.new('node', [::KDL::Value::Int.new(1)])]), @parser.parse("node\t \\ // hello\n 1") end def test_single_line_comment assert_equal ::KDL::Document.new([]), @parser.parse('//hello') assert_equal ::KDL::Document.new([]), @parser.parse("// \thello") assert_equal ::KDL::Document.new([]), @parser.parse("//hello\n") assert_equal ::KDL::Document.new([]), @parser.parse("//hello\r\n") assert_equal ::KDL::Document.new([]), @parser.parse("//hello\n\r") assert_equal ::KDL::Document.new([::KDL::Node.new('world')]), @parser.parse("//hello\rworld") assert_equal ::KDL::Document.new([::KDL::Node.new('world')]), @parser.parse("//hello\nworld\r\n") end def test_multi_line_comment assert_equal ::KDL::Document.new([]), @parser.parse("/*hello*/") assert_equal ::KDL::Document.new([]), @parser.parse("/*hello*/\n") assert_equal ::KDL::Document.new([]), @parser.parse("/*\nhello\r\n*/") assert_equal ::KDL::Document.new([]), @parser.parse("/*\nhello** /\n*/") assert_equal ::KDL::Document.new([]), @parser.parse("/**\nhello** /\n*/") assert_equal ::KDL::Document.new([::KDL::Node.new('world')]), @parser.parse('/*hello*/world') end def test_escline assert_equal ::KDL::Document.new([::KDL::Node.new('node', [::KDL::Value.from(1)])]), @parser.parse("node\\\n 1") assert_raises { @parser.parse("node\\\nnode2") } assert_raises { @parser.parse("node\\\\\nnode2") } assert_raises { @parser.parse("node \\\\\nnode2") } assert_raises { @parser.parse("node \\ //comment\n node2") } end def test_whitespace assert_equal ::KDL::Document.new([::KDL::Node.new('node')]), @parser.parse(" node") assert_equal ::KDL::Document.new([::KDL::Node.new('node')]), @parser.parse("\tnode") assert_equal ::KDL::Document.new([::KDL::Node.new('etc')]), @parser.parse("/* \nfoo\r\n */ etc") end def test_newline assert_equal ::KDL::Document.new([::KDL::Node.new('node1'), ::KDL::Node.new('node2')]), @parser.parse("node1\nnode2") assert_equal ::KDL::Document.new([::KDL::Node.new('node1'), ::KDL::Node.new('node2')]), @parser.parse("node1\rnode2") assert_equal ::KDL::Document.new([::KDL::Node.new('node1'), ::KDL::Node.new('node2')]), @parser.parse("node1\r\nnode2") assert_equal ::KDL::Document.new([::KDL::Node.new('node1'), ::KDL::Node.new('node2')]), @parser.parse("node1\n\nnode2") end def test_basic doc = @parser.parse('title "Hello, World"') nodes = KDL.build { title "Hello, World" } assert_equal nodes, doc end def test_multiple_values doc = @parser.parse('bookmarks 12 15 188 1234') nodes = KDL.build { bookmarks 12, 15, 188, 1234 } assert_equal nodes, doc end def test_properties doc = @parser.parse <<~KDL author "Alex Monad" email="alex@example.com" active=true foo bar=true "baz" quux=false 1 2 3 KDL nodes = KDL.build { author "Alex Monad", email: "alex@example.com", active: true foo "baz", 1, 2, 3, bar: true, quux: false } assert_equal nodes, doc end def test_nested_child_nodes doc = @parser.parse <<~KDL contents { section "First section" { paragraph "This is the first paragraph" paragraph "This is the second paragraph" } } KDL nodes = KDL.build { contents { section("First section") { paragraph "This is the first paragraph" paragraph "This is the second paragraph" } } } assert_equal nodes, doc end def test_semicolon doc = @parser.parse('node1; node2; node3;') nodes = KDL.build { node1; node2; node3; } assert_equal nodes, doc end def test_raw_strings doc = @parser.parse <<~KDL foo "this\\nhas\\tescapes" bar r"C:\\Users\\zkat\\" baz r#"hello"world"# KDL nodes = KDL.build { foo "this\nhas\tescapes" bar "C:\\Users\\zkat\\" baz "hello\"world" } assert_equal nodes, doc end def test_multiline_strings doc = @parser.parse <<~KDL string "my multiline value" KDL nodes = KDL.build { string "my\nmultiline\nvalue" } assert_equal nodes, doc end def test_numbers doc = @parser.parse <<~KDL num 1.234e-42 my-hex 0xdeadbeef my-octal 0o755 my-binary 0b10101101 bignum 1_000_000 KDL nodes = KDL.build { num 1.234e-42 _ 'my-hex', 0xdeadbeef _ 'my-octal', 0o755 _ 'my-binary', 0b10101101 bignum 1_000_000 } assert_equal nodes, doc end def test_comments doc = @parser.parse <<~KDL // C style /* C style multiline */ tag /*foo=true*/ bar=false /*/* hello */*/ KDL nodes = KDL.build { tag bar: false } assert_equal nodes, doc end def test_slash_dash doc = @parser.parse <<~KDL /-mynode "foo" key=1 { a b c } mynode /-"commented" "not commented" /-key="value" /-{ a b } KDL nodes = KDL.build { mynode("not commented") { } } assert_equal nodes, doc end def test_multiline_nodes doc = @parser.parse <<~KDL title \\ "Some title" my-node 1 2 \\ // comments are ok after \\ 3 4 KDL nodes = KDL.build { title "Some title" _ "my-node", 1, 2, 3, 4 } assert_equal nodes, doc end def test_utf8 doc = @parser.parse <<~KDL smile "๐Ÿ˜" ใƒŽใƒผใƒ‰ ใŠๅๅ‰="โ˜œ(๏พŸใƒฎ๏พŸโ˜œ)" KDL nodes = ::KDL::Document.new([ ::KDL::Node.new('smile', [::KDL::Value::String.new('๐Ÿ˜')]), ::KDL::Node.new('ใƒŽใƒผใƒ‰', [], { 'ใŠๅๅ‰' => ::KDL::Value::String.new('โ˜œ(๏พŸใƒฎ๏พŸโ˜œ)') }) ]) assert_equal nodes, doc end def test_node_names doc = @parser.parse <<~KDL "!@#$@$%Q#$%~@!40" "1.2.3" "!!!!!"=true foo123~!@#$%^&*.:'|?+ "weeee" - 1 KDL nodes = KDL.build { _ "!@#$@$%Q#$%~@!40", "1.2.3", "!!!!!": true _ "foo123~!@#$%^&*.:'|?+", "weeee" _ "-", 1 } assert_equal nodes, doc end def test_escaping doc = @parser.parse <<~KDL node1 "\\u{1f600}" node2 "\\n\\t\\r\\\\\\"\\f\\b" KDL nodes = KDL.build { node1 "๐Ÿ˜€" node2 "\n\t\r\\\"\f\b" } assert_equal nodes, doc end def test_node_type doc = @parser.parse <<~KDL (foo)node KDL nodes = ::KDL::Document.new([ ::KDL::Node.new('node', type: 'foo'), ]) assert_equal nodes, doc end def test_value_type doc = @parser.parse <<~KDL node (foo)"bar" KDL nodes = ::KDL::Document.new([ ::KDL::Node.new('node', [::KDL::Value::String.new('bar', type: 'foo')]), ]) assert_equal nodes, doc end def test_property_type doc = @parser.parse <<~KDL node baz=(foo)"bar" KDL nodes = ::KDL::Document.new([ ::KDL::Node.new('node', [], { 'baz' => ::KDL::Value::String.new('bar', type: 'foo') }), ]) assert_equal nodes, doc end def test_child_type doc = @parser.parse <<~KDL node { (foo)bar } KDL nodes = ::KDL::Document.new([ ::KDL::Node.new('node', [], {}, [ ::KDL::Node.new('bar', type: 'foo') ]), ]) assert_equal nodes, doc end def test_version_directive refute_nil @parser.parse <<~KDL /- kdl-version 1 node "foo" KDL assert_raises(KDL::VersionMismatchError) do @parser.parse <<~KDL /- kdl-version 2 node "foo" KDL end end end danini-the-panini-kdl-rb-56d7cf1/test/v1/spec_test.rb000066400000000000000000000020271515522600200224220ustar00rootroot00000000000000# frozen_string_literal: true require 'test_helper' class KDL::V1::SpecTest < Minitest::Test TEST_CASES_DIR = File.join(__dir__, 'kdl-org/tests/test_cases') INPUTS_DIR = File.join(TEST_CASES_DIR, 'input') EXPECTED_DIR = File.join(TEST_CASES_DIR, 'expected_kdl') EXCLUDE = %w[ escline_comment_node ] Dir.glob(File.join(INPUTS_DIR, '*.kdl')).each do |input_path| input_name = File.basename(input_path, '.kdl') next if EXCLUDE.include?(input_name) expected_path = File.join(EXPECTED_DIR, "#{input_name}.kdl") if File.exist?(expected_path) define_method "test_v1_#{input_name}_matches_expected_output" do expected = File.read(expected_path, encoding: Encoding::UTF_8) assert_equal expected, ::KDL.load_file(input_path, version: 1).to_s end else define_method "test_v1_#{input_name}_does_not_parse" do err = assert_raises { ::KDL.load_file(input_path, version: 1) } raise err unless err.is_a?(KDL::Error) || err.is_a?(Racc::ParseError) end end end end danini-the-panini-kdl-rb-56d7cf1/test/v1/tokenizer_test.rb000066400000000000000000000232421515522600200235040ustar00rootroot00000000000000# frozen_string_literal: true require "test_helper" class KDL::V1::TokenizerTest < Minitest::Test def test_identifier assert_equal t(:IDENT, "foo"), ::KDL::V1::Tokenizer.new("foo").next_token assert_equal t(:IDENT, "foo-bar123"), ::KDL::V1::Tokenizer.new("foo-bar123").next_token assert_equal t(:IDENT, "-"), ::KDL::V1::Tokenizer.new("-").next_token assert_equal t(:IDENT, "--"), ::KDL::V1::Tokenizer.new("--").next_token end def test_string assert_equal t(:STRING, "foo"), ::KDL::V1::Tokenizer.new('"foo"').next_token assert_equal t(:STRING, "foo\nbar"), ::KDL::V1::Tokenizer.new('"foo\nbar"').next_token end def test_rawstring assert_equal t(:RAWSTRING, "foo\\nbar"), ::KDL::V1::Tokenizer.new('r"foo\\nbar"').next_token assert_equal t(:RAWSTRING, "foo\"bar"), ::KDL::V1::Tokenizer.new('r#"foo"bar"#').next_token assert_equal t(:RAWSTRING, "foo\"#bar"), ::KDL::V1::Tokenizer.new('r##"foo"#bar"##').next_token assert_equal t(:RAWSTRING, "\"foo\""), ::KDL::V1::Tokenizer.new('r#""foo""#').next_token tokenizer = ::KDL::V1::Tokenizer.new('node r"C:\\Users\\zkat\\"') assert_equal t(:IDENT, "node"), tokenizer.next_token assert_equal t(:WS, " ", 1, 5), tokenizer.next_token assert_equal t(:RAWSTRING, "C:\\Users\\zkat\\", 1, 6), tokenizer.next_token tokenizer = ::KDL::V1::Tokenizer.new('other-node r#"hello"world"#') assert_equal t(:IDENT, "other-node"), tokenizer.next_token assert_equal t(:WS, " ", 1, 11), tokenizer.next_token assert_equal t(:RAWSTRING, "hello\"world", 1, 12), tokenizer.next_token end def test_integer assert_equal t(:INTEGER, 123), ::KDL::V1::Tokenizer.new("123").next_token assert_equal t(:INTEGER, 0x0123456789abcdef), ::KDL::V1::Tokenizer.new("0x0123456789abcdef").next_token assert_equal t(:INTEGER, 0o01234567), ::KDL::V1::Tokenizer.new("0o01234567").next_token assert_equal t(:INTEGER, 0b101001), ::KDL::V1::Tokenizer.new("0b101001").next_token assert_equal t(:INTEGER, -0x0123456789abcdef), ::KDL::V1::Tokenizer.new("-0x0123456789abcdef").next_token assert_equal t(:INTEGER, -0o01234567), ::KDL::V1::Tokenizer.new("-0o01234567").next_token assert_equal t(:INTEGER, -0b101001), ::KDL::V1::Tokenizer.new("-0b101001").next_token end def test_float assert_equal t(:FLOAT, 1.23), ::KDL::V1::Tokenizer.new("1.23").next_token end def test_boolean assert_equal t(:TRUE, true), ::KDL::V1::Tokenizer.new("true").next_token assert_equal t(:FALSE, false), ::KDL::V1::Tokenizer.new("false").next_token end def test_null assert_equal t(:NULL, nil), ::KDL::V1::Tokenizer.new("null").next_token end def test_symbols assert_equal t(:LBRACE, '{'), ::KDL::V1::Tokenizer.new("{").next_token assert_equal t(:RBRACE, '}'), ::KDL::V1::Tokenizer.new("}").next_token assert_equal t(:EQUALS, '='), ::KDL::V1::Tokenizer.new("=").next_token end def test_whitespace assert_equal t(:WS, ' '), ::KDL::V1::Tokenizer.new(" ").next_token assert_equal t(:WS, "\t"), ::KDL::V1::Tokenizer.new("\t").next_token assert_equal t(:WS, " \t"), ::KDL::V1::Tokenizer.new(" \t").next_token end def test_escline assert_equal t(:WS, "\\\n"), ::KDL::V1::Tokenizer.new("\\\n").next_token assert_equal t(:WS, "\\\n"), ::KDL::V1::Tokenizer.new("\\\n//some comment").next_token assert_equal t(:WS, "\\\n "), ::KDL::V1::Tokenizer.new("\\\n //some comment").next_token assert_equal t(:STRING, "foo"), ::KDL::V1::Tokenizer.new("\"\\\n\n\nfoo\"").next_token end def test_multiple_tokens tokenizer = ::KDL::V1::Tokenizer.new("node 1 \"two\" a=3") assert_equal t(:IDENT, 'node'), tokenizer.next_token assert_equal t(:WS, ' ', 1, 5), tokenizer.next_token assert_equal t(:INTEGER, 1, 1, 6), tokenizer.next_token assert_equal t(:WS, ' ', 1, 7), tokenizer.next_token assert_equal t(:STRING, 'two', 1, 8), tokenizer.next_token assert_equal t(:WS, ' ', 1, 13), tokenizer.next_token assert_equal t(:IDENT, 'a', 1, 14), tokenizer.next_token assert_equal t(:EQUALS, '=', 1, 15), tokenizer.next_token assert_equal t(:INTEGER, 3, 1, 16), tokenizer.next_token assert_equal t(:EOF, :EOF, 1, 17), tokenizer.next_token assert_equal eof(1, 17), tokenizer.next_token end def test_single_line_comment assert_equal t(:EOF, :EOF), ::KDL::V1::Tokenizer.new("// comment").next_token tokenizer = ::KDL::V1::Tokenizer.new <<~KDL node1 // comment node2 KDL assert_equal t(:IDENT, 'node1'), tokenizer.next_token assert_equal t(:NEWLINE, "\n", 1, 6), tokenizer.next_token assert_equal t(:NEWLINE, "\n", 2, 11), tokenizer.next_token assert_equal t(:IDENT, 'node2', 3, 1), tokenizer.next_token assert_equal t(:NEWLINE, "\n", 3, 6), tokenizer.next_token assert_equal t(:EOF, :EOF, 4, 1), tokenizer.next_token assert_equal eof(4, 1), tokenizer.next_token end def test_multiline_comment tokenizer = ::KDL::V1::Tokenizer.new("foo /*bar=1*/ baz=2") assert_equal t(:IDENT, 'foo'), tokenizer.next_token assert_equal t(:WS, ' ', 1, 4), tokenizer.next_token assert_equal t(:IDENT, 'baz', 1, 15), tokenizer.next_token assert_equal t(:EQUALS, '=', 1, 18), tokenizer.next_token assert_equal t(:INTEGER, 2, 1, 19), tokenizer.next_token assert_equal t(:EOF, :EOF, 1, 20), tokenizer.next_token assert_equal eof(1, 20), tokenizer.next_token end def test_utf8 assert_equal t(:IDENT, '๐Ÿ˜'), ::KDL::V1::Tokenizer.new("๐Ÿ˜").next_token assert_equal t(:STRING, '๐Ÿ˜'), ::KDL::V1::Tokenizer.new('"๐Ÿ˜"').next_token assert_equal t(:IDENT, 'ใƒŽใƒผใƒ‰'), ::KDL::V1::Tokenizer.new('ใƒŽใƒผใƒ‰').next_token assert_equal t(:IDENT, 'ใŠๅๅ‰'), ::KDL::V1::Tokenizer.new('ใŠๅๅ‰').next_token assert_equal t(:STRING, 'โ˜œ(๏พŸใƒฎ๏พŸโ˜œ)'), ::KDL::V1::Tokenizer.new('"โ˜œ(๏พŸใƒฎ๏พŸโ˜œ)"').next_token tokenizer = ::KDL::V1::Tokenizer.new <<~KDL smile "๐Ÿ˜" ใƒŽใƒผใƒ‰ ใŠๅๅ‰="โ˜œ(๏พŸใƒฎ๏พŸโ˜œ)" KDL assert_equal t(:IDENT, 'smile'), tokenizer.next_token assert_equal t(:WS, ' ', 1, 6), tokenizer.next_token assert_equal t(:STRING, '๐Ÿ˜', 1, 7), tokenizer.next_token assert_equal t(:NEWLINE, "\n", 1, 10), tokenizer.next_token assert_equal t(:IDENT, 'ใƒŽใƒผใƒ‰', 2, 1), tokenizer.next_token assert_equal t(:WS, ' ', 2, 4), tokenizer.next_token assert_equal t(:IDENT, 'ใŠๅๅ‰', 2, 5), tokenizer.next_token assert_equal t(:EQUALS, '=', 2, 8), tokenizer.next_token assert_equal t(:STRING, 'โ˜œ(๏พŸใƒฎ๏พŸโ˜œ)', 2, 9), tokenizer.next_token assert_equal t(:NEWLINE, "\n", 2, 18), tokenizer.next_token assert_equal t(:EOF, :EOF, 3, 1), tokenizer.next_token assert_equal eof(3, 1), tokenizer.next_token end def test_semicolon tokenizer = ::KDL::V1::Tokenizer.new 'node1; node2' assert_equal t(:IDENT, 'node1'), tokenizer.next_token assert_equal t(:SEMICOLON, ';', 1, 6), tokenizer.next_token assert_equal t(:WS, ' ', 1, 7), tokenizer.next_token assert_equal t(:IDENT, 'node2', 1, 8), tokenizer.next_token assert_equal t(:EOF, :EOF, 1, 13), tokenizer.next_token assert_equal eof(1, 13), tokenizer.next_token end def test_slash_dash tokenizer = ::KDL::V1::Tokenizer.new <<~KDL /-mynode /-"foo" /-key=1 /-{ a } KDL assert_equal t(:SLASHDASH, '/-'), tokenizer.next_token assert_equal t(:IDENT, 'mynode', 1, 3), tokenizer.next_token assert_equal t(:WS, ' ', 1, 9), tokenizer.next_token assert_equal t(:SLASHDASH, '/-', 1, 10), tokenizer.next_token assert_equal t(:STRING, 'foo', 1, 12), tokenizer.next_token assert_equal t(:WS, ' ', 1, 17), tokenizer.next_token assert_equal t(:SLASHDASH, '/-', 1, 18), tokenizer.next_token assert_equal t(:IDENT, 'key', 1, 20), tokenizer.next_token assert_equal t(:EQUALS, '=', 1, 23), tokenizer.next_token assert_equal t(:INTEGER, 1, 1, 24), tokenizer.next_token assert_equal t(:WS, ' ', 1, 25), tokenizer.next_token assert_equal t(:SLASHDASH, '/-', 1, 26), tokenizer.next_token assert_equal t(:LBRACE, '{', 1, 28), tokenizer.next_token assert_equal t(:NEWLINE, "\n", 1, 29), tokenizer.next_token assert_equal t(:WS, ' ', 2, 1), tokenizer.next_token assert_equal t(:IDENT, 'a', 2, 3), tokenizer.next_token assert_equal t(:NEWLINE, "\n", 2, 4), tokenizer.next_token assert_equal t(:RBRACE, '}', 3, 1), tokenizer.next_token assert_equal t(:NEWLINE, "\n", 3, 2), tokenizer.next_token assert_equal t(:EOF, :EOF, 4, 1), tokenizer.next_token assert_equal eof(4, 1), tokenizer.next_token end def test_multiline_nodes tokenizer = ::KDL::V1::Tokenizer.new <<~KDL title \\ "Some title" KDL assert_equal t(:IDENT, 'title'), tokenizer.next_token assert_equal t(:WS, " \\\n ", 1, 6), tokenizer.next_token assert_equal t(:STRING, 'Some title', 2, 3), tokenizer.next_token assert_equal t(:NEWLINE, "\n", 2, 15), tokenizer.next_token assert_equal t(:EOF, :EOF, 3, 1), tokenizer.next_token assert_equal eof(3, 1), tokenizer.next_token end def test_multiline_nodes_with_comment tokenizer = ::KDL::V1::Tokenizer.new <<~KDL title \\ // some comment "Some title" KDL assert_equal t(:IDENT, 'title'), tokenizer.next_token assert_equal t(:WS, " \\ \n ", 1, 6), tokenizer.next_token assert_equal t(:STRING, 'Some title', 2, 3), tokenizer.next_token assert_equal t(:NEWLINE, "\n", 2, 15), tokenizer.next_token assert_equal t(:EOF, :EOF, 3, 1), tokenizer.next_token assert_equal eof(3, 1), tokenizer.next_token end private def t(type, value, line = 1, col = 1) [type, ::KDL::V1::Tokenizer::Token.new(type, value, line, col)] end def eof(line = 1, col = 1) [false, ::KDL::V1::Tokenizer::Token.new(:EOF, :EOF, line, col)] end end danini-the-panini-kdl-rb-56d7cf1/test/v1/value_test.rb000066400000000000000000000031641515522600200226070ustar00rootroot00000000000000# frozen_string_literal: true require "test_helper" class KDL::V1::ValueTest < Minitest::Test def test_to_s assert_equal "1", ::KDL::V1::Value::Int.new(1).to_s assert_equal "1.5", ::KDL::V1::Value::Float.new(1.5).to_s assert_equal "null", ::KDL::V1::Value::Float.new(Float::INFINITY).to_s assert_equal "null", ::KDL::V1::Value::Float.new(-Float::INFINITY).to_s assert_equal "null", ::KDL::V1::Value::Float.new(Float::NAN).to_s assert_equal "true", ::KDL::V1::Value::Boolean.new(true).to_s assert_equal "false", ::KDL::V1::Value::Boolean.new(false).to_s assert_equal "null", ::KDL::V1::Value::Null.to_s assert_equal '"foo"', ::KDL::V1::Value::String.new("foo").to_s assert_equal '"foo \"bar\" baz"', ::KDL::V1::Value::String.new('foo "bar" baz').to_s assert_equal '(ty)"foo"', ::KDL::V1::Value::String.new("foo", type: 'ty').to_s end def test_from assert_equal(::KDL::V1::Value::Int.new(1), ::KDL::V1::Value::from(1)) assert_equal(::KDL::V1::Value::Float.new(1.5), ::KDL::V1::Value::from(1.5)) assert_equal( ::KDL::V1::Value::String.new("foo"), ::KDL::V1::Value::from("foo") ) assert_equal(::KDL::V1::Value::String.new("bar"), ::KDL::V1::Value::from("bar")) assert_equal(::KDL::V1::Value::Boolean.new(true), ::KDL::V1::Value::from(true)) assert_equal(::KDL::V1::Value::Null, ::KDL::V1::Value::from(nil)) assert_raises { ::KDL::V1::Value.from(Object.new) } end def test_equal assert(::KDL::V1::Value::String.new("foo") == ::KDL::Value::String.new("foo")) assert(::KDL::Value::String.new("foo") == ::KDL::V1::Value::String.new("foo")) end end danini-the-panini-kdl-rb-56d7cf1/test/value_test.rb000066400000000000000000000115331515522600200222600ustar00rootroot00000000000000# frozen_string_literal: true require "test_helper" class ValueTest < Minitest::Test def test_to_s assert_equal "1", ::KDL::Value::Int.new(1).to_s assert_equal "1.5", ::KDL::Value::Float.new(1.5).to_s assert_equal "#inf", ::KDL::Value::Float.new(Float::INFINITY).to_s assert_equal "#-inf", ::KDL::Value::Float.new(-Float::INFINITY).to_s assert_equal "#nan", ::KDL::Value::Float.new(Float::NAN).to_s assert_equal "#true", ::KDL::Value::Boolean.new(true).to_s assert_equal "#false", ::KDL::Value::Boolean.new(false).to_s assert_equal "#null", ::KDL::Value::Null.to_s assert_equal 'foo', ::KDL::Value::String.new("foo").to_s assert_equal '"foo \"bar\" baz"', ::KDL::Value::String.new('foo "bar" baz').to_s assert_equal '"false"', ::KDL::Value::String.new("false").to_s assert_equal '(ty)foo', ::KDL::Value::String.new("foo", type: 'ty').to_s end def test_from assert_equal(KDL::Value::Int.new(1), KDL::Value::from(1)) assert_equal(KDL::Value::Float.new(1.5), KDL::Value::from(1.5)) assert_equal( KDL::Value::String.new("foo"), KDL::Value::from("foo") ) assert_equal(KDL::Value::String.new("bar"), KDL::Value::from("bar")) assert_equal(KDL::Value::Boolean.new(true), KDL::Value::from(true)) assert_equal(KDL::Value::Null, KDL::Value::from(nil)) assert_raises { ::KDL::Value.from(Object.new) } end def test_equal assert_equal ::KDL::Value::Int.new(42), ::KDL::Value::Int.new(42) assert_equal ::KDL::Value::Float.new(3.14), ::KDL::Value::Float.new(3.14) assert_equal ::KDL::Value::Float.new(::Float::NAN), ::KDL::Value::Float.new(::Float::NAN) assert_equal ::KDL::Value::Boolean.new(true), ::KDL::Value::Boolean.new(true) assert_equal ::KDL::Value::NullImpl.new, ::KDL::Value::NullImpl.new assert_equal ::KDL::Value::String.new("lorem"), ::KDL::Value::String.new("lorem") assert_equal ::KDL::Value::Int.new(42), 42 assert_equal ::KDL::Value::Float.new(3.14), 3.14 assert_equal ::KDL::Value::Boolean.new(true), true assert_equal ::KDL::Value::NullImpl.new, nil assert_equal ::KDL::Value::String.new("lorem"), "lorem" refute_equal ::KDL::Value::Int.new(69), ::KDL::Value::Int.new(42) refute_equal ::KDL::Value::Float.new(6.28), ::KDL::Value::Float.new(3.14) refute_equal ::KDL::Value::Boolean.new(false), ::KDL::Value::Boolean.new(true) refute_equal ::KDL::Value::String.new("ipsum"), ::KDL::Value::String.new("lorem") refute_equal ::KDL::Value::Int.new(42), 69 refute_equal ::KDL::Value::Float.new(3.14), 6.28 refute_equal ::KDL::Value::Boolean.new(true), false refute_equal ::KDL::Value::NullImpl.new, 7 refute_equal ::KDL::Value::String.new("lorem"), "ipsum" end class Something < KDL::Value::Custom end def test_as_type value = ::KDL::Value::String.new("foo") assert_equal "bar", value.as_type("bar").type assert_kind_of Something, value.as_type("bar", lambda { |v, type| Something.new(v) }) nil_parse = value.as_type("bar", lambda { |v, type| nil }) assert_equal value, nil_parse assert_equal "bar", nil_parse.type assert_raises { value.as_type("bar", lambda { |v, type| Object.new }) } end def test_inspect assert_equal "1", ::KDL::Value::Int.new(1).inspect assert_equal "1.5", ::KDL::Value::Float.new(1.5).inspect assert_equal "true", ::KDL::Value::Boolean.new(true).inspect assert_equal "false", ::KDL::Value::Boolean.new(false).inspect assert_equal "nil", ::KDL::Value::Null.inspect assert_equal '"foo"', ::KDL::Value::String.new("foo").inspect assert_equal '"foo \"bar\" baz"', ::KDL::Value::String.new('foo "bar" baz').inspect assert_equal '("ty")"foo"', ::KDL::Value::String.new("foo", type: 'ty').inspect end def test_version assert_equal 2, ::KDL::Value::Int.new(1).version assert_equal 2, ::KDL::Value::Float.new(1.5).version assert_equal 2, ::KDL::Value::Boolean.new(true).version assert_equal 2, ::KDL::Value::Boolean.new(false).version assert_equal 2, ::KDL::Value::Null.version assert_equal 2, ::KDL::Value::String.new("foo").version end def test_to_v1 [ ::KDL::Value::Int.new(1), ::KDL::Value::Float.new(1.5), ::KDL::Value::Boolean.new(true), ::KDL::Value::Boolean.new(false), ::KDL::Value::Null, ::KDL::Value::String.new("foo") ].each do |v| v1 = v.to_v1 assert_equal 1, v1.version assert_equal v, v1 assert_equal v1, v end end def test_to_v2 [ ::KDL::Value::Int.new(1), ::KDL::Value::Float.new(1.5), ::KDL::Value::Boolean.new(true), ::KDL::Value::Boolean.new(false), ::KDL::Value::Null, ::KDL::Value::String.new("foo") ].each do |v| assert_same v, v.to_v2 end end def test_method_missing v = ::KDL::Value::String.new("foo") assert v.respond_to?(:upcase) assert_equal "FOO", v.upcase end end