Skip to content

Commit

Permalink
Update dependencies, add Scala Native support for circe integration, …
Browse files Browse the repository at this point in the history
…add jsoniter-scala integration
  • Loading branch information
plokhotnyuk committed Sep 19, 2022
1 parent 71f93a6 commit c2383d7
Show file tree
Hide file tree
Showing 6 changed files with 287 additions and 27 deletions.
38 changes: 19 additions & 19 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ jobs:
strategy:
matrix:
os: [ubuntu-latest]
scala: [2.12.16, 2.13.8, 3.1.3]
scala: [2.12.17, 2.13.8, 3.2.0]
java: [temurin@8]
project: [rootJS, rootJVM, rootNative]
runs-on: ${{ matrix.os }}
Expand Down Expand Up @@ -151,32 +151,32 @@ jobs:
~/Library/Caches/Coursier/v1
key: ${{ runner.os }}-sbt-cache-v2-${{ hashFiles('**/*.sbt') }}-${{ hashFiles('project/build.properties') }}

- name: Download target directories (2.12.16, rootJS)
- name: Download target directories (2.12.17, rootJS)
uses: actions/download-artifact@v2
with:
name: target-${{ matrix.os }}-${{ matrix.java }}-2.12.16-rootJS
name: target-${{ matrix.os }}-${{ matrix.java }}-2.12.17-rootJS

- name: Inflate target directories (2.12.16, rootJS)
- name: Inflate target directories (2.12.17, rootJS)
run: |
tar xf targets.tar
rm targets.tar
- name: Download target directories (2.12.16, rootJVM)
- name: Download target directories (2.12.17, rootJVM)
uses: actions/download-artifact@v2
with:
name: target-${{ matrix.os }}-${{ matrix.java }}-2.12.16-rootJVM
name: target-${{ matrix.os }}-${{ matrix.java }}-2.12.17-rootJVM

- name: Inflate target directories (2.12.16, rootJVM)
- name: Inflate target directories (2.12.17, rootJVM)
run: |
tar xf targets.tar
rm targets.tar
- name: Download target directories (2.12.16, rootNative)
- name: Download target directories (2.12.17, rootNative)
uses: actions/download-artifact@v2
with:
name: target-${{ matrix.os }}-${{ matrix.java }}-2.12.16-rootNative
name: target-${{ matrix.os }}-${{ matrix.java }}-2.12.17-rootNative

- name: Inflate target directories (2.12.16, rootNative)
- name: Inflate target directories (2.12.17, rootNative)
run: |
tar xf targets.tar
rm targets.tar
Expand Down Expand Up @@ -211,32 +211,32 @@ jobs:
tar xf targets.tar
rm targets.tar
- name: Download target directories (3.1.3, rootJS)
- name: Download target directories (3.2.0, rootJS)
uses: actions/download-artifact@v2
with:
name: target-${{ matrix.os }}-${{ matrix.java }}-3.1.3-rootJS
name: target-${{ matrix.os }}-${{ matrix.java }}-3.2.0-rootJS

- name: Inflate target directories (3.1.3, rootJS)
- name: Inflate target directories (3.2.0, rootJS)
run: |
tar xf targets.tar
rm targets.tar
- name: Download target directories (3.1.3, rootJVM)
- name: Download target directories (3.2.0, rootJVM)
uses: actions/download-artifact@v2
with:
name: target-${{ matrix.os }}-${{ matrix.java }}-3.1.3-rootJVM
name: target-${{ matrix.os }}-${{ matrix.java }}-3.2.0-rootJVM

- name: Inflate target directories (3.1.3, rootJVM)
- name: Inflate target directories (3.2.0, rootJVM)
run: |
tar xf targets.tar
rm targets.tar
- name: Download target directories (3.1.3, rootNative)
- name: Download target directories (3.2.0, rootNative)
uses: actions/download-artifact@v2
with:
name: target-${{ matrix.os }}-${{ matrix.java }}-3.1.3-rootNative
name: target-${{ matrix.os }}-${{ matrix.java }}-3.2.0-rootNative

- name: Inflate target directories (3.1.3, rootNative)
- name: Inflate target directories (3.2.0, rootNative)
run: |
tar xf targets.tar
rm targets.tar
Expand Down
25 changes: 19 additions & 6 deletions build.sbt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
val scala212 = "2.12.16"
val scala212 = "2.12.17"
val scala213 = "2.13.8"
val scala3 = "3.1.3"
val scala3 = "3.2.0"

ThisBuild / tlBaseVersion := "0.2"

Expand All @@ -17,11 +17,11 @@ ThisBuild / tlSonatypeUseLegacyHost := true
ThisBuild / crossScalaVersions := Seq(scala212, scala213, scala3)
ThisBuild / scalaVersion := scala213 // the default Scala

lazy val root = tlCrossRootProject.aggregate(core, circe, polyline).settings(name := "geo-scala")
lazy val root = tlCrossRootProject.aggregate(core, circe, jsoniterScala, polyline).settings(name := "geo-scala")

lazy val commonSettings = Seq(
libraryDependencies ++= Seq(
"org.scalatest" %%% "scalatest" % "3.2.12" % Test,
"org.scalatest" %%% "scalatest" % "3.2.13" % Test,
"org.scalatestplus" %%% "scalacheck-1-16" % "3.2.13.0" % Test,
"org.scalacheck" %%% "scalacheck" % "1.16.0" % Test
),
Expand All @@ -39,8 +39,8 @@ lazy val core = crossProject(JVMPlatform, JSPlatform, NativePlatform)
)
)

val circeVersion = "0.14.2"
lazy val circe = crossProject(JVMPlatform, JSPlatform)
val circeVersion = "0.14.3"
lazy val circe = crossProject(JVMPlatform, JSPlatform, NativePlatform)
.crossType(CrossType.Pure)
.in(file("circe"))
.dependsOn(core)
Expand All @@ -52,6 +52,19 @@ lazy val circe = crossProject(JVMPlatform, JSPlatform)
)
)

val jsoniterScalaVersion = "2.17.4"
lazy val jsoniterScala = crossProject(JVMPlatform, JSPlatform, NativePlatform)
.crossType(CrossType.Pure)
.in(file("jsoniter-scala"))
.dependsOn(core)
.settings(
commonSettings ++ Seq(
name := "geo-scala-jsoniter-scala",
libraryDependencies += "com.github.plokhotnyuk.jsoniter-scala" %%% "jsoniter-scala-core" % jsoniterScalaVersion,
libraryDependencies += "com.github.plokhotnyuk.jsoniter-scala" %%% "jsoniter-scala-macros" % jsoniterScalaVersion % Provided
)
)

