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

Mixed choice/non-choice decoding #155

Merged
merged 2 commits into from Dec 1, 2019

Conversation

bwetherfield
Copy link
Collaborator

Mirrors #154

Fixes bugs

  1. Decoding multiple choice elements in the same Keyed Container.
  2. Decoding choice elements after decoding regular keyed elements in the same container.

Case 1 refers to decoding implementations of the form:

    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        otherValue = try container.decode(String.self, forKey: .otherValue)
        intOrString = try IntOrString(from: decoder)
    }

where IntOrString is a choice coding element

(IntOrString defined as follows)

enum IntOrString {
    case int(Int)
    case string(String)
}

extension IntOrString: Decodable {
    enum CodingKeys: String, CodingKey {
        case int
        case string
    }

    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        if container.contains(.int) {
            self = .int(try container.decode(Int.self, forKey: .int))
        } else {
            self = .string(try container.decode(String.self, forKey: .string))
        }
    }
}

extension IntOrString.CodingKeys: XMLChoiceCodingKey {} // signifies that `IntOrString` is a choice element

Case 2 refers to decoding implementations of the following form:

    init(from decoder: Decoder) throws {
        self.first = try IntOrString(from: decoder)
        self.second = try AlternateIntOrString(from: decoder)
    }

Where both first: IntOrString and second: AlternateIntOrString are choice elements.

(AlternateIntOrString defined as follows)

private enum AlternateIntOrString {
    case alternateInt(Int)
    case alternateString(String)
}

extension AlternateIntOrString: Decodable {
    enum CodingKeys: String, CodingKey {
        case alternateInt = "alternate-int"
        case alternateString = "alternate-string"
    }

    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        if container.contains(.alternateInt) {
            self = .alternateInt(try container.decode(Int.self, forKey: .alternateInt))
        } else {
            self = .alternateString(try container.decode(String.self, forKey: .alternateString))
        }
    }
}

extension AlternateIntOrString.CodingKeys: XMLChoiceCodingKey {} // signifies that `AlternateIntOrString` is a choice element

Copy link
Collaborator

@MaxDesiatov MaxDesiatov left a comment

Choose a reason for hiding this comment

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

Seems legit 👍

@MaxDesiatov MaxDesiatov merged commit c47aa6a into CoreOffice:master Dec 1, 2019
@MaxDesiatov MaxDesiatov added the bug Something isn't working label Dec 1, 2019
arjungupta0107 pushed a commit to salido/XMLCoder that referenced this pull request Jun 26, 2020
Mirrors CoreOffice#154 

Fixes bugs 
1) Decoding multiple choice elements in the same Keyed Container.
2) Decoding choice elements after decoding regular keyed elements in the same container.

Case 1 refers to decoding implementations of the form: 
```swift
    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        otherValue = try container.decode(String.self, forKey: .otherValue)
        intOrString = try IntOrString(from: decoder)
    }
```
where `IntOrString` is a choice coding element

`IntOrString` defined as follows:

```swift 
enum IntOrString {
    case int(Int)
    case string(String)
}

extension IntOrString: Decodable {
    enum CodingKeys: String, CodingKey {
        case int
        case string
    }

    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        if container.contains(.int) {
            self = .int(try container.decode(Int.self, forKey: .int))
        } else {
            self = .string(try container.decode(String.self, forKey: .string))
        }
    }
}

extension IntOrString.CodingKeys: XMLChoiceCodingKey {} // signifies that `IntOrString` is a choice element
```

Case 2 refers to decoding implementations of the following form:

```swift
    init(from decoder: Decoder) throws {
        self.first = try IntOrString(from: decoder)
        self.second = try AlternateIntOrString(from: decoder)
    }
```

Where both `first: IntOrString` and `second: AlternateIntOrString` are choice elements.

`AlternateIntOrString` defined as follows:

```swift
private enum AlternateIntOrString {
    case alternateInt(Int)
    case alternateString(String)
}

extension AlternateIntOrString: Decodable {
    enum CodingKeys: String, CodingKey {
        case alternateInt = "alternate-int"
        case alternateString = "alternate-string"
    }

    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        if container.contains(.alternateInt) {
            self = .alternateInt(try container.decode(Int.self, forKey: .alternateInt))
        } else {
            self = .alternateString(try container.decode(String.self, forKey: .alternateString))
        }
    }
}

extension AlternateIntOrString.CodingKeys: XMLChoiceCodingKey {} // signifies that `AlternateIntOrString` is a choice element
```

* Add tests
* Fix failing tests
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants