-
Notifications
You must be signed in to change notification settings - Fork 308
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
63 changed files
with
5,960 additions
and
31 deletions.
There are no files selected for viewing
98 changes: 98 additions & 0 deletions
98
Sources/EeveeSpotify/Dependencies/XMLCoder/Auxiliaries/Attribute.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
// | ||
// XMLAttribute.swift | ||
// XMLCoder | ||
// | ||
// Created by Benjamin Wetherfield on 6/3/20. | ||
// | ||
|
||
protocol XMLAttributeProtocol {} | ||
|
||
/** Property wrapper specifying that a given property should be encoded and decoded as an XML attribute. | ||
|
||
For example, this type | ||
```swift | ||
struct Book: Codable { | ||
@Attribute var id: Int | ||
} | ||
``` | ||
|
||
will encode value `Book(id: 42)` as `<Book id="42"></Book>`. And vice versa, | ||
it will decode the former into the latter. | ||
*/ | ||
@propertyWrapper | ||
public struct Attribute<Value>: XMLAttributeProtocol { | ||
public var wrappedValue: Value | ||
|
||
public init(_ wrappedValue: Value) { | ||
self.wrappedValue = wrappedValue | ||
} | ||
} | ||
|
||
extension Attribute: Codable where Value: Codable { | ||
public func encode(to encoder: Encoder) throws { | ||
try wrappedValue.encode(to: encoder) | ||
} | ||
|
||
public init(from decoder: Decoder) throws { | ||
try wrappedValue = .init(from: decoder) | ||
} | ||
} | ||
|
||
extension Attribute: Equatable where Value: Equatable {} | ||
extension Attribute: Hashable where Value: Hashable {} | ||
|
||
extension Attribute: ExpressibleByIntegerLiteral where Value: ExpressibleByIntegerLiteral { | ||
public typealias IntegerLiteralType = Value.IntegerLiteralType | ||
|
||
public init(integerLiteral value: Value.IntegerLiteralType) { | ||
wrappedValue = Value(integerLiteral: value) | ||
} | ||
} | ||
|
||
extension Attribute: ExpressibleByUnicodeScalarLiteral where Value: ExpressibleByUnicodeScalarLiteral { | ||
public init(unicodeScalarLiteral value: Value.UnicodeScalarLiteralType) { | ||
wrappedValue = Value(unicodeScalarLiteral: value) | ||
} | ||
|
||
public typealias UnicodeScalarLiteralType = Value.UnicodeScalarLiteralType | ||
} | ||
|
||
extension Attribute: ExpressibleByExtendedGraphemeClusterLiteral where Value: ExpressibleByExtendedGraphemeClusterLiteral { | ||
public typealias ExtendedGraphemeClusterLiteralType = Value.ExtendedGraphemeClusterLiteralType | ||
|
||
public init(extendedGraphemeClusterLiteral value: Value.ExtendedGraphemeClusterLiteralType) { | ||
wrappedValue = Value(extendedGraphemeClusterLiteral: value) | ||
} | ||
} | ||
|
||
extension Attribute: ExpressibleByStringLiteral where Value: ExpressibleByStringLiteral { | ||
public typealias StringLiteralType = Value.StringLiteralType | ||
|
||
public init(stringLiteral value: Value.StringLiteralType) { | ||
wrappedValue = Value(stringLiteral: value) | ||
} | ||
} | ||
|
||
extension Attribute: ExpressibleByBooleanLiteral where Value: ExpressibleByBooleanLiteral { | ||
public typealias BooleanLiteralType = Value.BooleanLiteralType | ||
|
||
public init(booleanLiteral value: Value.BooleanLiteralType) { | ||
wrappedValue = Value(booleanLiteral: value) | ||
} | ||
} | ||
|
||
extension Attribute: ExpressibleByNilLiteral where Value: ExpressibleByNilLiteral { | ||
public init(nilLiteral: ()) { | ||
wrappedValue = Value(nilLiteral: ()) | ||
} | ||
} | ||
|
||
protocol XMLOptionalAttributeProtocol: XMLAttributeProtocol { | ||
init() | ||
} | ||
|
||
extension Attribute: XMLOptionalAttributeProtocol where Value: AnyOptional { | ||
init() { | ||
wrappedValue = Value() | ||
} | ||
} |
53 changes: 53 additions & 0 deletions
53
Sources/EeveeSpotify/Dependencies/XMLCoder/Auxiliaries/Box/BoolBox.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
// Copyright (c) 2018-2020 XMLCoder contributors | ||
// | ||
// This software is released under the MIT License. | ||
// https://opensource.org/licenses/MIT | ||
// | ||
// Created by Vincent Esche on 12/17/18. | ||
// | ||
|
||
struct BoolBox: Equatable { | ||
typealias Unboxed = Bool | ||
|
||
let unboxed: Unboxed | ||
|
||
init(_ unboxed: Unboxed) { | ||
self.unboxed = unboxed | ||
} | ||
|
||
init?(xmlString: String) { | ||
switch xmlString.lowercased() { | ||
case "false", "0", "n", "no": self.init(false) | ||
case "true", "1", "y", "yes": self.init(true) | ||
case _: return nil | ||
} | ||
} | ||
} | ||
|
||
extension BoolBox: Box { | ||
var isNull: Bool { | ||
return false | ||
} | ||
|
||
/// # Lexical representation | ||
/// Boolean has a lexical representation consisting of the following | ||
/// legal literals {`true`, `false`, `1`, `0`}. | ||
/// | ||
/// # Canonical representation | ||
/// The canonical representation for boolean is the set of literals {`true`, `false`}. | ||
/// | ||
/// --- | ||
/// | ||
/// [Schema definition](https://www.w3.org/TR/xmlschema-2/#boolean) | ||
var xmlString: String? { | ||
return (unboxed) ? "true" : "false" | ||
} | ||
} | ||
|
||
extension BoolBox: SimpleBox {} | ||
|
||
extension BoolBox: CustomStringConvertible { | ||
var description: String { | ||
return unboxed.description | ||
} | ||
} |
32 changes: 32 additions & 0 deletions
32
Sources/EeveeSpotify/Dependencies/XMLCoder/Auxiliaries/Box/Box.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
// Copyright (c) 2018-2020 XMLCoder contributors | ||
// | ||
// This software is released under the MIT License. | ||
// https://opensource.org/licenses/MIT | ||
// | ||
// Created by Vincent Esche on 12/17/18. | ||
// | ||
|
||
protocol Box { | ||
var isNull: Bool { get } | ||
var xmlString: String? { get } | ||
} | ||
|
||
/// A box that only describes a single atomic value. | ||
protocol SimpleBox: Box { | ||
// A simple tagging protocol, for now. | ||
} | ||
|
||
protocol TypeErasedSharedBoxProtocol { | ||
func typeErasedUnbox() -> Box | ||
} | ||
|
||
protocol SharedBoxProtocol: TypeErasedSharedBoxProtocol { | ||
associatedtype B: Box | ||
func unbox() -> B | ||
} | ||
|
||
extension SharedBoxProtocol { | ||
func typeErasedUnbox() -> Box { | ||
return unbox() | ||
} | ||
} |
41 changes: 41 additions & 0 deletions
41
Sources/EeveeSpotify/Dependencies/XMLCoder/Auxiliaries/Box/ChoiceBox.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
// Copyright (c) 2019-2020 XMLCoder contributors | ||
// | ||
// This software is released under the MIT License. | ||
// https://opensource.org/licenses/MIT | ||
// | ||
// Created by James Bean on 7/18/19. | ||
// | ||
|
||
/// A `Box` which represents an element which is known to contain an XML choice element. | ||
struct ChoiceBox { | ||
var key: String = "" | ||
var element: Box = NullBox() | ||
} | ||
|
||
extension ChoiceBox: Box { | ||
var isNull: Bool { | ||
return false | ||
} | ||
|
||
var xmlString: String? { | ||
return nil | ||
} | ||
} | ||
|
||
extension ChoiceBox: SimpleBox {} | ||
|
||
extension ChoiceBox { | ||
init?(_ keyedBox: KeyedBox) { | ||
guard | ||
let firstKey = keyedBox.elements.keys.first, | ||
let firstElement = keyedBox.elements[firstKey].first | ||
else { | ||
return nil | ||
} | ||
self.init(key: firstKey, element: firstElement) | ||
} | ||
|
||
init(_ singleKeyedBox: SingleKeyedBox) { | ||
self.init(key: singleKeyedBox.key, element: singleKeyedBox.element) | ||
} | ||
} |
57 changes: 57 additions & 0 deletions
57
Sources/EeveeSpotify/Dependencies/XMLCoder/Auxiliaries/Box/DataBox.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
// Copyright (c) 2018-2020 XMLCoder contributors | ||
// | ||
// This software is released under the MIT License. | ||
// https://opensource.org/licenses/MIT | ||
// | ||
// Created by Vincent Esche on 12/19/18. | ||
// | ||
|
||
import Foundation | ||
|
||
struct DataBox: Equatable { | ||
enum Format: Equatable { | ||
case base64 | ||
} | ||
|
||
typealias Unboxed = Data | ||
|
||
let unboxed: Unboxed | ||
let format: Format | ||
|
||
init(_ unboxed: Unboxed, format: Format) { | ||
self.unboxed = unboxed | ||
self.format = format | ||
} | ||
|
||
init?(base64 string: String) { | ||
guard let data = Data(base64Encoded: string) else { | ||
return nil | ||
} | ||
self.init(data, format: .base64) | ||
} | ||
|
||
func xmlString(format: Format) -> String { | ||
switch format { | ||
case .base64: | ||
return unboxed.base64EncodedString() | ||
} | ||
} | ||
} | ||
|
||
extension DataBox: Box { | ||
var isNull: Bool { | ||
return false | ||
} | ||
|
||
var xmlString: String? { | ||
return xmlString(format: format) | ||
} | ||
} | ||
|
||
extension DataBox: SimpleBox {} | ||
|
||
extension DataBox: CustomStringConvertible { | ||
var description: String { | ||
return unboxed.description | ||
} | ||
} |
99 changes: 99 additions & 0 deletions
99
Sources/EeveeSpotify/Dependencies/XMLCoder/Auxiliaries/Box/DateBox.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
// Copyright (c) 2018-2020 XMLCoder contributors | ||
// | ||
// This software is released under the MIT License. | ||
// https://opensource.org/licenses/MIT | ||
// | ||
// Created by Vincent Esche on 12/18/18. | ||
// | ||
|
||
import Foundation | ||
|
||
struct DateBox: Equatable { | ||
enum Format: Equatable { | ||
case secondsSince1970 | ||
case millisecondsSince1970 | ||
case iso8601 | ||
case formatter(DateFormatter) | ||
} | ||
|
||
typealias Unboxed = Date | ||
|
||
let unboxed: Unboxed | ||
let format: Format | ||
|
||
init(_ unboxed: Unboxed, format: Format) { | ||
self.unboxed = unboxed | ||
self.format = format | ||
} | ||
|
||
init?(secondsSince1970 string: String) { | ||
guard let seconds = TimeInterval(string) else { | ||
return nil | ||
} | ||
let unboxed = Date(timeIntervalSince1970: seconds) | ||
self.init(unboxed, format: .secondsSince1970) | ||
} | ||
|
||
init?(millisecondsSince1970 string: String) { | ||
guard let milliseconds = TimeInterval(string) else { | ||
return nil | ||
} | ||
let unboxed = Date(timeIntervalSince1970: milliseconds / 1000.0) | ||
self.init(unboxed, format: .millisecondsSince1970) | ||
} | ||
|
||
init?(iso8601 string: String) { | ||
if #available(macOS 10.12, iOS 10.0, watchOS 3.0, tvOS 10.0, *) { | ||
guard let unboxed = _iso8601Formatter.date(from: string) else { | ||
return nil | ||
} | ||
self.init(unboxed, format: .iso8601) | ||
} else { | ||
fatalError("ISO8601DateFormatter is unavailable on this platform.") | ||
} | ||
} | ||
|
||
init?(xmlString: String, formatter: DateFormatter) { | ||
guard let date = formatter.date(from: xmlString) else { | ||
return nil | ||
} | ||
self.init(date, format: .formatter(formatter)) | ||
} | ||
|
||
func xmlString(format: Format) -> String { | ||
switch format { | ||
case .secondsSince1970: | ||
let seconds = unboxed.timeIntervalSince1970 | ||
return seconds.description | ||
case .millisecondsSince1970: | ||
let milliseconds = unboxed.timeIntervalSince1970 * 1000.0 | ||
return milliseconds.description | ||
case .iso8601: | ||
if #available(macOS 10.12, iOS 10.0, watchOS 3.0, tvOS 10.0, *) { | ||
return _iso8601Formatter.string(from: self.unboxed) | ||
} else { | ||
fatalError("ISO8601DateFormatter is unavailable on this platform.") | ||
} | ||
case let .formatter(formatter): | ||
return formatter.string(from: unboxed) | ||
} | ||
} | ||
} | ||
|
||
extension DateBox: Box { | ||
var isNull: Bool { | ||
return false | ||
} | ||
|
||
var xmlString: String? { | ||
return xmlString(format: format) | ||
} | ||
} | ||
|
||
extension DateBox: SimpleBox {} | ||
|
||
extension DateBox: CustomStringConvertible { | ||
var description: String { | ||
return unboxed.description | ||
} | ||
} |
Oops, something went wrong.