Skip to content

Commit 3b1e980

Browse files
committed
Replace sequence init with inline byte array init
1 parent d4ec2e9 commit 3b1e980

2 files changed

Lines changed: 47 additions & 145 deletions

File tree

Sources/ClassicFourCharCode/ClassicFourCharCode.swift

Lines changed: 36 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -139,79 +139,6 @@ extension ClassicFourCharCode {
139139
public var isPrintable: Bool { !haveOctetsUnder(0x20) && !hasOctet(of: 0x7F) }
140140
}
141141

142-
// MARK: More Initializers
143-
144-
extension ClassicFourCharCode {
145-
/// Creates a new code repeating the given byte value.
146-
///
147-
/// - Parameter value: The octet to repeat.
148-
/// - Postcondition: `self.elementsEqual(repeatElement(value, count: 4))`
149-
@inlinable
150-
public init(repeating value: UInt8) {
151-
self.init(rawValue: FourCharCode(value) &* 0x0101_0101)
152-
}
153-
154-
/// Creates a code from the given byte values, in order.
155-
///
156-
/// - Parameters
157-
/// - first: The most-significant byte stored in the code.
158-
/// - second: The second-most significant byte stored in the code.
159-
/// - third: The second-lowest significant byte stored in the code.
160-
/// - fourth: The least-significant byte stored in the code.
161-
/// - Postcondition: `self.elementsEqual([first, second, third, fourth])`
162-
@inlinable
163-
public init(
164-
rawOctets first: UInt8,
165-
_ second: UInt8,
166-
_ third: UInt8,
167-
_ fourth: UInt8
168-
) {
169-
self.init(
170-
rawValue: FourCharCode(first) &* 0x0100_0000 | FourCharCode(second)
171-
&* 0x0001_0000 | FourCharCode(third) &* 0x0000_0100
172-
| FourCharCode(fourth)
173-
)
174-
}
175-
176-
/// Creates a code from combining bytes extracted from the given iterator.
177-
///
178-
/// - Parameter iterator: The source of the bytes to extract.
179-
/// - Postcondition: `self.elementsEqual([A, B, C, D])`,
180-
/// where `A`, `B`, `C`, and `D` are the first four bytes extracted from
181-
/// `iterator` (in that order).
182-
/// Any later elements are untouched.
183-
/// If `iterator` doesn't have at least four elements available,
184-
/// this initializer fails.
185-
public init?(extractingFrom iterator: inout some IteratorProtocol<UInt8>) {
186-
guard let first = iterator.next(), let second = iterator.next(),
187-
let third = iterator.next(), let fourth = iterator.next()
188-
else { return nil }
189-
self.init(rawOctets: first, second, third, fourth)
190-
}
191-
192-
/// Creates a code from combining bytes read from the given sequence.
193-
///
194-
/// - Parameters:
195-
/// - sequence: The source of the bytes to read.
196-
/// - useAllBytes: Whether every element from `sequence` needs to be read
197-
/// from.
198-
/// If not given,
199-
/// defaults to `true`,
200-
/// meaning the entire `sequence` needs to be read in.
201-
/// - Postcondition: `self.elementsEqual(sequence.prefix(4))`.
202-
/// If the `sequence` either has less than four elements,
203-
/// or it has more than four elements while `useAllBytes` is `true`,
204-
/// this initializer fails.
205-
public init?(
206-
reading sequence: some Sequence<UInt8>,
207-
totally useAllBytes: Bool = true
208-
) {
209-
var iterator = sequence.makeIterator()
210-
self.init(extractingFrom: &iterator)
211-
guard !useAllBytes || iterator.next() == nil else { return nil }
212-
}
213-
}
214-
215142
// MARK: Element Access
216143

217144
extension ClassicFourCharCode: ContiguousBytes {
@@ -222,3 +149,39 @@ extension ClassicFourCharCode: ContiguousBytes {
222149
return try Swift.withUnsafeBytes(of: &bigRawValue, body)
223150
}
224151
}
152+
153+
@available(macOS 26.0, *)
154+
extension ClassicFourCharCode {
155+
/// The four character codes, separated.
156+
///
157+
/// The first element is the string value's first character and
158+
/// the numeric value's highest-order code.
159+
/// Later elements correspond to later characters and lower-order codes.
160+
public var octets: [4 of UInt8] {
161+
.init({ index in
162+
return .init(truncatingIfNeeded: rawValue >> (8 * (3 - index)))
163+
})
164+
}
165+
166+
/// Creates a code from the given quartet of byte values.
167+
///
168+
/// - Parameter octets: The four separated character codes,
169+
/// starting from the string value's first character,
170+
/// which is also the numeric value's highest-order octet.
171+
/// Subsequent elements map to later characters in the string view and
172+
/// lower-order octets in the numeric value.
173+
/// - Postcondition: `self.rawValue ==`
174+
/// `octets[0] << 24 | octets[1] << 16 | octets[2] << 8 | octets[3]`
175+
public init(octets: [4 of UInt8]) {
176+
self.init(
177+
rawValue: octets.span.withUnsafeBufferPointer({ buffer in
178+
return buffer.lazy.map(FourCharCode.init(truncatingIfNeeded:)).reduce(
179+
into: 0
180+
) {
181+
$0 <<= 8
182+
$0 |= $1
183+
}
184+
})
185+
)
186+
}
187+
}

