Skip to content

Commit f45ef73

Browse files
Merge pull request #245 from code0-tech/#244-expand-number-value
Expand NumberValue to Contain Integer
2 parents cb37f34 + 7a939e3 commit f45ef73

5 files changed

Lines changed: 395 additions & 49 deletions

File tree

build/ruby/lib/tucana/shared/shared.struct.rb

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,11 @@ def to_ruby(recursive = false)
6565
when :null_value
6666
nil
6767
when :number_value
68-
self.number_value
68+
if recursive
69+
self.number_value.to_ruby
70+
else
71+
self.number_value
72+
end
6973
when :string_value
7074
self.string_value
7175
when :bool_value
@@ -84,7 +88,7 @@ def from_ruby(value)
8488
when NilClass
8589
self.null_value = :NULL_VALUE
8690
when Numeric
87-
self.number_value = value
91+
self.number_value = NumberValue.from_ruby(value)
8892
when String
8993
self.string_value = value
9094
when TrueClass
@@ -107,6 +111,36 @@ def from_ruby(value)
107111
end
108112
end
109113

114+
NumberValue.class_eval do
115+
def to_ruby
116+
case self.number
117+
when :integer
118+
self.integer
119+
when :float
120+
self.float
121+
else
122+
raise UnexpectedStructType
123+
end
124+
end
125+
126+
def self.from_ruby(value)
127+
self.new.from_ruby(value)
128+
end
129+
130+
def from_ruby(value)
131+
case value
132+
when Integer
133+
self.integer = value
134+
when Float
135+
self.float = value
136+
else
137+
raise UnexpectedStructType
138+
end
139+
140+
self
141+
end
142+
end
143+
110144
ListValue.class_eval do
111145
include Enumerable
112146

