Skip to content

Commit

Permalink
Fix Float32 decoding, add DoubleBox (#138)
Browse files Browse the repository at this point in the history
Resolve #130.

Also make `xmlString` function a computed property.
  • Loading branch information
MaxDesiatov committed Oct 6, 2019
1 parent bb6dda2 commit 9e680f2
Show file tree
Hide file tree
Showing 38 changed files with 150 additions and 61 deletions.
2 changes: 1 addition & 1 deletion Sources/XMLCoder/Auxiliaries/Box/BoolBox.swift
Expand Up @@ -38,7 +38,7 @@ extension BoolBox: Box {
/// ---
///
/// [Schema definition](https://www.w3.org/TR/xmlschema-2/#boolean)
func xmlString() -> String? {
var xmlString: String? {
return (unboxed) ? "true" : "false"
}
}
Expand Down
2 changes: 1 addition & 1 deletion Sources/XMLCoder/Auxiliaries/Box/Box.swift
Expand Up @@ -7,7 +7,7 @@

protocol Box {
var isNull: Bool { get }
func xmlString() -> String?
var xmlString: String? { get }
}

/// A box that only describes a single atomic value.
Expand Down
2 changes: 1 addition & 1 deletion Sources/XMLCoder/Auxiliaries/Box/ChoiceBox.swift
Expand Up @@ -16,7 +16,7 @@ extension ChoiceBox: Box {
return false
}

func xmlString() -> String? {
var xmlString: String? {
return nil
}
}
Expand Down
2 changes: 1 addition & 1 deletion Sources/XMLCoder/Auxiliaries/Box/DataBox.swift
Expand Up @@ -42,7 +42,7 @@ extension DataBox: Box {
return false
}

func xmlString() -> String? {
var xmlString: String? {
return xmlString(format: format)
}
}
Expand Down
2 changes: 1 addition & 1 deletion Sources/XMLCoder/Auxiliaries/Box/DateBox.swift
Expand Up @@ -84,7 +84,7 @@ extension DateBox: Box {
return false
}

func xmlString() -> String? {
var xmlString: String? {
return xmlString(format: format)
}
}
Expand Down
2 changes: 1 addition & 1 deletion Sources/XMLCoder/Auxiliaries/Box/DecimalBox.swift
Expand Up @@ -47,7 +47,7 @@ extension DecimalBox: Box {
/// ---
///
/// [Schema definition](https://www.w3.org/TR/xmlschema-2/#decimal)
func xmlString() -> String? {
var xmlString: String? {
return "\(unboxed)"
}
}
Expand Down
48 changes: 48 additions & 0 deletions Sources/XMLCoder/Auxiliaries/Box/DoubleBox.swift
@@ -0,0 +1,48 @@
//
// DoubleBox.swift
// XMLCoder
//
// Created by Max Desiatov on 05/10/2019.
//

struct DoubleBox: Equatable, ValueBox {
typealias Unboxed = Double

let unboxed: Unboxed

init(_ value: Unboxed) {
unboxed = value
}

init?(xmlString: String) {
guard let unboxed = Double(xmlString) else { return nil }

self.init(unboxed)
}
}

extension DoubleBox: Box {
var isNull: Bool {
return false
}

var xmlString: String? {
guard !unboxed.isNaN else {
return "NaN"
}

guard !unboxed.isInfinite else {
return (unboxed > 0.0) ? "INF" : "-INF"
}

return unboxed.description
}
}

extension DoubleBox: SimpleBox {}

extension DoubleBox: CustomStringConvertible {
var description: String {
return unboxed.description
}
}
10 changes: 3 additions & 7 deletions Sources/XMLCoder/Auxiliaries/Box/FloatBox.swift
Expand Up @@ -5,8 +5,8 @@
// Created by Vincent Esche on 12/17/18.
//

struct FloatBox: Equatable {
typealias Unboxed = Float64
struct FloatBox: Equatable, ValueBox {
typealias Unboxed = Float

let unboxed: Unboxed

Expand All @@ -20,10 +20,6 @@ struct FloatBox: Equatable {
}
self.init(unboxed)
}

func unbox<Float: BinaryFloatingPoint>() -> Float? {
return Float(exactly: unboxed)
}
}

extension FloatBox: Box {
Expand Down Expand Up @@ -59,7 +55,7 @@ extension FloatBox: Box {
/// ---
///
/// [Schema definition](https://www.w3.org/TR/xmlschema-2/#float)
func xmlString() -> String? {
var xmlString: String? {
guard !unboxed.isNaN else {
return "NaN"
}
Expand Down
2 changes: 1 addition & 1 deletion Sources/XMLCoder/Auxiliaries/Box/IntBox.swift
Expand Up @@ -44,7 +44,7 @@ extension IntBox: Box {
/// ---
///
/// [Schema definition](https://www.w3.org/TR/xmlschema-2/#integer)
func xmlString() -> String? {
var xmlString: String? {
return unboxed.description
}
}
Expand Down
2 changes: 1 addition & 1 deletion Sources/XMLCoder/Auxiliaries/Box/KeyedBox.swift
Expand Up @@ -43,7 +43,7 @@ extension KeyedBox: Box {
return false
}

func xmlString() -> String? {
var xmlString: String? {
return nil
}
}
Expand Down
2 changes: 1 addition & 1 deletion Sources/XMLCoder/Auxiliaries/Box/NullBox.swift
Expand Up @@ -12,7 +12,7 @@ extension NullBox: Box {
return true
}

func xmlString() -> String? {
var xmlString: String? {
return nil
}
}
Expand Down
4 changes: 2 additions & 2 deletions Sources/XMLCoder/Auxiliaries/Box/SharedBox.swift
Expand Up @@ -22,8 +22,8 @@ extension SharedBox: Box {
return unboxed.isNull
}

func xmlString() -> String? {
return unboxed.xmlString()
var xmlString: String? {
return unboxed.xmlString
}
}

Expand Down
2 changes: 1 addition & 1 deletion Sources/XMLCoder/Auxiliaries/Box/SingleKeyedBox.swift
Expand Up @@ -18,7 +18,7 @@ extension SingleKeyedBox: Box {
return false
}

func xmlString() -> String? {
var xmlString: String? {
return nil
}
}
2 changes: 1 addition & 1 deletion Sources/XMLCoder/Auxiliaries/Box/StringBox.swift
Expand Up @@ -24,7 +24,7 @@ extension StringBox: Box {
return false
}

func xmlString() -> String? {
var xmlString: String? {
return unboxed.description
}
}
Expand Down
2 changes: 1 addition & 1 deletion Sources/XMLCoder/Auxiliaries/Box/UIntBox.swift
Expand Up @@ -47,7 +47,7 @@ extension UIntBox: Box {
/// ---
///
/// [Schema definition](https://www.w3.org/TR/xmlschema-2/#nonNegativeInteger)
func xmlString() -> String? {
var xmlString: String? {
return unboxed.description
}
}
Expand Down
2 changes: 1 addition & 1 deletion Sources/XMLCoder/Auxiliaries/Box/URLBox.swift
Expand Up @@ -29,7 +29,7 @@ extension URLBox: Box {
return false
}

func xmlString() -> String? {
var xmlString: String? {
return unboxed.absoluteString
}
}
Expand Down
2 changes: 1 addition & 1 deletion Sources/XMLCoder/Auxiliaries/Box/UnkeyedBox.swift
Expand Up @@ -12,7 +12,7 @@ extension Array: Box {
return false
}

func xmlString() -> String? {
var xmlString: String? {
return nil
}
}
12 changes: 12 additions & 0 deletions Sources/XMLCoder/Auxiliaries/Box/ValueBox.swift
@@ -0,0 +1,12 @@
//
// File.swift
// XMLCoder
//
// Created by Max Desiatov on 05/10/2019.
//

protocol ValueBox: SimpleBox {
associatedtype Unboxed

init(_ value: Unboxed)
}
4 changes: 2 additions & 2 deletions Sources/XMLCoder/Auxiliaries/XMLCoderElement.swift
Expand Up @@ -288,7 +288,7 @@ extension XMLCoderElement {
}

let attributes: [Attribute] = box.attributes.compactMap { key, box in
guard let value = box.xmlString() else {
guard let value = box.xmlString else {
return nil
}
return Attribute(key: key, value: value)
Expand All @@ -299,7 +299,7 @@ extension XMLCoderElement {

init(key: String, box: SimpleBox) {
self.init(key: key)
value = box.xmlString()
value = box.xmlString
}

init(key: String, box: Box) {
Expand Down
2 changes: 2 additions & 0 deletions Sources/XMLCoder/Decoder/DecodingErrorExtension.swift
Expand Up @@ -43,6 +43,8 @@ extension DecodingError {
return "an unsigned integer value"
case is FloatBox:
return "a floating-point value"
case is DoubleBox:
return "a double floating-point value"
case is UnkeyedBox:
return "a array value"
case is KeyedBox:
Expand Down
6 changes: 5 additions & 1 deletion Sources/XMLCoder/Decoder/SingleValueDecodingContainer.swift
Expand Up @@ -31,7 +31,11 @@ extension XMLDecoderImplementation: SingleValueDecodingContainer {
return try unbox(try topContainer())
}

public func decode<T: BinaryFloatingPoint & Decodable>(_: T.Type) throws -> T {
public func decode(_: Float.Type) throws -> Float {
return try unbox(try topContainer())
}

public func decode(_: Double.Type) throws -> Double {
return try unbox(try topContainer())
}

Expand Down
22 changes: 13 additions & 9 deletions Sources/XMLCoder/Decoder/XMLDecoderImplementation.swift
Expand Up @@ -286,22 +286,26 @@ extension XMLDecoderImplementation {
return uint
}

func unbox<T: BinaryFloatingPoint & Decodable>(_ box: Box) throws -> T {
let stringBox: StringBox = try typedBox(box, for: T.self)
func unbox(_ box: Box) throws -> Float {
let stringBox: StringBox = try typedBox(box, for: Float.self)
let string = stringBox.unboxed

guard let floatBox = FloatBox(xmlString: string) else {
throw DecodingError.typeMismatch(at: codingPath, expectation: T.self, reality: box)
throw DecodingError.typeMismatch(at: codingPath, expectation: Float.self, reality: box)
}

guard let float: T = floatBox.unbox() else {
throw DecodingError.dataCorrupted(DecodingError.Context(
codingPath: codingPath,
debugDescription: "Parsed XML number <\(string)> does not fit in \(T.self)."
))
return floatBox.unboxed
}

func unbox(_ box: Box) throws -> Double {
let stringBox: StringBox = try typedBox(box, for: Double.self)
let string = stringBox.unboxed

guard let doubleBox = DoubleBox(xmlString: string) else {
throw DecodingError.typeMismatch(at: codingPath, expectation: Double.self, reality: box)
}

return float
return doubleBox.unboxed
}

func unbox(_ box: Box) throws -> String {
Expand Down
23 changes: 18 additions & 5 deletions Sources/XMLCoder/Encoder/XMLEncoderImplementation.swift
Expand Up @@ -165,13 +165,26 @@ extension XMLEncoderImplementation {
return UIntBox(value)
}

func box<T: BinaryFloatingPoint & Encodable>(_ value: T) throws -> SimpleBox {
func box(_ value: Float) throws -> SimpleBox {
return try box(value, FloatBox.self)
}

func box(_ value: Double) throws -> SimpleBox {
return try box(value, DoubleBox.self)
}

func box<T: BinaryFloatingPoint & Encodable, B: ValueBox>(
_ value: T,
_: B.Type
) throws -> SimpleBox where B.Unboxed == T {
guard value.isInfinite || value.isNaN else {
return FloatBox(value)
return B(value)
}
guard case let .convertToString(positiveInfinity: posInfString,
negativeInfinity: negInfString,
nan: nanString) = options.nonConformingFloatEncodingStrategy else {
guard case let .convertToString(
positiveInfinity: posInfString,
negativeInfinity: negInfString,
nan: nanString
) = options.nonConformingFloatEncodingStrategy else {
throw EncodingError._invalidFloatingPointValue(value, at: codingPath)
}
if value == T.infinity {
Expand Down
2 changes: 1 addition & 1 deletion Tests/XMLCoderTests/Box/BoolBoxTests.swift
Expand Up @@ -36,7 +36,7 @@ class BoolBoxTests: XCTestCase {

for (unboxed, string) in values {
let box = Boxed(unboxed)
XCTAssertEqual(box.xmlString(), string)
XCTAssertEqual(box.xmlString, string)
}
}

Expand Down
2 changes: 1 addition & 1 deletion Tests/XMLCoderTests/Box/DataBoxTests.swift
Expand Up @@ -42,7 +42,7 @@ class DataBoxTests: XCTestCase {

guard let box = boxOrNil else { continue }

XCTAssertEqual(box.xmlString(), xmlString)
XCTAssertEqual(box.xmlString, xmlString)
}
}

Expand Down
8 changes: 4 additions & 4 deletions Tests/XMLCoderTests/Box/DateBoxTests.swift
Expand Up @@ -48,7 +48,7 @@ class DateBoxTests: XCTestCase {

guard let box = boxOrNil else { continue }

XCTAssertEqual(box.xmlString(), xmlString)
XCTAssertEqual(box.xmlString, xmlString)
}
}

Expand All @@ -65,7 +65,7 @@ class DateBoxTests: XCTestCase {

guard let box = boxOrNil else { continue }

XCTAssertEqual(box.xmlString(), xmlString)
XCTAssertEqual(box.xmlString, xmlString)
}
}

Expand All @@ -80,7 +80,7 @@ class DateBoxTests: XCTestCase {

guard let box = boxOrNil else { continue }

XCTAssertEqual(box.xmlString(), xmlString)
XCTAssertEqual(box.xmlString, xmlString)
}
}

Expand All @@ -95,7 +95,7 @@ class DateBoxTests: XCTestCase {

guard let box = boxOrNil else { continue }

XCTAssertEqual(box.xmlString(), xmlString)
XCTAssertEqual(box.xmlString, xmlString)
}
}

Expand Down

0 comments on commit 9e680f2

Please sign in to comment.