Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove dependency on Half #21

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 0 additions & 16 deletions Package.resolved

This file was deleted.

19 changes: 9 additions & 10 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,21 @@ let package = Package(
name: "CBORCoding",

platforms: [
.iOS("12.0"),
.macOS("10.13"),
.tvOS("12.0"),
.watchOS("4.0")
.iOS("14.0"),
.macOS("11.0"),
.tvOS("14.0"),
.watchOS("7.0"),
],

products: [
.library(name: "CBORCoding", targets: ["CBORCoding"])
],
dependencies: [],

dependencies: [
.package(url: "https://github.com/SomeRandomiOSDev/Half", from: "1.4.1")
targets: [
.target(name: "CBORCoding", dependencies: []),
.testTarget(name: "CBORCodingTests", dependencies: ["CBORCoding"])
],

targets: [
.target(name: "CBORCoding", dependencies: ["Half"]),
.testTarget(name: "CBORCodingTests", dependencies: ["CBORCoding", "Half"])
]
swiftLanguageVersions: [.v5]
)
111 changes: 49 additions & 62 deletions Sources/CBORCoding/CBORDecoder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
//

import Foundation
#if canImport(Half)
@_implementationOnly import Half
#endif

#if canImport(Combine)
import Combine
Expand Down Expand Up @@ -286,34 +288,34 @@ internal class __CBORDecoder: Decoder, SingleValueDecodingContainer {
}

fileprivate func decode<T: Decodable>(_ value: Any, as type: T.Type) throws -> T {
let result: T

// swiftlint:disable force_cast
if type == Data.self, let value = value as? CBORDecodedData {
result = value.decodedDataValue() as! T
} else if type == String.self, let value = value as? CBORDecodedString {
result = try value.decodedStringValue() as! T
} else if type == CBOR.NegativeUInt64.self {
result = try decode(value, as: CBOR.NegativeUInt64.self) as! T
} else if type == CBOR.Undefined.self {
return value.decodedDataValue() as! T
}
if type == String.self, let value = value as? CBORDecodedString {
return try value.decodedStringValue() as! T
}
if type == CBOR.NegativeUInt64.self {
return try decode(value, as: CBOR.NegativeUInt64.self) as! T
}
if type == CBOR.Undefined.self {
guard let decodedValue = value as? T else {
throw DecodingError._typeMismatch(at: codingPath, expectation: type, reality: value)
}

result = decodedValue
} else if let decodedValue = value as? T {
result = decodedValue
} else if type == Half.self {
result = try decodeFloatingPoint(value, as: Half.self) as! T
} else {
storage.push(container: value)
defer { storage.popContainer() }

result = try type.init(from: self)
return decodedValue
}
if let decodedValue = value as? T {
return decodedValue
}
if type == Float16.self {
return try decodeFloatingPoint(value, as: Float16.self) as! T
}
// swiftlint:enable force_cast

return result
storage.push(container: value)
defer { storage.popContainer() }
// swiftlint:enable force_cast
return try type.init(from: self)
}

//
Expand Down Expand Up @@ -378,54 +380,39 @@ internal class __CBORDecoder: Decoder, SingleValueDecodingContainer {
}

fileprivate func decodeFloatingPoint<T>(_ value: Any, as type: T.Type) throws -> T where T: BinaryFloatingPoint {
let floatingPoint: T
if let half = value as? Half {
if half.isNaN {
if half.isSignalingNaN {
floatingPoint = .signalingNaN
} else {
floatingPoint = .nan
}
} else {
guard let value = T(exactly: half) else {
throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: codingPath, debugDescription: "Decoded CBOR number <\(half)> does not fit in \(type)."))
}

floatingPoint = value
if let half = value as? Float16 {
guard !half.isNaN else {
return half.isSignalingNaN ? .signalingNaN : .nan
}
} else if let float = value as? Float {
if float.isNaN {
if float.isSignalingNaN {
floatingPoint = .signalingNaN
} else {
floatingPoint = .nan
}
} else {
guard let value = T(exactly: float) else {
throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: codingPath, debugDescription: "Decoded CBOR number <\(float)> does not fit in \(type)."))
}

floatingPoint = value
guard let value = T(exactly: half) else {
throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: codingPath, debugDescription: "Decoded CBOR number <\(half)> does not fit in \(type)."))
}
} else if let double = value as? Double {
if double.isNaN {
if double.isSignalingNaN {
floatingPoint = .signalingNaN
} else {
floatingPoint = .nan
}
} else {
guard let value = T(exactly: double) else {
throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: codingPath, debugDescription: "Decoded CBOR number <\(double)> does not fit in \(type)."))
}

floatingPoint = value
return value
}

if let float = value as? Float {
guard !float.isNaN else {
return float.isSignalingNaN ? .signalingNaN : .nan
}
} else {
throw DecodingError._typeMismatch(at: codingPath, expectation: type, reality: value)
guard let value = T(exactly: float) else {
throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: codingPath, debugDescription: "Decoded CBOR number <\(float)> does not fit in \(type)."))
}

return value
}
if let double = value as? Double {
guard !double.isNaN else {
return double.isSignalingNaN ? .signalingNaN : .nan
}
guard let value = T(exactly: double) else {
throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: codingPath, debugDescription: "Decoded CBOR number <\(double)> does not fit in \(type)."))
}

return floatingPoint
return value

}
throw DecodingError._typeMismatch(at: codingPath, expectation: type, reality: value)
}

