curiosity-ai / rocksdb-sharp

.net bindings for the rocksdb by facebook
BSD 2-Clause "Simplified" License
155 stars 38 forks source link

PinnableSlice support #21

Open devhawk opened 2 years ago

devhawk commented 2 years ago

Only for netstandard2.1 and up

Potential Implementation:

public sealed class PinnableSlice : IDisposable
{
    public IntPtr Handle { get; internal set; }

    public PinnableSlice(IntPtr handle)
    {
        Handle = handle;
    }

    public bool Valid => Handle != IntPtr.Zero;

    public ReadOnlySpan<byte> GetValue()
    {
        if (Handle == IntPtr.Zero) return default;
        var valuePtr = Native.Instance.rocksdb_pinnableslice_value(Handle, out var valueLength);
        if (valuePtr == IntPtr.Zero) return default;
        unsafe 
        {
            return new ReadOnlySpan<byte>((byte*)valuePtr, (int)valueLength);
        }
    }

    public void Dispose()
    {
        if (Handle != IntPtr.Zero)
        {
            var handle = Handle;
            Handle = IntPtr.Zero;
            Native.Instance.rocksdb_pinnableslice_destroy(handle);
        }
    }
}

// Added to RocksDb class

public static PinnableSlice GetSlice(this RocksDb db, byte[]? key, ReadOptions? readOptions = null)
    => db.GetSlice(key, null, readOptions);

public unsafe static PinnableSlice GetSlice(this RocksDb db, byte[]? key, ColumnFamilyHandle? columnFamily, ReadOptions? readOptions = null)
{
    key ??= Array.Empty<byte>();
    readOptions ??= DefaultReadOptions;

    fixed (byte* keyPtr = key)
    {
        var slice = columnFamily is null
            ? Instance.rocksdb_get_pinned(db.Handle, readOptions.Handle, (IntPtr)keyPtr, (UIntPtr)key.Length)
            : Instance.rocksdb_get_pinned_cf(db.Handle, readOptions.Handle, columnFamily.Handle, (IntPtr)keyPtr, (UIntPtr)key.Length);
        return new PinnableSlice(slice);
    }
}
devhawk commented 2 years ago

Note, key should probably be ReadOnlyMemory or ReadOnlySpan. And PinnableSlice should probably be a struct like MemoryHandle