Skip to content

Commit 06d593c

Browse files
committed
Implement Encoding and built-in encodings.
1 parent f3066bf commit 06d593c

File tree

3 files changed

+749
-8
lines changed

3 files changed

+749
-8
lines changed

Package.swift

+6
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@ import PackageDescription
55

66
let package = Package(
77
name: "swift-coding",
8+
platforms: [
9+
.iOS(.v13),
10+
.macOS(.v10_15),
11+
.tvOS(.v13),
12+
.watchOS(.v6),
13+
],
814
products: [
915
.library(
1016
name: "Coding",

Sources/Coding/Encoding.swift

+378-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,379 @@
1-
struct swift_coding {
2-
var text = "Hello, World!"
1+
import Foundation
2+
import Combine
3+
4+
// MARK: - Interface
5+
6+
/// Represents a way of encoding a single value.
7+
public struct Encoding<Value> {
8+
/// A function that uses the provided encoder to encode the given input value.
9+
public var encode: (Value, Encoder) throws -> Void
10+
11+
public init(encode: @escaping (Value, Encoder) throws -> Void) {
12+
self.encode = encode
13+
}
14+
}
15+
16+
// MARK: - Operators
17+
18+
public extension Encoding {
19+
/// Combines multiple encodings of the same type itnto a single encoding.
20+
///
21+
static func combine(_ encodings: Self...) -> Self {
22+
.init { value, encoder in
23+
for encoding in encodings {
24+
try encoding.encode(value, encoder)
25+
}
26+
}
27+
}
28+
29+
/// Transforms an encoding of type `Value` to produce a new encoding of type `NewValue`.
30+
///
31+
/// You can use this function to derive new encodings from existing ones - a common use case would be to
32+
/// transform an encoding of some lower-level type into some higher-level type by pulling back along a property
33+
/// on the higher-level type.
34+
///
35+
/// - Parameters:
36+
/// - transform: A function that transforms values of `NewValue` into `Value`.
37+
///
38+
func pullback<NewValue>(_ transform: @escaping (NewValue) -> Value) -> Encoding<NewValue> {
39+
.init { newValue, encoder in
40+
try self.encode(transform(newValue), encoder)
41+
}
42+
}
43+
44+
/// Turns an encoding of some non-optional value type into an encoding of an optional value of the same type.
45+
///
46+
/// You can use this to encode optional values only if they are non-nil.
47+
///
48+
func optional() -> Encoding<Value?> {
49+
.init { value, encoder in
50+
guard let value = value else { return }
51+
try self.encode(value, encoder)
52+
}
53+
}
54+
55+
/// Turns an encoding of some non-optional value type into an encoding of an optional value of the same type.
56+
///
57+
/// Unlike `.optional()`, this will return an encoding that will encode the value if it is non-nil, otherwise it
58+
/// will encode the provided default value instead.
59+
///
60+
/// - Parameters:
61+
/// - defaultValue: The value to encode when the input value is nil.
62+
///
63+
func defaulting(to defaultValue: Value) -> Encoding<Value?> {
64+
.init { value, encoder in
65+
try self.encode(value ?? defaultValue, encoder)
66+
}
67+
}
68+
}
69+
70+
// MARK: - Encoder API
71+
72+
fileprivate struct EncodingProxy<T>: Encodable {
73+
let value: T
74+
let encoding: Encoding<T>
75+
76+
func encode(to encoder: Encoder) throws {
77+
try encoding.encode(value, encoder)
78+
}
79+
}
80+
81+
public extension TopLevelEncoder {
82+
/// Encodes a value `T` using the given encoding.
83+
///
84+
/// - Parameters:
85+
/// - value: The value to be encoded.
86+
/// - encoding: The encoding used to encode the value.
87+
///
88+
func encode<T>(_ value: T, as encoding: Encoding<T>) throws -> Output {
89+
try encode(EncodingProxy(value: value, encoding: encoding))
90+
}
91+
}
92+
93+
// MARK: - Built-in encodings
94+
95+
public extension Encoding where Value == UInt16 {
96+
static let singleValue = Self { value, encoder in
97+
var container = encoder.singleValueContainer()
98+
try container.encode(value)
99+
}
100+
101+
static let unkeyed = Self { value, encoder in
102+
var container = encoder.unkeyedContainer()
103+
try container.encode(value)
104+
}
105+
106+
static func withKey<Key: CodingKey>(_ key: Key) -> Self {
107+
.init { value, encoder in
108+
var container = encoder.container(keyedBy: Key.self)
109+
try container.encode(value, forKey: key)
110+
}
111+
}
112+
}
113+
114+
public extension Encoding where Value == Int64 {
115+
static let singleValue = Self { value, encoder in
116+
var container = encoder.singleValueContainer()
117+
try container.encode(value)
118+
}
119+
120+
static let unkeyed = Self { value, encoder in
121+
var container = encoder.unkeyedContainer()
122+
try container.encode(value)
123+
}
124+
125+
static func withKey<Key: CodingKey>(_ key: Key) -> Self {
126+
.init { value, encoder in
127+
var container = encoder.container(keyedBy: Key.self)
128+
try container.encode(value, forKey: key)
129+
}
130+
}
131+
}
132+
133+
public extension Encoding where Value == Int8 {
134+
static let singleValue = Self { value, encoder in
135+
var container = encoder.singleValueContainer()
136+
try container.encode(value)
137+
}
138+
139+
static let unkeyed = Self { value, encoder in
140+
var container = encoder.unkeyedContainer()
141+
try container.encode(value)
142+
}
143+
144+
static func withKey<Key: CodingKey>(_ key: Key) -> Self {
145+
.init { value, encoder in
146+
var container = encoder.container(keyedBy: Key.self)
147+
try container.encode(value, forKey: key)
148+
}
149+
}
150+
}
151+
152+
public extension Encoding where Value == Double {
153+
static let singleValue = Self { value, encoder in
154+
var container = encoder.singleValueContainer()
155+
try container.encode(value)
156+
}
157+
158+
static let unkeyed = Self { value, encoder in
159+
var container = encoder.unkeyedContainer()
160+
try container.encode(value)
161+
}
162+
163+
static func withKey<Key: CodingKey>(_ key: Key) -> Self {
164+
.init { value, encoder in
165+
var container = encoder.container(keyedBy: Key.self)
166+
try container.encode(value, forKey: key)
167+
}
168+
}
169+
}
170+
171+
public extension Encoding where Value == String {
172+
static let singleValue = Self { value, encoder in
173+
var container = encoder.singleValueContainer()
174+
try container.encode(value)
175+
}
176+
177+
static let unkeyed = Self { value, encoder in
178+
var container = encoder.unkeyedContainer()
179+
try container.encode(value)
180+
}
181+
182+
static func withKey<Key: CodingKey>(_ key: Key) -> Self {
183+
.init { value, encoder in
184+
var container = encoder.container(keyedBy: Key.self)
185+
try container.encode(value, forKey: key)
186+
}
187+
}
188+
}
189+
190+
public extension Encoding where Value == UInt64 {
191+
static let singleValue = Self { value, encoder in
192+
var container = encoder.singleValueContainer()
193+
try container.encode(value)
194+
}
195+
196+
static let unkeyed = Self { value, encoder in
197+
var container = encoder.unkeyedContainer()
198+
try container.encode(value)
199+
}
200+
201+
static func withKey<Key: CodingKey>(_ key: Key) -> Self {
202+
.init { value, encoder in
203+
var container = encoder.container(keyedBy: Key.self)
204+
try container.encode(value, forKey: key)
205+
}
206+
}
207+
}
208+
209+
public extension Encoding where Value == UInt8 {
210+
static let singleValue = Self { value, encoder in
211+
var container = encoder.singleValueContainer()
212+
try container.encode(value)
213+
}
214+
215+
static let unkeyed = Self { value, encoder in
216+
var container = encoder.unkeyedContainer()
217+
try container.encode(value)
218+
}
219+
220+
static func withKey<Key: CodingKey>(_ key: Key) -> Self {
221+
.init { value, encoder in
222+
var container = encoder.container(keyedBy: Key.self)
223+
try container.encode(value, forKey: key)
224+
}
225+
}
226+
}
227+
228+
public extension Encoding where Value == Float {
229+
static let singleValue = Self { value, encoder in
230+
var container = encoder.singleValueContainer()
231+
try container.encode(value)
232+
}
233+
234+
static let unkeyed = Self { value, encoder in
235+
var container = encoder.unkeyedContainer()
236+
try container.encode(value)
237+
}
238+
239+
static func withKey<Key: CodingKey>(_ key: Key) -> Self {
240+
.init { value, encoder in
241+
var container = encoder.container(keyedBy: Key.self)
242+
try container.encode(value, forKey: key)
243+
}
244+
}
245+
}
246+
247+
public extension Encoding where Value == UInt32 {
248+
static let singleValue = Self { value, encoder in
249+
var container = encoder.singleValueContainer()
250+
try container.encode(value)
251+
}
252+
253+
static let unkeyed = Self { value, encoder in
254+
var container = encoder.unkeyedContainer()
255+
try container.encode(value)
256+
}
257+
258+
static func withKey<Key: CodingKey>(_ key: Key) -> Self {
259+
.init { value, encoder in
260+
var container = encoder.container(keyedBy: Key.self)
261+
try container.encode(value, forKey: key)
262+
}
263+
}
264+
}
265+
266+
public extension Encoding where Value == UInt {
267+
static let singleValue = Self { value, encoder in
268+
var container = encoder.singleValueContainer()
269+
try container.encode(value)
270+
}
271+
272+
static let unkeyed = Self { value, encoder in
273+
var container = encoder.unkeyedContainer()
274+
try container.encode(value)
275+
}
276+
277+
static func withKey<Key: CodingKey>(_ key: Key) -> Self {
278+
.init { value, encoder in
279+
var container = encoder.container(keyedBy: Key.self)
280+
try container.encode(value, forKey: key)
281+
}
282+
}
283+
}
284+
285+
public extension Encoding where Value == Int16 {
286+
static let singleValue = Self { value, encoder in
287+
var container = encoder.singleValueContainer()
288+
try container.encode(value)
289+
}
290+
291+
static let unkeyed = Self { value, encoder in
292+
var container = encoder.unkeyedContainer()
293+
try container.encode(value)
294+
}
295+
296+
static func withKey<Key: CodingKey>(_ key: Key) -> Self {
297+
.init { value, encoder in
298+
var container = encoder.container(keyedBy: Key.self)
299+
try container.encode(value, forKey: key)
300+
}
301+
}
302+
}
303+
304+
public extension Encoding where Value == Int {
305+
static let singleValue = Self { value, encoder in
306+
var container = encoder.singleValueContainer()
307+
try container.encode(value)
308+
}
309+
310+
static let unkeyed = Self { value, encoder in
311+
var container = encoder.unkeyedContainer()
312+
try container.encode(value)
313+
}
314+
315+
static func withKey<Key: CodingKey>(_ key: Key) -> Self {
316+
.init { value, encoder in
317+
var container = encoder.container(keyedBy: Key.self)
318+
try container.encode(value, forKey: key)
319+
}
320+
}
321+
}
322+
323+
public extension Encoding where Value == Int32 {
324+
static let singleValue = Self { value, encoder in
325+
var container = encoder.singleValueContainer()
326+
try container.encode(value)
327+
}
328+
329+
static let unkeyed = Self { value, encoder in
330+
var container = encoder.unkeyedContainer()
331+
try container.encode(value)
332+
}
333+
334+
static func withKey<Key: CodingKey>(_ key: Key) -> Self {
335+
.init { value, encoder in
336+
var container = encoder.container(keyedBy: Key.self)
337+
try container.encode(value, forKey: key)
338+
}
339+
}
340+
}
341+
342+
public extension Encoding where Value: Encodable {
343+
static var singleValue: Self {
344+
.init { value, encoder in
345+
var container = encoder.singleValueContainer()
346+
try container.encode(value)
347+
}
348+
}
349+
350+
static var unkeyed: Self {
351+
Self { value, encoder in
352+
var container = encoder.unkeyedContainer()
353+
try container.encode(value)
354+
}
355+
}
356+
357+
static func withKey<Key: CodingKey>(_ key: Key) -> Self {
358+
.init { value, encoder in
359+
var container = encoder.container(keyedBy: Key.self)
360+
try container.encode(value, forKey: key)
361+
}
362+
}
363+
}
364+
365+
public extension Encoding {
366+
static var nullValue: Self {
367+
.init { _, encoder in
368+
var container = encoder.singleValueContainer()
369+
try container.encodeNil()
370+
}
371+
}
372+
373+
static func nullValue<Key: CodingKey>(key: Key) -> Self {
374+
.init { _, encoder in
375+
var container = encoder.container(keyedBy: Key.self)
376+
try container.encodeNil(forKey: key)
377+
}
378+
}
3379
}

0 commit comments

Comments
 (0)