From da14fa8fd0d6f460f48e1c57c63ce9f381b3396e Mon Sep 17 00:00:00 2001 From: a dinosaur Date: Thu, 14 Nov 2024 00:57:29 +1100 Subject: [PATCH] yep steam classes are faster... --- Sources/apk/Index/ApkIndexUpdate.swift | 16 ++++++------- Sources/apk/Utility/FileInputStream.swift | 10 ++++----- Sources/apk/Utility/GZip.swift | 2 +- Sources/apk/Utility/InputStream.swift | 25 ++++++++++++--------- Sources/apk/Utility/MemoryInputStream.swift | 12 +++++----- Sources/apk/Utility/Stream.swift | 25 +++++++++++++++------ Sources/apk/Utility/TarMemoryReader.swift | 2 +- 7 files changed, 54 insertions(+), 38 deletions(-) diff --git a/Sources/apk/Index/ApkIndexUpdate.swift b/Sources/apk/Index/ApkIndexUpdate.swift index 6af0512..77a006d 100644 --- a/Sources/apk/Index/ApkIndexUpdate.swift +++ b/Sources/apk/Index/ApkIndexUpdate.swift @@ -73,11 +73,11 @@ public struct ApkIndexUpdater { var tars = [Data]() do { - var file: any InputStream = try FileInputStream(indexURL) - //var file: any InputStream = try MemoryInputStream(buffer: try Data(contentsOf: indexURL)) + var file = try FileInputStream(indexURL) + //var file = try MemoryInputStream(buffer: try Data(contentsOf: indexURL)) var gzip = GZipReader() - tars.append(try gzip.read(inStream: &file)) - tars.append(try gzip.read(inStream: &file)) + tars.append(try gzip.read(inStream: file)) + tars.append(try gzip.read(inStream: file)) } catch { fatalError(error.localizedDescription) } @@ -85,10 +85,10 @@ public struct ApkIndexUpdater { print("Gzip time: \((ContinuousClock.now - gzipStart).formatted(durFormat))") let untarStart = ContinuousClock.now - var signatureStream = MemoryInputStream(buffer: tars[0]) - tarSignature = try TarReader.read(&signatureStream) - var recordsStream = MemoryInputStream(buffer: tars[1]) - tarRecords = try TarReader.read(&recordsStream) + let signatureStream = MemoryInputStream(buffer: tars[0]) + tarSignature = try TarReader.read(signatureStream) + let recordsStream = MemoryInputStream(buffer: tars[1]) + tarRecords = try TarReader.read(recordsStream) guard case .file(let signatureName, _) = tarSignature.first else { fatalError("Missing signature") } diff --git a/Sources/apk/Utility/FileInputStream.swift b/Sources/apk/Utility/FileInputStream.swift index 483b2a1..fe41092 100644 --- a/Sources/apk/Utility/FileInputStream.swift +++ b/Sources/apk/Utility/FileInputStream.swift @@ -7,14 +7,14 @@ import Foundation import Darwin import System -public struct FileInputStream: InputStream { +public class FileInputStream: InputStream { private var _hnd: FileHandle public init(_ fileURL: URL) throws { self._hnd = try FileHandle(forReadingFrom: fileURL) } - public mutating func seek(_ whence: StreamWhence) throws(StreamError) { + public override func seek(_ whence: Whence) throws(StreamError) { let applyOffset = { (position: UInt64, offset: Int) throws(StreamError) -> UInt64 in if offset < 0 { let (newPosition, overflow) = position.subtractingReportingOverflow(UInt64(-offset)) @@ -55,7 +55,7 @@ public struct FileInputStream: InputStream { } } - public var tell: Int { + public override var tell: Int { get throws(StreamError) { let offset: UInt64 do { offset = try self._hnd.offset() } @@ -67,7 +67,7 @@ public struct FileInputStream: InputStream { } } - public mutating func read(_ count: Int) throws(StreamError) -> Data { + public override func read(_ count: Int) throws(StreamError) -> Data { do { return try self._hnd.read(upToCount: count) ?? Data() } catch { @@ -75,7 +75,7 @@ public struct FileInputStream: InputStream { } } - public mutating func read(_ buffer: UnsafeMutablePointer, maxLength len: Int) throws(StreamError) -> Int { + public override func read(_ buffer: UnsafeMutablePointer, maxLength len: Int) throws(StreamError) -> Int { let res = unistd.read(self._hnd.fileDescriptor, buffer, len) if res < 0 { throw .fileHandleError(Errno(rawValue: errno)) diff --git a/Sources/apk/Utility/GZip.swift b/Sources/apk/Utility/GZip.swift index ce6c068..0c13bcb 100644 --- a/Sources/apk/Utility/GZip.swift +++ b/Sources/apk/Utility/GZip.swift @@ -18,7 +18,7 @@ struct GZipReader: ~Copyable { inflateEnd(&zstream) } - mutating func read(inStream stream: inout any InputStream) throws(GZipError) -> Data { + mutating func read(inStream stream: InputStream) throws(GZipError) -> Data { // Initialise zlib if this is the first time we're called // otherwise reset the stream in anticipation of reading the next concatenated stream var zerr = if self.zstream.state == nil { diff --git a/Sources/apk/Utility/InputStream.swift b/Sources/apk/Utility/InputStream.swift index 0f09fee..f2c5b96 100644 --- a/Sources/apk/Utility/InputStream.swift +++ b/Sources/apk/Utility/InputStream.swift @@ -5,19 +5,24 @@ import Foundation -public protocol InputStream: Stream, IteratorProtocol where Element == UInt8 { - mutating func read(_ count: Int) throws(StreamError) -> Data - mutating func read(_ buffer: UnsafeMutablePointer, maxLength len: Int) throws(StreamError) -> Int -} +public class InputStream: Stream, IteratorProtocol { + public typealias Element = UInt8 -public extension InputStream { - mutating func read(_ size: Int, items: Int) throws(StreamError) -> Data { - try self.read(size * items) + public func read(_ count: Int) throws(StreamError) -> Data { + throw .notImplemented } -} -public extension InputStream { - mutating func next() -> UInt8? { + public func read(_ buffer: UnsafeMutablePointer, maxLength len: Int) throws(StreamError) -> Int { + throw .notImplemented + } + + public func next() -> UInt8? { try? self.read(1).first } } + +public extension InputStream { + func read(_ size: Int, items: Int) throws(StreamError) -> Data { + try self.read(size * items) + } +} diff --git a/Sources/apk/Utility/MemoryInputStream.swift b/Sources/apk/Utility/MemoryInputStream.swift index a2fd4c8..f617553 100644 --- a/Sources/apk/Utility/MemoryInputStream.swift +++ b/Sources/apk/Utility/MemoryInputStream.swift @@ -6,7 +6,7 @@ import Foundation import System -public struct MemoryInputStream: InputStream { +public class MemoryInputStream: InputStream { private var _buf: ContiguousArray! = nil private let _sli: ArraySlice private let _ptr: UnsafeBufferPointer @@ -50,7 +50,7 @@ public struct MemoryInputStream: InputStream { } */ - public mutating func seek(_ whence: StreamWhence) throws(StreamError) { + public override func seek(_ whence: Whence) throws(StreamError) { let (position, overflow) = switch whence { case .set(let position): (position, false) case .current(let offset): self._idx.addingReportingOverflow(offset) @@ -65,13 +65,13 @@ public struct MemoryInputStream: InputStream { } } - public var tell: Int { + public override var tell: Int { get throws(StreamError) { self._idx } } - public mutating func read(_ count: Int) throws(StreamError) -> Data { + public override func read(_ count: Int) throws(StreamError) -> Data { let beg = min(self._idx, self._len) let end = min(self._idx + count, self._len) let bytes = Data(self._ptr[beg.., maxLength count: Int) throws(StreamError) -> Int { + public override func read(_ buffer: UnsafeMutablePointer, maxLength count: Int) throws(StreamError) -> Int { let beg = min(self._idx, self._len) let end = min(self._idx + count, self._len) let len = beg.distance(to: end) @@ -88,7 +88,7 @@ public struct MemoryInputStream: InputStream { return self._ptr.copyBytes(to: buf, from: beg.. UInt8? { + public override func next() -> UInt8? { if _fastPath(self._idx < self._len) { defer { self._idx += 1 } return self._ptr[self._idx] diff --git a/Sources/apk/Utility/Stream.swift b/Sources/apk/Utility/Stream.swift index f14c2d4..5a9e1f3 100644 --- a/Sources/apk/Utility/Stream.swift +++ b/Sources/apk/Utility/Stream.swift @@ -6,19 +6,29 @@ import Foundation import System -public protocol Stream { - mutating func seek(_ whence: StreamWhence) throws(StreamError) - var tell: Int { get throws(StreamError) } +public class Stream { + func seek(_ whence: Whence) throws(StreamError) { + throw .unsupported + } + + var tell: Int { + get throws(StreamError) { + throw .unsupported + } + } } -public enum StreamWhence { - case set(_ position: Int) - case current(_ offset: Int) - case end(_ offset: Int) +extension Stream { + public enum Whence { + case set(_ position: Int) + case current(_ offset: Int) + case end(_ offset: Int) + } } public enum StreamError: Error, LocalizedError { case unsupported + case notImplemented case seekRange case overflow case fileHandleError(_ error: any Error) @@ -27,6 +37,7 @@ public enum StreamError: Error, LocalizedError { public var errorDescription: String? { switch self { case .unsupported: "Unsupported operation" + case .notImplemented: "The stream object doesn't implement this function" case .seekRange: "Seek out of range" case .overflow: "Stream position overflowed" case .fileHandleError(let error): "Error from file handle: \(error.localizedDescription)" diff --git a/Sources/apk/Utility/TarMemoryReader.swift b/Sources/apk/Utility/TarMemoryReader.swift index 9c37937..95c7fa4 100644 --- a/Sources/apk/Utility/TarMemoryReader.swift +++ b/Sources/apk/Utility/TarMemoryReader.swift @@ -18,7 +18,7 @@ public struct TarReader { case directory(name: String) } - public static func read(_ stream: inout S) throws -> [Entry] { + public static func read(_ stream: InputStream) throws -> [Entry] { var entries = [Entry]() while true {