|
15 | 15 | import Foundation
|
16 | 16 | import Logging
|
17 | 17 |
|
18 |
| -public typealias URLEncodedBase64 = String |
19 |
| -public typealias EncodedBase64 = String |
| 18 | +/// Container for URL encoded base64 data |
| 19 | +public struct URLEncodedBase64: ExpressibleByStringLiteral, Codable, Hashable { |
| 20 | + let string: String |
| 21 | + |
| 22 | + public init(_ string: String) { |
| 23 | + self.string = string |
| 24 | + } |
| 25 | + |
| 26 | + public init(stringLiteral value: StringLiteralType) { |
| 27 | + self.init(value) |
| 28 | + } |
| 29 | + |
| 30 | + public init(from decoder: Decoder) throws { |
| 31 | + let container = try decoder.singleValueContainer() |
| 32 | + self.string = try container.decode(String.self) |
| 33 | + } |
| 34 | + |
| 35 | + public func encode(to encoder: Encoder) throws { |
| 36 | + var container = encoder.singleValueContainer() |
| 37 | + try container.encode(self.string) |
| 38 | + } |
| 39 | +} |
| 40 | + |
| 41 | +/// Container for base64 encoded data |
| 42 | +public struct EncodedBase64: ExpressibleByStringLiteral, Codable, Hashable { |
| 43 | + let string: String |
| 44 | + |
| 45 | + public init(_ string: String) { |
| 46 | + self.string = string |
| 47 | + } |
| 48 | + |
| 49 | + public init(stringLiteral value: StringLiteralType) { |
| 50 | + self.init(value) |
| 51 | + } |
| 52 | + |
| 53 | + public init(from decoder: Decoder) throws { |
| 54 | + let container = try decoder.singleValueContainer() |
| 55 | + self.string = try container.decode(String.self) |
| 56 | + } |
| 57 | + |
| 58 | + public func encode(to encoder: Encoder) throws { |
| 59 | + var container = encoder.singleValueContainer() |
| 60 | + try container.encode(self.string) |
| 61 | + } |
| 62 | +} |
| 63 | + |
| 64 | +//public typealias URLEncodedBase64 = String |
| 65 | +//public typealias EncodedBase64 = String |
20 | 66 |
|
21 | 67 | extension Array where Element == UInt8 {
|
22 | 68 | /// Encodes an array of bytes into a base64url-encoded string
|
23 | 69 | /// - Returns: A base64url-encoded string
|
24 |
| - public func base64URLEncodedString() -> String { |
| 70 | + public func base64URLEncodedString() -> URLEncodedBase64 { |
25 | 71 | let base64String = Data(bytes: self, count: self.count).base64EncodedString()
|
26 |
| - return String.base64URL(fromBase64: base64String) |
| 72 | + return String.base64URL(fromBase64: .init(base64String)) |
27 | 73 | }
|
28 | 74 |
|
29 | 75 | /// Encodes an array of bytes into a base64 string
|
30 | 76 | /// - Returns: A base64-encoded string
|
31 |
| - public func base64EncodedString() -> String { |
32 |
| - return Data(bytes: self, count: self.count).base64EncodedString() |
| 77 | + public func base64EncodedString() -> EncodedBase64 { |
| 78 | + return .init(Data(bytes: self, count: self.count).base64EncodedString()) |
33 | 79 | }
|
34 | 80 | }
|
35 | 81 |
|
36 | 82 | extension Data {
|
37 | 83 | /// Encodes data into a base64url-encoded string
|
38 | 84 | /// - Returns: A base64url-encoded string
|
39 |
| - public func base64URLEncodedString() -> String { |
| 85 | + public func base64URLEncodedString() -> URLEncodedBase64 { |
40 | 86 | return [UInt8](self).base64URLEncodedString()
|
41 | 87 | }
|
42 | 88 | }
|
43 | 89 |
|
44 | 90 | extension String {
|
45 | 91 | /// Decode a base64url-encoded `String` to a base64 `String`
|
46 | 92 | /// - Returns: A base64-encoded `String`
|
47 |
| - public static func base64(fromBase64URLEncoded base64URLEncoded: String) -> Self { |
48 |
| - return base64URLEncoded.replacingOccurrences(of: "-", with: "+").replacingOccurrences(of: "_", with: "/") |
| 93 | + public static func base64(fromBase64URLEncoded base64URLEncoded: URLEncodedBase64) -> EncodedBase64 { |
| 94 | + return .init( |
| 95 | + base64URLEncoded.string.replacingOccurrences(of: "-", with: "+").replacingOccurrences(of: "_", with: "/") |
| 96 | + ) |
49 | 97 | }
|
50 | 98 |
|
51 |
| - public static func base64URL(fromBase64 base64Encoded: String) -> Self { |
52 |
| - return base64Encoded.replacingOccurrences(of: "+", with: "-") |
53 |
| - .replacingOccurrences(of: "/", with: "_") |
54 |
| - .replacingOccurrences(of: "=", with: "") |
| 99 | + public static func base64URL(fromBase64 base64Encoded: EncodedBase64) -> URLEncodedBase64 { |
| 100 | + return .init( |
| 101 | + base64Encoded.string.replacingOccurrences(of: "+", with: "-") |
| 102 | + .replacingOccurrences(of: "/", with: "_") |
| 103 | + .replacingOccurrences(of: "=", with: "") |
| 104 | + ) |
55 | 105 | }
|
56 | 106 |
|
57 |
| - func toBase64() -> String { |
58 |
| - return Data(self.utf8).base64EncodedString() |
| 107 | + func toBase64() -> EncodedBase64 { |
| 108 | + return .init(Data(self.utf8).base64EncodedString()) |
59 | 109 | }
|
60 | 110 | }
|
61 | 111 |
|
62 |
| -extension String { |
| 112 | +extension URLEncodedBase64 { |
63 | 113 | public var base64URLDecodedData: Data? {
|
64 |
| - var result = self.replacingOccurrences(of: "-", with: "+").replacingOccurrences(of: "_", with: "/") |
| 114 | + var result = self.string.replacingOccurrences(of: "-", with: "+").replacingOccurrences(of: "_", with: "/") |
65 | 115 | while result.count % 4 != 0 {
|
66 | 116 | result = result.appending("=")
|
67 | 117 | }
|
|
0 commit comments