1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
|
/*
This source file is part of the Swift.org open source project
Copyright (c) 2020 Apple Inc. and the Swift project authors
Licensed under Apache License v2.0 with Runtime Library Exception
See http://swift.org/LICENSE.txt for license information
See http://swift.org/CONTRIBUTORS.txt for Swift project authors
*/
import Foundation
import TSCBasic
struct Bits: RandomAccessCollection {
var buffer: ByteString
var startIndex: Int { return 0 }
var endIndex: Int { return buffer.count * 8 }
subscript(index: Int) -> UInt8 {
let byte = buffer.contents[index / 8]
return (byte >> UInt8(index % 8)) & 1
}
func readBits(atOffset offset: Int, count: Int) -> UInt64 {
precondition(count >= 0 && count <= 64)
precondition(offset >= 0)
precondition(offset &+ count >= offset)
precondition(offset &+ count <= self.endIndex)
return buffer.contents.withUnsafeBytes { (bytes: UnsafeRawBufferPointer) in
let upperBound = offset &+ count
let topByteIndex = upperBound >> 3
var result: UInt64 = 0
if upperBound & 7 != 0 {
let mask: UInt8 = (1 << UInt8(upperBound & 7)) &- 1
result = UInt64(bytes[topByteIndex] & mask)
}
for i in ((offset >> 3)..<(upperBound >> 3)).reversed() {
result <<= 8
result |= UInt64(bytes[i])
}
if offset & 7 != 0 {
result >>= UInt64(offset & 7)
}
return result
}
}
struct Cursor {
enum Error: Swift.Error { case bufferOverflow }
let buffer: Bits
private var offset: Int = 0
init(buffer: Bits) {
self.buffer = buffer
}
init(buffer: ByteString) {
self.init(buffer: Bits(buffer: buffer))
}
var isAtStart: Bool {
return offset == buffer.startIndex
}
var isAtEnd: Bool {
return offset == buffer.count
}
func peek(_ count: Int) throws -> UInt64 {
if buffer.count - offset < count { throw Error.bufferOverflow }
return buffer.readBits(atOffset: offset, count: count)
}
mutating func read(_ count: Int) throws -> UInt64 {
defer { offset += count }
return try peek(count)
}
mutating func read(bytes count: Int) throws -> ArraySlice<UInt8> {
precondition(count >= 0)
precondition(offset & 0b111 == 0)
let newOffset = offset &+ (count << 3)
precondition(newOffset >= offset)
if newOffset > buffer.count { throw Error.bufferOverflow }
defer { offset = newOffset }
return buffer.buffer.contents.dropFirst(offset >> 3).prefix((newOffset - offset) >> 3)
}
mutating func skip(bytes count: Int) throws {
precondition(count >= 0)
precondition(offset & 0b111 == 0)
let newOffset = offset &+ (count << 3)
precondition(newOffset >= offset)
if newOffset > buffer.count { throw Error.bufferOverflow }
offset = newOffset
}
mutating func advance(toBitAlignment align: Int) throws {
precondition(align > 0)
precondition(offset &+ (align&-1) >= offset)
precondition(align & (align &- 1) == 0)
if offset % align == 0 { return }
offset = (offset &+ align) & ~(align &- 1)
if offset > buffer.count { throw Error.bufferOverflow }
}
}
}
|