lazy val polyline = crossProject(JVMPlatform, JSPlatform, NativePlatform)
.in(file("polyline"))
.dependsOn(core)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,11 @@ class CirceDecodingTests extends AnyFlatSpec with Matchers with EitherValues {
List(Feature(Json.obj("id" := 7), Point(Coordinate(12.3046875, 51.8357775))))
)
)
parser.decode[GeoJson[Json]](json) shouldBe Right(
FeatureCollection(
List(Feature(Json.obj("id" := 7), Point(Coordinate(12.3046875, 51.8357775))))
)
)
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
/*
* Copyright 2019 GHM Mobile Development GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.free2move.geoscala

import com.github.plokhotnyuk.jsoniter_scala.core._
import com.github.plokhotnyuk.jsoniter_scala.macros._

object jsoniter_scala {
// Uncomment for printing of generating codecs
// implicit val printCodec: CodecMakerConfig.PrintCodec = new CodecMakerConfig.PrintCodec {}

implicit val coordinateCodec: JsonValueCodec[Coordinate] =
new JsonValueCodec[Coordinate] {
override def decodeValue(in: JsonReader, default: Coordinate): Coordinate =
if (in.isNextToken('[')) {
val lon = in.readDouble()
if (!in.isNextToken(',')) in.commaError()
val lat = in.readDouble()
while (in.isNextToken(',')) in.skip()
if (!in.isCurrentToken(']')) in.arrayEndOrCommaError()
Coordinate(lon, lat)
} else in.readNullOrTokenError(default, '[')

override def encodeValue(x: Coordinate, out: JsonWriter): Unit = {
out.writeArrayStart()
out.writeVal(x.longitude)
out.writeVal(x.latitude)
out.writeArrayEnd()
}

override def nullValue: Coordinate = null
}

implicit val listOfCoordinatesCodec: JsonValueCodec[List[Coordinate]] =
JsonCodecMaker.make

implicit val listOfListOfCoordinatesCodec: JsonValueCodec[List[List[Coordinate]]] =
JsonCodecMaker.make

implicit val listOfListOfListOfCoordinatesCodec: JsonValueCodec[List[List[List[Coordinate]]]] =
JsonCodecMaker.make

implicit val pointCodec: JsonValueCodec[Point] =
makeGeometryCodec("Point", _.coordinates, Point)

implicit val multiPointCodec: JsonValueCodec[MultiPoint] =
makeGeometryCodec("MultiPoint", _.coordinates, MultiPoint)

implicit val lineStringCodec: JsonValueCodec[LineString] =
makeGeometryCodec("LineString", _.coordinates, LineString)

implicit val multiLineStringCodec: JsonValueCodec[MultiLineString] =
makeGeometryCodec("MultiLineString", _.coordinates, MultiLineString)

implicit val polygonCodec: JsonValueCodec[Polygon] =
makeGeometryCodec("Polygon", _.coordinates, Polygon)

implicit val multiPolygonCodec: JsonValueCodec[MultiPolygon] =
makeGeometryCodec("MultiPolygon", _.coordinates, MultiPolygon)

private def makeGeometryCodec[C: JsonValueCodec, G <: Geometry](`type`: String, coords: G => C, geom: C => G): JsonValueCodec[G] =
new JsonValueCodec[G] {
private val coordinatesCodec: JsonValueCodec[C] = implicitly[JsonValueCodec[C]]

override def decodeValue(in: JsonReader, default: G): G =
if (in.isNextToken('{')) {
var coordinates: C = coordinatesCodec.nullValue
var mask = 3
var len = -1
while (len < 0 || in.isNextToken(',')) {
len = in.readKeyAsCharBuf()
if (in.isCharBufEqualsTo(len, "type")) {
if ((mask & 0x1) != 0) mask ^= 0x1
else in.duplicatedKeyError(len)
len = in.readStringAsCharBuf()
if (!in.isCharBufEqualsTo(len, `type`)) in.discriminatorValueError("type")
} else if (in.isCharBufEqualsTo(len, "coordinates")) {
if ((mask & 0x2) != 0) mask ^= 0x2
else in.duplicatedKeyError(len)
coordinates = coordinatesCodec.decodeValue(in, coordinates)
} else in.skip()
}
geom(coordinates)
} else in.readNullOrTokenError(default, '}')

override def encodeValue(x: G, out: JsonWriter): Unit = {
out.writeObjectStart()
out.writeNonEscapedAsciiKey("type")
out.writeNonEscapedAsciiVal(`type`)
out.writeNonEscapedAsciiKey("coordinates")
coordinatesCodec.encodeValue(coords(x), out)
out.writeObjectEnd()
}

override def nullValue: G = null.asInstanceOf[G]
}

implicit val geometryCodec: JsonValueCodec[Geometry] =
JsonCodecMaker.make

implicit def featureCodec[P: JsonValueCodec]: JsonValueCodec[Feature[P]] =
JsonCodecMaker.make

implicit def featureCollectionCodec[P: JsonValueCodec]: JsonValueCodec[FeatureCollection[P]] =
JsonCodecMaker.make

implicit def geoJson[P: JsonValueCodec]: JsonValueCodec[GeoJson[P]] =
new JsonValueCodec[GeoJson[P]] {
private val fc: JsonValueCodec[Feature[P]] = featureCodec
private val fcc: JsonValueCodec[FeatureCollection[P]] = featureCollectionCodec

override def decodeValue(in: JsonReader, default: GeoJson[P]): GeoJson[P] = {
in.setMark()
if (in.isNextToken('{')) {
if (!in.skipToKey("type")) in.discriminatorError()
val len = in.readStringAsCharBuf()
in.rollbackToMark()
if (in.isCharBufEqualsTo(len, "Feature")) fc.decodeValue(in, fc.nullValue)
else if (in.isCharBufEqualsTo(len, "FeatureCollection")) fcc.decodeValue(in, fcc.nullValue)
else geometryCodec.decodeValue(in, geometryCodec.nullValue).asInstanceOf[GeoJson[P]]
} else {
val gj = in.readNullOrTokenError(default, '{')
in.rollbackToMark()
in.skip()
gj
}
}

override def encodeValue(x: GeoJson[P], out: JsonWriter): Unit =
x match {
case f: Feature[P] => fc.encodeValue(f, out)
case fc: FeatureCollection[P] => fcc.encodeValue(fc, out)
case _ => geometryCodec.encodeValue(x.asInstanceOf[Geometry], out)
}

override def nullValue: GeoJson[P] = null.asInstanceOf[GeoJson[P]]
}
}
Loading

0 comments on commit c2383d7

Please sign in to comment.