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 }