kdl 1.0.6 → 2.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby.yml +8 -1
  3. data/.gitignore +1 -0
  4. data/.gitmodules +4 -0
  5. data/Gemfile +6 -1
  6. data/README.md +67 -7
  7. data/Rakefile +6 -1
  8. data/bin/kdl +1 -1
  9. data/kdl.gemspec +2 -2
  10. data/lib/kdl/document.rb +60 -2
  11. data/lib/kdl/error.rb +24 -0
  12. data/lib/kdl/kdl.tab.rb +305 -231
  13. data/lib/kdl/kdl.yy +57 -49
  14. data/lib/kdl/node.rb +116 -13
  15. data/lib/kdl/parser_common.rb +28 -0
  16. data/lib/kdl/string_dumper.rb +32 -33
  17. data/lib/kdl/tokenizer.rb +387 -136
  18. data/lib/kdl/types/base64.rb +3 -1
  19. data/lib/kdl/types/country/iso3166_countries.rb +3 -1
  20. data/lib/kdl/types/country/iso3166_subdivisions.rb +3 -1
  21. data/lib/kdl/types/country.rb +4 -2
  22. data/lib/kdl/types/currency/iso4217_currencies.rb +3 -1
  23. data/lib/kdl/types/currency.rb +3 -1
  24. data/lib/kdl/types/date_time.rb +5 -3
  25. data/lib/kdl/types/decimal.rb +3 -1
  26. data/lib/kdl/types/duration/iso8601_parser.rb +3 -1
  27. data/lib/kdl/types/duration.rb +3 -1
  28. data/lib/kdl/types/email/parser.rb +10 -8
  29. data/lib/kdl/types/email.rb +3 -1
  30. data/lib/kdl/types/hostname/validator.rb +3 -1
  31. data/lib/kdl/types/hostname.rb +3 -1
  32. data/lib/kdl/types/ip.rb +3 -1
  33. data/lib/kdl/types/irl/parser.rb +10 -8
  34. data/lib/kdl/types/irl.rb +3 -1
  35. data/lib/kdl/types/regex.rb +3 -1
  36. data/lib/kdl/types/url.rb +3 -1
  37. data/lib/kdl/types/url_template.rb +6 -4
  38. data/lib/kdl/types/uuid.rb +3 -1
  39. data/lib/kdl/types.rb +2 -0
  40. data/lib/kdl/v1/document.rb +19 -0
  41. data/lib/kdl/v1/kdl.tab.rb +594 -0
  42. data/lib/kdl/v1/kdl.yy +89 -0
  43. data/lib/kdl/v1/node.rb +32 -0
  44. data/lib/kdl/v1/string_dumper.rb +30 -0
  45. data/lib/kdl/v1/tokenizer.rb +298 -0
  46. data/lib/kdl/v1/value.rb +91 -0
  47. data/lib/kdl/v1.rb +13 -0
  48. data/lib/kdl/value.rb +87 -15
  49. data/lib/kdl/version.rb +3 -1
  50. data/lib/kdl.rb +47 -1
  51. metadata +14 -7
@@ -1,8 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'base64'
2
4
 
3
5
  module KDL
4
6
  module Types
5
- class Base64 < Value
7
+ class Base64 < Value::Custom
6
8
  RGX = /^[A-Za-z0-9+\/=]+$/.freeze
7
9
 
8
10
  def self.call(value, type = 'base64')
@@ -1,6 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module KDL
2
4
  module Types
3
- class Country < Value
5
+ class Country < Value::Custom
4
6
  # From: https://en.wikipedia.org/wiki/ISO_3166-1#Current_codes
5
7
  COUNTRIES3 = {
6
8
  'AFG' => { alpha3: 'AFG', alpha2: 'AF', numeric_code: 4, name: 'Afghanistan' }.freeze,
@@ -1,6 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module KDL
2
4
  module Types
3
- class CountrySubdivision < Value
5
+ class CountrySubdivision < Value::Custom
4
6
  # From: https://en.wikipedia.org/wiki/ISO_3166-2#Current_codes
5
7
  COUNTRY_SUBDIVISIONS = {
6
8
  "AD" => {
@@ -1,9 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'kdl/types/country/iso3166_countries'
2
4
  require 'kdl/types/country/iso3166_subdivisions'
3
5
 
4
6
  module KDL
5
7
  module Types
6
- class Country < Value
8
+ class Country < Value::Custom
7
9
  attr_reader :name, :alpha2, :alpha3, :numeric_code
8
10
 
9
11
  def initialize(value, format: nil, type: 'country-3')
@@ -42,7 +44,7 @@ module KDL
42
44
  end
43
45
  MAPPING['country-2'] = Country2
44
46
 
45
- class CountrySubdivision < Value
47
+ class CountrySubdivision < Value::Custom
46
48
  attr_reader :country, :name
47
49
 
48
50
  def initialize(value, type: 'country-subdivision', country:, name:, **kwargs)
@@ -1,6 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module KDL
2
4
  module Types
3
- class Currency < Value
5
+ class Currency < Value::Custom
4
6
  # From https://en.wikipedia.org/wiki/ISO_4217#Active_codes
5
7
  CURRENCIES = {
6
8
  'AED' => { numeric_code: 784, minor_unit: 2, name: 'United Arab Emirates dirham' }.freeze,
@@ -1,8 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'kdl/types/currency/iso4217_currencies'
2
4
 
3
5
  module KDL
4
6
  module Types
5
- class Currency < Value
7
+ class Currency < Value::Custom
6
8
  attr_reader :numeric_code, :minor_unit, :name
7
9
 
8
10
  def initialize(value, format: nil, type: 'currency')
@@ -1,8 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'time'
2
4
 
3
5
  module KDL
4
6
  module Types
5
- class DateTime < Value
7
+ class DateTime < Value::Custom
6
8
  def self.call(value, type = 'date-time')
7
9
  return nil unless value.is_a? ::KDL::Value::String
8
10
 
@@ -12,7 +14,7 @@ module KDL
12
14
  end
13
15
  MAPPING['date-time'] = DateTime
14
16
 
15
- class Time < Value
17
+ class Time < Value::Custom
16
18
  # TODO: this is not a perfect ISO8601 time string
17
19
  REGEX = /^T?((?:2[0-3]|[01][0-9]):[0-5][0-9]:[0-5][0-9](?:\.[0-9]+)?(?:Z|[+-]\d\d:\d\d)?)$/
18
20
 
@@ -28,7 +30,7 @@ module KDL
28
30
  end
29
31
  MAPPING['time'] = Time
30
32
 
31
- class Date < Value
33
+ class Date < Value::Custom
32
34
  def self.call(value, type = 'date')
33
35
  return nil unless value.is_a? ::KDL::Value::String
34
36
 
@@ -1,6 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module KDL
2
4
  module Types
3
- class Decimal < Value
5
+ class Decimal < Value::Custom
4
6
  def self.call(value, type = 'decimal')
5
7
  return nil unless value.is_a? ::KDL::Value::String
6
8
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Shamelessly borrowed from https://github.com/rails/rails/tree/main/activesupport
2
4
  #
3
5
  # Copyright (c) 2005-2021 David Heinemeier Hansson
@@ -25,7 +27,7 @@ require 'strscan'
25
27
 
26
28
  module KDL
27
29
  module Types
28
- class Duration < Value
30
+ class Duration < Value::Custom
29
31
  # Parses a string formatted according to ISO 8601 Duration into the hash.
30
32
  #
31
33
  # See {ISO 8601}[https://en.wikipedia.org/wiki/ISO_8601#Durations] for more information.
@@ -1,8 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'kdl/types/duration/iso8601_parser'
2
4
 
3
5
  module KDL
4
6
  module Types
5
- class Duration < Value
7
+ class Duration < Value::Custom
6
8
  attr_reader :years, :months, :weeks, :days, :hours, :minutes, :seconds
7
9
 
8
10
  def initialize(parts = {}, format: nil, type: 'duration')
@@ -1,8 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative '../hostname/validator'
2
4
 
3
5
  module KDL
4
6
  module Types
5
- class Email < Value
7
+ class Email < Value::Custom
6
8
  class Parser
7
9
  def initialize(string, idn: false)
8
10
  @string = string
@@ -11,7 +13,7 @@ module KDL
11
13
  end
12
14
 
13
15
  def parse
14
- local = ''
16
+ local = +''
15
17
  unicode_domain = nil
16
18
  domain = nil
17
19
  context = :start
@@ -23,7 +25,7 @@ module KDL
23
25
  when :part
24
26
  case context
25
27
  when :start, :after_dot
26
- local += value
28
+ local << value
27
29
  context = :after_part
28
30
  else
29
31
  raise ArgumentError, "invalid email #{@string} (unexpected part #{value} at #{context})"
@@ -31,7 +33,7 @@ module KDL
31
33
  when :dot
32
34
  case context
33
35
  when :after_part
34
- local += value
36
+ local << value
35
37
  context = :after_dot
36
38
  else
37
39
  raise ArgumentError, "invalid email #{@string} (unexpected dot at #{context})"
@@ -91,7 +93,7 @@ module KDL
91
93
  end
92
94
  end
93
95
  @context = nil
94
- @buffer = ''
96
+ @buffer = +''
95
97
  loop do
96
98
  c = @string[@index]
97
99
  return [:end, nil] if c.nil?
@@ -111,7 +113,7 @@ module KDL
111
113
  @index += 1
112
114
  when local_part_chars
113
115
  @context = :part
114
- @buffer += c
116
+ @buffer << c
115
117
  @index += 1
116
118
  else
117
119
  raise ArgumentError, "invalid email #{@string} (unexpected #{c})"
@@ -119,7 +121,7 @@ module KDL
119
121
  when :part
120
122
  case c
121
123
  when local_part_chars
122
- @buffer += c
124
+ @buffer << c
123
125
  @index += 1
124
126
  when '.', '@'
125
127
  return [:part, @buffer]
@@ -135,7 +137,7 @@ module KDL
135
137
  @index += 1
136
138
  return [:part, @buffer]
137
139
  else
138
- @buffer += c
140
+ @buffer << c
139
141
  @index += 1
140
142
  end
141
143
  end
@@ -1,8 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative './email/parser'
2
4
 
3
5
  module KDL
4
6
  module Types
5
- class Email < Value
7
+ class Email < Value::Custom
6
8
  attr_reader :local, :domain
7
9
 
8
10
  def initialize(value, local:, domain:, **kwargs)
@@ -1,8 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'simpleidn'
2
4
 
3
5
  module KDL
4
6
  module Types
5
- class Hostname < Value
7
+ class Hostname < Value::Custom
6
8
  class Validator
7
9
  PART_RGX = /^[a-z0-9_][a-z0-9_\-]{0,62}$/i
8
10
 
@@ -1,8 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative './hostname/validator'
2
4
 
3
5
  module KDL
4
6
  module Types
5
- class Hostname < Value
7
+ class Hostname < Value::Custom
6
8
  def self.call(value, type = 'hostname')
7
9
  return nil unless value.is_a? ::KDL::Value::String
8
10
 
data/lib/kdl/types/ip.rb CHANGED
@@ -1,6 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module KDL
2
4
  module Types
3
- class IP < Value
5
+ class IP < Value::Custom
4
6
  def self.call(value, type = ip_type)
5
7
  return nil unless value.is_a? ::KDL::Value::String
6
8
 
@@ -1,6 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module KDL
2
4
  module Types
3
- class IRLReference < Value
5
+ class IRLReference < Value::Custom
4
6
  class Parser
5
7
  RGX = /^(?:(?:([a-z][a-z0-9+.\-]+)):\/\/([^@]+@)?([^\/?#]+)?)?(\/?[^?#]*)?(?:\?([^#]*))?(?:#(.*))?$/i.freeze
6
8
  PERCENT_RGX = /%[a-f0-9]{2}/i.freeze
@@ -96,13 +98,13 @@ module KDL
96
98
  end
97
99
 
98
100
  def self.build_uri_string(scheme, auth, domain, path, search, hash)
99
- string = ''
100
- string += "#{scheme}://" if scheme
101
- string += auth if auth
102
- string += domain if domain
103
- string += path if path
104
- string += "?#{search}" if search
105
- string += "##{hash}" if hash
101
+ string = +''
102
+ string << "#{scheme}://" if scheme
103
+ string << auth if auth
104
+ string << domain if domain
105
+ string << path if path
106
+ string << "?#{search}" if search
107
+ string << "##{hash}" if hash
106
108
  string
107
109
  end
108
110
  end
data/lib/kdl/types/irl.rb CHANGED
@@ -1,8 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative './irl/parser'
2
4
 
3
5
  module KDL
4
6
  module Types
5
- class IRLReference < Value
7
+ class IRLReference < Value::Custom
6
8
  attr_reader :unicode_value,
7
9
  :unicode_domain,
8
10
  :unicode_path,
@@ -1,6 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module KDL
2
4
  module Types
3
- class Regex < Value
5
+ class Regex < Value::Custom
4
6
  def self.call(value, type = 'regex')
5
7
  return nil unless value.is_a? ::KDL::Value::String
6
8
 
data/lib/kdl/types/url.rb CHANGED
@@ -1,6 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module KDL
2
4
  module Types
3
- class URLReference < Value
5
+ class URLReference < Value::Custom
4
6
  def self.call(value, type = 'url-reference')
5
7
  return nil unless value.is_a? ::KDL::Value::String
6
8
 
@@ -1,8 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'uri'
2
4
 
3
5
  module KDL
4
6
  module Types
5
- class URLTemplate < Value
7
+ class URLTemplate < Value::Custom
6
8
  UNRESERVED = /[a-zA-Z0-9\-._~]/.freeze
7
9
  RESERVED = %r{[:/?#\[\]@!$&'()*+,;=]}.freeze
8
10
 
@@ -39,7 +41,7 @@ module KDL
39
41
  end
40
42
 
41
43
  def next_token
42
- buffer = ''
44
+ buffer = +''
43
45
  context = nil
44
46
  expansion_type = nil
45
47
  loop do
@@ -49,7 +51,7 @@ module KDL
49
51
  case c
50
52
  when '{'
51
53
  context = :expansion
52
- buffer = ''
54
+ buffer = +''
53
55
  n = @string[@index + 1]
54
56
  expansion_type = case n
55
57
  when '+' then ReservedExpansion
@@ -64,7 +66,7 @@ module KDL
64
66
  @index += (expansion_type == StringExpansion ? 1 : 2)
65
67
  when nil then return nil
66
68
  else
67
- buffer = c
69
+ buffer = +c
68
70
  @index += 1
69
71
  context = :literal
70
72
  end
@@ -1,6 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module KDL
2
4
  module Types
3
- class UUID < Value
5
+ class UUID < Value::Custom
4
6
  RGX = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/
5
7
 
6
8
  def self.call(value, type = 'uuid')
data/lib/kdl/types.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module KDL
2
4
  module Types
3
5
  MAPPING = {}
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module KDL
4
+ module V1
5
+ class Document < ::KDL::Document
6
+ def version
7
+ 1
8
+ end
9
+
10
+ def to_v1
11
+ self
12
+ end
13
+
14
+ def to_v2
15
+ ::KDL::Document.new(nodes.map(&:to_v2))
16
+ end
17
+ end
18
+ end
19
+ end