fileprivate func decode(_ value: Any, as type: CBOR.NegativeUInt64.Type) throws -> CBOR.NegativeUInt64 {
Expand Down
101 changes: 54 additions & 47 deletions Sources/CBORCoding/CBOREncoder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
//

import Foundation
#if canImport(Half)
@_implementationOnly import Half
#endif

#if canImport(Combine)
import Combine
Expand Down Expand Up @@ -227,7 +229,7 @@ open class CBOREncoder {
return Data(bytes)
}

internal static func encode(_ value: Half) -> Data {
internal static func encode(_ value: Float16) -> Data {
var half = value
let data = Data(bytes: &half, count: MemoryLayout.size(ofValue: half))

Expand Down Expand Up @@ -708,60 +710,65 @@ internal class __CBOREncoder: CBOREncoderProtocol, SingleValueEncodingContainer
}

fileprivate func encodeValueToCBOR(_ value: Encodable) throws -> Any? {
let result: Any?

if let encoded = value as? CBOR.CBOREncoded {
result = encoded.encodedData
} else if let date = value as? Date {
result = CBOREncoder.encode(date, using: options.dateEncodingStrategy)
} else if let data = value as? Data {
result = CBOREncoder.encode(data)
} else if let url = value as? URL {
return encoded.encodedData
}
if let date = value as? Date {
return CBOREncoder.encode(date, using: options.dateEncodingStrategy)
}
if let data = value as? Data {
return CBOREncoder.encode(data)
}
if let url = value as? URL {
// swiftlint:disable force_try
result = try! CBOREncoder.encode(url, forTag: .uri).encodedData
return try! CBOREncoder.encode(url, forTag: .uri).encodedData
// swiftlint:enable force_try
} else if value is NSNull || value is CBOR.Null {
result = CBOREncoder.encodeNil()
} else if value is CBOR.Undefined {
result = CBOREncoder.encodeUndefined()
} else if let dict = value as? [String: Encodable] {
result = try encode(dict)
} else if let dict = value as? [Int: Encodable] {
result = try encode(dict)
} else if let data = value as? CBOR.IndefiniteLengthData {
result = try encode(data)
} else if let string = value as? CBOR.IndefiniteLengthString {
result = try encode(string)
} else if let value = value as? CBOR.NegativeUInt64 {
result = CBOREncoder.encode(value)
} else if let value = value as? Half {
result = CBOREncoder.encode(value)
} else {
let action: () throws -> Any? = {
let depth = self.storage.count

do {
try value.encode(to: self)
} catch {
if self.storage.count > depth {
_ = self.storage.popContainer()
}

throw error
}
if value is NSNull || value is CBOR.Null {
return CBOREncoder.encodeNil()
}
if value is CBOR.Undefined {
return CBOREncoder.encodeUndefined()
}
if let dict = value as? [String: Encodable] {
return try encode(dict)
}
if let dict = value as? [Int: Encodable] {
return try encode(dict)
}
if let data = value as? CBOR.IndefiniteLengthData {
return try encode(data)
}
if let string = value as? CBOR.IndefiniteLengthString {
return try encode(string)
}
if let value = value as? CBOR.NegativeUInt64 {
return CBOREncoder.encode(value)
}
if let value = value as? Float16 {
return CBOREncoder.encode(value)
}
let action: () throws -> Any? = {
let depth = self.storage.count

do {
try value.encode(to: self)
} catch {
if self.storage.count > depth {
_ = self.storage.popContainer()
}

guard self.storage.count > depth else { return nil }
return self.storage.popContainer()
throw error
}

if newContainerLength.contains(.includeSubcontainers) {
result = try action()
} else {
result = try definiteLengthContainerContext(action)
}
guard self.storage.count > depth else { return nil }
return self.storage.popContainer()
}

return result
if newContainerLength.contains(.includeSubcontainers) {
return try action()
} else {
return try definiteLengthContainerContext(action)
}
}

// MARK: Encoder Protocol Requirements
Expand Down
7 changes: 3 additions & 4 deletions Sources/CBORCoding/CBORParser.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
//

import Foundation
@_implementationOnly import Half

// MARK: - CBORParser Definition

Expand Down Expand Up @@ -226,7 +225,7 @@ internal class CBORParser {
index += simple.decodedBytes

case 25:
let half = try decode(Half.self, from: data[index...])
let half = try decode(Float16.self, from: data[index...])
try storage.append(half.value)

index += half.decodedBytes
Expand Down Expand Up @@ -627,10 +626,10 @@ internal class CBORParser {
}

let result: (value: T, decodedBytes: Int)
if header == CBOR.Bits.half.rawValue { // Half
if header == CBOR.Bits.half.rawValue { // Float16
if data.count >= 3 {
// swiftlint:disable force_unwrapping
let half = data[data.index(data.startIndex, offsetBy: 1) ..< data.index(data.startIndex, offsetBy: 3)].reversed().withUnsafeBytes { $0.bindMemory(to: Half.self).baseAddress!.pointee }
let half = data[data.index(data.startIndex, offsetBy: 1) ..< data.index(data.startIndex, offsetBy: 3)].reversed().withUnsafeBytes { $0.bindMemory(to: Float16.self).baseAddress!.pointee }
// swiftlint:enable force_unwrapping

if half.isNaN {
Expand Down
7 changes: 7 additions & 0 deletions Sources/CBORCoding/Half.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import Foundation

#if canImport(Half) && swift(<5.3)
import Half

typealias Float16 = Half
#endif
Loading