kvn 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 487ee8d85ce8eac0225f08b86d21dd815aff1f09
4
- data.tar.gz: 3eb23b598b95eab8155d6a3aaabfb8a1f16766c5
3
+ metadata.gz: 832c9ff0fe7496bfe3c6f5a93cc7b959e8889cb2
4
+ data.tar.gz: 05dd1ba7428b883dc2fe7669ae70fa180f14c383
5
5
  SHA512:
6
- metadata.gz: 87ed111e0c4a50bcce9a9220e76c42b94ca1146ffed4d956914d26342ee041efb037e7050e9195fad1776cec93b191137174cd493451852ec656a378aedc80eb
7
- data.tar.gz: 88e51aa82458c196d912d80c4f705d3403cb3991e0b75e50948ea2d6a6375ce7b6a1037d0bb8e77378d9debfab4214f25c5416401aeab06221b5e3af82479257
6
+ metadata.gz: 2ec2564e05c43f19bd5897d58cf7bda7392817ce7bcb738e44abec846deccc332893d292565b9855605385462383d7309164ee52729f3060ccd7808cdfbbf28c
7
+ data.tar.gz: 2f00b76e616acf6177ca67558004c89545fb9adb0a616fac958f3eabc9c28db556ac626cb36bc563bc02f12fb0d37dffa6ec2d5d7f09c4fcdd7e3b176fd9a761
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- kvn (0.1.0)
4
+ kvn (0.2.0)
5
5
  lex (= 0.1.0)
6
6
 
7
7
  GEM
@@ -11,25 +11,18 @@ GEM
11
11
  debug_inspector (>= 0.0.1)
12
12
  byebug (8.2.2)
13
13
  coderay (1.1.1)
14
- coveralls (0.8.10)
14
+ coveralls (0.8.13)
15
15
  json (~> 1.8)
16
- rest-client (>= 1.6.8, < 2)
17
16
  simplecov (~> 0.11.0)
18
17
  term-ansicolor (~> 1.3)
19
18
  thor (~> 0.19.1)
20
19
  tins (~> 1.6.0)
21
20
  debug_inspector (0.0.2)
22
21
  docile (1.1.5)
23
- domain_name (0.5.20160128)
24
- unf (>= 0.0.5, < 1.0.0)
25
- http-cookie (1.0.2)
26
- domain_name (~> 0.5)
27
22
  interception (0.5)
28
23
  json (1.8.3)
29
24
  lex (0.1.0)
30
25
  method_source (0.8.2)
31
- mime-types (2.99.1)
32
- netrc (0.11.0)
33
26
  os (0.9.6)
34
27
  pry (0.10.3)
35
28
  coderay (~> 1.1.0)
@@ -51,10 +44,6 @@ GEM
51
44
  pry-rescue
52
45
  pry-stack_explorer
53
46
  rake (10.5.0)
54
- rest-client (1.8.0)
55
- http-cookie (>= 1.0.2, < 2.0)
56
- mime-types (>= 1.16, < 3.0)
57
- netrc (~> 0.7)
58
47
  simplecov (0.11.2)
59
48
  docile (~> 1.1.0)
60
49
  json (~> 1.8)
@@ -65,9 +54,6 @@ GEM
65
54
  tins (~> 1.0)
66
55
  thor (0.19.1)
67
56
  tins (1.6.0)
68
- unf (0.1.4)
69
- unf_ext
70
- unf_ext (0.0.7.2)
71
57
 
72
58
  PLATFORMS
73
59
  ruby
