Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

doc: added tutorials for helper and dynamic decoding/encoding #64

Merged
merged 1 commit into from Feb 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 6 additions & 0 deletions .github/config/spellcheck-wordlist.txt
Expand Up @@ -9,7 +9,10 @@ HelperCoders
JSON
LossySequenceCoder
Codable
Encodable
Decodable
MetaCodable
MetaProtocolCodable
Midbin
README
Refactorings
Expand Down Expand Up @@ -56,3 +59,6 @@ enums
conformances
Podfile
cocoapods
DocumentationExtension
mergeBehavior
lowercasing
4 changes: 2 additions & 2 deletions Sources/HelperCoders/Base64Coder.swift
@@ -1,7 +1,7 @@
import Foundation
import MetaCodable

/// An ``/MetaCodable/HelperCoder`` that helps decoding/encoding
/// An `HelperCoder` that helps decoding/encoding
/// base64 data.
///
/// This type can be used to decode/encode base64 data
Expand All @@ -12,7 +12,7 @@ public struct Base64Coder: HelperCoder {
/// The options to use when encoding data.
private let encodeOptions: Data.Base64EncodingOptions

/// Creates a new instance of ``/MetaCodable/HelperCoder`` that decodes/encodes
/// Creates a new instance of `HelperCoder` that decodes/encodes
/// base64 data.
///
/// - Parameters:
Expand Down
32 changes: 16 additions & 16 deletions Sources/HelperCoders/ConditionalCoder.swift
@@ -1,76 +1,76 @@
import MetaCodable

/// An ``/MetaCodable/HelperCoder`` that helps decoding/encoding
/// with two separate ``/MetaCodable/HelperCoder``s.
/// An `HelperCoder` that helps decoding/encoding
/// with two separate `HelperCoder`s.
///
/// This type can be used to use separate ``/MetaCodable/HelperCoder``s
/// This type can be used to use separate `HelperCoder`s
/// for decoding and encoding.
public struct ConditionalCoder<D: HelperCoder, E: HelperCoder>: HelperCoder
where D.Coded == E.Coded {
/// The ``/MetaCodable/HelperCoder`` used for decoding.
/// The `HelperCoder` used for decoding.
@usableFromInline
internal let decoder: D
/// The ``/MetaCodable/HelperCoder`` used for encoding.
/// The `HelperCoder` used for encoding.
@usableFromInline
internal let encoder: E

/// Creates a new instance of ``/MetaCodable/HelperCoder`` that decodes/encodes
/// Creates a new instance of `HelperCoder` that decodes/encodes
/// conditionally with provided decoder/encoder respectively.
///
/// The provided decoder is used only for decoding
/// and encoder only for encoding.
///
/// - Parameters:
/// - decoder: The ``/MetaCodable/HelperCoder`` used for decoding.
/// - encoder: The ``/MetaCodable/HelperCoder`` used for encoding.
/// - decoder: The `HelperCoder` used for decoding.
/// - encoder: The `HelperCoder` used for encoding.
public init(decoder: D, encoder: E) {
self.decoder = decoder
self.encoder = encoder
}

/// Decodes using the decode specific ``/MetaCodable/HelperCoder``
/// Decodes using the decode specific `HelperCoder`
/// from the given `decoder`.
///
/// - Parameter decoder: The decoder to read data from.
/// - Returns: The decoded value.
/// - Throws: If the underlying ``/MetaCodable/HelperCoder`` throws error.
/// - Throws: If the underlying `HelperCoder` throws error.
@inlinable
public func decode(from decoder: Decoder) throws -> D.Coded {
return try self.decoder.decode(from: decoder)
}

/// Decodes optional value using the decode specific
/// ``/MetaCodable/HelperCoder`` from the given `decoder`.
/// `HelperCoder` from the given `decoder`.
///
/// - Parameter decoder: The decoder to read data from.
/// - Returns: The decoded optional value.
/// - Throws: If the underlying ``/MetaCodable/HelperCoder`` throws error.
/// - Throws: If the underlying `HelperCoder` throws error.
@inlinable
public func decodeIfPresent(from decoder: Decoder) throws -> D.Coded? {
return try self.decoder.decodeIfPresent(from: decoder)
}

/// Encodes using the encode specific ``/MetaCodable/HelperCoder``
/// Encodes using the encode specific `HelperCoder`
/// from the given `encoder`.
///
/// - Parameters:
/// - value: The value to encode.
/// - encoder: The encoder to write data to.
///
/// - Throws: If the underlying ``/MetaCodable/HelperCoder`` throws error.
/// - Throws: If the underlying `HelperCoder` throws error.
@inlinable
public func encode(_ value: E.Coded, to encoder: Encoder) throws {
try self.encoder.encode(value, to: encoder)
}

/// Encodes optional value using the encode specific
/// ``/MetaCodable/HelperCoder`` from the given `encoder`.
/// `HelperCoder` from the given `encoder`.
///
/// - Parameters:
/// - value: The value to encode.
/// - encoder: The encoder to write data to.
///
/// - Throws: If the underlying ``/MetaCodable/HelperCoder`` throws error.
/// - Throws: If the underlying `HelperCoder` throws error.
@inlinable
public func encodeIfPresent(_ value: E.Coded?, to encoder: Encoder) throws {
try self.encoder.encodeIfPresent(value, to: encoder)
Expand Down
6 changes: 3 additions & 3 deletions Sources/HelperCoders/DateCoders/DateCoder.swift
Expand Up @@ -8,7 +8,7 @@ import MetaCodable
/// represented in **ISO 8601** text format.
public typealias ISO8601DateCoder = DateCoder<ISO8601DateFormatter>

/// An ``/MetaCodable/HelperCoder`` that helps decoding/encoding
/// An `HelperCoder` that helps decoding/encoding
/// formatted date representation.
///
/// This type can be used to decode/encode dates
Expand All @@ -18,7 +18,7 @@ public struct DateCoder<Formatter: DateFormatConverter>: HelperCoder {
@usableFromInline
internal let formatter: Formatter

/// Creates a new instance of ``/MetaCodable/HelperCoder`` that decodes/encodes
/// Creates a new instance of `HelperCoder` that decodes/encodes
/// formatted date representation.
///
/// Created instance can be used to decode/encode dates
Expand All @@ -29,7 +29,7 @@ public struct DateCoder<Formatter: DateFormatConverter>: HelperCoder {
self.formatter = formatter
}

/// Creates a new instance of ``/MetaCodable/HelperCoder`` that decodes/encodes
/// Creates a new instance of `HelperCoder` that decodes/encodes
/// **ISO 8601** formatted date representation.
///
/// Created instance can be used to decode/encode dates
Expand Down
4 changes: 2 additions & 2 deletions Sources/HelperCoders/DateCoders/Since1970DateCoder.swift
@@ -1,7 +1,7 @@
import Foundation
import MetaCodable

/// An ``/MetaCodable/HelperCoder`` that helps decoding/encoding
/// An `HelperCoder` that helps decoding/encoding
/// UNIX timestamp.
///
/// This type can be used to decode/encode dates
Expand Down Expand Up @@ -47,7 +47,7 @@ public struct Since1970DateCoder: HelperCoder {
@usableFromInline
internal let type: IntervalType

/// Creates a new instance of ``/MetaCodable/HelperCoder`` that decodes/encodes
/// Creates a new instance of `HelperCoder` that decodes/encodes
/// UNIX timestamp.
///
/// Created instance can be used to decode/encode dates
Expand Down
2 changes: 1 addition & 1 deletion Sources/HelperCoders/HelperCoders.docc/HelperCoders.md
Expand Up @@ -4,7 +4,7 @@
@Available(swift, introduced: "5.9")
}

Level up ``/MetaCodable``'s generated implementations with helpers assisting common decoding/encoding requirements.
Level up `MetaCodable`'s generated implementations with helpers assisting common decoding/encoding requirements.

## Overview

Expand Down
4 changes: 2 additions & 2 deletions Sources/HelperCoders/NonConformingCoder.swift
@@ -1,6 +1,6 @@
import MetaCodable

/// An ``/MetaCodable/HelperCoder`` that helps decoding/encoding
/// An `HelperCoder` that helps decoding/encoding
/// non-confirming floating point values.
///
/// This type can be used to decode/encode exceptional
Expand All @@ -14,7 +14,7 @@ where Float: FloatingPoint & Codable & LosslessStringConvertible {
/// The value representing not-a-number.
private let nan: String

/// Creates a new instance of ``/MetaCodable/HelperCoder`` that decodes/encodes
/// Creates a new instance of `HelperCoder` that decodes/encodes
/// exceptional floating-point values matching provided
/// string representations.
///
Expand Down
6 changes: 3 additions & 3 deletions Sources/HelperCoders/PropertyWrapperCoder.swift
@@ -1,13 +1,13 @@
import MetaCodable

/// An ``/MetaCodable/HelperCoder`` that helps decoding/encoding
/// An `HelperCoder` that helps decoding/encoding
/// using existing property wrappers.
///
/// This type can be used to reuse existing property
/// wrappers with custom decoding/encoding with
/// ``/MetaCodable`` generated implementations.
/// `MetaCodable` generated implementations.
public struct PropertyWrapperCoder<Wrapper: PropertyWrappable>: HelperCoder {
/// Creates a new instance of ``/MetaCodable/HelperCoder`` that decodes/encodes
/// Creates a new instance of `HelperCoder` that decodes/encodes
/// using existing property wrappers.
///
/// - Returns: A new property wrapper based decoder/encoder.
Expand Down
@@ -1,6 +1,6 @@
import MetaCodable

/// An ``/MetaCodable/HelperCoder`` that performs default decoding/encoding.
/// An `HelperCoder` that performs default decoding/encoding.
///
/// This type doesn't provide any customization and used only to opt out of
/// decoding/encoding customizations.
Expand Down
14 changes: 7 additions & 7 deletions Sources/HelperCoders/SequenceCoder/SequenceCoder.swift
@@ -1,19 +1,19 @@
import MetaCodable

/// An ``/MetaCodable/HelperCoder`` that helps decoding/encoding sequence.
/// An `HelperCoder` that helps decoding/encoding sequence.
///
/// This type tries to decode and encode a sequence according to provided
/// ``Configuration-swift.struct`` and element ``/MetaCodable/HelperCoder``.
/// ``Configuration-swift.struct`` and element `HelperCoder`.
///
/// `DefaultSequenceElementCoding` can be used as element
/// ``/MetaCodable/HelperCoder``, if on configuration based.
/// `HelperCoder`, if on configuration based.
/// decoding/encoding needed
public struct SequenceCoder<Sequence, ElementHelper>: HelperCoder
where
Sequence: SequenceInitializable, ElementHelper: HelperCoder,
Sequence.Element == ElementHelper.Coded
{
/// The ``/MetaCodable/HelperCoder`` for element.
/// The `HelperCoder` for element.
///
/// Each element is decoded/encoded using this.
public let elementHelper: ElementHelper
Expand All @@ -28,7 +28,7 @@ where
///
/// - Parameters:
/// - output: The resulting sequence type.
/// - elementHelper: The ``/MetaCodable/HelperCoder`` for element.
/// - elementHelper: The `HelperCoder` for element.
/// - configuration: The configuration for decoding and encoding.
public init(
output: Sequence.Type, elementHelper: ElementHelper,
Expand All @@ -43,7 +43,7 @@ where
/// Sequence type is inferred from provided configuration.
///
/// - Parameters:
/// - elementHelper: The ``/MetaCodable/HelperCoder`` for element.
/// - elementHelper: The `HelperCoder` for element.
/// - configuration: The configuration for decoding and encoding.
public init(
elementHelper: ElementHelper, configuration: Configuration
Expand Down Expand Up @@ -92,7 +92,7 @@ where
/// By default, no additional customizations configuration is used.
///
/// - Parameters:
/// - elementHelper: The ``/MetaCodable/HelperCoder`` for element.
/// - elementHelper: The `HelperCoder` for element.
/// - configuration: The configuration for decoding and encoding.
public init(
elementHelper: ElementHelper, configuration: Configuration = .init()
Expand Down
4 changes: 2 additions & 2 deletions Sources/HelperCoders/ValueCoders/ValueCoder.swift
@@ -1,12 +1,12 @@
import MetaCodable

/// An ``/MetaCodable/HelperCoder`` that helps decoding/encoding
/// An `HelperCoder` that helps decoding/encoding
/// basic value types.
///
/// This type can be used to decode/encode dates
/// basic value types, i.e. `Bool`, `Int`, `String` etc.
public struct ValueCoder<Strategy: ValueCodingStrategy>: HelperCoder {
/// Creates a new instance of ``/MetaCodable/HelperCoder`` that decodes/encodes
/// Creates a new instance of `HelperCoder` that decodes/encodes
/// basic value types.
///
/// - Returns: A new basic value type decoder/encoder.
Expand Down
6 changes: 3 additions & 3 deletions Sources/MetaCodable/MetaCodable.docc/Limitations.md
Expand Up @@ -61,18 +61,18 @@ enum SomeEnum {
}
```

### Why `enum`s with raw value aren't supported?
### Why enums with raw value aren't supported?

`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.

### Why `actor` conformance to `Encodable` not generated?
### Why actor conformance to Encodable not generated?

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`.

To generate `Encodable` conformance, the `encode(to:)` method must be `nonisolated` to `actor`, and since `encode(to:)` method must be synchronous making it `nonisolated` will prevent accessing mutable properties.

Due to these limitations, `Encodable` conformance isn't generated, users has to implement the conformance manually.

### Why `MetaProtocolCodable` plugin can't scan Xcode target dependencies?
### Why MetaProtocolCodable plugin can't scan Xcode target dependencies?

Currently Swift Package Manager always returns empty list for Xcode target dependencies as noted in [this bug](https://github.com/apple/swift-package-manager/issues/6003). Hence `MetaProtocolCodable` can currently only scan the files from the target or from the project including the target.
1 change: 1 addition & 0 deletions Sources/MetaCodable/MetaCodable.docc/MetaCodable.md
Expand Up @@ -95,3 +95,4 @@ Supercharge `Swift`'s `Codable` implementations with macros.

- ``DynamicCodable``
- ``DynamicCodableIdentifier``
- ``MetaCodableConfig``
@@ -0,0 +1,25 @@
# ``MetaCodableConfig``

@Metadata {
@DocumentationExtension(mergeBehavior: override)
}

The configuration file providing additional customization options for `MetaProtocolCodable` build tool plugin.

## Overview

The data present in this file can be either of `plist` or `json` format. The name of the configuration file can be of any format as long as removing non-alphanumeric characters and lowercasing the name matches `metacodableconfig` text, i.e. following names are supported:

- `MetaCodableConfig.plist`
- `meta_codable_config.json`
- `meta-codable-config.json` etc.

- Important: The file must be added at the target root directory for Swift packages and for Xcode targets the file must be part of the target.

- Tip: The option names/keys provided in this file are also case-insensitive. i.e. `Scan`, `scan`, `SCAN` are all valid option names for ``Scan``.

## Topics

### Options

- ``Scan``
16 changes: 16 additions & 0 deletions Sources/MetaCodable/MetaCodable.docc/MetaCodableConfig/Scan.md
@@ -0,0 +1,16 @@
# ``MetaCodableConfig/Scan``

@Metadata {
@DocumentationExtension(mergeBehavior: override)
}

The source file scan option for `MetaProtocolCodable` build tool plugin.

## Overview

This option can accept any of the following values, depending on which the source files scanned by `MetaProtocolCodable` build tool plugin is controlled:

- `target`: Source files present in the `MetaProtocolCodable` build tool plugin target are scanned rest of the files are ignored.
- `direct`: Source files present in the `MetaProtocolCodable` build tool plugin target and its direct dependencies are scanned rest of the files are ignored.
- `local`: Source files present in the `MetaProtocolCodable` build tool plugin target and only its direct dependencies which are local dependencies are scanned rest of the files are ignored.
- `recursive`: Source files present in the `MetaProtocolCodable` build tool plugin target and all its dependencies are scanned rest of the files are ignored.