Last active
March 30, 2021 14:45
-
-
Save fanf/25cb3a4a74853a50ed8d78f5a5c2119d to your computer and use it in GitHub Desktop.
A value lexer for zio-json that stores said value in a frame buffer
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package zio.json.internal | |
object StoreLexer { | |
/* | |
* An utility method that store the next value in a string so that | |
* something else can parse it. | |
* Copied fomr zio.json.Lexer#skipValue | |
*/ | |
import zio.json.JsonDecoder._ | |
import zio.json.internal.Lexer._ | |
import scala.annotation.switch | |
private[this] val ull: Array[Char] = "ull".toCharArray | |
private[this] val alse: Array[Char] = "alse".toCharArray | |
private[this] val rue: Array[Char] = "rue".toCharArray | |
def storeValue(trace: List[JsonError], in: RetractReader, sb: StringBuilder): Unit = | |
(in.nextNonWhitespace(): @switch) match { | |
case 'n' => readChars(trace, in, ull, "null") ; sb.append("null") | |
case 'f' => readChars(trace, in, alse, "false") ; sb.append("false") | |
case 't' => readChars(trace, in, rue, "true") ; sb.append("true") | |
case '{' => | |
if (firstField(trace, in)) { | |
sb.append('{') | |
do { | |
Lexer.char(trace, in, '"') | |
storeString(trace, in, sb) | |
Lexer.char(trace, in, ':') ; sb.append(':') | |
storeValue(trace, in, sb) | |
} while (nextFieldStoreSep(trace, in, sb)) | |
} else { | |
sb.append("{}") | |
} | |
case '[' => | |
if (firstArrayElement(in)) { | |
sb.append('[') | |
do storeValue(trace, in, sb) while (nextArrayElementStoreSep(trace, in, sb)) | |
} else { | |
sb.append("[]") | |
} | |
case '"' => | |
storeString(trace, in, sb) | |
case c@('-' | '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9') => | |
sb.append(c) | |
storeNumber(in, sb) | |
case c => throw UnsafeJson(JsonError.Message(s"unexpected '$c'") :: trace) | |
} | |
def storeNumber(in: RetractReader, sb: StringBuilder): Unit = { | |
var cont = true | |
while (cont) { | |
val c = in.readChar() | |
cont = isNumber(c) | |
if(cont) { | |
sb.append(c) | |
} | |
} | |
in.retract() | |
} | |
def storeString(trace: List[JsonError], in: OneCharReader, sb: StringBuilder): Unit = { | |
sb.append('"') | |
val stream = new EscapedString(trace, in) | |
var i: Int = 0 | |
do { i = stream.read(); if(i!= -1) {sb.append(i.toChar)} } while (i != -1) | |
sb.append('"') | |
} | |
// True if we got a comma, and False for } | |
def nextFieldStoreSep(trace: List[JsonError], in: OneCharReader, sb: StringBuilder): Boolean = | |
(in.nextNonWhitespace(): @switch) match { | |
case ',' => sb.append(',') ; true | |
case '}' => sb.append('}') ; false | |
case c => | |
throw UnsafeJson( | |
JsonError.Message(s"expected ',' or '}' got '$c'") :: trace | |
) | |
} | |
def nextArrayElementStoreSep(trace: List[JsonError], in: OneCharReader, sb: StringBuilder): Boolean = | |
(in.nextNonWhitespace(): @switch) match { | |
case ',' => sb.append(','); true | |
case ']' => sb.append(']'); false | |
case c => | |
throw UnsafeJson( | |
JsonError.Message(s"expected ',' or ']' got '$c'") :: trace | |
) | |
} | |
// non-positional for performance | |
@inline private[this] def isNumber(c: Char): Boolean = | |
(c: @switch) match { | |
case '+' | '-' | '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' | '.' | 'e' | 'E' => | |
true | |
case _ => false | |
} | |
} | |
/* | |
use it with: | |
implicit val configDecoder: JsonDecoder[Config] = new JsonDecoder[Config] { | |
override def unsafeDecode(trace: List[JsonDecoder.JsonError], in: RetractReader): Config = { | |
val sb = new StringBuilder() | |
StoreLexer.storeValue(trace, in, sb) | |
GenericProperty.parseSerialisedConfig(sb.toString()) match { | |
case Right(value) => value | |
case Left(err) => throw UnsafeJson( | |
JsonError.Message(s"Cannot parse Config value: ${err.fullMsg}") :: trace | |
) | |
} | |
} | |
} | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment