rison 1.2.1 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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:
|