space_object 0.1.1 → 0.1.3
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 +8 -8
- data/Gemfile.lock +1 -1
- data/lib/space_object/base.rb +66 -0
- data/lib/space_object/core_ext/object/space_object.rb +100 -0
- data/lib/space_object/encode_error.rb +2 -0
- data/lib/space_object/encoder.rb +22 -0
- data/lib/space_object/parser.rb +4 -1
- data/lib/space_object/string_encodable.rb +19 -0
- data/lib/space_object/version.rb +1 -1
- data/lib/space_object.rb +6 -0
- data/spec/space_object/base_spec.rb +36 -2
- data/spec/space_object/encoder_spec.rb +24 -0
- data/spec/space_object/parser_spec.rb +6 -6
- data/spec/space_object_spec.rb +28 -4
- metadata +8 -2
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
MTU2ZjBhNWE0NWVhZGZhMzM1OTQxMTUzNjYyNDlhMzU1ZTk2ZGQxNQ==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
MDQ3OWFiOWIyMTIyZjFiODI2NmVlOGEzMGY1MWIyOGM0OTNjNGIyZQ==
|
7
7
|
!binary "U0hBNTEy":
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
YzcxNWE1N2QxMzczNmEyMzk3M2Q4Yjg0M2EyZmM2OGE0MDI1NGRlZmE5MjZl
|
10
|
+
NGIzYTIzMWMzMTExYTc2NWU1ZGFmNjFkYmIzNTYyNTg5ZWY4N2Q1OTA4Yzc1
|
11
|
+
ODk5YjRjNGZkM2EyZDYzMjQzMzc1MGI3NzE2ZmQ2MGQ5ZDY5Mjg=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
MmNjNDY2YTRjMjZkOTY2NzQ1YmU5MmE5OTdlZWJiMWIwNGYwMWNlMmY4ODJi
|
14
|
+
ZGQ2Yzg0YTI3N2I2NmJjZDIwYjRlY2NhYTU5MzZkMGU1MjBiODc0NzY4M2Ey
|
15
|
+
MjViYjg1MDFmYTk2MmUyNjZkYWI4NTJkMTY5MTQ2ZjZlNDBjZmY=
|
data/Gemfile.lock
CHANGED
data/lib/space_object/base.rb
CHANGED
@@ -1,6 +1,72 @@
|
|
1
1
|
require 'active_support/ordered_hash'
|
2
|
+
require 'space_object/core_ext/object/space_object'
|
2
3
|
|
3
4
|
module SpaceObject
|
4
5
|
class Base < ActiveSupport::OrderedHash
|
6
|
+
def [](key)
|
7
|
+
key = convert_key!(key)
|
8
|
+
unless key[' ']
|
9
|
+
super(key)
|
10
|
+
else
|
11
|
+
first_key = key[/^[^ ]+/]
|
12
|
+
value = self[first_key]
|
13
|
+
|
14
|
+
return nil if hash.nil?
|
15
|
+
rest_keys = key[(first_key.length + 1)..-1]
|
16
|
+
value[rest_keys]
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def []=(key, value)
|
21
|
+
key = convert_key!(key)
|
22
|
+
unless key[' ']
|
23
|
+
super(key, convert_value!(value))
|
24
|
+
else
|
25
|
+
first_key = key[/^[^ ]+/]
|
26
|
+
value = (self[first_key] ||= self.class.new)
|
27
|
+
value[(first_key.length + 1)..-1] = value
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
alias_method :store, :[]=
|
32
|
+
|
33
|
+
def default(key = nil)
|
34
|
+
super(key ? convert_key!(key) : nil)
|
35
|
+
end
|
36
|
+
|
37
|
+
def default=(val)
|
38
|
+
super(key ? convert_key!(key) : nil)
|
39
|
+
end
|
40
|
+
|
41
|
+
def fetch(key, *extras)
|
42
|
+
key = convert_key!(key)
|
43
|
+
first_key = key[/^[^ ]+/]
|
44
|
+
|
45
|
+
value = self[first_key]
|
46
|
+
if key[' '].nil? || hash.nil?
|
47
|
+
super(key, *extras)
|
48
|
+
else
|
49
|
+
value.fetch(first_key, *extras)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
protected
|
54
|
+
def convert_key(key)
|
55
|
+
key.to_nested_space_key
|
56
|
+
end
|
57
|
+
|
58
|
+
def convert_key!(key)
|
59
|
+
raise(ArgumentError, "#{key.class} cannot be stored as a key in a #{self.class}") unless key.respond_to?(:to_nested_space_key)
|
60
|
+
convert_key(key)
|
61
|
+
end
|
62
|
+
|
63
|
+
def convert_value(val)
|
64
|
+
val.to_space_value
|
65
|
+
end
|
66
|
+
|
67
|
+
def convert_value!(val)
|
68
|
+
raise(ArgumentError, "#{val.class} cannot be stored as a key in a #{self.class}") unless val.respond_to?(:to_space_value)
|
69
|
+
convert_value(val)
|
70
|
+
end
|
5
71
|
end
|
6
72
|
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
# List of classes to encode mirrors JSON encodable objects in ActiveSupport
|
2
|
+
|
3
|
+
require 'time'
|
4
|
+
require 'space_object/string_encodable'
|
5
|
+
|
6
|
+
class Array
|
7
|
+
def to_space_object
|
8
|
+
each_with_index.map do |item, index|
|
9
|
+
{index => item}.to_space_object
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def to_space_value
|
14
|
+
to_space_object
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
class Date
|
19
|
+
include SpaceObject::StringEncodable
|
20
|
+
end
|
21
|
+
|
22
|
+
class DateTime
|
23
|
+
include SpaceObject::StringEncodable
|
24
|
+
end
|
25
|
+
|
26
|
+
module Enumerable
|
27
|
+
def to_space_object
|
28
|
+
to_a.to_space_object
|
29
|
+
end
|
30
|
+
|
31
|
+
def to_space_value
|
32
|
+
to_space_object
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
class FalseClass
|
37
|
+
include SpaceObject::StringEncodable
|
38
|
+
end
|
39
|
+
|
40
|
+
class Hash
|
41
|
+
def to_space_object
|
42
|
+
SpaceObject::Encoder.new(self).encode
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
class NilClass
|
47
|
+
include SpaceObject::StringEncodable
|
48
|
+
end
|
49
|
+
|
50
|
+
class Numeric
|
51
|
+
include SpaceObject::StringEncodable
|
52
|
+
end
|
53
|
+
|
54
|
+
class Object
|
55
|
+
# Highly inspired by ActiveSupport
|
56
|
+
def to_space_object
|
57
|
+
hash = respond_to?(:to_hash) ? to_hash : insance_values
|
58
|
+
hash.to_space_object
|
59
|
+
end
|
60
|
+
|
61
|
+
def to_space_value
|
62
|
+
to_space_object
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
class Process::Status
|
67
|
+
include SpaceObject::StringEncodable
|
68
|
+
end
|
69
|
+
|
70
|
+
class Regexp
|
71
|
+
include SpaceObject::StringEncodable
|
72
|
+
end
|
73
|
+
|
74
|
+
class String
|
75
|
+
include SpaceObject::StringEncodable
|
76
|
+
end
|
77
|
+
|
78
|
+
class Symbol
|
79
|
+
include SpaceObject::StringEncodable
|
80
|
+
end
|
81
|
+
|
82
|
+
class Struct
|
83
|
+
# Highly inspired by ActiveSupport
|
84
|
+
def to_space_object
|
85
|
+
hash = Hash[members.zip(values)]
|
86
|
+
hash.to_space_object
|
87
|
+
end
|
88
|
+
|
89
|
+
def to_space_value
|
90
|
+
to_space_object
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
class Time
|
95
|
+
include SpaceObject::StringEncodable
|
96
|
+
end
|
97
|
+
|
98
|
+
class TrueClass
|
99
|
+
include SpaceObject::StringEncodable
|
100
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'space_object/base'
|
2
|
+
|
3
|
+
module SpaceObject
|
4
|
+
class Encoder
|
5
|
+
def initialize(object, options = {})
|
6
|
+
self.object = object
|
7
|
+
@as_key = !options.has_key?(:key) || options[:key]
|
8
|
+
end
|
9
|
+
|
10
|
+
def encode
|
11
|
+
raise(ArgumentError, "#{@object} is not a Hash") unless @object.is_a?(Hash)
|
12
|
+
@object.inject(Base.new) do |space, (key, val)|
|
13
|
+
space[key.to_space_key] = val.to_space_value
|
14
|
+
space
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def object=(object)
|
19
|
+
@object = object
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/lib/space_object/parser.rb
CHANGED
@@ -19,6 +19,9 @@ module SpaceObject
|
|
19
19
|
@document = @document.strip.gsub(/(\r\n|\n\r|\n\n+)/, "\n")
|
20
20
|
end
|
21
21
|
|
22
|
+
def populate_space(space, str)
|
23
|
+
end
|
24
|
+
|
22
25
|
def parse_string(str)
|
23
26
|
str.split(DELIMITER).inject(Base.new) do |obj, space|
|
24
27
|
key, value = if matches = KEY_LINE.match(space)
|
@@ -28,7 +31,7 @@ module SpaceObject
|
|
28
31
|
offset = matches[1].length + 1
|
29
32
|
[matches[1], space[offset..-1].gsub(NEST_SPACING, "\n")]
|
30
33
|
end
|
31
|
-
key
|
34
|
+
(key.nil? || key.empty?) or obj[key] = value
|
32
35
|
obj
|
33
36
|
end
|
34
37
|
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'space_object/encode_error'
|
2
|
+
|
3
|
+
module SpaceObject
|
4
|
+
module StringEncodable
|
5
|
+
def to_nested_space_key
|
6
|
+
to_s
|
7
|
+
end
|
8
|
+
|
9
|
+
def to_space_key
|
10
|
+
str = to_nested_space_key
|
11
|
+
raise(EncodeError, "`#{str}' contains spaces and cannot be used as a key") if str[' ']
|
12
|
+
str
|
13
|
+
end
|
14
|
+
|
15
|
+
def to_space_value
|
16
|
+
to_s
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/space_object/version.rb
CHANGED
data/lib/space_object.rb
CHANGED
@@ -1,9 +1,15 @@
|
|
1
1
|
require 'space_object/version'
|
2
|
+
require 'space_object/encode_error'
|
2
3
|
require 'space_object/base'
|
3
4
|
require 'space_object/parser'
|
5
|
+
require 'space_object/encoder'
|
4
6
|
|
5
7
|
module SpaceObject
|
6
8
|
class << self
|
9
|
+
def encode(object)
|
10
|
+
Encoder.new(object).encode
|
11
|
+
end
|
12
|
+
|
7
13
|
def parse(document)
|
8
14
|
Parser.new(document).parse
|
9
15
|
end
|
@@ -1,7 +1,41 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe SpaceObject::Base do
|
4
|
-
|
5
|
-
|
4
|
+
let(:key) { 'foo' }
|
5
|
+
let(:not_contained) { 'baz' }
|
6
|
+
let(:value) { 'bar' }
|
7
|
+
|
8
|
+
it 'is an Enumerable' do
|
9
|
+
expect(subject).to be_an(Enumerable)
|
10
|
+
end
|
11
|
+
|
12
|
+
describe '[]' do
|
13
|
+
subject { SpaceObject.encode({key => value}) }
|
14
|
+
|
15
|
+
it 'returns nil if the key does not exist' do
|
16
|
+
expect(subject[not_contained]).to be_nil
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'returns the value for a key which exists' do
|
20
|
+
expect(subject[key]).to eq(value)
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'can query with a key which implements #to_s' do
|
24
|
+
expect(subject[key.to_sym]).to eq(subject[key])
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe '[]=' do
|
29
|
+
subject { SpaceObject::Base.new }
|
30
|
+
|
31
|
+
it 'can assign with a non-nested key' do
|
32
|
+
subject[key] = value
|
33
|
+
expect(subject[key]).to eq(value)
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'can assign with a key which implements #to_s' do
|
37
|
+
subject[key.to_sym] = value
|
38
|
+
expect(subject[key]).to eq(value)
|
39
|
+
end
|
6
40
|
end
|
7
41
|
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe SpaceObject::Encoder do
|
4
|
+
let(:valid_example) { {:hello => 'world', 'foo' => :bar, 'foobar' => {'baz' => 'zip'}} }
|
5
|
+
let(:invalid_example) { { 'keys are not allowed' => 'value' } }
|
6
|
+
let(:wrong_class) { ['foo'] }
|
7
|
+
|
8
|
+
describe '#encode' do
|
9
|
+
it 'only encodes Hash objects' do
|
10
|
+
expect { SpaceObject::Encoder.new(wrong_class).encode }.to raise_error(ArgumentError)
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'encodes a compliant Hash as a SpaceObject::Base' do |variable|
|
14
|
+
space = SpaceObject::Encoder.new(valid_example).encode
|
15
|
+
expect(space['hello']).to eq('world')
|
16
|
+
expect(space['foo']).to eq('bar')
|
17
|
+
expect(space['foobar baz']).to eq('zip')
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'raises a SpaceObject::EncodeError if an invalid key is present' do
|
21
|
+
expect { SpaceObject::Encoder.new(invalid_example).encode }.to raise_error(SpaceObject::EncodeError)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -19,22 +19,22 @@ describe SpaceObject::Parser do
|
|
19
19
|
end
|
20
20
|
|
21
21
|
context 'when given a key-value pair' do
|
22
|
-
it_has_behavior 'correctness', 'key value', SpaceObject
|
22
|
+
it_has_behavior 'correctness', 'key value', SpaceObject.encode({'key' => 'value'})
|
23
23
|
end
|
24
24
|
|
25
25
|
context 'when given multiple key-value pairs' do
|
26
|
-
it_has_behavior 'correctness', "1 2\na b", SpaceObject
|
26
|
+
it_has_behavior 'correctness', "1 2\na b", SpaceObject.encode({'1' => '2', 'a' => 'b'})
|
27
27
|
end
|
28
28
|
|
29
29
|
context 'when given a nested space' do
|
30
30
|
document = "foo\n" +
|
31
31
|
" bar\n" +
|
32
32
|
" baz foobar"
|
33
|
-
expected = SpaceObject
|
34
|
-
'foo' =>
|
35
|
-
'bar' =>
|
33
|
+
expected = SpaceObject.encode({
|
34
|
+
'foo' => {
|
35
|
+
'bar' => {},
|
36
36
|
'baz' => 'foobar'
|
37
|
-
}
|
37
|
+
}
|
38
38
|
})
|
39
39
|
it_has_behavior 'correctness', document, expected
|
40
40
|
end
|
data/spec/space_object_spec.rb
CHANGED
@@ -5,21 +5,45 @@ describe SpaceObject do
|
|
5
5
|
expect(subject.const_get('VERSION')).not_to be_empty
|
6
6
|
end
|
7
7
|
|
8
|
+
describe(:encode) do
|
9
|
+
let(:hash) { {'foo' => 'bar'} }
|
10
|
+
let(:encoder) { SpaceObject::Encoder.new(hash) }
|
11
|
+
|
12
|
+
before(:each) {
|
13
|
+
@instance = encoder
|
14
|
+
@instance.stub(:encode)
|
15
|
+
SpaceObject::Encoder.stub(:new).and_return(@instance)
|
16
|
+
|
17
|
+
SpaceObject.encode(hash)
|
18
|
+
}
|
19
|
+
|
20
|
+
it "creates a new SpaceObject::Encoder" do
|
21
|
+
expect(SpaceObject::Encoder).to have_received(:new).with(hash)
|
22
|
+
end
|
23
|
+
|
24
|
+
it "calls SpaceObject::Parser#encode" do
|
25
|
+
expect(@instance).to have_received(:encode)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
8
29
|
describe "::parse" do
|
9
30
|
let(:test_document) { 'foo bar' }
|
31
|
+
let(:parser) { SpaceObject::Parser.new(test_document) }
|
10
32
|
|
11
33
|
before(:each) {
|
12
|
-
@instance =
|
34
|
+
@instance = parser
|
35
|
+
@instance.stub(:parse)
|
13
36
|
SpaceObject::Parser.stub(:new).and_return(@instance)
|
37
|
+
|
38
|
+
SpaceObject.parse(test_document)
|
14
39
|
}
|
15
40
|
|
16
41
|
it "creates a new SpaceObject::Parser" do
|
17
|
-
|
42
|
+
expect(SpaceObject::Parser).to have_received(:new).with(test_document)
|
18
43
|
end
|
19
44
|
|
20
45
|
it "calls SpaceObject::Parser#parse" do
|
21
|
-
@instance.
|
22
|
-
SpaceObject.parse(test_document) and expect(@instance).to have_received(:parse)
|
46
|
+
expect(@instance).to have_received(:parse)
|
23
47
|
end
|
24
48
|
end
|
25
49
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: space_object
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Robert Fruchtman
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-11-
|
11
|
+
date: 2013-11-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rdoc
|
@@ -83,10 +83,15 @@ files:
|
|
83
83
|
- Rakefile
|
84
84
|
- lib/space_object.rb
|
85
85
|
- lib/space_object/base.rb
|
86
|
+
- lib/space_object/core_ext/object/space_object.rb
|
87
|
+
- lib/space_object/encode_error.rb
|
88
|
+
- lib/space_object/encoder.rb
|
86
89
|
- lib/space_object/parser.rb
|
90
|
+
- lib/space_object/string_encodable.rb
|
87
91
|
- lib/space_object/version.rb
|
88
92
|
- space_object.gemspec
|
89
93
|
- spec/space_object/base_spec.rb
|
94
|
+
- spec/space_object/encoder_spec.rb
|
90
95
|
- spec/space_object/parser_spec.rb
|
91
96
|
- spec/space_object_spec.rb
|
92
97
|
- spec/spec_helper.rb
|
@@ -116,6 +121,7 @@ specification_version: 4
|
|
116
121
|
summary: A lightweight language for objects
|
117
122
|
test_files:
|
118
123
|
- spec/space_object/base_spec.rb
|
124
|
+
- spec/space_object/encoder_spec.rb
|
119
125
|
- spec/space_object/parser_spec.rb
|
120
126
|
- spec/space_object_spec.rb
|
121
127
|
- spec/spec_helper.rb
|