rison 1.2.1 → 2.0.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.
- data/{COPYING.txt → License.txt} +2 -2
- data/README.md +40 -0
- data/Rakefile.rb +3 -79
- data/lib/rison/dump.rb +20 -29
- data/lib/rison/parslet_parser.rb +55 -0
- data/lib/rison/parslet_transform.rb +44 -0
- data/lib/rison.rb +8 -41
- data/rison.gemspec +13 -0
- data/spec/rison_dump_spec.rb +78 -0
- data/spec/rison_load_spec.rb +93 -0
- metadata +53 -53
- data/README.html +0 -57
- data/lib/rison/evaluator.rb +0 -172
- data/lib/rison/grammar.rb +0 -114
- data/lib/rison/lexer.rb +0 -33
- data/lib/rison/parser.rb +0 -360
- data/test/test_dump.rb +0 -70
- data/test/test_parser.rb +0 -106
data/{COPYING.txt → License.txt}
RENAMED
@@ -1,4 +1,4 @@
|
|
1
|
-
Copyright
|
1
|
+
Copyright the authors and contributors. All rights reserved.
|
2
2
|
|
3
3
|
Permission is hereby granted, free of charge, to any person
|
4
4
|
obtaining a copy of this software and associated documentation
|
@@ -19,4 +19,4 @@ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
19
19
|
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
20
20
|
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
21
21
|
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
22
|
-
OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
rison
|
2
|
+
=====
|
3
|
+
|
4
|
+
|
5
|
+
A Ruby implementation of [Rison - Compact Data in URIs](http://mjtemplate.org/examples/rison.html).
|
6
|
+
|
7
|
+
|
8
|
+
Installation
|
9
|
+
------------
|
10
|
+
|
11
|
+
```
|
12
|
+
$ gem install rison
|
13
|
+
```
|
14
|
+
|
15
|
+
|
16
|
+
Usage
|
17
|
+
-----
|
18
|
+
|
19
|
+
Use `Rison.dump` to encode Ruby objects as Rison, and `Rison.load` to decode
|
20
|
+
Rison encoded strings into Ruby objects:
|
21
|
+
|
22
|
+
```ruby
|
23
|
+
require 'rison'
|
24
|
+
|
25
|
+
Rison.dump(true) # => '!t'
|
26
|
+
|
27
|
+
Rison.dump([1, 2, 3]) # => '!(1,2,3)'
|
28
|
+
|
29
|
+
Rison.dump({:a => 0}) # => '(a:0)'
|
30
|
+
|
31
|
+
Rison.dump(Array) # => Rison::DumpError
|
32
|
+
|
33
|
+
Rison.load('!t') # => true
|
34
|
+
|
35
|
+
Rison.load('!(1,2,3)') # => [1, 2, 3]
|
36
|
+
|
37
|
+
Rison.load('(a:0)') # => {:a => 0}
|
38
|
+
|
39
|
+
Rison.load('abc def') # => Rison::ParseError
|
40
|
+
```
|
data/Rakefile.rb
CHANGED
@@ -1,83 +1,7 @@
|
|
1
|
-
require 'rake'
|
2
1
|
require 'rake/testtask'
|
3
|
-
require 'rake/gempackagetask'
|
4
2
|
|
3
|
+
task :default => :spec
|
5
4
|
|
6
|
-
|
7
|
-
|
8
|
-
s.version = '1.2.1'
|
9
|
-
s.platform = Gem::Platform::RUBY
|
10
|
-
s.has_rdoc = false
|
11
|
-
s.summary = 'Pure Ruby parser for Rison (http://mjtemplate.org/examples/rison.html)'
|
12
|
-
s.description = s.summary
|
13
|
-
s.author = 'Tim Fletcher'
|
14
|
-
s.email = 'twoggle@gmail.com'
|
15
|
-
s.homepage = 'http://rison.rubyforge.org/'
|
16
|
-
s.files = Dir.glob('{lib,test}/**/*') + %w( COPYING.txt Rakefile.rb README.html )
|
17
|
-
s.require_paths = ['lib']
|
18
|
-
s.add_dependency 'dhaka'
|
19
|
-
end
|
20
|
-
|
21
|
-
|
22
|
-
Rake::GemPackageTask.new(GEMSPEC) { }
|
23
|
-
|
24
|
-
|
25
|
-
Rake::PackageTask.new(GEMSPEC.name, GEMSPEC.version) do |p|
|
26
|
-
p.need_tar_gz = true
|
27
|
-
p.package_files.include GEMSPEC.files
|
28
|
-
end
|
29
|
-
|
30
|
-
|
31
|
-
desc 'Run all the tests'
|
32
|
-
Rake::TestTask.new do |t|
|
33
|
-
t.verbose = true
|
34
|
-
t.ruby_opts = ['-rubygems']
|
35
|
-
end
|
36
|
-
|
37
|
-
|
38
|
-
namespace :stdin do
|
39
|
-
$:.unshift 'lib'
|
40
|
-
require 'rison'
|
41
|
-
require 'pp'
|
42
|
-
|
43
|
-
task :lex do
|
44
|
-
pp Rison.lex($stdin.read.chomp).to_a
|
45
|
-
end
|
46
|
-
task :parse do
|
47
|
-
parsed = Rison.parse(Rison.lex($stdin.read.chomp))
|
48
|
-
|
49
|
-
if parsed.has_error?
|
50
|
-
p parsed
|
51
|
-
else
|
52
|
-
pp Rison.load(parsed)
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
|
58
|
-
task :reinstall do
|
59
|
-
sh 'sudo gem uninstall rison dhaka'
|
60
|
-
sh 'sudo gem install pkg/rison-%s.gem' % GEMSPEC.version
|
61
|
-
end
|
62
|
-
|
63
|
-
|
64
|
-
desc 'Regenerate the compiled parser'
|
65
|
-
task :regen do
|
66
|
-
$:.unshift 'lib'
|
67
|
-
|
68
|
-
require 'rison/grammar'
|
69
|
-
require 'dhaka'
|
70
|
-
|
71
|
-
parser = Dhaka::Parser.new(Rison::Grammar)
|
72
|
-
|
73
|
-
source = [
|
74
|
-
"require 'dhaka'",
|
75
|
-
"require 'rison/grammar'",
|
76
|
-
'',
|
77
|
-
'module Rison',
|
78
|
-
parser.compile_to_ruby_source_as(:Parser).gsub(/^/, ' '),
|
79
|
-
'end'
|
80
|
-
]
|
81
|
-
|
82
|
-
File.open('lib/rison/parser.rb', 'w+') { |f| f.puts source * "\n" }
|
5
|
+
Rake::TestTask.new(:spec) do |t|
|
6
|
+
t.test_files = FileList['spec/*_spec.rb']
|
83
7
|
end
|
data/lib/rison/dump.rb
CHANGED
@@ -1,49 +1,40 @@
|
|
1
1
|
require 'rational'
|
2
2
|
|
3
3
|
module Rison
|
4
|
+
NIL = '!n'.freeze
|
5
|
+
|
6
|
+
TRUE = '!t'.freeze
|
7
|
+
|
8
|
+
FALSE = '!f'.freeze
|
9
|
+
|
10
|
+
class DumpError < StandardError; end
|
11
|
+
|
4
12
|
def self.dump(object)
|
5
13
|
case object
|
6
|
-
when NilClass then
|
14
|
+
when NilClass then NIL
|
15
|
+
|
16
|
+
when TrueClass then TRUE
|
7
17
|
|
8
|
-
when
|
18
|
+
when FalseClass then FALSE
|
9
19
|
|
10
|
-
when
|
11
|
-
|
12
|
-
when Symbol then dump(object.to_s)
|
20
|
+
when Symbol then object.to_s
|
13
21
|
|
14
22
|
when Rational then object.to_f.to_s
|
15
|
-
|
23
|
+
|
16
24
|
when Numeric then object.to_s
|
17
25
|
|
18
|
-
when String
|
19
|
-
if object.empty?
|
20
|
-
"''"
|
21
|
-
elsif id?(object)
|
22
|
-
object
|
23
|
-
else
|
24
|
-
quote(object)
|
25
|
-
end
|
26
|
+
when String then "'#{escape(object)}'"
|
26
27
|
|
27
|
-
when Hash
|
28
|
-
'(%s)' % (object.sort_by { |k, v| k.to_s }.map { |(k, v)| '%s:%s' % [ dump(k), dump(v) ] } * ',')
|
28
|
+
when Hash then '(%s)' % object.map { |(k, v)| "#{dump(k)}:#{dump(v)}" }.join(?,)
|
29
29
|
|
30
|
-
when Array
|
31
|
-
'!(%s)' % (object.map { |x| dump(x) } * ',')
|
30
|
+
when Array then '!(%s)' % object.map { |member| dump(member) }.join(?,)
|
32
31
|
|
33
32
|
else
|
34
|
-
raise
|
33
|
+
raise DumpError, "Cannot encode #{object.class} objects"
|
35
34
|
end
|
36
35
|
end
|
37
36
|
|
38
|
-
def self.quote(string)
|
39
|
-
"'%s'" % escape(string)
|
40
|
-
end
|
41
|
-
|
42
37
|
def self.escape(string)
|
43
|
-
string.gsub('!', '!!').gsub("'", "!'")
|
44
|
-
end
|
45
|
-
|
46
|
-
def self.id?(string)
|
47
|
-
string !~ /^(-|\d)/ && string !~ /['!:(),*@$ ]/
|
38
|
+
string.gsub('!', '!!').gsub("'", "!'")
|
48
39
|
end
|
49
|
-
end
|
40
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'parslet'
|
2
|
+
|
3
|
+
module Rison
|
4
|
+
class ParsletParser < Parslet::Parser
|
5
|
+
root(:value)
|
6
|
+
|
7
|
+
rule(:value) { t | f | n | number | string | id | object | array }
|
8
|
+
|
9
|
+
rule(:object) { str(?() >> members >> str(?)) | str('()').as(:empty_object) }
|
10
|
+
|
11
|
+
rule(:array) { str('!(') >> elements >> str(?)) | str('!()').as(:empty_array) }
|
12
|
+
|
13
|
+
rule(:string) { str(?') >> strchars.repeat.as(:string) >> str(?') }
|
14
|
+
|
15
|
+
rule(:number) { int >> exp | int >> frac >> exp | int >> frac | int }
|
16
|
+
|
17
|
+
rule(:elements) { value.as(:array_value) >> str(?,) >> elements.as(:array_elements) | value.as(:array_value) }
|
18
|
+
|
19
|
+
rule(:members) { pair.as(:object_pair) >> str(?,) >> members.as(:object_members) | pair }
|
20
|
+
|
21
|
+
rule(:pair) { key.as(:key) >> str(?:) >> value.as(:value) }
|
22
|
+
|
23
|
+
rule(:key) { id | string }
|
24
|
+
|
25
|
+
rule(:id) { (idstart >> idchars | idstart).as(:identifier) }
|
26
|
+
|
27
|
+
rule(:idchars) { idchar.repeat(1) }
|
28
|
+
|
29
|
+
rule(:idchar) { match(/[a-zA-Z_\.\/~\-0-9]/) } # TODO: any non-ASCII Unicode character
|
30
|
+
|
31
|
+
rule(:idstart) { match(/[a-zA-Z_\.\/~]/) }
|
32
|
+
|
33
|
+
rule(:int) { (str('-').maybe >> (non_zero_digit >> digits | digit)).as(:int) }
|
34
|
+
|
35
|
+
rule(:frac) { str(?.) >> digits.as(:frac) }
|
36
|
+
|
37
|
+
rule(:exp) { str(?e) >> (str(?-).maybe >> digits).as(:exp) }
|
38
|
+
|
39
|
+
rule(:strchars) { strchar.repeat(1) }
|
40
|
+
|
41
|
+
rule(:strchar) { str(?!) >> str(?').as(:chr) | str(?!) >> str(?!).as(:chr) | match('[^\'\!]').as(:chr) }
|
42
|
+
|
43
|
+
rule(:non_zero_digit) { match('[1-9]') }
|
44
|
+
|
45
|
+
rule(:digits) { digit.repeat(1) }
|
46
|
+
|
47
|
+
rule(:digit) { match('[0-9]') }
|
48
|
+
|
49
|
+
rule(:t) { str('!t').as(:tfn) }
|
50
|
+
|
51
|
+
rule(:f) { str('!f').as(:tfn) }
|
52
|
+
|
53
|
+
rule(:n) { str('!n').as(:tfn) }
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'parslet'
|
2
|
+
require 'rational'
|
3
|
+
|
4
|
+
module Rison
|
5
|
+
class ParsletTransform < Parslet::Transform
|
6
|
+
rule(tfn: '!t') { true }
|
7
|
+
|
8
|
+
rule(tfn: '!f') { false }
|
9
|
+
|
10
|
+
rule(tfn: '!n') { nil }
|
11
|
+
|
12
|
+
rule(int: simple(:value)) { value.to_i }
|
13
|
+
|
14
|
+
rule(int: simple(:int), exp: simple(:exp)) { Rison::Number(int, nil, exp) }
|
15
|
+
|
16
|
+
rule(int: simple(:int), frac: simple(:frac)) { Rison::Number(int, frac) }
|
17
|
+
|
18
|
+
rule(int: simple(:int), frac: simple(:frac), exp: simple(:exp)) { Rison::Number(int, frac, exp) }
|
19
|
+
|
20
|
+
rule(identifier: simple(:value)) { value.to_s.to_sym }
|
21
|
+
|
22
|
+
rule(chr: simple(:chr)) { chr.to_s }
|
23
|
+
|
24
|
+
rule(string: subtree(:characters)) { characters.join }
|
25
|
+
|
26
|
+
rule(key: subtree(:k), value: subtree(:v)) { {k => v} }
|
27
|
+
|
28
|
+
rule(empty_object: '()') { Hash.new }
|
29
|
+
|
30
|
+
rule(object_pair: subtree(:pair), object_members: subtree(:members)) { pair.merge(members) }
|
31
|
+
|
32
|
+
rule(empty_array: '!()') { [] }
|
33
|
+
|
34
|
+
rule(array_value: subtree(:h)) { [h] }
|
35
|
+
|
36
|
+
rule(array_value: subtree(:h), array_elements: subtree(:t)) { [h] + t }
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.Number(int, frac = nil, exp = nil)
|
40
|
+
base = frac ? int.to_i + Rational(frac.to_i, 10 ** frac.to_s.length) : int.to_i
|
41
|
+
|
42
|
+
exp ? base * 10 ** exp.to_i : base
|
43
|
+
end
|
44
|
+
end
|
data/lib/rison.rb
CHANGED
@@ -1,46 +1,13 @@
|
|
1
|
-
require '
|
2
|
-
require 'rison/
|
3
|
-
require 'rison/parser'
|
4
|
-
require 'rison/evaluator'
|
1
|
+
require 'rison/parslet_parser'
|
2
|
+
require 'rison/parslet_transform'
|
5
3
|
require 'rison/dump'
|
6
4
|
|
7
5
|
module Rison
|
6
|
+
class ParseError < StandardError; end
|
8
7
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
@result = result
|
14
|
-
|
15
|
-
super "invalid Rison string: %p" % invalid_string
|
16
|
-
end
|
8
|
+
def self.load(string)
|
9
|
+
ParsletTransform.new.apply(ParsletParser.new.parse(string))
|
10
|
+
rescue Parslet::ParseFailed => exception
|
11
|
+
raise ParseError, "Invalid Rison input. #{exception.message}"
|
17
12
|
end
|
18
|
-
|
19
|
-
def self.load(data)
|
20
|
-
lexed = lex(data)
|
21
|
-
|
22
|
-
parsed = parse(lexed)
|
23
|
-
|
24
|
-
raise ParseError.new(data, parsed) if parsed.has_error?
|
25
|
-
|
26
|
-
evaluate(parsed)
|
27
|
-
end
|
28
|
-
|
29
|
-
|
30
|
-
LEXER = Dhaka::Lexer.new(LexerSpec)
|
31
|
-
|
32
|
-
EVALUATOR = Evaluator.new
|
33
|
-
|
34
|
-
def self.lex(data)
|
35
|
-
LEXER.lex(data.to_s)
|
36
|
-
end
|
37
|
-
|
38
|
-
def self.parse(lexed)
|
39
|
-
Parser.parse(lexed)
|
40
|
-
end
|
41
|
-
|
42
|
-
def self.evaluate(parsed)
|
43
|
-
EVALUATOR.evaluate(parsed)
|
44
|
-
end
|
45
|
-
|
46
|
-
end
|
13
|
+
end
|
data/rison.gemspec
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = 'rison'
|
3
|
+
s.version = '2.0.0'
|
4
|
+
s.platform = Gem::Platform::RUBY
|
5
|
+
s.authors = ['Tim Fletcher']
|
6
|
+
s.email = ['mail@tfletcher.com']
|
7
|
+
s.homepage = 'http://github.com/tim/ruby-rison'
|
8
|
+
s.description = 'A Ruby implementation of Rison (http://mjtemplate.org/examples/rison.html)'
|
9
|
+
s.summary = 'See description'
|
10
|
+
s.files = Dir.glob('{lib,spec}/**/*') + %w(README.md Rakefile.rb rison.gemspec License.txt)
|
11
|
+
s.add_dependency('parslet', ['~> 1.4.0'])
|
12
|
+
s.require_path = 'lib'
|
13
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
|
3
|
+
$:.unshift 'lib'
|
4
|
+
|
5
|
+
require 'rison'
|
6
|
+
|
7
|
+
describe 'Rison dump method' do
|
8
|
+
it 'encodes true' do
|
9
|
+
Rison.dump(true).must_equal('!t')
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'encodes false' do
|
13
|
+
Rison.dump(false).must_equal('!f')
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'encodes nil' do
|
17
|
+
Rison.dump(nil).must_equal('!n')
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'encodes zero' do
|
21
|
+
Rison.dump(0).must_equal('0')
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'encodes positive integers' do
|
25
|
+
Rison.dump(1).must_equal('1')
|
26
|
+
Rison.dump(42).must_equal('42')
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'encodes negative integers' do
|
30
|
+
Rison.dump(-3).must_equal('-3')
|
31
|
+
Rison.dump(-33).must_equal('-33')
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'encodes rationals as fractional numbers' do
|
35
|
+
Rison.dump(Rational(3, 2)).must_equal('1.5')
|
36
|
+
Rison.dump(Rational(9999, 100)).must_equal('99.99')
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'encodes symbols as ids' do
|
40
|
+
Rison.dump(:a).must_equal('a')
|
41
|
+
Rison.dump(:'a-z').must_equal('a-z')
|
42
|
+
Rison.dump(:'domain.com').must_equal('domain.com')
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'encodes strings' do
|
46
|
+
Rison.dump('').must_equal(%(''))
|
47
|
+
Rison.dump('0a').must_equal(%('0a'))
|
48
|
+
Rison.dump('-h').must_equal(%('-h'))
|
49
|
+
Rison.dump('abc def').must_equal(%('abc def'))
|
50
|
+
Rison.dump('user@domain.com').must_equal(%('user@domain.com'))
|
51
|
+
Rison.dump('US $10').must_equal(%('US $10'))
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'encodes strings with escape sequences' do
|
55
|
+
Rison.dump(%(can't)).must_equal(%('can!'t'))
|
56
|
+
Rison.dump('wow!').must_equal(%('wow!!'))
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'encodes hashes as objects' do
|
60
|
+
Rison.dump({}).must_equal('()')
|
61
|
+
Rison.dump({:a => 0}).must_equal('(a:0)')
|
62
|
+
Rison.dump({:a => 0, :b => 1}).must_equal('(a:0,b:1)')
|
63
|
+
Rison.dump({:a => 0, :b => :foo, :c => '23skidoo'}).must_equal('(a:0,b:foo,c:\'23skidoo\')')
|
64
|
+
Rison.dump({:id => nil, :type => :'/common/document'}).must_equal('(id:!n,type:/common/document)')
|
65
|
+
Rison.dump({'id' => nil, 'type' => '/common/document'}).must_equal(%(('id':!n,'type':'/common/document')))
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'encodes arrays' do
|
69
|
+
Rison.dump([]).must_equal('!()')
|
70
|
+
Rison.dump([true]).must_equal('!(!t)')
|
71
|
+
Rison.dump([true, false]).must_equal('!(!t,!f)')
|
72
|
+
Rison.dump([true, false, nil, 123]).must_equal('!(!t,!f,!n,123)')
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'raises an exception when given an undumpable object' do
|
76
|
+
proc { Rison.dump(Array) }.must_raise(Rison::DumpError)
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
|
3
|
+
$:.unshift 'lib'
|
4
|
+
|
5
|
+
require 'rison'
|
6
|
+
|
7
|
+
describe 'Rison load method' do
|
8
|
+
it 'parses true' do
|
9
|
+
Rison.load('!t').must_equal(true)
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'parses false' do
|
13
|
+
Rison.load('!f').must_equal(false)
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'parses nil' do
|
17
|
+
Rison.load('!n').must_equal(nil)
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'parses zero' do
|
21
|
+
Rison.load('0').must_equal(0)
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'parses positive integers' do
|
25
|
+
Rison.load('1').must_equal(1)
|
26
|
+
Rison.load('42').must_equal(42)
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'parses negative integers' do
|
30
|
+
Rison.load('-3').must_equal(-3)
|
31
|
+
Rison.load('-33').must_equal(-33)
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'parses integers with exponents' do
|
35
|
+
Rison.load('1e30').must_equal(10 ** 30)
|
36
|
+
Rison.load('1e-30').must_equal(10 ** -30)
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'parses fractional numbers as rationals' do
|
40
|
+
Rison.load('1.5').must_equal(Rational(3, 2))
|
41
|
+
Rison.load('99.99').must_equal(Rational(9999, 100))
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'parses fractional numbers with exponents' do
|
45
|
+
Rison.load('1.5e2').must_equal(150)
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'parses ids as symbols' do
|
49
|
+
Rison.load('a').must_equal(:a)
|
50
|
+
Rison.load('a-z').must_equal(:'a-z')
|
51
|
+
Rison.load('domain.com').must_equal(:'domain.com')
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'parses strings' do
|
55
|
+
Rison.load(%('')).must_equal('')
|
56
|
+
Rison.load(%('0a')).must_equal('0a')
|
57
|
+
Rison.load(%('-h')).must_equal('-h')
|
58
|
+
Rison.load(%('abc def')).must_equal('abc def')
|
59
|
+
Rison.load(%('user@domain.com')).must_equal('user@domain.com')
|
60
|
+
Rison.load(%('US $10')).must_equal('US $10')
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'parses strings with escape sequences' do
|
64
|
+
Rison.load(%('wow!!')).must_equal('wow!')
|
65
|
+
Rison.load(%('can!'t')).must_equal("can't")
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'parses objects as hashes' do
|
69
|
+
Rison.load('()').must_equal({})
|
70
|
+
Rison.load('(a:0)').must_equal(:a => 0)
|
71
|
+
Rison.load('(a:0,b:1)').must_equal(:a => 0, :b => 1)
|
72
|
+
Rison.load('(a:0,b:foo,c:\'23skidoo\')').must_equal(:a => 0, :b => :foo, :c => '23skidoo')
|
73
|
+
Rison.load('(id:!n,type:/common/document)').must_equal(:id => nil, :type => :'/common/document')
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'parses arrays' do
|
77
|
+
Rison.load('!()').must_equal([])
|
78
|
+
Rison.load("!(!t)").must_equal([true])
|
79
|
+
Rison.load("!(!t,!f)").must_equal([true, false])
|
80
|
+
Rison.load("!(!t,!f,!n,123)").must_equal([true, false, nil, 123])
|
81
|
+
end
|
82
|
+
|
83
|
+
it 'raises an exception when given invalid input' do
|
84
|
+
proc { Rison.load('-h') }.must_raise(Rison::ParseError)
|
85
|
+
proc { Rison.load('1.5e+2') }.must_raise(Rison::ParseError)
|
86
|
+
proc { Rison.load('1.5E2') }.must_raise(Rison::ParseError)
|
87
|
+
proc { Rison.load('1.5E+2') }.must_raise(Rison::ParseError)
|
88
|
+
proc { Rison.load('1.5E-2') }.must_raise(Rison::ParseError)
|
89
|
+
proc { Rison.load('abc def') }.must_raise(Rison::ParseError)
|
90
|
+
proc { Rison.load('US $10') }.must_raise(Rison::ParseError)
|
91
|
+
proc { Rison.load('user@domain.com') }.must_raise(Rison::ParseError)
|
92
|
+
end
|
93
|
+
end
|
metadata
CHANGED
@@ -1,72 +1,72 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: rison
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 2.0.0
|
5
|
+
prerelease:
|
5
6
|
platform: ruby
|
6
|
-
authors:
|
7
|
+
authors:
|
7
8
|
- Tim Fletcher
|
8
9
|
autorequire:
|
9
10
|
bindir: bin
|
10
11
|
cert_chain: []
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
12
|
+
date: 2012-11-03 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: parslet
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 1.4.0
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 1.4.0
|
30
|
+
description: A Ruby implementation of Rison (http://mjtemplate.org/examples/rison.html)
|
31
|
+
email:
|
32
|
+
- mail@tfletcher.com
|
26
33
|
executables: []
|
27
|
-
|
28
34
|
extensions: []
|
29
|
-
|
30
35
|
extra_rdoc_files: []
|
31
|
-
|
32
|
-
files:
|
33
|
-
- lib/rison
|
36
|
+
files:
|
34
37
|
- lib/rison/dump.rb
|
35
|
-
- lib/rison/
|
36
|
-
- lib/rison/
|
37
|
-
- lib/rison/lexer.rb
|
38
|
-
- lib/rison/parser.rb
|
38
|
+
- lib/rison/parslet_parser.rb
|
39
|
+
- lib/rison/parslet_transform.rb
|
39
40
|
- lib/rison.rb
|
40
|
-
-
|
41
|
-
-
|
42
|
-
-
|
41
|
+
- spec/rison_dump_spec.rb
|
42
|
+
- spec/rison_load_spec.rb
|
43
|
+
- README.md
|
43
44
|
- Rakefile.rb
|
44
|
-
-
|
45
|
-
|
46
|
-
homepage: http://
|
45
|
+
- rison.gemspec
|
46
|
+
- License.txt
|
47
|
+
homepage: http://github.com/tim/ruby-rison
|
48
|
+
licenses: []
|
47
49
|
post_install_message:
|
48
50
|
rdoc_options: []
|
49
|
-
|
50
|
-
require_paths:
|
51
|
+
require_paths:
|
51
52
|
- lib
|
52
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
53
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
54
|
+
none: false
|
55
|
+
requirements:
|
56
|
+
- - ! '>='
|
57
|
+
- !ruby/object:Gem::Version
|
58
|
+
version: '0'
|
59
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
60
|
+
none: false
|
61
|
+
requirements:
|
62
|
+
- - ! '>='
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
version: '0'
|
64
65
|
requirements: []
|
65
|
-
|
66
66
|
rubyforge_project:
|
67
|
-
rubygems_version: 1.
|
67
|
+
rubygems_version: 1.8.24
|
68
68
|
signing_key:
|
69
|
-
specification_version:
|
70
|
-
summary:
|
69
|
+
specification_version: 3
|
70
|
+
summary: See description
|
71
71
|
test_files: []
|
72
|
-
|
72
|
+
has_rdoc:
|