dotnet icon indicating copy to clipboard operation
dotnet copied to clipboard

SpanBuilder

Open SupinePandora43 opened this issue 3 years ago • 5 comments

Overview

A StringBuilder-like api, but for spans.

API breakdown

public ref struct SpanBuilder<T>
{
    Span<T> span;
    int length;

    public SpanBuilder(Span<T> storage) { span = storage; }
    public SpanBuilder(int capacity) { span = new T[capacity]; }

    public void Add(in T @value)
    {
        EnsureCapacity(length + 1);
        span[length++] = @value;
    }
    public EnsureCapacity(int capacity)
    {
        if(span.Length >= capacity) return;
        Span<T> newSpan = new T[Math.Pow(2, BitOperations.LeadingZeroCount(checked((uint)capacity)))];
        span.Slice(0, length).CopyTo(newSpan);
        span = newSpan;
    }
    public Span<T> Build(){
        Span<T> built = span.Slice(0, length);
        span = default;
        length = default;
        return built;
    }
}

Usage example

// too big 😅

Breaking change?

No

Alternatives

List<T>

  • causes allocation by itself (isn't a value type)
  • doesn't support use of existing storage

StringBuilder

  • only for strings

ValueStringBuilder

  • is internal

Additional context

No response

Help us help you

Yes, I'd like to be assigned to work on this item

SupinePandora43 avatar Aug 07 '22 09:08 SupinePandora43

This is performed by the ArrayPoolBufferWriter<T>, is that not sufficient?

JorgeCandeias avatar Aug 07 '22 10:08 JorgeCandeias

This is performed by the ArrayPoolBufferWriter<T>, is that not sufficient?

It is not a value type and uses ArrayPool... Perhaps, you can prove me that I'm wrong about it?

SupinePandora43 avatar Aug 07 '22 11:08 SupinePandora43

I'm not sure I understand the use case scenario for this. The way I see it:

  • If you wanted a general writer, it'd make sense to use ArrayPoolBufferWriter<T>, so you can also reuse buffers.
  • If the ask is for a general writer type for a span, then I don't think the backing field should be an array at all. It should just be a writer type targeting a captured Span<T>. I agree that that would be useful, but then the proposed API surface is not nearly sufficient. There's a related proposal for this (and for a span reader) in the runtime as well, so it might make sense to coordinate with that. I'm not entirely sure this is something we should add to the Toolkit if the goal is to get that into .NET soon. For reference, see https://github.com/dotnet/runtime/issues/23601 and https://github.com/dotnet/runtime/issues/23616.
  • If you're creating a span and writing to it just to return it from a method, I'd argue it's the wrong design. If you're sole owner of an array you wrote data to, you wouldn't want to return it as a span, because it makes things much clunkier for callers. If you do own the array, just return that (optionally as an ReadOnlyMemory<T> or an ImmutableArray<T>). Otherwise you're just restricting callers for no real reason, since they'd be the sole owners of that data anyway.

Sergio0694 avatar Aug 07 '22 11:08 Sergio0694