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

Code before:
            return self!.writeBuffer(&buffer)
        }
    }
}

#if compiler(>=6)
extension ByteBuffer {
    /// Get the string at `index` from this `ByteBuffer` decoding using the UTF-8 encoding. Does not move the reader index.
    /// The selected bytes must be readable or else `nil` will be returned.
    ///
    /// This is an alternative to `ByteBuffer.getString(at:length:)` which ensures the returned string is valid UTF8
    ///
    /// - Parameters:
    ///   - index: The starting index into `ByteBuffer` containing the string of interest.
    ///   - length: The number of bytes making up the string.
    /// - Returns: A `String` value containing the UTF-8 decoded selected bytes from this `ByteBuffer` or `nil` if
    ///            the requested bytes are not readable.
    @inlinable
    @available(macOS 15, iOS 18, tvOS 18, watchOS 11, *)
    public func getUTF8ValidatedString(at index: Int, length: Int) -> String? {
        guard let range = self.rangeWithinReadableBytes(index: index, length: length) else {
            return nil
        }
        return self.withUnsafeReadableBytes { pointer in
            assert(range.lowerBound >= 0 && (range.upperBound - range.lowerBound) <= pointer.count)
            return String(validating: UnsafeRawBufferPointer(fastRebase: pointer[range]), as: Unicode.UTF8.self)
        }
    }

    /// Read `length` bytes off this `ByteBuffer`, decoding it as `String` using the UTF-8 encoding. Move the reader index
    /// forward by `length`.
    ///
    /// This is an alternative to `ByteBuffer.readString(length:)` which ensures the returned string is valid UTF8. If the
    /// string is not valid UTF8 then the reader index is not advanced.
    ///
    /// - Parameters:
    ///   - length: The number of bytes making up the string.
    /// - Returns: A `String` value deserialized from this `ByteBuffer` or `nil` if there aren't at least `length` bytes readable.
    @inlinable
    @available(macOS 15, iOS 18, tvOS 18, watchOS 11, *)
    public mutating func readUTF8ValidatedString(length: Int) -> String? {
        guard let result = self.getUTF8ValidatedString(at: self.readerIndex, length: length) else {
            return nil
        }
        self.moveReaderIndex(forwardBy: length)
        return result
    }
}
#endif  // compiler(>=6)


Review comment (bug):
This is probably not the spelling we want. Right now it's not possible to tell if this API call fails because there aren't enough readable bytes or because the string is not valid UTF8. We need to distinguish the two cases.

Code after:
            return self!.writeBuffer(&buffer)
        }
    }
}

#if compiler(>=6)
extension ByteBuffer {
    /// Get the string at `index` from this `ByteBuffer` decoding using the UTF-8 encoding. Does not move the reader index.
    /// The selected bytes must be readable or else `nil` will be returned.
    ///
    /// This is an alternative to `ByteBuffer.getString(at:length:)` which ensures the returned string is valid UTF8. If the
    /// string is not valid UTF8 then a `ReadUTF8ValidationError` error is thrown.
    ///
    /// - Parameters:
    ///   - index: The starting index into `ByteBuffer` containing the string of interest.
    ///   - length: The number of bytes making up the string.
    /// - Returns: A `String` value containing the UTF-8 decoded selected bytes from this `ByteBuffer` or `nil` if
    ///            the requested bytes are not readable.
    @inlinable
    @available(macOS 15, iOS 18, tvOS 18, watchOS 11, *)
    public func getUTF8ValidatedString(at index: Int, length: Int) throws -> String? {
        guard let slice = self.getSlice(at: index, length: length) else {
            return nil
        }
        guard
            let string = String(
                validating: slice.readableBytesView,
                as: Unicode.UTF8.self
            )
        else {
            throw ReadUTF8ValidationError.invalidUTF8
        }
        return string
    }

    /// Read `length` bytes off this `ByteBuffer`, decoding it as `String` using the UTF-8 encoding. Move the reader index
    /// forward by `length`.
    ///
    /// This is an alternative to `ByteBuffer.readString(length:)` which ensures the returned string is valid UTF8. If the
    /// string is not valid UTF8 then a `ReadUTF8ValidationError` error is thrown and the reader index is not advanced.
    ///
    /// - Parameters:
    ///   - length: The number of bytes making up the string.
    /// - Returns: A `String` value deserialized from this `ByteBuffer` or `nil` if there aren't at least `length` bytes readable.
    @inlinable
    @available(macOS 15, iOS 18, tvOS 18, watchOS 11, *)
    public mutating func readUTF8ValidatedString(length: Int) throws -> String? {
        guard let result = try self.getUTF8ValidatedString(at: self.readerIndex, length: length) else {
            return nil
        }
        self.moveReaderIndex(forwardBy: length)