1 module text.json.ParserMarker;
2 
3 import funkwerk.stdx.data.json.lexer;
4 import funkwerk.stdx.data.json.parser;
5 import meta.never;
6 import std.json;
7 import std.typecons;
8 import text.json.Decode;
9 import text.json.JsonValueRange;
10 
11 /**
12  * This magic type represents an offset into a JSON parser input stream.
13  * While parsing a message, a value of this type is skipped.
14  * Later on, it can be parsed into a (now better known) type.
15  */
16 struct ParserMarker
17 {
18     alias StringStream = typeof(parseJSONStream!(LexOptions.noTrackLocation)(""));
19     alias JsonStream = JsonValueRange;
20 
21     private Nullable!StringStream stringStream;
22 
23     private Nullable!JsonStream jsonStream;
24 
25     invariant (this.stringStream.isNull != this.jsonStream.isNull);
26 
27     public this(this This)(const StringStream stringStream)
28     {
29         // It's impossible to construct an immutable(Nullable) directly. (?)
30         // However, JSONParserRange is @immutable.
31         this.stringStream = cast(typeof(this.stringStream)) stringStream.nullable;
32     }
33 
34     public this(JsonStream jsonStream)
35     {
36         this.jsonStream = jsonStream.nullable;
37     }
38 
39     public this(JSONValue value)
40     {
41         this.jsonStream = JsonStream(value).nullable;
42     }
43 
44     public T decode(T, alias transform = never)() const
45     {
46         import std.typecons: Yes;
47 
48         if (!this.stringStream.isNull)
49         {
50             StringStream stream = this.stringStream.get.dup;
51 
52             return decodeJson!(T, transform, Yes.logErrors)(stream, T.stringof);
53         }
54         else
55         {
56             JsonStream stream = this.jsonStream.get.dup;
57 
58             return decodeJson!(T, transform, Yes.logErrors)(stream, T.stringof);
59         }
60     }
61 }