@@ -14,58 +14,93 @@ import Logging
1414import NIOCore
1515
1616extension ByteBuffer {
17+ /// Returns `true` if byte to be read immediately is a GDB RP checksum
18+ /// delimiter. Returns `false` otherwise.
1719 var isChecksumDelimiterAtReader : Bool {
1820 self . peekInteger ( as: UInt8 . self) == UInt8 ( ascii: " # " )
1921 }
2022
23+ /// Returns `true` if byte to be read immediately is a GDB RP command arguments
24+ /// delimiter. Returns `false` otherwise.
2125 var isArgumentsDelimiterAtReader : Bool {
2226 self . peekInteger ( as: UInt8 . self) == UInt8 ( ascii: " : " )
2327 }
2428}
2529
30+ /// Decoder of GDB RP host commands, that takes raw `ByteBuffer` as an input encoded
31+ /// per https://sourceware.org/gdb/current/onlinedocs/gdb.html/Overview.html#Overview
32+ /// and produces a `GDBPacket<GDBHostCommand>` value as output. This decoder is
33+ /// compatible with NIO channel pipelines, making it easy to integrate with different
34+ /// I/O configurations.
2635package struct GDBHostCommandDecoder : ByteToMessageDecoder {
27- enum Error : Swift . Error {
36+ /// Errors that can be thrown during host command decoding.
37+ package enum Error : Swift . Error {
38+ /// Expected `+` acknowledgement character to be included in the packet, when
39+ /// ``GDBHostCommandDecoder/isNoAckModeActive`` is set to `false`.
2840 case expectedAck
41+
42+ /// Expected command to start with `$` character`.
2943 case expectedCommandStart
30- case unknownCommandKind( String )
44+
45+ /// Expected checksum to be included with the packet was not found.
3146 case expectedChecksum
47+
48+ /// Expected checksum included with the packet did not match the expected value.
3249 case checksumIncorrect( expectedChecksum: Int , receivedChecksum: UInt8 )
50+
51+ /// Unexpected arguments value supplied for a given command.
52+ case unexpectedArgumentsValue
53+
54+ /// Host command kind could not be parsed. See `GDBHostCommand.Kind` for the
55+ /// list of supported commands.
56+ case unknownCommand( kind: String , arguments: String )
3357 }
3458
59+ /// Type of the output value produced by this decoder.
3560 package typealias InboundOut = GDBPacket < GDBHostCommand >
3661
3762 private var accumulatedDelimiter : UInt8 ?
3863
3964 private var accummulatedKind = [ UInt8] ( )
4065 private var accummulatedArguments = [ UInt8] ( )
41-
66+
67+ /// Logger instance used by this decoder.
4268 private let logger : Logger
43-
69+
70+ /// Initializes a new decoder.
71+ /// - Parameter logger: logger instance that consumes messages from the newly
72+ /// initialized decoder.
4473 package init ( logger: Logger ) { self . logger = logger }
45-
74+
75+ /// Sum of the raw character values consumed in the current command so far,
76+ /// used in checksum computation.
4677 private var accummulatedSum = 0
78+
79+ /// Computed checksum for the values consumed in the current command so far.
4780 package var accummulatedChecksum : UInt8 {
4881 UInt8 ( self . accummulatedSum % 256 )
4982 }
5083
5184 private var isNoAckModeRequested = false
5285 private var isNoAckModeActive = false
5386
54- mutating package func decode( buffer: inout ByteBuffer ) throws -> GDBPacket < GDBHostCommand > ? {
87+ package mutating func decode(
88+ buffer: inout ByteBuffer
89+ ) throws ( Error) -> GDBPacket < GDBHostCommand > ? {
5590 guard var startDelimiter = self . accumulatedDelimiter ?? buffer. readInteger ( as: UInt8 . self) else {
5691 // Not enough data to parse.
5792 return nil
5893 }
5994
60- if !isNoAckModeActive {
95+ if !self . isNoAckModeActive {
6196 let firstStartDelimiter = startDelimiter
6297
6398 guard firstStartDelimiter == UInt8 ( ascii: " + " ) else {
6499 logger. error ( " unexpected ack character: \( Character ( UnicodeScalar ( startDelimiter) ) ) " )
65100 throw Error . expectedAck
66101 }
67102
68- if isNoAckModeRequested {
103+ if self . isNoAckModeRequested {
69104 self . isNoAckModeActive = true
70105 }
71106
@@ -82,7 +117,7 @@ package struct GDBHostCommandDecoder: ByteToMessageDecoder {
82117
83118 // Command start delimiters.
84119 guard startDelimiter == UInt8 ( ascii: " $ " ) else {
85- logger. error ( " unexpected delimiter: \( Character ( UnicodeScalar ( startDelimiter) ) ) " )
120+ self . logger. error ( " unexpected delimiter: \( Character ( UnicodeScalar ( startDelimiter) ) ) " )
86121 throw Error . expectedCommandStart
87122 }
88123
@@ -151,7 +186,7 @@ package struct GDBHostCommandDecoder: ByteToMessageDecoder {
151186 mutating package func decode(
152187 context: ChannelHandlerContext ,
153188 buffer: inout ByteBuffer
154- ) throws -> DecodingState {
189+ ) throws ( Error ) -> DecodingState {
155190 logger. trace ( . init( stringLiteral: buffer. peekString ( length: buffer. readableBytes) !) )
156191
157192 guard let command = try self . decode ( buffer: & buffer) else {
0 commit comments