Skip to content

Add BluetoothSDP - #230

Merged
colemancda merged 11 commits into
masterfrom
feature/sdp
Aug 3, 2026
Merged

Add BluetoothSDP#230
colemancda merged 11 commits into
masterfrom
feature/sdp

Conversation

@colemancda

@colemancda colemancda commented Aug 3, 2026

Copy link
Copy Markdown
Member

Summary

Adds BluetoothSDP, an idiomatic pure-Swift implementation of the SDP
(Service Discovery Protocol) data model, service record, and PDU
framing — no C, no vendored headers, no @c ABI bindings. A normal,
always-on target alongside BluetoothGAP/BluetoothGATT/BluetoothHCI,
built the same way the rest of this package encodes its wire formats
(DataConvertible, reusing BluetoothUUID for SDP's UUID data
element).

  • SDPDataElement — the core recursive data model every SDP value
    (attribute values, search patterns, attribute ID lists) is built
    from: null, unsigned/signed integers (8 through 128-bit), UUID,
    text, boolean, sequence, alternative, and URL, each self-describing
    via a one-byte type/size-descriptor header. Since SDP is big-endian
    (unlike most of this package's little-endian wire formats), integer
    encode/decode goes through small dedicated big-endian helpers
    (SDPBigEndian.swift) rather than the package's little-endian-
    oriented integer DataConvertible conformances.
  • SDPAttributeID — the universal attribute IDs every service record
    shares, plus the language-base-offset scheme the name/description/
    provider string attributes are defined relative to.
  • SDPServiceRecord — a record's attributes keyed by SDPAttributeID,
    encoding to/decoding from the flat data element sequence the wire
    format expects, with convenience accessors for the universal
    attributes (service class ID list, protocol descriptor list,
    Bluetooth profile descriptor list, service name/description/provider).
  • SDPPDUHeader — the fixed 5-byte PDU header (PDU ID, transaction
    ID, parameter length) plus the SDPPDUID values.
  • SDPError — the ErrorResponse error codes.

Scope boundary: this covers PDU framing and the data model/record
codec, not the per-request-type parameter layouts (ServiceSearchRequest
and friends) or continuation-state fragmentation/reassembly — those
belong with a socket-based session layer, not this pure data model,
and aren't included here.

Verified

  • swift build / swift test — full suite (494 tests, 32 suites)
    passes, no regressions.
  • 9 new tests: data element round-trip across every case (including a
    128-bit integer, empty string, and a length large enough to force
    the 16-bit size descriptor), nested sequences, malformed-input
    rejection, service record round-trip (including attribute-sorted
    wire order), attribute ID helpers, PDU header round-trip, and error
    code description.

Test plan

  • swift build
  • swift test --filter SDPTests
  • swift test (full suite)

@github-code-quality

github-code-quality Bot commented Aug 3, 2026

Copy link
Copy Markdown

Code Coverage Overview

Languages: Swift

Swift / code-coverage/llvm-cov

The overall coverage in commit 6a3b633 in the feature/sdp branch is 89%. The coverage in commit c0c14dc in the master branch is 88%.

Show a code coverage summary of the most impacted files.
File master c0c14dc feature/sdp 6a3b633 +/-
Sources/Bluetoo...tributeID.swift 0% 47% +47%
Sources/Bluetoo...DP/SDPPDU.swift 0% 53% +53%
Sources/Bluetoo.../SDPError.swift 0% 88% +88%
Sources/Bluetoo...iceRecord.swift 0% 89% +89%
Sources/Bluetoo...taElement.swift 0% 97% +97%
Sources/Bluetoo...BigEndian.swift 0% 100% +100%

Updated August 03, 2026 01:29 UTC

@colemancda colemancda changed the title Add BluetoothSDP: Swift implementation of the SDP data model, codec, and record accessors Add SDP Aug 3, 2026
SDP PDUs are network byte order, unlike most Bluetooth wire formats in
this package, which are little-endian — so this module reads/writes
multi-byte integers explicitly rather than reusing the
little-endian-oriented DataConvertible conformances elsewhere.
Every value inside an SDP PDU or service record — attribute values,
search patterns, attribute ID lists — is a data element, self-
describing via a one-byte type/size-descriptor header. Conforms to
this package's DataConvertible, matching how the rest of the
Bluetooth package (BluetoothGAP, BluetoothGATT) encodes its own wire
formats, rather than a C ABI.
Covers PDU framing (PDU ID, transaction ID, parameter length) plus
the data model and record codec. Per-request-type parameter layouts
and continuation-state fragmentation belong with a socket-based
session layer, not this pure data model, and aren't included here.
Attributes keyed by SDPAttributeID, encoding/decoding to the flat
data element sequence the wire format expects (attribute ID followed
directly by its value, sorted by ID), plus convenience accessors for
the universal attributes (service class list, protocol descriptor
list, profile descriptor list, and the language-base-relative
name/description/provider strings).
A normal, always-on target like BluetoothGAP/BluetoothGATT/BluetoothHCI
— no C, no environment-variable gating, no @c bindings; just an
idiomatic Swift module depending only on Bluetooth.
@colemancda colemancda changed the title Add SDP Add BluetoothSDP: pure-Swift SDP data model, service record, and PDU header Aug 3, 2026
@colemancda colemancda changed the title Add BluetoothSDP: pure-Swift SDP data model, service record, and PDU header Add BluetoothSDP Aug 3, 2026
The generic FixedWidthInteger-constrained big-endian helper doesn't
compile for UInt128 at this package's macOS 10.15 deployment target,
since this package's UInt128 only conforms to FixedWidthInteger under
@available(macOS 15, ...) (a hand-rolled struct backs it before the
native stdlib type existed). Dedicated, non-generic UInt128 overloads
go through the always-available ByteValue tuple accessor instead.
Round-tripping alone can't distinguish correct big-endian byte order
from a consistently-reversed implementation, since encode/decode are
exact inverses of each other by construction either way. This checks
against a known numeric value instead.
Same availability gate as the library fix — UInt128's
ExpressibleByIntegerLiteral and BinaryInteger conformances are
macOS 15+ only here. Builds the comparison value via the
unconditionally-available ByteValue tuple initializer instead.
@colemancda
colemancda merged commit 653818f into master Aug 3, 2026
59 of 62 checks passed
@colemancda
colemancda deleted the feature/sdp branch August 3, 2026 02:09
colemancda added a commit that referenced this pull request Aug 3, 2026
Rebasing feature/c-abi onto master surfaced a name collision:
feature/c-abi's own C-ABI-style sdp_* implementation was declared as
a target/product named BluetoothSDP, unaware that master had since
gained an unrelated pure-Swift BluetoothSDP target (merged via #230,
after the "no C ABI at all" decision for feature/sdp). Both ended up
declared in Package.swift and both wrote into Sources/BluetoothSDP/.

Folds the C-ABI sdp_* implementation into BluetoothABI instead of
giving it a separate module — CMake already links them into a single
shared object (bluetooth-util), so this also removes a redundant
static-library layer. The 8 source files move to Sources/BluetoothABI/
with an SDP prefix (avoiding a real filename collision on UUID.swift,
whose bt_uuid_* and sdp_* implementations are unrelated), and their
round-trip tests move into BluetoothABITests. Sources/BluetoothSDP/
now holds only master's pure-Swift implementation, untouched.

Updates CMakeLists.txt (drops the separate BluetoothSDP static
library), Conformance/compare.sh (sdp_* symbols now live in
libBluetoothABI.so, so the differential driver no longer needs a
second binary path), and CBluetooth's README.
colemancda added a commit that referenced this pull request Aug 3, 2026
Rebasing feature/c-abi onto master surfaced a name collision:
feature/c-abi's own C-ABI-style sdp_* implementation was declared as
a target/product named BluetoothSDP, unaware that master had since
gained an unrelated pure-Swift BluetoothSDP target (merged via #230,
after the "no C ABI at all" decision for feature/sdp). Both ended up
declared in Package.swift and both wrote into Sources/BluetoothSDP/.

Folds the C-ABI sdp_* implementation into BluetoothABI instead of
giving it a separate module — CMake already links them into a single
shared object (bluetooth-util), so this also removes a redundant
static-library layer. The 8 source files move to Sources/BluetoothABI/
with an SDP prefix (avoiding a real filename collision on UUID.swift,
whose bt_uuid_* and sdp_* implementations are unrelated), and their
round-trip tests move into BluetoothABITests. Sources/BluetoothSDP/
now holds only master's pure-Swift implementation, untouched.

Updates CMakeLists.txt (drops the separate BluetoothSDP static
library), Conformance/compare.sh (sdp_* symbols now live in
libBluetoothABI.so, so the differential driver no longer needs a
second binary path), and CBluetooth's README.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant