Skip to content

Commit b988856

Browse files
committed
style: format with swift-format and enforce lint + warnings in CI
Adds .swift-format (4-space); CI lint job + -warnings-as-errors on Linux.
1 parent 2708ac5 commit b988856

8 files changed

Lines changed: 66 additions & 25 deletions

File tree

.dod.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# Definition of Done, shown by `tbdflow commit` before each commit.
22
checklist:
3-
- "`swift build -c release` succeeds."
3+
- "`swift build -c release` succeeds with no warnings (`-Xswiftc -warnings-as-errors`)."
4+
- "`swift format lint --strict --recursive Sources Tests Package.swift` is clean."
45
- "`swift test` passes on Linux."
56
- "New behaviour is covered by tests (golden vectors for codec changes)."
67
- "CHANGELOG.md is updated for user-visible changes."

.github/workflows/ci.yml

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ jobs:
1717
steps:
1818
- uses: actions/checkout@v7
1919
- run: swift --version
20-
- run: swift build
21-
- run: swift test
20+
- run: swift build -Xswiftc -warnings-as-errors
21+
- run: swift test -Xswiftc -warnings-as-errors
2222

2323
macos:
2424
name: Build & test (macOS)
@@ -48,3 +48,11 @@ jobs:
4848
COBS_CONFORMANCE_SENTINEL: ${{ github.workspace }}/sentinel.jsonl
4949
COBS_CONFORMANCE_ERRORS: ${{ github.workspace }}/errors.jsonl
5050
run: swift test --filter Conformance
51+
52+
lint:
53+
name: swift-format lint
54+
runs-on: ubuntu-latest
55+
container: swift:6.1
56+
steps:
57+
- uses: actions/checkout@v7
58+
- run: swift format lint --strict --recursive Sources Tests Package.swift

.swift-format

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"version": 1,
3+
"lineLength": 100,
4+
"indentation": {
5+
"spaces": 4
6+
},
7+
"maximumBlankLines": 1,
8+
"respectsExistingLineBreaks": true,
9+
"lineBreakBeforeEachArgument": false,
10+
"lineBreakBeforeControlFlowKeywords": false,
11+
"indentConditionalCompilationBlocks": true
12+
}

Package.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ let package = Package(
2121
.library(
2222
name: "CobsCodec",
2323
targets: ["CobsCodec"]
24-
),
24+
)
2525
],
2626
targets: [
2727
.target(

Sources/CobsCodec/Framing.swift

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,11 @@ public enum Framing {
2929
/// - reduced: Use COBS/R (``Cobsr``) instead of basic COBS (``Cobs``).
3030
/// - sentinel: The byte the encoding avoids and that delimits the frame.
3131
/// - Returns: The encoded packet followed by the delimiter byte.
32-
public static func frame(_ packet: [UInt8], reduced: Bool = false, sentinel: UInt8 = 0) -> [UInt8] {
33-
var output = reduced
32+
public static func frame(_ packet: [UInt8], reduced: Bool = false, sentinel: UInt8 = 0)
33+
-> [UInt8]
34+
{
35+
var output =
36+
reduced
3437
? Cobsr.encode(packet, sentinel: sentinel)
3538
: Cobs.encode(packet, sentinel: sentinel)
3639
output.append(sentinel)
@@ -73,7 +76,8 @@ public enum Framing {
7376
}
7477
continue
7578
}
76-
let decoded = reduced
79+
let decoded =
80+
reduced
7781
? try Cobsr.decode(frame, sentinel: sentinel)
7882
: try Cobs.decode(frame, sentinel: sentinel)
7983
frames.append(decoded)
@@ -147,7 +151,8 @@ public final class CobsStreamDecoder {
147151
}
148152
continue
149153
}
150-
let decoded = reduced
154+
let decoded =
155+
reduced
151156
? try Cobsr.decode(frame, sentinel: sentinel)
152157
: try Cobs.decode(frame, sentinel: sentinel)
153158
frames.append(decoded)

Tests/CobsCodecTests/ConformanceTests.swift

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,9 @@
1111
// COBS_CONFORMANCE_ERRORS -> {encoded, cobs, cobsr} (cobs/cobsr may be null)
1212
//
1313

14-
import XCTest
1514
import Foundation
15+
import XCTest
16+
1617
@testable import CobsCodec
1718

1819
final class ConformanceTests: XCTestCase {
@@ -102,8 +103,12 @@ final class ConformanceTests: XCTestCase {
102103
XCTAssertEqual(encCobs, cobs, "line \(n): cobs sentinel encode")
103104
XCTAssertEqual(encCobsr, cobsr, "line \(n): cobsr sentinel encode")
104105
// sentinel decode matches
105-
XCTAssertEqual(try Cobs.decode(cobs, sentinel: sentinel), decoded, "line \(n): cobs sentinel decode")
106-
XCTAssertEqual(try Cobsr.decode(cobsr, sentinel: sentinel), decoded, "line \(n): cobsr sentinel decode")
106+
XCTAssertEqual(
107+
try Cobs.decode(cobs, sentinel: sentinel), decoded,
108+
"line \(n): cobs sentinel decode")
109+
XCTAssertEqual(
110+
try Cobsr.decode(cobsr, sentinel: sentinel), decoded,
111+
"line \(n): cobsr sentinel decode")
107112
// output avoids the sentinel byte
108113
XCTAssertFalse(encCobs.contains(sentinel), "line \(n): cobs output contains sentinel")
109114
XCTAssertFalse(encCobsr.contains(sentinel), "line \(n): cobsr output contains sentinel")
@@ -127,16 +132,22 @@ final class ConformanceTests: XCTestCase {
127132
// where null means the decode must throw.
128133
switch expectation(row, "cobs") {
129134
case .output(let want):
130-
XCTAssertEqual(try Cobs.decode(encoded), want, "line \(n): cobs decode of \(hexFromBytes(encoded))")
135+
XCTAssertEqual(
136+
try Cobs.decode(encoded), want,
137+
"line \(n): cobs decode of \(hexFromBytes(encoded))")
131138
case .throwsError:
132-
XCTAssertThrowsError(try Cobs.decode(encoded), "line \(n): cobs decode should throw")
139+
XCTAssertThrowsError(
140+
try Cobs.decode(encoded), "line \(n): cobs decode should throw")
133141
}
134142

135143
switch expectation(row, "cobsr") {
136144
case .output(let want):
137-
XCTAssertEqual(try Cobsr.decode(encoded), want, "line \(n): cobsr decode of \(hexFromBytes(encoded))")
145+
XCTAssertEqual(
146+
try Cobsr.decode(encoded), want,
147+
"line \(n): cobsr decode of \(hexFromBytes(encoded))")
138148
case .throwsError:
139-
XCTAssertThrowsError(try Cobsr.decode(encoded), "line \(n): cobsr decode should throw")
149+
XCTAssertThrowsError(
150+
try Cobsr.decode(encoded), "line \(n): cobsr decode should throw")
140151
}
141152
}
142153
}

Tests/CobsCodecTests/GoldenTests.swift

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
//
88

99
import XCTest
10+
1011
@testable import CobsCodec
1112

1213
final class GoldenTests: XCTestCase {
@@ -63,7 +64,7 @@ final class GoldenTests: XCTestCase {
6364

6465
func testCobsRoundTripBlockBoundaries() throws {
6566
for n in [253, 254, 255, 256, 510] {
66-
let data = (0..<n).map { UInt8(($0 % 255) + 1) } // no zeros
67+
let data = (0..<n).map { UInt8(($0 % 255) + 1) } // no zeros
6768
let encoded = Cobs.encode(data)
6869
XCTAssertFalse(encoded.contains(0), "n=\(n) output has zero")
6970
XCTAssertEqual(try Cobs.decode(encoded), data, "cobs round trip n=\(n)")
@@ -78,7 +79,7 @@ final class GoldenTests: XCTestCase {
7879
// A pseudo-random spread of lengths and byte values.
7980
var state: UInt64 = 0x1234_5678_9abc_def0
8081
func next() -> UInt8 {
81-
state = state &* 6364136223846793005 &+ 1442695040888963407
82+
state = state &* 6_364_136_223_846_793_005 &+ 1_442_695_040_888_963_407
8283
return UInt8((state >> 33) & 0xFF)
8384
}
8485
for len in 0..<300 {
@@ -105,13 +106,15 @@ final class GoldenTests: XCTestCase {
105106
for p in payloads {
106107
let c = Cobs.encode(p, sentinel: sentinel)
107108
if sentinel != 0 {
108-
XCTAssertFalse(c.contains(sentinel), "cobs output must avoid sentinel \(sentinel)")
109+
XCTAssertFalse(
110+
c.contains(sentinel), "cobs output must avoid sentinel \(sentinel)")
109111
}
110112
XCTAssertEqual(try Cobs.decode(c, sentinel: sentinel), p)
111113

112114
let r = Cobsr.encode(p, sentinel: sentinel)
113115
if sentinel != 0 {
114-
XCTAssertFalse(r.contains(sentinel), "cobsr output must avoid sentinel \(sentinel)")
116+
XCTAssertFalse(
117+
r.contains(sentinel), "cobsr output must avoid sentinel \(sentinel)")
115118
}
116119
XCTAssertEqual(try Cobsr.decode(r, sentinel: sentinel), p)
117120
}
@@ -123,7 +126,7 @@ final class GoldenTests: XCTestCase {
123126
func testDecodeInPlaceMatchesNormal() throws {
124127
var state: UInt64 = 0xdead_beef_cafe_babe
125128
func next() -> UInt8 {
126-
state = state &* 6364136223846793005 &+ 1442695040888963407
129+
state = state &* 6_364_136_223_846_793_005 &+ 1_442_695_040_888_963_407
127130
return UInt8((state >> 33) & 0xFF)
128131
}
129132
for sentinel: UInt8 in [0x00, 0x7F, 0xFF] {
@@ -190,7 +193,8 @@ final class GoldenTests: XCTestCase {
190193
wire += Framing.frame(p, reduced: reduced, sentinel: sentinel)
191194
nonEmpty.append(p)
192195
}
193-
let out = try Framing.unframe(wire, reduced: reduced, skipEmpty: false, sentinel: sentinel)
196+
let out = try Framing.unframe(
197+
wire, reduced: reduced, skipEmpty: false, sentinel: sentinel)
194198
XCTAssertEqual(out, nonEmpty, "reduced=\(reduced) sentinel=\(sentinel)")
195199
}
196200
}
@@ -246,7 +250,7 @@ final class GoldenTests: XCTestCase {
246250

247251
func testStreamDecoderReset() throws {
248252
let dec = CobsStreamDecoder()
249-
_ = try dec.feed([0x02, 0x11]) // partial frame, no delimiter yet
253+
_ = try dec.feed([0x02, 0x11]) // partial frame, no delimiter yet
250254
dec.reset()
251255
// After reset the buffered partial frame is gone; a fresh frame decodes.
252256
let frames = try dec.feed(Framing.frame([0x33]))

Tests/CobsCodecTests/HexHelpers.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@ func bytesFromHex(_ hex: String) -> [UInt8]? {
1919

2020
func nibble(_ c: UInt8) -> UInt8? {
2121
switch c {
22-
case 0x30...0x39: return c - 0x30 // '0'..'9'
23-
case 0x61...0x66: return c - 0x61 + 10 // 'a'..'f'
24-
case 0x41...0x46: return c - 0x41 + 10 // 'A'..'F'
22+
case 0x30...0x39: return c - 0x30 // '0'..'9'
23+
case 0x61...0x66: return c - 0x61 + 10 // 'a'..'f'
24+
case 0x41...0x46: return c - 0x41 + 10 // 'A'..'F'
2525
default: return nil
2626
}
2727
}

0 commit comments

Comments
 (0)