diff --git a/Sources/NIOCore/ByteBuffer-core.swift b/Sources/NIOCore/ByteBuffer-core.swift index b8317d0545..287d029544 100644 --- a/Sources/NIOCore/ByteBuffer-core.swift +++ b/Sources/NIOCore/ByteBuffer-core.swift @@ -832,12 +832,13 @@ public struct ByteBuffer { return true } - /// Reset capacity of the buffer to the specified amount. + /// Clamps the buffers capacity to either the maximum of the `desiredCapacity` or the buffer's `readableBytes`. /// - /// - returns: `true` if one or more bytes have been discarded, `false` if there are no bytes to discard. + /// - returns: A boolean indicating if the capacity of the buffer has changed. @inlinable - @discardableResult public mutating func clampBufferCapacity(to maxRetainedCapacity: Int) -> Bool { - guard maxRetainedCapacity >= readableBytes && maxRetainedCapacity < capacity else { + @discardableResult public mutating func clampBufferCapacity(to desiredCapacity: Int) -> Bool { + let maxRetainedCapacity = max(self.readableBytes, desiredCapacity) + guard maxRetainedCapacity < capacity else { return false } diff --git a/Tests/NIOCoreTests/ByteBufferTest.swift b/Tests/NIOCoreTests/ByteBufferTest.swift index cf2c64f71a..b926a5b720 100644 --- a/Tests/NIOCoreTests/ByteBufferTest.swift +++ b/Tests/NIOCoreTests/ByteBufferTest.swift @@ -1839,34 +1839,28 @@ class ByteBufferTest: XCTestCase { } func testRestoreBufferCapacity() { - let maxBufferCapacityToBeRetained = 1024 + let desiredCapacity = 1024 var buffer = self.allocator.buffer(capacity: 512) - - // For an item equal to the maximum specified buffer capacity it should not clamp buffer capacity + + // If readable capacity and desired capacity are less than or equal to buffer capacity, should not clamp buffer.clear() - buffer.writeString(String(repeating: "x", count: maxBufferCapacityToBeRetained)) - XCTAssertFalse(buffer.clampBufferCapacity(to: maxBufferCapacityToBeRetained)) - XCTAssertEqual(buffer.capacity, 1024) + buffer.writeString(String(repeating: "x", count: desiredCapacity)) + XCTAssertEqual(buffer.capacity, 1024) // Before + XCTAssertFalse(buffer.clampBufferCapacity(to: desiredCapacity)) + XCTAssertEqual(buffer.capacity, 1024) // After - // For an item with readable bytes above the maximum specified buffer capacity it should not clamp + // If readable capacity is greater less than to buffer capacity, should clamp to readable bytes buffer.clear() - buffer.writeString(String(repeating: "x", count: maxBufferCapacityToBeRetained + 1)) - XCTAssertFalse(buffer.clampBufferCapacity(to: maxBufferCapacityToBeRetained)) - XCTAssertEqual(buffer.capacity, 2048) + buffer.writeString(String(repeating: "x", count: desiredCapacity + 1)) + XCTAssertTrue(buffer.clampBufferCapacity(to: desiredCapacity)) + XCTAssertEqual(buffer.capacity, 1025) - // For a subsequent item smaller than buffer capacity it should clamp if the maximum specified buffer capacity is equal to, or less than readable bytes + // If desiredCapacity capacity is less than buffer capacity and larger than readable bytes, should clamp to desiredCapacity bytes buffer.clear() - buffer.writeString(String(repeating: "x", count: maxBufferCapacityToBeRetained)) - XCTAssertTrue(buffer.clampBufferCapacity(to: maxBufferCapacityToBeRetained)) + buffer.writeString(String(repeating: "x", count: 512)) + XCTAssertTrue(buffer.clampBufferCapacity(to: desiredCapacity)) XCTAssertEqual(buffer.capacity, 1024) - // For a small item smaller than maxBufferCapacityToBeRetained, it should not clamp further. - // This is to avoid flip-flopping between clamping and expansion during buffer lifecycle - buffer.clear() - buffer.writeString("Small item") - XCTAssertFalse(buffer.clampBufferCapacity(to: maxBufferCapacityToBeRetained)) - XCTAssertEqual(buffer.capacity, 1024) - // For any item, it should not clamp buffer capacity to a value larger than the current buffer capacity buffer.clear() buffer.writeString("Any item")