data/README.md CHANGED
@@ -1,4 +1,47 @@
1
+ [![Lines of Code](http://img.shields.io/badge/lines_of_code-145-brightgreen.svg?style=flat)](http://blog.codinghorror.com/the-best-code-is-no-code-at-all/)
2
+ [![Code Status](http://img.shields.io/codeclimate/github/hopsoft/kvn.svg?style=flat)](https://codeclimate.com/github/hopsoft/kvn)
3
+ [![Dependency Status](http://img.shields.io/gemnasium/hopsoft/kvn.svg?style=flat)](https://gemnasium.com/hopsoft/kvn)
4
+ [![Build Status](http://img.shields.io/travis/hopsoft/kvn.svg?style=flat)](https://travis-ci.org/hopsoft/kvn)
5
+ [![Coverage Status](https://img.shields.io/coveralls/hopsoft/kvn.svg?style=flat)](https://coveralls.io/r/hopsoft/kvn?branch=master)
6
+ [![Downloads](http://img.shields.io/gem/dt/kvn.svg?style=flat)](http://rubygems.org/gems/kvn)
7
+
1
8
  # KVN (kevin)
2
9
 
3
- A [KVN](https://github.com/hopsoft/bighorn#kvn) parser.
10
+ ## Key/Value Notation
11
+
12
+ Similar to JSON but more limited in scope.
13
+ Can be used to represent basic key/value data structures as (human readable) strings.
14
+
15
+ Useful when working with limited storage options
16
+ to capture additional (human readable) data in a single field.
17
+
18
+ ## Rules
19
+
20
+ * Data structures should be flat (i.e. 1 level deep, no nesting)
21
+ * Keys & values are limited to primitive types
22
+
23
+ * String
24
+ * Numeric
25
+ * Boolean
26
+ * Null
27
+
28
+ * Colons & semicolons are prohibited in keys & values
29
+ * Keys are sorted alphabetically
30
+
31
+ ## Examples
32
+
33
+ ### Convert a Hash to a KVN string
34
+
35
+ ```ruby
36
+ data = { d: "example with whitespace", a: true, c: "example", b: 1, e: nil }
37
+ Kvn::Converter.new(data).convert
38
+ # => "a:true; b:1; c:example; d:example with whitespace; e:null;"
39
+ ```
40
+
41
+ ### Parse a KVN string into a Hash
4
42
 
43
+ ```ruby
44
+ value = "a:true; b:1; c:example; d:example with whitespace; e:null;"
45
+ Kvn::Parser.new(value).parse
46
+ # => {"a"=>true, "b"=>1, "c"=>"example", "d"=>"example with whitespace", "e"=>nil}
47
+ ```
data/lib/kvn.rb CHANGED
@@ -1,34 +1,21 @@
1
1
  require "kvn/version"
2
- require "kvn/illegal_character_error"
2
+ require "kvn/unsupported_hash_error"
3
+ require "kvn/value_lexer"
3
4
  require "kvn/lexer"
5
+ require "kvn/converter"
4
6
  require "kvn/parser"
5
7
 
6
8
  module Kvn
7
- class << self
8
-
9
- def parse(value)
10
- raise ArgumentError.new("Value is not a valid KVN string!") unless valid?(value)
11
- pairs = standardize(value).split(";")
12
- pairs.each_with_object({}) do |pair, memo|
13
- parts = pair.split(":")
14
- memo[parts.first] = parts.last
15
- end
16
- end
17
-
18
- def valid?(value)
19
- value = standardize(value)
20
- semicolon_count = value.scan(";").size
21
- colon_count = value.scan(":").size
22
- return false unless semicolon_count > 0
23
- return false unless colon_count > 0
24
- return false unless semicolon_count == colon_count
25
- end
26
-
27
- private
28
-
29
- def standardize(value)
30
- value.to_s.strip
31
- end
32
-
33
- end
9
+ SUPPORTED_VALUE_TYPES = [
10
+ NilClass,
11
+ TrueClass,
12
+ FalseClass,
13
+ Symbol,
14
+ String,
15
+ Integer,
16
+ Fixnum,
17
+ Bignum,
18
+ Float,
19
+ Rational
20
+ ]
34
21
  end
@@ -0,0 +1,38 @@
1
+ module Kvn
2
+ class Converter
3
+ attr_reader :value
4
+
5
+ def initialize(value)
6
+ @value = (value ||= {}).to_h rescue {}
7
+
8
+ if invalid_values_present?
9
+ message = "All values must be a supported type! #{Kvn::SUPPORTED_VALUE_TYPES.join ", "}"
10
+ raise Kvn::UnsupportedHashError.new(message)
11
+ end
12
+ end
13
+
14
+ def convert
15
+ value.keys.sort.each_with_object([]) do |key, memo|
16
+ v = value[key]
17
+ v = "null" if v.nil?
18
+ next if v.to_s.strip.empty?
19
+ memo << "#{key}:#{v};"
20
+ end.join(" ")
21
+ end
22
+
23
+ private
24
+
25
+ def standardize_value(value)
26
+ value.to_s.strip
27
+ end
28
+
29
+ def value_types
30
+ value.values.map(&:class).uniq
31
+ end
32
+
33
+ def invalid_values_present?
34
+ !(value_types - Kvn::SUPPORTED_VALUE_TYPES).empty?
35
+ end
36
+
37
+ end
38
+ end
@@ -9,14 +9,14 @@ module Kvn
9
9
  :PARTDELIM
10
10
  )
11
11
 
12
- rule :KEY, /(\w|\s)+(?=:)/
13
- rule :VALUE, /(\w|\s)+(?=;)/
12
+ rule :KEY, /\w+(?=:)/
13
+ rule :VALUE, /[\w+(\s|\.)]+(?=;)/
14
14
  rule :PAIRDELIM, /;\s*/
15
15
  rule :PARTDELIM, /:/
16
16
 
17
17
  error do |lexer, token|
18
- message = "Illegal character in KVN string! #{token.line}:#{token.column} #{token.value}"
19
- raise Kvn::IllegalCharacterError.new(message)
18
+ message = "Illegal character in KVN string! #{token.line}:#{token.column} <#{token.value}>"
19
+ raise SyntaxError.new(message)
20
20
  end
21
21
  end
22
22
  end
@@ -1,28 +1,56 @@
1
1
  module Kvn
2
2
  class Parser
3
+ attr_reader :value
3
4
 
4
- def parse(value)
5
- parsed = {}
5
+ def initialize(value)
6
+ @value = value.to_s.strip
7
+ end
8
+
9
+ def parse
6
10
  lexer = Kvn::Lexer.new
7
- output = lexer.lex(standardize_value(value))
11
+ output = lexer.lex(value)
12
+ {}.tap do |parsed|
13
+ begin
14
+ key = nil
15
+ key_found = false
16
+ value_found = false
17
+ while output.peek
18
+ token = output.next
19
+ if token.name == :KEY
20
+ key = token.value
21
+ key_found = true
22
+ value_found = false
23
+ end
24
+
25
+ if token.name == :VALUE
26
+ raise SyntaxError.new("Empty key detected for value! <#{token.value}>") unless key_found
27
+ parsed[key] = parse_value(token.value)
28
+ value_found = true
29
+ key_found = false
30
+ end
8
31
 
9
- begin
10
- key = nil
11
- while output.peek
12
- token = output.next
13
- key = token.value if token.name == :KEY
14
- parsed[key] = token.value if token.name == :VALUE
32
+ if token.name == :PAIRDELIM && !value_found
33
+ raise SyntaxError.new("Empty value detected for key! <#{key}>")
34
+ end
35
+ end
36
+ rescue StopIteration
15
37
  end
16
- rescue StopIteration
17
38
  end
18
-
19
- parsed
20
39
  end
21
40
 
22
41
  private
23
42
 
24
- def standardize_value(value)
25
- value.to_s.strip
43
+ def parse_value(value)
44
+ lexer = Kvn::ValueLexer.new
45
+ token = lexer.lex(value).next
46
+ case token.name
47
+ when :NIL then value = nil
48
+ when :TRUE then value = true
49
+ when :FALSE then value = false
50
+ when :FLOAT then value = value.to_f
51
+ when :INTEGER then value = value.to_i
52
+ else value.to_s
53
+ end
26
54
  end
27
55
 
28
56
  end
@@ -0,0 +1,4 @@
1
+ module Kvn
2
+ class UnsupportedHashError < StandardError
3
+ end
4
+ end
@@ -0,0 +1,21 @@
1
+ require "lex"
2
+
3
+ module Kvn
4
+ class ValueLexer < Lex::Lexer
5
+ tokens(
6
+ :NIL,
7
+ :TRUE,
8
+ :FALSE,
9
+ :FLOAT,
10
+ :INTEGER,
11
+ :STRING
12
+ )
13
+
14
+ rule :NIL, /null/
15
+ rule :TRUE, /true/
16
+ rule :FALSE, /false/
17
+ rule :FLOAT, /\d+\.\d+/
18
+ rule :INTEGER, /\d+/
19
+ rule :STRING, /.*/
20
+ end
21
+ end
@@ -1,3 +1,3 @@
1
1
  module Kvn
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kvn
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nathan Hopkins
@@ -93,9 +93,11 @@ files:
93
93
  - README.md
94
94
  - Rakefile
95
95
  - lib/kvn.rb
96
- - lib/kvn/illegal_character_error.rb
96
+ - lib/kvn/converter.rb
97
97
  - lib/kvn/lexer.rb
98
98
  - lib/kvn/parser.rb
99
+ - lib/kvn/unsupported_hash_error.rb
100
+ - lib/kvn/value_lexer.rb
99
101
  - lib/kvn/version.rb
100
102
  homepage: https://github.com/hopsoft/kvn
101
103
  licenses:
@@ -120,5 +122,5 @@ rubyforge_project:
120
122
  rubygems_version: 2.5.1
121
123
  signing_key:
122
124
  specification_version: 4
123
- summary: KVN (kevin) parser
125
+ summary: KVN key/value notation converter & parser
124
126
  test_files: []
@@ -1,4 +0,0 @@
1
- module Kvn
2
- class IllegalCharacterError < StandardError
3
- end
4
- end