PooledSegment<T> Class
An ISegmentOwner<T> that rents a buffer from ArrayPool<T>.Shared
and returns it automatically on dispose.
Namespace
CryptoHives.Foundation.Memory.Buffers
Inheritance
Object → PooledSegment<T>
Implements
ISegmentOwner<T>IDisposable
Syntax
public sealed class PooledSegment<T> : ISegmentOwner<T>
Overview
PooledSegment<T> is the right choice whenever you need a temporary, right-sized buffer
that should go back to the pool once work is done. It wraps the rented array in an
ArraySegment<T> so the actual rented length (which ArrayPool<T> may round up) is hidden
behind a clean Count == minimumLength view.
Implemented as a sealed class so the backing array can never be disposed more than once
by an unintended struct copy.
Factory Method
public static ISegmentOwner<T> Rent(int minimumLength, bool clearArray = false)
Rents a buffer with at least minimumLength elements from ArrayPool<T>.Shared and
returns it wrapped in an PooledSegment<T>.
| Parameter | Description |
|---|---|
minimumLength |
The minimum number of elements required |
clearArray |
Whether to zero the buffer as it returns to the pool. Defaults to false. |
Returns — An owner whose Segment.Count equals minimumLength.
Holding secrets
A rented buffer arrives holding whatever the previous tenant left in it, and by default goes back the
same way. Pass clearArray: true for key material or anything else that should not be legible to the
next renter:
using ISegmentOwner<byte> key = PooledSegment<byte>.Rent(32, clearArray: true);
DeriveKey(key.Segment.AsSpan());
Sign(payload, key.Segment.AsSpan());
// the buffer is zeroed on the way back to the pool
Two things it does not do. It says nothing about the window in which the data was live, or about copies taken elsewhere — it only stops the next renter reading it. And it is not free: disposal costs a pass over the buffer, proportional to its length.
The whole array is zeroed, not just the current segment window, so narrowing the view with
TrySetSegment cannot leave part of it legible.
Properties
| Property | Type | Description |
|---|---|---|
Segment |
ArraySegment<T> |
Current segment view (offset and length track TrySetSegment calls) |
Methods
| Method | Description |
|---|---|
bool TrySetSegment(int offset, int length) |
Repositions the segment view; returns false if offset + length > array.Length |
void Dispose() |
Returns the rented array to ArrayPool<T>.Shared and resets Segment to default |
Usage Examples
Basic Rent and Use
using CryptoHives.Foundation.Memory.Buffers;
using ISegmentOwner<byte> segment = PooledSegment<byte>.Rent(1024);
Span<byte> buffer = segment.Segment.AsSpan();
int written = encoder.GetBytes(text, buffer);
// Use only the filled portion
ProcessData(buffer[..written]);
// Rented array is returned to the pool when segment is disposed
Narrowing the View with TrySetSegment
using ISegmentOwner<byte> segment = PooledSegment<byte>.Rent(256);
// Skip a 4-byte header and work on 64 data bytes
if (segment.TrySetSegment(offset: 4, length: 64))
{
Span<byte> data = segment.Segment.AsSpan();
FillData(data);
}
Indexed Access
using ISegmentOwner<byte> segment = PooledSegment<byte>.Rent(4);
segment[0] = 0x01;
segment[1] = 0x02;
segment[2] = 0x03;
segment[3] = 0x04;
Remarks
- The backing array rented from
ArrayPool<T>.Sharedmay be larger thanminimumLength;Segment.Countalways reflects the requested length. DEBUGbuilds clear every returned array whateverclearArraysays, turning a use-after-return into obvious zeroes rather than plausible stale data. That is a diagnostic, not a security control — never conclude from debug behaviour that a release build wipes anything. TheclearArrayflag itself is honoured in every configuration.- Calling
Disposemore than once is safe; subsequent calls are no-ops. - After
Dispose,Segment.Arrayisnull.
See Also
© 2026 The Keepers of the CryptoHives