Sources/OSS/Types/ByteStream.swift (84 lines of code) (raw):

import Foundation public enum ByteStream: @unchecked Sendable { /// nil body case none /// from the provided `Data` value. case data(Data) /// Body data is read from the given file URL case file(URL) /// from the provided `InputStream` case stream(InputStream) } public extension ByteStream { internal enum _Error: Error { case fileForBodyNotFound case streamForBodyNotSuportedRead } // Static property for an empty ByteStream static var empty: ByteStream { .data(Data()) } // Returns true if the byte stream is seekable var isSeekable: Bool { switch self { case .none, .data, .file: return true case .stream: return false } } /// - Returns: The body length, or `nil` for no body (e.g. `GET` request). func getBodyLength() throws -> UInt64? { switch self { case .none: return 0 case let .data(d): return UInt64(d.count) /// Body data is read from the given file URL case let .file(fileURL): guard let s = try FileManager.default.attributesOfItem(atPath: fileURL.path)[.size] as? NSNumber else { throw _Error.fileForBodyNotFound } return s.uint64Value case .stream: return nil } } // Read Data func readData() throws -> Data? { switch self { case .none: return nil case let .data(data): return data case .stream: throw _Error.streamForBodyNotSuportedRead case let .file(fileURL): let fh = try FileHandle(forReadingFrom: fileURL) if #available(macOS 10.15.4, iOS 13.4, watchOS 6.2, tvOS 13.4, *) { return try fh.readToEnd() } else { return fh.readDataToEndOfFile() } } } /// The 64-bit CRC value of the object. This value is calculated based on the ECMA-182 standard. /// This value is used to verify the integrity of the object. func hashCrc64ecma(crc: UInt64 = 0) -> UInt64? { switch self { case .none: return 0 case let .data(data): return data.withUnsafeBytes { dataBytes in let buffer: UnsafePointer<UInt8> = dataBytes.baseAddress!.assumingMemoryBound(to: UInt8.self) return CRC64.default.crc64(crc: crc, buf: buffer, len: dataBytes.count) } case let .file(url): guard let input = InputStream(url: url) else { return nil } input.open() let bufferSize = 16 * 1024 let buffer = UnsafeMutablePointer<UInt8>.allocate(capacity: bufferSize) var crc = crc while input.hasBytesAvailable { let read = input.read(buffer, maxLength: bufferSize) crc = CRC64.default.crc64(crc: crc, buf: buffer, len: read) } buffer.deallocate() input.close() return crc case .stream: return nil } } }