Skip to content

Commit 2670fde

Browse files
committed
doc: added sample usage tutorials
1 parent a28bb9c commit 2670fde

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

65 files changed

+855
-10
lines changed

.github/config/spellcheck-wordlist.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,3 +50,6 @@ vscode
5050
watchOS
5151
www
5252
typealias
53+
customizable
54+
enum
55+
enums

README.md

Lines changed: 69 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# MetaCodable
22

3-
[![API Docs](http://img.shields.io/badge/Read_the-docs-2196f3.svg)](https://swiftpackageindex.com/SwiftyLab/MetaCodable/main/documentation/metacodable)
3+
[![API Docs](http://img.shields.io/badge/Read_the-docs-2196f3.svg)](https://swiftpackageindex.com/SwiftyLab/MetaCodable/documentation/metacodable)
44
[![Swift Package Manager Compatible](https://img.shields.io/github/v/tag/SwiftyLab/MetaCodable?label=SPM&color=orange)](https://badge.fury.io/gh/SwiftyLab%2FMetaCodable)
55
[![Swift](https://img.shields.io/badge/Swift-5.9+-orange)](https://img.shields.io/badge/Swift-5-DE5D43)
66
[![Platforms](https://img.shields.io/badge/Platforms-all-sucess)](https://img.shields.io/badge/Platforms-all-sucess)
@@ -229,13 +229,79 @@ Library provides following helpers that address common custom decoding/encoding
229229
- Custom Date decoding/encoding with UNIX timestamp (`Since1970DateCoder`) or date formatters (`DateCoder`, `ISO8601DateCoder`).
230230
- `Base64Coder` to decode/encode data in base64 string representation.
231231

232-
And more, see the full documentation for [`HelperCoders`](https://swiftpackageindex.com/SwiftyLab/MetaCodable/main/documentation/helpercoders) for more details.
232+
And more, see the full documentation for [`HelperCoders`](https://swiftpackageindex.com/SwiftyLab/MetaCodable/documentation/helpercoders) for more details.
233233

234234
You can even create your own by conforming to `HelperCoder`.
235235

236236
</details>
237237

238-
See the full documentation for [`MetaCodable`](https://swiftpackageindex.com/SwiftyLab/MetaCodable/main/documentation/metacodable) and [`HelperCoders`](https://swiftpackageindex.com/SwiftyLab/MetaCodable/main/documentation/helpercoders), for API details and advanced use cases.
238+
<details>
239+
<summary>Represent data with variations in the form of external/internal/adjacent tagging, with single enum with each case as a variation.</summary>
240+
241+
i.e. while `Swift` compiler only generates implementation assuming external tagged enums, only following data:
242+
243+
```json
244+
[
245+
{
246+
"load": {
247+
"key": "MyKey"
248+
}
249+
},
250+
{
251+
"store": {
252+
"key": "MyKey",
253+
"value": 42
254+
}
255+
}
256+
]
257+
```
258+
259+
can be represented by following `enum` with current compiler implementation:
260+
261+
```swift
262+
enum Command {
263+
case load(key: String)
264+
case store(key: String, value: Int)
265+
}
266+
```
267+
268+
while `MetaCodable` allows data in both of the following format to be represented by above `enum` as well:
269+
270+
```json
271+
[
272+
{
273+
"type": "load",
274+
"key": "MyKey"
275+
},
276+
{
277+
"type": "store",
278+
"key": "MyKey",
279+
"value": 42
280+
}
281+
]
282+
```
283+
284+
```json
285+
[
286+
{
287+
"type": "load",
288+
"content": {
289+
"key": "MyKey"
290+
}
291+
},
292+
{
293+
"type": "store",
294+
"content": {
295+
"key": "MyKey",
296+
"value": 42
297+
}
298+
}
299+
]
300+
```
301+
302+
</details>
303+
304+
See the full documentation for [`MetaCodable`](https://swiftpackageindex.com/SwiftyLab/MetaCodable/documentation/metacodable) and [`HelperCoders`](https://swiftpackageindex.com/SwiftyLab/MetaCodable/documentation/helpercoders), for API details and advanced use cases.
239305
Also, [see the limitations](Sources/MetaCodable/MetaCodable.docc/Limitations.md).
240306

241307
## Contributing

Sources/CodableMacroPlugin/Variables/Syntax/EnumCaseVariableDeclSyntax.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ struct EnumCaseVariableDeclSyntax: MemberGroupSyntax, AttributableDeclSyntax {
77
/// The `Variable` type this syntax represents.
88
///
99
/// Represents basic enum-case variable decoding/encoding data.
10-
typealias Variable = EnumCaseVariable
10+
typealias Variable = BasicEnumCaseVariable
1111

1212
/// The actual variable syntax.
1313
///

Sources/CodableMacroPlugin/Variables/Type/Data/CodingKeysMap/CodingKeysMap.swift

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,12 @@ final class CodingKeysMap {
2222
/// `add(forKeys:field:context:)`
2323
/// method.
2424
private var data: OrderedDictionary<String, Case> = [:]
25+
/// The `CodingKey`s that have been used.
26+
///
27+
/// Represents these `CodingKey`s have been used
28+
/// in generated code syntax and must be present as case
29+
/// in generated `CodingKey` enum declaration.
30+
private var usedKeys: Set<String> = []
2531

2632
/// Creates a new case-map with provided enum name.
2733
///
@@ -116,13 +122,17 @@ final class CodingKeysMap {
116122

117123
/// The case name token syntax available for a key.
118124
///
125+
/// Adds key to the list of used keys, as this method is invoked to use
126+
/// key in generated code syntax.
127+
///
119128
/// - Parameter key: The key to look up against.
120129
/// - Returns: The token syntax for case name stored against
121130
/// a key if exists. Otherwise `nil` returned.
122131
///
123132
/// - Note: Should only be used after case names generated
124133
/// or all the keys for a particular type.
125134
func `case`(forKey key: String) -> TokenSyntax? {
135+
usedKeys.insert(key)
126136
return data[key]?.token
127137
}
128138

@@ -132,6 +142,8 @@ final class CodingKeysMap {
132142
/// The generated enum is a raw enum of `String` type
133143
/// and confirms to `CodingKey`.
134144
///
145+
/// Only keys used in generated code syntax is present in this enum.
146+
///
135147
/// - Parameter context: The macro expansion context.
136148
/// - Returns: The generated enum declaration syntax.
137149
func decl(in context: some MacroExpansionContext) -> EnumDeclSyntax? {
@@ -141,7 +153,7 @@ final class CodingKeysMap {
141153
InheritedTypeSyntax(type: "CodingKey" as TypeSyntax)
142154
}
143155
return EnumDeclSyntax(name: typeName, inheritanceClause: clause) {
144-
for (key, `case`) in data {
156+
for (key, `case`) in data where usedKeys.contains(key) {
145157
"case \(`case`.token) = \(literal: key)" as DeclSyntax
146158
}
147159
}

Sources/MetaCodable/Codable/Codable.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
/// * Use ``Default(_:)`` to provide default value when decoding fails.
1818
/// * Use ``CodedAs(_:)`` to provided custom value for enum cases.
1919
/// * Use ``CodedAt(_:)`` to provide enum-case identifier tag path.
20+
/// * Use ``CodedAs()`` to provide enum-case identifier tag type.
2021
/// * Use ``ContentAt(_:_:)`` to provided enum-case content path.
2122
/// * Use ``IgnoreCoding()``, ``IgnoreDecoding()`` and
2223
/// ``IgnoreEncoding()`` to ignore specific properties/cases from

Sources/MetaCodable/CodedAs.swift

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,12 @@
1818
/// when generating final implementations.
1919
///
2020
/// - Important: The value type must be `String` when used in
21-
/// externally tagged enums.
21+
/// externally tagged enums, and internally/adjacently tagged enums
22+
/// without type specified with ``CodedAs()`` macro. When used
23+
/// along with ``CodedAs()`` macro, both the generic type must be same.
2224
@attached(peer)
2325
@available(swift 5.9)
24-
public macro CodedAs<T: Codable>(_ value: T) =
26+
public macro CodedAs<T: Codable & Equatable>(_ value: T) =
2527
#externalMacro(module: "CodableMacroPlugin", type: "CodedAs")
2628

2729
/// Provides the identifier actual type for internally/adjacently tagged enums.
@@ -56,7 +58,10 @@ public macro CodedAs<T: Codable>(_ value: T) =
5658
/// will be used for comparison. If the type here conforms to
5759
/// `ExpressibleByStringLiteral` and can be represented by case name
5860
/// as `String` literal then no need to provide value with ``CodedAs(_:)``.
61+
///
62+
/// - Important: This attribute must be used combined with ``Codable()``
63+
/// and ``CodedAt(_:)``.
5964
@attached(peer)
6065
@available(swift 5.9)
61-
public macro CodedAs<T: Codable>() =
66+
public macro CodedAs<T: Codable & Equatable>() =
6267
#externalMacro(module: "CodableMacroPlugin", type: "CodedAs")

Sources/MetaCodable/CodedBy.swift

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/// Indicates the field needs to be decoded and encoded by
1+
/// Indicates the field/enum identifier needs to be decoded and encoded by
22
/// the provided `helper` instance.
33
///
44
/// An instance confirming to ``HelperCoder`` can be provided
@@ -7,6 +7,9 @@
77
/// sequence from JSON ignoring invalid data matches instead of throwing error
88
/// (failing decoding of entire sequence).
99
///
10+
/// For enums, applying this attribute means ``HelperCoder`` will be used to
11+
/// decode and encode identifier value in internally or adjacently tagged enums.
12+
///
1013
/// - Parameter helper: The value that performs decoding and encoding.
1114
///
1215
/// - Note: This macro on its own only validates if attached declaration
@@ -15,6 +18,9 @@
1518
///
1619
/// - Important: The `helper`'s ``HelperCoder/Coded``
1720
/// associated type must be the same as field type.
21+
///
22+
/// - Important: This attribute must be used combined with ``Codable()``
23+
/// and ``CodedAt(_:)`` when applying to enums.
1824
@attached(peer)
1925
@available(swift 5.9)
2026
public macro CodedBy<T: HelperCoder>(_ helper: T) =

Sources/MetaCodable/ContentAt.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@
2626
/// - Note: This macro on its own only validates if attached declaration
2727
/// is a variable declaration. ``Codable()`` macro uses this macro
2828
/// when generating final implementations.
29+
///
30+
/// - Important: This attribute must be used combined with ``Codable()``
31+
/// and ``CodedAt(_:)``.
2932
@attached(peer)
3033
@available(swift 5.9)
3134
public macro ContentAt(_ path: StaticString, _: StaticString...) =

Sources/MetaCodable/HelperCoders/LossySequence.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ where S: Codable, S.Element: Codable {
5555
}
5656

5757
/// A sequence type that can be initialized from another sequence.
58+
@_documentation(visibility:internal)
5859
public protocol SequenceInitializable: Sequence {
5960
/// Creates a new instance of a sequence containing the elements of
6061
/// provided sequence.

Sources/MetaCodable/MetaCodable.docc/Limitations.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ Currently all the limitations of this library and possible workarounds and futur
88

99
### Why strict typing is necessary?
1010

11-
`Swift` doesn't provide any type inference data, so to know type of variables ``Codable()`` needs types to be explicitly specified in the code. i.e. following code will not work and will cause error while macro expansion:
11+
`Swift` compiler doesn't provide any type inference data to macros, so to know type of variables ``Codable()`` needs types to be explicitly specified in the code. i.e. following code will not work and will cause error while macro expansion:
1212

1313
```swift
1414
@Codable
@@ -61,6 +61,10 @@ enum SomeEnum {
6161
}
6262
```
6363

64+
### Why `enum`s with raw value aren't supported?
65+
66+
`Swift` compiler by default generates `Codable` conformance for `enum`s with raw value and `MetaCodable` has nothing extra to add for these type of `enum`s. Hence, in this case the default compiler generated implementation can be used.
67+
6468
### Why `actor` conformance to `Encodable` not generated?
6569

6670
For `actor`s ``Codable()`` generates `Decodable` conformance, while `Encodable` conformance isn't generated, only `encode(to:)` method implementation is generated which is isolated to `actor`.

0 commit comments

Comments
 (0)