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) } } }