142 lines
5.4 KiB
Swift
142 lines
5.4 KiB
Swift
import Foundation
|
|
|
|
/// Represents the media type [suffix](https://en.wikipedia.org/wiki/Media_type#Suffix)es.
|
|
///
|
|
/// The library allows all ``MediaType``s to have a suffix. Keep in mind though, that not all such combinations are
|
|
/// registered (see the [official site](https://www.iana.org/assignments/media-types/media-types.xhtml) for details).
|
|
///
|
|
/// It is also possible to create completely custom suffixes by using either the ``Suffix/other(_:)`` case directly or a
|
|
/// string literal.
|
|
///
|
|
/// ```swift
|
|
/// MediaType.application(.jose(.json)) // Creates: application/jose+json
|
|
/// MediaType.application(.jose(.other("custom"))) // Creates: application/jose+custom
|
|
/// MediaType.image(.svg("zip")) // Creates: image/svg+zip
|
|
/// ```
|
|
public enum Suffix {
|
|
case xml
|
|
case json
|
|
case ber
|
|
case cbor
|
|
case der
|
|
case fastinfoset
|
|
case wbxml
|
|
case zip
|
|
case tlv
|
|
case jsonSeq
|
|
case sqlite3
|
|
case jwt
|
|
case gzip
|
|
case cborSeq
|
|
case zstd
|
|
case other(CustomStringConvertible)
|
|
}
|
|
|
|
extension Suffix: RawRepresentable {
|
|
public init(rawValue: String) {
|
|
let rawValue = rawValue.starts(with: "+")
|
|
? String(rawValue.split(separator: "+", maxSplits: 1).last!)
|
|
: rawValue
|
|
switch (rawValue) {
|
|
case "xml": self = .xml
|
|
case "json": self = .json
|
|
case "ber": self = .ber
|
|
case "cbor": self = .cbor
|
|
case "der": self = .der
|
|
case "fastinfoset": self = .fastinfoset
|
|
case "wbxml": self = .wbxml
|
|
case "zip": self = .zip
|
|
case "tlv": self = .tlv
|
|
case "json-seq": self = .jsonSeq
|
|
case "sqlite3": self = .sqlite3
|
|
case "jwt": self = .jwt
|
|
case "gzip": self = .gzip
|
|
case "cbor-seq": self = .cborSeq
|
|
case "zstd": self = .zstd
|
|
default: self = .other(rawValue)
|
|
}
|
|
}
|
|
|
|
public var rawValue: String {
|
|
switch self {
|
|
case .xml: return "+xml"
|
|
case .json: return "+json"
|
|
case .ber: return "+ber"
|
|
case .cbor: return "+cbor"
|
|
case .der: return "+der"
|
|
case .fastinfoset: return "+fastinfoset"
|
|
case .wbxml: return "+wbxml"
|
|
case .zip: return "+zip"
|
|
case .tlv: return "+tlv"
|
|
case .jsonSeq: return "+json-seq"
|
|
case .sqlite3: return "+sqlite3"
|
|
case .jwt: return "+jwt"
|
|
case .gzip: return "+gzip"
|
|
case .cborSeq: return "+cbor-seq"
|
|
case .zstd: return "+zstd"
|
|
case .other(let value): return value.description.starts(with: "+") ? value.description : "+\(value)"
|
|
}
|
|
}
|
|
}
|
|
|
|
extension Suffix: CustomStringConvertible { public var description: String { rawValue } }
|
|
|
|
extension Optional: CustomStringConvertible where Wrapped == Suffix {
|
|
public var description: String {
|
|
switch self {
|
|
case .none: return ""
|
|
case .some(let value): return value.description
|
|
}
|
|
}
|
|
}
|
|
|
|
extension Suffix: ExpressibleByStringLiteral {
|
|
public init(stringLiteral value: String) {
|
|
self.init(rawValue: value)
|
|
}
|
|
}
|
|
|
|
extension Suffix: Hashable {
|
|
public static func ==(lhs: Self, rhs: Self) -> Bool {
|
|
switch lhs {
|
|
case .xml: if case .xml = rhs { return true } else { return false }
|
|
case .json: if case .json = rhs { return true } else { return false }
|
|
case .ber: if case .ber = rhs { return true } else { return false }
|
|
case .cbor: if case .cbor = rhs { return true } else { return false }
|
|
case .der: if case .der = rhs { return true } else { return false }
|
|
case .fastinfoset: if case .fastinfoset = rhs { return true } else { return false }
|
|
case .wbxml: if case .wbxml = rhs { return true } else { return false }
|
|
case .zip: if case .zip = rhs { return true } else { return false }
|
|
case .tlv: if case .tlv = rhs { return true } else { return false }
|
|
case .jsonSeq: if case .jsonSeq = rhs { return true } else { return false }
|
|
case .sqlite3: if case .sqlite3 = rhs { return true } else { return false }
|
|
case .jwt: if case .jwt = rhs { return true } else { return false }
|
|
case .gzip: if case .gzip = rhs { return true } else { return false }
|
|
case .cborSeq: if case .cborSeq = rhs { return true } else { return false }
|
|
case .zstd: if case .zstd = rhs { return true } else { return false }
|
|
case .other(let lhsSuffix): if case let .other(rhsSuffix) = rhs { return lhsSuffix.description == rhsSuffix.description } else { return false }
|
|
}
|
|
}
|
|
|
|
public func hash(into hasher: inout Hasher) {
|
|
switch self {
|
|
case .xml: hasher.combine(0)
|
|
case .json: hasher.combine(1)
|
|
case .ber: hasher.combine(2)
|
|
case .cbor: hasher.combine(3)
|
|
case .der: hasher.combine(4)
|
|
case .fastinfoset: hasher.combine(5)
|
|
case .wbxml: hasher.combine(6)
|
|
case .zip: hasher.combine(7)
|
|
case .tlv: hasher.combine(8)
|
|
case .jsonSeq: hasher.combine(9)
|
|
case .sqlite3: hasher.combine(10)
|
|
case .jwt: hasher.combine(11)
|
|
case .gzip: hasher.combine(12)
|
|
case .cborSeq: hasher.combine(13)
|
|
case .zstd: hasher.combine(14)
|
|
case .other(let other): hasher.combine(other.description)
|
|
}
|
|
}
|
|
}
|