Tests/ClassicFourCharCodeTests/ClassicFourCharCodeTests.swift

Lines changed: 11 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -149,26 +149,10 @@ func memoryRead(_ rawCode: FourCharCode, _ octets: [UInt8]) async throws {
149149
#expect(code.withUnsafeBytes { $0.elementsEqual(octets) })
150150
}
151151

152-
/// Test repeating-value initializer.
153-
@Test("Repeating single octet initializer")
154-
func repeating() async throws {
155-
for i in UInt8.min...UInt8.max {
156-
let code = ClassicFourCharCode(repeating: i)
157-
let expectedRawValue = stride(from: 24, through: 0, by: -8).map {
158-
FourCharCode(i) << $0
159-
}.reduce(0, |)
160-
#expect(
161-
code.withUnsafeBytes({ bufferPointer in
162-
return bufferPointer.elementsEqual(repeatElement(i, count: 4))
163-
})
164-
)
165-
#expect(code.rawValue == expectedRawValue)
166-
}
167-
}
168-
169-
/// Test seperate-bytes initializer.
152+
/// Test reading from inline arrays.
153+
@available(macOS 26.0, *)
170154
@Test(
171-
"Individual byte initializer",
155+
"Initialize from inline array",
172156
arguments: zip(
173157
[
174158
[0, 0, 0, 0],
@@ -180,58 +164,13 @@ func repeating() async throws {
180164
]
181165
)
182166
)
183-
func seperateBytes(_ octets: [UInt8], `as` rawCode: FourCharCode) async throws {
184-
#expect(
185-
ClassicFourCharCode(rawOctets: octets[0], octets[1], octets[2], octets[3])
186-
== ClassicFourCharCode(rawValue: rawCode)
187-
)
188-
}
189-
190-
/// Test reading from iterators and sequences.
191-
@Test("Initialize from iterator/sequence")
192-
func initializeFromSequence() async throws {
193-
let source2 = [0x41 as UInt8, 0x42, 0x43, 0x44, 0x61, 0x62, 0x63, 0x64]
194-
do {
195-
var iterator = source2.makeIterator()
196-
let code1 = ClassicFourCharCode(extractingFrom: &iterator)
197-
let code2 = ClassicFourCharCode(extractingFrom: &iterator)
198-
#expect(code1 == .some(.init(rawValue: 0x4142_4344)))
199-
#expect(code2 == .some(.init(rawValue: 0x6162_6364)))
200-
#expect(iterator.next() == nil)
201-
}
202-
do {
203-
var iterator = source2.prefix(3).makeIterator()
204-
let code1 = ClassicFourCharCode(extractingFrom: &iterator)
205-
#expect(code1 == .none)
206-
}
207-
do {
208-
let code1 = ClassicFourCharCode(reading: source2.prefix(4))
209-
#expect(code1 == .some(.init(rawValue: 0x4142_4344)))
210-
211-
let code2 = ClassicFourCharCode(reading: source2.prefix(4), totally: true)
212-
#expect(code2 == .some(.init(rawValue: 0x4142_4344)))
213-
214-
let code3 = ClassicFourCharCode(reading: source2.prefix(4), totally: false)
215-
#expect(code3 == .some(.init(rawValue: 0x4142_4344)))
216-
}
217-
do {
218-
let code1 = ClassicFourCharCode(reading: source2.suffix(4))
219-
#expect(code1 == .some(.init(rawValue: 0x6162_6364)))
220-
221-
let code2 = ClassicFourCharCode(reading: source2.suffix(4), totally: true)
222-
#expect(code2 == .some(.init(rawValue: 0x6162_6364)))
223-
224-
let code3 = ClassicFourCharCode(reading: source2.suffix(4), totally: false)
225-
#expect(code3 == .some(.init(rawValue: 0x6162_6364)))
226-
}
227-
do {
228-
let code1 = ClassicFourCharCode(reading: source2)
229-
#expect(code1 == .none)
230-
231-
let code2 = ClassicFourCharCode(reading: source2, totally: true)
232-
#expect(code2 == .none)
233-
234-
let code3 = ClassicFourCharCode(reading: source2, totally: false)
235-
#expect(code3 == .some(.init(rawValue: 0x4142_4344)))
167+
func initializeFromArray(_ octets: [UInt8], `as` rawCode: FourCharCode)
168+
async throws
169+
{
170+
let array: InlineArray = [octets[0], octets[1], octets[2], octets[3]]
171+
let code = ClassicFourCharCode(octets: array)
172+
#expect(code.rawValue == rawCode)
173+
code.octets.span.withUnsafeBufferPointer { buffer in
174+
#expect(buffer.elementsEqual(octets))
236175
}
237176
}

0 commit comments

Comments
 (0)