Skip to content

Conversation

ephemer
Copy link

@ephemer ephemer commented Oct 14, 2025

Hallo aus Berlin @fabianfett,

We're interested in using JSONValue with Embedded Swift to manually encode and decode values like in your example here. We could just "rip out" the bits we need, but I thought this functionality might be useful for some of your audience as well.

Note that Codable and co are not available on Embedded at all, so the library without these changes does not compile.
With this change, users have a minimal but totally usable JSON implementation for Embedded platforms and devices.

Note that the resulting Embedded Swift binary must be compiled with -l swiftUnicodeDataTables, found in the respective embedded library directory of the Swift toolchain, for example:

export TOOLCHAIN_DIR="$(dirname "$(dirname "$(swiftly run which swift)")")"

swift run \
  -Xswiftc -target -Xswiftc arm64-apple-macos15.0 \
  -Xswiftc -enable-experimental-feature -Xswiftc Embedded \
  -Xswiftc -lswiftUnicodeDataTables -Xswiftc -L"$TOOLCHAIN_DIR/lib/swift/embedded/arm64-apple-macos"

With this, I'm able to build a test file via Embedded Swift:

import ExtrasJSON

func print(_ value: JSONValue) {
    var str: [UInt8] = []
    result.appendBytes(to: &str)
    print(String(decoding: str, as: UTF8.self))
}

let result = try! JSONParser().parse(bytes: """
    {
        "test": 123.123,
        "test2": true
    }
""".utf8)

print(result)

What do you think?

}

public enum JSONValue {
public enum JSONValue: Sendable {
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I realised just before submitting this PR that this is not strictly necessary. But given that all of the enum cases themselves are Sendable, I think this is correct and desirable. Let me know if you'd like me to revert the change

throw JSONError.couldNotCreateUnicodeScalarFromUInt32(
in: output!, index: failureIndex, unicodeScalarValue: unicodeScalarValue
)
switch error {
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

moving this to a single switch statement rather than multiple catch statements cleans up the code somewhat by removing repetition. More importantly, Swift didn't seem to recognise that all cases are satisfied without this change

case expectedLowSurrogateUTF8SequenceAfterHighSurrogate(index: Int)
case unexpectedEscapedCharacter(ascii: UInt8, index: Int)
case couldNotCreateUnicodeScalarFromUInt32(index: Int, unicodeScalarValue: UInt32)
case jsonError(JSONError)
Copy link
Author

@ephemer ephemer Oct 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is arguably the biggest "functional change" of the PR, and I'm not extremely happy about it, but I couldn't find a better way of keeping to a single error type per function (noting that some of these functions throw JSONError or EscapedSequenceError)

I think it's fine though, especially given that EscapedSequenceError is internal to the library.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant