Perf. opt.

This commit is contained in:
Christian Köllner 2020-02-17 21:23:44 +01:00
parent 37d642c249
commit 686dfeba52
2 changed files with 40 additions and 21 deletions

View File

@ -7,7 +7,7 @@ using System.Text;
namespace Capnp
{
/// <summary>
/// ListDeserializer specialization for List(Int*), List(UInt*), List(Float*), and List(Enum).
/// ListDeserializer specialization for unmanaged primitive types (including enum).
/// </summary>
/// <typeparam name="T">List element type</typeparam>
public class ListOfPrimitivesDeserializer<T>: ListDeserializer, IReadOnlyList<T>
@ -84,7 +84,10 @@ namespace Capnp
/// </summary>
public override ListKind Kind => _kind;
ReadOnlySpan<T> Data => MemoryMarshal.Cast<ulong, T>(State.CurrentSegment.Slice(State.Offset)).Slice(0, Count);
/// <summary>
/// Retrieves the underlying memory span of this object
/// </summary>
public ReadOnlySpan<T> Span => MemoryMarshal.Cast<ulong, T>(State.CurrentSegment.Slice(State.Offset)).Slice(0, Count);
/// <summary>
/// Returns the element at given index.
@ -92,7 +95,7 @@ namespace Capnp
/// <param name="index">Element index</param>
/// <returns>Element value</returns>
/// <exception cref="IndexOutOfRangeException"><paramref name="index"/> is out of range.</exception>
public T this[int index] => Data[index];
public T this[int index] => Span[index];
ListOfPrimitivesDeserializer<U> PrimitiveCast<U>() where U: unmanaged
{
@ -202,7 +205,7 @@ namespace Capnp
/// <exception cref="NotSupportedException">Element size is different from 1 byte.</exception>
public override string CastText()
{
var utf8Bytes = PrimitiveCast<byte>().Data;
var utf8Bytes = PrimitiveCast<byte>().Span;
if (utf8Bytes.Length == 0) return string.Empty;
var utf8GytesNoZterm = utf8Bytes.Slice(0, utf8Bytes.Length - 1);
return Encoding.UTF8.GetString(utf8GytesNoZterm.ToArray());

View File

@ -6,13 +6,13 @@ using System.Runtime.InteropServices;
namespace Capnp
{
/// <summary>
/// SerializerState specialization for List(Int*), List(UInt*), List(Float*), and List(Enum).
/// SerializerState specialization for unmanaged primitive types (including enum).
/// </summary>
/// <typeparam name="T">List element type, must be primitive. Static constructor will throw if the type does not work.</typeparam>
public class ListOfPrimitivesSerializer<T> :
SerializerState,
IReadOnlyList<T>
where T : struct
where T : unmanaged
{
static readonly int ElementSize;
@ -28,7 +28,10 @@ namespace Capnp
}
}
Span<T> Data => MemoryMarshal.Cast<ulong, T>(RawData);
/// <summary>
/// Retrieves the underlying memory span of the represented items.
/// </summary>
public Span<T> Span => MemoryMarshal.Cast<ulong, T>(RawData);
/// <summary>
/// Gets or sets the value at given index.
@ -37,8 +40,8 @@ namespace Capnp
/// <returns>Element value</returns>
public T this[int index]
{
get => Data[index];
set => Data[index] = value;
get => Span[index];
set => Span[index] = value;
}
/// <summary>
@ -78,25 +81,38 @@ namespace Capnp
Init(items.Count);
if (items is T[] array)
switch (items)
{
array.CopyTo(Data);
}
else
{
for (int i = 0; i < items.Count; i++)
{
this[i] = items[i];
}
case T[] array:
array.CopyTo(Span);
break;
case ArraySegment<T> segment:
segment.AsSpan().CopyTo(Span);
break;
case ListOfPrimitivesDeserializer<T> deser:
deser.Span.CopyTo(Span);
break;
case ListOfPrimitivesSerializer<T> ser:
ser.Span.CopyTo(Span);
break;
default:
for (int i = 0; i < items.Count; i++)
{
this[i] = items[i];
}
break;
}
}
/// <summary>
/// Implements <see cref="IEnumerable{T}"/>.
/// </summary>
/// <returns></returns>
public IEnumerator<T> GetEnumerator() => (IEnumerator<T>)Data.ToArray().GetEnumerator();
public IEnumerator<T> GetEnumerator() => (IEnumerator<T>)Span.ToArray().GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => Data.ToArray().GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => Span.ToArray().GetEnumerator();
}
}