Skip to content

Commit 2ce17b6

Browse files
committed
add DefaultTokenWriter; main changes
1 parent 082127b commit 2ce17b6

File tree

14 files changed

+2278
-66
lines changed

14 files changed

+2278
-66
lines changed

.sbtopts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
-Dsbt.io.implicit.relative.glob.conversion=allow

build.sbt

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,7 @@ lazy val `jackson-212` = project
225225
"com.fasterxml.jackson.core" % "jackson-core" % "2.12.7"
226226
)
227227
)
228-
.dependsOn(core)
228+
.dependsOn(core % "compile->compile;test->test")
229229

230230
lazy val `jackson-213` = project
231231
.in(jackson / "jackson-213")
@@ -239,7 +239,7 @@ lazy val `jackson-213` = project
239239
"com.fasterxml.jackson.core" % "jackson-core" % "2.13.5"
240240
)
241241
)
242-
.dependsOn(core)
242+
.dependsOn(core % "compile->compile;test->test")
243243

244244
lazy val `jackson-214` = project
245245
.in(jackson / "jackson-214")
@@ -253,7 +253,7 @@ lazy val `jackson-214` = project
253253
"com.fasterxml.jackson.core" % "jackson-core" % "2.14.3"
254254
)
255255
)
256-
.dependsOn(core)
256+
.dependsOn(core % "compile->compile;test->test")
257257

258258
lazy val `jackson-215` = project
259259
.in(jackson / "jackson-215")
@@ -267,7 +267,7 @@ lazy val `jackson-215` = project
267267
"com.fasterxml.jackson.core" % "jackson-core" % "2.15.4"
268268
)
269269
)
270-
.dependsOn(core)
270+
.dependsOn(core % "compile->compile;test->test")
271271

272272
lazy val `jackson-216` = project
273273
.in(jackson / "jackson-216")
@@ -281,7 +281,7 @@ lazy val `jackson-216` = project
281281
"com.fasterxml.jackson.core" % "jackson-core" % "2.16.2"
282282
)
283283
)
284-
.dependsOn(core)
284+
.dependsOn(core % "compile->compile;test->test")
285285

286286
lazy val `jackson-217` = project
287287
.in(jackson / "jackson-217")
@@ -295,7 +295,7 @@ lazy val `jackson-217` = project
295295
"com.fasterxml.jackson.core" % "jackson-core" % "2.17.3"
296296
)
297297
)
298-
.dependsOn(core)
298+
.dependsOn(core % "compile->compile;test->test")
299299

300300
lazy val `jackson-218` = project
301301
.in(jackson / "jackson-218")
@@ -309,7 +309,7 @@ lazy val `jackson-218` = project
309309
"com.fasterxml.jackson.core" % "jackson-core" % "2.18.3"
310310
)
311311
)
312-
.dependsOn(core)
312+
.dependsOn(core % "compile->compile;test->test")
313313

