Last active
July 10, 2020 07:28
-
-
Save ntnmrndn/42cf2d32b1e42ecb27428e170d1c499a to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// MARK: - Caches | |
public protocol DirectoryCachable { | |
var directoryName: String { get } | |
} | |
extension Caches { | |
// MARK: - DataCacheStack | |
/// A synchronous, thread safe, directory cache. | |
public class DirectoryBased<E: DirectoryCachable> { | |
// MARK: Public | |
/// Multiple instances of the same generic type are NOT supported. | |
public init() throws { | |
self.baseURL = try Self.directoryURL.unwrap() | |
try FileManager.default.createDirectory( | |
at: self.baseURL, | |
withIntermediateDirectories: true | |
) | |
self.keys = try FileManager.default.contentsOfDirectory(at: self.baseURL, includingPropertiesForKeys: nil).map { | |
$0.lastPathComponent | |
}.asSet() | |
} | |
static var directoryURL: URL? { | |
guard let cacheURL = FileManager.default.urls( | |
for: .cachesDirectory, | |
in: .userDomainMask | |
).first else { | |
return nil | |
} | |
return cacheURL.appendingPathComponent(String(describing: E.self)) | |
} | |
public func contains(_ element: E) -> Bool { | |
self.queue.sync { | |
keys.contains(element.directoryName) | |
} | |
} | |
public func get(_ element: E) -> URL? { | |
let key = element.directoryName | |
guard self.queue.sync(execute: { | |
keys.contains(key) | |
}) | |
else { | |
return nil | |
} | |
return self.baseURL.appendingPathComponent(key, isDirectory: true) | |
} | |
public func add(_ element: E, fileURL: URL) throws { | |
try FileManager.default.moveItem(at: fileURL, to: self.baseURL.appendingPathComponent(element.directoryName, isDirectory: true)) | |
_ = self.queue.async(flags: .barrier) { | |
self.keys.insert(element.directoryName) | |
} | |
} | |
// MARK: Private | |
private let baseURL: URL | |
private var keys: Set<String> | |
private let queue = DispatchQueue( | |
label: "Caches.DirectoryBased<\(String(describing: E.self))>", | |
attributes: .concurrent | |
) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment