Skip to content

Commit

Permalink
Move to swift-extras (#67)
Browse files Browse the repository at this point in the history
  • Loading branch information
fabianfett authored Nov 14, 2020
1 parent a5c49df commit 122b945
Show file tree
Hide file tree
Showing 43 changed files with 117 additions and 117 deletions.
8 changes: 4 additions & 4 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ jobs:
- name: Test
run: swift test --enable-code-coverage --enable-test-discovery
- name: Convert coverage files
run: llvm-cov export -format="lcov" .build/debug/pure-swift-jsonPackageTests.xctest -instr-profile .build/debug/codecov/default.profdata > info.lcov
run: llvm-cov export -format="lcov" .build/debug/swift-extras-jsonPackageTests.xctest -instr-profile .build/debug/codecov/default.profdata > info.lcov
- name: Install curl
run: apt-get update && apt-get install -y curl # required by the codecov action.
- name: Upload to codecov.io
Expand Down Expand Up @@ -94,7 +94,7 @@ jobs:
fail-fast: false
matrix:
xcode:
- Xcode_11.1.app
- Xcode_11.2.app
- Xcode_11.6.app
- Xcode_12.2.app
steps:
Expand All @@ -109,7 +109,7 @@ jobs:
- name: Xcode Tests
run: |
swift package generate-xcodeproj --skip-extra-files --enable-code-coverage
xcodebuild -quiet -parallel-testing-enabled YES -scheme pure-swift-json-Package -enableCodeCoverage YES build test
xcodebuild -quiet -parallel-testing-enabled YES -scheme swift-extras-json-Package -enableCodeCoverage YES build test
- name: Codecov
run: bash <(curl -s https://codecov.io/bash) -t ${{secrets.CODECOV_TOKEN}} -f *.coverage.txt

Expand All @@ -119,7 +119,7 @@ jobs:
fail-fast: false
matrix:
xcode:
- Xcode_11.1.app
- Xcode_11.2.app
- Xcode_11.6.app
- Xcode_12.2.app
steps:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ for f in "${files[@]}"; do
test -f "$f" || die "file '$f' not a file"
done

working_dir=$(mktemp -d "$tmp_dir/.pure-swift-json-alloc-counter-tests-XXXXXX")
working_dir=$(mktemp -d "$tmp_dir/.swift-extras-json-alloc-counter-tests-XXXXXX")

selected_hooked_functions="HookedFunctionsDoHook"
selected_bootstrap="bootstrapDoHook"
Expand Down
2 changes: 1 addition & 1 deletion IntegrationTests/run-tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ set -eu
shopt -s nullglob

here="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
tmp=$(mktemp -d /tmp/.pure-swift-json-sh-tests_XXXXXX)
tmp=$(mktemp -d /tmp/.swift-extras-json-sh-tests_XXXXXX)

# start_time
function time_diff_to_now() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ fi

"$here/../../allocation-counter-tests-framework/run-allocation-counter.sh" \
-p "$here/../../.." \
-m PureSwiftJSON \
-m ExtrasJSON \
-s "$here/shared.swift" \
-t "$tmp_dir" \
"${tests_to_run[@]}"
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import PureSwiftJSON
import ExtrasJSON

func run(identifier: String) {
let sampleString = SampleStructure.sampleJSON
Expand Down
12 changes: 6 additions & 6 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,17 @@
import PackageDescription

var package = Package(
name: "pure-swift-json",
name: "swift-extras-json",
products: [
.library(name: "PureSwiftJSON", targets: ["PureSwiftJSON"]),
.library(name: "ExtrasJSON", targets: ["ExtrasJSON"]),
],
targets: [
.target(name: "PureSwiftJSON"),
.testTarget(name: "PureSwiftJSONTests", dependencies: [
.byName(name: "PureSwiftJSON"),
.target(name: "ExtrasJSON"),
.testTarget(name: "ExtrasJSONTests", dependencies: [
.byName(name: "ExtrasJSON"),
]),
.testTarget(name: "LearningTests", dependencies: [
.byName(name: "PureSwiftJSON"),
.byName(name: "ExtrasJSON"),
]),
]
)
4 changes: 2 additions & 2 deletions PerfTests/Package.resolved
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@
"repositoryURL": "https://github.com/apple/swift-nio.git",
"state": {
"branch": null,
"revision": "4409b57d4c0c40d41ac2b320fccf02e4d451e3db",
"version": "2.13.0"
"revision": "c3e2359c55cd8b47207ab7363b77c9c398a95294",
"version": "2.23.0"
}
},
{
Expand Down
4 changes: 2 additions & 2 deletions PerfTests/Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import PackageDescription

var package = Package(
name: "pure-swift-json-performance",
name: "swift-extras-json-performance",
products: [
.executable(name: "CodingPerfTests", targets: ["CodingPerfTests"]),
],
Expand All @@ -17,7 +17,7 @@ var package = Package(
.target(
name: "CodingPerfTests",
dependencies: [
.product(name: "PureSwiftJSON", package: "pure-swift-json"),
.product(name: "ExtrasJSON", package: "swift-extras-json"),
.product(name: "NIO", package: "swift-nio"),
.product(name: "NIOFoundationCompat", package: "swift-nio"),
.product(name: "IkigaJSON", package: "IkigaJSON"),
Expand Down
38 changes: 19 additions & 19 deletions PerfTests/Sources/CodingPerfTests/main.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import ExtrasJSON
import Foundation
import PureSwiftJSON
#if os(macOS)
import SwiftyJSON
#endif
Expand All @@ -20,15 +20,15 @@ func timing(name: String, execute: () throws -> Void) rethrows -> TimeInterval {

let sampleString = SampleStructure.sampleJSON
let sampleBytes = [UInt8](sampleString.utf8)
let sampleStruct = try PSJSONDecoder().decode([SampleStructure].self, from: sampleBytes)
let sampleStruct = try XJSONDecoder().decode([SampleStructure].self, from: sampleBytes)
let sampleJSON = try JSONParser().parse(bytes: sampleBytes)

print("Number of invocations: \(runs)")

print("------------------------------------------")
print("JSONValue to bytes")

let toBytes = timing(name: "PureSwift ") {
let toBytes = timing(name: "ExtrasJSON ") {
for _ in 1 ... runs {
var bytes = [UInt8]()
bytes.reserveCapacity(2000)
Expand All @@ -53,10 +53,10 @@ let ikigaEncoding = try timing(name: "Ikiga ") {
}
}

let pureEncoder = PSJSONEncoder()
let pureEncoding = try timing(name: "PureSwift ") {
let xjsonEncoder = XJSONEncoder()
let xjsonEncoding = try timing(name: "ExtrasJSON ") {
for _ in 1 ... runs {
_ = try pureEncoder.encode(sampleStruct)
_ = try xjsonEncoder.encode(sampleStruct)
}
}

Expand All @@ -65,21 +65,21 @@ print("Reading")

let sampleData = sampleString.data(using: .utf8)!

let reading = timing(name: "PureSwift on [UInt8] ") {
let reading = timing(name: "ExtrasJSON on [UInt8] ") {
for _ in 1 ... runs {
var iterator = sampleBytes.makeIterator()
while let _ = iterator.next() {}
}
}

let readingFoundationData = timing(name: "PureSwift on Foundation.Data ") {
let readingFoundationData = timing(name: "ExtrasJSON on Foundation.Data") {
for _ in 1 ... runs {
var iterator = sampleData.makeIterator()
while let _ = iterator.next() {}
}
}

let readingNIOByteBuffer = timing(name: "PureSwift on NIO.ByteBuffer ") {
let readingNIOByteBuffer = timing(name: "ExtrasJSON on NIO.ByteBuffer ") {
for _ in 1 ... runs {
var buffer = ByteBufferAllocator().buffer(capacity: sampleBytes.count)
buffer.writeBytes(sampleBytes)
Expand All @@ -98,19 +98,19 @@ let foundationParsing = try timing(name: "Foundation on Foundation.Data") {
}
}

let pureParsing = try timing(name: "PureSwift on [UInt8] ") {
let xjsonParsing = try timing(name: "ExtrasJSON on [UInt8] ") {
for _ in 1 ... runs {
_ = try JSONParser().parse(bytes: sampleBytes)
}
}

let pureParsingData = try timing(name: "PureSwift on Foundation.Data ") {
let xjsonParsingData = try timing(name: "ExtrasJSON on Foundation.Data") {
for _ in 1 ... runs {
_ = try JSONParser().parse(bytes: sampleData)
}
}

let pureParsingBuffer = try timing(name: "PureSwift on NIO.ByteBuffer ") {
let xjsonParsingBuffer = try timing(name: "ExtrasJSON on NIO.ByteBuffer ") {
for _ in 1 ... runs {
var buffer = ByteBufferAllocator().buffer(capacity: sampleBytes.count)
buffer.writeBytes(sampleBytes)
Expand Down Expand Up @@ -166,24 +166,24 @@ let ikigaDecodingBuffer = try timing(name: "IkigaJSON on NIO.ByteBuffer ") {
}
}

let pureDecoder = PSJSONDecoder()
let pureDecoding = try timing(name: "PureSwift on [UInt8] ") {
let xjsonDecoder = XJSONDecoder()
let xjsonDecoding = try timing(name: "ExtrasJSON on [UInt8] ") {
for _ in 1 ... runs {
_ = try pureDecoder.decode([SampleStructure].self, from: sampleBytes)
_ = try xjsonDecoder.decode([SampleStructure].self, from: sampleBytes)
}
}

let pureDecodingOnData = try timing(name: "PureSwift on Foundation.Data ") {
let xjsonDecodingOnData = try timing(name: "ExtrasJSON on Foundation.Data") {
for _ in 1 ... runs {
_ = try pureDecoder.decode([SampleStructure].self, from: sampleData)
_ = try xjsonDecoder.decode([SampleStructure].self, from: sampleData)
}
}

let pureDecodingOnByteBuffer = try timing(name: "PureSwift on NIO.ByteBuffer ") {
let xjsonDecodingOnByteBuffer = try timing(name: "ExtrasJSON on NIO.ByteBuffer ") {
for _ in 1 ... runs {
var buffer = ByteBufferAllocator().buffer(capacity: sampleBytes.count)
buffer.writeBytes(sampleBytes)
_ = try pureDecoder.decode(
_ = try xjsonDecoder.decode(
[SampleStructure].self,
from: buffer.readBytes(length: buffer.readableBytes)!
)
Expand Down
48 changes: 24 additions & 24 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
# pure-swift-json
# swift-extras-json

[![Swift 5.1](https://img.shields.io/badge/Swift-5.1-blue.svg)](https://swift.org/download/)
[![github-actions](https://github.com/fabianfett/pure-swift-json/workflows/CI/badge.svg)](https://github.com/fabianfett/pure-swift-json/actions)
[![codecov](https://codecov.io/gh/fabianfett/pure-swift-json/branch/main/graph/badge.svg)](https://codecov.io/gh/fabianfett/pure-swift-json)
[![github-actions](https://github.com/swift-extras/swift-extras-json/workflows/CI/badge.svg)](https://github.com/swift-extras/swift-extras-json/actions)
[![codecov](https://codecov.io/gh/swift-extras/swift-extras-json/branch/main/graph/badge.svg)](https://codecov.io/gh/swift-extras/swift-extras-json)

This package provides a json encoder and decoder in pure Swift (without the use of Foundation or any other dependency).
This package provides a json encoder and decoder in Swift (without the use of Foundation or any other dependency).
The implementation is [RFC8259](https://tools.ietf.org/html/rfc8259) compliant. It offers a significant performance improvement compared to the Foundation implementation on Linux.

If you like the idea of using pure Swift without any dependencies, you might also like my reimplementation of Base64 in pure Swift: [`swift-base64-kit`](https://github.com/fabianfett/swift-base64-kit)
If you like the idea of using Swift without any dependencies, you might also like our reimplementation of Base64 in Swift: [`swift-extras-base64`](https://github.com/swift-extras/swift-extras-base64)

## Goals

Expand All @@ -29,59 +29,59 @@ If you like the idea of using pure Swift without any dependencies, you might als

## Usage

Add `pure-swift-json` as dependency to your `Package.swift`:
Add `swift-extras-json` as dependency to your `Package.swift`:

```swift
dependencies: [
.package(url: "https://github.com/fabianfett/pure-swift-json.git", .upToNextMajor(from: "0.2.1")),
.package(url: "https://github.com/swift-extras/swift-extras-json.git", .upToNextMajor(from: "0.6.0")),
],
```

Add `PureSwiftJSON` to the target you want to use it in.
Add `ExtrasJSON` to the target you want to use it in.

```swift
targets: [
.target(name: "MyFancyTarget", dependencies: [
.product(name: "PureSwiftJSON", package: "pure-swift-json"),
.product(name: "ExtrasJSON", package: "swift-extras-json"),
])
]
```

Use it as you would use the Foundation encoder and decoder.

```swift
import PureSwiftJSON
import ExtrasJSON

let bytesArray = try PSJSONEncoder().encode(myEncodable)
let myDecodable = try PSJSONDecoder().decode(MyDecodable.self, from: bytes)
let bytesArray = try XJSONEncoder().encode(myEncodable)
let myDecodable = try XJSONDecoder().decode(MyDecodable.self, from: bytes)
```

### Use with SwiftNIO ByteBuffer

For maximal performance create an `[UInt8]` from your `ByteBuffer`, even though `buffer.readableBytesView` would technically work as well.

```swift
let result = try pureDecoder.decode(
let result = try XJSONDecoder().decode(
[SampleStructure].self,
from: buffer.readBytes(length: buffer.readableBytes)!)
```

```swift
let bytes = try pureEncoder.encode(encodable)
let bytes = try XJSONEncoder().encode(encodable)
var buffer = byteBufferAllocator.buffer(capacity: bytes.count)
buffer.writeBytes(bytes)
```


### Use with Vapor 4

Increase the performance of your Vapor 4 API by using `pure-swift-json` instead of the default Foundation implementation. First you'll need to implement the conformance to Vapor's `ContentEncoder` and `ContentDecoder` as described in the [Vapor docs](https://docs.vapor.codes/4.0/content/#custom-coders).
Increase the performance of your Vapor 4 API by using `swift-extras-json` instead of the default Foundation implementation. First you'll need to implement the conformance to Vapor's `ContentEncoder` and `ContentDecoder` as described in the [Vapor docs](https://docs.vapor.codes/4.0/content/#custom-coders).

```swift
import Vapor
import PureSwiftJSON
import ExtrasJSON

extension PSJSONEncoder: ContentEncoder {
extension XJSONEncoder: ContentEncoder {
public func encode<E: Encodable>(
_ encodable: E,
to body: inout ByteBuffer,
Expand All @@ -94,7 +94,7 @@ extension PSJSONEncoder: ContentEncoder {
}
}

extension PSJSONDecoder: ContentDecoder {
extension XJSONDecoder: ContentDecoder {
public func decode<D: Decodable>(
_ decodable: D.Type,
from body: ByteBuffer,
Expand All @@ -112,10 +112,10 @@ extension PSJSONDecoder: ContentDecoder {
Next, register the encoder and decoder for use in Vapor:

```swift
let decoder = PSJSONDecoder()
let decoder = XJSONDecoder()
ContentConfiguration.global.use(decoder: decoder, for: .json)

let encoder = PSJSONEncoder()
let encoder = XJSONEncoder()
ContentConfiguration.global.use(encoder: encoder, for: .json)
```

Expand All @@ -138,7 +138,7 @@ $ swift run -c release
| | macOS Swift 5.1 | macOS Swift 5.2 | Linux Swift 5.1 | Linux Swift 5.2 |
|:--|:--|:--|:--|:--|
| Foundation | 2.61s | 2.62s | 13.03s | 12.52s |
| PureSwiftJSON | 1.23s | 1.25s | 1.13s | 1.05s |
| ExtrasJSON | 1.23s | 1.25s | 1.13s | 1.05s |
| Speedup | ~2x | ~2x | **~10x** | **~10x** |


Expand All @@ -147,7 +147,7 @@ $ swift run -c release
| | macOS Swift 5.1 | macOS Swift 5.2 | Linux Swift 5.1 | Linux Swift 5.2 |
|:--|:--|:--|:--|:--|
| Foundation | 2.72s | 3.04s | 10.27s | 10.65s |
| PureSwiftJSON | 1.70s | 1.72s | 1.39s | 1.16s |
| ExtrasJSON | 1.70s | 1.72s | 1.39s | 1.16s |
| Speedup | ~1.5x | ~1.5x | **~7x** | **~8x** |

## Workarounds
Expand Down Expand Up @@ -242,7 +242,7 @@ struct MyEvent: Decodable {
}
```

Checkout a full example in the test file [DateCodingTests](https://github.com/fabianfett/pure-swift-json/blob/main/Tests/PureSwiftJSONTests/DateCodingTests.swift).
Checkout a full example in the test file [DateCodingTests](https://github.com/swift-extras/swift-extras-json/blob/main/Tests/ExtrasJSONTests/DateCodingTests.swift).

### UTF-16 and UTF-32

Expand All @@ -260,7 +260,7 @@ let utf8 = Array(String(decoding: utf32, as: Unicode.UTF32.self).utf8)

## Contributing

Please feel welcome and encouraged to contribute to `pure-swift-json`. This is a very young endeavour and help is always welcome.
Please feel welcome and encouraged to contribute to `swift-extras-json`. This is a very young endeavour and help is always welcome.

If you've found a bug, have a suggestion, or need help getting started, please open an Issue or a PR. If you use this package, I'd be grateful for sharing your experience.

Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

public struct PSJSONDecoder {
public struct XJSONDecoder {
public var userInfo: [CodingUserInfoKey: Any] = [:]

public init() {}
Expand Down
Loading

0 comments on commit 122b945

Please sign in to comment.