Skip to content

Commit c882cac

Browse files
Swift 6 compatibility and naming convention fixes
- Update to Swift 6.0 tools version - Add Sendable conformance to property wrappers - BREAKING: Rename property wrapper types to follow Swift conventions: - @Embedded.json → @Embedded.JSON - @Embedded.yaml → @Embedded.YAML - @Embedded.text → @Embedded.Text - Fix static methods to work without property wrappers - Add SwiftLint configuration - Fix all linting issues
1 parent d630ec7 commit c882cac

File tree

6 files changed

+100
-86
lines changed

6 files changed

+100
-86
lines changed

.swiftlint.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
excluded:
2+
- .build

Makefile

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,11 @@ clean:
1616
build:
1717
swift build
1818

19-
# Format code
20-
format:
21-
swift-format . -i -r
22-
23-
# Lint code
2419
lint:
25-
swift-format lint . -r
20+
swiftlint
21+
22+
lint-fix:
23+
swiftlint --fix
2624

2725
# Create a new release
2826
release:

Package.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// swift-tools-version: 5.9
1+
// swift-tools-version: 6.0
22
// The swift-tools-version declares the minimum version of Swift required to build this package.
33

44
import PackageDescription
@@ -14,7 +14,7 @@ let package = Package(
1414
products: [
1515
.library(
1616
name: "SwiftEmbed",
17-
targets: ["SwiftEmbed"]),
17+
targets: ["SwiftEmbed"])
1818
],
1919
dependencies: [
2020
.package(url: "https://github.com/jpsim/Yams.git", from: "6.1.0")
@@ -30,6 +30,6 @@ let package = Package(
3030
resources: [
3131
.copy("TestData")
3232
]
33-
),
33+
)
3434
]
3535
)

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ dependencies: [
2929
## Usage
3030

3131
SwiftEmbed provides two ways to load resources:
32-
- **Property wrappers** (`@Embedded.json` / `@Embedded.yaml` / `@Embedded.text`) - for class/struct properties
32+
- **Property wrappers** (`@Embedded.JSON` / `@Embedded.YAML` / `@Embedded.Text`) - for class/struct properties
3333
- **Direct loading** (`Embedded.getJSON` / `Embedded.getYAML` / `Embedded.getText`) - for immediate use
3434

3535
### Property Wrappers
@@ -49,13 +49,13 @@ struct User: Decodable {
4949
}
5050

5151
struct MyApp {
52-
@Embedded.json(Bundle.main, path: "Resources/users.json")
52+
@Embedded.JSON(Bundle.main, path: "Resources/users.json")
5353
var users: [User]
5454

55-
@Embedded.yaml(Bundle.main, path: "Config/settings.yaml")
55+
@Embedded.YAML(Bundle.main, path: "Config/settings.yaml")
5656
var config: Config
5757

58-
@Embedded.text(Bundle.main, path: "Resources/template.html")
58+
@Embedded.Text(Bundle.main, path: "Resources/template.html")
5959
var htmlTemplate: String
6060

6161
func printInfo() {

Sources/SwiftEmbed/Embedded.swift

Lines changed: 50 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -5,36 +5,50 @@ import Yams
55
public enum Embedded {
66
/// Load JSON resource and decode it to the specified type
77
public static func getJSON<T: Decodable>(_ bundle: Bundle, path: String, as type: T.Type = T.self) -> T {
8-
@json(bundle, path: path)
9-
var value: T
10-
return value
8+
let data = loadData(path: path, bundle: bundle)
9+
10+
do {
11+
let decoder = JSONDecoder()
12+
return try decoder.decode(T.self, from: data)
13+
} catch {
14+
fatalError("Failed to decode JSON from '\(path)': \(error)")
15+
}
1116
}
12-
17+
1318
/// Load YAML resource and decode it to the specified type
1419
public static func getYAML<T: Decodable>(_ bundle: Bundle, path: String, as type: T.Type = T.self) -> T {
15-
@yaml(bundle, path: path)
16-
var value: T
17-
return value
20+
let data = loadData(path: path, bundle: bundle)
21+
22+
do {
23+
let decoder = YAMLDecoder()
24+
return try decoder.decode(T.self, from: data)
25+
} catch {
26+
fatalError("Failed to decode YAML from '\(path)': \(error)")
27+
}
1828
}
19-
29+
2030
/// Load text resource as String
2131
public static func getText(_ bundle: Bundle, path: String) -> String {
22-
@text(bundle, path: path)
23-
var value: String
24-
return value
32+
let data = loadData(path: path, bundle: bundle)
33+
34+
guard let string = String(data: data, encoding: .utf8) else {
35+
fatalError("Failed to decode text from '\(path)': not valid UTF-8")
36+
}
37+
38+
return string
2539
}
26-
40+
2741
@propertyWrapper
28-
public struct json<T: Decodable> {
42+
public struct JSON<T: Decodable>: Sendable where T: Sendable {
2943
private let value: T
30-
44+
3145
public var wrappedValue: T {
3246
value
3347
}
34-
48+
3549
public init(_ bundle: Bundle, path: String) {
3650
let data = Self.loadData(path: path, bundle: bundle)
37-
51+
3852
do {
3953
let decoder = JSONDecoder()
4054
self.value = try decoder.decode(T.self, from: data)
@@ -43,18 +57,18 @@ public enum Embedded {
4357
}
4458
}
4559
}
46-
60+
4761
@propertyWrapper
48-
public struct yaml<T: Decodable> {
62+
public struct YAML<T: Decodable>: Sendable where T: Sendable {
4963
private let value: T
50-
64+
5165
public var wrappedValue: T {
5266
value
5367
}
54-
68+
5569
public init(_ bundle: Bundle, path: String) {
5670
let data = Self.loadData(path: path, bundle: bundle)
57-
71+
5872
do {
5973
let decoder = YAMLDecoder()
6074
self.value = try decoder.decode(T.self, from: data)
@@ -63,22 +77,22 @@ public enum Embedded {
6377
}
6478
}
6579
}
66-
80+
6781
@propertyWrapper
68-
public struct text {
82+
public struct Text: Sendable {
6983
private let value: String
70-
84+
7185
public var wrappedValue: String {
7286
value
7387
}
74-
88+
7589
public init(_ bundle: Bundle, path: String) {
7690
let data = Self.loadData(path: path, bundle: bundle)
77-
91+
7892
guard let string = String(data: data, encoding: .utf8) else {
7993
fatalError("Failed to decode text from '\(path)': not valid UTF-8")
8094
}
81-
95+
8296
self.value = string
8397
}
8498
}
@@ -89,26 +103,26 @@ private extension Embedded {
89103
static func loadData(path: String, bundle: Bundle) -> Data {
90104
// Split path into components
91105
let pathComponents = path.split(separator: "/").map(String.init)
92-
106+
93107
// Extract filename and extension from last component
94108
let filename = pathComponents.last ?? path
95109
let url = URL(fileURLWithPath: filename)
96110
let nameWithoutExtension = url.deletingPathExtension().lastPathComponent
97111
let fileExtension = url.pathExtension
98-
112+
99113
// Get subdirectory if path has multiple components
100-
let subdirectory: String? = pathComponents.count > 1
114+
let subdirectory: String? = pathComponents.count > 1
101115
? pathComponents.dropLast().joined(separator: "/")
102116
: nil
103-
117+
104118
guard let resourceURL = bundle.url(
105119
forResource: nameWithoutExtension,
106120
withExtension: fileExtension,
107121
subdirectory: subdirectory
108122
) else {
109123
fatalError("Resource not found: '\(path)' in bundle: \(bundle.bundlePath)")
110124
}
111-
125+
112126
do {
113127
return try Data(contentsOf: resourceURL)
114128
} catch {
@@ -117,20 +131,20 @@ private extension Embedded {
117131
}
118132
}
119133

120-
private extension Embedded.json {
134+
private extension Embedded.JSON {
121135
static func loadData(path: String, bundle: Bundle) -> Data {
122136
Embedded.loadData(path: path, bundle: bundle)
123137
}
124138
}
125139

126-
private extension Embedded.yaml {
140+
private extension Embedded.YAML {
127141
static func loadData(path: String, bundle: Bundle) -> Data {
128142
Embedded.loadData(path: path, bundle: bundle)
129143
}
130144
}
131145

132-
private extension Embedded.text {
146+
private extension Embedded.Text {
133147
static func loadData(path: String, bundle: Bundle) -> Data {
134148
Embedded.loadData(path: path, bundle: bundle)
135149
}
136-
}
150+
}

0 commit comments

Comments
 (0)