Lines changed: 227 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,227 @@
1+
# frozen_string_literal: true
2+
3+
Tucana.load_protocol(:shared)
4+
5+
RSpec.describe Tucana::Shared do
6+
describe "Struct" do
7+
subject(:struct) { Tucana::Shared::Struct.new }
8+
9+
describe "#[]" do
10+
it "returns the ruby value for an existing key" do
11+
struct["name"] = "test"
12+
expect(struct["name"]).to eq("test")
13+
end
14+
15+
it "returns nil for a missing key" do
16+
expect(struct["missing"]).to be_nil
17+
end
18+
end
19+
20+
describe "#[]=" do
21+
it "sets string values" do
22+
struct["key"] = "value"
23+
expect(struct["key"]).to eq("value")
24+
end
25+
26+
it "sets numeric values" do
27+
struct["num"] = 42
28+
expect(struct["num"]).to be_a(Tucana::Shared::NumberValue)
29+
expect(struct["num"].to_ruby).to eq(42)
30+
end
31+
32+
it "sets boolean values" do
33+
struct["flag"] = true
34+
expect(struct["flag"]).to eq(true)
35+
end
36+
37+
it "sets nil values" do
38+
struct["empty"] = nil
39+
expect(struct["empty"]).to be_nil
40+
end
41+
42+
it "raises UnexpectedStructType for non-string keys" do
43+
expect { struct[123] = "val" }.to raise_error(Tucana::Shared::UnexpectedStructType)
44+
end
45+
end
46+
47+
describe "#to_h" do
48+
it "returns a hash with ruby values" do
49+
struct["a"] = "hello"
50+
struct["b"] = 1
51+
expect(struct.to_h).to eq({ "a" => "hello", "b" => 1 })
52+
end
53+
end
54+
55+
describe ".from_hash" do
56+
it "creates a Struct from a hash" do
57+
result = Tucana::Shared::Struct.from_hash({ "x" => "y", "n" => 5 })
58+
expect(result).to be_a(Tucana::Shared::Struct)
59+
expect(result.to_h).to eq({ "x" => "y", "n" => 5 })
60+
end
61+
end
62+
63+
describe "#has_key?" do
64+
it "returns true for existing keys" do
65+
struct["key"] = "val"
66+
expect(struct.has_key?("key")).to be true
67+
end
68+
69+
it "returns false for missing keys" do
70+
expect(struct.has_key?("nope")).to be false
71+
end
72+
end
73+
end
74+
75+
describe "Value" do
76+
describe "#to_ruby" do
77+
it "converts string values" do
78+
val = Tucana::Shared::Value.from_ruby("hello")
79+
expect(val.to_ruby).to eq("hello")
80+
end
81+
82+
it "converts boolean values" do
83+
val = Tucana::Shared::Value.from_ruby(true)
84+
expect(val.to_ruby).to eq(true)
85+
end
86+
87+
it "converts nil" do
88+
val = Tucana::Shared::Value.from_ruby(nil)
89+
expect(val.to_ruby).to be_nil
90+
end
91+
92+
it "returns Struct for struct values when not recursive" do
93+
val = Tucana::Shared::Value.from_ruby({ "a" => 1 })
94+
expect(val.to_ruby).to be_a(Tucana::Shared::Struct)
95+
end
96+
97+
it "returns Hash for struct values when recursive" do
98+
val = Tucana::Shared::Value.from_ruby({ "a" => 1 })
99+
expect(val.to_ruby(true)).to eq({ "a" => 1 })
100+
end
101+
102+
it "returns ListValue for list values when not recursive" do
103+
val = Tucana::Shared::Value.from_ruby([1, 2])
104+
expect(val.to_ruby).to be_a(Tucana::Shared::ListValue)
105+
end
106+
107+
it "returns Array for list values when recursive" do
108+
val = Tucana::Shared::Value.from_ruby([1, 2])
109+
expect(val.to_ruby(true)).to eq([1, 2])
110+
end
111+
112+
it "returns NumberValue for number values when not recursive" do
113+
val = Tucana::Shared::Value.from_ruby(42)
114+
expect(val.to_ruby).to be_a(Tucana::Shared::NumberValue)
115+
end
116+
117+
it "returns ruby number for number values when recursive" do
118+
val = Tucana::Shared::Value.from_ruby(42)
119+
expect(val.to_ruby(true)).to eq(42)
120+
end
121+
end
122+
123+
describe "#from_ruby" do
124+
it "handles Hash by converting to Struct" do
125+
val = Tucana::Shared::Value.from_ruby({ "k" => "v" })
126+
expect(val.kind).to eq(:struct_value)
127+
end
128+
129+
it "handles Array by converting to ListValue" do
130+
val = Tucana::Shared::Value.from_ruby([1])
131+
expect(val.kind).to eq(:list_value)
132+
end
133+
134+
it "handles Struct directly" do
135+
s = Tucana::Shared::Struct.from_hash({ "a" => 1 })
136+
val = Tucana::Shared::Value.from_ruby(s)
137+
expect(val.kind).to eq(:struct_value)
138+
end
139+
140+
it "handles ListValue directly" do
141+
lv = Tucana::Shared::ListValue.from_a([1])
142+
val = Tucana::Shared::Value.from_ruby(lv)
143+
expect(val.kind).to eq(:list_value)
144+
end
145+
146+
it "raises UnexpectedStructType for unsupported types" do
147+
expect { Tucana::Shared::Value.from_ruby(:symbol) }.to raise_error(Tucana::Shared::UnexpectedStructType)
148+
end
149+
end
150+
end
151+
152+
describe "NumberValue" do
153+
describe "#to_ruby" do
154+
it "returns integer for integer values" do
155+
nv = Tucana::Shared::NumberValue.from_ruby(5)
156+
expect(nv.number).to eq(:integer)
157+
expect(nv.to_ruby).to eq(5)
158+
expect(nv.to_ruby).to be_a(Integer)
159+
end
160+
161+
it "returns float for float values" do
162+
nv = Tucana::Shared::NumberValue.from_ruby(3.14)
163+
expect(nv.number).to eq(:float)
164+
expect(nv.to_ruby).to eq(3.14)
165+
expect(nv.to_ruby).to be_a(Float)
166+
end
167+
end
168+
169+
describe "#from_ruby" do
170+
it "raises UnexpectedStructType for non-numeric types" do
171+
expect { Tucana::Shared::NumberValue.from_ruby("5") }.to raise_error(Tucana::Shared::UnexpectedStructType)
172+
end
173+
end
174+
end
175+
176+
describe "ListValue" do
177+
subject(:list) { Tucana::Shared::ListValue.from_a([1, "two", true]) }
178+
179+
describe "#length" do
180+
it "returns the number of elements" do
181+
expect(list.length).to eq(3)
182+
end
183+
end
184+
185+
describe "#[]" do
186+
it "returns the ruby value at the index" do
187+
expect(list[1]).to eq("two")
188+
end
189+
end
190+
191+
describe "#<<" do
192+
it "appends a value" do
193+
list << "new"
194+
expect(list.length).to eq(4)
195+
expect(list[3]).to eq("new")
196+
end
197+
end
198+
199+
describe "#each" do
200+
it "yields ruby values" do
201+
values = []
202+
list.each { |v| values << v }
203+
expect(values).to include("two", true)
204+
end
205+
end
206+
207+
describe "#to_a" do
208+
it "returns a ruby array" do
209+
expect(list.to_a).to eq([1, "two", true])
210+
end
211+
end
212+
213+
describe ".from_a" do
214+
it "creates a ListValue from an array" do
215+
result = Tucana::Shared::ListValue.from_a(["a", 1])
216+
expect(result).to be_a(Tucana::Shared::ListValue)
217+
expect(result.to_a).to eq(["a", 1])
218+
end
219+
end
220+
221+
describe "Enumerable" do
222+
it "supports Enumerable methods" do
223+
expect(list.map { |v| v }).to include("two")
224+
end
225+
end
226+
end
227+
end

0 commit comments

Comments
 (0)