From 59dcefb116f72e1db52737cbb3e845d33739712a Mon Sep 17 00:00:00 2001 From: "Tristan B. Velloza Kildaire" Date: Wed, 16 Jul 2025 19:01:26 +0200 Subject: [PATCH 01/22] JSONProvider - Initial code being worked on --- source/hummus/providers/json.d | 118 +++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 source/hummus/providers/json.d diff --git a/source/hummus/providers/json.d b/source/hummus/providers/json.d new file mode 100644 index 0000000..2bd242e --- /dev/null +++ b/source/hummus/providers/json.d @@ -0,0 +1,118 @@ +module hummus.providers.json; + +import hummus.provider : Provider; + +public class JSONProvider : Provider +{ + import std.json : JSONValue, parseJSON, JSONException, JSONType; + + private JSONValue _j; + + this(string json) + { + // todo: handle exceptions in non-library specific way + // OR require they parse in the JSONValue - that is + // library-dependent tho + this._j = parseJSON(json); + } + + protected bool provideImpl(string n, ref string v) + { + import std.stdio : writeln; + string[] c; + if(dotExtract(n, c) == false) + { + writeln("direct access for: ", n); + + JSONValue* p = n in this._j; + if(p) + { + string finalV; + + // todo: bail on unsupported types + + // de-stringatize if it is a JSON string + if(p.type() == JSONType.string) + { + + // finalV = p.str()[] + } + else + { + finalV = p.toString(); + } + // import std.string : strip + // todo: value must be vconverte here + writeln("finalV: ", finalV); + + v = finalV; + return true; + } + else + { + return false; + } + + pragma(msg, typeof(p)); + } + else + { + writeln("Access path: ", c); + } + + // todo: use dot-explorer on the JSONValue + return true; + } +} + +private bool dotExtract(string i, ref string[] o) +{ + import std.string : split; + + auto cmps = split(i, "."); + + if(cmps.length == 1) + { + return false; + } + else + { + o = cmps; + return true; + } +} + +private version(unittest) +{ + import hummus.cfg : fieldsOf; + import std.stdio : writeln; +} + +unittest +{ + struct Basic + { + string name; + ulong age; + } + + auto cfg = Basic(); + writeln("Before provisioning: ", cfg); + + string json = ` + { + "name": "Tristan Brice Velloza Kildaire", + "age": 25 + } + `; + + + + // todo: state what should be present + // create a new JSON provider with the + // input JSON + fieldsOf(cfg, new JSONProvider(json)); + + // assert(cfg.name == "Tristan Brice Velloza Kildaire"); + assert(cfg.age == 25); +} \ No newline at end of file From 100fd35235f4d8813372781b7c5ea1530bd858e4 Mon Sep 17 00:00:00 2001 From: "Tristan B. Velloza Kildaire" Date: Wed, 16 Jul 2025 22:43:45 +0200 Subject: [PATCH 02/22] json - Added `traverseTo(string, JSONValue*`) --- source/hummus/providers/json.d | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/source/hummus/providers/json.d b/source/hummus/providers/json.d index 2bd242e..186f038 100644 --- a/source/hummus/providers/json.d +++ b/source/hummus/providers/json.d @@ -65,6 +65,35 @@ public class JSONProvider : Provider } } +import std.json : JSONValue; + +// todo: this belongs in the niknaks library +private JSONValue* traverseTo(string path, JSONValue* start) +{ + import std.string : split, indexOf; + + // no dots `.` in the name + if(indexOf(path, ".") < 0) + { + JSONValue* p = path in *start; + + return p; + } + // if there are dots present like `x.y` + else + { + string[] cmps = split(path, "."); + + JSONValue* root = cmps[0] in *start; + + // todo: range check? + string[] rem = cmps[1..$]; + import std.string : join; + + return traverseTo(join(rem, "."), root); + } +} + private bool dotExtract(string i, ref string[] o) { import std.string : split; From 010b5f3cd1eddc4ae9fcc979dceaaddf7fc3b753 Mon Sep 17 00:00:00 2001 From: "Tristan B. Velloza Kildaire" Date: Wed, 16 Jul 2025 22:51:55 +0200 Subject: [PATCH 03/22] JSONProvider - Use the new `jsonNormal(JSONValue*)` for processing values of JSON nodes json - Implemented `jsonNormal(JSONValue*)` --- source/hummus/providers/json.d | 112 +++++++++++++++++++++------------ 1 file changed, 71 insertions(+), 41 deletions(-) diff --git a/source/hummus/providers/json.d b/source/hummus/providers/json.d index 186f038..4366bc6 100644 --- a/source/hummus/providers/json.d +++ b/source/hummus/providers/json.d @@ -18,55 +18,85 @@ public class JSONProvider : Provider protected bool provideImpl(string n, ref string v) { - import std.stdio : writeln; - string[] c; - if(dotExtract(n, c) == false) - { - writeln("direct access for: ", n); - - JSONValue* p = n in this._j; - if(p) - { - string finalV; - - // todo: bail on unsupported types - - // de-stringatize if it is a JSON string - if(p.type() == JSONType.string) - { - - // finalV = p.str()[] - } - else - { - finalV = p.toString(); - } - // import std.string : strip - // todo: value must be vconverte here - writeln("finalV: ", finalV); - - v = finalV; - return true; - } - else - { - return false; - } - - pragma(msg, typeof(p)); - } - else + // todo: check return value for nullity + JSONValue* f_node = traverseTo(n, &this._j); + + // todo: value conversion here + if(f_node is null) { - writeln("Access path: ", c); + return false; } - // todo: use dot-explorer on the JSONValue + string s = jsonNormal(f_node); + writeln("found JSON node toString(): ", s); + v = s; return true; + + + // import std.stdio : writeln; + // string[] c; + // if(dotExtract(n, c) == false) + // { + // writeln("direct access for: ", n); + + // JSONValue* p = n in this._j; + // if(p) + // { + // string finalV; + + // // todo: bail on unsupported types + + // // de-stringatize if it is a JSON string + // if(p.type() == JSONType.string) + // { + + // // finalV = p.str()[] + // } + // else + // { + // finalV = p.toString(); + // } + // // import std.string : strip + // // todo: value must be vconverte here + // writeln("finalV: ", finalV); + + // v = finalV; + // return true; + // } + // else + // { + // return false; + // } + + // pragma(msg, typeof(p)); + // } + // else + // { + // writeln("Access path: ", c); + // } + + // // todo: use dot-explorer on the JSONValue + // return true; } } import std.json : JSONValue; +import std.json : JSONType; +private string jsonNormal(JSONValue* i) +{ + if(i.type() == JSONType.string) + { + string s = i.str(); + return s; + } + // todo: disallow array types and object types + else + { + return i.toString(); + } +} + // todo: this belongs in the niknaks library private JSONValue* traverseTo(string path, JSONValue* start) { @@ -142,6 +172,6 @@ unittest // input JSON fieldsOf(cfg, new JSONProvider(json)); - // assert(cfg.name == "Tristan Brice Velloza Kildaire"); + assert(cfg.name == "Tristan Brice Velloza Kildaire"); assert(cfg.age == 25); } \ No newline at end of file From 4c010065b4f62c1b229e384aea7b07223cf2d5d2 Mon Sep 17 00:00:00 2001 From: "Tristan B. Velloza Kildaire" Date: Wed, 16 Jul 2025 22:52:10 +0200 Subject: [PATCH 04/22] JSONProvider - Removed old code --- source/hummus/providers/json.d | 46 ---------------------------------- 1 file changed, 46 deletions(-) diff --git a/source/hummus/providers/json.d b/source/hummus/providers/json.d index 4366bc6..132fc38 100644 --- a/source/hummus/providers/json.d +++ b/source/hummus/providers/json.d @@ -31,52 +31,6 @@ public class JSONProvider : Provider writeln("found JSON node toString(): ", s); v = s; return true; - - - // import std.stdio : writeln; - // string[] c; - // if(dotExtract(n, c) == false) - // { - // writeln("direct access for: ", n); - - // JSONValue* p = n in this._j; - // if(p) - // { - // string finalV; - - // // todo: bail on unsupported types - - // // de-stringatize if it is a JSON string - // if(p.type() == JSONType.string) - // { - - // // finalV = p.str()[] - // } - // else - // { - // finalV = p.toString(); - // } - // // import std.string : strip - // // todo: value must be vconverte here - // writeln("finalV: ", finalV); - - // v = finalV; - // return true; - // } - // else - // { - // return false; - // } - - // pragma(msg, typeof(p)); - // } - // else - // { - // writeln("Access path: ", c); - // } - - // // todo: use dot-explorer on the JSONValue - // return true; } } From 8bd7f485e13ce95eace76bdddf76c8aa22a55c28 Mon Sep 17 00:00:00 2001 From: "Tristan B. Velloza Kildaire" Date: Wed, 16 Jul 2025 23:08:16 +0200 Subject: [PATCH 05/22] json - More work being done on `traverseTo(string, JSONValue*)` --- source/hummus/providers/json.d | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/source/hummus/providers/json.d b/source/hummus/providers/json.d index 132fc38..a512469 100644 --- a/source/hummus/providers/json.d +++ b/source/hummus/providers/json.d @@ -51,14 +51,18 @@ private string jsonNormal(JSONValue* i) } } +import std.stdio; + // todo: this belongs in the niknaks library private JSONValue* traverseTo(string path, JSONValue* start) { + // todo: nullity check here on `start`? import std.string : split, indexOf; // no dots `.` in the name if(indexOf(path, ".") < 0) { + writeln("naaier: ", path); JSONValue* p = path in *start; return p; @@ -67,6 +71,7 @@ private JSONValue* traverseTo(string path, JSONValue* start) else { string[] cmps = split(path, "."); + writeln("cmps: ", cmps); JSONValue* root = cmps[0] in *start; @@ -103,10 +108,16 @@ private version(unittest) unittest { + struct Inner + { + int prop; + } + struct Basic { string name; ulong age; + Inner x; } auto cfg = Basic(); @@ -115,7 +126,8 @@ unittest string json = ` { "name": "Tristan Brice Velloza Kildaire", - "age": 25 + "age": 25, + } `; @@ -128,4 +140,5 @@ unittest assert(cfg.name == "Tristan Brice Velloza Kildaire"); assert(cfg.age == 25); + assert(cfg.x.prop == 2); } \ No newline at end of file From 404b76157e13c1273bb0bc03ab5bd9021e850b32 Mon Sep 17 00:00:00 2001 From: "Tristan B. Velloza Kildaire" Date: Fri, 18 Jul 2025 14:09:21 +0200 Subject: [PATCH 06/22] json - `traverseTo(string, JSONValue*)` now checks for `null` in `start` to prevent any signals being sent for SIGSEGV --- source/hummus/providers/json.d | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/source/hummus/providers/json.d b/source/hummus/providers/json.d index a512469..9816511 100644 --- a/source/hummus/providers/json.d +++ b/source/hummus/providers/json.d @@ -56,6 +56,11 @@ import std.stdio; // todo: this belongs in the niknaks library private JSONValue* traverseTo(string path, JSONValue* start) { + if(start is null) + { + return null; + } + // todo: nullity check here on `start`? import std.string : split, indexOf; From 0093424854405b8826cfa66fc0fb2a24fcb2fa79 Mon Sep 17 00:00:00 2001 From: "Tristan B. Velloza Kildaire" Date: Fri, 18 Jul 2025 14:11:25 +0200 Subject: [PATCH 07/22] JSONProvider - Updated the unittest --- source/hummus/providers/json.d | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/source/hummus/providers/json.d b/source/hummus/providers/json.d index 9816511..73ee41e 100644 --- a/source/hummus/providers/json.d +++ b/source/hummus/providers/json.d @@ -116,6 +116,7 @@ unittest struct Inner { int prop; + int k; } struct Basic @@ -132,7 +133,9 @@ unittest { "name": "Tristan Brice Velloza Kildaire", "age": 25, - + "x": { + "prop": 2 + } } `; @@ -146,4 +149,8 @@ unittest assert(cfg.name == "Tristan Brice Velloza Kildaire"); assert(cfg.age == 25); assert(cfg.x.prop == 2); + + // it is not present (in the JSON) hence it should + // never be set in our struct + assert(cfg.x.k == cfg.x.k.init); } \ No newline at end of file From 2980bebf2fd5cfcccafdfa0689a5d44f2c23b0fa Mon Sep 17 00:00:00 2001 From: "Tristan B. Velloza Kildaire" Date: Fri, 18 Jul 2025 14:13:24 +0200 Subject: [PATCH 08/22] json - Removed `dotExtract(...)` --- source/hummus/providers/json.d | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/source/hummus/providers/json.d b/source/hummus/providers/json.d index 73ee41e..d830b09 100644 --- a/source/hummus/providers/json.d +++ b/source/hummus/providers/json.d @@ -88,23 +88,6 @@ private JSONValue* traverseTo(string path, JSONValue* start) } } -private bool dotExtract(string i, ref string[] o) -{ - import std.string : split; - - auto cmps = split(i, "."); - - if(cmps.length == 1) - { - return false; - } - else - { - o = cmps; - return true; - } -} - private version(unittest) { import hummus.cfg : fieldsOf; From 991791821ee80df05e7333acab1376369a8b87d5 Mon Sep 17 00:00:00 2001 From: "Tristan B. Velloza Kildaire" Date: Fri, 18 Jul 2025 14:17:10 +0200 Subject: [PATCH 09/22] JSONProvider - When providing a value use the new `jsonNormal(..., ...)` API json - Updated how `jsonNormal(..., ...)` works --- source/hummus/providers/json.d | 33 ++++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/source/hummus/providers/json.d b/source/hummus/providers/json.d index d830b09..0d4c0a5 100644 --- a/source/hummus/providers/json.d +++ b/source/hummus/providers/json.d @@ -27,27 +27,42 @@ public class JSONProvider : Provider return false; } - string s = jsonNormal(f_node); - writeln("found JSON node toString(): ", s); - v = s; - return true; + string s_out; + if(jsonNormal(f_node, s_out)) + { + writeln("found JSON node toString(): ", s_out); + v = s_out; + return true; + } + else + { + return false; + } } } import std.json : JSONValue; import std.json : JSONType; -private string jsonNormal(JSONValue* i) + +private bool jsonNormal(JSONValue* i, ref string o) { - if(i.type() == JSONType.string) + auto t = i.type(); + if(t == JSONType.string) { - string s = i.str(); - return s; + o = i.str(); + return true; + } + else if(t == JSONType.ARRAY) + { + writeln("'", i, "' is an array type, these are unsupported"); + return false; } // todo: disallow array types and object types else { - return i.toString(); + o = i.toString(); + return true; } } From ec81888c917ef1fadb296dee934d566ab77157de Mon Sep 17 00:00:00 2001 From: "Tristan B. Velloza Kildaire" Date: Fri, 18 Jul 2025 14:27:34 +0200 Subject: [PATCH 10/22] lean up --- source/hummus/providers/json.d | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/source/hummus/providers/json.d b/source/hummus/providers/json.d index 0d4c0a5..f91bd69 100644 --- a/source/hummus/providers/json.d +++ b/source/hummus/providers/json.d @@ -127,6 +127,7 @@ unittest auto cfg = Basic(); writeln("Before provisioning: ", cfg); + // input json string json = ` { "name": "Tristan Brice Velloza Kildaire", @@ -137,9 +138,6 @@ unittest } `; - - - // todo: state what should be present // create a new JSON provider with the // input JSON fieldsOf(cfg, new JSONProvider(json)); From d56f14e5c5ffb05ba43eef85ea21df3c94cac49b Mon Sep 17 00:00:00 2001 From: "Tristan B. Velloza Kildaire" Date: Fri, 18 Jul 2025 15:58:54 +0200 Subject: [PATCH 11/22] JSONProvider - Updated unittest to add a JSON entity of type `JSONType.array` which should fail and not have any value set for it then because it is an unsupported type --- source/hummus/providers/json.d | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/source/hummus/providers/json.d b/source/hummus/providers/json.d index f91bd69..f18d66f 100644 --- a/source/hummus/providers/json.d +++ b/source/hummus/providers/json.d @@ -122,6 +122,7 @@ unittest string name; ulong age; Inner x; + string bad; } auto cfg = Basic(); @@ -134,7 +135,8 @@ unittest "age": 25, "x": { "prop": 2 - } + }, + "bad": ["", 2] } `; @@ -149,4 +151,5 @@ unittest // it is not present (in the JSON) hence it should // never be set in our struct assert(cfg.x.k == cfg.x.k.init); + assert(cfg.bad.length == 0); } \ No newline at end of file From 108cf66f2210d9993ce4dcef24dd6729776d1d59 Mon Sep 17 00:00:00 2001 From: "Tristan B. Velloza Kildaire" Date: Fri, 18 Jul 2025 16:36:49 +0200 Subject: [PATCH 12/22] Dub - Upgraded dependency `niknaks` to at least version `0.27.0` --- dub.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dub.json b/dub.json index d08a148..7e0a570 100644 --- a/dub.json +++ b/dub.json @@ -4,7 +4,7 @@ ], "copyright": "Copyright © 2025, Tristan Brice Velloza Kildaire", "dependencies": { - "niknaks": ">=0.26.2" + "niknaks": ">=0.27.0" }, "description": "Pluggable configuration engine", "license": "LGPL-2.0-only", @@ -18,4 +18,4 @@ "versions": ["DBG_DEBUG_LOGGING", "DBG_VERBOSE_LOGGING"] } } -} \ No newline at end of file +} From 86f569dc26eafc1f5d6f668376ee333a5820e1ed Mon Sep 17 00:00:00 2001 From: "Tristan B. Velloza Kildaire" Date: Fri, 18 Jul 2025 16:39:23 +0200 Subject: [PATCH 13/22] json - Now just use the niknaks package --- source/hummus/providers/json.d | 45 +++------------------------------- 1 file changed, 3 insertions(+), 42 deletions(-) diff --git a/source/hummus/providers/json.d b/source/hummus/providers/json.d index f18d66f..b2be9a8 100644 --- a/source/hummus/providers/json.d +++ b/source/hummus/providers/json.d @@ -1,10 +1,12 @@ module hummus.providers.json; import hummus.provider : Provider; +import std.json : JSONValue, JSONType; +import niknaks.json : traverseTo; public class JSONProvider : Provider { - import std.json : JSONValue, parseJSON, JSONException, JSONType; + import std.json : parseJSON, JSONException; private JSONValue _j; @@ -41,10 +43,6 @@ public class JSONProvider : Provider } } -import std.json : JSONValue; - -import std.json : JSONType; - private bool jsonNormal(JSONValue* i, ref string o) { auto t = i.type(); @@ -66,43 +64,6 @@ private bool jsonNormal(JSONValue* i, ref string o) } } -import std.stdio; - -// todo: this belongs in the niknaks library -private JSONValue* traverseTo(string path, JSONValue* start) -{ - if(start is null) - { - return null; - } - - // todo: nullity check here on `start`? - import std.string : split, indexOf; - - // no dots `.` in the name - if(indexOf(path, ".") < 0) - { - writeln("naaier: ", path); - JSONValue* p = path in *start; - - return p; - } - // if there are dots present like `x.y` - else - { - string[] cmps = split(path, "."); - writeln("cmps: ", cmps); - - JSONValue* root = cmps[0] in *start; - - // todo: range check? - string[] rem = cmps[1..$]; - import std.string : join; - - return traverseTo(join(rem, "."), root); - } -} - private version(unittest) { import hummus.cfg : fieldsOf; From 0c4a44e000b6d6b0da5dba3ab91dbe39c126f7c7 Mon Sep 17 00:00:00 2001 From: "Tristan B. Velloza Kildaire" Date: Fri, 18 Jul 2025 16:41:45 +0200 Subject: [PATCH 14/22] Update json.d --- source/hummus/providers/json.d | 3 +++ 1 file changed, 3 insertions(+) diff --git a/source/hummus/providers/json.d b/source/hummus/providers/json.d index b2be9a8..d7e6b73 100644 --- a/source/hummus/providers/json.d +++ b/source/hummus/providers/json.d @@ -4,6 +4,9 @@ import hummus.provider : Provider; import std.json : JSONValue, JSONType; import niknaks.json : traverseTo; +// todo: remove +import std.stdio; + public class JSONProvider : Provider { import std.json : parseJSON, JSONException; From 9aa70b516406a821dadf6871b3dc57ee05581ef7 Mon Sep 17 00:00:00 2001 From: Tristan Brice Velloza Kildaire Date: Wed, 26 Nov 2025 13:57:11 +0200 Subject: [PATCH 15/22] JSONProvider - DOcumented --- source/hummus/providers/json.d | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/source/hummus/providers/json.d b/source/hummus/providers/json.d index d7e6b73..e772688 100644 --- a/source/hummus/providers/json.d +++ b/source/hummus/providers/json.d @@ -7,6 +7,23 @@ import niknaks.json : traverseTo; // todo: remove import std.stdio; +/** + * A provider which will look for + * JSON key-value pairs based on + * matching them to the names of the + * fields in the provided struct. + * + * Struct fields which are of + * a struct-type themselves are + * supported and are filled + * whenever json such as `x.y` + * is encountered. This means `x` + * is some field in the "outer" + * struct. Then because we have + * `x.y`, `x` MUST be of a struct + * type. Then we access the field + * named `y` in this "inner" struct + */ public class JSONProvider : Provider { import std.json : parseJSON, JSONException; From 2699f86cb68f7e91bcc63893a48158a682589fbf Mon Sep 17 00:00:00 2001 From: Tristan Brice Velloza Kildaire Date: Wed, 26 Nov 2025 13:58:14 +0200 Subject: [PATCH 16/22] json - Documented package --- source/hummus/providers/json.d | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/source/hummus/providers/json.d b/source/hummus/providers/json.d index e772688..d2cb3a8 100644 --- a/source/hummus/providers/json.d +++ b/source/hummus/providers/json.d @@ -1,3 +1,14 @@ +/** + * JSON-based provider + * + * You should use this when + * you want to fill up your + * config with values stored + * in a string containing + * JSON-encoded data + * + * Authors: Tristan Brice Velloza Kildaire (deavmi) + */ module hummus.providers.json; import hummus.provider : Provider; From 84e3f4c2c222829be0a1046ef4c8248d34637208 Mon Sep 17 00:00:00 2001 From: Tristan Brice Velloza Kildaire Date: Wed, 26 Nov 2025 13:59:01 +0200 Subject: [PATCH 17/22] Repo - Added `test.sh` for easier testing --- test.sh | 2 ++ 1 file changed, 2 insertions(+) create mode 100755 test.sh diff --git a/test.sh b/test.sh new file mode 100755 index 0000000..75471ab --- /dev/null +++ b/test.sh @@ -0,0 +1,2 @@ +#!/bin/bash +V=1 I__Z=2 dub test From ab2813b28f29a4eed7241903324b778964b46131 Mon Sep 17 00:00:00 2001 From: Tristan Brice Velloza Kildaire Date: Wed, 26 Nov 2025 13:59:54 +0200 Subject: [PATCH 18/22] Repo - Updated testing instructions --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 88a43b2..942a839 100644 --- a/README.md +++ b/README.md @@ -85,7 +85,7 @@ a search for an environment variable named ## Testing In order to run the full test suite use the following -command: +command (or just `./test.sh`): ```d V=1 I__Z=2 dub test From 9f6d02871495ff5839d8565a863316e05880711c Mon Sep 17 00:00:00 2001 From: Tristan Brice Velloza Kildaire Date: Wed, 26 Nov 2025 14:03:35 +0200 Subject: [PATCH 19/22] Repo - Added information on `JSONProvider` - Added documentation links for both providers --- README.md | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/README.md b/README.md index 942a839..75c7a6d 100644 --- a/README.md +++ b/README.md @@ -80,6 +80,27 @@ A name like `root.a` will be translated to a search for an environment variable named `ROOT__A`. +Read the [API](https://hummus.dpldocs.info/hummus.providers.env.html). + +### `JSONProvider` + +A provider which will look for JSON key-value pairs +based on matching them to the names of the fields in +the provided struct. + +Struct fields which are of a struct-type themselves +are supported and are filled whenever json such as +`x.y` is encountered. This means `x` is some field +in the "outer" struct. Then because we have `x.y`, +`x` MUST be of a struct type. Then we access the field +named `y` in this "inner" struct. + +Hence a name like `root.a` will be translated to +an access at `jsonObject["root"].a` (where `jsonObject` +is the root document). + +Read the [API](https://hummus.dpldocs.info/hummus.providers.json.html). + # Development ## Testing From 15e57fc028086ed26d69d9b8d9d847a6c08f4cdd Mon Sep 17 00:00:00 2001 From: Tristan Brice Velloza Kildaire Date: Wed, 26 Nov 2025 14:10:32 +0200 Subject: [PATCH 20/22] Dub - Cleaned up Repo - Added information on build modes, like `debug` JSONProvider - Now uses `gogga` for logging when in `debug` build mode --- README.md | 7 +++++++ dub.json | 8 ++++---- source/hummus/providers/json.d | 14 ++++++++++---- 3 files changed, 21 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 75c7a6d..00f0194 100644 --- a/README.md +++ b/README.md @@ -118,6 +118,13 @@ is for the `EnvironmentProvider` which searches for environment variables, and in particular its unittest looks for those two. +### Build configurations + +1. `debug` + * In this mode the `gogga` logging library is + brought in and various flags are set to enable + verbose logging that aids debugging + ## License Licensed under the LGPL-2.0-only . diff --git a/dub.json b/dub.json index 7e0a570..ce31a7d 100644 --- a/dub.json +++ b/dub.json @@ -12,10 +12,10 @@ "targetType": "library", "configurations": { "debug": { - "dependencies": { - "gogga": ">=3.2.0" - }, - "versions": ["DBG_DEBUG_LOGGING", "DBG_VERBOSE_LOGGING"] + "dependencies": { + "gogga": ">=3.2.0" + }, + "versions": ["DBG_DEBUG_LOGGING", "DBG_VERBOSE_LOGGING"] } } } diff --git a/source/hummus/providers/json.d b/source/hummus/providers/json.d index d2cb3a8..cce9d39 100644 --- a/source/hummus/providers/json.d +++ b/source/hummus/providers/json.d @@ -15,8 +15,10 @@ import hummus.provider : Provider; import std.json : JSONValue, JSONType; import niknaks.json : traverseTo; -// todo: remove -import std.stdio; +version(unittest) +{ + import gogga.mixins; +} /** * A provider which will look for @@ -63,7 +65,9 @@ public class JSONProvider : Provider string s_out; if(jsonNormal(f_node, s_out)) { - writeln("found JSON node toString(): ", s_out); + version(unittest) + DEBUG("found JSON node toString(): ", s_out); + v = s_out; return true; } @@ -84,7 +88,9 @@ private bool jsonNormal(JSONValue* i, ref string o) } else if(t == JSONType.ARRAY) { - writeln("'", i, "' is an array type, these are unsupported"); + version(unittest) + DEBUG("'", i, "' is an array type, these are unsupported"); + return false; } // todo: disallow array types and object types From 81f615163bac03fd1d800478c00aafca44f4275d Mon Sep 17 00:00:00 2001 From: Tristan Brice Velloza Kildaire Date: Wed, 26 Nov 2025 14:12:51 +0200 Subject: [PATCH 21/22] docs --- source/hummus/providers/json.d | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/source/hummus/providers/json.d b/source/hummus/providers/json.d index cce9d39..ea6f28e 100644 --- a/source/hummus/providers/json.d +++ b/source/hummus/providers/json.d @@ -43,6 +43,17 @@ public class JSONProvider : Provider private JSONValue _j; + /** + * Constructs a new JSON provider + * with the given input JSON to + * parse + * + * Params: + * json = the input JSON + * Throws: + * JSONException when parsing + * fails + */ this(string json) { // todo: handle exceptions in non-library specific way From a7b6a14af5443b2b3be9ef51d8d470258fbc9327 Mon Sep 17 00:00:00 2001 From: Tristan Brice Velloza Kildaire Date: Wed, 26 Nov 2025 14:13:02 +0200 Subject: [PATCH 22/22] more --- source/hummus/providers/json.d | 3 +++ 1 file changed, 3 insertions(+) diff --git a/source/hummus/providers/json.d b/source/hummus/providers/json.d index ea6f28e..4242cd1 100644 --- a/source/hummus/providers/json.d +++ b/source/hummus/providers/json.d @@ -62,6 +62,9 @@ public class JSONProvider : Provider this._j = parseJSON(json); } + /** + * Implementation + */ protected bool provideImpl(string n, ref string v) { // todo: check return value for nullity