-
-
Notifications
You must be signed in to change notification settings - Fork 18
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(
HelperCoders
): added base64 data decoding/encoding helpers
- Loading branch information
1 parent
ae9ed44
commit bee7cc4
Showing
3 changed files
with
107 additions
and
0 deletions.
There are no files selected for viewing
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,64 @@ | ||
import Foundation | ||
import MetaCodable | ||
|
||
/// An ``/MetaCodable/HelperCoder`` that helps decoding/encoding | ||
/// base64 data. | ||
/// | ||
/// This type can be used to decode/encode base64 data | ||
/// string and convert to `Data` type. | ||
public struct Base64Coder: HelperCoder { | ||
/// The options to use when decoding data. | ||
private let decodeOptions: Data.Base64DecodingOptions | ||
/// The options to use when encoding data. | ||
private let encodeOptions: Data.Base64EncodingOptions | ||
|
||
/// Creates a new instance of ``/MetaCodable/HelperCoder`` that decodes/encodes | ||
/// base64 data. | ||
/// | ||
/// - Parameters: | ||
/// - decodeOptions: The options to use when decoding data. | ||
/// - encodeOptions: The options to use when encoding data. | ||
public init( | ||
decodeOptions: Data.Base64DecodingOptions = [], | ||
encodeOptions: Data.Base64EncodingOptions = [] | ||
) { | ||
self.decodeOptions = decodeOptions | ||
self.encodeOptions = encodeOptions | ||
} | ||
|
||
/// Decodes base64 data with provided decoding options | ||
/// from the given `decoder`. | ||
/// | ||
/// The data is decoded from a base64 string representation. | ||
/// | ||
/// - Parameter decoder: The decoder to read data from. | ||
/// - Returns: The data decoded. | ||
/// | ||
/// - Throws: `DecodingError.typeMismatch` if the decoded string | ||
/// isn't a valid base64 representation. | ||
public func decode(from decoder: Decoder) throws -> Data { | ||
let base64Str = try String(from: decoder) | ||
guard let data = Data(base64Encoded: base64Str, options: decodeOptions) | ||
else { | ||
let errDesc = "Invalid base64 string \"\(base64Str)\"" | ||
throw DecodingError.typeMismatch( | ||
Data.self, | ||
.init(codingPath: decoder.codingPath, debugDescription: errDesc) | ||
) | ||
} | ||
return data | ||
} | ||
|
||
/// Encodes base64 data with provided encoding options | ||
/// to the given `decoder`. | ||
/// | ||
/// The data is encoded as a base64 string representation. | ||
/// | ||
/// - Parameters: | ||
/// - value: The data to encode. | ||
/// - encoder: The encoder to write data to. | ||
public func encode(_ value: Data, to encoder: Encoder) throws { | ||
let base64Str = value.base64EncodedString(options: encodeOptions) | ||
try base64Str.encode(to: encoder) | ||
} | ||
} |
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
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,38 @@ | ||
import HelperCoders | ||
import MetaCodable | ||
import XCTest | ||
|
||
final class DataCoderTests: XCTestCase { | ||
func testDecoding() throws { | ||
let jsonStr = """ | ||
{ | ||
"data": "SGVsbG8h" | ||
} | ||
""" | ||
let json = try XCTUnwrap(jsonStr.data(using: .utf8)) | ||
let model = try JSONDecoder().decode(Model.self, from: json) | ||
XCTAssertEqual(String(data: model.data, encoding: .utf8), "Hello!") | ||
let encoded = try JSONEncoder().encode(model) | ||
let newModel = try JSONDecoder().decode(Model.self, from: encoded) | ||
XCTAssertEqual(newModel, model) | ||
} | ||
|
||
func testInvalidDataDecoding() throws { | ||
let jsonStr = """ | ||
{ | ||
"data": "invalid data" | ||
} | ||
""" | ||
let json = try XCTUnwrap(jsonStr.data(using: .utf8)) | ||
do { | ||
let _ = try JSONDecoder().decode(Model.self, from: json) | ||
XCTFail("Invalid Base64 conversion") | ||
} catch {} | ||
} | ||
} | ||
|
||
@Codable | ||
fileprivate struct Model: Equatable { | ||
@CodedBy(Base64Coder()) | ||
let data: Data | ||
} |