Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Serializable #6

Merged
merged 6 commits into from
Feb 25, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 116 additions & 0 deletions spec/kdl/serializable_spec.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
require "../spec_helper"

class TestChild
include KDL::Serializable

@[KDL::Argument]
property value : String
end

class TestNode
include KDL::Serializable

@[KDL::Argument]
property first : String

@[KDL::Argument]
property second : Bool

@[KDL::Arguments]
property numbers : Array(UInt32)

@[KDL::Property]
property foo : String

@[KDL::Property(name: "bardle")]
property bar : String

@[KDL::Properties]
property map : Hash(String, String)

@[KDL::Child(unwrap: "argument")]
property arg : String

@[KDL::Child(unwrap: "arguments")]
property args : Array(String)

@[KDL::Child(unwrap: "properties")]
property props : Hash(String, String)

@[KDL::Child(name: "feature", unwrap: "argument")]
property feature_name : String

@[KDL::Child(name: "feature", unwrap: "property", property_name: "enabled")]
property feature_enabled : Bool

@[KDL::Child(name: "feature", unwrap: "property", property_name: "option")]
property feature_option : UInt32

@[KDL::Child(unwrap: "dash_vals")]
property dashies : Array(String)

@[KDL::Child]
property norf : TestChild

@[KDL::Children(name: "thing")]
property things : Array(TestChild)

@[KDL::Child(unwrap: "children")]
property thangs : Array(TestChild)

@[KDL::Children(name: "path", unwrap: "argument")]
property paths : Array(String)
end

describe KDL::Serializable do
it "serializes documents" do
doc = KDL.parse <<-KDL
TestNode "arg1" #true 1 22 333 foo="a" bardle="b" baz="c" qux="d" {
norf wat
thing foo
thing bar
thing baz
path "some/path"
path "some/other/path"
arg arg2
args x y z
props a=x b=y c=z
feature florp enabled=#true option=42
dashies {
- Lorem
- Ipsum
}
thangs {
- qux
- norf
}
}
KDL

obj = TestNode.from_kdl(doc.nodes[0])
obj.first.should eq "arg1"
obj.second.should eq true
obj.numbers.should eq [1, 22, 333]
obj.foo.should eq "a"
obj.bar.should eq "b"
obj.map.should eq({ "baz" => "c", "qux" => "d" })
obj.arg.should eq "arg2"
obj.args.should eq ["x", "y", "z"]
obj.props.should eq({ "a" => "x", "b" => "y", "c" => "z" })
obj.feature_name.should eq("florp")
obj.feature_enabled.should eq(true)
obj.feature_option.should eq(42_u64)
obj.dashies.should eq(["Lorem", "Ipsum"])
obj.norf.value.should eq "wat"
obj.things.size.should eq 3
obj.things[0].value.should eq "foo"
obj.things[1].value.should eq "bar"
obj.things[2].value.should eq "baz"
Comment on lines +106 to +108
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This syntax is quite common, e.g.:

some-paths {
  path "path/to/something"
  path "path/to/something/else"
}

Having to call #value on it is a bit cumbersome. Directly newing up Array(String) for such cases would be nicer. This is related to my other comment about arrays in serializable.cr :D

obj.thangs.size.should eq 2
obj.thangs[0].value.should eq "qux"
obj.thangs[1].value.should eq "norf"
obj.paths.should eq ["some/path", "some/other/path"]

KDL::Document.new([obj.to_kdl]).should eq doc
end
end
11 changes: 8 additions & 3 deletions src/kdl/builder.cr
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,9 @@ module KDL
if parent = current_node
parent.children << node
else
document.nodes << node
document << node
end
node
end

# Node name only
Expand Down Expand Up @@ -64,7 +65,9 @@ module KDL

def arg(value : Value::Type, *, type : String? = nil, comment : String? = nil)
if node = current_node
node.arguments << Value.new(value, type: type, comment: comment)
val = Value.new(value, type: type, comment: comment)
node.arguments << val
val
else
raise Error.new "Can't do argument, not inside Node"
end
Expand All @@ -73,7 +76,9 @@ module KDL
def prop(key : String | Symbol, value : Value::Type, *, type : String? = nil, comment : String? = nil)
key = key.to_s
if node = current_node
node.properties[key] = Value.new(value, type: type, comment: comment)
val = Value.new(value, type: type, comment: comment)
node.properties[key] = val
val
else
raise Error.new "Can't do property, not inside Node"
end
Expand Down
14 changes: 14 additions & 0 deletions src/kdl/document.cr
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,26 @@ require "./node"

module KDL
class Document
include Enumerable(Node)

property nodes
property comment

def initialize(@nodes = [] of Node, *, @comment : String? = nil)
end

def each(&)
@nodes.each { |n| yield n }
end

def <<(node)
@nodes << node
end

def empty?
@nodes.empty?
end

def [](index : Int)
nodes[index]
end
Expand Down
14 changes: 13 additions & 1 deletion src/kdl/node.cr
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,24 @@ module KDL
*,
@arguments = [] of KDL::Value,
@properties = {} of String => KDL::Value,
@children = [] of Node,
@children : KDL::Document = KDL::Document.new,
@type : String? = nil,
@comment : String? = nil,
)
end

def initialize(
name : String,
*,
arguments = [] of KDL::Value,
properties = {} of String => KDL::Value,
children : Array(KDL::Node),
type : String? = nil,
comment : String? = nil,
)
initialize(name, arguments: arguments, properties: properties, children: KDL::Document.new(children), type: type, comment: comment)
end

def [](index : Int) : Value::Type
arguments[index].value
end
Expand Down
2 changes: 1 addition & 1 deletion src/kdl/parser.cr
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ module KDL
@depth += 1
children = parse_children
@depth -= 1
node.children = children unless commented
node.children = KDL::Document.new(children) unless commented
end

private def parse_rbrace
Expand Down
Loading