@@ -3,23 +3,52 @@ import Dependencies
33import Foundation
44
55extension PersistenceReaderKey {
6- /// Creates a persistence key that can read and write to a `Codable` value to the file system.
6+ /// Creates a persistence key that can read and write to a `Codable` value in the file system.
77 ///
8- /// - Parameter url: The file URL from which to read and write the value.
8+ /// - Parameters:
9+ /// - url: The file URL from which to read and write the value.
10+ /// - decoder: The JSONDecoder to use for decoding the value.
11+ /// - encoder: The JSONEncoder to use for encoding the value.
912 /// - Returns: A file persistence key.
10- public static func fileStorage< Value: Codable > ( _ url: URL ) -> Self
13+ public static func fileStorage< Value: Codable > (
14+ _ url: URL ,
15+ decoder: JSONDecoder = JSONDecoder ( ) ,
16+ encoder: JSONEncoder = JSONEncoder ( )
17+ ) -> Self
1118 where Self == FileStorageKey < Value > {
12- FileStorageKey ( url: url)
19+ FileStorageKey (
20+ url: url,
21+ decode: { try decoder. decode ( Value . self, from: $0) } ,
22+ encode: { try encoder. encode ( $0) }
23+ )
24+ }
25+
26+ /// Creates a persistence key that can read and write to a value in the file system.
27+ ///
28+ /// - Parameters:
29+ /// - url: The file URL from which to read and write the value.
30+ /// - decode: The closure to use for decoding the value.
31+ /// - encode: The closure to use for encoding the value.
32+ /// - Returns: A file persistence key.
33+ public static func fileStorage< Value> (
34+ _ url: URL ,
35+ decode: @escaping @Sendable ( Data) throws -> Value ,
36+ encode: @escaping @Sendable ( Value) throws -> Data
37+ ) -> Self
38+ where Self == FileStorageKey < Value > {
39+ FileStorageKey ( url: url, decode: decode, encode: encode)
1340 }
1441}
1542
1643/// A type defining a file persistence strategy
1744///
1845/// Use ``PersistenceReaderKey/fileStorage(_:)`` to create values of this type.
19- public final class FileStorageKey < Value: Codable & Sendable > : PersistenceKey , Sendable {
46+ public final class FileStorageKey < Value: Sendable > : PersistenceKey , Sendable {
2047 private let storage : FileStorage
2148 private let isSetting = LockIsolated ( false )
2249 private let url : URL
50+ private let decode : @Sendable ( Data) throws -> Value
51+ private let encode : @Sendable ( Value) throws -> Data
2352 fileprivate let state = LockIsolated ( State ( ) )
2453 // private let value = LockIsolated<Value?>(nil)
2554 // private let workItem = LockIsolated<DispatchWorkItem?>(nil)
@@ -33,15 +62,21 @@ public final class FileStorageKey<Value: Codable & Sendable>: PersistenceKey, Se
3362 FileStorageKeyID ( url: self . url, storage: self . storage)
3463 }
3564
36- fileprivate init ( url: URL ) {
65+ fileprivate init (
66+ url: URL ,
67+ decode: @escaping @Sendable ( Data) throws -> Value ,
68+ encode: @escaping @Sendable ( Value) throws -> Data
69+ ) {
3770 @Dependency ( \. defaultFileStorage) var storage
3871 self . storage = storage
3972 self . url = url
73+ self . decode = decode
74+ self . encode = encode
4075 }
4176
4277 public func load( initialValue: Value ? ) -> Value ? {
4378 do {
44- return try JSONDecoder ( ) . decode ( Value . self , from : self . storage. load ( self . url) )
79+ return try decode ( self . storage. load ( self . url) )
4580 } catch {
4681 return initialValue
4782 }
@@ -51,7 +86,7 @@ public final class FileStorageKey<Value: Codable & Sendable>: PersistenceKey, Se
5186 self . state. withValue { state in
5287 if state. workItem == nil {
5388 self . isSetting. setValue ( true )
54- try ? self . storage. save ( JSONEncoder ( ) . encode ( value) , self . url)
89+ try ? self . storage. save ( encode ( value) , self . url)
5590 let workItem = DispatchWorkItem { [ weak self] in
5691 guard let self else { return }
5792 self . state. withValue { state in
@@ -62,7 +97,7 @@ public final class FileStorageKey<Value: Codable & Sendable>: PersistenceKey, Se
6297 guard let value = state. value
6398 else { return }
6499 self . isSetting. setValue ( true )
65- try ? self . storage. save ( JSONEncoder ( ) . encode ( value) , self . url)
100+ try ? self . storage. save ( self . encode ( value) , self . url)
66101 }
67102 }
68103 state. workItem = workItem
0 commit comments