Skip to content

Commit 207f9c6

Browse files
authored
Merge pull request #189 from CodaFi/reality-bytes
Switch BitstreamReader Entrypoints to Use ByteString
2 parents 15db71f + 0348d61 commit 207f9c6

File tree

5 files changed

+53
-24
lines changed

5 files changed

+53
-24
lines changed

Sources/TSCUtility/Bits.swift

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,16 @@
99
*/
1010

1111
import Foundation
12+
import TSCBasic
1213

1314
struct Bits: RandomAccessCollection {
14-
var buffer: Data
15+
var buffer: ByteString
1516

1617
var startIndex: Int { return 0 }
1718
var endIndex: Int { return buffer.count * 8 }
1819

1920
subscript(index: Int) -> UInt8 {
20-
let byte = buffer[index / 8]
21+
let byte = buffer.contents[index / 8]
2122
return (byte >> UInt8(index % 8)) & 1
2223
}
2324

@@ -27,7 +28,7 @@ struct Bits: RandomAccessCollection {
2728
precondition(offset &+ count >= offset)
2829
precondition(offset &+ count <= self.endIndex)
2930

30-
return buffer.withUnsafeBytes { (bytes: UnsafeRawBufferPointer) in
31+
return buffer.contents.withUnsafeBytes { (bytes: UnsafeRawBufferPointer) in
3132
let upperBound = offset &+ count
3233
let topByteIndex = upperBound >> 3
3334
var result: UInt64 = 0
@@ -56,10 +57,14 @@ struct Bits: RandomAccessCollection {
5657
self.buffer = buffer
5758
}
5859

59-
init(buffer: Data) {
60+
init(buffer: ByteString) {
6061
self.init(buffer: Bits(buffer: buffer))
6162
}
6263

64+
var isAtStart: Bool {
65+
return offset == buffer.startIndex
66+
}
67+
6368
var isAtEnd: Bool {
6469
return offset == buffer.count
6570
}
@@ -74,14 +79,14 @@ struct Bits: RandomAccessCollection {
7479
return try peek(count)
7580
}
7681

77-
mutating func read(bytes count: Int) throws -> Data {
82+
mutating func read(bytes count: Int) throws -> ArraySlice<UInt8> {
7883
precondition(count >= 0)
7984
precondition(offset & 0b111 == 0)
8085
let newOffset = offset &+ (count << 3)
8186
precondition(newOffset >= offset)
8287
if newOffset > buffer.count { throw Error.bufferOverflow }
8388
defer { offset = newOffset }
84-
return buffer.buffer.dropFirst(offset >> 3).prefix((newOffset - offset) >> 3)
89+
return buffer.buffer.contents.dropFirst(offset >> 3).prefix((newOffset - offset) >> 3)
8590
}
8691

8792
mutating func skip(bytes count: Int) throws {

Sources/TSCUtility/BitstreamReader.swift

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,34 +9,42 @@
99
*/
1010

1111
import Foundation
12+
import TSCBasic
1213

1314
extension Bitcode {
1415
/// Parse a bitstream from data.
16+
@available(*, deprecated, message: "Use Bitcode.init(bytes:) instead")
1517
public init(data: Data) throws {
1618
precondition(data.count > 4)
17-
let signatureValue = UInt32(Bits(buffer: data).readBits(atOffset: 0, count: 32))
18-
let bitstreamData = data[4..<data.count]
19-
20-
var reader = BitstreamReader(buffer: bitstreamData)
19+
try self.init(bytes: ByteString(data))
20+
}
21+
22+
public init(bytes: ByteString) throws {
23+
precondition(bytes.count > 4)
24+
var reader = BitstreamReader(buffer: bytes)
25+
let signature = try reader.readSignature()
2126
var visitor = CollectingVisitor()
2227
try reader.readBlock(id: BitstreamReader.fakeTopLevelBlockID,
2328
abbrevWidth: 2,
2429
abbrevInfo: [],
2530
visitor: &visitor)
26-
self.init(signature: .init(value: signatureValue),
31+
self.init(signature: signature,
2732
elements: visitor.finalizeTopLevelElements(),
2833
blockInfo: reader.blockInfo)
2934
}
3035

3136
/// Traverse a bitstream using the specified `visitor`, which will receive
3237
/// callbacks when blocks and records are encountered.
38+
@available(*, deprecated, message: "Use Bitcode.read(bytes:using:) instead")
3339
public static func read<Visitor: BitstreamVisitor>(stream data: Data, using visitor: inout Visitor) throws {
3440
precondition(data.count > 4)
35-
let signatureValue = UInt32(Bits(buffer: data).readBits(atOffset: 0, count: 32))
36-
try visitor.validate(signature: .init(value: signatureValue))
41+
try Self.read(bytes: ByteString(data), using: &visitor)
42+
}
3743

38-
let bitstreamData = data[4..<data.count]
39-
var reader = BitstreamReader(buffer: bitstreamData)
44+
public static func read<Visitor: BitstreamVisitor>(bytes: ByteString, using visitor: inout Visitor) throws {
45+
precondition(bytes.count > 4)
46+
var reader = BitstreamReader(buffer: bytes)
47+
try visitor.validate(signature: reader.readSignature())
4048
try reader.readBlock(id: BitstreamReader.fakeTopLevelBlockID,
4149
abbrevWidth: 2,
4250
abbrevInfo: [],
@@ -113,8 +121,14 @@ private struct BitstreamReader {
113121
var blockInfo: [UInt64: BlockInfo] = [:]
114122
var globalAbbrevs: [UInt64: [Bitstream.Abbreviation]] = [:]
115123

116-
init(buffer: Data) {
117-
cursor = Bits.Cursor(buffer: buffer)
124+
init(buffer: ByteString) {
125+
self.cursor = Bits.Cursor(buffer: buffer)
126+
}
127+
128+
mutating func readSignature() throws -> Bitcode.Signature {
129+
precondition(self.cursor.isAtStart)
130+
let bits = try UInt32(self.cursor.read(MemoryLayout<UInt32>.size * 8))
131+
return Bitcode.Signature(value: bits)
118132
}
119133

120134
mutating func readAbbrevOp() throws -> Bitstream.Abbreviation.Operand {
@@ -220,7 +234,7 @@ private struct BitstreamReader {
220234
case .blob:
221235
let length = Int(try cursor.readVBR(6))
222236
try cursor.advance(toBitAlignment: 32)
223-
payload = .blob(try cursor.read(bytes: length))
237+
payload = .blob(try Data(cursor.read(bytes: length)))
224238
try cursor.advance(toBitAlignment: 32)
225239
default:
226240
fatalError()

Sources/TSCUtility/SerializedDiagnostics.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
See http://swift.org/CONTRIBUTORS.txt for Swift project authors
99
*/
1010
import Foundation
11+
import TSCBasic
1112

1213
/// Represents diagnostics serialized in a .dia file by the Swift compiler or Clang.
1314
public struct SerializedDiagnostics {
@@ -42,13 +43,22 @@ public struct SerializedDiagnostics {
4243
/// Serialized diagnostics.
4344
public var diagnostics: [Diagnostic]
4445

46+
@available(*, deprecated, message: "Use SerializedDiagnostics.init(bytes:) instead")
4547
public init(data: Data) throws {
4648
var reader = Reader()
4749
try Bitcode.read(stream: data, using: &reader)
4850
guard let version = reader.versionNumber else { throw Error.noMetadataBlock }
4951
self.versionNumber = version
5052
self.diagnostics = reader.diagnostics
5153
}
54+
55+
public init(bytes: ByteString) throws {
56+
var reader = Reader()
57+
try Bitcode.read(bytes: bytes, using: &reader)
58+
guard let version = reader.versionNumber else { throw Error.noMetadataBlock }
59+
self.versionNumber = version
60+
self.diagnostics = reader.diagnostics
61+
}
5262
}
5363

5464
extension SerializedDiagnostics {

Tests/TSCUtilityTests/BitstreamTests.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ final class BitstreamTests: XCTestCase {
3737
.appending(components: "Inputs", "serialized.dia")
3838
let contents = try localFileSystem.readFileContents(bitstreamPath)
3939
var visitor = LoggingVisitor()
40-
try Bitcode.read(stream: Data(contents.contents), using: &visitor)
40+
try Bitcode.read(bytes: contents, using: &visitor)
4141
XCTAssertEqual(visitor.log, [
4242
"entering block: 8",
4343
"Record (id: 1, fields: [1], payload: none",
@@ -130,7 +130,7 @@ final class BitstreamTests: XCTestCase {
130130
.appending(components: "Inputs", "serialized.dia")
131131
let contents = try localFileSystem.readFileContents(bitstreamPath)
132132
var visitor = LoggingVisitor()
133-
try Bitcode.read(stream: Data(contents.contents), using: &visitor)
133+
try Bitcode.read(bytes: contents, using: &visitor)
134134
XCTAssertEqual(visitor.log, ["skipping block: 8",
135135
"skipping block: 9",
136136
"skipping block: 9",
@@ -155,7 +155,7 @@ final class BitstreamTests: XCTestCase {
155155
let bitstreamPath = AbsolutePath(#file).parentDirectory
156156
.appending(components: "Inputs", "serialized.dia")
157157
let contents = try localFileSystem.readFileContents(bitstreamPath)
158-
let bitcode = try Bitcode(data: Data(contents.contents))
158+
let bitcode = try Bitcode(bytes: contents)
159159
XCTAssertEqual(bitcode.signature, .init(string: "DIAG"))
160160
XCTAssertEqual(bitcode.elements.count, 18)
161161
guard case .block(let metadataBlock) = bitcode.elements.first else {
@@ -381,7 +381,7 @@ final class BitstreamTests: XCTestCase {
381381
}
382382

383383
var visitor = RoundTripVisitor()
384-
try Bitcode.read(stream: Data(writer.data), using: &visitor)
384+
try Bitcode.read(bytes: ByteString(writer.data), using: &visitor)
385385
}
386386

387387
func testSimpleRecordWrite() {

Tests/TSCUtilityTests/SerializedDiagnosticsTests.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ final class SerializedDiagnosticsTests: XCTestCase {
1818
let serializedDiagnosticsPath = AbsolutePath(#file).parentDirectory
1919
.appending(components: "Inputs", "serialized.dia")
2020
let contents = try localFileSystem.readFileContents(serializedDiagnosticsPath)
21-
let serializedDiags = try SerializedDiagnostics(data: Data(contents.contents))
21+
let serializedDiags = try SerializedDiagnostics(bytes: contents)
2222

2323
XCTAssertEqual(serializedDiags.versionNumber, 1)
2424
XCTAssertEqual(serializedDiags.diagnostics.count, 17)
@@ -66,7 +66,7 @@ final class SerializedDiagnosticsTests: XCTestCase {
6666
let serializedDiagnosticsPath = AbsolutePath(#file).parentDirectory
6767
.appending(components: "Inputs", "clang.dia")
6868
let contents = try localFileSystem.readFileContents(serializedDiagnosticsPath)
69-
let serializedDiags = try SerializedDiagnostics(data: Data(contents.contents))
69+
let serializedDiags = try SerializedDiagnostics(bytes: contents)
7070

7171
XCTAssertEqual(serializedDiags.versionNumber, 1)
7272
XCTAssertEqual(serializedDiags.diagnostics.count, 4)

0 commit comments

Comments
 (0)