2020-05-11 12:48:14 +02:00
|
|
|
require "../spec_helper"
|
|
|
|
|
|
|
|
class ExampleA
|
|
|
|
include CBOR::Serializable
|
|
|
|
|
|
|
|
property a : Int32
|
|
|
|
property b : Array(Int32)
|
|
|
|
end
|
|
|
|
|
|
|
|
class ExampleB
|
|
|
|
include CBOR::Serializable
|
|
|
|
|
|
|
|
@[CBOR::Field(key: "Fun")]
|
|
|
|
property is_fun : Bool
|
|
|
|
|
|
|
|
@[CBOR::Field(key: "Amt")]
|
|
|
|
property amt : Int32
|
|
|
|
end
|
|
|
|
|
|
|
|
class ExampleC
|
|
|
|
include CBOR::Serializable
|
|
|
|
|
|
|
|
property b : String
|
|
|
|
end
|
|
|
|
|
2020-05-22 23:16:10 +02:00
|
|
|
class ExampleStrict
|
|
|
|
include CBOR::Serializable
|
|
|
|
|
|
|
|
property a : Int32
|
|
|
|
end
|
|
|
|
|
|
|
|
class ExampleUnmapped
|
|
|
|
include CBOR::Serializable
|
|
|
|
include CBOR::Serializable::Unmapped
|
|
|
|
|
|
|
|
property a : Int32
|
|
|
|
end
|
|
|
|
|
2020-05-27 13:52:29 +02:00
|
|
|
class Location
|
|
|
|
include CBOR::Serializable
|
|
|
|
|
|
|
|
@[CBOR::Field(key: "lat")]
|
|
|
|
property latitude : Float64
|
|
|
|
|
|
|
|
@[CBOR::Field(key: "lng")]
|
|
|
|
property longitude : Float64
|
|
|
|
|
|
|
|
def initialize(@latitude, @longitude)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
class House
|
|
|
|
include CBOR::Serializable
|
|
|
|
property address : String
|
|
|
|
property location : Location?
|
|
|
|
|
|
|
|
def initialize(@address, @location)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
struct A
|
|
|
|
include CBOR::Serializable
|
|
|
|
@a : Int32
|
|
|
|
@b : Float64 = 1.0
|
|
|
|
end
|
|
|
|
|
2020-05-11 12:48:14 +02:00
|
|
|
describe CBOR::Serializable do
|
|
|
|
describe "rfc examples" do
|
2020-11-11 00:42:41 +01:00
|
|
|
describe %(example {"a": 1, "b": [2, 3]}) do
|
2020-05-11 12:48:14 +02:00
|
|
|
it "decodes from cbor" do
|
|
|
|
result = ExampleA.from_cbor(Bytes[0xbf, 0x61, 0x61, 0x01, 0x61, 0x62, 0x9f, 0x02, 0x03, 0xff, 0xff])
|
|
|
|
|
|
|
|
result.a.should eq(1)
|
|
|
|
result.b.should eq([2, 3])
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2020-11-11 00:42:41 +01:00
|
|
|
describe %(example {"Fun": true, "Amt": -2}) do
|
2020-05-11 12:48:14 +02:00
|
|
|
it "decodes from cbor" do
|
|
|
|
result = ExampleB.from_cbor(Bytes[0xbf, 0x63, 0x46, 0x75, 0x6e, 0xf5, 0x63, 0x41, 0x6d, 0x74, 0x21, 0xff])
|
|
|
|
|
|
|
|
result.is_fun.should be_true
|
|
|
|
result.amt.should eq(-2)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2020-11-11 00:42:41 +01:00
|
|
|
describe %(example ["a", {"b": "c"}]) do
|
2020-05-11 12:48:14 +02:00
|
|
|
it "decodes from cbor" do
|
|
|
|
result = Array(String | ExampleC).from_cbor(Bytes[0x82, 0x61, 0x61, 0xbf, 0x61, 0x62, 0x61, 0x63, 0xff])
|
|
|
|
|
|
|
|
result.size.should eq(2)
|
|
|
|
|
|
|
|
result[0].as(String).should eq("a")
|
|
|
|
result[1].as(ExampleC).b.should eq("c")
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2020-05-22 23:16:10 +02:00
|
|
|
|
2020-05-24 14:36:34 +02:00
|
|
|
describe "strict by default" do
|
2020-05-22 23:16:10 +02:00
|
|
|
it "errors on missing fields" do
|
|
|
|
expect_raises(CBOR::ParseError) do
|
|
|
|
ExampleStrict.from_cbor(Bytes[0xbf, 0x61, 0x61, 0x01, 0x61, 0x62, 0x9f, 0x02, 0x03, 0xff, 0xff])
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe CBOR::Serializable::Unmapped do
|
|
|
|
it "adds missing fields to the map" do
|
|
|
|
result = ExampleUnmapped.from_cbor(Bytes[0xbf, 0x61, 0x61, 0x01, 0x61, 0x62, 0x9f, 0x02, 0x03, 0xff, 0xff])
|
|
|
|
|
|
|
|
result.a.should eq(1)
|
|
|
|
result.cbor_unmapped.should eq({"b" => [2, 3]})
|
|
|
|
end
|
|
|
|
end
|
2020-05-27 13:52:29 +02:00
|
|
|
|
|
|
|
describe "documentation examples" do
|
|
|
|
describe "house example" do
|
2020-05-30 12:37:12 +02:00
|
|
|
data = {
|
|
|
|
"address" => "Crystal Road 1234",
|
|
|
|
"location" => {"lat" => 12.3, "lng" => 34.5},
|
|
|
|
}
|
|
|
|
bytes = data.to_cbor
|
|
|
|
|
|
|
|
it "has the correct starting data" do
|
|
|
|
CBOR::Diagnostic.to_s(bytes).should eq(%({"address": "Crystal Road 1234", "location": {"lat": 12.3, "lng": 34.5}}))
|
|
|
|
end
|
|
|
|
|
|
|
|
it "decodes from CBOR" do
|
|
|
|
house = House.from_cbor(bytes)
|
2020-05-27 13:52:29 +02:00
|
|
|
|
2020-05-30 12:37:12 +02:00
|
|
|
house.address.should eq("Crystal Road 1234")
|
|
|
|
loc = house.location
|
|
|
|
loc.should_not be_nil
|
|
|
|
loc.not_nil!.latitude.should eq(12.3)
|
|
|
|
loc.not_nil!.longitude.should eq(34.5)
|
2020-05-27 13:52:29 +02:00
|
|
|
end
|
|
|
|
|
2020-05-30 12:37:12 +02:00
|
|
|
it "encodes to CBOR" do
|
|
|
|
cbor = House.from_cbor(bytes).to_cbor
|
2020-11-11 00:42:41 +01:00
|
|
|
CBOR::Diagnostic.to_s(cbor).should eq(%({"address": "Crystal Road 1234", "location": {"lat": 12.3, "lng": 34.5}}))
|
2020-05-30 12:37:12 +02:00
|
|
|
end
|
|
|
|
end
|
2020-05-27 13:52:29 +02:00
|
|
|
|
2020-05-30 12:37:12 +02:00
|
|
|
describe "houses array" do
|
|
|
|
data = [{
|
|
|
|
"address" => "Crystal Road 1234",
|
|
|
|
"location" => {"lat" => 12.3, "lng" => 34.5},
|
|
|
|
}]
|
|
|
|
bytes = data.to_cbor
|
|
|
|
|
|
|
|
it "has the correct starting data" do
|
|
|
|
CBOR::Diagnostic.to_s(bytes).should eq(%([{"address": "Crystal Road 1234", "location": {"lat": 12.3, "lng": 34.5}}]))
|
|
|
|
end
|
|
|
|
|
|
|
|
it "decodes from CBOR" do
|
|
|
|
houses = Array(House).from_cbor(bytes)
|
|
|
|
|
|
|
|
houses.size.should eq(1)
|
|
|
|
house = houses[0]
|
2020-05-27 13:52:29 +02:00
|
|
|
house.address.should eq("Crystal Road 1234")
|
|
|
|
|
|
|
|
loc = house.location
|
|
|
|
loc.should_not be_nil
|
|
|
|
loc.not_nil!.latitude.should eq(12.3)
|
|
|
|
loc.not_nil!.longitude.should eq(34.5)
|
|
|
|
end
|
2020-05-30 12:37:12 +02:00
|
|
|
|
|
|
|
it "encodes to CBOR" do
|
|
|
|
cbor = Array(House).from_cbor(bytes).to_cbor
|
|
|
|
|
2020-11-11 00:42:41 +01:00
|
|
|
CBOR::Diagnostic.to_s(cbor).should eq(%([{"address": "Crystal Road 1234", "location": {"lat": 12.3, "lng": 34.5}}]))
|
2020-05-30 12:37:12 +02:00
|
|
|
end
|
2020-05-27 13:52:29 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
describe "default values example" do
|
|
|
|
it "respects default values" do
|
|
|
|
A.from_cbor({"a" => 1}.to_cbor).inspect.should eq("A(@a=1, @b=1.0)")
|
|
|
|
end
|
|
|
|
end
|
2020-05-30 12:37:12 +02:00
|
|
|
|
|
|
|
describe "Unmapped extension" do
|
|
|
|
it "decodes with the values in cbor_unmapped" do
|
|
|
|
res = ExampleUnmapped.from_cbor({"a" => 1, "b" => 2}.to_cbor)
|
|
|
|
|
|
|
|
res.a.should eq(1)
|
|
|
|
res.cbor_unmapped.should eq({"b" => 2})
|
|
|
|
|
2020-11-11 00:42:41 +01:00
|
|
|
CBOR::Diagnostic.to_s(res.to_cbor).should eq(%({"a": 1, "b": 2}))
|
2020-05-30 12:37:12 +02:00
|
|
|
end
|
|
|
|
end
|
2020-05-27 13:52:29 +02:00
|
|
|
end
|
2020-05-11 12:48:14 +02:00
|
|
|
end
|