pax_global_header00006660000000000000000000000064141377410270014520gustar00rootroot0000000000000052 comment=4319d9d5345249101c20eafb90509861b5da19dc toml-rb-2.1.0/000077500000000000000000000000001413774102700130745ustar00rootroot00000000000000toml-rb-2.1.0/.github/000077500000000000000000000000001413774102700144345ustar00rootroot00000000000000toml-rb-2.1.0/.github/workflows/000077500000000000000000000000001413774102700164715ustar00rootroot00000000000000toml-rb-2.1.0/.github/workflows/codeql-analysis.yml000066400000000000000000000044371413774102700223140ustar00rootroot00000000000000# For most projects, this workflow file will not need changing; you simply need # to commit it to your repository. # # You may wish to alter this file to override the set of languages analyzed, # or to provide custom queries or build logic. # # ******** NOTE ******** # We have attempted to detect the languages in your repository. Please check # the `language` matrix defined below to confirm you have the correct set of # supported CodeQL languages. # name: "CodeQL" on: push: branches: [ master ] pull_request: # The branches below must be a subset of the branches above branches: [ master ] schedule: - cron: '31 9 * * 4' jobs: analyze: name: Analyze runs-on: ubuntu-latest permissions: actions: read contents: read security-events: write strategy: fail-fast: false matrix: language: [ 'ruby' ] # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] # Learn more about CodeQL language support at https://git.io/codeql-language-support steps: - name: Checkout repository uses: actions/checkout@v2 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL uses: github/codeql-action/init@v1 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. # By default, queries listed here will override any specified in a config file. # Prefix the list here with "+" to use these queries and those in the config file. # queries: ./path/to/local/query, your-org/your-repo/queries@main # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild uses: github/codeql-action/autobuild@v1 # ℹ️ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines # and modify them (or add more) to build your code if your project # uses a compiled language #- run: | # make bootstrap # make release - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@v1 toml-rb-2.1.0/.github/workflows/ruby.yml000066400000000000000000000025331413774102700202000ustar00rootroot00000000000000# 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: CI on: push: branches: [ master ] pull_request: branches: [ master ] workflow_dispatch: schedule: - cron: '0 6 * * *' # Every day at 6 AM jobs: test: runs-on: ubuntu-latest strategy: fail-fast: false matrix: ruby-version: ['2.5', '2.6', '2.7', '3.0'] steps: - uses: actions/checkout@v2 - name: Set up Ruby uses: ruby/setup-ruby@v1 with: ruby-version: ${{ matrix.ruby-version }} bundler-cache: true # runs 'bundle install' and caches installed gems automatically - name: Run tests run: bundle exec rake lint: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - name: Set up Ruby uses: ruby/setup-ruby@v1 with: ruby-version: 2.7 bundler-cache: true # runs 'bundle install' and caches installed gems automatically - name: Run standardrb run: bundle exec rake standard STANDARDOPTS="--format progress" toml-rb-2.1.0/.gitignore000066400000000000000000000000501413774102700150570ustar00rootroot00000000000000*.gem .config test/tmp tmp Gemfile.lock toml-rb-2.1.0/.rubocop.yml000066400000000000000000000020171413774102700153460ustar00rootroot00000000000000Metrics/LineLength: Description: 'Limit lines to 80 characters.' Max: 80 Exclude: - test/*.rb Metrics/MethodLength: Description: Avoid methods longer than 25 lines of code. Enabled: true CountComments: false Max: 25 Exclude: - test/*.rb Metrics/ClassLength: Exclude: - test/*.rb Metrics/CyclomaticComplexity: Max: 10 Style/StringLiterals: Description: 'Checks if uses of quotes match the configured preference.' Enabled: false Style/IfUnlessModifier: Enabled: false Style/RaiseArgs: Description: 'Check if exceptions are raised in a particular way' Enabled: false Style/Documentation: Description: 'Document classes and non-namespace modules.' Enabled: false Style/ClassAndModuleChildren: Description: Checks style of children classes and modules. Enabled: false EnforcedStyle: nested Style/AlignParameters: Enabled: false Style/GuardClause: Enabled: false Style/DoubleNegation: Enabled: false Style/NumericLiterals: Enabled: false Style/ClassVars: Enabled: false toml-rb-2.1.0/.standard.yml000066400000000000000000000002201413774102700154670ustar00rootroot00000000000000parallel: true # default: false format: progress # default: Standard::Formatter ruby_version: 2.5 # default: RUBY_VERSION toml-rb-2.1.0/Gemfile000066400000000000000000000001061413774102700143640ustar00rootroot00000000000000# frozen_string_literal: true source "https://rubygems.org" gemspec toml-rb-2.1.0/LICENSE000066400000000000000000000020261413774102700141010ustar00rootroot00000000000000The MIT License (MIT) 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. toml-rb-2.1.0/README.md000066400000000000000000000055151413774102700143610ustar00rootroot00000000000000![TOML Logo](https://github.com/toml-lang/toml/blob/master/logos/toml-100.png) toml-rb ======= [![Gem Version](https://badge.fury.io/rb/toml-rb.svg)](http://badge.fury.io/rb/toml-rb) [![Build Status](https://github.com/emancu/toml-rb/actions/workflows/ruby.yml/badge.svg)](https://github.com/emancu/toml-rb/actions/workflows/ruby.yml) [![Code Climate](https://codeclimate.com/github/emancu/toml-rb/badges/gpa.svg)](https://codeclimate.com/github/emancu/toml-rb) [![RubyGem](https://img.shields.io/gem/dt/toml-rb.svg)](https://rubygems.org/gems/toml-rb) A [TOML](https://github.com/toml-lang/toml) parser using [Citrus](http://mjackson.github.io/citrus) library. TOML specs supported: `0.5.0` Installation ------------ $ gem install toml-rb Parser Usage ------------ ```ruby require 'toml-rb' # From a file! path = File.join(File.dirname(__FILE__), 'path', 'to', 'file') TomlRB.load_file(path) # From a stream! stream = <<-EOS title = "wow!" [awesome] you = true others = false EOS TomlRB.parse(stream) # => {"title"=>"wow!", "awesome"=>{"you"=>true, "others"=>false}} # You want symbols as your keys? No problem! TomlRB.load_file(path, symbolize_keys: true) # Works the same for TomlRB.parse ``` Dumper Usage ------------ ```ruby require 'toml-rb' # Simple example TomlRB.dump( simple: true) # => "simple = true\n" # Complex example hash = { "title"=>"wow!", "awesome"=> { "you"=>true, "others"=>false } } TomlRB.dump(hash) # => "title = \"wow!\"\n[awesome]\nothers = false\nyou = true\n" ``` Contributing ------------ 1. Fork it 2. Create your feature branch `git checkout -b my-new-feature` 3. Add tests and commit your changes `git commit -am 'Add some feature'` 4. Run tests `$ rake` 5. Push the branch `git push origin my-new-feature` 6. Create new Pull Request License ------- MIT License 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. toml-rb-2.1.0/Rakefile000066400000000000000000000002021413774102700145330ustar00rootroot00000000000000require "rake/testtask" require "standard/rake" Rake::TestTask.new do |t| t.pattern = "test/*_test.rb" end task default: :test toml-rb-2.1.0/lib/000077500000000000000000000000001413774102700136425ustar00rootroot00000000000000toml-rb-2.1.0/lib/toml-rb.rb000066400000000000000000000053431413774102700155500ustar00rootroot00000000000000require "citrus" require_relative "toml-rb/errors" require_relative "toml-rb/array" require_relative "toml-rb/string" require_relative "toml-rb/datetime" require_relative "toml-rb/table" require_relative "toml-rb/table_array" require_relative "toml-rb/inline_table" require_relative "toml-rb/keyvalue" require_relative "toml-rb/parser" require_relative "toml-rb/dumper" File.dirname(File.expand_path(__FILE__)).tap do |root| Citrus.load "#{root}/toml-rb/grammars/helper.citrus" Citrus.load "#{root}/toml-rb/grammars/primitive.citrus" Citrus.load "#{root}/toml-rb/grammars/array.citrus" Citrus.load "#{root}/toml-rb/grammars/document.citrus" end module TomlRB # Public: Returns a hash from *TomlRB* content. # # content - TomlRB string to be parsed. # :symbolize_keys - true | false (default: false). # # # Examples # # TomlRB.parse('[group]') # # => {"group"=>{}} # # TomlRB.parse('title = "TomlRB parser"') # # => {"title"=>"TomlRB parser"} # # TomlRB.parse('[group]', symbolize_keys: true) # # => {group: {}} # # TomlRB.parse('title = "TomlRB parser"', symbolize_keys: true) # # => {title: "TomlRB parser"} # # # Returns a Ruby hash representation of the content according to TomlRB spec. # Raises ValueOverwriteError if a key is overwritten. # Raises ParseError if the content has invalid TomlRB. def self.parse(content, symbolize_keys: false) Parser.new(content, symbolize_keys: symbolize_keys).hash end # Public: Returns a hash from a *TomlRB* file. # # path - TomlRB File path # :symbolize_keys - true|false (optional). # # # Examples # # TomlRB.load_file('/tmp/simple.toml') # # => {"group"=>{}} # # TomlRB.load_file('/tmp/simple.toml', symbolize_keys: true) # # => {group: {}} # # # Returns a Ruby hash representation of the content. # Raises ValueOverwriteError if a key is overwritten. # Raises ParseError if the content has invalid TomlRB. # Raises Errno::ENOENT if the file cannot be found. # Raises Errno::EACCES if the file cannot be accessed. def self.load_file(path, symbolize_keys: false) TomlRB.parse(File.read(path), symbolize_keys: symbolize_keys) end # Public: Returns a *TomlRB* string from a Ruby Hash. # # hash - Ruby Hash to be dumped into *TomlRB* # # # Examples # # TomlRB.dump(title: 'TomlRB dump') # # => "simple = true\n" # # hash = { # "title"=>"wow!", # "awesome"=> { # "you"=>true, # "others"=>false # } # } # # TomlRB.dump(hash) # # => "title = \"wow!\"\n[awesome]\nothers = false\nyou = true\n" # # # Returns a TomlRB string representing the hash. def self.dump(hash) Dumper.new(hash).toml_str end end toml-rb-2.1.0/lib/toml-rb/000077500000000000000000000000001413774102700152165ustar00rootroot00000000000000toml-rb-2.1.0/lib/toml-rb/array.rb000066400000000000000000000002311413774102700166550ustar00rootroot00000000000000module TomlRB module ArrayParser def value elements = captures[:array_elements].first elements ? elements.value : [] end end end toml-rb-2.1.0/lib/toml-rb/datetime.rb000066400000000000000000000017671413774102700173520ustar00rootroot00000000000000module TomlRB module OffsetDateTimeParser def value skeleton = captures[:datetime_skeleton].first year, mon, day, hour, min, sec, sec_frac = skeleton.value offset = captures[:date_offset].first || "+00:00" sec = "#{sec}.#{sec_frac}".to_f Time.new(year, mon, day, hour, min, sec, offset.to_s) end end module LocalDateTimeParser def value year, mon, day = captures[:date_skeleton].first.value hour, min, sec, sec_frac = captures[:time_skeleton].first.value usec = sec_frac.to_s.ljust(6, "0") Time.local(year, mon, day, hour, min, sec, usec) end end module LocalDateParser def value year, mon, day = captures[:date_skeleton].first.value Time.local(year, mon, day) end end module LocalTimeParser def value hour, min, sec, sec_frac = captures[:time_skeleton].first.value usec = sec_frac.to_s.ljust(6, "0") Time.at(3600 * hour.to_i + 60 * min.to_i + sec.to_i, usec.to_i) end end end toml-rb-2.1.0/lib/toml-rb/dumper.rb000066400000000000000000000051551413774102700170450ustar00rootroot00000000000000require "date" module TomlRB class Dumper attr_reader :toml_str def initialize(hash) @toml_str = "" visit(hash, []) end private def visit(hash, prefix, extra_brackets = false) simple_pairs, nested_pairs, table_array_pairs = sort_pairs hash if prefix.any? && (simple_pairs.any? || hash.empty?) print_prefix prefix, extra_brackets end dump_pairs simple_pairs, nested_pairs, table_array_pairs, prefix end def sort_pairs(hash) nested_pairs = [] simple_pairs = [] table_array_pairs = [] hash.keys.sort.each do |key| val = hash[key] element = [key, val] if val.is_a? Hash nested_pairs << element elsif val.is_a?(Array) && val.first.is_a?(Hash) table_array_pairs << element else simple_pairs << element end end [simple_pairs, nested_pairs, table_array_pairs] end def dump_pairs(simple, nested, table_array, prefix = []) # First add simple pairs, under the prefix dump_simple_pairs simple dump_nested_pairs nested, prefix dump_table_array_pairs table_array, prefix end def dump_simple_pairs(simple_pairs) simple_pairs.each do |key, val| key = quote_key(key) unless bare_key? key @toml_str << "#{key} = #{to_toml(val)}\n" end end def dump_nested_pairs(nested_pairs, prefix) nested_pairs.each do |key, val| key = quote_key(key) unless bare_key? key visit val, prefix + [key], false end end def dump_table_array_pairs(table_array_pairs, prefix) table_array_pairs.each do |key, val| key = quote_key(key) unless bare_key? key aux_prefix = prefix + [key] val.each do |child| print_prefix aux_prefix, true args = sort_pairs(child) << aux_prefix dump_pairs(*args) end end end def print_prefix(prefix, extra_brackets = false) new_prefix = prefix.join(".") new_prefix = "[" + new_prefix + "]" if extra_brackets @toml_str += "[" + new_prefix + "]\n" end def to_toml(obj) if obj.is_a?(Time) || obj.is_a?(DateTime) obj.strftime("%Y-%m-%dT%H:%M:%SZ") elsif obj.is_a?(Date) obj.strftime("%Y-%m-%d") elsif obj.is_a? Regexp obj.inspect.inspect elsif obj.is_a? String obj.inspect.gsub(/\\(#[$@{])/, '\1') else obj.inspect end end def bare_key?(key) !!key.to_s.match(/^[a-zA-Z0-9_-]*$/) end def quote_key(key) '"' + key.gsub('"', '\\"') + '"' end end end toml-rb-2.1.0/lib/toml-rb/errors.rb000066400000000000000000000005361413774102700170630ustar00rootroot00000000000000module TomlRB # Parent class for all TomlRB errors Error = Class.new(StandardError) # Error related to parsing. ParseError = Class.new(Error) # Overwrite error class ValueOverwriteError < Error attr_accessor :key def initialize(key) @key = key super "Key #{key.inspect} is defined more than once" end end end toml-rb-2.1.0/lib/toml-rb/grammars/000077500000000000000000000000001413774102700170275ustar00rootroot00000000000000toml-rb-2.1.0/lib/toml-rb/grammars/array.citrus000066400000000000000000000013171413774102700214020ustar00rootroot00000000000000grammar TomlRB::Arrays include TomlRB::Primitive rule array_comments (indent? (comment indent?)*) end rule float_array (float (space "," array_comments float)*) { captures[:float].map(&:value) } end rule string_array (string (space "," array_comments string)*) { captures[:string].map(&:value) } end rule integer_array (integer (space "," array_comments integer)*) { captures[:integer].map(&:value) } end rule datetime_array (datetime (space "," array_comments datetime)*) { captures[:datetime].map(&:value) } end rule bool_array (bool (space "," array_comments bool)*) { captures[:bool].map(&:value) } end end toml-rb-2.1.0/lib/toml-rb/grammars/document.citrus000066400000000000000000000023721413774102700221040ustar00rootroot00000000000000grammar TomlRB::Document include TomlRB::Primitive include TomlRB::Arrays rule document (comment | table_array | table | keyvalue | line_break)* end rule table_array (space? '[[' stripped_key ']]' comment?) end rule table (space? '[' stripped_key ']' comment?) end rule keyvalue (stripped_key '=' space? v:(toml_values) comment? space) end rule inline_table (space? '{' (keyvalue? (',' keyvalue)*)? space? '}' ) end rule inline_table_array (inline_table (space "," array_comments inline_table)*) { captures[:inline_table].map(&:value).map(&:value) } end rule array ("[" array_comments (array_elements)? space ","? array_comments "]" indent?) end rule array_elements inline_table_array | float_array | string_array | array_array | integer_array | datetime_array | bool_array end rule array_array (array (space "," array_comments array)*) { captures[:array].map(&:value) } end rule toml_values primitive | inline_table | array | inline_table_array end rule stripped_key (space? key space?) { captures[:key].first.value } end end toml-rb-2.1.0/lib/toml-rb/grammars/helper.citrus000066400000000000000000000003641413774102700215440ustar00rootroot00000000000000grammar TomlRB::Helper rule comment (space? "#" (~line_break)* line_break?) { nil } end rule space [ \t]* end rule indent [ \t\r\n]* end rule line_break (space "\n" space | space "\r\n" space) { nil } end end toml-rb-2.1.0/lib/toml-rb/grammars/primitive.citrus000066400000000000000000000060361413774102700222770ustar00rootroot00000000000000grammar TomlRB::Primitive include TomlRB::Helper rule primitive datetime | bool | number | string end ## # String rules ## rule string multiline_string | multiline_literal | basic_string | literal_string end rule basic_string (/(["])(?:\\?.)*?\1/ space) end rule literal_string (/(['])(?:\\?.)*?\1/ space) end rule multiline_string ('"""' line_break* (text:~('"""' !'"')|'') '"""' space) end rule multiline_literal ("'''" line_break* (text:~("'''" !"'")|'') "'''" space) end ## # Date time rules ## rule datetime offset_datetime | local_datetime | local_date | local_time end rule offset_datetime ( skeleton:datetime_skeleton ("Z" | date_offset) ) end rule local_datetime datetime_skeleton end rule local_date (date_skeleton space) end rule local_time (time_skeleton space) end rule datetime_skeleton (date_skeleton ("T"|" ") time_skeleton) { capture(:date_skeleton).value + capture(:time_skeleton).value } end rule date_skeleton (year:/\d\d\d\d/ "-" mon:/\d\d/ "-" day:/\d\d/) { [:year,:mon,:day].map{ |s| capture(s).value } } end rule time_skeleton ( hour:([0-2][0-9]) ":" mim:([0-6][0-9]) ":" sec:([0-6][0-9]) ([,\.] sec_frac:(/\d/1*6))? ) { [:hour,:mim,:sec].map{ |s| capture(s).value } + [capture(:sec_frac) || '0'] } end rule date_offset offset:(sign /\d\d/ ":" /\d\d/) end ## # Number rules ## rule number float | integer end rule float inf | nan | exponential_float | fractional_float end rule inf (s:sign? 'inf') { sign = (capture(:s).value != '-') ? 1 : -1 sign * Float::INFINITY } end rule nan (sign? 'nan') { Float::NAN } end rule exponential_float ((fractional_float | demical_integer) [eE] demical_integer) { to_str.to_f } end rule fractional_float (demical_integer '.' [0-9_]+) { to_str.to_f } end rule integer hexadecimal_integer | octal_integer | binary_integer | demical_integer end rule hexadecimal_integer ('0x' [a-fA-F0-9_]+) { to_str.to_i(16) } end rule octal_integer ('0o' [0-7_]+) { to_str.to_i(8) } end rule binary_integer ('0b' [01_]+) { to_str.to_i(2) } end rule demical_integer (sign? [0-9_]+) { to_str.to_i } end rule sign '+' | '-' end ## # Boolean rules ## rule bool true | false end rule true 'true' { true } end rule false 'false' { false } end ## # Key rules ## rule key dotted_key end rule bare_key [a-zA-Z0-9_-]+ end rule quoted_key basic_string | literal_string end rule single_key quoted_key | bare_key end rule dotted_key (space? single_key space? ("." space? single_key space?)* ) { captures[:single_key].map(&:value) } end end toml-rb-2.1.0/lib/toml-rb/inline_table.rb000066400000000000000000000010571413774102700201730ustar00rootroot00000000000000module TomlRB class InlineTable def initialize(keyvalue_pairs) @pairs = keyvalue_pairs end def accept_visitor(keyvalue) value keyvalue.symbolize_keys end def value(symbolize_keys = false) result = {} @pairs.each do |kv| update = kv.assign({}, [], symbolize_keys) result.merge!(update) { |key, _, _| fail ValueOverwriteError.new(key) } end result end end module InlineTableParser def value TomlRB::InlineTable.new captures[:keyvalue].map(&:value) end end end toml-rb-2.1.0/lib/toml-rb/keyvalue.rb000066400000000000000000000030311413774102700173650ustar00rootroot00000000000000require_relative "inline_table" module TomlRB class Keyvalue attr_reader :dotted_keys, :value, :symbolize_keys def initialize(dotted_keys, value) @dotted_keys = dotted_keys @value = value @symbolize_keys = false end def assign(hash, fully_defined_keys, symbolize_keys = false) @symbolize_keys = symbolize_keys dotted_keys_str = @dotted_keys.join(".") keys = symbolize_keys ? @dotted_keys.map(&:to_sym) : @dotted_keys update = keys.reverse.inject(visit_value(@value)) { |k1, k2| {k2 => k1} } if @value.is_a?(InlineTable) fully_defined_keys << dotted_keys_str hash.merge!(update) { |key, _, _| fail ValueOverwriteError.new(key) } elsif fully_defined_keys.find { |k| update.dig(*k) } hash.merge!(update) { |key, _, _| fail ValueOverwriteError.new(key) } else dotted_key_merge(hash, update) end end def dotted_key_merge(hash, update) hash.merge!(update) { |key, old, new| if old.is_a?(Hash) && new.is_a?(Hash) dotted_key_merge(old, new) else fail ValueOverwriteError.new(key) end } end def accept_visitor(parser) parser.visit_keyvalue self end private def visit_value(a_value) return a_value unless a_value.respond_to? :accept_visitor a_value.accept_visitor self end end # Used in document.citrus module KeyvalueParser def value TomlRB::Keyvalue.new(capture(:stripped_key).value, capture(:v).value) end end end toml-rb-2.1.0/lib/toml-rb/parser.rb000066400000000000000000000021031413774102700170330ustar00rootroot00000000000000module TomlRB class Parser attr_reader :hash def initialize(content, symbolize_keys: false) @hash = {} @visited_keys = [] @fully_defined_keys = [] @current = @hash @symbolize_keys = symbolize_keys begin parsed = TomlRB::Document.parse(content) parsed.matches.map(&:value).compact.each { |m| m.accept_visitor(self) } rescue Citrus::ParseError => e raise TomlRB::ParseError.new(e.message) end end # Read about the Visitor pattern # http://en.wikipedia.org/wiki/Visitor_pattern def visit_table_array(table_array) @fully_defined_keys = [] table_array_key = table_array.full_key @visited_keys.reject! { |k| k.start_with? table_array_key } @current = table_array.navigate_keys @hash, @symbolize_keys end def visit_table(table) @fully_defined_keys = [] @current = table.navigate_keys @hash, @visited_keys, @symbolize_keys end def visit_keyvalue(keyvalue) keyvalue.assign @current, @fully_defined_keys, @symbolize_keys end end end toml-rb-2.1.0/lib/toml-rb/string.rb000066400000000000000000000027041413774102700170540ustar00rootroot00000000000000module TomlRB # Used in primitive.citrus module BasicString SPECIAL_CHARS = { "\\0" => "\0", "\\t" => "\t", "\\b" => "\b", "\\f" => "\f", "\\n" => "\n", "\\r" => "\r", '\\"' => '"', "\\\\" => "\\" }.freeze def value aux = TomlRB::BasicString.transform_escaped_chars first.value aux[1...-1] end # Replace the unicode escaped characters with the corresponding character # e.g. \u03B4 => ? def self.decode_unicode(str) [str[2..-1].to_i(16)].pack("U") end def self.transform_escaped_chars(str) str.gsub(/\\(u[\da-fA-F]{4}|U[\da-fA-F]{8}|.)/) do |m| if m.size == 2 SPECIAL_CHARS[m] || parse_error(m) else decode_unicode(m).force_encoding("UTF-8") end end end def self.parse_error(m) fail ParseError.new "Escape sequence #{m} is reserved" end end module LiteralString def value first.value[1...-1] end end module MultilineString def value return "" if captures[:text].empty? aux = captures[:text].first.value # Remove spaces on multilined Singleline strings aux.gsub!(/\\\r?\n[\n\t\r ]*/, "") TomlRB::BasicString.transform_escaped_chars aux end end module MultilineLiteral def value return "" if captures[:text].empty? aux = captures[:text].first.value aux.gsub(/\\\r?\n[\n\t\r ]*/, "") end end end toml-rb-2.1.0/lib/toml-rb/table.rb000066400000000000000000000022271413774102700166350ustar00rootroot00000000000000module TomlRB class Table def initialize(dotted_keys) @dotted_keys = dotted_keys end def navigate_keys(hash, visited_keys, symbolize_keys = false) ensure_key_not_defined(visited_keys) current = hash keys = symbolize_keys ? @dotted_keys.map(&:to_sym) : @dotted_keys keys.each do |key| current[key] = {} unless current.key?(key) element = current[key] current = element.is_a?(Array) ? element.last : element # check that key has not been defined before as a scalar value fail ValueOverwriteError.new(key) unless current.is_a?(Hash) end current end def accept_visitor(parser) parser.visit_table self end def full_key @dotted_keys.join(".") end private # Fail if the key was already defined with a ValueOverwriteError def ensure_key_not_defined(visited_keys) fail ValueOverwriteError.new(full_key) if visited_keys.include?(full_key) visited_keys << full_key end end # Used in document.citrus module TableParser def value TomlRB::Table.new(captures[:stripped_key].map(&:value).first) end end end toml-rb-2.1.0/lib/toml-rb/table_array.rb000066400000000000000000000022361413774102700200330ustar00rootroot00000000000000module TomlRB class TableArray def initialize(dotted_keys) @dotted_keys = dotted_keys end def navigate_keys(hash, symbolize_keys = false) current = hash keys = symbolize_keys ? @dotted_keys.map(&:to_sym) : @dotted_keys last_key = keys.pop # Go over the parent keys keys.each do |key| current[key] = {} unless current[key] if current[key].is_a? Array current[key] << {} if current[key].empty? current = current[key].last else current = current[key] end end # Define Table Array if current[last_key].is_a? Hash fail TomlRB::ParseError, "#{last_key} was defined as hash but is now redefined as a table!" end current[last_key] = [] unless current[last_key] current[last_key] << {} current[last_key].last end def accept_visitor(parser) parser.visit_table_array self end def full_key @dotted_keys.join(".") end end # Used in document.citrus module TableArrayParser def value TomlRB::TableArray.new(captures[:stripped_key].map(&:value).first) end end end toml-rb-2.1.0/lib/toml-rb/version.rb000066400000000000000000000001051413774102700172240ustar00rootroot00000000000000# frozen_string_literal: true module TomlRB VERSION = "2.1.0" end toml-rb-2.1.0/test/000077500000000000000000000000001413774102700140535ustar00rootroot00000000000000toml-rb-2.1.0/test/dumper_test.rb000066400000000000000000000065221413774102700167400ustar00rootroot00000000000000require_relative "helper" require "date" class DumperTest < Minitest::Test def test_dump_empty dumped = TomlRB.dump({}) assert_equal("", dumped) end def test_dump_types dumped = TomlRB.dump(string: 'TomlRB "dump"') assert_equal("string = \"TomlRB \\\"dump\\\"\"\n", dumped) dumped = TomlRB.dump(float: -13.24) assert_equal("float = -13.24\n", dumped) dumped = TomlRB.dump(int: 1234) assert_equal("int = 1234\n", dumped) dumped = TomlRB.dump(truthy: true) assert_equal("truthy = true\n", dumped) dumped = TomlRB.dump(falsey: false) assert_equal("falsey = false\n", dumped) dumped = TomlRB.dump(array: [1, 2, 3]) assert_equal("array = [1, 2, 3]\n", dumped) dumped = TomlRB.dump(array: [[1, 2], %w[weird one]]) assert_equal("array = [[1, 2], [\"weird\", \"one\"]]\n", dumped) dumped = TomlRB.dump(time: Time.utc(1986, 8, 28, 15, 15)) assert_equal("time = 1986-08-28T15:15:00Z\n", dumped) dumped = TomlRB.dump(datetime: DateTime.new(1986, 8, 28, 15, 15)) assert_equal("datetime = 1986-08-28T15:15:00Z\n", dumped) dumped = TomlRB.dump(date: Date.new(1986, 8, 28)) assert_equal("date = 1986-08-28\n", dumped) dumped = TomlRB.dump(regexp: /abc\n*\{/) assert_equal("regexp = \"/abc\\\\n*\\\\{/\"\n", dumped) end def test_dump_nested_attributes hash = {nested: {hash: {deep: true}}} dumped = TomlRB.dump(hash) assert_equal("[nested.hash]\ndeep = true\n", dumped) hash[:nested][:other] = 12 dumped = TomlRB.dump(hash) assert_equal("[nested]\nother = 12\n[nested.hash]\ndeep = true\n", dumped) hash[:nested][:nest] = {again: "it never ends"} dumped = TomlRB.dump(hash) toml = <<-EOS.gsub(/^ {6}/, "") [nested] other = 12 [nested.hash] deep = true [nested.nest] again = "it never ends" EOS assert_equal(toml, dumped) hash = {non: {'bare."keys"' => {"works" => true}}} dumped = TomlRB.dump(hash) assert_equal("[non.\"bare.\\\"keys\\\"\"]\nworks = true\n", dumped) hash = {hola: [{chau: 4}, {chau: 3}]} dumped = TomlRB.dump(hash) assert_equal("[[hola]]\nchau = 4\n[[hola]]\nchau = 3\n", dumped) end def test_print_empty_tables hash = {plugins: {cpu: {foo: "bar", baz: 1234}, disk: {}, io: {}}} dumped = TomlRB.dump(hash) toml = <<-EOS.gsub(/^ {6}/, "") [plugins.cpu] baz = 1234 foo = "bar" [plugins.disk] [plugins.io] EOS assert_equal toml, dumped end def test_dump_array_tables hash = {fruit: [{physical: {color: "red"}}, {physical: {color: "blue"}}]} dumped = TomlRB.dump(hash) toml = <<-EOS.gsub(/^ {6}/, "") [[fruit]] [fruit.physical] color = "red" [[fruit]] [fruit.physical] color = "blue" EOS assert_equal toml, dumped end def test_dump_interpolation_curly hash = {"key" => "includes \#{variable}"} dumped = TomlRB.dump(hash) assert_equal %(key = "includes \#{variable}") + "\n", dumped end def test_dump_interpolation_at hash = {"key" => 'includes #@variable'} dumped = TomlRB.dump(hash) assert_equal 'key = "includes #@variable"' + "\n", dumped end def test_dump_interpolation_dollar hash = {"key" => 'includes #$variable'} dumped = TomlRB.dump(hash) assert_equal 'key = "includes #$variable"' + "\n", dumped end end toml-rb-2.1.0/test/errors_test.rb000066400000000000000000000050621413774102700167560ustar00rootroot00000000000000require_relative "helper" class ErrorsTest < Minitest::Test def test_text_after_table str = "[error] if you didn't catch this, your parser is broken" assert_raises(TomlRB::ParseError) { TomlRB.parse(str) } end def test_text_after_string str = 'string = "Anything other than tabs, spaces and newline after a ' str += "table or key value pair has ended should produce an error " str += 'unless it is a comment" like this' assert_raises(TomlRB::ParseError) { TomlRB.parse(str) } end def test_multiline_array_bad_string str = <<-EOS array = [ "This might most likely happen in multiline arrays", Like here, "or here, and here" ] End of array comment, forgot the # EOS assert_raises(TomlRB::ParseError) { TomlRB.parse(str) } end def test_multiline_array_string_not_ended str = <<-EOS array = [ "This might most likely happen in multiline arrays", "or here, and here" ] End of array comment, forgot the # EOS assert_raises(TomlRB::ParseError) { TomlRB.parse(str) } end def test_text_after_multiline_array str = <<-EOS array = [ "This might most likely happen in multiline arrays", "or here", "and here" ] End of array comment, forgot the # EOS assert_raises(TomlRB::ParseError) { TomlRB.parse(str) } end def test_text_after_number str = "number = 3.14 pi <--again forgot the #" assert_raises(TomlRB::ParseError) { TomlRB.parse(str) } end def test_value_overwrite str = "a = 1\na = 2" e = assert_raises(TomlRB::ValueOverwriteError) { TomlRB.parse(str) } assert_equal "Key \"a\" is defined more than once", e.message assert_equal "a", e.key str = "a = false\na = true" assert_raises(TomlRB::ValueOverwriteError) { TomlRB.parse(str) } end def test_table_overwrite str = "[a]\nb=1\n[a]\nc=2" e = assert_raises(TomlRB::ValueOverwriteError) { TomlRB.parse(str) } assert_equal "Key \"a\" is defined more than once", e.message str = "[a]\nb=1\n[a]\nb=1" e = assert_raises(TomlRB::ValueOverwriteError) { TomlRB.parse(str) } assert_equal "Key \"a\" is defined more than once", e.message end def test_value_overwrite_with_table str = "[a]\nb=1\n[a.b]\nc=2" e = assert_raises(TomlRB::ValueOverwriteError) { TomlRB.parse(str) } assert_equal "Key \"b\" is defined more than once", e.message str = "[a]\nb=1\n[a.b.c]\nd=3" e = assert_raises(TomlRB::ValueOverwriteError) { TomlRB.parse(str) } assert_equal "Key \"b\" is defined more than once", e.message end end toml-rb-2.1.0/test/example-v0.4.0.toml000066400000000000000000000121731413774102700172320ustar00rootroot00000000000000################################################################################ ## Comment # Speak your mind with the hash symbol. They go from the symbol to the end of # the line. ################################################################################ ## Table # Tables (also known as hash tables or dictionaries) are collections of # key/value pairs. They appear in square brackets on a line by themselves. [table] key = "value" # Yeah, you can do this. # Nested tables are denoted by table names with dots in them. Name your tables # whatever crap you please, just don't use #, ., [ or ]. [table.subtable] key = "another value" # You don't need to specify all the super-tables if you don't want to. TomlRB # knows how to do it for you. # [x] you # [x.y] don't # [x.y.z] need these [x.y.z.w] # for this to work ################################################################################ ## Inline Table # Inline tables provide a more compact syntax for expressing tables. They are # especially useful for grouped data that can otherwise quickly become verbose. # Inline tables are enclosed in curly braces `{` and `}`. No newlines are # allowed between the curly braces unless they are valid within a value. [table.inline] name = { first = "Tom", last = "Preston-Werner" } point = { x = 1, y = 2 } ################################################################################ ## String # There are four ways to express strings: basic, multi-line basic, literal, and # multi-line literal. All strings must contain only valid UTF-8 characters. [string.basic] basic = "I'm a string. \"You can quote me\". Name\tJos\u00E9\nLocation\tSF." [string.multiline] # The following strings are byte-for-byte equivalent: key1 = "One\nTwo" key2 = """One\nTwo""" key3 = """ One Two""" [string.multiline.continued] # The following strings are byte-for-byte equivalent: key1 = "The quick brown fox jumps over the lazy dog." key2 = """ The quick brown \ fox jumps over \ the lazy dog.""" key3 = """\ The quick brown \ fox jumps over \ the lazy dog.\ """ [string.literal] # What you see is what you get. winpath = 'C:\Users\nodejs\templates' winpath2 = '\\ServerX\admin$\system32\' quoted = 'Tom "Dubs" Preston-Werner' regex = '<\i\c*\s*>' [string.literal.multiline] regex2 = '''I [dw]on't need \d{2} apples''' lines = ''' The first newline is trimmed in raw strings. All other whitespace is preserved. ''' ################################################################################ ## Integer # Integers are whole numbers. Positive numbers may be prefixed with a plus sign. # Negative numbers are prefixed with a minus sign. [integer] key1 = +99 key2 = 42 key3 = 0 key4 = -17 [integer.underscores] # For large numbers, you may use underscores to enhance readability. Each # underscore must be surrounded by at least one digit. key1 = 1_000 key2 = 5_349_221 key3 = 1_2_3_4_5 # valid but inadvisable ################################################################################ ## Float # A float consists of an integer part (which may be prefixed with a plus or # minus sign) followed by a fractional part and/or an exponent part. [float.fractional] key1 = +1.0 key2 = 3.1415 key3 = -0.01 [float.exponent] key1 = 5e+22 key2 = 1e6 key3 = -2E-2 [float.both] key = 6.626e-34 [float.underscores] key1 = 9_224_617.445_991_228_313 key2 = 1e1_00 ################################################################################ ## Boolean # Booleans are just the tokens you're used to. Always lowercase. [boolean] True = true False = false ################################################################################ ## Datetime # Datetimes are RFC 3339 dates. [datetime] key1 = 1979-05-27T07:32:00Z key2 = 1979-05-27T00:32:00-07:00 key3 = 1979-05-27T00:32:00.999999-07:00 ################################################################################ ## Array # Arrays are square brackets with other primitives inside. Whitespace is # ignored. Elements are separated by commas. Data types may not be mixed. [array] key1 = [ 1, 2, 3 ] key2 = [ "red", "yellow", "green" ] key3 = [ [ 1, 2 ], [3, 4, 5] ] key4 = [ [ 1, 2 ], ["a", "b", "c"] ] # this is ok # Arrays can also be multiline. So in addition to ignoring whitespace, arrays # also ignore newlines between the brackets. Terminating commas are ok before # the closing bracket. key5 = [ 1, 2, 3 ] key6 = [ 1, 2, # this is ok ] ################################################################################ ## Array of Tables # These can be expressed by using a table name in double brackets. Each table # with the same double bracketed name will be an element in the array. The # tables are inserted in the order encountered. [[products]] name = "Hammer" sku = 738594937 [[products]] [[products]] name = "Nail" sku = 284758393 color = "gray" # You can create nested arrays of tables as well. [[fruit]] name = "apple" [fruit.physical] color = "red" shape = "round" [[fruit.variety]] name = "red delicious" [[fruit.variety]] name = "granny smith" [[fruit]] name = "banana" [[fruit.variety]] name = "plantain" toml-rb-2.1.0/test/example-v0.5.0.toml000066400000000000000000000227771413774102700172460ustar00rootroot00000000000000[keys] # Bare keys may only contain ASCII letters, ASCII digits, # underscores, and dashes (A-Za-z0-9_-). # Note that bare keys are allowed to be composed of only ASCII digits, # e.g. 1234, but are always interpreted as strings. key = "value" bare_key = "value" bare-key = "value" 1234 = "value" # Quoted keys follow the exact same rules as either basic strings # or literal strings and allow you to use a much broader set of key names. # Best practice is to use bare keys except when absolutely necessary. "127.0.0.1" = "value" "character encoding" = "value" "ʎǝʞ" = "value" 'key2' = "value" 'quoted "value"' = "value" # Dotted keys are a sequence of bare or quoted keys joined with a dot. # This allows for grouping similar properties together: name = "Orange" physical.color = "orange" physical.shape = "round" site."google.com" = true # Since bare keys are allowed to compose of only ASCII integers, # it is possible to write dotted keys that look like floats # but are 2-part dotted keys. # Don't do this unless you have a good reason to (you probably don't). 3.14159 = "pi" # As long as a key hasn't been directly defined, # you may still write to it and to names within it. a.b.c = 1 a.d = 2 # Defining dotted keys out-of-order is discouraged. # VALID BUT DISCOURAGED a.type = '' b.type = '' a.name = '' b.name = '' a.data = '' b.data = '' [string] # Multi-line basic strings are surrounded by three quotation marks # on each side and allow newlines. # A newline immediately following the opening delimiter will be trimmed. # All other whitespace and newline characters remain intact. str1 = """ Roses are red Violets are blue""" # On a Unix system, the above multi-line string will most likely be the same as: str2 = "Roses are red\nViolets are blue" # On a Windows system, it will most likely be equivalent to: str3 = "Roses are red\r\nViolets are blue" # All of the escape sequences that are valid for basic strings are # also valid for multi-line basic strings. same.str1 = "The quick brown fox jumps over the lazy dog." same.str2 = """ The quick brown \ fox jumps over \ the lazy dog.""" same.str3 = """\ The quick brown \ fox jumps over \ the lazy dog.\ """ # Literal strings are surrounded by single quotes. # Like basic strings, they must appear on a single line: winpath = 'C:\Users\nodejs\templates' winpath2 = '\\ServerX\admin$\system32\' quoted = 'Tom "Dubs" Preston-Werner' regex = '<\i\c*\s*>' # Multi-line literal strings are surrounded by three single quotes # on each side and allow newlines. Like literal strings, # there is no escaping whatsoever. # A newline immediately following the opening delimiter will be trimmed. # All other content between the delimiters is # interpreted as-is without modification. regex2 = '''I [dw]on't need \d{2} apples''' lines = ''' The first newline is trimmed in raw strings. All other whitespace is preserved. ''' [integer] # Integers are whole numbers. # Positive numbers may be prefixed with a plus sign. # Negative numbers are prefixed with a minus sign. int1 = +99 int2 = 42 int3 = 0 int4 = -17 # For large numbers, you may use underscores between digits # to enhance readability. # Each underscore must be surrounded by at least one digit on each side. int5 = 1_000 int6 = 5_349_221 int7 = 1_2_3_4_5 # Non-negative integer values may also be expressed # in hexadecimal, octal, or binary. # In these formats, leading + is not allowed and leading zeros are # allowed (after the prefix). # Hex values are case insensitive. # Underscores are allowed between digits # (but not between the prefix and the value). # hexadecimal with prefix `0x` hex1 = 0xDEADBEEF hex2 = 0xdeadbeef hex3 = 0xdead_beef # octal with prefix `0o` oct1 = 0o01234567 oct2 = 0o755 # useful for Unix file permissions # binary with prefix `0b` bin1 = 0b11010110 [float] # Floats should be implemented as IEEE 754 binary64 values. # A float consists of an integer part # (which follows the same rules as decimal integer values) followed # by a fractional part and/or an exponent part. # If both a fractional part and exponent part are present, # the fractional part must precede the exponent part. # fractional flt1 = +1.0 flt2 = 3.1415 flt3 = -0.01 # exponent flt4 = 5e+22 flt5 = 1e06 flt6 = -2E-2 # both flt7 = 6.626e-34 # Similar to integers, you may use underscores to enhance readability. # Each underscore must be surrounded by at least one digit. flt8 = 224_617.445_991_228 # Float values -0.0 and +0.0 are valid and should map according to IEEE 754. flt9 = -0.0 flt10 = +0.0 # Special float values can also be expressed. They are always lowercase. # infinity sf1 = inf # positive infinity sf2 = +inf # positive infinity sf3 = -inf # negative infinity # not a number sf4 = nan # actual sNaN/qNaN encoding is implementation specific sf5 = +nan # same as `nan` sf6 = -nan # valid, actual encoding is implementation specific [boolean] # Booleans are just the tokens you're used to. Always lowercase. bool1 = true bool2 = false [offset-date-time] # To unambiguously represent a specific instant in time, # you may use an RFC 3339 formatted date-time with offset. odt1 = 1979-05-27T07:32:00Z odt2 = 1979-05-27T00:32:00-07:00 odt3 = 1979-05-27T00:32:00.999999-07:00 # For the sake of readability, you may replace the T delimiter # between date and time with a space (as permitted by RFC 3339 section 5.6). odt4 = 1979-05-27 07:32:00Z [local-date-time] # If you omit the offset from an RFC 3339 formatted date-time, # it will represent the given date-time without any relation # to an offset or timezone. # It cannot be converted to an instant in time without additional information. # Conversion to an instant, if required, is implementation specific. ldt1 = 1979-05-27T07:32:00 ldt2 = 1979-05-27T00:32:00.999999 [local-date] # If you include only the date portion of an RFC 3339 formatted date-time, # it will represent that entire day without any relation # to an offset or timezone. ld1 = 1979-05-27 [local-time] # If you include only the time portion of an RFC 3339 formatted date-time, # it will represent that time of day without any relation to a specific day # or any offset or timezone. lt1 = 07:32:00 lt2 = 00:32:00.999999 [array] # Arrays are square brackets with values inside. # Whitespace is ignored. Elements are separated by commas. # Data types may not be mixed (different ways to define strings # should be considered the same type, # and so should arrays with different element types). arr1 = [ 1, 2, 3 ] arr2 = [ "red", "yellow", "green" ] arr3 = [ [ 1, 2 ], [3, 4, 5] ] arr4 = [ "all", 'strings', """are the same""", '''type'''] arr5 = [ [ 1, 2 ], ["a", "b", "c"] ] # Arrays can also be multiline. # A terminating comma (also called trailing comma) is # ok after the last value of the array. # There can be an arbitrary number of newlines and comments # before a value and before the closing bracket. arr7 = [ 1, 2, 3 ] arr8 = [ 1, 2, # this is ok ] [table] # Tables (also known as hash tables or dictionaries) are # collections of key/value pairs. # They appear in square brackets on a line by themselves. # You can tell them apart from arrays because arrays are only ever values. # Under that, and until the next table or EOF are the key/values of that table. # Key/value pairs within tables are not guaranteed to be in any specific order. [table.table-1] key1 = "some string" key2 = 123 [table.table-2] key1 = "another string" key2 = 456 # Naming rules for tables are the same as for keys (see definition of Keys above). [table.dog."tater.man"] type.name = "pug" # Whitespace around the key is ignored, however, best practice is to not use any extraneous whitespace. [table.a.b.c] # this is best practice [ table.d.e.f ] # same as [d.e.f] [ table . g . h . i ] # same as [g.h.i] [ table . j . "ʞ" . 'l' ] # same as [j."ʞ".'l'] # You don't need to specify all the super-tables if you don't want to. # TOML knows how to do it for you. # [x] you # [x.y] don't # [x.y.z] need these [table.x.y.z.w] # for this to work [table.x] # defining a super-table afterwards is ok # Defining tables out-of-order is discouraged. # VALID BUT DISCOURAGED [table.a.x] [table.b] [table.a.y] # Dotted keys define everything to the left of each dot as a table. # Since tables cannot be defined more than once, # redefining such tables using a [table] header is not allowed. # Likewise, using dotted keys to redefine tables already defined # in [table] form is not allowed. # The [table] form can, however, # be used to define sub-tables within tables defined via dotted keys. [table.fruit] apple.color = "red" apple.taste.sweet = true # [table.fruit.apple] # INVALID # [table.fruit.apple.taste] # INVALID [table.fruit.apple.texture] # you can add sub-tables smooth = true [inline-table] # Inline tables provide a more compact syntax for expressing tables. name = { first = "Tom", last = "Preston-Werner" } point = { x = 1, y = 2 } animal = { type.name = "pug" } [array-of-tables] # Array of Tables are inserted in the order encountered. # A double bracketed table without any key/value pairs # will be considered an empty table. [[array-of-tables.products]] name = "Hammer" sku = 738594937 [[array-of-tables.products]] [[array-of-tables.products]] name = "Nail" sku = 284758393 color = "gray" [[array-of-tables.fruit]] name = "apple" [array-of-tables.fruit.physical] color = "red" shape = "round" [[array-of-tables.fruit.variety]] name = "red delicious" [[array-of-tables.fruit.variety]] name = "granny smith" [[array-of-tables.fruit]] name = "banana" [[array-of-tables.fruit.variety]] name = "plantain" toml-rb-2.1.0/test/example.toml000066400000000000000000000014671413774102700164130ustar00rootroot00000000000000# This is a TomlRB document. Boom. title = "TomlRB Example" [owner] name = "Tom Preston-Werner" organization = "GitHub" bio = "GitHub Cofounder & CEO\nLikes tater tots and beer." dob = 1979-05-27T07:32:00Z # First class dates? Why not? [database] server = "192.168.1.1" ports = [ 8001, 8001, 8002 ] connection_max = 5000 enabled = true [servers] # You can indent as you please. Tabs or spaces. TomlRB don't care. [servers.alpha] ip = "10.0.0.1" dc = "eqdc10" [servers.beta] ip = "10.0.0.2" dc = "eqdc10" [clients] data = [ ["gamma", "delta"], [1, 2] ] # Line breaks are OK when inside arrays hosts = [ "alpha", "omega" ] [amqp] exchange = {durable = true, auto_delete = false} [[products]] name = "Hammer" sku = 738594937 [[products]] [[products]] name = "Nail" sku = 284758393 color = "gray" toml-rb-2.1.0/test/examples/000077500000000000000000000000001413774102700156715ustar00rootroot00000000000000toml-rb-2.1.0/test/examples/invalid/000077500000000000000000000000001413774102700173175ustar00rootroot00000000000000toml-rb-2.1.0/test/examples/invalid/array-mixed-types-arrays-and-ints.toml000066400000000000000000000000651413774102700266130ustar00rootroot00000000000000arrays-and-ints = [1, ["Arrays are not integers."]] toml-rb-2.1.0/test/examples/invalid/array-mixed-types-ints-and-floats.toml000066400000000000000000000000331413774102700265750ustar00rootroot00000000000000ints-and-floats = [1, 1.1] toml-rb-2.1.0/test/examples/invalid/array-mixed-types-strings-and-ints.toml000066400000000000000000000000361413774102700270010ustar00rootroot00000000000000strings-and-ints = ["hi", 42] toml-rb-2.1.0/test/examples/invalid/datetime-malformed-no-leads.toml000066400000000000000000000000371413774102700254540ustar00rootroot00000000000000no-leads = 1987-7-05T17:45:00Z toml-rb-2.1.0/test/examples/invalid/datetime-malformed-no-secs.toml000066400000000000000000000000341413774102700253160ustar00rootroot00000000000000no-secs = 1987-07-05T17:45Z toml-rb-2.1.0/test/examples/invalid/datetime-malformed-no-t.toml000066400000000000000000000000331413774102700246230ustar00rootroot00000000000000no-t = 1987-07-0517:45:00Z toml-rb-2.1.0/test/examples/invalid/datetime-malformed-with-milli.toml000066400000000000000000000000441413774102700260270ustar00rootroot00000000000000with-milli = 1987-07-5T17:45:00.12Z toml-rb-2.1.0/test/examples/invalid/duplicate-key-table.toml000066400000000000000000000000631413774102700240400ustar00rootroot00000000000000[fruit] type = "apple" [fruit.type] apple = "yes" toml-rb-2.1.0/test/examples/invalid/duplicate-keys.toml000066400000000000000000000000311413774102700231310ustar00rootroot00000000000000dupe = false dupe = true toml-rb-2.1.0/test/examples/invalid/duplicate-tables.toml000066400000000000000000000000101413774102700234250ustar00rootroot00000000000000[a] [a] toml-rb-2.1.0/test/examples/invalid/empty-implicit-table.toml000066400000000000000000000000231413774102700242420ustar00rootroot00000000000000[naughty..naughty] toml-rb-2.1.0/test/examples/invalid/empty-table.toml000066400000000000000000000000031413774102700224300ustar00rootroot00000000000000[] toml-rb-2.1.0/test/examples/invalid/float-no-leading-zero.toml000066400000000000000000000000441413774102700243070ustar00rootroot00000000000000answer = .12345 neganswer = -.12345 toml-rb-2.1.0/test/examples/invalid/float-no-trailing-digits.toml000066400000000000000000000000341413774102700250200ustar00rootroot00000000000000answer = 1. neganswer = -1. toml-rb-2.1.0/test/examples/invalid/inline-table-duplicate-key.toml000066400000000000000000000003421413774102700253140ustar00rootroot00000000000000# Inline tables fully define the keys and sub-tables within them. # So, inline tables can not be used to add keys # or sub-tables to an already-defined table. [product] type.name = "Nail" type = { edible = false } # INVALID toml-rb-2.1.0/test/examples/invalid/inline-table-duplicate-key2.toml000066400000000000000000000002541413774102700254000ustar00rootroot00000000000000# Inline tables fully define the keys and sub-tables within them. # New keys and sub-tables cannot be added to them. [product] type = { name = "Nail" } type.edible = false toml-rb-2.1.0/test/examples/invalid/key-empty.toml000066400000000000000000000000051413774102700221330ustar00rootroot00000000000000 = 1 toml-rb-2.1.0/test/examples/invalid/key-hash.toml000066400000000000000000000000071413774102700217220ustar00rootroot00000000000000a# = 1 toml-rb-2.1.0/test/examples/invalid/key-newline.toml000066400000000000000000000000061413774102700224370ustar00rootroot00000000000000a = 1 toml-rb-2.1.0/test/examples/invalid/key-open-bracket.toml000066400000000000000000000000111413774102700233440ustar00rootroot00000000000000[abc = 1 toml-rb-2.1.0/test/examples/invalid/key-single-open-bracket.toml000066400000000000000000000000011413774102700246220ustar00rootroot00000000000000[toml-rb-2.1.0/test/examples/invalid/key-space.toml000066400000000000000000000000071413774102700220720ustar00rootroot00000000000000a b = 1toml-rb-2.1.0/test/examples/invalid/key-start-bracket.toml000066400000000000000000000000211413774102700235410ustar00rootroot00000000000000[a] [xyz = 5 [b] toml-rb-2.1.0/test/examples/invalid/key-two-equals.toml000066400000000000000000000000111413774102700230730ustar00rootroot00000000000000key= = 1 toml-rb-2.1.0/test/examples/invalid/string-bad-byte-escape.toml000066400000000000000000000000211413774102700244360ustar00rootroot00000000000000naughty = "\xAg" toml-rb-2.1.0/test/examples/invalid/string-bad-escape.toml000066400000000000000000000000761413774102700235070ustar00rootroot00000000000000invalid-escape = "This string has a bad \a escape character." toml-rb-2.1.0/test/examples/invalid/string-byte-escapes.toml000066400000000000000000000000201413774102700240740ustar00rootroot00000000000000answer = "\x33" toml-rb-2.1.0/test/examples/invalid/string-no-close.toml000066400000000000000000000000521413774102700232340ustar00rootroot00000000000000no-ending-quote = "One time, at band camp toml-rb-2.1.0/test/examples/invalid/table-array-implicit.toml000066400000000000000000000011601413774102700242250ustar00rootroot00000000000000# This test is a bit tricky. It should fail because the first use of # `[[albums.songs]]` without first declaring `albums` implies that `albums` # must be a table. The alternative would be quite weird. Namely, it wouldn't # comply with the TomlRB spec: "Each double-bracketed sub-table will belong to # the most *recently* defined table element *above* it." # # This is in contrast to the *valid* test, table-array-implicit where # `[[albums.songs]]` works by itself, so long as `[[albums]]` isn't declared # later. (Although, `[albums]` could be.) [[albums.songs]] name = "Glory Days" [[albums]] name = "Born in the USA" toml-rb-2.1.0/test/examples/invalid/table-array-malformed-bracket.toml000066400000000000000000000000371413774102700257740ustar00rootroot00000000000000[[albums] name = "Born to Run" toml-rb-2.1.0/test/examples/invalid/table-array-malformed-empty.toml000066400000000000000000000000321413774102700255120ustar00rootroot00000000000000[[]] name = "Born to Run" toml-rb-2.1.0/test/examples/invalid/table-array-override-table-name.toml000066400000000000000000000002761413774102700262440ustar00rootroot00000000000000# INVALID TomlRB DOC [[fruit]] name = "apple" [[fruit.variety]] name = "red delicious" # This table conflicts with the previous table [fruit.variety] name = "granny smith" toml-rb-2.1.0/test/examples/invalid/table-empty.toml000066400000000000000000000000031413774102700224300ustar00rootroot00000000000000[] toml-rb-2.1.0/test/examples/invalid/table-nested-brackets-close.toml000066400000000000000000000000171413774102700254600ustar00rootroot00000000000000[a]b] zyx = 42 toml-rb-2.1.0/test/examples/invalid/table-nested-brackets-open.toml000066400000000000000000000000171413774102700253140ustar00rootroot00000000000000[a[b] zyx = 42 toml-rb-2.1.0/test/examples/invalid/table-whitespace.toml000066400000000000000000000000151413774102700234310ustar00rootroot00000000000000[invalid key]toml-rb-2.1.0/test/examples/invalid/table-with-double-period.toml000066400000000000000000000000171413774102700250020ustar00rootroot00000000000000[invalid..key] toml-rb-2.1.0/test/examples/invalid/table-with-ending-period.toml000066400000000000000000000000131413774102700247700ustar00rootroot00000000000000[invalid.] toml-rb-2.1.0/test/examples/invalid/table-with-pound.toml000066400000000000000000000000271413774102700233760ustar00rootroot00000000000000[key#group] answer = 42toml-rb-2.1.0/test/examples/invalid/table-with-starting-period.toml000066400000000000000000000000131413774102700253570ustar00rootroot00000000000000[.invalid] toml-rb-2.1.0/test/examples/invalid/text-after-array-entries.toml000066400000000000000000000001061413774102700250570ustar00rootroot00000000000000array = [ "Is there life after an array separator?", No "Entry" ] toml-rb-2.1.0/test/examples/invalid/text-after-integer.toml000066400000000000000000000000411413774102700237250ustar00rootroot00000000000000answer = 42 the ultimate answer? toml-rb-2.1.0/test/examples/invalid/text-after-string.toml000066400000000000000000000000541413774102700236020ustar00rootroot00000000000000string = "Is there life after strings?" No. toml-rb-2.1.0/test/examples/invalid/text-after-table.toml000066400000000000000000000000371413774102700233640ustar00rootroot00000000000000[error] this shouldn't be here toml-rb-2.1.0/test/examples/invalid/text-before-array-separator.toml000066400000000000000000000001071413774102700255500ustar00rootroot00000000000000array = [ "Is there life before an array separator?" No, "Entry" ] toml-rb-2.1.0/test/examples/invalid/text-in-array.toml000066400000000000000000000000701413774102700227150ustar00rootroot00000000000000array = [ "Entry 1", I don't belong, "Entry 2", ] toml-rb-2.1.0/test/examples/valid/000077500000000000000000000000001413774102700167705ustar00rootroot00000000000000toml-rb-2.1.0/test/examples/valid/array-empty.json000066400000000000000000000000361413774102700221340ustar00rootroot00000000000000{ "thevoid": [[[[[]]]]] } toml-rb-2.1.0/test/examples/valid/array-empty.toml000066400000000000000000000000251413774102700221340ustar00rootroot00000000000000thevoid = [[[[[]]]]] toml-rb-2.1.0/test/examples/valid/array-nospaces.json000066400000000000000000000000301413774102700226030ustar00rootroot00000000000000{ "ints": [1,2,3] } toml-rb-2.1.0/test/examples/valid/array-nospaces.toml000066400000000000000000000000171413774102700226120ustar00rootroot00000000000000ints = [1,2,3] toml-rb-2.1.0/test/examples/valid/arrays-hetergeneous.json000066400000000000000000000000621413774102700236550ustar00rootroot00000000000000{ "mixed": [[1, 2], ["a", "b"], [1.1, 2.1]] } toml-rb-2.1.0/test/examples/valid/arrays-hetergeneous.toml000066400000000000000000000000511413774102700236550ustar00rootroot00000000000000mixed = [[1, 2], ["a", "b"], [1.1, 2.1]] toml-rb-2.1.0/test/examples/valid/arrays-nested.json000066400000000000000000000000371413774102700224440ustar00rootroot00000000000000{ "nest": [["a"], ["b"]] } toml-rb-2.1.0/test/examples/valid/arrays-nested.toml000066400000000000000000000000261413774102700224440ustar00rootroot00000000000000nest = [["a"], ["b"]] toml-rb-2.1.0/test/examples/valid/arrays.json000066400000000000000000000003651413774102700211700ustar00rootroot00000000000000{ "ints": [1, 2, 3], "floats": [1.1, 2.1, 3.1, 410000.0], "strings": ["a", "b", "c"], "multiline_strings": ["This is a test string", "Other test string"], "multiline_literal": ["This is a test string", "Other test string"] } toml-rb-2.1.0/test/examples/valid/arrays.toml000066400000000000000000000006061413774102700211700ustar00rootroot00000000000000ints = [1, 2, 3] floats = [1.1, 2.1, 3.1, 4.1E+5] strings = ["a", "b", "c"] multiline_strings = ["""\ This \ is \ a \ test \ string""", "Other test string"] multiline_literal = ['''\ This \ is \ a \ test \ string''', "Other test string"] toml-rb-2.1.0/test/examples/valid/bool.json000066400000000000000000000000421413774102700206120ustar00rootroot00000000000000{ "f": false, "t": true } toml-rb-2.1.0/test/examples/valid/bool.toml000066400000000000000000000000231413774102700206130ustar00rootroot00000000000000t = true f = false toml-rb-2.1.0/test/examples/valid/comments-everywhere.json000066400000000000000000000001161413774102700236710ustar00rootroot00000000000000{ "group": { "answer": 42, "more": [ 42, 42 ] } } toml-rb-2.1.0/test/examples/valid/comments-everywhere.toml000066400000000000000000000007251413774102700237010ustar00rootroot00000000000000# Top comment. # Top comment. # Top comment. # [no-extraneous-groups-please] [group] # Comment answer = 42 # Comment # no-extraneous-keys-please = 999 # Between comment. more = [ # Comment # What about multiple # comments? # Can you handle it? # # Evil. # Evil. 42, 42, # Comments within arrays are fun. # What about multiple # comments? # Can you handle it? # # Evil. # Such evil # Evil. # ] Did I fool you? ] # Hopefully not. toml-rb-2.1.0/test/examples/valid/empty.json000066400000000000000000000000031413774102700210120ustar00rootroot00000000000000{} toml-rb-2.1.0/test/examples/valid/empty.toml000066400000000000000000000000001413774102700210110ustar00rootroot00000000000000toml-rb-2.1.0/test/examples/valid/example.json000066400000000000000000000001451413774102700213160ustar00rootroot00000000000000{ "numtheory": { "boring": false, "perfection": [ 6, 28, 496 ] } } toml-rb-2.1.0/test/examples/valid/example.toml000066400000000000000000000000651413774102700213210ustar00rootroot00000000000000[numtheory] boring = false perfection = [6, 28, 496] toml-rb-2.1.0/test/examples/valid/float.json000066400000000000000000000000471413774102700207710ustar00rootroot00000000000000{ "pi": 3.14, "negpi": -3.14 } toml-rb-2.1.0/test/examples/valid/float.toml000066400000000000000000000000301413774102700207630ustar00rootroot00000000000000pi = 3.14 negpi = -3.14 toml-rb-2.1.0/test/examples/valid/implicit-and-explicit-after.json000066400000000000000000000002021413774102700251450ustar00rootroot00000000000000{ "a": { "better": 43, "b": { "c": { "answer": 42 } } } } toml-rb-2.1.0/test/examples/valid/implicit-and-explicit-after.toml000066400000000000000000000000451413774102700251540ustar00rootroot00000000000000[a.b.c] answer = 42 [a] better = 43 toml-rb-2.1.0/test/examples/valid/implicit-and-explicit-before.json000066400000000000000000000002021413774102700253060ustar00rootroot00000000000000{ "a": { "better": 43, "b": { "c": { "answer": 42 } } } } toml-rb-2.1.0/test/examples/valid/implicit-and-explicit-before.toml000066400000000000000000000000451413774102700253150ustar00rootroot00000000000000[a] better = 43 [a.b.c] answer = 42 toml-rb-2.1.0/test/examples/valid/implicit-groups.json000066400000000000000000000001541413774102700230120ustar00rootroot00000000000000{ "a": { "b": { "c": { "answer": 42 } } } } toml-rb-2.1.0/test/examples/valid/implicit-groups.toml000066400000000000000000000000241413774102700230100ustar00rootroot00000000000000[a.b.c] answer = 42 toml-rb-2.1.0/test/examples/valid/integer.json000066400000000000000000000000471413774102700213210ustar00rootroot00000000000000{ "answer": 42, "neganswer": -42 } toml-rb-2.1.0/test/examples/valid/integer.toml000066400000000000000000000000341413774102700213170ustar00rootroot00000000000000answer = 42 neganswer = -42 toml-rb-2.1.0/test/examples/valid/key-equals-nospace.json000066400000000000000000000000251413774102700233660ustar00rootroot00000000000000{ "answer": 42 } toml-rb-2.1.0/test/examples/valid/key-equals-nospace.toml000066400000000000000000000000121413774102700233640ustar00rootroot00000000000000answer=42 toml-rb-2.1.0/test/examples/valid/key-space.json000066400000000000000000000000211413774102700215350ustar00rootroot00000000000000{ "a b": 1 } toml-rb-2.1.0/test/examples/valid/key-space.toml000066400000000000000000000000121413774102700215370ustar00rootroot00000000000000"a b" = 1 toml-rb-2.1.0/test/examples/valid/key-special-chars.json000066400000000000000000000000611413774102700231640ustar00rootroot00000000000000{ "~!@$^&*()_+-`1234567890[]|/?><.,;:'": 1 } toml-rb-2.1.0/test/examples/valid/key-special-chars.toml000066400000000000000000000000521413774102700231660ustar00rootroot00000000000000"~!@$^&*()_+-`1234567890[]|/?><.,;:'" = 1 toml-rb-2.1.0/test/examples/valid/key-starts-with-number.json000066400000000000000000000000531413774102700242260ustar00rootroot00000000000000{ "123-key": "value", "12345": 67890 } toml-rb-2.1.0/test/examples/valid/key-starts-with-number.toml000066400000000000000000000000401413774102700242240ustar00rootroot00000000000000123-key = "value" 12345 = 67890 toml-rb-2.1.0/test/examples/valid/key-with-pound.json000066400000000000000000000000261413774102700225450ustar00rootroot00000000000000{ "key#name": 5 } toml-rb-2.1.0/test/examples/valid/key-with-pound.toml000066400000000000000000000000171413774102700225470ustar00rootroot00000000000000"key#name" = 5 toml-rb-2.1.0/test/examples/valid/long-float.json000066400000000000000000000001051413774102700217210ustar00rootroot00000000000000{ "longpi": 3.141592653589793, "neglongpi": -3.141592653589793 } toml-rb-2.1.0/test/examples/valid/long-float.toml000066400000000000000000000000721413774102700217260ustar00rootroot00000000000000longpi = 3.141592653589793 neglongpi = -3.141592653589793 toml-rb-2.1.0/test/examples/valid/long-integer.json000066400000000000000000000001111413774102700222460ustar00rootroot00000000000000{ "answer": 9223372036854775807, "neganswer": -9223372036854775808 } toml-rb-2.1.0/test/examples/valid/long-integer.toml000066400000000000000000000000761413774102700222620ustar00rootroot00000000000000answer = 9223372036854775807 neganswer = -9223372036854775808 toml-rb-2.1.0/test/examples/valid/multiline-string.json000066400000000000000000000005521413774102700231730ustar00rootroot00000000000000{ "multiline_empty_one": "", "multiline_empty_two": "", "multiline_empty_three": "", "multiline_empty_four": "", "equivalent_one": "The quick brown fox jumps over the lazy dog.", "equivalent_two": "The quick brown fox jumps over the lazy dog.", "equivalent_three": "The quick brown fox jumps over the lazy dog.", "issue_89": "\"Hello\nWorld\"" } toml-rb-2.1.0/test/examples/valid/multiline-string.toml000066400000000000000000000006511413774102700231750ustar00rootroot00000000000000multiline_empty_one = "" multiline_empty_two = """\ """ multiline_empty_three = """\ """ multiline_empty_four = """\ \ \ """ equivalent_one = "The quick brown fox jumps over the lazy dog." equivalent_two = """ The quick brown \ fox jumps over \ the lazy dog.""" equivalent_three = """\ The quick brown \ fox jumps over \ the lazy dog.\ """ issue_89 = """\"Hello World\"""" toml-rb-2.1.0/test/examples/valid/raw-multiline-string.json000066400000000000000000000003101413774102700237520ustar00rootroot00000000000000{ "oneline": "This string has a ' quote character.", "firstnl": "This string has a ' quote character.", "multiline": "This string\nhas ' a quote character\nand more than\none newline\nin it." } toml-rb-2.1.0/test/examples/valid/raw-multiline-string.toml000066400000000000000000000003031413774102700237560ustar00rootroot00000000000000oneline = '''This string has a ' quote character.''' firstnl = ''' This string has a ' quote character.''' multiline = ''' This string has ' a quote character and more than one newline in it.''' toml-rb-2.1.0/test/examples/valid/raw-string.json000066400000000000000000000006341413774102700217630ustar00rootroot00000000000000{ "backspace": "This string has a \\b backspace character.", "tab": "This string has a \\t tab character.", "newline": "This string has a \\n new line character.", "formfeed": "This string has a \\f form feed character.", "carriage": "This string has a \\r carriage return character.", "slash": "This string has a \\/ slash character.", "backslash": "This string has a \\\\ backslash character." } toml-rb-2.1.0/test/examples/valid/raw-string.toml000066400000000000000000000005651413774102700217700ustar00rootroot00000000000000backspace = 'This string has a \b backspace character.' tab = 'This string has a \t tab character.' newline = 'This string has a \n new line character.' formfeed = 'This string has a \f form feed character.' carriage = 'This string has a \r carriage return character.' slash = 'This string has a \/ slash character.' backslash = 'This string has a \\ backslash character.' toml-rb-2.1.0/test/examples/valid/string-empty.json000066400000000000000000000000251413774102700223220ustar00rootroot00000000000000{ "answer": "" } toml-rb-2.1.0/test/examples/valid/string-empty.toml000066400000000000000000000000141413774102700223220ustar00rootroot00000000000000answer = "" toml-rb-2.1.0/test/examples/valid/string-escapes.json000066400000000000000000000013151413774102700226120ustar00rootroot00000000000000{ "backspace": "This string has a \u0008 backspace character.", "tab": "This string has a \u0009 tab character.", "newline": "This string has a \u000A new line character.", "formfeed": "This string has a \u000C form feed character.", "carriage": "This string has a \u000D carriage return character.", "quote": "This string has a \u0022 quote character.", "backslash": "This string has a \u005C backslash character.", "notunicode1": "This string does not have a unicode \\u escape.", "notunicode2": "This string does not have a unicode \u005Cu escape.", "notunicode3": "This string does not have a unicode \\u0075 escape.", "notunicode4": "This string does not have a unicode \\\u0075 escape." } toml-rb-2.1.0/test/examples/valid/string-escapes.toml000066400000000000000000000012021413774102700226070ustar00rootroot00000000000000backspace = "This string has a \b backspace character." tab = "This string has a \t tab character." newline = "This string has a \n new line character." formfeed = "This string has a \f form feed character." carriage = "This string has a \r carriage return character." quote = "This string has a \" quote character." backslash = "This string has a \\ backslash character." notunicode1 = "This string does not have a unicode \\u escape." notunicode2 = "This string does not have a unicode \u005Cu escape." notunicode3 = "This string does not have a unicode \\u0075 escape." notunicode4 = "This string does not have a unicode \\\u0075 escape." toml-rb-2.1.0/test/examples/valid/string-simple.json000066400000000000000000000000661413774102700224620ustar00rootroot00000000000000{ "answer": "You are not drinking enough whisky." } toml-rb-2.1.0/test/examples/valid/string-simple.toml000066400000000000000000000000571413774102700224640ustar00rootroot00000000000000answer = "You are not drinking enough whisky." toml-rb-2.1.0/test/examples/valid/string-with-pound.json000066400000000000000000000001451413774102700232650ustar00rootroot00000000000000{ "pound": "We see no # comments here.", "poundcomment": "But there are # some comments here." } toml-rb-2.1.0/test/examples/valid/string-with-pound.toml000066400000000000000000000001611413774102700232650ustar00rootroot00000000000000pound = "We see no # comments here." poundcomment = "But there are # some comments here." # Did I # mess you up? toml-rb-2.1.0/test/examples/valid/table-array-implicit.json000066400000000000000000000001301413774102700236700ustar00rootroot00000000000000{ "albums": { "songs": [ { "name": "Glory Days" } ] } } toml-rb-2.1.0/test/examples/valid/table-array-implicit.toml000066400000000000000000000000451413774102700236770ustar00rootroot00000000000000[[albums.songs]] name = "Glory Days" toml-rb-2.1.0/test/examples/valid/table-array-many.json000066400000000000000000000003511413774102700230270ustar00rootroot00000000000000{ "people": [ { "first_name": "Bruce", "last_name": "Springsteen" }, { "first_name": "Eric", "last_name": "Clapton" }, { "first_name": "Bob", "last_name": "Seger" } ] } toml-rb-2.1.0/test/examples/valid/table-array-many.toml000066400000000000000000000002431413774102700230310ustar00rootroot00000000000000[[people]] first_name = "Bruce" last_name = "Springsteen" [[people]] first_name = "Eric" last_name = "Clapton" [[people]] first_name = "Bob" last_name = "Seger" toml-rb-2.1.0/test/examples/valid/table-array-nest.json000066400000000000000000000005771413774102700230460ustar00rootroot00000000000000{ "fruit": [ { "name": "apple", "physical": { "color": "red", "shape": "round" }, "variety": [ { "name": "red delicious" }, { "name": "granny smith" } ] }, { "name": "banana", "physical": { "color": "yellow" }, "variety": [ { "name": "plantain" } ] } ] } toml-rb-2.1.0/test/examples/valid/table-array-nest.toml000066400000000000000000000004451413774102700230420ustar00rootroot00000000000000[[fruit]] name = "apple" [fruit.physical] color = "red" shape = "round" [[fruit.variety]] name = "red delicious" [[fruit.variety]] name = "granny smith" [[fruit]] name = "banana" [fruit.physical] color = "yellow" [[fruit.variety]] name = "plantain" toml-rb-2.1.0/test/examples/valid/table-array-one.json000066400000000000000000000001401413774102700226400ustar00rootroot00000000000000{ "people": [ { "first_name": "Bruce", "last_name": "Springsteen" } ] } toml-rb-2.1.0/test/examples/valid/table-array-one.toml000066400000000000000000000000721413774102700226460ustar00rootroot00000000000000[[people]] first_name = "Bruce" last_name = "Springsteen" toml-rb-2.1.0/test/examples/valid/table-array-whitespace.json000066400000000000000000000001751413774102700242230ustar00rootroot00000000000000{ "people": { "attrs": [ { "first_name": "Bruce", "last_name": "Springsteen" } ] } } toml-rb-2.1.0/test/examples/valid/table-array-whitespace.toml000066400000000000000000000001031413774102700242140ustar00rootroot00000000000000[[ people .attrs ]] first_name = "Bruce" last_name = "Springsteen" toml-rb-2.1.0/test/examples/valid/table-empty.json000066400000000000000000000000201413774102700220760ustar00rootroot00000000000000{ "a": {} } toml-rb-2.1.0/test/examples/valid/table-empty.toml000066400000000000000000000000041413774102700221020ustar00rootroot00000000000000[a] toml-rb-2.1.0/test/examples/valid/table-sub-empty.json000066400000000000000000000000311413774102700226670ustar00rootroot00000000000000{ "a": { "b": {} } } toml-rb-2.1.0/test/examples/valid/table-sub-empty.toml000066400000000000000000000000121413774102700226700ustar00rootroot00000000000000[a] [a.b] toml-rb-2.1.0/test/examples/valid/table-whitespace.json000066400000000000000000000001601413774102700231010ustar00rootroot00000000000000{ "valid key": {}, "also": { "valid": {} }, "apparently": { "this.is": { "valid": { "too": {} }}} } toml-rb-2.1.0/test/examples/valid/table-whitespace.toml000066400000000000000000000001031413774102700231000ustar00rootroot00000000000000["valid key"] [ also.valid ] [ apparently . "this.is". valid.too ] toml-rb-2.1.0/test/examples/valid/table-with-pound.json000066400000000000000000000000521413774102700230430ustar00rootroot00000000000000{ "key#group": { "answer": 42 } } toml-rb-2.1.0/test/examples/valid/table-with-pound.toml000066400000000000000000000000321413774102700230430ustar00rootroot00000000000000["key#group"] answer = 42 toml-rb-2.1.0/test/examples/valid/unicode-escape.json000066400000000000000000000000611413774102700225440ustar00rootroot00000000000000{ "answer4": "\u03B4", "answer8": "\u03B4" } toml-rb-2.1.0/test/examples/valid/unicode-escape.toml000066400000000000000000000000521413774102700225460ustar00rootroot00000000000000answer4 = "\u03B4" answer8 = "\U000003B4" toml-rb-2.1.0/test/examples/valid/unicode-literal.json000066400000000000000000000000251413774102700227400ustar00rootroot00000000000000{ "answer": "δ" } toml-rb-2.1.0/test/examples/valid/unicode-literal.toml000066400000000000000000000000161413774102700227420ustar00rootroot00000000000000answer = "δ" toml-rb-2.1.0/test/grammar_test.rb000066400000000000000000000256471413774102700171030ustar00rootroot00000000000000require_relative "helper" class GrammarTest < Minitest::Test def test_comment match = TomlRB::Document.parse(" # A comment", root: :comment) assert_nil(match.value) end def test_key match = TomlRB::Document.parse("bad_key-", root: :key) assert_equal("bad_key-", match.value.first) match = TomlRB::Document.parse('"123.ʎǝʞ.#?"', root: :key) assert_equal("123.ʎǝʞ.#?", match.value.first) end def test_table indentation_alternatives_for("[akey]") do |str| match = TomlRB::Document.parse(str, root: :table) assert_equal(TomlRB::Table, match.value.class) assert_equal(["akey"], match.value.instance_variable_get("@dotted_keys")) end match = TomlRB::Document.parse("[owner.emancu]", root: :table) assert_equal(%w[owner emancu], match.value.instance_variable_get("@dotted_keys")) match = TomlRB::Document.parse('["owner.emancu"]', root: :table) assert_equal(%w[owner.emancu], match.value.instance_variable_get("@dotted_keys")) match = TomlRB::Document.parse('["first key"."second key"]', root: :table) assert_equal(["first key", "second key"], match.value.instance_variable_get("@dotted_keys")) match = TomlRB::Document.parse("[ owner . emancu ]", root: :table) assert_equal(%w[owner emancu], match.value.instance_variable_get("@dotted_keys")) assert_raises Citrus::ParseError do TomlRB::Document.parse("[ owner emancu ]", root: :table) end end def test_keyvalue indentation_alternatives_for('key = "value"') do |str| match = TomlRB::Document.parse(str, root: :keyvalue) assert_equal(TomlRB::Keyvalue, match.value.class) keyvalue = match.value assert_equal("key", keyvalue.instance_variable_get("@dotted_keys").first) assert_equal("value", keyvalue.instance_variable_get("@value")) end indentation_alternatives_for('key1."key2".key3 = "value"') do |str| match = TomlRB::Document.parse(str, root: :keyvalue) assert_equal(TomlRB::Keyvalue, match.value.class) keyvalue = match.value assert_equal("key1", keyvalue.instance_variable_get("@dotted_keys")[0]) assert_equal("key2", keyvalue.instance_variable_get("@dotted_keys")[1]) assert_equal("key3", keyvalue.instance_variable_get("@dotted_keys")[2]) assert_equal("value", keyvalue.instance_variable_get("@value")) end end def test_string match = TomlRB::Document.parse('"TomlRB-Example, should work."', root: :string) assert_equal("TomlRB-Example, should work.", match.value) end def test_multiline_string match = TomlRB::Document.parse('"""\tOne\nTwo"""', root: :multiline_string) assert_equal "\tOne\nTwo", match.value to_parse = '"""\ One \ Two\ """' match = TomlRB::Document.parse(to_parse, root: :multiline_string) assert_equal "One Two", match.value end def test_empty_multiline_string to_parse = '""""""' match = TomlRB::Document.parse(to_parse, root: :multiline_string) assert_equal "", match.value end def test_special_characters match = TomlRB::Document.parse('"\0 \" \t \n \r"', root: :string) assert_equal("\0 \" \t \n \r", match.value) match = TomlRB::Document.parse('"C:\\\\Documents\\\\nada.exe"', root: :string) assert_equal("C:\\Documents\\nada.exe", match.value) end def test_bool match = TomlRB::Document.parse("true", root: :bool) assert_equal(true, match.value) match = TomlRB::Document.parse("false", root: :bool) assert_equal(false, match.value) end def test_integer match = TomlRB::Document.parse("+99", root: :integer) assert_equal(99, match.value) match = TomlRB::Document.parse("42", root: :integer) assert_equal(42, match.value) match = TomlRB::Document.parse("0", root: :integer) assert_equal(0, match.value) match = TomlRB::Document.parse("-17", root: :integer) assert_equal(-17, match.value) match = TomlRB::Document.parse("1_000", root: :integer) assert_equal(1_000, match.value) match = TomlRB::Document.parse("5_349_221", root: :integer) assert_equal(5_349_221, match.value) match = TomlRB::Document.parse("1_2_3_4_5", root: :integer) assert_equal(1_2_3_4_5, match.value) match = TomlRB::Document.parse("0xDEADBEEF", root: :integer) assert_equal(0xDEADBEEF, match.value) match = TomlRB::Document.parse("0xdeadbeef", root: :integer) assert_equal(0xdeadbeef, match.value) match = TomlRB::Document.parse("0xdead_beef", root: :integer) assert_equal(0xdead_beef, match.value) match = TomlRB::Document.parse("0o01234567", root: :integer) assert_equal(0o01234567, match.value) match = TomlRB::Document.parse("0o755", root: :integer) assert_equal(0o755, match.value) match = TomlRB::Document.parse("0b11010110", root: :integer) assert_equal(0b11010110, match.value) end def test_float match = TomlRB::Document.parse("+1.0", root: :float) assert_equal(+1.0, match.value) match = TomlRB::Document.parse("3.1415", root: :float) assert_equal(3.1415, match.value) match = TomlRB::Document.parse("-0.01", root: :float) assert_equal(-0.01, match.value) match = TomlRB::Document.parse("5e+22", root: :float) assert_equal(5e+22, match.value) match = TomlRB::Document.parse("1e6", root: :float) assert_equal(1e6, match.value) match = TomlRB::Document.parse("-2E-2", root: :float) assert_equal(-2E-2, match.value) match = TomlRB::Document.parse("6.626e-34", root: :float) assert_equal(6.626e-34, match.value) match = TomlRB::Document.parse("224_617.445_991_228", root: :float) assert_equal(224_617.445_991_228, match.value) match = TomlRB::Document.parse("inf", root: :float) assert_equal(Float::INFINITY, match.value) match = TomlRB::Document.parse("+inf", root: :float) assert_equal(Float::INFINITY, match.value) match = TomlRB::Document.parse("-inf", root: :float) assert_equal(-Float::INFINITY, match.value) match = TomlRB::Document.parse("nan", root: :float) assert(match.value.nan?) match = TomlRB::Document.parse("+nan", root: :float) assert(match.value.nan?) match = TomlRB::Document.parse("-nan", root: :float) assert(match.value.nan?) end def test_signed_numbers match = TomlRB::Document.parse("+26", root: :number) assert_equal(26, match.value) match = TomlRB::Document.parse("-26", root: :number) assert_equal(-26, match.value) match = TomlRB::Document.parse("1.69", root: :number) assert_equal(1.69, match.value) match = TomlRB::Document.parse("-1.69", root: :number) assert_equal(-1.69, match.value) end def test_expressions_with_comments match = TomlRB::Document.parse("[shouldwork] # with comment", root: :table) assert_equal(["shouldwork"], match.value.instance_variable_get("@dotted_keys")) match = TomlRB::Document.parse("works = true # with comment", root: :keyvalue).value assert_equal("works", match.instance_variable_get("@dotted_keys").first) assert_equal(true, match.instance_variable_get("@value")) end def test_array match = TomlRB::Document.parse("[]", root: :array) assert_equal([], match.value) match = TomlRB::Document.parse("[ 2, 4]", root: :array) assert_equal([2, 4], match.value) match = TomlRB::Document.parse("[ 2.4, 4.72]", root: :array) assert_equal([2.4, 4.72], match.value) match = TomlRB::Document.parse('[ "hey", "TomlRB"]', root: :array) assert_equal(%w[hey TomlRB], match.value) match = TomlRB::Document.parse('[ ["hey", "TomlRB"], [2,4] ]', root: :array) assert_equal([%w[hey TomlRB], [2, 4]], match.value) match = TomlRB::Document.parse("[ { one = 1 }, { two = 2, three = 3} ]", root: :array) assert_equal([{"one" => 1}, {"two" => 2, "three" => 3}], match.value) end def test_empty_array # test that [] is parsed as array and not as inline table array match = TomlRB::Document.parse("a = []", root: :keyvalue).value assert_equal [], match.value end def test_multiline_array multiline_array = "[ \"hey\",\n \"ho\",\n\t \"lets\", \"go\",\n ]" match = TomlRB::Document.parse(multiline_array, root: :array) assert_equal(%w[hey ho lets go], match.value) multiline_array = "[\n#1,\n2,\n# 3\n]" match = TomlRB::Document.parse(multiline_array, root: :array) assert_equal([2], match.value) multiline_array = "[\n# comment\n#, more comments\n4]" match = TomlRB::Document.parse(multiline_array, root: :array) assert_equal([4], match.value) multiline_array = "[\n 1,\n # 2,\n 3 ,\n]" match = TomlRB::Document.parse(multiline_array, root: :array) assert_equal([1, 3], match.value) multiline_array = "[\n 1 , # useless comment\n # 2,\n 3 #other comment\n]" match = TomlRB::Document.parse(multiline_array, root: :array) assert_equal([1, 3], match.value) end # Dates are really hard to test from JSON, due the imposibility to represent # datetimes without quotes. def test_datetime match = TomlRB::Document.parse("1979-05-27T07:32:00Z", root: :datetime) assert_equal(Time.utc(1979, 5, 27, 7, 32, 0), match.value) match = TomlRB::Document.parse("1979-05-27T00:32:00-07:00", root: :datetime) assert_equal(Time.new(1979, 5, 27, 0, 32, 0, "-07:00"), match.value) match = TomlRB::Document.parse("1979-05-27T00:32:00.999999-07:00", root: :datetime) assert_equal(Time.new(1979, 5, 27, 0, 32, 0.999999, "-07:00"), match.value) match = TomlRB::Document.parse("1979-05-27 07:32:00Z", root: :datetime) assert_equal(Time.utc(1979, 5, 27, 7, 32, 0), match.value) match = TomlRB::Document.parse("1979-05-27T07:32:00", root: :datetime) assert_equal(Time.local(1979, 5, 27, 7, 32, 0), match.value) match = TomlRB::Document.parse("1979-05-27T00:32:00.999999", root: :datetime) assert_equal(Time.local(1979, 5, 27, 0, 32, 0, 999999), match.value) match = TomlRB::Document.parse("1979-05-27", root: :datetime) assert_equal(Time.local(1979, 5, 27), match.value) match = TomlRB::Document.parse("07:32:00", root: :datetime) assert_equal(Time.at(3600 * 7 + 60 * 32), match.value) match = TomlRB::Document.parse("00:32:00.999999", root: :datetime) assert_equal(Time.at(60 * 32, 999999), match.value) end def test_inline_table match = TomlRB::Document.parse("{ }", root: :inline_table) assert_equal({}, match.value.value) match = TomlRB::Document.parse("{ simple = true, params = 2 }", root: :inline_table) assert_equal({"simple" => true, "params" => 2}, match.value.value) match = TomlRB::Document.parse("{ nest = { really = { hard = true } } }", root: :inline_table) assert_equal({"nest" => {"really" => {"hard" => true}}}, match.value.value) assert_equal({nest: {really: {hard: true}}}, match.value.value(true)) end private # Creates all the alternatives of valid indentations to test def indentation_alternatives_for(str) [str, " #{str}", "\t#{str}", "\t\t#{str}"].each do |alternative| yield(alternative) end end end toml-rb-2.1.0/test/hard_example.toml000066400000000000000000000027721413774102700174110ustar00rootroot00000000000000# Test file for TomlRB # Only this one tries to emulate a TomlRB file written by a user of the kind of parser writers probably hate # This part you'll really hate [the] test_string = "You'll hate me after this - #" # " Annoying, isn't it? [the.hard] test_array = [ "] ", " # "] # ] There you go, parse this! test_array2 = [ "Test #11 ]proved that", "Experiment #9 was a success" ] # You didn't think it'd as easy as chucking out the last #, did you? another_test_string = " Same thing, but with a string #" harder_test_string = " And when \"'s are in the string, along with # \"" # "and comments are there too" # Things will get harder [the.hard."bit#"] "what?" = "You don't think some user won't do that?" multi_line_array = [ "]", # ] Oh yes I did ] [parent.child1] key = 'value' [[parent.child2]] key2 = 'value' [[parent.child2]] key3 = 'value' [[a.b]] c = 3 # Each of the following table/key value pairs should produce an error. Uncomment to them to test #[error] if you didn't catch this, your parser is broken #string = "Anything other than tabs, spaces and newline after a table or key value pair has ended should produce an error unless it is a comment" like this #array = [ # "This might most likely happen in multiline arrays", # Like here, # "or here, # and here" # ] End of array comment, forgot the # #number = 3.14 pi <--again forgot the # toml-rb-2.1.0/test/helper.rb000066400000000000000000000000751413774102700156610ustar00rootroot00000000000000require "minitest/autorun" require_relative "../lib/toml-rb" toml-rb-2.1.0/test/toml_examples.rb000066400000000000000000000246421413774102700172610ustar00rootroot00000000000000class TomlRB::Examples def self.example_v_0_4_0 { "table" => { "key" => "value", "subtable" => { "key" => "another value" }, "inline" => { "name" => { "first" => "Tom", "last" => "Preston-Werner" }, "point" => { "x" => 1, "y" => 2 } } }, "x" => { "y" => { "z" => { "w" => {} } } }, "string" => { "basic" => { "basic" => "I'm a string. \"You can quote me\". Name\tJos\u00E9\nLocation\tSF." }, "multiline" => { "key1" => "One\nTwo", "key2" => "One\nTwo", "key3" => "One\nTwo", "continued" => { "key1" => "The quick brown fox jumps over the lazy dog.", "key2" => "The quick brown fox jumps over the lazy dog.", "key3" => "The quick brown fox jumps over the lazy dog." } }, "literal" => { "winpath" => "C:\\Users\\nodejs\\templates", "winpath2" => "\\\\ServerX\\admin$\\system32\\", "quoted" => "Tom \"Dubs\" Preston-Werner", "regex" => "<\\i\\c*\\s*>", "multiline" => { "regex2" => "I [dw]on't need \\d{2} apples", "lines" => "The first newline is\ntrimmed in raw strings.\n All other whitespace\n is preserved.\n" } } }, "integer" => { "key1" => 99, "key2" => 42, "key3" => 0, "key4" => -17, "underscores" => { "key1" => 1000, "key2" => 5349221, "key3" => 12345 } }, "float" => { "fractional" => { "key1" => 1.0, "key2" => 3.1415, "key3" => -0.01 }, "exponent" => { "key1" => 5.0e+22, "key2" => 1000000.0, "key3" => -0.02 }, "both" => { "key" => 6.626e-34 }, "underscores" => { "key1" => 9224617.445991227, "key2" => 1e1_00 } }, "boolean" => { "True" => true, "False" => false }, "datetime" => { "key1" => Time.utc(1979, 5, 27, 7, 32, 0), "key2" => Time.new(1979, 5, 27, 0, 32, 0, "-07:00"), "key3" => Time.new(1979, 5, 27, 0, 32, 0.999999, "-07:00") }, "array" => { "key1" => [1, 2, 3], "key2" => %w[red yellow green], "key3" => [[1, 2], [3, 4, 5]], "key4" => [[1, 2], %w[a b c]], "key5" => [1, 2, 3], "key6" => [1, 2] }, "products" => [ {"name" => "Hammer", "sku" => 738594937}, {}, {"name" => "Nail", "sku" => 284758393, "color" => "gray"} ], "fruit" => [ { "name" => "apple", "physical" => { "color" => "red", "shape" => "round" }, "variety" => [ {"name" => "red delicious"}, {"name" => "granny smith"} ] }, { "name" => "banana", "variety" => [ {"name" => "plantain"} ] } ] } end def self.example_v_0_5_0 { "keys" => { "key" => "value", "bare_key" => "value", "bare-key" => "value", "1234" => "value", "127.0.0.1" => "value", "character encoding" => "value", "ʎǝʞ" => "value", "key2" => "value", 'quoted "value"' => "value", "name" => "Orange", "physical" => { "color" => "orange", "shape" => "round" }, "site" => {"google.com" => true}, "3" => {"14159" => "pi"}, "a" => { "b" => {"c" => 1}, "d" => 2, "type" => "", "name" => "", "data" => "" }, "b" => { "type" => "", "name" => "", "data" => "" } }, "string" => { "str1" => "Roses are red\nViolets are blue", "str2" => "Roses are red\nViolets are blue", "str3" => "Roses are red\r\nViolets are blue", "same" => { "str1" => "The quick brown fox jumps over the lazy dog.", "str2" => "The quick brown fox jumps over the lazy dog.", "str3" => "The quick brown fox jumps over the lazy dog." }, "winpath" => "C:\\Users\\nodejs\\templates", "winpath2" => "\\\\ServerX\\admin$\\system32\\", "quoted" => 'Tom "Dubs" Preston-Werner', "regex" => "<\\i\\c*\\s*>", "regex2" => "I [dw]on't need \\d{2} apples", "lines" => "The first newline is\ntrimmed in raw strings.\n All other whitespace\n is preserved.\n" }, "integer" => { "int1" => +99, "int2" => 42, "int3" => 0, "int4" => -17, "int5" => 1000, "int6" => 5349221, "int7" => 12345, "hex1" => 0xDEADBEEF, "hex2" => 0xdeadbeef, "hex3" => 0xdead_beef, "oct1" => 0o01234567, "oct2" => 0o755, "bin1" => 0b11010110 }, "float" => { "flt1" => 1.0, "flt2" => 3.1415, "flt3" => -0.01, "flt4" => 5e+22, "flt5" => 1e06, "flt6" => -2E-2, "flt7" => 6.626e-34, "flt8" => 224_617.445_991_228, "flt9" => -0.0, "flt10" => +0.0, "sf1" => Float::INFINITY, "sf2" => Float::INFINITY, "sf3" => -Float::INFINITY, "sf4" => Float::NAN, "sf5" => Float::NAN, "sf6" => Float::NAN }, "boolean" => { "bool1" => true, "bool2" => false }, "offset-date-time" => { "odt1" => Time.new(1979, 5, 27, 7, 32, 0, "+00:00"), "odt2" => Time.new(1979, 5, 27, 0, 32, 0, "-07:00"), "odt3" => Time.new(1979, 5, 27, 0, 32, 0.999999, "-07:00"), "odt4" => Time.new(1979, 5, 27, 7, 32, 0, "+00:00") }, "local-date-time" => { "ldt1" => Time.local(1979, 5, 27, 7, 32, 0), "ldt2" => Time.local(1979, 5, 27, 0, 32, 0, 999999) }, "local-date" => { "ld1" => Time.local(1979, 5, 27) }, "local-time" => { "lt1" => Time.at(3600 * 7 + 60 * 32 + 0, 0), "lt2" => Time.at(3600 * 0 + 60 * 32 + 0, 999999) }, "array" => { "arr1" => [1, 2, 3], "arr2" => ["red", "yellow", "green"], "arr3" => [[1, 2], [3, 4, 5]], "arr4" => ["all", "strings", "are the same", "type"], "arr5" => [[1, 2], ["a", "b", "c"]], "arr7" => [1, 2, 3], "arr8" => [1, 2] }, "table" => { "table-1" => { "key1" => "some string", "key2" => 123 }, "table-2" => { "key1" => "another string", "key2" => 456 }, "dog" => { "tater.man" => { "type" => { "name" => "pug" } } }, "a" => { "b" => { "c" => {} }, "x" => {}, "y" => {} }, "d" => { "e" => { "f" => {} } }, "g" => { "h" => { "i" => {} } }, "j" => { "ʞ" => { "l" => {} } }, "x" => { "y" => { "z" => { "w" => {} } } }, "b" => {}, "fruit" => { "apple" => { "color" => "red", "taste" => { "sweet" => true }, "texture" => { "smooth" => true } } } }, "inline-table" => { "name" => { "first" => "Tom", "last" => "Preston-Werner" }, "point" => { "x" => 1, "y" => 2 }, "animal" => { "type" => { "name" => "pug" } } }, "array-of-tables" => { "products" => [ {"name" => "Hammer", "sku" => 738594937}, {}, {"name" => "Nail", "sku" => 284758393, "color" => "gray"} ], "fruit" => [ { "name" => "apple", "physical" => { "color" => "red", "shape" => "round" }, "variety" => [ {"name" => "red delicious"}, {"name" => "granny smith"} ] }, { "name" => "banana", "variety" => [ {"name" => "plantain"} ] } ] } } end def self.example { "title" => "TomlRB Example", "owner" => { "name" => "Tom Preston-Werner", "organization" => "GitHub", "bio" => "GitHub Cofounder & CEO\nLikes tater tots and beer.", "dob" => Time.utc(1979, 5, 27, 7, 32, 0) }, "database" => { "server" => "192.168.1.1", "ports" => [8001, 8001, 8002], "connection_max" => 5000, "enabled" => true }, "servers" => { "alpha" => { "ip" => "10.0.0.1", "dc" => "eqdc10" }, "beta" => { "ip" => "10.0.0.2", "dc" => "eqdc10" } }, "clients" => { "data" => [%w[gamma delta], [1, 2]], "hosts" => %w[alpha omega] }, "amqp" => { "exchange" => { "durable" => true, "auto_delete" => false } }, "products" => [ {"name" => "Hammer", "sku" => 738_594_937}, {}, {"name" => "Nail", "sku" => 284_758_393, "color" => "gray"} ] } end def self.hard_example { "the" => { "test_string" => "You'll hate me after this - #", "hard" => { "test_array" => ["] ", " # "], "test_array2" => ["Test #11 ]proved that", "Experiment #9 was a success"], "another_test_string" => " Same thing, but with a string #", "harder_test_string" => " And when \"'s are in the string, along with # \"", "bit#" => { "what?" => "You don't think some user won't do that?", "multi_line_array" => ["]"] } } }, "parent" => { "child1" => {"key" => "value"}, "child2" => [ {"key2" => "value"}, {"key3" => "value"} ] }, "a" => { "b" => [ {"c" => 3} ] } } end end toml-rb-2.1.0/test/toml_test.rb000066400000000000000000000105341413774102700164150ustar00rootroot00000000000000require_relative "helper" require_relative "toml_examples" require "json" class TomlTest < Minitest::Test def test_file_v_0_4_0 path = File.join(File.dirname(__FILE__), "example-v0.4.0.toml") parsed = TomlRB.load_file(path) hash = TomlRB::Examples.example_v_0_4_0 assert_equal hash["array"], parsed["array"] assert_equal hash["boolean"], parsed["boolean"] assert_equal hash["datetime"], parsed["datetime"] assert_equal hash["float"], parsed["float"] assert_equal hash["integer"], parsed["integer"] assert_equal hash["string"], parsed["string"] assert_equal hash["table"], parsed["table"] assert_equal hash["products"], parsed["products"] assert_equal hash["fruit"], parsed["fruit"] end def test_file_v_0_5_0 path = File.join(File.dirname(__FILE__), "example-v0.5.0.toml") parsed = TomlRB.load_file(path) hash = TomlRB::Examples.example_v_0_5_0 assert_equal hash["keys"], parsed["keys"] assert_equal hash["string"], parsed["string"] assert_equal hash["integer"], parsed["integer"] assert_equal hash["float"], parsed["float"] assert_equal hash["boolean"], parsed["boolean"] assert_equal hash["offset-date-time"], parsed["offset-date-time"] assert_equal hash["local-date-time"], parsed["local-date-time"] assert_equal hash["local-date"], parsed["local-date"] assert_equal hash["local-time"], parsed["local-time"] assert_equal hash["array"], parsed["array"] assert_equal hash["table"], parsed["table"] assert_equal hash["inline-table"], parsed["inline-table"] assert_equal hash["array-of-tables"], parsed["array-of-tables"] end def test_file path = File.join(File.dirname(__FILE__), "example.toml") parsed = TomlRB.load_file(path) assert_equal TomlRB::Examples.example, parsed end def test_hard_example path = File.join(File.dirname(__FILE__), "hard_example.toml") parsed = TomlRB.load_file(path) assert_equal TomlRB::Examples.hard_example, parsed end def test_symbolize_keys path = File.join(File.dirname(__FILE__), "example.toml") parsed = TomlRB.load_file(path, symbolize_keys: true) hash = { title: "TomlRB Example", owner: { name: "Tom Preston-Werner", organization: "GitHub", bio: "GitHub Cofounder & CEO\nLikes tater tots and beer.", dob: Time.utc(1979, 0o5, 27, 0o7, 32, 0o0) }, database: { server: "192.168.1.1", ports: [8001, 8001, 8002], connection_max: 5000, enabled: true }, servers: { alpha: { ip: "10.0.0.1", dc: "eqdc10" }, beta: { ip: "10.0.0.2", dc: "eqdc10" } }, clients: { data: [%w[gamma delta], [1, 2]], hosts: %w[alpha omega] }, amqp: { exchange: { durable: true, auto_delete: false } }, products: [ {name: "Hammer", sku: 738_594_937}, {}, {name: "Nail", sku: 284_758_393, color: "gray"} ] } assert_equal(hash, parsed) end def test_line_break parsed = TomlRB.parse("hello = 'world'\r\nline_break = true") assert_equal({"hello" => "world", "line_break" => true}, parsed) end def test_trailing_whitespace_after_keyvalue parsed = TomlRB.parse("a = 1 ") assert_equal({"a" => 1}, parsed) end def test_trailing_whitespace_after_line_break parsed = TomlRB.parse("[table]\r\na = 1\r\n ") assert_equal({"table" => {"a" => 1}}, parsed) end def compare_toml_files(folder, file = nil, &block) file ||= "*" Dir["test/examples/#{folder}/#{file}.json"].each do |json_file| toml_file = File.join(File.dirname(json_file), File.basename(json_file, ".json")) + ".toml" begin toml = TomlRB.load_file(toml_file) rescue TomlRB::Error => e assert false, "Error: #{e} in #{toml_file}" end json = JSON.parse(File.read(json_file)) block.call(json, toml, toml_file) end end def test_valid_cases compare_toml_files "valid" do |json, toml, file| assert_equal json, toml, "In file '#{file}'" end end def test_invalid_cases file = "*" Dir["test/examples/invalid/#{file}.toml"].each do |toml_file| assert_raises(TomlRB::Error, "For file #{toml_file}") do TomlRB.load_file(toml_file) end end end end toml-rb-2.1.0/toml-rb.gemspec000066400000000000000000000015501413774102700160160ustar00rootroot00000000000000# frozen_string_literal: true lib = File.expand_path("lib", __dir__) $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) require "toml-rb/version" Gem::Specification.new do |s| s.name = "toml-rb" s.version = TomlRB::VERSION s.summary = "Toml parser in ruby, for ruby." s.description = "A Toml parser using Citrus parsing library. " s.authors = ["Emiliano Mancuso", "Lucas Tolchinsky"] s.email = ["emiliano.mancuso@gmail.com", "lucas.tolchinsky@gmail.com"] s.homepage = "https://github.com/emancu/toml-rb" s.license = "MIT" s.files = Dir[ "README.md", "lib/**/*.rb", "lib/**/*.citrus", "LICENSE" ] s.required_ruby_version = ">= 2.3" s.add_dependency "citrus", "~> 3.0", "> 3.0" s.add_development_dependency "minitest", "~> 5.7" s.add_development_dependency "standard", "~> 1.4" s.add_development_dependency "rake" end