Repository: apple/swift-nio
File: Sources/NIOCore/ByteBuffer-hexdump.swift (Swift)

Code before:
    func _hexDumpLines(offset: Int) -> String {
        var result = ""
        // Each hex dump line represents 16 bytes, and takes up to 79 characters including the \n in the end.
        // Plus the last line of the hex dump which is just 8 characters.
        result.reserveCapacity(self.readableBytes / 16 * 79 + 8)

        var buffer = self
        // We're going to move the lineOffset index forward, so copy it into a variable
        var lineOffset = offset

        while buffer.readableBytes > 0 {
            let slice = buffer.readSlice(length: min(16, buffer.readableBytes))!
            let lineLength = slice.readableBytes

            // Left column of the hex dump signifies the offset from the beginning of the dumped buffer
            // and is separated from the next column with two spaces.
            result += String(byte: lineOffset, padding: 8)
            result += "  "

            // Center column consists of:
            // - xxd-compatible dump of the first 8 bytes
            // - space
            // - xxd-compatible dump of the rest 8 bytes
            // If there are not enough bytes to dump, the column is padded with space.
            let left = slice.getSlice(at: 0, length: min( 8, slice.readableBytes ))!
            let right = slice.getSlice(at: 8, length: min( 8, slice.readableBytes - 8)) ?? ByteBuffer()
            let leftHex = left.hexDumpShort()
            let rightHex = right.hexDumpShort()

            result += leftHex
            result += String(repeating: " ", count: 25 - leftHex.count)
            result += rightHex
            result += String(repeating: " ", count: 25 - rightHex.count)

            // Right column renders the 16 bytes line as ASCII characters, or "." if the character is not printable.
            let printableBytes = slice.readableBytesView.map {
                let printableRange = UInt8(ascii: " ") ..< UInt8(ascii: "~")
                return printableRange.contains($0) ? $0 : UInt8(ascii: ".")
            }
            result += "|\(String(decoding: printableBytes, as: UTF8.self))|\n"

            lineOffset += lineLength
        }
        return result
    }

    /// Returns a `String` of hexadecimal digits of bytes in the Buffer,
    /// with formatting compatible with output of `hexdump -C`.
    func hexDumpLong() -> String {
        var result = self._hexDumpLines(offset: 0)
        result += String(byte: self.readableBytes, padding: 8)

Review comment (suggestion):
Rather than the games with indices, can I propose we do this?

```swift
let left = slice.readSlice(length: min(8, slice.readableBytes))!
let right = slice
```


Code after:
        return startHex + " ... " + endHex
    }

    /// Returns a `String` containing a detailed hex dump of this buffer.
    /// Intended to be used internally in ``hexDump(format:)``
    /// - parameters:
    ///     - lineOffset: an offset from the beginning of the outer buffer that is being dumped. It's used to print the line offset in hexdump -C format.
    ///     - paddingBefore: the amount of space to pad before the first byte dumped on this line, used in center and right columns.
    ///     - paddingAfter: the amount of sapce to pad after the last byte on this line, used in center and right columns.
    private func _hexDumpLine(lineOffset: Int, paddingBefore: Int = 0, paddingAfter: Int = 0) -> String {
        // Each line takes 78 visible characters + \n
        var result = ""
        result.reserveCapacity(79)

        // Left column of the hex dump signifies the offset from the beginning of the dumped buffer
        // and is separated from the next column with two spaces.
        result += String(lineOffset, radix: 16, padding: 8)
        result += "  "

        // Center column consists of:
        // - xxd-compatible dump of the first 8 bytes
        // - space
        // - xxd-compatible dump of the rest 8 bytes
        // If there are not enough bytes to dump, the column is padded with space.

        // If there's any padding on the left, apply that first.
        result += String(repeating: " ", count: paddingBefore * 3)

        // Add the left side of the central column
        let bytesInLeftColumn = max(8 - paddingBefore, 0)
        for byte in self.readableBytesView.prefix(bytesInLeftColumn) {
            result += String(byte, radix: 16, padding: 2)
            result += " "
        }

        // Add an extra space for the centre column.
        result += " "

        // Add the right side of the central column.
        for byte in self.readableBytesView.dropFirst(bytesInLeftColumn) {
            result += String(byte, radix: 16, padding: 2)
            result += " "
        }

        // Pad the resulting center column line to 60 characters.
        result += String(repeating: " ", count: 60 - result.count)

        // Right column renders the 16 bytes line as ASCII characters, or "." if the character is not printable.
        let printableRange = UInt8(ascii: " ") ..< UInt8(ascii: "~")
        let printableBytes = self.readableBytesView.map {
            printableRange.contains($0) ? $0 : UInt8(ascii: ".")