diff --git a/src/FSharpx.Collections/CircularBuffer.fs b/src/FSharpx.Collections/CircularBuffer.fs index ea44f8db..5359b20b 100644 --- a/src/FSharpx.Collections/CircularBuffer.fs +++ b/src/FSharpx.Collections/CircularBuffer.fs @@ -48,17 +48,31 @@ type CircularBuffer<'T>(bufferSize: int) = dequeued member this.Enqueue(value: _[], offset, count) = + if isNull value then + invalidArg "value" "value must not be null." + + if offset < 0 then + invalidArg "offset" "offset must not be negative." + + if count < 0 then + invalidArg "count" "count must not be negative." + + if offset + count > value.Length then + invalidArg "count" "offset and count exceed the length of the source array." + if count > bufferSize then invalidOp "Requested count is too large." let mutable offset = offset - head <- (head + 1) % bufferSize + let startPos = (head + 1) % bufferSize - for x, y in nextBuffer head count do + for x, y in nextBuffer startPos count do Array.blit value offset buffer x y offset <- offset + y + head <- (head + count) % bufferSize + if length = bufferSize then tail <- (tail + count) % bufferSize else diff --git a/tests/FSharpx.Collections.Tests/CircularBufferTests.fs b/tests/FSharpx.Collections.Tests/CircularBufferTests.fs index ae455d44..d371ddc7 100644 --- a/tests/FSharpx.Collections.Tests/CircularBufferTests.fs +++ b/tests/FSharpx.Collections.Tests/CircularBufferTests.fs @@ -84,7 +84,34 @@ module CircularBufferTests = Expect.throwsT "" f } - ptest "Printing after multiple enqueue circles" { + test "fail on negative offset" { + let f = + fun _ -> + let circularBuffer = CircularBuffer 5 + circularBuffer.Enqueue([| 1; 2; 3 |], -1, 2) + + Expect.throwsT "" f + } + + test "fail on negative count" { + let f = + fun _ -> + let circularBuffer = CircularBuffer 5 + circularBuffer.Enqueue([| 1; 2; 3 |], 0, -1) + + Expect.throwsT "" f + } + + test "fail when offset + count exceeds array length" { + let f = + fun _ -> + let circularBuffer = CircularBuffer 5 + circularBuffer.Enqueue([| 1; 2; 3 |], 2, 3) + + Expect.throwsT "" f + } + + test "Printing after multiple enqueue circles" { let circularBuffer = CircularBuffer 5 circularBuffer.Enqueue [| 1; 2; 3; 4; 5 |] @@ -96,7 +123,7 @@ module CircularBufferTests = - ptest "Printing from a queue 1..8 and dequeue 5, then enqueue 1..3 and dequeue 3, from array" { + test "Printing from a queue 1..8 and dequeue 5, then enqueue 1..3 and dequeue 3, from array" { let circularBuffer = CircularBuffer 5 circularBuffer.Enqueue([| 1; 2; 3; 4; 5 |]) @@ -106,7 +133,7 @@ module CircularBufferTests = Expect.equal "buffer" [| 1; 2; 3 |] <| circularBuffer.Dequeue 3 } - ptest "Consider a large array with various, incoming array segments" { + test "Consider a large array with various, incoming array segments" { let circularBuffer = CircularBuffer 5 let source =