Skip to content

Commit e8f3efc

Browse files
authored
Remove NIO dependency (#20)
Motivation: NIO's ByteBuffer is used as an implementation detail for parsing responses in the DNSD implementation. However NIO is quite a heavy dependency so we should avoid it if possible. Modifications: - Use `ArraySlice<UInt8>` instead of `ByteBuffer` and remove the dependency on SwiftNIO Result: No dependency on SwiftNIO
1 parent 66b7dc7 commit e8f3efc

File tree

3 files changed

+89
-10
lines changed

3 files changed

+89
-10
lines changed

Package.swift

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ let package = Package(
2929
.library(name: "AsyncDNSResolver", targets: ["AsyncDNSResolver"]),
3030
],
3131
dependencies: [
32-
.package(url: "https://github.com/apple/swift-nio", .upToNextMajor(from: "2.53.0")),
3332
.package(url: "https://github.com/apple/swift-docc-plugin", from: "1.0.0"),
3433
],
3534
targets: [
@@ -49,7 +48,6 @@ let package = Package(
4948
name: "AsyncDNSResolver",
5049
dependencies: [
5150
"CAsyncDNSResolver",
52-
.product(name: "NIOCore", package: "swift-nio"),
5351
]
5452
),
5553

Sources/AsyncDNSResolver/dnssd/DNSResolver_dnssd.swift

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414

1515
#if canImport(Darwin)
1616
import dnssd
17-
import NIOCore
1817

1918
/// ``DNSResolver`` implementation backed by dnssd framework.
2019
public struct DNSSDDNSResolver: DNSResolver {
@@ -267,7 +266,7 @@ extension DNSSD {
267266
}
268267

269268
let bufferPtr = UnsafeBufferPointer(start: ptr, count: Int(length))
270-
var buffer = ByteBuffer(bytes: bufferPtr)
269+
var buffer = Array(bufferPtr)[...]
271270

272271
guard let nameserver = self.readName(&buffer) else {
273272
throw AsyncDNSResolver.Error.badResponse("failed to read name")
@@ -290,7 +289,7 @@ extension DNSSD {
290289
}
291290

292291
let bufferPtr = UnsafeBufferPointer(start: ptr, count: Int(length))
293-
var buffer = ByteBuffer(bytes: bufferPtr)
292+
var buffer = Array(bufferPtr)[...]
294293

295294
guard let cname = self.readName(&buffer) else {
296295
throw AsyncDNSResolver.Error.badResponse("failed to read name")
@@ -313,7 +312,7 @@ extension DNSSD {
313312
}
314313

315314
let bufferPtr = UnsafeBufferPointer(start: ptr, count: Int(length))
316-
var buffer = ByteBuffer(bytes: bufferPtr)
315+
var buffer = Array(bufferPtr)[...]
317316

318317
guard let mname = self.readName(&buffer),
319318
let rname = self.readName(&buffer),
@@ -350,7 +349,7 @@ extension DNSSD {
350349
}
351350

352351
let bufferPtr = UnsafeBufferPointer(start: ptr, count: Int(length))
353-
var buffer = ByteBuffer(bytes: bufferPtr)
352+
var buffer = Array(bufferPtr)[...]
354353

355354
guard let name = self.readName(&buffer) else {
356355
throw AsyncDNSResolver.Error.badResponse("failed to read name")
@@ -373,7 +372,7 @@ extension DNSSD {
373372
}
374373

375374
let bufferPtr = UnsafeBufferPointer(start: ptr, count: Int(length))
376-
var buffer = ByteBuffer(bytes: bufferPtr)
375+
var buffer = Array(bufferPtr)[...]
377376

378377
guard let priority = buffer.readInteger(as: UInt16.self),
379378
let host = self.readName(&buffer) else {
@@ -416,7 +415,7 @@ extension DNSSD {
416415
}
417416

418417
let bufferPtr = UnsafeBufferPointer(start: ptr, count: Int(length))
419-
var buffer = ByteBuffer(bytes: bufferPtr)
418+
var buffer = Array(bufferPtr)[...]
420419

421420
guard let priority = buffer.readInteger(as: UInt16.self),
422421
let weight = buffer.readInteger(as: UInt16.self),
@@ -440,13 +439,14 @@ extension DNSSD {
440439
}
441440

442441
extension DNSSDQueryReplyHandler {
443-
func readName(_ buffer: inout ByteBuffer) -> String? {
442+
func readName(_ buffer: inout ArraySlice<UInt8>) -> String? {
444443
var parts: [String] = []
445444
while let length = buffer.readInteger(as: UInt8.self),
446445
length > 0,
447446
let part = buffer.readString(length: Int(length)) {
448447
parts.append(part)
449448
}
449+
450450
return parts.isEmpty ? nil : parts.joined(separator: ".")
451451
}
452452

@@ -460,4 +460,30 @@ extension DNSSDQueryReplyHandler {
460460
return record
461461
}
462462
}
463+
464+
extension ArraySlice<UInt8> {
465+
mutating func readInteger<T: FixedWidthInteger>(as: T.Type = T.self) -> T? {
466+
let size = MemoryLayout<T>.size
467+
guard self.count >= size else { return nil }
468+
469+
let value = self.withUnsafeBytes { pointer in
470+
var value = T.zero
471+
Swift.withUnsafeMutableBytes(of: &value) { valuePointer in
472+
valuePointer.copyMemory(from: UnsafeRawBufferPointer(rebasing: pointer[..<size]))
473+
}
474+
return value.bigEndian
475+
}
476+
477+
self = self.dropFirst(size)
478+
return value
479+
}
480+
481+
mutating func readString(length: Int) -> String? {
482+
guard self.count >= length else { return nil }
483+
484+
let prefix = self.prefix(length)
485+
self = self.dropFirst(length)
486+
return String(decoding: prefix, as: UTF8.self)
487+
}
488+
}
463489
#endif
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the SwiftAsyncDNSResolver open source project
4+
//
5+
// Copyright (c) 2024 Apple Inc. and the SwiftAsyncDNSResolver project authors
6+
// Licensed under Apache License v2.0
7+
//
8+
// See LICENSE.txt for license information
9+
// See CONTRIBUTORS.txt for the list of SwiftAsyncDNSResolver project authors
10+
//
11+
// SPDX-License-Identifier: Apache-2.0
12+
//
13+
//===----------------------------------------------------------------------===//
14+
15+
@testable import AsyncDNSResolver
16+
import XCTest
17+
18+
#if canImport(Darwin)
19+
final class DNSDArraySliceTests: XCTestCase {
20+
func testReadUnsignedInteger() {
21+
// [UInt8(0), UInt16(.max), UInt32(0), UInt64(.max)]
22+
let bytes: [UInt8] = [0, 255, 255, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255]
23+
var slice = bytes[...]
24+
25+
XCTAssertEqual(slice.readInteger(as: UInt8.self), 0)
26+
XCTAssertEqual(slice.readInteger(as: UInt16.self), .max)
27+
XCTAssertEqual(slice.readInteger(as: UInt32.self), 0)
28+
XCTAssertEqual(slice.readInteger(as: UInt64.self), .max)
29+
30+
XCTAssertNil(slice.readInteger(as: UInt8.self))
31+
}
32+
33+
func testReadSignedInteger() {
34+
// [Int8(0), Int16(-1), Int32(0), Int64(-1)]
35+
let bytes: [UInt8] = [0, 255, 255, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255]
36+
var slice = bytes[...]
37+
38+
XCTAssertEqual(slice.readInteger(as: Int8.self), 0)
39+
XCTAssertEqual(slice.readInteger(as: Int16.self), -1)
40+
XCTAssertEqual(slice.readInteger(as: Int32.self), 0)
41+
XCTAssertEqual(slice.readInteger(as: Int64.self), -1)
42+
43+
XCTAssertNil(slice.readInteger(as: Int8.self))
44+
}
45+
46+
func testReadString() {
47+
let bytes = Array("hello, world!".utf8)
48+
var slice = bytes[...]
49+
50+
XCTAssertEqual(slice.readString(length: 13), "hello, world!")
51+
XCTAssertEqual(slice.readString(length: 0), "")
52+
XCTAssertNil(slice.readString(length: 1))
53+
}
54+
}
55+
#endif

0 commit comments

Comments
 (0)