diff --git a/manifest.toml b/manifest.toml index baee2a7..269cdf3 100644 --- a/manifest.toml +++ b/manifest.toml @@ -3,30 +3,32 @@ packages = [ { name = "argv", version = "1.0.2", build_tools = ["gleam"], requirements = [], otp_app = "argv", source = "hex", outer_checksum = "BA1FF0929525DEBA1CE67256E5ADF77A7CDDFE729E3E3F57A5BDCAA031DED09D" }, - { name = "birl", version = "1.7.1", build_tools = ["gleam"], requirements = ["gleam_stdlib", "ranger"], otp_app = "birl", source = "hex", outer_checksum = "5C66647D62BCB11FE327E7A6024907C4A17954EF22865FE0940B54A852446D01" }, + { name = "birl", version = "1.8.0", build_tools = ["gleam"], requirements = ["gleam_regexp", "gleam_stdlib", "ranger"], otp_app = "birl", source = "hex", outer_checksum = "2AC7BA26F998E3DFADDB657148BD5DDFE966958AD4D6D6957DD0D22E5B56C400" }, { name = "decode", version = "0.5.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "decode", source = "hex", outer_checksum = "05E14DC95A550BA51B8774485B04894B87A898C588B9B1C920104B110AED218B" }, { name = "filepath", version = "1.1.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "filepath", source = "hex", outer_checksum = "67A6D15FB39EEB69DD31F8C145BB5A421790581BD6AA14B33D64D5A55DBD6587" }, - { name = "gleam_community_ansi", version = "1.4.1", build_tools = ["gleam"], requirements = ["gleam_community_colour", "gleam_stdlib"], otp_app = "gleam_community_ansi", source = "hex", outer_checksum = "4CD513FC62523053E62ED7BAC2F36136EC17D6A8942728250A9A00A15E340E4B" }, + { name = "gleam_community_ansi", version = "1.4.2", build_tools = ["gleam"], requirements = ["gleam_community_colour", "gleam_regexp", "gleam_stdlib"], otp_app = "gleam_community_ansi", source = "hex", outer_checksum = "479DEDC748D08B310C9FEB9C4CBEC46B95C874F7F4F2844304D6D20CA78A8BB5" }, { name = "gleam_community_colour", version = "1.4.1", build_tools = ["gleam"], requirements = ["gleam_json", "gleam_stdlib"], otp_app = "gleam_community_colour", source = "hex", outer_checksum = "386CB9B01B33371538672EEA8A6375A0A0ADEF41F17C86DDCB81C92AD00DA610" }, { name = "gleam_erlang", version = "0.33.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_erlang", source = "hex", outer_checksum = "A1D26B80F01901B59AABEE3475DD4C18D27D58FA5C897D922FCB9B099749C064" }, { name = "gleam_http", version = "3.7.2", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_http", source = "hex", outer_checksum = "8A70D2F70BB7CFEB5DF048A2183FFBA91AF6D4CF5798504841744A16999E33D2" }, { name = "gleam_httpc", version = "4.0.0", build_tools = ["gleam"], requirements = ["gleam_erlang", "gleam_http", "gleam_stdlib"], otp_app = "gleam_httpc", source = "hex", outer_checksum = "76FEEC99473E568EBA34336A37CF3D54629ACE77712950DC9BB097B5FD664664" }, - { name = "gleam_json", version = "2.1.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_json", source = "hex", outer_checksum = "0A57FB5666E695FD2BEE74C0428A98B0FC11A395D2C7B4CDF5E22C5DD32C74C6" }, - { name = "gleam_otp", version = "0.15.0", build_tools = ["gleam"], requirements = ["gleam_erlang", "gleam_stdlib"], otp_app = "gleam_otp", source = "hex", outer_checksum = "E9ED3DF7E7285DA0C440F46AE8236ADC8475E8CCBEE4899BF09A8468DA3F9187" }, - { name = "gleam_stdlib", version = "0.45.0", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "206FCE1A76974AECFC55AEBCD0217D59EDE4E408C016E2CFCCC8FF51278F186E" }, - { name = "glearray", version = "1.0.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "glearray", source = "hex", outer_checksum = "B99767A9BC63EF9CC8809F66C7276042E5EFEACAA5B25188B552D3691B91AC6D" }, + { name = "gleam_json", version = "2.3.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_json", source = "hex", outer_checksum = "C55C5C2B318533A8072D221C5E06E5A75711C129E420DD1CE463342106012E5D" }, + { name = "gleam_otp", version = "0.16.1", build_tools = ["gleam"], requirements = ["gleam_erlang", "gleam_stdlib"], otp_app = "gleam_otp", source = "hex", outer_checksum = "50DA1539FC8E8FA09924EB36A67A2BBB0AD6B27BCDED5A7EF627057CF69D035E" }, + { name = "gleam_regexp", version = "1.0.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_regexp", source = "hex", outer_checksum = "A3655FDD288571E90EE9C4009B719FEF59FA16AFCDF3952A76A125AF23CF1592" }, + { name = "gleam_stdlib", version = "0.53.0", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "53F3E1E56F692C20FA3E0A23650AC46592464E40D8EF3EC7F364FB328E73CDF5" }, + { name = "gleam_yielder", version = "1.1.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_yielder", source = "hex", outer_checksum = "8E4E4ECFA7982859F430C57F549200C7749823C106759F4A19A78AEA6687717A" }, + { name = "glearray", version = "2.0.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "glearray", source = "hex", outer_checksum = "2CDF973B9ECE4A1AB8FBFB719AA37D9F3F1FF947B260C1B21ED5B608B52BC111" }, { name = "gleescript", version = "1.4.0", build_tools = ["gleam"], requirements = ["argv", "filepath", "gleam_erlang", "gleam_stdlib", "simplifile", "snag", "tom"], otp_app = "gleescript", source = "hex", outer_checksum = "8CDDD29F91064E69950A91A40061785F10275ADB70A0520075591F61A724C455" }, - { name = "gleeunit", version = "1.2.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleeunit", source = "hex", outer_checksum = "F7A7228925D3EE7D0813C922E062BFD6D7E9310F0BEE585D3A42F3307E3CFD13" }, + { name = "gleeunit", version = "1.3.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleeunit", source = "hex", outer_checksum = "0E6C83834BA65EDCAAF4FE4FB94AC697D9262D83E6F58A750D63C9F6C8A9D9FF" }, { name = "glisten", version = "7.0.0", build_tools = ["gleam"], requirements = ["gleam_erlang", "gleam_otp", "gleam_stdlib", "logging", "telemetry"], otp_app = "glisten", source = "hex", outer_checksum = "028C0882EAC7ABEDEFBE92CE4D1FEDADE95FA81B1B1AB099C4F91C133BEF2C42" }, { name = "logging", version = "1.3.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "logging", source = "hex", outer_checksum = "1098FBF10B54B44C2C7FDF0B01C1253CAFACDACABEFB4B0D027803246753E06D" }, { name = "mug", version = "1.2.0", build_tools = ["gleam"], requirements = ["gleam_erlang", "gleam_stdlib"], otp_app = "mug", source = "hex", outer_checksum = "C5F62A3FD753B823CE296ED1B223D4B2FF06E91170A7DE35A283D70BB74B700E" }, - { name = "ranger", version = "1.3.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "ranger", source = "hex", outer_checksum = "B8F3AFF23A3A5B5D9526B8D18E7C43A7DFD3902B151B97EC65397FE29192B695" }, + { name = "ranger", version = "1.4.0", build_tools = ["gleam"], requirements = ["gleam_stdlib", "gleam_yielder"], otp_app = "ranger", source = "hex", outer_checksum = "C8988E8F8CDBD3E7F4D8F2E663EF76490390899C2B2885A6432E942495B3E854" }, { name = "repeatedly", version = "2.1.2", build_tools = ["gleam"], requirements = [], otp_app = "repeatedly", source = "hex", outer_checksum = "93AE1938DDE0DC0F7034F32C1BF0D4E89ACEBA82198A1FE21F604E849DA5F589" }, { name = "simplifile", version = "2.2.0", build_tools = ["gleam"], requirements = ["filepath", "gleam_stdlib"], otp_app = "simplifile", source = "hex", outer_checksum = "0DFABEF7DC7A9E2FF4BB27B108034E60C81BEBFCB7AB816B9E7E18ED4503ACD8" }, - { name = "snag", version = "1.0.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "snag", source = "hex", outer_checksum = "08E9EB87C413457DB1DD66CD704C6878DACC9C93B418600F63873D0CD224E756" }, - { name = "spinner", version = "1.3.0", build_tools = ["gleam"], requirements = ["gleam_community_ansi", "gleam_stdlib", "glearray", "repeatedly"], otp_app = "spinner", source = "hex", outer_checksum = "B824C4CFDA6AC912D14365BF365F2A52C4DA63EF2D768D2A1C46D9BF7AF669E7" }, + { name = "snag", version = "1.1.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "snag", source = "hex", outer_checksum = "7E9F06390040EB5FAB392CE642771484136F2EC103A92AE11BA898C8167E6E17" }, + { name = "spinner", version = "1.3.1", build_tools = ["gleam"], requirements = ["gleam_community_ansi", "gleam_stdlib", "glearray", "repeatedly"], otp_app = "spinner", source = "hex", outer_checksum = "21BDE7FF9D7D9ACBB4086C0D5C86F0A90CE6B0F3CB593B41D03384AE7724B5B4" }, { name = "telemetry", version = "1.3.0", build_tools = ["rebar3"], requirements = [], otp_app = "telemetry", source = "hex", outer_checksum = "7015FC8919DBE63764F4B4B87A95B7C0996BD539E0D499BE6EC9D7F3875B79E6" }, - { name = "tom", version = "1.1.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "tom", source = "hex", outer_checksum = "228E667239504B57AD05EC3C332C930391592F6C974D0EFECF32FFD0F3629A27" }, + { name = "tom", version = "1.1.1", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "tom", source = "hex", outer_checksum = "0910EE688A713994515ACAF1F486A4F05752E585B9E3209D8F35A85B234C2719" }, ] [requirements] diff --git a/src/json_serde.gleam b/src/json_serde.gleam index b1d96f9..d34b54c 100644 --- a/src/json_serde.gleam +++ b/src/json_serde.gleam @@ -49,6 +49,7 @@ fn leaf_to_json(tree: tree.Tree) -> json.Json { } } +/// Decodes a full tree (which root is tree.Root) from JSON pub fn deserialize(string) { case json.decode(string, zero.run(_, zero.dynamic)) { Error(_) -> Error(DecodingError) @@ -56,6 +57,14 @@ pub fn deserialize(string) { } } +/// Decodes a subtree (which root is NOT tree.Root) from JSON +pub fn deserialize_sub(string) { + case json.decode(string, zero.run(_, zero.dynamic)) { + Error(_) -> Error(DecodingError) + Ok(data) -> data |> tree_decoder(False) |> Ok + } +} + fn tree_decoder(data, root) { let _ = case dynamic.classify(data), root { "Dict", True -> { diff --git a/src/query.gleam b/src/query.gleam index 5af510b..5338fbf 100644 --- a/src/query.gleam +++ b/src/query.gleam @@ -1,5 +1,3 @@ -import gleam/dynamic -import gleam/json import gleam/string import json_serde import query_error.{type QueryError, QueryError} @@ -27,8 +25,7 @@ pub fn parse(query: String) { case path |> parse_path { Error(_) -> Error(QueryError("Wrong query format.")) Ok(#(head, tail)) -> { - let assert Ok(data) = data |> json.decode(dynamic.dynamic) - let data = data |> json_serde.decode_leafdata + let data = data |> json_serde.deserialize_sub case data { Error(_) -> Error(QueryError("Wrong data format.")) Ok(data) -> diff --git a/src/tree.gleam b/src/tree.gleam index 6d0775d..d2d4589 100644 --- a/src/tree.gleam +++ b/src/tree.gleam @@ -51,10 +51,10 @@ pub fn set(tree, path, data) { res } -fn set_step(tree: Tree, path: List(String), data: LeafData) { +fn set_step(tree: Tree, path: List(String), data: Tree) { case tree, path { - Leaf(_), [child] -> Node(dict.new() |> dict.insert(child, Leaf(data))) - Node(children), [child] -> Node(children |> dict.insert(child, Leaf(data))) + Leaf(_), [child] -> Node(dict.new() |> dict.insert(child, data)) + Node(children), [child] -> Node(children |> dict.insert(child, data)) Leaf(_), [head, ..tail] -> Node( dict.new() @@ -74,7 +74,7 @@ fn set_step(tree: Tree, path: List(String), data: LeafData) { Root(children), [head] -> Root( children - |> dict.insert(head, Leaf(data)), + |> dict.insert(head, data), ) Root(children), [head, ..tail] -> diff --git a/src/tree_events.gleam b/src/tree_events.gleam index 065e9ce..e6bfd99 100644 --- a/src/tree_events.gleam +++ b/src/tree_events.gleam @@ -7,7 +7,7 @@ pub type TreeEvents { SetEvent( path: List(String), - data: tree.LeafData, + data: tree.Tree, reply_with: Subject(Result(String, QueryError)), ) diff --git a/test/raw_benchmark.gleam b/test/raw_benchmark.gleam index bf95760..6b246a5 100644 --- a/test/raw_benchmark.gleam +++ b/test/raw_benchmark.gleam @@ -39,7 +39,7 @@ fn fill(tree, i) { 1_000_000 -> tree _ -> { let assert Ok(tree) = - tree |> query.set([".", int.to_string(i)], tree.Int(i)) + tree |> query.set([".", int.to_string(i)], tree.Leaf(tree.Int(i))) tree |> fill(i + 1) } } @@ -81,7 +81,7 @@ fn tree_bench() { fn fill_tree(tree, paths) { paths |> list.fold(tree, fn(tree, path) { - let assert Ok(tree) = tree |> query.set(path, tree.String("foo")) + let assert Ok(tree) = tree |> query.set(path, tree.Leaf(tree.String("foo"))) tree }) } diff --git a/test/server_test.gleam b/test/server_test.gleam index 36402e9..1447fdb 100644 --- a/test/server_test.gleam +++ b/test/server_test.gleam @@ -35,4 +35,23 @@ pub fn server_test() { let assert Ok(packet) = mug.receive(socket, timeout_milliseconds: 100) packet |> should.equal(<<"{\"a\":2,\"b\":\"foo\"}":utf8>>) + + let assert Ok(Nil) = + mug.send(socket, << + "set root.c {\"a\":{\"b\":{\"c\":{\"d\":{\"e\":{\"f\":true}}}}}}":utf8, + >>) + let assert Ok(_) = mug.receive(socket, timeout_milliseconds: 100) + let assert Ok(Nil) = mug.send(socket, <<"get root.c":utf8>>) + let assert Ok(packet) = mug.receive(socket, timeout_milliseconds: 100) + packet + |> should.equal(<< + "{\"a\":{\"b\":{\"c\":{\"d\":{\"e\":{\"f\":true}}}}}}":utf8, + >>) + + let assert Ok(Nil) = mug.send(socket, <<"set root.a {\"baz\":\"bar\"}":utf8>>) + let assert Ok(_) = mug.receive(socket, timeout_milliseconds: 100) + let assert Ok(Nil) = mug.send(socket, <<"get root.a":utf8>>) + let assert Ok(packet) = mug.receive(socket, timeout_milliseconds: 100) + packet + |> should.equal(<<"{\"baz\":\"bar\"}":utf8>>) } diff --git a/test/treevault_test.gleam b/test/treevault_test.gleam index 6966f31..cf3aafd 100644 --- a/test/treevault_test.gleam +++ b/test/treevault_test.gleam @@ -18,11 +18,11 @@ pub fn path_parse_test() { pub fn kv_test() { let tree = tree.new() - let assert Ok(tree) = query.set(tree, ["a"], tree.String("foo")) - let assert Ok(tree) = query.set(tree, ["b"], tree.Int(42)) - let assert Ok(tree) = query.set(tree, ["c"], tree.Float(12.34)) - let assert Ok(tree) = query.set(tree, ["d"], tree.Bool(False)) - let assert Ok(tree) = query.set(tree, ["e"], tree.Null) + let assert Ok(tree) = query.set(tree, ["a"], tree.Leaf(tree.String("foo"))) + let assert Ok(tree) = query.set(tree, ["b"], tree.Leaf(tree.Int(42))) + let assert Ok(tree) = query.set(tree, ["c"], tree.Leaf(tree.Float(12.34))) + let assert Ok(tree) = query.set(tree, ["d"], tree.Leaf(tree.Bool(False))) + let assert Ok(tree) = query.set(tree, ["e"], tree.Leaf(tree.Null)) query.get(tree, ["a"]) |> should.equal(tree.Leaf(tree.String("foo")) |> Ok()) @@ -39,11 +39,13 @@ pub fn kv_test() { pub fn tree_test() { let tree = tree.new() let assert Ok(tree) = - query.set(tree, ["a", "b", "c", "d"], tree.String("foo")) - let assert Ok(tree) = query.set(tree, ["a", "b2", "c"], tree.String("bar")) - let assert Ok(tree) = query.set(tree, ["a", "b"], tree.String("new foo")) - let assert Ok(tree) = query.set(tree, ["a2", "b3"], tree.Int(42)) - let assert Ok(tree) = query.set(tree, ["a2", "b3"], tree.Int(43)) + query.set(tree, ["a", "b", "c", "d"], tree.Leaf(tree.String("foo"))) + let assert Ok(tree) = + query.set(tree, ["a", "b2", "c"], tree.Leaf(tree.String("bar"))) + let assert Ok(tree) = + query.set(tree, ["a", "b"], tree.Leaf(tree.String("new foo"))) + let assert Ok(tree) = query.set(tree, ["a2", "b3"], tree.Leaf(tree.Int(42))) + let assert Ok(tree) = query.set(tree, ["a2", "b3"], tree.Leaf(tree.Int(43))) query.get(tree, ["a", "b"]) |> should.equal(tree.Leaf(tree.String("new foo")) |> Ok()) @@ -60,11 +62,13 @@ pub fn tree_test() { pub fn json_test() { let tree = tree.new() let assert Ok(tree) = - query.set(tree, ["a", "b", "c", "d"], tree.String("foo")) - let assert Ok(tree) = query.set(tree, ["a", "b2", "c"], tree.String("bar")) - let assert Ok(tree) = query.set(tree, ["a", "b"], tree.String("new foo")) - let assert Ok(tree) = query.set(tree, ["a2", "b3"], tree.Int(42)) - let assert Ok(tree) = query.set(tree, ["a2", "b3"], tree.Int(43)) + query.set(tree, ["a", "b", "c", "d"], tree.Leaf(tree.String("foo"))) + let assert Ok(tree) = + query.set(tree, ["a", "b2", "c"], tree.Leaf(tree.String("bar"))) + let assert Ok(tree) = + query.set(tree, ["a", "b"], tree.Leaf(tree.String("new foo"))) + let assert Ok(tree) = query.set(tree, ["a2", "b3"], tree.Leaf(tree.Int(42))) + let assert Ok(tree) = query.set(tree, ["a2", "b3"], tree.Leaf(tree.Int(43))) let json = tree |> json_serde.serialize let assert Ok(decoded) = json |> json_serde.deserialize()