314314
lazy val benchmarks = project
315315
.in(modules / "benchmarks")
@@ -327,6 +327,8 @@ lazy val benchmarks = project
327327
"io.circe" %% "circe-jackson210" % "0.14.0",
328328
"dev.zio" %% "zio-json" % "0.7.1",
329329
"com.typesafe.play" %% "play-json" % "2.10.5",
330+
"com.github.plokhotnyuk.jsoniter-scala" %% "jsoniter-scala-core" % "2.33.1",
331+
"com.github.plokhotnyuk.jsoniter-scala" %% "jsoniter-scala-macros" % "2.33.1",
330332
"org.knowm.xchart" % "xchart" % "3.8.2" exclude ("de.erichseifert.vectorgraphics2d", "VectorGraphics2D") withSources ()
331333
),
332334
scalacOptions ++= {

modules/backend/jackson/jackson-backend/src/main/scala/tethys/jackson/JacksonTokenWriter.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,4 +92,7 @@ class JacksonTokenWriter(jsonGenerator: JsonGenerator) extends TokenWriter {
9292
override def close(): Unit = jsonGenerator.close()
9393

9494
override def flush(): Unit = jsonGenerator.flush()
95+
96+
override def result(): String =
97+
jsonGenerator.getOutputTarget.toString
9598
}

modules/backend/jackson/jackson-backend/src/main/scala/tethys/jackson/package.scala

Lines changed: 53 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,66 @@
11
package tethys
22

3-
import java.io.{Reader, Writer}
4-
5-
import com.fasterxml.jackson.core.JsonFactory
3+
import java.io.Reader
4+
import com.fasterxml.jackson.core.{
5+
JsonFactory,
6+
JsonFactoryBuilder,
7+
JsonGenerator
8+
}
69
import tethys.readers.{FieldName, ReaderError}
710
import tethys.readers.tokens.{TokenIterator, TokenIteratorProducer}
8-
import tethys.writers.tokens.{TokenWriter, TokenWriterProducer}
11+
import tethys.writers.tokens.{
12+
TokenWriter,
13+
TokenWriterConfig,
14+
TokenWriterProducer
15+
}
916

1017
package object jackson {
11-
lazy val defaultJsonFactory: JsonFactory = {
12-
val f = new JsonFactory()
13-
f.configure(JsonFactory.Feature.INTERN_FIELD_NAMES, false)
14-
f
18+
lazy val defaultJsonFactory: JsonFactory =
19+
new JsonFactoryBuilder()
20+
.configure(JsonFactory.Feature.INTERN_FIELD_NAMES, false)
21+
.build()
22+
23+
class JacksonTokenWriterProducer(
24+
jsonFactory: JsonFactory,
25+
// used for compatibility where tethys.jackson.pretty import is required
26+
modifyConfig: TokenWriterConfig => TokenWriterConfig
27+
) extends TokenWriterProducer {
28+
29+
private def updateGeneratorFromConfig(
30+
generator: JsonGenerator,
31+
config: TokenWriterConfig
32+
): JsonGenerator = {
33+
if (config == TokenWriterConfig.default)
34+
generator
35+
else {
36+
val first =
37+
if (config.indentionStep == 2)
38+
generator.useDefaultPrettyPrinter()
39+
else
40+
generator
41+
42+
val second =
43+
if (config.escapeUnicode)
44+
first.setHighestNonEscapedChar(127)
45+
else
46+
first
47+
second
48+
}
49+
}
50+
51+
override def produce(config: TokenWriterConfig): TokenWriter = {
52+
val generator = updateGeneratorFromConfig(
53+
jsonFactory.createGenerator(new java.io.StringWriter()),
54+
modifyConfig(config)
55+
)
56+
new JacksonTokenWriter(generator)
57+
}
1558
}
1659

1760
implicit def jacksonTokenWriterProducer(implicit
1861
jsonFactory: JsonFactory = defaultJsonFactory
19-
): TokenWriterProducer = new TokenWriterProducer {
20-
override def forWriter(writer: Writer): TokenWriter = {
21-
new JacksonTokenWriter(jsonFactory.createGenerator(writer))
22-
}
23-
}
62+
): JacksonTokenWriterProducer =
63+
new JacksonTokenWriterProducer(jsonFactory, identity)
2464

2565
implicit def jacksonTokenIteratorProducer(implicit
2666
jsonFactory: JsonFactory = defaultJsonFactory

modules/backend/jackson/jackson-backend/src/main/scala/tethys/jackson/pretty/package.scala

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,18 @@
11
package tethys.jackson
22

3-
import java.io.Writer
4-
53
import com.fasterxml.jackson.core.JsonFactory
64
import tethys.readers.tokens.TokenIteratorProducer
7-
import tethys.writers.tokens.{TokenWriter, TokenWriterProducer}
85

96
package object pretty {
7+
8+
@deprecated("Provide implicit TokenWriterConfig to `asJson` instead")
109
implicit def prettyJacksonTokenWriterProducer(implicit
1110
jsonFactory: JsonFactory = defaultJsonFactory
12-
): TokenWriterProducer = new TokenWriterProducer {
13-
override def forWriter(writer: Writer): TokenWriter = {
14-
new JacksonTokenWriter(
15-
jsonFactory.createGenerator(writer).useDefaultPrettyPrinter()
16-
)
17-
}
18-
}
11+
): JacksonTokenWriterProducer =
12+
new tethys.jackson.JacksonTokenWriterProducer(
13+
jsonFactory,
14+
modifyConfig = _.withDefaultPrettyPrinter
15+
)
1916

2017
implicit def jacksonTokenIteratorProducer(implicit
2118
jsonFactory: JsonFactory = defaultJsonFactory
Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
package tethys.commons
22

3-
import java.io.StringWriter
4-
53
import tethys.readers.FieldName
64
import tethys.readers.tokens.TokenIterator
7-
import tethys.writers.tokens.{TokenWriter, TokenWriterProducer}
5+
import tethys.writers.tokens.{
6+
TokenWriter,
7+
TokenWriterConfig,
8+
TokenWriterProducer
9+
}
810
import tethys.{JsonReader, JsonStreaming, JsonWriter}
911

1012
final case class RawJson(json: String)
@@ -16,16 +18,16 @@ object RawJson {
1618
}
1719

1820
implicit def rawJsonReader(implicit
19-
tokenWriterProducer: TokenWriterProducer
21+
tokenWriterProducer: TokenWriterProducer,
22+
tokenWriterConfig: TokenWriterConfig
2023
): JsonReader[RawJson] = new JsonReader[RawJson] {
2124
override def read(
2225
it: TokenIterator
2326
)(implicit fieldName: FieldName): RawJson = {
24-
val stringWriter = new StringWriter()
25-
val tokenWriter: TokenWriter = tokenWriterProducer.forWriter(stringWriter)
26-
JsonStreaming.streamValue(it, tokenWriter)
27-
tokenWriter.flush()
28-
RawJson(stringWriter.toString)
27+
val tokenWriter = tokenWriterProducer.produce(tokenWriterConfig)
28+
try JsonStreaming.streamValue(it, tokenWriter)
29+
finally tokenWriter.flush()
30+
RawJson(tokenWriter.result())
2931
}
3032
}
3133
}

modules/core/src/main/scala/tethys/package.scala

Lines changed: 26 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
1-
import java.io.{Reader, StringReader, StringWriter, Writer}
2-
3-
import tethys.readers.{FieldName, ReaderError}
41
import tethys.readers.tokens.{TokenIterator, TokenIteratorProducer}
5-
import tethys.writers.tokens.{TokenWriter, TokenWriterProducer}
2+
import tethys.readers.{FieldName, ReaderError}
3+
import tethys.writers.tokens.{
4+
TokenWriter,
5+
TokenWriterConfig,
6+
TokenWriterProducer
7+
}
68

9+
import java.io.{Reader, StringReader}
710
import scala.Specializable.Group
811

912
package object tethys {
@@ -12,40 +15,42 @@ package object tethys {
1215
(Byte, Short, Int, Long, Float, Double, Boolean)
1316
)
1417

15-
// given
16-
1718
implicit class JsonWriterOps[A](val a: A) extends AnyVal {
1819
def asJson(implicit
1920
jsonWriter: JsonWriter[A],
20-
tokenWriterProducer: TokenWriterProducer
21+
tokenWriterProducer: TokenWriterProducer,
22+
tokenWriterConfig: TokenWriterConfig
2123
): String = {
22-
val stringWriter = new StringWriter()
23-
writeJson(tokenWriterProducer.forWriter(stringWriter))
24-
stringWriter.toString
24+
val tokenWriter = tokenWriterProducer.produce(tokenWriterConfig)
25+
try jsonWriter.write(a, tokenWriter)
26+
finally tokenWriter.flush()
27+
tokenWriter.result()
2528
}
2629

2730
def asJsonWith(
2831
jsonWriter: JsonWriter[A]
29-
)(implicit tokenWriterProducer: TokenWriterProducer): String = {
30-
asJson(jsonWriter, tokenWriterProducer)
32+
)(implicit
33+
tokenWriterProducer: TokenWriterProducer,
34+
tokenWriterConfig: TokenWriterConfig
35+
): String = {
36+
val tokenWriter = tokenWriterProducer.produce(tokenWriterConfig)
37+
try
38+
jsonWriter.write(a, tokenWriter)
39+
finally
40+
tokenWriter.flush()
41+
tokenWriter.result()
3142
}
3243

3344
def writeJson(
3445
tokenWriter: TokenWriter
3546
)(implicit jsonWriter: JsonWriter[A]): Unit = {
36-
try jsonWriter.write(a, tokenWriter)
37-
finally {
47+
try
48+
jsonWriter.write(a, tokenWriter)
49+
finally
3850
tokenWriter.flush()
39-
}
4051
}
4152
}
4253

43-
implicit class WriterOps(val w: Writer) extends AnyVal {
44-
def toTokenWriter(implicit
45-
tokenWriterProducer: TokenWriterProducer
46-
): TokenWriter = tokenWriterProducer.forWriter(w)
47-
}
48-
4954
implicit class StringReaderOps(val json: String) extends AnyVal {
5055
def jsonAs[A](implicit
5156
jsonReader: JsonReader[A],
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package tethys.writers.tokens;
2+
3+
import java.lang.invoke.MethodHandles;
4+
import java.lang.invoke.VarHandle;
5+
import java.nio.ByteOrder;
6+
7+
class ByteArrayAccess { // FIXME: Use Java wrapper as w/a for missing support of @PolymorphicSignature methods in Scala 3, see: https://github.com/lampepfl/dotty/issues/11332
8+
private static final VarHandle VH_LONG =
9+
MethodHandles.byteArrayViewVarHandle(long[].class, ByteOrder.LITTLE_ENDIAN);
10+
private static final VarHandle VH_INT =
11+
MethodHandles.byteArrayViewVarHandle(int[].class, ByteOrder.LITTLE_ENDIAN);
12+
private static final VarHandle VH_SHORT =
13+
MethodHandles.byteArrayViewVarHandle(short[].class, ByteOrder.LITTLE_ENDIAN);
14+
private static final VarHandle VH_LONG_REVERSED =
15+
MethodHandles.byteArrayViewVarHandle(long[].class, ByteOrder.BIG_ENDIAN);
16+
private static final VarHandle VH_INT_REVERSED =
17+
MethodHandles.byteArrayViewVarHandle(int[].class, ByteOrder.BIG_ENDIAN);
18+
19+
static void setLong(byte[] buf, int pos, long value) {
20+
VH_LONG.set(buf, pos, value);
21+
}
22+
23+
static long getLong(byte[] buf, int pos) {
24+
return (long) VH_LONG.get(buf, pos);
25+
}
26+
27+
static void setInt(byte[] buf, int pos, int value) {
28+
VH_INT.set(buf, pos, value);
29+
}
30+
31+
static int getInt(byte[] buf, int pos) {
32+
return (int) VH_INT.get(buf, pos);
33+
}
34+
35+
static void setShort(byte[] buf, int pos, short value) {
36+
VH_SHORT.set(buf, pos, value);
37+
}
38+
39+
static void setLongReversed(byte[] buf, int pos, long value) {
40+
VH_LONG_REVERSED.set(buf, pos, value);
41+
}
42+
43+
static int getIntReversed(byte[] buf, int pos) {
44+
return (int) VH_INT_REVERSED.get(buf, pos);
45+
}
46+
}

0 commit comments

Comments
 (0)