Skip to content

Commit f628219

Browse files
committed
Add doc comments for GDBHostCommandDecoder
# Conflicts: # Sources/GDBRemoteProtocol/GDBPacket.swift
1 parent 2407284 commit f628219

File tree

3 files changed

+71
-20
lines changed

3 files changed

+71
-20
lines changed

Sources/GDBRemoteProtocol/GDBHostCommand.swift

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,6 @@
1616
/// * https://sourceware.org/gdb/current/onlinedocs/gdb.html/General-Query-Packets.html
1717
/// * https://lldb.llvm.org/resources/lldbgdbremote.html
1818
package struct GDBHostCommand: Equatable {
19-
enum Error: Swift.Error {
20-
case unexpectedArgumentsValue
21-
case unknownCommand(kind: String, arguments: String)
22-
}
23-
2419
package enum Kind: String, Equatable {
2520
// Currently listed in the order that LLDB sends them in.
2621
case startNoAckMode
@@ -94,8 +89,12 @@ package struct GDBHostCommand: Equatable {
9489

9590
/// Arguments supplied with a host command.
9691
package let arguments: String
97-
98-
package init(kindString: String, arguments: String) throws {
92+
93+
/// Initialize a host command from raw strings sent from a host.
94+
/// - Parameters:
95+
/// - kindString: raw ``String`` that denotes kind of the command.
96+
/// - arguments: raw arguments that immediately follow kind of the command.
97+
package init(kindString: String, arguments: String) throws(GDBHostCommandDecoder.Error) {
9998
let registerInfoPrefix = "qRegisterInfo"
10099

101100
if kindString.starts(with: "x") {
@@ -110,20 +109,20 @@ package struct GDBHostCommand: Equatable {
110109
self.kind = .registerInfo
111110

112111
guard arguments.isEmpty else {
113-
throw Error.unexpectedArgumentsValue
112+
throw GDBHostCommandDecoder.Error.unexpectedArgumentsValue
114113
}
115114
self.arguments = String(kindString.dropFirst(registerInfoPrefix.count))
116115
return
117116
} else if let kind = Kind(rawValue: kindString) {
118117
self.kind = kind
119118
} else {
120-
throw Error.unknownCommand(kind: kindString, arguments: arguments)
119+
throw GDBHostCommandDecoder.Error.unknownCommand(kind: kindString, arguments: arguments)
121120
}
122121

123122
self.arguments = arguments
124123
}
125124

126-
/// Memberwise initializer of `GDBHostCommand` type.
125+
/// Member-wise initializer of `GDBHostCommand` type.
127126
package init(kind: Kind, arguments: String) {
128127
self.kind = kind
129128
self.arguments = arguments

Sources/GDBRemoteProtocol/GDBHostCommandDecoder.swift

Lines changed: 45 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,58 +2,93 @@ import Logging
22
import NIOCore
33

44
extension ByteBuffer {
5+
/// Returns `true` if byte to be read immediately is a GDB RP checksum
6+
/// delimiter. Returns `false` otherwise.
57
var isChecksumDelimiterAtReader: Bool {
68
self.peekInteger(as: UInt8.self) == UInt8(ascii: "#")
79
}
810

11+
/// Returns `true` if byte to be read immediately is a GDB RP command arguments
12+
/// delimiter. Returns `false` otherwise.
913
var isArgumentsDelimiterAtReader: Bool {
1014
self.peekInteger(as: UInt8.self) == UInt8(ascii: ":")
1115
}
1216
}
1317

18+
/// Decoder of GDB RP host commands, that takes raw `ByteBuffer` as an input encoded
19+
/// per https://sourceware.org/gdb/current/onlinedocs/gdb.html/Overview.html#Overview
20+
/// and produces a `GDBPacket<GDBHostCommand>` value as output. This decoder is
21+
/// compatible with NIO channel pipelines, making it easy to integrate with different
22+
/// I/O configurations.
1423
package struct GDBHostCommandDecoder: ByteToMessageDecoder {
15-
enum Error: Swift.Error {
24+
/// Errors that can be thrown during host command decoding.
25+
package enum Error: Swift.Error {
26+
/// Expected `+` acknowledgement character to be included in the packet, when
27+
/// ``GDBHostCommandDecoder/isNoAckModeActive`` is set to `false`.
1628
case expectedAck
29+
30+
/// Expected command to start with `$` character`.
1731
case expectedCommandStart
18-
case unknownCommandKind(String)
32+
33+
/// Expected checksum to be included with the packet was not found.
1934
case expectedChecksum
35+
36+
/// Expected checksum included with the packet did not match the expected value.
2037
case checksumIncorrect(expectedChecksum: Int, receivedChecksum: UInt8)
38+
39+
/// Unexpected arguments value supplied for a given command.
40+
case unexpectedArgumentsValue
41+
42+
/// Host command kind could not be parsed. See `GDBHostCommand.Kind` for the
43+
/// list of supported commands.
44+
case unknownCommand(kind: String, arguments: String)
2145
}
2246

47+
/// Type of the output value produced by this decoder.
2348
package typealias InboundOut = GDBPacket<GDBHostCommand>
2449

2550
private var accumulatedDelimiter: UInt8?
2651

2752
private var accummulatedKind = [UInt8]()
2853
private var accummulatedArguments = [UInt8]()
29-
54+
55+
/// Logger instance used by this decoder.
3056
private let logger: Logger
31-
57+
58+
/// Initializes a new decoder.
59+
/// - Parameter logger: logger instance that consumes messages from the newly
60+
/// initialized decoder.
3261
package init(logger: Logger) { self.logger = logger }
33-
62+
63+
/// Sum of the raw character values consumed in the current command so far,
64+
/// used in checksum computation.
3465
private var accummulatedSum = 0
66+
67+
/// Computed checksum for the values consumed in the current command so far.
3568
package var accummulatedChecksum: UInt8 {
3669
UInt8(self.accummulatedSum % 256)
3770
}
3871

3972
private var isNoAckModeRequested = false
4073
private var isNoAckModeActive = false
4174

42-
mutating package func decode(buffer: inout ByteBuffer) throws -> GDBPacket<GDBHostCommand>? {
75+
package mutating func decode(
76+
buffer: inout ByteBuffer
77+
) throws(Error) -> GDBPacket<GDBHostCommand>? {
4378
guard var startDelimiter = self.accumulatedDelimiter ?? buffer.readInteger(as: UInt8.self) else {
4479
// Not enough data to parse.
4580
return nil
4681
}
4782

48-
if !isNoAckModeActive {
83+
if !self.isNoAckModeActive {
4984
let firstStartDelimiter = startDelimiter
5085

5186
guard firstStartDelimiter == UInt8(ascii: "+") else {
5287
logger.error("unexpected ack character: \(Character(UnicodeScalar(startDelimiter)))")
5388
throw Error.expectedAck
5489
}
5590

56-
if isNoAckModeRequested {
91+
if self.isNoAckModeRequested {
5792
self.isNoAckModeActive = true
5893
}
5994

@@ -70,7 +105,7 @@ package struct GDBHostCommandDecoder: ByteToMessageDecoder {
70105

71106
// Command start delimiters.
72107
guard startDelimiter == UInt8(ascii: "$") else {
73-
logger.error("unexpected delimiter: \(Character(UnicodeScalar(startDelimiter)))")
108+
self.logger.error("unexpected delimiter: \(Character(UnicodeScalar(startDelimiter)))")
74109
throw Error.expectedCommandStart
75110
}
76111

@@ -139,7 +174,7 @@ package struct GDBHostCommandDecoder: ByteToMessageDecoder {
139174
mutating package func decode(
140175
context: ChannelHandlerContext,
141176
buffer: inout ByteBuffer
142-
) throws -> DecodingState {
177+
) throws(Error) -> DecodingState {
143178
logger.trace(.init(stringLiteral: buffer.peekString(length: buffer.readableBytes)!))
144179

145180
guard let command = try self.decode(buffer: &buffer) else {

Sources/GDBRemoteProtocol/GDBPacket.swift

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,20 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2025 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
/// GDB host commands and target responses are wrapped with delimiters followed
14+
/// by a single byte checksum value. This type denotes such a packet by attaching
15+
/// a checksum value to the contained payload.
16+
/// See GDB remote protocol overview for more details:
17+
/// https://sourceware.org/gdb/current/onlinedocs/gdb.html/Overview.html#Overview
118
package struct GDBPacket<Payload: Sendable>: Sendable {
219
package let payload: Payload
320
package let checksum: UInt8

0 commit comments

Comments
 (0)