Skip to content

Commit d6d6325

Browse files
authored
Leif/2.0.0 (#12)
* Update with changes for 2.0.0 * Remove unused workflow * Update PropertyWrappersTests * Remove ComposableCache from windows * Remove AnyCacheable from windows * Fix test to handle windows * Update test case * Add Logger typealias and Logging wrapper (#11) * Update README
1 parent d9be5df commit d6d6325

13 files changed

+1006
-64
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ Add the following line to your `Package.swift` file in the dependencies array:
2222

2323
```swift
2424
dependencies: [
25-
.package(url: "https://github.com/0xLeif/Cache.git", from: "1.0.0")
25+
.package(url: "https://github.com/0xLeif/Cache.git", from: "2.0.0")
2626
]
2727
```
2828

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
#if !os(Windows)
2+
public class AnyCacheable: Cacheable {
3+
public typealias Key = AnyHashable
4+
public typealias Value = Any
5+
6+
private var cache: any Cacheable
7+
8+
private var cacheGet: ((AnyHashable) -> Any?)!
9+
private var cacheResolve: ((AnyHashable) throws -> Any)!
10+
private var cacheSet: ((Any, AnyHashable) -> Void)!
11+
private var cacheRemove: ((AnyHashable) -> Void)!
12+
private var cacheContains: ((AnyHashable) -> Bool)!
13+
private var cacheRequireKeys: ((Set<AnyHashable>) throws -> Void)!
14+
private var cacheRequireKey: ((AnyHashable) throws -> Void)!
15+
private var cacheValues: (() -> [AnyHashable: Any])!
16+
17+
public init<InnerCache: Cacheable>(_ cache: InnerCache) {
18+
self.cache = cache
19+
20+
self.cacheGet = { key in
21+
guard let key = key as? InnerCache.Key else { return nil }
22+
23+
return cache.get(key, as: Any.self)
24+
}
25+
26+
self.cacheResolve = { key in
27+
guard
28+
let key = key as? InnerCache.Key
29+
else { throw MissingRequiredKeysError(keys: [key]) }
30+
31+
return try cache.resolve(key, as: Any.self)
32+
}
33+
34+
self.cacheSet = { value, key in
35+
guard
36+
let value = value as? InnerCache.Value,
37+
let key = key as? InnerCache.Key
38+
else { return }
39+
40+
var mutableCache = cache
41+
42+
mutableCache.set(value: value, forKey: key)
43+
44+
self.cache = mutableCache
45+
}
46+
47+
self.cacheRemove = { key in
48+
guard let key = key as? InnerCache.Key else { return }
49+
50+
var mutableCache = cache
51+
52+
mutableCache.remove(key)
53+
54+
self.cache = mutableCache
55+
}
56+
57+
self.cacheContains = { key in
58+
guard
59+
let key = key as? InnerCache.Key
60+
else { return false }
61+
62+
return cache.contains(key)
63+
}
64+
65+
self.cacheRequireKeys = { keys in
66+
let validKeys: Set<InnerCache.Key> = Set(keys.compactMap { $0 as? InnerCache.Key })
67+
68+
guard
69+
validKeys.count == keys.count
70+
else { throw MissingRequiredKeysError(keys: keys.subtracting(validKeys)) }
71+
72+
_ = try cache.require(keys: validKeys)
73+
}
74+
75+
self.cacheRequireKey = { key in
76+
guard
77+
let key = key as? InnerCache.Key
78+
else { throw MissingRequiredKeysError(keys: [key]) }
79+
80+
_ = try cache.require(key)
81+
}
82+
83+
self.cacheValues = {
84+
cache.values(ofType: Any.self)
85+
}
86+
}
87+
88+
required public convenience init(initialValues: [AnyHashable: Any]) {
89+
self.init(Cache(initialValues: initialValues))
90+
}
91+
92+
public func get<Output>(
93+
_ key: AnyHashable,
94+
as: Output.Type = Output.self
95+
) -> Output? {
96+
guard let value = cacheGet(key) else {
97+
return nil
98+
}
99+
100+
guard let output = value as? Output else {
101+
return nil
102+
}
103+
104+
return output
105+
}
106+
107+
public func resolve<Output>(
108+
_ key: AnyHashable,
109+
as: Output.Type = Output.self
110+
) throws -> Output {
111+
let resolvedValue = try cacheResolve(key)
112+
113+
guard let output = resolvedValue as? Output else {
114+
throw InvalidTypeError(
115+
expectedType: Output.self,
116+
actualType: type(of: get(key, as: Any.self))
117+
)
118+
}
119+
120+
return output
121+
}
122+
123+
public func set(value: Value, forKey key: AnyHashable) {
124+
cacheSet(value, key)
125+
}
126+
127+
public func remove(_ key: AnyHashable) {
128+
cacheRemove(key)
129+
}
130+
131+
public func contains(_ key: AnyHashable) -> Bool {
132+
cacheContains(key)
133+
}
134+
135+
public func require(keys: Set<AnyHashable>) throws -> Self {
136+
try cacheRequireKeys(keys)
137+
138+
return self
139+
}
140+
141+
public func require(_ key: AnyHashable) throws -> Self {
142+
try cacheRequireKey(key)
143+
144+
return self
145+
}
146+
147+
public func values<Output>(ofType: Output.Type) -> [AnyHashable: Output] {
148+
cacheValues().compactMapValues { value in
149+
value as? Output
150+
}
151+
}
152+
}
153+
#endif

Sources/Cache/Cache/Cache.swift

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,3 +162,28 @@ open class Cache<Key: Hashable, Value>: Cacheable {
162162
#if !os(Linux) && !os(Windows)
163163
extension Cache: ObservableObject { }
164164
#endif
165+
166+
extension Cache {
167+
/**
168+
Gets a value from the cache for a given key.
169+
170+
- Parameters:
171+
- key: The key to retrieve the value for.
172+
- Returns: The value stored in cache for the given key, or `nil` if it doesn't exist.
173+
*/
174+
public func get(_ key: Key) -> Value? {
175+
get(key, as: Value.self)
176+
}
177+
178+
/**
179+
Resolves a value from the cache for a given key.
180+
181+
- Parameters:
182+
- key: The key to retrieve the value for.
183+
- Returns: The value stored in cache for the given key.
184+
- Throws: `MissingRequiredKeysError` if the key is missing, or `InvalidTypeError` if the value type is not compatible with the expected type.
185+
*/
186+
public func resolve(_ key: Key) throws -> Value {
187+
try resolve(key, as: Value.self)
188+
}
189+
}
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
#if !os(Windows)
2+
public struct ComposableCache<Key: Hashable>: Cacheable {
3+
private let caches: [AnyCacheable]
4+
5+
public init(caches: [any Cacheable]) {
6+
self.caches = caches.map { AnyCacheable($0) }
7+
}
8+
9+
public init(initialValues: [Key: Any]) {
10+
self.init(caches: [Cache(initialValues: initialValues)])
11+
}
12+
13+
public func get<Output>(
14+
_ key: Key,
15+
as: Output.Type = Output.self
16+
) -> Output? {
17+
for cache in caches {
18+
guard
19+
let output = cache.get(key, as: Output.self)
20+
else {
21+
continue
22+
}
23+
24+
return output
25+
}
26+
27+
return nil
28+
}
29+
30+
public func resolve<Output>(
31+
_ key: Key,
32+
as: Output.Type = Output.self
33+
) throws -> Output {
34+
for cache in caches {
35+
guard
36+
let output = try? cache.resolve(key, as: Output.self)
37+
else {
38+
continue
39+
}
40+
41+
return output
42+
}
43+
44+
throw MissingRequiredKeysError(keys: [key])
45+
}
46+
47+
public func set(value: Any, forKey key: Key) {
48+
for cache in caches {
49+
cache.set(value: value, forKey: key)
50+
}
51+
}
52+
53+
public func remove(_ key: Key) {
54+
for cache in caches {
55+
cache.remove(key)
56+
}
57+
}
58+
59+
public func contains(_ key: Key) -> Bool {
60+
for cache in caches {
61+
if cache.contains(key) {
62+
return true
63+
}
64+
}
65+
66+
return false
67+
}
68+
69+
public func require(keys: Set<Key>) throws -> ComposableCache<Key> {
70+
for cache in caches {
71+
_ = try cache.require(keys: keys)
72+
}
73+
74+
return self
75+
}
76+
77+
public func require(_ key: Key) throws -> ComposableCache<Key> {
78+
for cache in caches {
79+
_ = try cache.require(key)
80+
}
81+
82+
return self
83+
}
84+
85+
public func values<Output>(ofType: Output.Type) -> [Key: Output] {
86+
for cache in caches {
87+
let values = cache.values(ofType: Output.self).compactMapKeys { $0 as? Key }
88+
89+
guard values.keys.count != 0 else {
90+
continue
91+
}
92+
93+
return values
94+
}
95+
96+
return [:]
97+
}
98+
}
99+
#endif

Sources/Cache/Cache/RequiredKeysCache.swift

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -65,14 +65,9 @@ public class RequiredKeysCache<Key: Hashable, Value>: Cache<Key, Value> {
6565
- Throws: A runtime error if the required key is not present in the cache or if the expected value type is incorrect.
6666
*/
6767
public func resolve<Output>(requiredKey: Key, as: Output.Type = Output.self) -> Output {
68-
guard
69-
requiredKeys.contains(requiredKey)
70-
else { fatalError("The key '\(requiredKey)' is not a Required Key.") }
71-
72-
guard
73-
contains(requiredKey)
74-
else { fatalError("Required Key Missing: '\(requiredKey)'") }
75-
68+
precondition(requiredKeys.contains(requiredKey), "The key '\(requiredKey)' is not a Required Key.")
69+
precondition(contains(requiredKey), "Required Key Missing: '\(requiredKey)'")
70+
7671
do {
7772
return try resolve(requiredKey, as: Output.self)
7873
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
public protocol CacheInitializable {
2+
associatedtype OriginCache: Cacheable
3+
4+
init(cache: OriginCache)
5+
}

Sources/Cache/Cacheable.swift

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -70,27 +70,4 @@ public extension Cacheable {
7070
var allValues: [Key: Value] {
7171
values(ofType: Value.self)
7272
}
73-
74-
/**
75-
Gets a value from the cache for a given key.
76-
77-
- Parameters:
78-
- key: The key to retrieve the value for.
79-
- Returns: The value stored in cache for the given key, or `nil` if it doesn't exist.
80-
*/
81-
func get(_ key: Key) -> Value? {
82-
get(key, as: Value.self)
83-
}
84-
85-
/**
86-
Resolves a value from the cache for a given key.
87-
88-
- Parameters:
89-
- key: The key to retrieve the value for.
90-
- Returns: The value stored in cache for the given key.
91-
- Throws: `MissingRequiredKeysError` if the key is missing, or `InvalidTypeError` if the value type is not compatible with the expected type.
92-
*/
93-
func resolve(_ key: Key) throws -> Value {
94-
try resolve(key, as: Value.self)
95-
}
9673
}

0 commit comments

Comments
 (0)