Skip to content

Commit

Permalink
Merge pull request #31 from orlandos-nl/feature/jo/simplify-unicode-d…
Browse files Browse the repository at this point in the history
…ecode-loop

Simplify the unicode decode loop, thereby fixing some Unicode decode errors
  • Loading branch information
Joannis authored Jun 27, 2023
2 parents c530e46 + 89a3fd1 commit 412a017
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 8 deletions.
12 changes: 4 additions & 8 deletions Sources/IkigaJSON/Core/Bounds.swift
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ internal struct Bounds {

// If we can't take a shortcut by decoding immediately thanks to an escaping character
if escaping || unicode {
var length = Int(self.length)
var i = 0
var unicodes = [UInt16]()

Expand All @@ -53,7 +52,7 @@ internal struct Bounds {
}
}

next: while i < length {
next: while i < data.count {
let byte = data[i]

unescape: if escaping {
Expand All @@ -68,7 +67,6 @@ internal struct Bounds {

// Remove the backslash and translate the next character
data.remove(at: i)
length = length &- 1

switch data[i] {
case .backslash, .solidus, .quote:
Expand All @@ -82,8 +80,7 @@ internal struct Bounds {
case .u:
// `\u` indicates a unicode character
data.remove(at: i)
length = length &- 1
let unicode = try decodeUnicode(from: &data, offset: &i, length: &length)
let unicode = try decodeUnicode(from: &data, offset: &i)
unicodes.append(unicode)

// Continue explicitly, so that we do not trigger the unicode 'flush' flow
Expand Down Expand Up @@ -159,9 +156,9 @@ internal struct Bounds {

struct UTF8ParsingError: Error {}

fileprivate func decodeUnicode(from data: inout Data, offset: inout Int, length: inout Int) throws -> UInt16 {
fileprivate func decodeUnicode(from data: inout Data, offset: inout Int) throws -> UInt16 {
let hexCharacters = 4
guard length - offset >= hexCharacters else {
guard data.count - offset >= hexCharacters else {
throw UTF8ParsingError()
}

Expand All @@ -174,7 +171,6 @@ fileprivate func decodeUnicode(from data: inout Data, offset: inout Int, length:
throw UTF8ParsingError()
}

length -= hexCharacters
var unicode: UInt16 = 0
unicode += UInt16(hex0) << 12
unicode += UInt16(hex1) << 8
Expand Down
9 changes: 9 additions & 0 deletions Tests/IkigaJSONTests/JSONTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,15 @@ final class IkigaJSONTests: XCTestCase {
XCTAssertEqual(result, ["simple": "ßhello world", "complex": "👩‍👩‍👧‍👧hello world"])
}
}

func testEscapedUnicodeWeis() throws {
do {
let json: Data = #"{"foo":"\u0022wei\u00DF\u0022"}"#.data(using: .utf8)!

let result = try IkigaJSONDecoder().decode([String: String].self, from: json)
XCTAssertEqual(result, ["foo": #""weiß""#])
}
}

func testPropertyWrapper() throws {
@propertyWrapper struct FluentPropertyTest<Value: Codable & Equatable>: Codable, Equatable {
Expand Down

0 comments on commit 412a017

Please sign in to comment.