Skip to content

Commit 3295f28

Browse files
authored
Merge pull request #23 from hartbit/byte-string-api
Add new useful ByteString APIs
2 parents d687256 + 70f1c5f commit 3295f28

File tree

3 files changed

+47
-0
lines changed

3 files changed

+47
-0
lines changed

Sources/TSCBasic/ByteString.swift

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

11+
import Foundation
12+
1113
/// A `ByteString` represents a sequence of bytes.
1214
///
1315
/// This struct provides useful operations for working with buffers of
@@ -73,6 +75,33 @@ public struct ByteString: ExpressibleByArrayLiteral, Hashable {
7375
public var count: Int {
7476
return _bytes.count
7577
}
78+
79+
/// Gives a non-escaping closure temporary access to an immutable `Data` instance wrapping the `ByteString` without
80+
/// copying any memory around.
81+
///
82+
/// - Parameters:
83+
/// - closure: The closure that will have access to a `Data` instance for the duration of its lifetime.
84+
@inlinable
85+
public func withData<T>(_ closure: (Data) throws -> T) rethrows -> T {
86+
return try _bytes.withUnsafeBytes { pointer -> T in
87+
let mutatingPointer = UnsafeMutableRawPointer(mutating: pointer.baseAddress!)
88+
let data = Data(bytesNoCopy: mutatingPointer, count: pointer.count, deallocator: .none)
89+
return try closure(data)
90+
}
91+
}
92+
93+
/// Returns a `String` lowercase hexadecimal representation of the contents of the `ByteString`.
94+
@inlinable
95+
public var hexadecimalRepresentation: String {
96+
_bytes.reduce("") {
97+
var str = String($1, radix: 16)
98+
// The above method does not do zero padding.
99+
if str.count == 1 {
100+
str = "0" + str
101+
}
102+
return $0 + str
103+
}
104+
}
76105
}
77106

78107
/// Conform to CustomDebugStringConvertible.

Tests/TSCBasicTests/ByteStringTests.swift

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,4 +67,20 @@ class ByteStringTests: XCTestCase {
6767
s <<< ByteString([1, 2, 3])
6868
XCTAssertEqual(s.bytes, [1, 2, 3])
6969
}
70+
71+
func testWithData() {
72+
let byteString = ByteString([0xde, 0xad, 0xbe, 0xef])
73+
byteString.withData { data in
74+
XCTAssertEqual(data.count, 4)
75+
XCTAssertEqual(data[0], 0xde)
76+
XCTAssertEqual(data[1], 0xad)
77+
XCTAssertEqual(data[2], 0xbe)
78+
XCTAssertEqual(data[3], 0xef)
79+
}
80+
}
81+
82+
func testHexadecimalRepresentation() {
83+
let byteString = ByteString([0xde, 0xad, 0xbe, 0xef])
84+
XCTAssertEqual(byteString.hexadecimalRepresentation, "deadbeef")
85+
}
7086
}

Tests/TSCBasicTests/XCTestManifests.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@ extension ByteStringTests {
2020
("testByteStreamable", testByteStreamable),
2121
("testDescription", testDescription),
2222
("testHashable", testHashable),
23+
("testHexadecimalRepresentation", testHexadecimalRepresentation),
2324
("testInitializers", testInitializers),
25+
("testWithData", testWithData),
2426
]
2527
}
2628

0 commit comments

Comments
 (0)