rainbow-dragon/Sources/ForgeOffload/FileHasher.swift

37 lines
1.2 KiB
Swift

import Foundation
public enum OffloadError: Error, Equatable {
case fileNotFound(String)
case readFailed(String)
case writeFailed(String)
case verifyFailed(path: String, expected: String, actual: String)
case destinationConflict(String)
}
/// Chunked file hashing constant memory over multi-GB camera files.
public enum FileHasher {
static let chunkSize = 4 * 1024 * 1024
public static func xxh64(path: String) throws -> String {
var hasher = XXHash64()
try stream(path: path) { hasher.update($0) }
return XXHash64.hexString(hasher.finalize())
}
public static func md5(path: String) throws -> String {
var hasher = MD5()
try stream(path: path) { hasher.update($0) }
return hasher.finalize().map { String(format: "%02x", $0) }.joined()
}
private static func stream(path: String, _ body: (Data) -> Void) throws {
guard let handle = FileHandle(forReadingAtPath: path) else {
throw OffloadError.fileNotFound(path)
}
defer { try? handle.close() }
while true {
guard let chunk = try handle.read(upToCount: chunkSize), !chunk.isEmpty else { break }
body(chunk)
}
}
}