Skip to content

Commit

Permalink
add crossbuild for scala native, update scala-js, update docs
Browse files Browse the repository at this point in the history
  • Loading branch information
colinrgodsey committed Mar 16, 2017
1 parent 034fdc8 commit b45b2dc
Show file tree
Hide file tree
Showing 10 changed files with 352 additions and 9 deletions.
4 changes: 3 additions & 1 deletion NOTICE
@@ -1,11 +1,13 @@
Scala-json is licensed under the conditions in the LICENSE document. The project includes
dependencies to other third-party projects that are obtained through SBT dependency management.
dependencies to other third-party projects that are obtained through SBT or other dependency management.

These projects are licensed as follows:

scala - (http://www.scala-lang.org/license.html)
scala-js - (https://github.com/scala-js/scala-js/blob/master/LICENSE)
scala-native - (https://github.com/scala-native/scala-native/blob/master/LICENSE)
jackson - (http://wiki.fasterxml.com/JacksonLicensing)
jansson - (https://github.com/akheron/jansson/blob/master/LICENSE)
tut - (https://github.com/tpolecat/tut/blob/master/LICENSE)
scalamacros.org paradise "macro paradise" - (https://github.com/scalamacros/paradise/blob/2.11.7/LICENSE.md)
utest - unknown license (https://github.com/lihaoyi/utest)
10 changes: 8 additions & 2 deletions README.md
Expand Up @@ -18,7 +18,8 @@ res0: json.JObject =
Features
-----
Compile time JSON marshalling of primitive values, case-classes, basic collections, and whatever you can imagine
for [scala](https://github.com/scala/scala) and [scala-js](https://github.com/scala-js/scala-js).
for [scala](https://github.com/scala/scala), [scala-native](https://github.com/scala-native/scala-native)
and [scala-js](https://github.com/scala-js/scala-js).
* Extensible accessor API. Serialize any type you want.
* Provides a useful JS-like AST for intermediate JSON data.
* Implicit [accessors](./docs/ACCESSORS.md) that chain to resolve Higher-Kind types (e.g. ```Option[T]```).
Expand All @@ -29,12 +30,15 @@ for [scala](https://github.com/scala/scala) and [scala-js](https://github.com/sc
* Enables use of normal looking scala structures with any previously existing JSON API.
* Produces pretty and human readable JSON from normal scala types.
* Supports [scala-js](https://github.com/scala-js/scala-js) so you can extend your models to the web.
* Supports [scala-native](https://github.com/scala-native/scala-native) so you can take your models everywhere else.
(requires [jansson](https://github.com/akheron/jansson)- available through apt, brew, etc)
* Enables you to create readable APIs that match existing/specific class structure.
* Exposes rich compile-time type info, more run-time type data than reflect could ever provide.
* Uses existing scala collection CanBuildFrom factories to support buildable collections.
* Provides support for unknown types (Any) via 'pickling' with a run-time class [registry](./docs/REGISTRY.md).
* Support for scala 2.10.x, 2.11.x, 2.12.0-M3.
* Support for scala-js 0.6.x.
* Support for scala-native 0.1.x.


Docs
Expand All @@ -57,7 +61,7 @@ resolvers += "mmreleases" at "https://artifactory.mediamath.com/artifactory/libs
//scala
libraryDependencies += "com.mediamath" %% "scala-json" % "1.0"

//or scala + scala-js
//or scala + scala-js/scala-native
libraryDependencies += "com.mediamath" %%% "scala-json" % "1.0"

//for @accessor annotation support
Expand All @@ -70,9 +74,11 @@ Dependencies

* [macro-paradise](http://docs.scala-lang.org/overviews/macros/paradise.html) 2.1.0+ required for @accessor annotation
* [jackson](https://github.com/FasterXML/jackson) for JVM JSON string parsing
* [jansson](https://github.com/akheron/jansson) for Scala Native JSON string parsing
* [µTest](https://github.com/lihaoyi/utest) for testing
* [tut](https://github.com/tpolecat/tut) for doc building

[Contributing](./docs/CONTRIBUTING.md)
---


9 changes: 8 additions & 1 deletion build.sbt
@@ -1,12 +1,19 @@
//shadow sbt-scalajs' crossProject and CrossType until Scala.js 1.0.0 is released
import sbtcrossproject.{crossProject, CrossType}

version in ThisBuild := "1.0"

lazy val json = crossProject.in(file("."))
lazy val json = crossProject(JSPlatform, JVMPlatform, NativePlatform)
.crossType(CrossType.Full)
.settings(ScalaJSON.commonSettings: _*)
.jvmSettings(ScalaJSON.jvmSettings: _*)
.jsSettings(ScalaJSON.jsSettings: _*)
.nativeSettings(Nil)
.in(file("."))

lazy val jsonJVM = json.jvm
lazy val jsonJS = json.js
lazy val jsonNative = json.native

lazy val tutProject = project.in(file("docs"))
.settings(ScalaJSON.tutSettings(jsonJVM): _*)
Expand Down
10 changes: 8 additions & 2 deletions docs/src/main/tut/README.md
Expand Up @@ -18,7 +18,8 @@ res0: json.JObject =
Features
-----
Compile time JSON marshalling of primitive values, case-classes, basic collections, and whatever you can imagine
for [scala](https://github.com/scala/scala) and [scala-js](https://github.com/scala-js/scala-js).
for [scala](https://github.com/scala/scala), [scala-native](https://github.com/scala-native/scala-native)
and [scala-js](https://github.com/scala-js/scala-js).
* Extensible accessor API. Serialize any type you want.
* Provides a useful JS-like AST for intermediate JSON data.
* Implicit [accessors](./docs/ACCESSORS.md) that chain to resolve Higher-Kind types (e.g. ```Option[T]```).
Expand All @@ -29,12 +30,15 @@ for [scala](https://github.com/scala/scala) and [scala-js](https://github.com/sc
* Enables use of normal looking scala structures with any previously existing JSON API.
* Produces pretty and human readable JSON from normal scala types.
* Supports [scala-js](https://github.com/scala-js/scala-js) so you can extend your models to the web.
* Supports [scala-native](https://github.com/scala-native/scala-native) so you can take your models everywhere else.
(requires [jansson](https://github.com/akheron/jansson)- available through apt, brew, etc)
* Enables you to create readable APIs that match existing/specific class structure.
* Exposes rich compile-time type info, more run-time type data than reflect could ever provide.
* Uses existing scala collection CanBuildFrom factories to support buildable collections.
* Provides support for unknown types (Any) via 'pickling' with a run-time class [registry](./docs/REGISTRY.md).
* Support for scala 2.10.x, 2.11.x, 2.12.0-M3.
* Support for scala-js 0.6.x.
* Support for scala-native 0.1.x.


Docs
Expand All @@ -57,7 +61,7 @@ resolvers += "mmreleases" at "https://artifactory.mediamath.com/artifactory/libs
//scala
libraryDependencies += "com.mediamath" %% "scala-json" % "__VER__"

//or scala + scala-js
//or scala + scala-js/scala-native
libraryDependencies += "com.mediamath" %%% "scala-json" % "__VER__"

//for @accessor annotation support
Expand All @@ -70,8 +74,10 @@ Dependencies

* [macro-paradise](http://docs.scala-lang.org/overviews/macros/paradise.html) 2.1.0+ required for @accessor annotation
* [jackson](https://github.com/FasterXML/jackson) for JVM JSON string parsing
* [jansson](https://github.com/akheron/jansson) for Scala Native JSON string parsing
* [µTest](https://github.com/lihaoyi/utest) for testing
* [tut](https://github.com/tpolecat/tut) for doc building

[Contributing](./docs/CONTRIBUTING.md)
---

124 changes: 124 additions & 0 deletions native/src/main/scala/json/internal/JanssonDeserializer.scala
@@ -0,0 +1,124 @@
/*
* Copyright 2017 MediaMath, Inc
*
* 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 json.internal

import scalanative.native

import janssonConstants._
import jansson._
import native._
import json._

object JanssonDeserializer {
def throwError(error: Ptr[json_error_t]): Unit = {
val line = !error._1
val column = !error._2
val position = !error._3
val source = native fromCString error._4.cast[CString]
val text = native fromCString error._5.cast[CString]

val errString = s"$text. line: $line col: $column pos: $position: $source"

sys.error(errString)
}

def parseString(jsonString: String): JValue = {
val error = stackalloc[json_error_t]

val decoded = json_loads(native toCString jsonString, JSON_DECODE_ANY, error)

if(decoded == null)
throwError(error)

val output = nativeToJSON(decoded)

json_delete(decoded)

output
}

def serializeString(str: String): String = {
val encoded = json_string(native toCString str)

val outNative = json_dumps(encoded, JSON_ENCODE_ANY)

json_delete(encoded)

require(outNative != null)

val out = native fromCString outNative

native.stdlib.free(outNative)

out
}

def nativeToJSON(x: Ptr[json_t]): JValue = {
val typ: json_type = !x._1

typ match {
case JSON_OBJECT =>
//TODO: is this messing with ordering?
JObject.empty ++ ObjectIterator(x)
case JSON_ARRAY =>
JArray.empty ++ ArrayIterator(x)
case JSON_STRING =>
JString(native fromCString json_string_value(x))
case JSON_INTEGER =>
JNumber(json_number_value(x))
case JSON_REAL =>
JNumber(json_number_value(x))
case JSON_TRUE =>
JTrue
case JSON_FALSE =>
JFalse
case JSON_NULL =>
JNull
}
}

case class ObjectIterator(obj: Ptr[json_t]) extends Iterator[(String, JValue)] {
private var itr = json_object_iter(obj)

def hasNext: Boolean = itr != null

def next(): (String, JValue) = {
val key: CString = json_object_iter_key(itr)
val value: Ptr[json_t] = json_object_iter_value(itr)

itr = json_object_iter_next(obj, itr)

(native fromCString key, nativeToJSON(value))
}
}

case class ArrayIterator(arr: Ptr[json_t]) extends Iterator[JValue] {
private var idx = 0

override val size = json_array_size(arr).toInt

def hasNext: Boolean = idx < size

def next(): JValue = {
val res = nativeToJSON(json_array_get(arr, idx))

idx += 1

res
}
}
}
101 changes: 101 additions & 0 deletions native/src/main/scala/json/internal/jansson.scala
@@ -0,0 +1,101 @@
/*
* Copyright 2017 MediaMath, Inc
*
* 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 json.internal

import scala.scalanative.native
import native._
import Nat._

@native.link("jansson")
@native.extern
object jansson {
type JSON_ERROR_TEXT_LENGTH = Digit[_1, Digit[_6, _0]]
type JSON_ERROR_SOURCE_LENGTH = Digit[_8, _0]

type json_type = CInt //enum

type json_error_t = CStruct5[
CInt, //line
CInt, //column
CInt, //position,
CArray[CChar, JSON_ERROR_SOURCE_LENGTH], //source
CArray[CChar, JSON_ERROR_TEXT_LENGTH] //text
]

type json_t = CStruct2[
json_type, //type
CSize //refcount
]

type json_iter = Ptr[Byte]

def json_loads(input: CString, flags: CSize, error: Ptr[json_error_t]): Ptr[json_t] = extern

def json_dumps(json: Ptr[json_t], flags: CSize): CString = extern

def json_delete(json: Ptr[json_t]): Unit = extern

def json_array_size(json: Ptr[json_t]): CSize = extern

def json_array_get(json: Ptr[json_t], index: CSize): Ptr[json_t] = extern

def json_object_iter(obj: Ptr[json_t]): json_iter = extern

def json_object_iter_at(obj: Ptr[json_t], key: CString): json_iter = extern

def json_object_iter_next(obj: Ptr[json_t], itr: json_iter): json_iter = extern

def json_object_iter_key(itr: json_iter): CString = extern

def json_object_iter_value(itr: json_iter): Ptr[json_t] = extern

def json_number_value(num: Ptr[json_t]): Double = extern

def json_string(value: CString): Ptr[json_t] = extern

def json_string_value(str: Ptr[json_t]): CString = extern
}

object janssonConstants {
//json_type
val JSON_OBJECT = 0
val JSON_ARRAY = 1
val JSON_STRING = 2
val JSON_INTEGER = 3
val JSON_REAL = 4
val JSON_TRUE = 5
val JSON_FALSE = 6
val JSON_NULL = 7

//flags
val JSON_REJECT_DUPLICATES = 0x1
val JSON_DISABLE_EOF_CHECK = 0x2
val JSON_DECODE_ANY = 0x4
val JSON_DECODE_INT_AS_REAL = 0x8
val JSON_ALLOW_NUL = 0x10

val JSON_MAX_INDENT = 0x1F
def JSON_INDENT(n: Int) = ((n) & JSON_MAX_INDENT)
val JSON_COMPACT = 0x20
val JSON_ENSURE_ASCII = 0x40
val JSON_SORT_KEYS = 0x80
val JSON_PRESERVE_ORDER = 0x100
val JSON_ENCODE_ANY = 0x200
val JSON_ESCAPE_SLASH = 0x400
def JSON_REAL_PRECISION(n: Int) = (((n) & 0x1F) << 11)
val JSON_EMBED = 0x10000
}

0 comments on commit b45b2dc

Please sign in to comment.