-
-
Notifications
You must be signed in to change notification settings - Fork 134
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #826 from lolgab/support-scala-native
Support Scala Native
- Loading branch information
Showing
13 changed files
with
278 additions
and
112 deletions.
There are no files selected for viewing
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
File renamed without changes.
File renamed without changes.
113 changes: 113 additions & 0 deletions
113
play-json/js-native/src/main/scala/StaticBindingNonJvm.scala
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
/* | ||
* Copyright (C) 2009-2021 Lightbend Inc. <https://www.lightbend.com> | ||
*/ | ||
|
||
package play.api.libs.json | ||
|
||
import java.io.InputStreamReader | ||
|
||
private[json] object StaticBindingNonJvm { | ||
|
||
/** Parses a [[JsValue]] from a stream (assuming UTF-8). */ | ||
def parseJsValue(stream: java.io.InputStream): JsValue = { | ||
var in: InputStreamReader = null | ||
|
||
try { | ||
in = new java.io.InputStreamReader(stream, "UTF-8") | ||
val acc = new StringBuilder() | ||
val buf = Array.ofDim[Char](1024) | ||
|
||
@annotation.tailrec | ||
def read(): String = { | ||
val r = in.read(buf, 0, 1024) | ||
|
||
if (r == 1024) { | ||
acc ++= buf | ||
read() | ||
} else if (r > 0) { | ||
acc ++= buf.slice(0, r) | ||
read() | ||
} else acc.result() | ||
} | ||
|
||
StaticBinding.parseJsValue(read()) | ||
} catch { | ||
case err: Throwable => throw err | ||
} finally { | ||
if (in != null) in.close() | ||
} | ||
} | ||
|
||
def generateFromJsValue(jsValue: JsValue, escapeNonASCII: Boolean): String = | ||
fromJs(jsValue, escapeNonASCII, 0, _ => "") | ||
|
||
def prettyPrint(jsValue: JsValue): String = | ||
fromJs( | ||
jsValue, | ||
false, | ||
0, | ||
{ l => | ||
0.until(l * 2).map(_ => ' ').mkString | ||
}, | ||
newline = true, | ||
fieldValueSep = " : ", | ||
arraySep = ("[ ", ", ", " ]") | ||
) | ||
|
||
def toBytes(jsValue: JsValue): Array[Byte] = | ||
generateFromJsValue(jsValue, false).getBytes("UTF-8") | ||
|
||
def fromJs( | ||
jsValue: JsValue, | ||
escapeNonASCII: Boolean, | ||
ilevel: Int, | ||
indent: Int => String, | ||
newline: Boolean = false, | ||
fieldValueSep: String = ":", | ||
arraySep: (String, String, String) = ("[", ",", "]") | ||
): String = { | ||
def str = jsValue match { | ||
case JsNull => "null" | ||
case JsString(s) => StaticBinding.fromString(s, escapeNonASCII) | ||
case JsNumber(n) => n.toString | ||
case JsTrue => "true" | ||
case JsFalse => "false" | ||
|
||
case JsArray(items) => { | ||
val il = ilevel + 1 | ||
|
||
items | ||
.map(fromJs(_, escapeNonASCII, il, indent, newline, fieldValueSep, arraySep)) | ||
.mkString(arraySep._1, arraySep._2, arraySep._3) | ||
} | ||
|
||
case JsObject(fields) => { | ||
val il = ilevel + 1 | ||
val (before, after) = if (newline) { | ||
s"\n${indent(il)}" -> s"\n${indent(ilevel)}}" | ||
} else indent(il) -> "}" | ||
|
||
fields | ||
.map { case (k, v) => | ||
@inline def key = StaticBinding.fromString(k, escapeNonASCII) | ||
@inline def value = fromJs(v, escapeNonASCII, il, indent, newline, fieldValueSep, arraySep) | ||
|
||
s"$before$key$fieldValueSep$value" | ||
} | ||
.mkString("{", ",", after) | ||
} | ||
} | ||
|
||
str | ||
} | ||
|
||
def escapeStr(s: String): String = s.flatMap { c => | ||
val code = c.toInt | ||
|
||
if (code > 31 && code < 127 /* US-ASCII */ ) String.valueOf(c) | ||
else { | ||
def hexCode = code.toHexString.reverse.padTo(4, '0').reverse | ||
'\\' +: s"u${hexCode.toUpperCase}" | ||
} | ||
} | ||
} |
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
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
File renamed without changes.
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
/* | ||
* Copyright (C) 2009-2021 Lightbend Inc. <https://www.lightbend.com> | ||
*/ | ||
|
||
package play.api.libs.json | ||
|
||
import org.typelevel.jawn | ||
|
||
object StaticBinding { | ||
|
||
private implicit object JsValueFacade extends jawn.Facade.SimpleFacade[JsValue] { | ||
final def jfalse: JsValue = JsFalse | ||
final def jnull: JsValue = JsNull | ||
final def jnum(s: CharSequence, decIndex: Int, expIndex: Int): JsValue = JsNumber( | ||
new java.math.BigDecimal(s.toString) | ||
) | ||
final def jstring(s: CharSequence): JsValue = JsString(s.toString) | ||
final def jtrue: JsValue = JsTrue | ||
|
||
final def jarray(vs: List[JsValue]): JsValue = JsArray(vs) | ||
final def jobject(vs: Map[String, JsValue]): JsValue = JsObject(vs) | ||
} | ||
|
||
/** Parses a [[JsValue]] from raw data (assuming UTF-8). */ | ||
def parseJsValue(data: Array[Byte]): JsValue = | ||
new jawn.ByteArrayParser[JsValue](data).parse() | ||
|
||
/** Parses a [[JsValue]] from a string content. */ | ||
def parseJsValue(input: String): JsValue = | ||
jawn.Parser.parseUnsafe[JsValue](input) | ||
|
||
/** Parses a [[JsValue]] from a stream (assuming UTF-8). */ | ||
def parseJsValue(stream: java.io.InputStream): JsValue = | ||
StaticBindingNonJvm.parseJsValue(stream) | ||
|
||
def generateFromJsValue(jsValue: JsValue, escapeNonASCII: Boolean): String = | ||
StaticBindingNonJvm.generateFromJsValue(jsValue, escapeNonASCII) | ||
|
||
def prettyPrint(jsValue: JsValue): String = StaticBindingNonJvm.prettyPrint(jsValue) | ||
|
||
def toBytes(jsValue: JsValue): Array[Byte] = StaticBindingNonJvm.toBytes(jsValue) | ||
|
||
@inline private[json] def fromString(s: String, escapeNonASCII: Boolean): String = { | ||
def escaped(c: Char) = c match { | ||
case '\b' => "\\b" | ||
case '\f' => "\\f" | ||
case '\n' => "\\n" | ||
case '\r' => "\\r" | ||
case '\t' => "\\t" | ||
case '\\' => "\\\\" | ||
case '\"' => "\\\"" | ||
case c => c.toString | ||
} | ||
val stringified = if (s == null) "null" else s""""${s.flatMap(escaped)}"""" | ||
if (!escapeNonASCII) stringified else StaticBindingNonJvm.escapeStr(stringified) | ||
} | ||
|
||
} |
Oops, something went wrong.