mirror of
https://github.com/GayPizzaSpecifications/darwin-apk.git
synced 2025-08-03 21:41:31 +00:00
Initial implementation of APKINDEX, fetching, reading, parsing, & merging
This commit is contained in:
72
Sources/apk/Utility/FileInputStream.swift
Normal file
72
Sources/apk/Utility/FileInputStream.swift
Normal file
@ -0,0 +1,72 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import Foundation
|
||||
|
||||
public struct 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) {
|
||||
let applyOffset = { (position: UInt64, offset: Int) throws(StreamError) -> UInt64 in
|
||||
if offset < 0 {
|
||||
let (newPosition, overflow) = position.subtractingReportingOverflow(UInt64(-offset))
|
||||
if overflow { throw .seekRange }
|
||||
return newPosition
|
||||
} else {
|
||||
let (newPosition, overflow) = position.addingReportingOverflow(UInt64(offset))
|
||||
if overflow { throw .overflow }
|
||||
return newPosition
|
||||
}
|
||||
}
|
||||
|
||||
switch whence {
|
||||
case .set(let position):
|
||||
if position < 0 { throw .seekRange }
|
||||
do { try self._hnd.seek(toOffset: UInt64(truncatingIfNeeded: position)) }
|
||||
catch {
|
||||
throw .fileHandleError(error)
|
||||
}
|
||||
case .current(let offset):
|
||||
do { try self._hnd.seek(toOffset: try applyOffset(try self._hnd.offset(), offset)) }
|
||||
catch {
|
||||
if error is StreamError {
|
||||
throw error as! StreamError
|
||||
} else {
|
||||
throw .fileHandleError(error)
|
||||
}
|
||||
}
|
||||
case .end(let offset):
|
||||
do { try self._hnd.seek(toOffset: applyOffset(try self._hnd.seekToEnd(), offset)) }
|
||||
catch {
|
||||
if error is StreamError {
|
||||
throw error as! StreamError
|
||||
} else {
|
||||
throw .fileHandleError(error)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public var tell: Int {
|
||||
get throws(StreamError) {
|
||||
let offset: UInt64
|
||||
do { offset = try self._hnd.offset() }
|
||||
catch {
|
||||
throw .fileHandleError(error)
|
||||
}
|
||||
if offset > Int.max { throw .overflow }
|
||||
return Int(truncatingIfNeeded: offset)
|
||||
}
|
||||
}
|
||||
|
||||
public mutating func read(_ count: Int) throws(StreamError) -> Data {
|
||||
do {
|
||||
return try self._hnd.read(upToCount: count) ?? Data()
|
||||
} catch {
|
||||
throw .fileHandleError(error)
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user