From a2ff390cea9f0e92dc0805ebeff05b9e70b264ba Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Wed, 24 Jan 2024 19:12:21 +0100 Subject: [PATCH 01/38] Update sbt-osgi to 0.9.11 (#796) --- project/plugins.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/plugins.sbt b/project/plugins.sbt index 7f518088..33b8bfb5 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -4,7 +4,7 @@ addSbtPlugin("com.github.sbt" % "sbt-pgp" % "2.2.1") // java.lang.NoClassDefFoundError: Could not initialize class org.jacoco.core.internal.flow.ClassProbesAdapter //addSbtPlugin("com.github.sbt" % "sbt-jacoco" % "3.3.0") addSbtPlugin("org.xerial.sbt" % "sbt-jcheckstyle" % "0.2.1") -addSbtPlugin("com.github.sbt" % "sbt-osgi" % "0.9.10") +addSbtPlugin("com.github.sbt" % "sbt-osgi" % "0.9.11") addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.5.2") addSbtPlugin("com.github.sbt" % "sbt-dynver" % "5.0.1") From 964800ec3abc4f2f64b0598083cbf0ef51c0a3a5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 24 Jan 2024 10:12:30 -0800 Subject: [PATCH 02/38] Bump actions/cache from 3 to 4 (#795) Bumps [actions/cache](https://github.com/actions/cache) from 3 to 4. - [Release notes](https://github.com/actions/cache/releases) - [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md) - [Commits](https://github.com/actions/cache/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/cache dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/CI.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 7732559a..7ff24e9b 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -36,7 +36,7 @@ jobs: with: distribution: 'zulu' java-version: '21' - - uses: actions/cache@v3 + - uses: actions/cache@v4 with: path: ~/.cache key: ${{ runner.os }}-jdk21-${{ hashFiles('**/*.sbt') }} @@ -54,7 +54,7 @@ jobs: with: distribution: 'zulu' java-version: '17' - - uses: actions/cache@v3 + - uses: actions/cache@v4 with: path: ~/.cache key: ${{ runner.os }}-jdk17-${{ hashFiles('**/*.sbt') }} @@ -72,7 +72,7 @@ jobs: with: distribution: 'zulu' java-version: '11' - - uses: actions/cache@v3 + - uses: actions/cache@v4 with: path: ~/.cache key: ${{ runner.os }}-jdk11-${{ hashFiles('**/*.sbt') }} @@ -90,7 +90,7 @@ jobs: with: distribution: 'zulu' java-version: '8' - - uses: actions/cache@v3 + - uses: actions/cache@v4 with: path: ~/.cache key: ${{ runner.os }}-jdk8-${{ hashFiles('**/*.sbt') }} From a1796398f331a8f94316a3ab9e52e0869d3ddb62 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 5 Feb 2024 16:34:11 -0800 Subject: [PATCH 03/38] Bump release-drafter/release-drafter from 5 to 6 (#798) Bumps [release-drafter/release-drafter](https://github.com/release-drafter/release-drafter) from 5 to 6. - [Release notes](https://github.com/release-drafter/release-drafter/releases) - [Commits](https://github.com/release-drafter/release-drafter/compare/v5...v6) --- updated-dependencies: - dependency-name: release-drafter/release-drafter dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/release-drafter.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release-drafter.yml b/.github/workflows/release-drafter.yml index 42d3901d..f77373a9 100644 --- a/.github/workflows/release-drafter.yml +++ b/.github/workflows/release-drafter.yml @@ -22,6 +22,6 @@ jobs: runs-on: ubuntu-latest steps: # Drafts your next Release notes as Pull Requests are merged into "master" - - uses: release-drafter/release-drafter@v5 + - uses: release-drafter/release-drafter@v6 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From fd386138fec6f2a469516dcb2b113dc66e6247e8 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Tue, 6 Feb 2024 01:34:21 +0100 Subject: [PATCH 04/38] Update sbt-osgi to 0.10.0 (#797) --- project/plugins.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/plugins.sbt b/project/plugins.sbt index 33b8bfb5..aa41287b 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -4,7 +4,7 @@ addSbtPlugin("com.github.sbt" % "sbt-pgp" % "2.2.1") // java.lang.NoClassDefFoundError: Could not initialize class org.jacoco.core.internal.flow.ClassProbesAdapter //addSbtPlugin("com.github.sbt" % "sbt-jacoco" % "3.3.0") addSbtPlugin("org.xerial.sbt" % "sbt-jcheckstyle" % "0.2.1") -addSbtPlugin("com.github.sbt" % "sbt-osgi" % "0.9.11") +addSbtPlugin("com.github.sbt" % "sbt-osgi" % "0.10.0") addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.5.2") addSbtPlugin("com.github.sbt" % "sbt-dynver" % "5.0.1") From 750a07c73329f9ab1e1b6d55c6b199093df9be0b Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Wed, 21 Feb 2024 18:21:12 +0100 Subject: [PATCH 05/38] Update airframe-json, airspec to 24.1.2 (#801) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 3bfc9133..e4bf7dad 100644 --- a/build.sbt +++ b/build.sbt @@ -5,7 +5,7 @@ Global / concurrentRestrictions := Seq( Tags.limit(Tags.Test, 1) ) -val AIRFRAME_VERSION = "24.1.1" +val AIRFRAME_VERSION = "24.1.2" // Use dynamic snapshot version strings for non tagged versions ThisBuild / dynverSonatypeSnapshots := true From b917abce56c83beca17a28e6a9f005206b4a9a48 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Wed, 6 Mar 2024 06:11:47 +0100 Subject: [PATCH 06/38] Update sbt to 1.9.9 (#803) --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index e5ca1ff5..b089b60c 100755 --- a/project/build.properties +++ b/project/build.properties @@ -1,2 +1,2 @@ -sbt.version=1.9.8 +sbt.version=1.9.9 From 55d774a0976ce7bad569deabdb88c62b336880fb Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Wed, 6 Mar 2024 06:12:06 +0100 Subject: [PATCH 07/38] Update airframe-json, airspec to 24.3.0 (#807) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index e4bf7dad..69cac77a 100644 --- a/build.sbt +++ b/build.sbt @@ -5,7 +5,7 @@ Global / concurrentRestrictions := Seq( Tags.limit(Tags.Test, 1) ) -val AIRFRAME_VERSION = "24.1.2" +val AIRFRAME_VERSION = "24.3.0" // Use dynamic snapshot version strings for non tagged versions ThisBuild / dynverSonatypeSnapshots := true From 690f5effcb731353a28b34cdd441eddd1931564e Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Wed, 24 Apr 2024 00:23:06 +0200 Subject: [PATCH 08/38] Update airframe-json, airspec to 24.4.2 (#817) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 69cac77a..35eb5564 100644 --- a/build.sbt +++ b/build.sbt @@ -5,7 +5,7 @@ Global / concurrentRestrictions := Seq( Tags.limit(Tags.Test, 1) ) -val AIRFRAME_VERSION = "24.3.0" +val AIRFRAME_VERSION = "24.4.2" // Use dynamic snapshot version strings for non tagged versions ThisBuild / dynverSonatypeSnapshots := true From 5f273cf4f6ff1ec327701fef613dabc968230ac7 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Wed, 24 Apr 2024 00:23:16 +0200 Subject: [PATCH 09/38] Update scalacheck to 1.17.1 (#815) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 35eb5564..4987196b 100644 --- a/build.sbt +++ b/build.sbt @@ -87,7 +87,7 @@ lazy val msgpackCore = Project(id = "msgpack-core", base = file("msgpack-core")) "org.wvlet.airframe" %% "airframe-json" % AIRFRAME_VERSION % "test", "org.wvlet.airframe" %% "airspec" % AIRFRAME_VERSION % "test", // Add property testing support with forAll methods - "org.scalacheck" %% "scalacheck" % "1.17.0" % "test", + "org.scalacheck" %% "scalacheck" % "1.17.1" % "test", // For performance comparison with msgpack v6 "org.msgpack" % "msgpack" % "0.6.12" % "test", // For integration test with Akka From d13e6b10e648fbe41bf3f6aa555aa11fb7168a9a Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Wed, 24 Apr 2024 00:23:25 +0200 Subject: [PATCH 10/38] Update scala-collection-compat to 2.12.0 (#814) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 4987196b..c63a53fa 100644 --- a/build.sbt +++ b/build.sbt @@ -92,7 +92,7 @@ lazy val msgpackCore = Project(id = "msgpack-core", base = file("msgpack-core")) "org.msgpack" % "msgpack" % "0.6.12" % "test", // For integration test with Akka "com.typesafe.akka" %% "akka-actor" % "2.6.20" % "test", - "org.scala-lang.modules" %% "scala-collection-compat" % "2.11.0" % "test" + "org.scala-lang.modules" %% "scala-collection-compat" % "2.12.0" % "test" ) ) From 6d0516ec9e53d269f1f208d5af99f439bfda8e5f Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Thu, 25 Apr 2024 19:56:54 +0200 Subject: [PATCH 11/38] Update airframe-json, airspec to 24.4.3 (#820) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index c63a53fa..a1c02e10 100644 --- a/build.sbt +++ b/build.sbt @@ -5,7 +5,7 @@ Global / concurrentRestrictions := Seq( Tags.limit(Tags.Test, 1) ) -val AIRFRAME_VERSION = "24.4.2" +val AIRFRAME_VERSION = "24.4.3" // Use dynamic snapshot version strings for non tagged versions ThisBuild / dynverSonatypeSnapshots := true From 577c474a9d069ce855772a13c56a7c8b3bbe2d5c Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Thu, 25 Apr 2024 19:57:01 +0200 Subject: [PATCH 12/38] Update scalacheck to 1.18.0 (#819) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index a1c02e10..fa2cb782 100644 --- a/build.sbt +++ b/build.sbt @@ -87,7 +87,7 @@ lazy val msgpackCore = Project(id = "msgpack-core", base = file("msgpack-core")) "org.wvlet.airframe" %% "airframe-json" % AIRFRAME_VERSION % "test", "org.wvlet.airframe" %% "airspec" % AIRFRAME_VERSION % "test", // Add property testing support with forAll methods - "org.scalacheck" %% "scalacheck" % "1.17.1" % "test", + "org.scalacheck" %% "scalacheck" % "1.18.0" % "test", // For performance comparison with msgpack v6 "org.msgpack" % "msgpack" % "0.6.12" % "test", // For integration test with Akka From 141f66dd615e797c96113169371d1767b251a0ae Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Thu, 25 Apr 2024 19:57:20 +0200 Subject: [PATCH 13/38] Update jackson-databind to 2.16.2 (#811) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index fa2cb782..6042dbcd 100644 --- a/build.sbt +++ b/build.sbt @@ -109,7 +109,7 @@ lazy val msgpackJackson = "org.msgpack.jackson.dataformat" ), libraryDependencies ++= Seq( - "com.fasterxml.jackson.core" % "jackson-databind" % "2.16.1", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.16.2", junitInterface, "org.apache.commons" % "commons-math3" % "3.6.1" % "test" ), From 29a44afbc1cbbe7be771897f322cb0b5649dee0b Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Wed, 8 May 2024 02:46:22 +0200 Subject: [PATCH 14/38] Update sbt to 1.10.0 (#823) --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index b089b60c..16c8f5b8 100755 --- a/project/build.properties +++ b/project/build.properties @@ -1,2 +1,2 @@ -sbt.version=1.9.9 +sbt.version=1.10.0 From 50cf4098c398026a5afe8fd11f43f96f3756cf91 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Wed, 8 May 2024 02:46:33 +0200 Subject: [PATCH 15/38] Update airframe-json, airspec to 24.5.0 (#824) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 6042dbcd..a456a489 100644 --- a/build.sbt +++ b/build.sbt @@ -5,7 +5,7 @@ Global / concurrentRestrictions := Seq( Tags.limit(Tags.Test, 1) ) -val AIRFRAME_VERSION = "24.4.3" +val AIRFRAME_VERSION = "24.5.0" // Use dynamic snapshot version strings for non tagged versions ThisBuild / dynverSonatypeSnapshots := true From fedf7ac8c57f4e73b74d30980472a468bbc0a715 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Tue, 18 Jun 2024 20:01:42 +0200 Subject: [PATCH 16/38] Update airframe-json, airspec to 24.5.2 (#826) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index a456a489..0c9f0898 100644 --- a/build.sbt +++ b/build.sbt @@ -5,7 +5,7 @@ Global / concurrentRestrictions := Seq( Tags.limit(Tags.Test, 1) ) -val AIRFRAME_VERSION = "24.5.0" +val AIRFRAME_VERSION = "24.5.2" // Use dynamic snapshot version strings for non tagged versions ThisBuild / dynverSonatypeSnapshots := true From a3590929a04c91b93db1c9be51589b3ca5275e69 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Tue, 9 Jul 2024 20:31:44 +0200 Subject: [PATCH 17/38] Update airframe-json, airspec to 24.7.0 (#829) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 0c9f0898..5ecd8cdc 100644 --- a/build.sbt +++ b/build.sbt @@ -5,7 +5,7 @@ Global / concurrentRestrictions := Seq( Tags.limit(Tags.Test, 1) ) -val AIRFRAME_VERSION = "24.5.2" +val AIRFRAME_VERSION = "24.7.0" // Use dynamic snapshot version strings for non tagged versions ThisBuild / dynverSonatypeSnapshots := true From abdab0deae9d0c52742f7271a85db53c8dc382ef Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Tue, 16 Jul 2024 19:42:36 +0200 Subject: [PATCH 18/38] Update sbt to 1.10.1 (#831) --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index 16c8f5b8..74d800f2 100755 --- a/project/build.properties +++ b/project/build.properties @@ -1,2 +1,2 @@ -sbt.version=1.10.0 +sbt.version=1.10.1 From ba386c3a7c4ad1e973510a44d6c6a2652675d331 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Mon, 22 Jul 2024 20:03:33 +0200 Subject: [PATCH 19/38] Update airframe-json, airspec to 24.7.1 (#832) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 5ecd8cdc..4087d23b 100644 --- a/build.sbt +++ b/build.sbt @@ -5,7 +5,7 @@ Global / concurrentRestrictions := Seq( Tags.limit(Tags.Test, 1) ) -val AIRFRAME_VERSION = "24.7.0" +val AIRFRAME_VERSION = "24.7.1" // Use dynamic snapshot version strings for non tagged versions ThisBuild / dynverSonatypeSnapshots := true From 72ead7ea34e0171de1c82d43b3faeeb33ca999fc Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Thu, 12 Sep 2024 19:55:52 +0200 Subject: [PATCH 20/38] Update airframe-json, airspec to 24.9.0 (#837) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 4087d23b..b57a6e10 100644 --- a/build.sbt +++ b/build.sbt @@ -5,7 +5,7 @@ Global / concurrentRestrictions := Seq( Tags.limit(Tags.Test, 1) ) -val AIRFRAME_VERSION = "24.7.1" +val AIRFRAME_VERSION = "24.9.0" // Use dynamic snapshot version strings for non tagged versions ThisBuild / dynverSonatypeSnapshots := true From 4fb85a52caf17703053351e786fc688d4cad6aca Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Thu, 26 Sep 2024 01:33:40 +0200 Subject: [PATCH 21/38] Update sbt to 1.10.2 (#839) --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index 74d800f2..a1ff42a6 100755 --- a/project/build.properties +++ b/project/build.properties @@ -1,2 +1,2 @@ -sbt.version=1.10.1 +sbt.version=1.10.2 From 1b51be899ad61b1a1e7cae9d8ae9ca478274b99b Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Thu, 26 Sep 2024 01:33:49 +0200 Subject: [PATCH 22/38] Update scalacheck to 1.18.1 (#840) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index b57a6e10..a102c0c4 100644 --- a/build.sbt +++ b/build.sbt @@ -87,7 +87,7 @@ lazy val msgpackCore = Project(id = "msgpack-core", base = file("msgpack-core")) "org.wvlet.airframe" %% "airframe-json" % AIRFRAME_VERSION % "test", "org.wvlet.airframe" %% "airspec" % AIRFRAME_VERSION % "test", // Add property testing support with forAll methods - "org.scalacheck" %% "scalacheck" % "1.18.0" % "test", + "org.scalacheck" %% "scalacheck" % "1.18.1" % "test", // For performance comparison with msgpack v6 "org.msgpack" % "msgpack" % "0.6.12" % "test", // For integration test with Akka From 6b26ad66c869493b960a8ab7a28571068ac982f2 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Tue, 8 Oct 2024 02:21:04 +0200 Subject: [PATCH 23/38] Update airframe-json, airspec to 24.9.3 (#844) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index a102c0c4..f76b603a 100644 --- a/build.sbt +++ b/build.sbt @@ -5,7 +5,7 @@ Global / concurrentRestrictions := Seq( Tags.limit(Tags.Test, 1) ) -val AIRFRAME_VERSION = "24.9.0" +val AIRFRAME_VERSION = "24.9.3" // Use dynamic snapshot version strings for non tagged versions ThisBuild / dynverSonatypeSnapshots := true From 76bc7d0caac175cf55db47c2a76c2b0af9689283 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Tue, 8 Oct 2024 02:23:43 +0200 Subject: [PATCH 24/38] Update sbt-pgp to 2.3.0 (#845) --- project/plugins.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/plugins.sbt b/project/plugins.sbt index aa41287b..5d631aae 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,5 +1,5 @@ addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "3.10.0") -addSbtPlugin("com.github.sbt" % "sbt-pgp" % "2.2.1") +addSbtPlugin("com.github.sbt" % "sbt-pgp" % "2.3.0") // TODO: Fixes jacoco error: // java.lang.NoClassDefFoundError: Could not initialize class org.jacoco.core.internal.flow.ClassProbesAdapter //addSbtPlugin("com.github.sbt" % "sbt-jacoco" % "3.3.0") From c48f6594accf3467ce1e97f42a16dd788733ae01 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Thu, 10 Oct 2024 21:45:04 +0200 Subject: [PATCH 25/38] Update sbt-sonatype to 3.12.0 (#846) --- project/plugins.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/plugins.sbt b/project/plugins.sbt index 5d631aae..34401fa5 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,4 +1,4 @@ -addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "3.10.0") +addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "3.12.0") addSbtPlugin("com.github.sbt" % "sbt-pgp" % "2.3.0") // TODO: Fixes jacoco error: // java.lang.NoClassDefFoundError: Could not initialize class org.jacoco.core.internal.flow.ClassProbesAdapter From 933b0f2b717f7835095fef2a8b499ed42409ea98 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Wed, 30 Oct 2024 22:53:06 +0100 Subject: [PATCH 26/38] Update sbt, scripted-plugin to 1.10.4 (#852) --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index a1ff42a6..3769c4af 100755 --- a/project/build.properties +++ b/project/build.properties @@ -1,2 +1,2 @@ -sbt.version=1.10.2 +sbt.version=1.10.4 From 093837ea3f96ec12a0c0475b67f83c4a7c929d7d Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Wed, 30 Oct 2024 22:53:19 +0100 Subject: [PATCH 27/38] Update airframe-json, airspec to 24.10.0 (#850) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index f76b603a..c94b9c3a 100644 --- a/build.sbt +++ b/build.sbt @@ -5,7 +5,7 @@ Global / concurrentRestrictions := Seq( Tags.limit(Tags.Test, 1) ) -val AIRFRAME_VERSION = "24.9.3" +val AIRFRAME_VERSION = "24.10.0" // Use dynamic snapshot version strings for non tagged versions ThisBuild / dynverSonatypeSnapshots := true From 067e0d9b05905805dc65f19cbb6c6da7dae7bbb0 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Wed, 30 Oct 2024 22:53:28 +0100 Subject: [PATCH 28/38] Update sbt-sonatype to 3.12.2 (#847) --- project/plugins.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/plugins.sbt b/project/plugins.sbt index 34401fa5..3df907dc 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,4 +1,4 @@ -addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "3.12.0") +addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "3.12.2") addSbtPlugin("com.github.sbt" % "sbt-pgp" % "2.3.0") // TODO: Fixes jacoco error: // java.lang.NoClassDefFoundError: Could not initialize class org.jacoco.core.internal.flow.ClassProbesAdapter From b6bae5b101ba021f2a139d8dbb60160a75822d7c Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Wed, 30 Oct 2024 22:53:38 +0100 Subject: [PATCH 29/38] Update sbt-dynver to 5.1.0 (#848) --- project/plugins.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/plugins.sbt b/project/plugins.sbt index 3df907dc..912d52f1 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -6,6 +6,6 @@ addSbtPlugin("com.github.sbt" % "sbt-pgp" % "2.3.0") addSbtPlugin("org.xerial.sbt" % "sbt-jcheckstyle" % "0.2.1") addSbtPlugin("com.github.sbt" % "sbt-osgi" % "0.10.0") addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.5.2") -addSbtPlugin("com.github.sbt" % "sbt-dynver" % "5.0.1") +addSbtPlugin("com.github.sbt" % "sbt-dynver" % "5.1.0") scalacOptions ++= Seq("-deprecation", "-feature") From ba0c44fe09313431db0c08fd8f98496cbed3aae7 Mon Sep 17 00:00:00 2001 From: kenji yoshida <6b656e6a69@gmail.com> Date: Tue, 5 Nov 2024 04:56:37 +0900 Subject: [PATCH 30/38] internal: Avoid deprecated `java.net.URL` constructor (#853) avoid deprecated java.net.URL constructor --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index c94b9c3a..ff396aa2 100644 --- a/build.sbt +++ b/build.sbt @@ -15,7 +15,7 @@ ThisBuild / dynverSeparator := "-" val buildSettings = Seq[Setting[_]]( organization := "org.msgpack", organizationName := "MessagePack", - organizationHomepage := Some(new URL("http://msgpack.org/")), + organizationHomepage := Some(url("http://msgpack.org/")), description := "MessagePack for Java", scalaVersion := "2.13.12", Test / logBuffered := false, From 84fd19761feeb5ec073ed238fb00498bd04994bd Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Tue, 5 Nov 2024 21:16:37 +0100 Subject: [PATCH 31/38] Update sbt, scripted-plugin to 1.10.5 (#854) --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index 3769c4af..30c85e4f 100755 --- a/project/build.properties +++ b/project/build.properties @@ -1,2 +1,2 @@ -sbt.version=1.10.4 +sbt.version=1.10.5 From 5161c53c1d3d7760bff84287ecae98c72b9190ea Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Sat, 30 Nov 2024 16:35:36 +0900 Subject: [PATCH 32/38] Bump the version of `jackson-databind` (#858) --- build.sbt | 2 +- .../jackson/dataformat/JsonArrayFormat.java | 18 ------------------ 2 files changed, 1 insertion(+), 19 deletions(-) diff --git a/build.sbt b/build.sbt index ff396aa2..4a4b2301 100644 --- a/build.sbt +++ b/build.sbt @@ -109,7 +109,7 @@ lazy val msgpackJackson = "org.msgpack.jackson.dataformat" ), libraryDependencies ++= Seq( - "com.fasterxml.jackson.core" % "jackson-databind" % "2.16.2", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.18.2", junitInterface, "org.apache.commons" % "commons-math3" % "3.6.1" % "test" ), diff --git a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/JsonArrayFormat.java b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/JsonArrayFormat.java index 9711e1b8..39155030 100644 --- a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/JsonArrayFormat.java +++ b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/JsonArrayFormat.java @@ -2,7 +2,6 @@ import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.databind.introspect.Annotated; -import com.fasterxml.jackson.databind.introspect.AnnotatedClass; import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector; import static com.fasterxml.jackson.annotation.JsonFormat.Shape.ARRAY; @@ -33,21 +32,4 @@ public JsonFormat.Value findFormat(Annotated ann) return ARRAY_FORMAT; } - - /** - * Defines that unknown properties will be ignored, and won't fail the un-marshalling process. - * Happens in case of de-serialization of a payload that contains more properties than the actual - * value type - */ - @Override - public Boolean findIgnoreUnknownProperties(AnnotatedClass ac) - { - // If the entity contains JsonIgnoreProperties annotation, give it higher priority. - final Boolean precedenceIgnoreUnknownProperties = super.findIgnoreUnknownProperties(ac); - if (precedenceIgnoreUnknownProperties != null) { - return precedenceIgnoreUnknownProperties; - } - - return true; - } } From 33ba1ea6260230a5d46ccd2fe1f64071733eee30 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Wed, 11 Dec 2024 19:05:02 +0100 Subject: [PATCH 33/38] Update sbt-pgp to 2.3.1 (#862) --- project/plugins.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/plugins.sbt b/project/plugins.sbt index 912d52f1..e702479f 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,5 +1,5 @@ addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "3.12.2") -addSbtPlugin("com.github.sbt" % "sbt-pgp" % "2.3.0") +addSbtPlugin("com.github.sbt" % "sbt-pgp" % "2.3.1") // TODO: Fixes jacoco error: // java.lang.NoClassDefFoundError: Could not initialize class org.jacoco.core.internal.flow.ClassProbesAdapter //addSbtPlugin("com.github.sbt" % "sbt-jacoco" % "3.3.0") From c7907ad886cbf734ae18131ac0553d51baf5965b Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Wed, 11 Dec 2024 19:05:11 +0100 Subject: [PATCH 34/38] Update airframe-json, airspec to 24.12.1 (#860) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 4a4b2301..ff74b955 100644 --- a/build.sbt +++ b/build.sbt @@ -5,7 +5,7 @@ Global / concurrentRestrictions := Seq( Tags.limit(Tags.Test, 1) ) -val AIRFRAME_VERSION = "24.10.0" +val AIRFRAME_VERSION = "24.12.1" // Use dynamic snapshot version strings for non tagged versions ThisBuild / dynverSonatypeSnapshots := true From d2b328e105b567d394d4e58b8d87fdad392db874 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Wed, 11 Dec 2024 19:05:21 +0100 Subject: [PATCH 35/38] Update sbt, scripted-plugin to 1.10.6 (#859) --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index 30c85e4f..e0a0e7d1 100755 --- a/project/build.properties +++ b/project/build.properties @@ -1,2 +1,2 @@ -sbt.version=1.10.5 +sbt.version=1.10.6 From e03d60d0808a021273bdab3a43e59330f6eb8e5c Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Thu, 19 Dec 2024 18:32:44 +0100 Subject: [PATCH 36/38] Update airframe-json, airspec to 24.12.2 (#863) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index ff74b955..31280a69 100644 --- a/build.sbt +++ b/build.sbt @@ -5,7 +5,7 @@ Global / concurrentRestrictions := Seq( Tags.limit(Tags.Test, 1) ) -val AIRFRAME_VERSION = "24.12.1" +val AIRFRAME_VERSION = "24.12.2" // Use dynamic snapshot version strings for non tagged versions ThisBuild / dynverSonatypeSnapshots := true From 56c0e5ac95c8037958b29eaf53fe591978e20c7d Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Tue, 24 Dec 2024 00:23:58 +0100 Subject: [PATCH 37/38] Update sbt, scripted-plugin to 1.10.7 (#865) --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index e0a0e7d1..8fc29878 100755 --- a/project/build.properties +++ b/project/build.properties @@ -1,2 +1,2 @@ -sbt.version=1.10.6 +sbt.version=1.10.7 From 59219838ffb6236eca84601dad1dd267541c070b Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Sun, 5 Jan 2025 19:48:24 +0900 Subject: [PATCH 38/38] Improve the performance of `jackson-dataformat-msgpack` (#866) * Improve the perf of msgpack-jackson * Refactoring --- .../ExtensionTypeCustomDeserializers.java | 10 +- .../msgpack/jackson/dataformat/JavaInfo.java | 41 ++ .../dataformat/MessagePackExtensionType.java | 5 +- .../dataformat/MessagePackFactory.java | 20 +- .../dataformat/MessagePackGenerator.java | 646 +++++++++++------- .../dataformat/MessagePackKeySerializer.java | 3 +- .../jackson/dataformat/MessagePackParser.java | 277 +++----- .../dataformat/MessagePackReadContext.java | 269 ++++++++ .../MessagePackSerializedString.java | 8 +- .../MessagePackDataformatForPojoTest.java | 36 +- .../MessagePackDataformatTestBase.java | 44 +- .../dataformat/MessagePackGeneratorTest.java | 49 +- ...essagePackDataformatPojoBenchmarkTest.java | 28 +- 13 files changed, 946 insertions(+), 490 deletions(-) create mode 100644 msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/JavaInfo.java create mode 100644 msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackReadContext.java diff --git a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/ExtensionTypeCustomDeserializers.java b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/ExtensionTypeCustomDeserializers.java index ae2e6353..aa587975 100644 --- a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/ExtensionTypeCustomDeserializers.java +++ b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/ExtensionTypeCustomDeserializers.java @@ -35,15 +35,7 @@ public ExtensionTypeCustomDeserializers(ExtensionTypeCustomDeserializers src) public void addCustomDeser(byte type, final Deser deser) { - deserTable.put(type, new Deser() - { - @Override - public Object deserialize(byte[] data) - throws IOException - { - return deser.deserialize(data); - } - }); + deserTable.put(type, deser); } public Deser getDeser(byte type) diff --git a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/JavaInfo.java b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/JavaInfo.java new file mode 100644 index 00000000..f5fda8c2 --- /dev/null +++ b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/JavaInfo.java @@ -0,0 +1,41 @@ +// +// MessagePack for Java +// +// 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 org.msgpack.jackson.dataformat; + +import java.lang.reflect.Field; +import java.util.function.Supplier; + +public final class JavaInfo +{ + static final Supplier STRING_VALUE_FIELD_IS_CHARS; + static { + boolean stringValueFieldIsChars = false; + try { + Field stringValueField = String.class.getDeclaredField("value"); + stringValueFieldIsChars = stringValueField.getType() == char[].class; + } + catch (NoSuchFieldException ignored) { + } + if (stringValueFieldIsChars) { + STRING_VALUE_FIELD_IS_CHARS = () -> true; + } + else { + STRING_VALUE_FIELD_IS_CHARS = () -> false; + } + } + + private JavaInfo() {} +} diff --git a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackExtensionType.java b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackExtensionType.java index 00b4f7de..e11c2cd0 100644 --- a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackExtensionType.java +++ b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackExtensionType.java @@ -1,7 +1,6 @@ package org.msgpack.jackson.dataformat; import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.annotation.JsonSerialize; @@ -52,7 +51,7 @@ public boolean equals(Object o) @Override public int hashCode() { - int result = (int) type; + int result = type; result = 31 * result + Arrays.hashCode(data); return result; } @@ -61,7 +60,7 @@ public static class Serializer extends JsonSerializer { @Override public void serialize(MessagePackExtensionType value, JsonGenerator gen, SerializerProvider serializers) - throws IOException, JsonProcessingException + throws IOException { if (gen instanceof MessagePackGenerator) { MessagePackGenerator msgpackGenerator = (MessagePackGenerator) gen; diff --git a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackFactory.java b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackFactory.java index 1e7acc5e..bb5064f1 100644 --- a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackFactory.java +++ b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackFactory.java @@ -18,7 +18,6 @@ import com.fasterxml.jackson.core.JsonEncoding; import com.fasterxml.jackson.core.JsonFactory; import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.core.JsonParseException; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.io.IOContext; import org.msgpack.core.MessagePack; @@ -97,14 +96,13 @@ public JsonGenerator createGenerator(File f, JsonEncoding enc) @Override public JsonGenerator createGenerator(Writer w) - throws IOException { throw new UnsupportedOperationException(); } @Override public JsonParser createParser(byte[] data) - throws IOException, JsonParseException + throws IOException { IOContext ioContext = _createContext(data, false); return _createParser(data, 0, data.length, ioContext); @@ -112,7 +110,7 @@ public JsonParser createParser(byte[] data) @Override public JsonParser createParser(InputStream in) - throws IOException, JsonParseException + throws IOException { IOContext ioContext = _createContext(in, false); return _createParser(in, ioContext); @@ -131,7 +129,7 @@ protected MessagePackParser _createParser(InputStream in, IOContext ctxt) @Override protected JsonParser _createParser(byte[] data, int offset, int len, IOContext ctxt) - throws IOException, JsonParseException + throws IOException { if (offset != 0 || len != data.length) { data = Arrays.copyOfRange(data, offset, offset + len); @@ -155,12 +153,6 @@ MessagePack.PackerConfig getPackerConfig() return packerConfig; } - @VisibleForTesting - boolean isReuseResourceInGenerator() - { - return reuseResourceInGenerator; - } - @VisibleForTesting boolean isReuseResourceInParser() { @@ -178,4 +170,10 @@ public String getFormatName() { return "msgpack"; } + + @Override + public boolean canHandleBinaryNatively() + { + return true; + } } diff --git a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackGenerator.java b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackGenerator.java index 96aa6a06..11aba6e5 100644 --- a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackGenerator.java +++ b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackGenerator.java @@ -16,14 +16,14 @@ package org.msgpack.jackson.dataformat; import com.fasterxml.jackson.core.Base64Variant; -import com.fasterxml.jackson.core.JsonGenerationException; import com.fasterxml.jackson.core.ObjectCodec; import com.fasterxml.jackson.core.SerializableString; import com.fasterxml.jackson.core.base.GeneratorBase; import com.fasterxml.jackson.core.io.SerializedString; -import com.fasterxml.jackson.core.json.JsonWriteContext; import org.msgpack.core.MessagePack; import org.msgpack.core.MessagePacker; +import org.msgpack.core.annotations.Nullable; +import org.msgpack.core.buffer.MessageBufferOutput; import org.msgpack.core.buffer.OutputStreamBufferOutput; import java.io.ByteArrayOutputStream; @@ -33,73 +33,170 @@ import java.math.BigInteger; import java.nio.ByteBuffer; import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; -import java.util.LinkedList; import java.util.List; +import static org.msgpack.jackson.dataformat.JavaInfo.STRING_VALUE_FIELD_IS_CHARS; + public class MessagePackGenerator extends GeneratorBase { - private static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); + private static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8; + private static final int IN_ROOT = 0; + private static final int IN_OBJECT = 1; + private static final int IN_ARRAY = 2; private final MessagePacker messagePacker; - private static ThreadLocal messageBufferOutputHolder = new ThreadLocal(); + private static final ThreadLocal messageBufferOutputHolder = new ThreadLocal<>(); private final OutputStream output; private final MessagePack.PackerConfig packerConfig; - private LinkedList stack; - private StackItem rootStackItem; - private abstract static class StackItem + private int currentParentElementIndex = -1; + private int currentState = IN_ROOT; + private final List nodes; + private boolean isElementsClosed = false; + + private static final class AsciiCharString + { + public final byte[] bytes; + + public AsciiCharString(byte[] bytes) + { + this.bytes = bytes; + } + } + + private abstract static class Node + { + // Root containers have -1. + final int parentIndex; + + public Node(int parentIndex) + { + this.parentIndex = parentIndex; + } + + abstract void incrementChildCount(); + + abstract int currentStateAsParent(); + } + + private abstract static class NodeContainer extends Node { - protected List objectKeys = new ArrayList(); - protected List objectValues = new ArrayList(); + // Only for containers. + int childCount; + + public NodeContainer(int parentIndex) + { + super(parentIndex); + } + + @Override + void incrementChildCount() + { + childCount++; + } + } - abstract void addKey(Object key); + private static final class NodeArray extends NodeContainer + { + public NodeArray(int parentIndex) + { + super(parentIndex); + } - void addValue(Object value) + @Override + int currentStateAsParent() { - objectValues.add(value); + return IN_ARRAY; } + } - abstract List getKeys(); + private static final class NodeObject extends NodeContainer + { + public NodeObject(int parentIndex) + { + super(parentIndex); + } - List getValues() + @Override + int currentStateAsParent() { - return objectValues; + return IN_OBJECT; } } - private static class StackItemForObject - extends StackItem + private static final class NodeEntryInArray extends Node { + final Object value; + + public NodeEntryInArray(int parentIndex, Object value) + { + super(parentIndex); + this.value = value; + } + @Override - void addKey(Object key) + void incrementChildCount() { - objectKeys.add(key); + throw new UnsupportedOperationException(); } @Override - List getKeys() + int currentStateAsParent() { - return objectKeys; + throw new UnsupportedOperationException(); } } - private static class StackItemForArray - extends StackItem + private static final class NodeEntryInObject extends Node { + final Object key; + // Lazily initialized. + Object value; + + public NodeEntryInObject(int parentIndex, Object key) + { + super(parentIndex); + this.key = key; + } + @Override - void addKey(Object key) + void incrementChildCount() { - throw new IllegalStateException("This method shouldn't be called"); + assert value instanceof NodeContainer; + ((NodeContainer) value).childCount++; } @Override - List getKeys() + int currentStateAsParent() { - throw new IllegalStateException("This method shouldn't be called"); + if (value instanceof NodeObject) { + return IN_OBJECT; + } + else if (value instanceof NodeArray) { + return IN_ARRAY; + } + else { + throw new AssertionError(); + } } } + // This is an internal constructor for nested serialization. + private MessagePackGenerator( + int features, + ObjectCodec codec, + OutputStream out, + MessagePack.PackerConfig packerConfig) + { + super(features, codec); + this.output = out; + this.messagePacker = packerConfig.newPacker(out); + this.packerConfig = packerConfig; + this.nodes = new ArrayList<>(); + } + public MessagePackGenerator( int features, ObjectCodec codec, @@ -110,7 +207,16 @@ public MessagePackGenerator( { super(features, codec); this.output = out; + this.messagePacker = packerConfig.newPacker(getMessageBufferOutputForOutputStream(out, reuseResourceInGenerator)); + this.packerConfig = packerConfig; + this.nodes = new ArrayList<>(); + } + private MessageBufferOutput getMessageBufferOutputForOutputStream( + OutputStream out, + boolean reuseResourceInGenerator) + throws IOException + { OutputStreamBufferOutput messageBufferOutput; if (reuseResourceInGenerator) { messageBufferOutput = messageBufferOutputHolder.get(); @@ -125,91 +231,106 @@ public MessagePackGenerator( else { messageBufferOutput = new OutputStreamBufferOutput(out); } - this.messagePacker = packerConfig.newPacker(messageBufferOutput); - - this.packerConfig = packerConfig; + return messageBufferOutput; + } - this.stack = new LinkedList(); + private String currentStateStr() + { + switch (currentState) { + case IN_OBJECT: + return "IN_OBJECT"; + case IN_ARRAY: + return "IN_ARRAY"; + default: + return "IN_ROOT"; + } } @Override public void writeStartArray() - throws IOException, JsonGenerationException { - _writeContext = _writeContext.createChildArrayContext(); - stack.push(new StackItemForArray()); + if (currentState == IN_OBJECT) { + Node node = nodes.get(nodes.size() - 1); + assert node instanceof NodeEntryInObject; + NodeEntryInObject nodeEntryInObject = (NodeEntryInObject) node; + nodeEntryInObject.value = new NodeArray(currentParentElementIndex); + } + else { + nodes.add(new NodeArray(currentParentElementIndex)); + } + currentParentElementIndex = nodes.size() - 1; + currentState = IN_ARRAY; } @Override public void writeEndArray() - throws IOException, JsonGenerationException + throws IOException { - if (!_writeContext.inArray()) { - _reportError("Current context not an array but " + _writeContext.getTypeDesc()); + if (currentState != IN_ARRAY) { + _reportError("Current context not an array but " + currentStateStr()); } - - getStackTopForArray(); - - _writeContext = _writeContext.getParent(); - - popStackAndStoreTheItemAsValue(); + endCurrentContainer(); } @Override public void writeStartObject() - throws IOException, JsonGenerationException { - _writeContext = _writeContext.createChildObjectContext(); - stack.push(new StackItemForObject()); + if (currentState == IN_OBJECT) { + Node node = nodes.get(nodes.size() - 1); + assert node instanceof NodeEntryInObject; + NodeEntryInObject nodeEntryInObject = (NodeEntryInObject) node; + nodeEntryInObject.value = new NodeObject(currentParentElementIndex); + } + else { + nodes.add(new NodeObject(currentParentElementIndex)); + } + currentParentElementIndex = nodes.size() - 1; + currentState = IN_OBJECT; } @Override public void writeEndObject() - throws IOException, JsonGenerationException + throws IOException { - if (!_writeContext.inObject()) { - _reportError("Current context not an object but " + _writeContext.getTypeDesc()); + if (currentState != IN_OBJECT) { + _reportError("Current context not an object but " + currentStateStr()); } + endCurrentContainer(); + } - StackItemForObject stackTop = getStackTopForObject(); - - if (stackTop.getKeys().size() != stackTop.getValues().size()) { - throw new IllegalStateException( - String.format( - "objectKeys.size() and objectValues.size() is not same: depth=%d, key=%d, value=%d", - stack.size(), stackTop.getKeys().size(), stackTop.getValues().size())); + private void endCurrentContainer() + { + Node parent = nodes.get(currentParentElementIndex); + if (currentParentElementIndex == 0) { + isElementsClosed = true; + currentParentElementIndex = parent.parentIndex; + return; } - _writeContext = _writeContext.getParent(); - popStackAndStoreTheItemAsValue(); + currentParentElementIndex = parent.parentIndex; + assert currentParentElementIndex >= 0; + Node currentParent = nodes.get(currentParentElementIndex); + currentParent.incrementChildCount(); + currentState = currentParent.currentStateAsParent(); } - private void pack(Object v) + private void packNonContainer(Object v) throws IOException { MessagePacker messagePacker = getMessagePacker(); - if (v == null) { - messagePacker.packNil(); + if (v instanceof String) { + messagePacker.packString((String) v); + } + else if (v instanceof AsciiCharString) { + byte[] bytes = ((AsciiCharString) v).bytes; + messagePacker.packRawStringHeader(bytes.length); + messagePacker.writePayload(bytes); } else if (v instanceof Integer) { messagePacker.packInt((Integer) v); } - else if (v instanceof ByteBuffer) { - ByteBuffer bb = (ByteBuffer) v; - int len = bb.remaining(); - if (bb.hasArray()) { - messagePacker.packBinaryHeader(len); - messagePacker.writePayload(bb.array(), bb.arrayOffset(), len); - } - else { - byte[] data = new byte[len]; - bb.get(data); - messagePacker.packBinaryHeader(len); - messagePacker.addPayload(data); - } - } - else if (v instanceof String) { - messagePacker.packString((String) v); + else if (v == null) { + messagePacker.packNil(); } else if (v instanceof Float) { messagePacker.packFloat((Float) v); @@ -217,12 +338,6 @@ else if (v instanceof Float) { else if (v instanceof Long) { messagePacker.packLong((Long) v); } - else if (v instanceof StackItemForObject) { - packObject((StackItemForObject) v); - } - else if (v instanceof StackItemForArray) { - packArray((StackItemForArray) v); - } else if (v instanceof Double) { messagePacker.packDouble((Double) v); } @@ -235,6 +350,20 @@ else if (v instanceof BigDecimal) { else if (v instanceof Boolean) { messagePacker.packBoolean((Boolean) v); } + else if (v instanceof ByteBuffer) { + ByteBuffer bb = (ByteBuffer) v; + int len = bb.remaining(); + if (bb.hasArray()) { + messagePacker.packBinaryHeader(len); + messagePacker.writePayload(bb.array(), bb.arrayOffset(), len); + } + else { + byte[] data = new byte[len]; + bb.get(data); + messagePacker.packBinaryHeader(len); + messagePacker.addPayload(data); + } + } else if (v instanceof MessagePackExtensionType) { MessagePackExtensionType extensionType = (MessagePackExtensionType) v; byte[] extData = extensionType.getData(); @@ -244,7 +373,7 @@ else if (v instanceof MessagePackExtensionType) { else { messagePacker.flush(); ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - MessagePackGenerator messagePackGenerator = new MessagePackGenerator(getFeatureMask(), getCodec(), outputStream, packerConfig, false); + MessagePackGenerator messagePackGenerator = new MessagePackGenerator(getFeatureMask(), getCodec(), outputStream, packerConfig); getCodec().writeValue(messagePackGenerator, v); output.write(outputStream.toByteArray()); } @@ -260,10 +389,7 @@ private void packBigDecimal(BigDecimal decimal) BigInteger integer = decimal.toBigIntegerExact(); messagePacker.packBigInteger(integer); } - catch (ArithmeticException e) { - failedToPackAsBI = true; - } - catch (IllegalArgumentException e) { + catch (ArithmeticException | IllegalArgumentException e) { failedToPackAsBI = true; } @@ -278,200 +404,297 @@ private void packBigDecimal(BigDecimal decimal) } } - private void packObject(StackItemForObject stackItem) + private void packObject(NodeObject container) throws IOException { - List keys = stackItem.getKeys(); - List values = stackItem.getValues(); + MessagePacker messagePacker = getMessagePacker(); + messagePacker.packMapHeader(container.childCount); + } + private void packArray(NodeArray container) + throws IOException + { MessagePacker messagePacker = getMessagePacker(); - messagePacker.packMapHeader(keys.size()); + messagePacker.packArrayHeader(container.childCount); + } - for (int i = 0; i < keys.size(); i++) { - pack(keys.get(i)); - pack(values.get(i)); + private void addKeyNode(Object key) + { + if (currentState != IN_OBJECT) { + throw new IllegalStateException(); } + Node node = new NodeEntryInObject(currentParentElementIndex, key); + nodes.add(node); } - private void packArray(StackItemForArray stackItem) - throws IOException + private void addValueNode(Object value) throws IOException { - List values = stackItem.getValues(); + switch (currentState) { + case IN_OBJECT: { + Node node = nodes.get(nodes.size() - 1); + assert node instanceof NodeEntryInObject; + NodeEntryInObject nodeEntryInObject = (NodeEntryInObject) node; + nodeEntryInObject.value = value; + nodes.get(node.parentIndex).incrementChildCount(); + break; + } + case IN_ARRAY: { + Node node = new NodeEntryInArray(currentParentElementIndex, value); + nodes.add(node); + nodes.get(node.parentIndex).incrementChildCount(); + break; + } + default: + packNonContainer(value); + flushMessagePacker(); + break; + } + } - MessagePacker messagePacker = getMessagePacker(); - messagePacker.packArrayHeader(values.size()); + @Nullable + private byte[] getBytesIfAscii(char[] chars, int offset, int len) + { + byte[] bytes = new byte[len]; + for (int i = offset; i < offset + len; i++) { + char c = chars[i]; + if (c >= 0x80) { + return null; + } + bytes[i] = (byte) c; + } + return bytes; + } - for (int i = 0; i < values.size(); i++) { - Object v = values.get(i); - pack(v); + private boolean areAllAsciiBytes(byte[] bytes, int offset, int len) + { + for (int i = offset; i < offset + len; i++) { + if ((bytes[i] & 0x80) != 0) { + return false; + } } + return true; + } + + private void writeCharArrayTextKey(char[] text, int offset, int len) + { + byte[] bytes = getBytesIfAscii(text, offset, len); + if (bytes != null) { + addKeyNode(new AsciiCharString(bytes)); + return; + } + addKeyNode(new String(text, offset, len)); + } + + private void writeCharArrayTextValue(char[] text, int offset, int len) throws IOException + { + byte[] bytes = getBytesIfAscii(text, offset, len); + if (bytes != null) { + addValueNode(new AsciiCharString(bytes)); + return; + } + addValueNode(new String(text, offset, len)); + } + + private void writeByteArrayTextValue(byte[] text, int offset, int len) throws IOException + { + if (areAllAsciiBytes(text, offset, len)) { + addValueNode(new AsciiCharString(text)); + return; + } + addValueNode(new String(text, offset, len, DEFAULT_CHARSET)); + } + + private void writeByteArrayTextKey(byte[] text, int offset, int len) throws IOException + { + if (areAllAsciiBytes(text, offset, len)) { + addValueNode(new AsciiCharString(text)); + return; + } + addValueNode(new String(text, offset, len, DEFAULT_CHARSET)); } @Override public void writeFieldName(String name) - throws IOException, JsonGenerationException { - addKeyToStackTop(name); + if (STRING_VALUE_FIELD_IS_CHARS.get()) { + char[] chars = name.toCharArray(); + writeCharArrayTextKey(chars, 0, chars.length); + } + else { + addKeyNode(name); + } } @Override public void writeFieldName(SerializableString name) - throws IOException { - if (name instanceof MessagePackSerializedString) { - addKeyToStackTop(((MessagePackSerializedString) name).getRawValue()); + if (name instanceof SerializedString) { + writeFieldName(name.getValue()); } - else if (name instanceof SerializedString) { - addKeyToStackTop(name.getValue()); + else if (name instanceof MessagePackSerializedString) { + addKeyNode(((MessagePackSerializedString) name).getRawValue()); } else { - System.out.println(name.getClass()); throw new IllegalArgumentException("Unsupported key: " + name); } } @Override public void writeString(String text) - throws IOException, JsonGenerationException + throws IOException { - addValueToStackTop(text); + if (STRING_VALUE_FIELD_IS_CHARS.get()) { + char[] chars = text.toCharArray(); + writeCharArrayTextValue(chars, 0, chars.length); + } + else { + addValueNode(text); + } } @Override public void writeString(char[] text, int offset, int len) - throws IOException, JsonGenerationException + throws IOException { - addValueToStackTop(new String(text, offset, len)); + writeCharArrayTextValue(text, offset, len); } @Override public void writeRawUTF8String(byte[] text, int offset, int length) - throws IOException, JsonGenerationException + throws IOException { - addValueToStackTop(new String(text, offset, length, DEFAULT_CHARSET)); + writeByteArrayTextValue(text, offset, length); } @Override public void writeUTF8String(byte[] text, int offset, int length) - throws IOException, JsonGenerationException + throws IOException { - addValueToStackTop(new String(text, offset, length, DEFAULT_CHARSET)); + writeByteArrayTextValue(text, offset, length); } @Override public void writeRaw(String text) - throws IOException, JsonGenerationException + throws IOException { - addValueToStackTop(text); + if (STRING_VALUE_FIELD_IS_CHARS.get()) { + char[] chars = text.toCharArray(); + writeCharArrayTextValue(chars, 0, chars.length); + } + else { + addValueNode(text); + } } @Override public void writeRaw(String text, int offset, int len) - throws IOException, JsonGenerationException + throws IOException { - addValueToStackTop(text.substring(0, len)); + // TODO: There is room to optimize this. + char[] chars = text.toCharArray(); + writeCharArrayTextValue(chars, offset, len); } @Override public void writeRaw(char[] text, int offset, int len) - throws IOException, JsonGenerationException + throws IOException { - addValueToStackTop(new String(text, offset, len)); + writeCharArrayTextValue(text, offset, len); } @Override public void writeRaw(char c) - throws IOException, JsonGenerationException + throws IOException { - addValueToStackTop(String.valueOf(c)); + writeCharArrayTextValue(new char[] { c }, 0, 1); } @Override public void writeBinary(Base64Variant b64variant, byte[] data, int offset, int len) - throws IOException, JsonGenerationException + throws IOException { - addValueToStackTop(ByteBuffer.wrap(data, offset, len)); + addValueNode(ByteBuffer.wrap(data, offset, len)); } @Override public void writeNumber(int v) - throws IOException, JsonGenerationException + throws IOException { - addValueToStackTop(Integer.valueOf(v)); + addValueNode(v); } @Override public void writeNumber(long v) - throws IOException, JsonGenerationException + throws IOException { - addValueToStackTop(Long.valueOf(v)); + addValueNode(v); } @Override public void writeNumber(BigInteger v) - throws IOException, JsonGenerationException + throws IOException { - addValueToStackTop(v); + addValueNode(v); } @Override public void writeNumber(double d) - throws IOException, JsonGenerationException + throws IOException { - addValueToStackTop(Double.valueOf(d)); + addValueNode(d); } @Override public void writeNumber(float f) - throws IOException, JsonGenerationException + throws IOException { - addValueToStackTop(Float.valueOf(f)); + addValueNode(f); } @Override public void writeNumber(BigDecimal dec) - throws IOException, JsonGenerationException + throws IOException { - addValueToStackTop(dec); + addValueNode(dec); } @Override public void writeNumber(String encodedValue) - throws IOException, JsonGenerationException, UnsupportedOperationException + throws IOException, UnsupportedOperationException { // There is a room to improve this API's performance while the implementation is robust. // If users can use other MessagePackGenerator#writeNumber APIs that accept // proper numeric types not String, it's better to use the other APIs instead. try { long l = Long.parseLong(encodedValue); - addValueToStackTop(l); + addValueNode(l); return; } - catch (NumberFormatException e) { + catch (NumberFormatException ignored) { } try { double d = Double.parseDouble(encodedValue); - addValueToStackTop(d); + addValueNode(d); return; } - catch (NumberFormatException e) { + catch (NumberFormatException ignored) { } try { BigInteger bi = new BigInteger(encodedValue); - addValueToStackTop(bi); + addValueNode(bi); return; } - catch (NumberFormatException e) { + catch (NumberFormatException ignored) { } try { BigDecimal bc = new BigDecimal(encodedValue); - addValueToStackTop(bc); + addValueNode(bc); return; } - catch (NumberFormatException e) { + catch (NumberFormatException ignored) { } throw new NumberFormatException(encodedValue); @@ -479,22 +702,22 @@ public void writeNumber(String encodedValue) @Override public void writeBoolean(boolean state) - throws IOException, JsonGenerationException + throws IOException { - addValueToStackTop(Boolean.valueOf(state)); + addValueNode(state); } @Override public void writeNull() - throws IOException, JsonGenerationException + throws IOException { - addValueToStackTop(null); + addValueNode(null); } public void writeExtensionType(MessagePackExtensionType extensionType) throws IOException { - addValueToStackTop(extensionType); + addValueNode(extensionType); } @Override @@ -516,19 +739,42 @@ public void close() public void flush() throws IOException { - if (rootStackItem != null) { - if (rootStackItem instanceof StackItemForObject) { - packObject((StackItemForObject) rootStackItem); + if (!isElementsClosed) { + // The whole elements are not closed yet. + return; + } + + for (int i = 0; i < nodes.size(); i++) { + Node node = nodes.get(i); + if (node instanceof NodeEntryInObject) { + NodeEntryInObject nodeEntry = (NodeEntryInObject) node; + packNonContainer(nodeEntry.key); + if (nodeEntry.value instanceof NodeObject) { + packObject((NodeObject) nodeEntry.value); + } + else if (nodeEntry.value instanceof NodeArray) { + packArray((NodeArray) nodeEntry.value); + } + else { + packNonContainer(nodeEntry.value); + } + } + else if (node instanceof NodeObject) { + packObject((NodeObject) node); + } + else if (node instanceof NodeEntryInArray) { + packNonContainer(((NodeEntryInArray) node).value); } - else if (rootStackItem instanceof StackItemForArray) { - packArray((StackItemForArray) rootStackItem); + else if (node instanceof NodeArray) { + packArray((NodeArray) node); } else { - throw new IllegalStateException("Unexpected rootStackItem: " + rootStackItem); + throw new AssertionError(); } - rootStackItem = null; - flushMessagePacker(); } + flushMessagePacker(); + nodes.clear(); + isElementsClosed = false; } private void flushMessagePacker() @@ -541,76 +787,18 @@ private void flushMessagePacker() @Override protected void _releaseBuffers() { - } - - @Override - protected void _verifyValueWrite(String typeMsg) - throws IOException, JsonGenerationException - { - int status = _writeContext.writeValue(); - if (status == JsonWriteContext.STATUS_EXPECT_NAME) { - _reportError("Can not " + typeMsg + ", expecting field name"); - } - } - - private StackItem getStackTop() - { - if (stack.isEmpty()) { - throw new IllegalStateException("The stack is empty"); - } - return stack.getFirst(); - } - - private StackItemForObject getStackTopForObject() - { - StackItem stackTop = getStackTop(); - if (!(stackTop instanceof StackItemForObject)) { - throw new IllegalStateException("The stack top should be Object: " + stackTop); - } - return (StackItemForObject) stackTop; - } - - private StackItemForArray getStackTopForArray() - { - StackItem stackTop = getStackTop(); - if (!(stackTop instanceof StackItemForArray)) { - throw new IllegalStateException("The stack top should be Array: " + stackTop); - } - return (StackItemForArray) stackTop; - } - - private void addKeyToStackTop(Object key) - { - getStackTop().addKey(key); - } - - private void addValueToStackTop(Object value) - throws IOException - { - if (stack.isEmpty()) { - pack(value); - flushMessagePacker(); + try { + messagePacker.close(); } - else { - getStackTop().addValue(value); + catch (IOException e) { + throw new RuntimeException("Failed to close MessagePacker", e); } } - private void popStackAndStoreTheItemAsValue() - throws IOException + @Override + protected void _verifyValueWrite(String typeMsg) throws IOException { - StackItem child = stack.pop(); - if (stack.size() > 0) { - addValueToStackTop(child); - } - else { - if (rootStackItem != null) { - throw new IllegalStateException("rootStackItem is not null"); - } - else { - rootStackItem = child; - } - } + // FIXME? } private MessagePacker getMessagePacker() diff --git a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackKeySerializer.java b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackKeySerializer.java index 8eaa8014..36fb235d 100644 --- a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackKeySerializer.java +++ b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackKeySerializer.java @@ -15,7 +15,6 @@ // package org.msgpack.jackson.dataformat; -import com.fasterxml.jackson.core.JsonGenerationException; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.ser.std.StdSerializer; @@ -32,7 +31,7 @@ public MessagePackKeySerializer() @Override public void serialize(Object value, JsonGenerator jgen, SerializerProvider provider) - throws JsonGenerationException, IOException + throws IOException { jgen.writeFieldName(new MessagePackSerializedString(value)); } diff --git a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackParser.java b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackParser.java index 2a95b69a..4876c797 100644 --- a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackParser.java +++ b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackParser.java @@ -17,9 +17,7 @@ import com.fasterxml.jackson.core.Base64Variant; import com.fasterxml.jackson.core.JsonLocation; -import com.fasterxml.jackson.core.JsonParseException; import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonStreamContext; import com.fasterxml.jackson.core.JsonToken; import com.fasterxml.jackson.core.ObjectCodec; @@ -28,7 +26,6 @@ import com.fasterxml.jackson.core.io.IOContext; import com.fasterxml.jackson.core.io.JsonEOFException; import com.fasterxml.jackson.core.json.DupDetector; -import com.fasterxml.jackson.core.json.JsonReadContext; import org.msgpack.core.ExtensionTypeHeader; import org.msgpack.core.MessageFormat; import org.msgpack.core.MessagePack; @@ -42,27 +39,29 @@ import java.io.InputStream; import java.math.BigDecimal; import java.math.BigInteger; -import java.util.LinkedList; +import java.nio.charset.StandardCharsets; + +import static org.msgpack.jackson.dataformat.JavaInfo.STRING_VALUE_FIELD_IS_CHARS; public class MessagePackParser extends ParserMinimalBase { - private static final ThreadLocal> messageUnpackerHolder = - new ThreadLocal>(); + private static final ThreadLocal> messageUnpackerHolder = new ThreadLocal<>(); private final MessageUnpacker messageUnpacker; - private static final BigInteger LONG_MIN = BigInteger.valueOf((long) Long.MIN_VALUE); - private static final BigInteger LONG_MAX = BigInteger.valueOf((long) Long.MAX_VALUE); + private static final BigInteger LONG_MIN = BigInteger.valueOf(Long.MIN_VALUE); + private static final BigInteger LONG_MAX = BigInteger.valueOf(Long.MAX_VALUE); private ObjectCodec codec; - private JsonReadContext parsingContext; + private MessagePackReadContext streamReadContext; - private final LinkedList stack = new LinkedList(); private boolean isClosed; private long tokenPosition; private long currentPosition; private final IOContext ioContext; private ExtensionTypeCustomDeserializers extTypeCustomDesers; + private final byte[] tempBytes = new byte[64]; + private final char[] tempChars = new char[64]; private enum Type { @@ -76,51 +75,6 @@ private enum Type private String stringValue; private BigInteger biValue; private MessagePackExtensionType extensionTypeValue; - private boolean reuseResourceInParser; - - private abstract static class StackItem - { - private long numOfElements; - - protected StackItem(long numOfElements) - { - this.numOfElements = numOfElements; - } - - public void consume() - { - numOfElements--; - } - - public boolean isEmpty() - { - return numOfElements == 0; - } - } - - private static class StackItemForObject - extends StackItem - { - StackItemForObject(long numOfElements) - { - super(numOfElements); - } - } - - private static class StackItemForArray - extends StackItem - { - StackItemForArray(long numOfElements) - { - super(numOfElements); - } - } - - public MessagePackParser(IOContext ctxt, int features, ObjectCodec objectCodec, InputStream in) - throws IOException - { - this(ctxt, features, objectCodec, in, true); - } public MessagePackParser( IOContext ctxt, @@ -133,12 +87,6 @@ public MessagePackParser( this(ctxt, features, new InputStreamBufferInput(in), objectCodec, in, reuseResourceInParser); } - public MessagePackParser(IOContext ctxt, int features, ObjectCodec objectCodec, byte[] bytes) - throws IOException - { - this(ctxt, features, objectCodec, bytes, true); - } - public MessagePackParser( IOContext ctxt, int features, @@ -164,17 +112,12 @@ private MessagePackParser(IOContext ctxt, ioContext = ctxt; DupDetector dups = Feature.STRICT_DUPLICATE_DETECTION.enabledIn(features) ? DupDetector.rootDetector(this) : null; - parsingContext = JsonReadContext.createRootContext(dups); - this.reuseResourceInParser = reuseResourceInParser; + streamReadContext = MessagePackReadContext.createRootContext(dups); if (!reuseResourceInParser) { - this.messageUnpacker = MessagePack.newDefaultUnpacker(input); + messageUnpacker = MessagePack.newDefaultUnpacker(input); return; } - else { - this.messageUnpacker = null; - } - MessageUnpacker messageUnpacker; Tuple messageUnpackerTuple = messageUnpackerHolder.get(); if (messageUnpackerTuple == null) { messageUnpacker = MessagePack.newDefaultUnpacker(input); @@ -189,7 +132,7 @@ private MessagePackParser(IOContext ctxt, } messageUnpacker = messageUnpackerTuple.second(); } - messageUnpackerHolder.set(new Tuple(src, messageUnpacker)); + messageUnpackerHolder.set(new Tuple<>(src, messageUnpacker)); } public void setExtensionTypeCustomDeserializers(ExtensionTypeCustomDeserializers extTypeCustomDesers) @@ -215,21 +158,47 @@ public Version version() return null; } + private String unpackString(MessageUnpacker messageUnpacker) throws IOException + { + int strLen = messageUnpacker.unpackRawStringHeader(); + if (strLen <= tempBytes.length) { + messageUnpacker.readPayload(tempBytes, 0, strLen); + if (STRING_VALUE_FIELD_IS_CHARS.get()) { + for (int i = 0; i < strLen; i++) { + byte b = tempBytes[i]; + if ((0x80 & b) != 0) { + return new String(tempBytes, 0, strLen, StandardCharsets.UTF_8); + } + tempChars[i] = (char) b; + } + return new String(tempChars, 0, strLen); + } + else { + return new String(tempBytes, 0, strLen); + } + } + else { + byte[] bytes = messageUnpacker.readPayload(strLen); + return new String(bytes, 0, strLen, StandardCharsets.UTF_8); + } + } + @Override - public JsonToken nextToken() - throws IOException, JsonParseException + public JsonToken nextToken() throws IOException { - MessageUnpacker messageUnpacker = getMessageUnpacker(); tokenPosition = messageUnpacker.getTotalReadBytes(); - JsonToken nextToken = null; - if (parsingContext.inObject() || parsingContext.inArray()) { - if (stack.getFirst().isEmpty()) { - stack.pop(); - _currToken = parsingContext.inObject() ? JsonToken.END_OBJECT : JsonToken.END_ARRAY; - parsingContext = parsingContext.getParent(); - - return _currToken; + boolean isObjectValueSet = streamReadContext.inObject() && _currToken != JsonToken.FIELD_NAME; + if (isObjectValueSet) { + if (!streamReadContext.expectMoreValues()) { + streamReadContext = streamReadContext.getParent(); + return _updateToken(JsonToken.END_OBJECT); + } + } + else if (streamReadContext.inArray()) { + if (!streamReadContext.expectMoreValues()) { + streamReadContext = streamReadContext.getParent(); + return _updateToken(JsonToken.END_ARRAY); } } @@ -238,24 +207,19 @@ public JsonToken nextToken() } MessageFormat format = messageUnpacker.getNextFormat(); - ValueType valueType = messageUnpacker.getNextFormat().getValueType(); - - // We should push a new StackItem lazily after updating the current stack. - StackItem newStack = null; + ValueType valueType = format.getValueType(); + JsonToken nextToken; switch (valueType) { - case NIL: - messageUnpacker.unpackNil(); - nextToken = JsonToken.VALUE_NULL; - break; - case BOOLEAN: - boolean b = messageUnpacker.unpackBoolean(); - if (parsingContext.inObject() && _currToken != JsonToken.FIELD_NAME) { - parsingContext.setCurrentName(Boolean.toString(b)); + case STRING: + type = Type.STRING; + stringValue = unpackString(messageUnpacker); + if (isObjectValueSet) { + streamReadContext.setCurrentName(stringValue); nextToken = JsonToken.FIELD_NAME; } else { - nextToken = b ? JsonToken.VALUE_TRUE : JsonToken.VALUE_FALSE; + nextToken = JsonToken.VALUE_STRING; } break; case INTEGER: @@ -289,42 +253,45 @@ public JsonToken nextToken() break; } - if (parsingContext.inObject() && _currToken != JsonToken.FIELD_NAME) { - parsingContext.setCurrentName(String.valueOf(v)); + if (isObjectValueSet) { + streamReadContext.setCurrentName(String.valueOf(v)); nextToken = JsonToken.FIELD_NAME; } else { nextToken = JsonToken.VALUE_NUMBER_INT; } break; - case FLOAT: - type = Type.DOUBLE; - doubleValue = messageUnpacker.unpackDouble(); - if (parsingContext.inObject() && _currToken != JsonToken.FIELD_NAME) { - parsingContext.setCurrentName(String.valueOf(doubleValue)); + case NIL: + messageUnpacker.unpackNil(); + nextToken = JsonToken.VALUE_NULL; + break; + case BOOLEAN: + boolean b = messageUnpacker.unpackBoolean(); + if (isObjectValueSet) { + streamReadContext.setCurrentName(Boolean.toString(b)); nextToken = JsonToken.FIELD_NAME; } else { - nextToken = JsonToken.VALUE_NUMBER_FLOAT; + nextToken = b ? JsonToken.VALUE_TRUE : JsonToken.VALUE_FALSE; } break; - case STRING: - type = Type.STRING; - stringValue = messageUnpacker.unpackString(); - if (parsingContext.inObject() && _currToken != JsonToken.FIELD_NAME) { - parsingContext.setCurrentName(stringValue); + case FLOAT: + type = Type.DOUBLE; + doubleValue = messageUnpacker.unpackDouble(); + if (isObjectValueSet) { + streamReadContext.setCurrentName(String.valueOf(doubleValue)); nextToken = JsonToken.FIELD_NAME; } else { - nextToken = JsonToken.VALUE_STRING; + nextToken = JsonToken.VALUE_NUMBER_FLOAT; } break; case BINARY: type = Type.BYTES; int len = messageUnpacker.unpackBinaryHeader(); bytesValue = messageUnpacker.readPayload(len); - if (parsingContext.inObject() && _currToken != JsonToken.FIELD_NAME) { - parsingContext.setCurrentName(new String(bytesValue, MessagePack.UTF8)); + if (isObjectValueSet) { + streamReadContext.setCurrentName(new String(bytesValue, MessagePack.UTF8)); nextToken = JsonToken.FIELD_NAME; } else { @@ -332,17 +299,19 @@ public JsonToken nextToken() } break; case ARRAY: - newStack = new StackItemForArray(messageUnpacker.unpackArrayHeader()); + nextToken = JsonToken.START_ARRAY; + streamReadContext = streamReadContext.createChildArrayContext(messageUnpacker.unpackArrayHeader()); break; case MAP: - newStack = new StackItemForObject(messageUnpacker.unpackMapHeader()); + nextToken = JsonToken.START_OBJECT; + streamReadContext = streamReadContext.createChildObjectContext(messageUnpacker.unpackMapHeader()); break; case EXTENSION: type = Type.EXT; ExtensionTypeHeader header = messageUnpacker.unpackExtensionTypeHeader(); extensionTypeValue = new MessagePackExtensionType(header.getType(), messageUnpacker.readPayload(header.getLength())); - if (parsingContext.inObject() && _currToken != JsonToken.FIELD_NAME) { - parsingContext.setCurrentName(deserializedExtensionTypeValue().toString()); + if (isObjectValueSet) { + streamReadContext.setCurrentName(deserializedExtensionTypeValue().toString()); nextToken = JsonToken.FIELD_NAME; } else { @@ -354,35 +323,18 @@ public JsonToken nextToken() } currentPosition = messageUnpacker.getTotalReadBytes(); - if (parsingContext.inObject() && nextToken != JsonToken.FIELD_NAME || parsingContext.inArray()) { - stack.getFirst().consume(); - } - - if (newStack != null) { - stack.push(newStack); - if (newStack instanceof StackItemForArray) { - nextToken = JsonToken.START_ARRAY; - parsingContext = parsingContext.createChildArrayContext(-1, -1); - } - else if (newStack instanceof StackItemForObject) { - nextToken = JsonToken.START_OBJECT; - parsingContext = parsingContext.createChildObjectContext(-1, -1); - } - } - _currToken = nextToken; + _updateToken(nextToken); return nextToken; } @Override protected void _handleEOF() - throws JsonParseException { } @Override - public String getText() - throws IOException, JsonParseException + public String getText() throws IOException { switch (type) { case STRING: @@ -405,8 +357,7 @@ public String getText() } @Override - public char[] getTextCharacters() - throws IOException, JsonParseException + public char[] getTextCharacters() throws IOException { return getText().toCharArray(); } @@ -418,22 +369,19 @@ public boolean hasTextCharacters() } @Override - public int getTextLength() - throws IOException, JsonParseException + public int getTextLength() throws IOException { return getText().length(); } @Override public int getTextOffset() - throws IOException, JsonParseException { return 0; } @Override public byte[] getBinaryValue(Base64Variant b64variant) - throws IOException, JsonParseException { switch (type) { case BYTES: @@ -449,7 +397,6 @@ public byte[] getBinaryValue(Base64Variant b64variant) @Override public Number getNumberValue() - throws IOException, JsonParseException { switch (type) { case INT: @@ -467,7 +414,6 @@ public Number getNumberValue() @Override public int getIntValue() - throws IOException, JsonParseException { switch (type) { case INT: @@ -485,7 +431,6 @@ public int getIntValue() @Override public long getLongValue() - throws IOException, JsonParseException { switch (type) { case INT: @@ -503,7 +448,6 @@ public long getLongValue() @Override public BigInteger getBigIntegerValue() - throws IOException, JsonParseException { switch (type) { case INT: @@ -521,7 +465,6 @@ public BigInteger getBigIntegerValue() @Override public float getFloatValue() - throws IOException, JsonParseException { switch (type) { case INT: @@ -539,11 +482,10 @@ public float getFloatValue() @Override public double getDoubleValue() - throws IOException, JsonParseException { switch (type) { case INT: - return (double) intValue; + return intValue; case LONG: return (double) longValue; case DOUBLE: @@ -557,7 +499,6 @@ public double getDoubleValue() @Override public BigDecimal getDecimalValue() - throws IOException { switch (type) { case INT: @@ -586,8 +527,7 @@ private Object deserializedExtensionTypeValue() } @Override - public Object getEmbeddedObject() - throws IOException, JsonParseException + public Object getEmbeddedObject() throws IOException { switch (type) { case BYTES: @@ -601,7 +541,6 @@ public Object getEmbeddedObject() @Override public NumberType getNumberType() - throws IOException, JsonParseException { switch (type) { case INT: @@ -623,7 +562,6 @@ public void close() { try { if (isEnabled(JsonParser.Feature.AUTO_CLOSE_SOURCE)) { - MessageUnpacker messageUnpacker = getMessageUnpacker(); messageUnpacker.close(); } } @@ -641,7 +579,7 @@ public boolean isClosed() @Override public JsonStreamContext getParsingContext() { - return parsingContext; + return streamReadContext; } @Override @@ -659,41 +597,34 @@ public JsonLocation getCurrentLocation() @Override public void overrideCurrentName(String name) { + // Simple, but need to look for START_OBJECT/ARRAY's "off-by-one" thing: + MessagePackReadContext ctxt = streamReadContext; + if (_currToken == JsonToken.START_OBJECT || _currToken == JsonToken.START_ARRAY) { + ctxt = ctxt.getParent(); + } + // Unfortunate, but since we did not expose exceptions, need to wrap try { - if (_currToken == JsonToken.START_OBJECT || _currToken == JsonToken.START_ARRAY) { - JsonReadContext parent = parsingContext.getParent(); - parent.setCurrentName(name); - } - else { - parsingContext.setCurrentName(name); - } + ctxt.setCurrentName(name); } - catch (JsonProcessingException e) { + catch (IOException e) { throw new IllegalStateException(e); } } @Override - public String getCurrentName() - throws IOException + public String currentName() { if (_currToken == JsonToken.START_OBJECT || _currToken == JsonToken.START_ARRAY) { - JsonReadContext parent = parsingContext.getParent(); + MessagePackReadContext parent = streamReadContext.getParent(); return parent.getCurrentName(); } - return parsingContext.getCurrentName(); + return streamReadContext.getCurrentName(); } - private MessageUnpacker getMessageUnpacker() + @Override + public String getCurrentName() + throws IOException { - if (!reuseResourceInParser) { - return this.messageUnpacker; - } - - Tuple messageUnpackerTuple = messageUnpackerHolder.get(); - if (messageUnpackerTuple == null) { - throw new IllegalStateException("messageUnpacker is null"); - } - return messageUnpackerTuple.second(); + return currentName(); } } diff --git a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackReadContext.java b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackReadContext.java new file mode 100644 index 00000000..403f1b36 --- /dev/null +++ b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackReadContext.java @@ -0,0 +1,269 @@ +package org.msgpack.jackson.dataformat; + +import com.fasterxml.jackson.core.JsonLocation; +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.JsonStreamContext; +import com.fasterxml.jackson.core.io.CharTypes; +import com.fasterxml.jackson.core.io.ContentReference; +import com.fasterxml.jackson.core.json.DupDetector; + +/** + * Replacement of {@link com.fasterxml.jackson.core.json.JsonReadContext} + * to support features needed by MessagePack format. + */ +public final class MessagePackReadContext + extends JsonStreamContext +{ + /** + * Parent context for this context; null for root context. + */ + protected final MessagePackReadContext parent; + + // // // Optional duplicate detection + + protected final DupDetector dups; + + /** + * For fixed-size Arrays, Objects, this indicates expected number of entries. + */ + protected int expEntryCount; + + // // // Location information (minus source reference) + + protected String currentName; + + protected Object currentValue; + + /* + /********************************************************** + /* Simple instance reuse slots + /********************************************************** + */ + + protected MessagePackReadContext child = null; + + /* + /********************************************************** + /* Instance construction, reuse + /********************************************************** + */ + + public MessagePackReadContext(MessagePackReadContext parent, DupDetector dups, + int type, int expEntryCount) + { + super(); + this.parent = parent; + this.dups = dups; + _type = type; + this.expEntryCount = expEntryCount; + _index = -1; + _nestingDepth = parent == null ? 0 : parent._nestingDepth + 1; + } + + protected void reset(int type, int expEntryCount) + { + _type = type; + this.expEntryCount = expEntryCount; + _index = -1; + currentName = null; + currentValue = null; + if (dups != null) { + dups.reset(); + } + } + + @Override + public Object getCurrentValue() + { + return currentValue; + } + + @Override + public void setCurrentValue(Object v) + { + currentValue = v; + } + + // // // Factory methods + + public static MessagePackReadContext createRootContext(DupDetector dups) + { + return new MessagePackReadContext(null, dups, TYPE_ROOT, -1); + } + + public MessagePackReadContext createChildArrayContext(int expEntryCount) + { + MessagePackReadContext ctxt = child; + if (ctxt == null) { + ctxt = new MessagePackReadContext(this, + (dups == null) ? null : dups.child(), + TYPE_ARRAY, expEntryCount); + child = ctxt; + } + else { + ctxt.reset(TYPE_ARRAY, expEntryCount); + } + return ctxt; + } + + public MessagePackReadContext createChildObjectContext(int expEntryCount) + { + MessagePackReadContext ctxt = child; + if (ctxt == null) { + ctxt = new MessagePackReadContext(this, + (dups == null) ? null : dups.child(), + TYPE_OBJECT, expEntryCount); + child = ctxt; + return ctxt; + } + ctxt.reset(TYPE_OBJECT, expEntryCount); + return ctxt; + } + + /* + /********************************************************** + /* Abstract method implementation + /********************************************************** + */ + + @Override + public String getCurrentName() + { + return currentName; + } + + @Override + public MessagePackReadContext getParent() + { + return parent; + } + + /* + /********************************************************** + /* Extended API + /********************************************************** + */ + + public boolean hasExpectedLength() + { + return (expEntryCount >= 0); + } + + public int getExpectedLength() + { + return expEntryCount; + } + + public boolean isEmpty() + { + return expEntryCount == 0; + } + + public int getRemainingExpectedLength() + { + int diff = expEntryCount - _index; + // Negative values would occur when expected count is -1 + return Math.max(0, diff); + } + + public boolean acceptsBreakMarker() + { + return (expEntryCount < 0) && _type != TYPE_ROOT; + } + + /** + * Method called to increment the current entry count (Object property, Array + * element or Root value) for this context level + * and then see if more entries are accepted. + * The only case where more entries are NOT expected is for fixed-count + * Objects and Arrays that just reached the entry count. + *

+ * Note that since the entry count is updated this is a state-changing method. + */ + public boolean expectMoreValues() + { + if (++_index == expEntryCount) { + return false; + } + return true; + } + + /** + * @return Location pointing to the point where the context + * start marker was found + */ + @Override + public JsonLocation startLocation(ContentReference srcRef) + { + return new JsonLocation(srcRef, 1L, -1, -1); + } + + @Override + @Deprecated // since 2.13 + public JsonLocation getStartLocation(Object rawSrc) + { + return startLocation(ContentReference.rawReference(rawSrc)); + } + + /* + /********************************************************** + /* State changes + /********************************************************** + */ + + public void setCurrentName(String name) throws JsonProcessingException + { + currentName = name; + if (dups != null) { + _checkDup(dups, name); + } + } + + private void _checkDup(DupDetector dd, String name) throws JsonProcessingException + { + if (dd.isDup(name)) { + throw new JsonParseException(null, + "Duplicate field '" + name + "'", dd.findLocation()); + } + } + + /* + /********************************************************** + /* Overridden standard methods + /********************************************************** + */ + + /** + * Overridden to provide developer readable "JsonPath" representation + * of the context. + */ + @Override + public String toString() + { + StringBuilder sb = new StringBuilder(64); + switch (_type) { + case TYPE_ROOT: + sb.append("/"); + break; + case TYPE_ARRAY: + sb.append('['); + sb.append(getCurrentIndex()); + sb.append(']'); + break; + case TYPE_OBJECT: + sb.append('{'); + if (currentName != null) { + sb.append('"'); + CharTypes.appendQuoted(sb, currentName); + sb.append('"'); + } + else { + sb.append('?'); + } + sb.append('}'); + break; + } + return sb.toString(); + } +} diff --git a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackSerializedString.java b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackSerializedString.java index c7c65ff2..72ed5d8d 100644 --- a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackSerializedString.java +++ b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackSerializedString.java @@ -17,15 +17,15 @@ import com.fasterxml.jackson.core.SerializableString; -import java.io.IOException; import java.io.OutputStream; import java.nio.ByteBuffer; import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; public class MessagePackSerializedString implements SerializableString { - private static final Charset UTF8 = Charset.forName("UTF-8"); + private static final Charset UTF8 = StandardCharsets.UTF_8; private final Object value; public MessagePackSerializedString(Object value) @@ -89,28 +89,24 @@ public int appendUnquoted(char[] chars, int i) @Override public int writeQuotedUTF8(OutputStream outputStream) - throws IOException { return 0; } @Override public int writeUnquotedUTF8(OutputStream outputStream) - throws IOException { return 0; } @Override public int putQuotedUTF8(ByteBuffer byteBuffer) - throws IOException { return 0; } @Override public int putUnquotedUTF8(ByteBuffer byteBuffer) - throws IOException { return 0; } diff --git a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackDataformatForPojoTest.java b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackDataformatForPojoTest.java index c6b02068..52269a7d 100644 --- a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackDataformatForPojoTest.java +++ b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackDataformatForPojoTest.java @@ -46,6 +46,7 @@ public void testNormal() assertArrayEquals(normalPojo.b, value.b); assertEquals(normalPojo.bi, value.bi); assertEquals(normalPojo.suit, Suit.HEART); + assertEquals(normalPojo.sMultibyte, value.sMultibyte); } @Test @@ -59,13 +60,38 @@ public void testNestedList() } @Test - public void testNestedListComplex() + public void testNestedListComplex1() throws IOException { - byte[] bytes = objectMapper.writeValueAsBytes(nestedListComplexPojo); - NestedListComplexPojo value = objectMapper.readValue(bytes, NestedListComplexPojo.class); - assertEquals(nestedListPojo.s, value.s); - assertEquals(nestedListComplexPojo.foos.get(0).t, value.foos.get(0).t); + byte[] bytes = objectMapper.writeValueAsBytes(nestedListComplexPojo1); + NestedListComplexPojo1 value = objectMapper.readValue(bytes, NestedListComplexPojo1.class); + assertEquals(nestedListComplexPojo1.s, value.s); + assertEquals(1, nestedListComplexPojo1.foos.size()); + assertEquals(nestedListComplexPojo1.foos.get(0).t, value.foos.get(0).t); + } + + @Test + public void testNestedListComplex2() + throws IOException + { + byte[] bytes = objectMapper.writeValueAsBytes(nestedListComplexPojo2); + NestedListComplexPojo2 value = objectMapper.readValue(bytes, NestedListComplexPojo2.class); + assertEquals(nestedListComplexPojo2.s, value.s); + assertEquals(2, nestedListComplexPojo2.foos.size()); + assertEquals(nestedListComplexPojo2.foos.get(0).t, value.foos.get(0).t); + assertEquals(nestedListComplexPojo2.foos.get(1).t, value.foos.get(1).t); + } + + @Test + public void testStrings() + throws IOException + { + byte[] bytes = objectMapper.writeValueAsBytes(stringPojo); + StringPojo value = objectMapper.readValue(bytes, StringPojo.class); + assertEquals(stringPojo.shortSingleByte, value.shortSingleByte); + assertEquals(stringPojo.longSingleByte, value.longSingleByte); + assertEquals(stringPojo.shortMultiByte, value.shortMultiByte); + assertEquals(stringPojo.longMultiByte, value.longMultiByte); } @Test diff --git a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackDataformatTestBase.java b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackDataformatTestBase.java index d2d3d456..b9ef4cf3 100644 --- a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackDataformatTestBase.java +++ b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackDataformatTestBase.java @@ -43,7 +43,9 @@ public class MessagePackDataformatTestBase protected ObjectMapper objectMapper; protected NormalPojo normalPojo; protected NestedListPojo nestedListPojo; - protected NestedListComplexPojo nestedListComplexPojo; + protected NestedListComplexPojo1 nestedListComplexPojo1; + protected NestedListComplexPojo2 nestedListComplexPojo2; + protected StringPojo stringPojo; protected TinyPojo tinyPojo; protected ComplexPojo complexPojo; @@ -65,18 +67,31 @@ public void setup() normalPojo.b = new byte[] {0x01, 0x02, (byte) 0xFE, (byte) 0xFF}; normalPojo.bi = BigInteger.valueOf(Long.MAX_VALUE).add(BigInteger.ONE); normalPojo.suit = Suit.HEART; + normalPojo.sMultibyte = "text文字"; nestedListPojo = new NestedListPojo(); nestedListPojo.s = "a string"; - nestedListPojo.strs = Arrays.asList("string", "another string", "another string"); + nestedListPojo.strs = Arrays.asList("string#1", "string#2", "string#3"); tinyPojo = new TinyPojo(); tinyPojo.t = "t string"; - nestedListComplexPojo = new NestedListComplexPojo(); - nestedListComplexPojo.s = "a string"; - nestedListComplexPojo.foos = new ArrayList(); - nestedListComplexPojo.foos.add(tinyPojo); + nestedListComplexPojo1 = new NestedListComplexPojo1(); + nestedListComplexPojo1.s = "a string"; + nestedListComplexPojo1.foos = new ArrayList<>(); + nestedListComplexPojo1.foos.add(tinyPojo); + + nestedListComplexPojo2 = new NestedListComplexPojo2(); + nestedListComplexPojo2.foos = new ArrayList<>(); + nestedListComplexPojo2.foos.add(tinyPojo); + nestedListComplexPojo2.foos.add(tinyPojo); + nestedListComplexPojo2.s = "another string"; + + stringPojo = new StringPojo(); + stringPojo.shortSingleByte = "hello"; + stringPojo.longSingleByte = "helloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworld"; + stringPojo.shortMultiByte = "こんにちは"; + stringPojo.longMultiByte = "こんにちは、世界!!こんにちは、世界!!こんにちは、世界!!こんにちは、世界!!こんにちは、世界!!"; complexPojo = new ComplexPojo(); complexPojo.name = "komamitsu"; @@ -131,12 +146,26 @@ public static class TinyPojo public String t; } - public static class NestedListComplexPojo + public static class NestedListComplexPojo1 { public String s; public List foos; } + public static class NestedListComplexPojo2 + { + public List foos; + public String s; + } + + public static class StringPojo + { + public String shortSingleByte; + public String longSingleByte; + public String shortMultiByte; + public String longMultiByte; + } + public static class NormalPojo { String s; @@ -148,6 +177,7 @@ public static class NormalPojo public byte[] b; public BigInteger bi; public Suit suit; + public String sMultibyte; public String getS() { diff --git a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackGeneratorTest.java b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackGeneratorTest.java index 931a33f5..7ba48a61 100644 --- a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackGeneratorTest.java +++ b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackGeneratorTest.java @@ -40,6 +40,7 @@ import java.math.BigDecimal; import java.math.BigInteger; import java.nio.ByteBuffer; +import java.nio.file.Files; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; @@ -283,6 +284,8 @@ public void testWritePrimitives() generator.writeNumber(0); generator.writeString("one"); generator.writeNumber(2.0f); + generator.writeString("三"); + generator.writeString("444④"); generator.flush(); generator.close(); @@ -291,6 +294,8 @@ public void testWritePrimitives() assertEquals(0, unpacker.unpackInt()); assertEquals("one", unpacker.unpackString()); assertEquals(2.0f, unpacker.unpackFloat(), 0.001f); + assertEquals("三", unpacker.unpackString()); + assertEquals("444④", unpacker.unpackString()); assertFalse(unpacker.hasNext()); } @@ -382,23 +387,24 @@ public void testWritePrimitiveObjectViaObjectMapper() throws Exception { File tempFile = createTempFile(); - OutputStream out = new FileOutputStream(tempFile); - - ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory()); - objectMapper.configure(JsonGenerator.Feature.AUTO_CLOSE_TARGET, false); - objectMapper.writeValue(out, 1); - objectMapper.writeValue(out, "two"); - objectMapper.writeValue(out, 3.14); - objectMapper.writeValue(out, Arrays.asList(4)); - objectMapper.writeValue(out, 5L); - - MessageUnpacker unpacker = MessagePack.newDefaultUnpacker(new FileInputStream(tempFile)); - assertEquals(1, unpacker.unpackInt()); - assertEquals("two", unpacker.unpackString()); - assertEquals(3.14, unpacker.unpackFloat(), 0.0001); - assertEquals(1, unpacker.unpackArrayHeader()); - assertEquals(4, unpacker.unpackInt()); - assertEquals(5, unpacker.unpackLong()); + try (OutputStream out = Files.newOutputStream(tempFile.toPath())) { + ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory()); + objectMapper.configure(JsonGenerator.Feature.AUTO_CLOSE_TARGET, false); + objectMapper.writeValue(out, 1); + objectMapper.writeValue(out, "two"); + objectMapper.writeValue(out, 3.14); + objectMapper.writeValue(out, Arrays.asList(4)); + objectMapper.writeValue(out, 5L); + } + + try (MessageUnpacker unpacker = MessagePack.newDefaultUnpacker(new FileInputStream(tempFile))) { + assertEquals(1, unpacker.unpackInt()); + assertEquals("two", unpacker.unpackString()); + assertEquals(3.14, unpacker.unpackFloat(), 0.0001); + assertEquals(1, unpacker.unpackArrayHeader()); + assertEquals(4, unpacker.unpackInt()); + assertEquals(5, unpacker.unpackLong()); + } } @Test @@ -442,10 +448,11 @@ public Exception call() throw exception; } else { - ByteArrayOutputStream outputStream = buffers.get(ti); - MessageUnpacker unpacker = MessagePack.newDefaultUnpacker(outputStream.toByteArray()); - for (int i = 0; i < loopCount; i++) { - assertEquals(ti, unpacker.unpackInt()); + try (ByteArrayOutputStream outputStream = buffers.get(ti); + MessageUnpacker unpacker = MessagePack.newDefaultUnpacker(outputStream.toByteArray())) { + for (int i = 0; i < loopCount; i++) { + assertEquals(ti, unpacker.unpackInt()); + } } } } diff --git a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatPojoBenchmarkTest.java b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatPojoBenchmarkTest.java index 179b0989..2713eaea 100644 --- a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatPojoBenchmarkTest.java +++ b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatPojoBenchmarkTest.java @@ -15,7 +15,6 @@ // package org.msgpack.jackson.dataformat.benchmark; -import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import org.junit.Test; @@ -23,9 +22,6 @@ import static org.msgpack.jackson.dataformat.MessagePackDataformatTestBase.NormalPojo; import static org.msgpack.jackson.dataformat.MessagePackDataformatTestBase.Suit; -import java.io.File; -import java.io.FileOutputStream; -import java.io.OutputStream; import java.math.BigInteger; import java.util.ArrayList; import java.util.List; @@ -45,9 +41,6 @@ public class MessagePackDataformatPojoBenchmarkTest public MessagePackDataformatPojoBenchmarkTest() { - origObjectMapper.configure(JsonGenerator.Feature.AUTO_CLOSE_TARGET, false); - msgpackObjectMapper.configure(JsonGenerator.Feature.AUTO_CLOSE_TARGET, false); - for (int i = 0; i < LOOP_MAX; i++) { NormalPojo pojo = new NormalPojo(); pojo.i = i; @@ -76,6 +69,7 @@ public MessagePackDataformatPojoBenchmarkTest() break; } pojo.b = new byte[] {(byte) i}; + pojo.sMultibyte = "012345678Ⅸ"; pojos.add(pojo); } @@ -104,14 +98,6 @@ public void testBenchmark() { Benchmarker benchmarker = new Benchmarker(); - File tempFileJackson = File.createTempFile("msgpack-jackson-", "-huge-jackson"); - tempFileJackson.deleteOnExit(); - final OutputStream outputStreamJackson = new FileOutputStream(tempFileJackson); - - File tempFileMsgpack = File.createTempFile("msgpack-jackson-", "-huge-msgpack"); - tempFileMsgpack.deleteOnExit(); - final OutputStream outputStreamMsgpack = new FileOutputStream(tempFileMsgpack); - benchmarker.addBenchmark(new Benchmarker.Benchmarkable("serialize(pojo) with JSON") { @Override public void run() @@ -119,7 +105,7 @@ public void run() { for (int j = 0; j < LOOP_FACTOR_SER; j++) { for (int i = 0; i < LOOP_MAX; i++) { - origObjectMapper.writeValue(outputStreamJackson, pojos.get(i)); + origObjectMapper.writeValueAsBytes(pojos.get(i)); } } } @@ -132,7 +118,7 @@ public void run() { for (int j = 0; j < LOOP_FACTOR_SER; j++) { for (int i = 0; i < LOOP_MAX; i++) { - msgpackObjectMapper.writeValue(outputStreamMsgpack, pojos.get(i)); + msgpackObjectMapper.writeValueAsBytes(pojos.get(i)); } } } @@ -164,12 +150,6 @@ public void run() } }); - try { - benchmarker.run(COUNT, WARMUP_COUNT); - } - finally { - outputStreamJackson.close(); - outputStreamMsgpack.close(); - } + benchmarker.run(COUNT, WARMUP_COUNT); } }