Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 82 additions & 0 deletions .github/workflows/pull_request.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
name: Pull Request

on:
pull_request:
branches: [ main ]
workflow_dispatch:

env:
SCHEME: "CodablePlus"

jobs:
Lint:
runs-on: macos-26
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Lint
run: swiftformat --lint . --reporter github-actions-log

Swift:
strategy:
fail-fast: false
matrix:
os: [
macos-26,
ubuntu-latest,
]
runs-on: ${{ matrix.os }}
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Cache
uses: actions/cache@v5
with:
path: |
.build
~/Library/Developer/Xcode/DerivedData/ModuleCache.noindex
~/Library/Caches/org.swift.swiftpm
~/Library/org.swift.swiftpm
key: ${{ runner.os }}-spm-${{ hashFiles('**/Package.swift', '**/Package.resolved') }}
restore-keys: |
${{ runner.os }}-spm-
- name: Package Resolution
run: swift package resolve
- name: Build
run: swift build
- name: Test
run: swift test

Xcode:
strategy:
fail-fast: false
matrix:
platform: [
"macOS",
"iOS",
"tvOS",
"watchOS",
"visionOS",
"macOS,variant=Mac Catalyst",
]
runs-on: macos-26
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Cache
uses: actions/cache@v5
with:
path: |
.build
~/Library/Developer/Xcode/DerivedData/ModuleCache.noindex
~/Library/Caches/org.swift.swiftpm
~/Library/org.swift.swiftpm
key: ${{ runner.os }}-spm-${{ hashFiles('**/Package.swift', '**/Package.resolved') }}
restore-keys: |
${{ runner.os }}-spm-
- name: Package Resolution
run: set -o pipefail && xcodebuild -resolvePackageDependencies | xcbeautify
- name: Build
env:
DESTINATION: "generic/platform=${{ matrix.platform }}"
run: set -o pipefail && xcodebuild build -scheme "$SCHEME" -destination "$DESTINATION" | xcbeautify
35 changes: 0 additions & 35 deletions .github/workflows/swift.yml

This file was deleted.

16 changes: 16 additions & 0 deletions .swiftformat
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Compiler
--languagemode 5
--swiftversion 5.9

# Options
--exclude derivedData
--ifdef no-indent
--indent 4

# Rules
--disable blankLinesAtStartOfScope
--disable hoistPatternLet
--disable redundantType
--disable unusedArguments
--disable wrapArguments
--disable wrapPropertyBodies
7 changes: 4 additions & 3 deletions Package.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// swift-tools-version:5.8
// swift-tools-version:5.9
// The swift-tools-version declares the minimum version of Swift required to build this package.

import PackageDescription
Expand All @@ -10,15 +10,16 @@ let package = Package(
.macCatalyst(.v15),
.iOS(.v15),
.tvOS(.v15),
.watchOS(.v8)
.watchOS(.v8),
.visionOS(.v1),
],
products: [
.library(
name: "CodablePlus",
targets: ["CodablePlus"]),
],
dependencies: [

],
targets: [
.target(
Expand Down
4 changes: 2 additions & 2 deletions Sources/CodablePlus/AnyEncodable.swift
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
/// A type-erased container that supports encoding its value to a `SingleValueEncodingContainer`.
public struct AnyEncodable: Encodable {
let value: Encodable

public init(_ value: Encodable) {
self.value = value
}

public func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
try value.encode(to: &container)
Expand Down
6 changes: 3 additions & 3 deletions Sources/CodablePlus/DictionaryKeys.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,13 @@ import Foundation
public struct DictionaryKeys: CodingKey {
public var stringValue: String
public var intValue: Int?

public init(stringValue: String) {
self.stringValue = stringValue
}

public init(intValue: Int) {
self.stringValue = "\(intValue)"
stringValue = "\(intValue)"
self.intValue = intValue
}
}
8 changes: 4 additions & 4 deletions Sources/CodablePlus/KeyedDecodingContainerProtocol+Any.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ public extension KeyedDecodingContainerProtocol {
return doubleValue
} else if let stringValue = try? decode(String.self, forKey: key) {
return stringValue
} else if let nestedDictionary = try? decode(Dictionary<String, Any>.self, forKey: key) {
} else if let nestedDictionary = try? decode([String: Any].self, forKey: key) {
return nestedDictionary
} else if let nestedArray = try? decode(Array<Any>.self, forKey: key) {
} else if let nestedArray = try? decode([Any].self, forKey: key) {
return nestedArray
} else if try decodeNil(forKey: key) {
return NSNull()
Expand All @@ -24,15 +24,15 @@ public extension KeyedDecodingContainerProtocol {
throw DecodingError.dataCorrupted(context)
}
}

/// Decodes a value of any decodable type, if present.
///
/// - parameter key: The key that the decoded value is associated with.
func decodeAnyIfPresent(forKey key: Key) throws -> Any? {
guard contains(key) else {
return nil
}

return try decodeAny(forKey: key)
}
}
34 changes: 17 additions & 17 deletions Sources/CodablePlus/KeyedDecodingContainerProtocol+Containers.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ public extension KeyedDecodingContainerProtocol {
/// for the given key.
/// - throws: `DecodingError.valueNotFound` if `self` has a null entry for
/// the given key.
func decode(_ type: Dictionary<String, Any>.Type, forKey key: Key) throws -> Dictionary<String, Any> {
let container = try self.nestedContainer(keyedBy: DictionaryKeys.self, forKey: key)
func decode(_ type: [String: Any].Type, forKey key: Key) throws -> [String: Any] {
let container = try nestedContainer(keyedBy: DictionaryKeys.self, forKey: key)
return try container.decode(type)
}

Expand All @@ -30,8 +30,8 @@ public extension KeyedDecodingContainerProtocol {
/// for the given key.
/// - throws: `DecodingError.valueNotFound` if `self` has a null entry for
/// the given key.
func decode(_ type: Array<Any>.Type, forKey key: Key) throws -> Array<Any> {
var container = try self.nestedUnkeyedContainer(forKey: key)
func decode(_ type: [Any].Type, forKey key: Key) throws -> [Any] {
var container = try nestedUnkeyedContainer(forKey: key)
return try container.decode(type)
}

Expand All @@ -48,7 +48,7 @@ public extension KeyedDecodingContainerProtocol {
/// the value is a null value.
/// - throws: `DecodingError.typeMismatch` if the encountered encoded value
/// is not convertible to the requested type.
func decodeIfPresent(_ type: Dictionary<String, Any>.Type, forKey key: Key) throws -> Dictionary<String, Any>? {
func decodeIfPresent(_ type: [String: Any].Type, forKey key: Key) throws -> [String: Any]? {
guard contains(key) else {
return nil
}
Expand All @@ -69,7 +69,7 @@ public extension KeyedDecodingContainerProtocol {
/// the value is a null value.
/// - throws: `DecodingError.typeMismatch` if the encountered encoded value
/// is not convertible to the requested type.
func decodeIfPresent(_ type: Array<Any>.Type, forKey key: Key) throws -> Array<Any>? {
func decodeIfPresent(_ type: [Any].Type, forKey key: Key) throws -> [Any]? {
guard contains(key) else {
return nil
}
Expand All @@ -86,36 +86,36 @@ public extension KeyedDecodingContainerProtocol where Key == DictionaryKeys {
/// and convertible to the requested type.
/// - throws: `DecodingError.typeMismatch` if the encountered encoded value
/// is not convertible to the requested type.
func decode(_ type: Dictionary<String, Any>.Type) throws -> Dictionary<String, Any> {
func decode(_ type: [String: Any].Type) throws -> [String: Any] {
var dictionary: [String: Any] = [:]

for key in allKeys {
if let boolValue = try? decode(Bool.self, forKey: key) {
dictionary[key.stringValue] = boolValue

} else if let intValue = try? decode(Int.self, forKey: key) {
dictionary[key.stringValue] = intValue

} else if let doubleValue = try? decode(Double.self, forKey: key) {
dictionary[key.stringValue] = doubleValue

} else if let stringValue = try? decode(String.self, forKey: key) {
dictionary[key.stringValue] = stringValue
} else if let nestedDictionary = try? decode(Dictionary<String, Any>.self, forKey: key) {

} else if let nestedDictionary = try? decode([String: Any].self, forKey: key) {
dictionary[key.stringValue] = nestedDictionary
} else if let nestedArray = try? decode(Array<Any>.self, forKey: key) {

} else if let nestedArray = try? decode([Any].self, forKey: key) {
dictionary[key.stringValue] = nestedArray

} else if try decodeNil(forKey: key) {
dictionary[key.stringValue] = NSNull()
} else {
let context = DecodingError.Context(codingPath: [key], debugDescription: "Invalid Decoding Value")
throw DecodingError.typeMismatch(type, context)
}
}

return dictionary
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public extension KeyedDecodingContainerProtocol {
///
/// - parameter key: The key that the decoded value is associated with.
/// - parameter defaultValue: Closure called to produce a value when needed.
func decode<T>(_ key: Key, defaultValue: @autoclosure () -> T) -> T where T: Decodable {
func decode<T: Decodable>(_ key: Key, defaultValue: @autoclosure () -> T) -> T {
guard contains(key) else {
return defaultValue()
}
Expand Down Expand Up @@ -51,7 +51,7 @@ public extension KeyedDecodingContainerProtocol {
///
/// - parameter keys: the keys that the given value may be associate with.
/// - parameter defaultValue: Closure called to produce a value when needed.
func decode<T>(_ keys: [Key], defaultValue: @autoclosure () -> T) -> T where T: Decodable {
func decode<T: Decodable>(_ keys: [Key], defaultValue: @autoclosure () -> T) -> T {
guard !keys.isEmpty else {
return defaultValue()
}
Expand All @@ -62,11 +62,8 @@ public extension KeyedDecodingContainerProtocol {
}

do {
let value = try decode(T.self, forKey: key)
return value
} catch {

}
return try decode(T.self, forKey: key)
} catch {}
}

return defaultValue()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ public extension KeyedDecodingContainerProtocol {
return true
}
}

return false
}

/// Decodes a value of the given type for any of the given keys.
///
/// This method will attempt to decode data in the order the keys are given.
Expand All @@ -35,7 +35,7 @@ public extension KeyedDecodingContainerProtocol {
/// one of the keys is not convertible to the requested type.
/// - throws: `DecodingError.valueNotFound` if `self` has a null entry for all
/// of the given keys.
func decode<T>(_ type: T.Type, forKeys keys: [Key]) throws -> T where T: Decodable {
func decode<T: Decodable>(_ type: T.Type, forKeys keys: [Key]) throws -> T {
guard keys.count > 0 else {
let context = DecodingError.Context(codingPath: [], debugDescription: "No Keys Specified")
throw DecodingError.dataCorrupted(context)
Expand Down Expand Up @@ -70,7 +70,7 @@ public extension KeyedDecodingContainerProtocol {
}

for key in keys {
if let value = try self.decodeIfPresent(type, forKey: key) {
if let value = try decodeIfPresent(type, forKey: key) {
return value
}
}
Expand Down
Loading
Loading