|
| 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 |
0 commit comments