MemoryPack icon indicating copy to clipboard operation
MemoryPack copied to clipboard

Source Generator didn't implement sufficient interfaces under certain circumstances

Open Delsin-Yu opened this issue 5 months ago • 0 comments

The following code won't compile; the error translates to:

Unimplmented interface member: 'void MemoryPack.IMemoryPackable<Data>.Deserialize(ref MemoryPackReader, scoped ref Data)'
using System.Buffers;
using System.Numerics;
using System.Runtime.InteropServices;
using MemoryPack;

internal class Program
{
    public static void Main(string[] args)
    {
        var writer = new MemoryPackWriter();

        writer.Write(new Data([1,2,3,4,5]));
        writer.Write(new Data([6,7,8,9,10]));
        writer.Write(new Data([11,12,13,14,15]));
        writer.Write(new Data([16,17,18,19,20]));

        var span = writer.AsSpan();

        var reader = new MemoryPackReader();
        reader.Reload(span);

        var deserialized1 = reader.Read<Data>();
        var deserialized2 = reader.Read<Data>();
        var deserialized3 = reader.Read<Data>();
        var deserialized4 = reader.Read<Data>();

        Console.WriteLine();
    }
}

[MemoryPackable]
partial record struct Data(byte[] Payload);

public class MemoryPackReader
{
    private readonly List<byte> _buffer = new(2048);
    private int _index;
    
    public void Reload(ReadOnlySpan<byte> span)
    {
        _buffer.Clear();
        _buffer.AddRange(span);
    }
    
    public T? Read<T>()
    {
        var span = CollectionsMarshal.AsSpan(_buffer)[_index..];
        T? value = default;
        var bytes = MemoryPackSerializer.Deserialize(span, ref value);
        _index += bytes;
        return value;
    }
}

public class MemoryPackWriter : IBufferWriter<byte>
{
    public void Write<T>(T value) => MemoryPackSerializer.Serialize(this, value);

    private byte[] _buffer = new byte[2048];
    private int _index;

    void IBufferWriter<byte>.Advance(int count)
    {
        if (_index + count > _buffer.Length)
            throw new InvalidOperationException("Cannot advance beyond the buffer size.");
        _index += count;
    }

    public Memory<byte> GetMemory(int sizeHint = 0)
    {
        Ensure(sizeHint);
        return _buffer.AsMemory(_index);
    }

    public Span<byte> GetSpan(int sizeHint = 0)
    {
        Ensure(sizeHint);
        return _buffer.AsSpan(_index);
    }

    private void Ensure(int sizeHint)
    {
        ArgumentOutOfRangeException.ThrowIfNegative(sizeHint);
        var available = _buffer.Length - _index;
        if (available >= sizeHint) return;
        var newSize = BitOperations.RoundUpToPowerOf2((uint)(_buffer.Length + sizeHint - available));
        Array.Resize(ref _buffer, (int)newSize);
    }
    
    public ReadOnlySpan<byte> AsSpan() => _buffer.AsSpan(0, _index);

    public void Clear()
    {
        Array.Clear(_buffer, 0, _index);
        _index = 0;
    }
}

Delsin-Yu avatar Sep 13 '25 13:09 Delsin-Yu