Skip to content

Commit

Permalink
feat(storage): Use Memory<byte> in buffer instead of byte[]
Browse files Browse the repository at this point in the history
  • Loading branch information
dr1rrb committed Oct 9, 2020
1 parent 9f49f07 commit 1080144
Show file tree
Hide file tree
Showing 17 changed files with 138 additions and 107 deletions.
5 changes: 3 additions & 2 deletions src/Uno.UI/UI/Xaml/Media/Imaging/WriteableBitmap.skia.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,10 @@ private protected override bool TryOpenSourceSync(int? targetWidth, int? targetH
{
_surface ??= new SkiaCompositionSurface();

_surface.SetPixels(PixelWidth, PixelHeight, _buffer.Data);
_surface.SetPixels(PixelWidth, PixelHeight, _buffer.ToArray());

image = new ImageData {
image = new ImageData
{
Value = _surface
};

Expand Down
4 changes: 2 additions & 2 deletions src/Uno.UWP/Devices/Midi/MidiChannelPressureMessage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,12 @@ internal MidiChannelPressureMessage(byte[] rawData, TimeSpan timestamp)
/// <summary>
/// Gets the channel from 0-15 that this message applies to.
/// </summary>
public byte Channel => MidiHelpers.GetChannel(_buffer.Data[0]);
public byte Channel => MidiHelpers.GetChannel(_buffer.GetByte(0));

/// <summary>
/// Gets the pressure from 0-127.
/// </summary>
public byte Pressure => _buffer.Data[1];
public byte Pressure => _buffer.GetByte(0);

/// <summary>
/// Gets the array of bytes associated with the MIDI message, including status byte.
Expand Down
6 changes: 3 additions & 3 deletions src/Uno.UWP/Devices/Midi/MidiControlChangeMessage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,17 +51,17 @@ internal MidiControlChangeMessage(byte[] rawData, TimeSpan timestamp)
/// <summary>
/// Gets the channel from 0-15 that this message applies to.
/// </summary>
public byte Channel => MidiHelpers.GetChannel(_buffer.Data[0]);
public byte Channel => MidiHelpers.GetChannel(_buffer.GetByte(0));

/// <summary>
/// Gets the value from 0-127 to apply to the controller.
/// </summary>
public byte ControlValue => _buffer.Data[2];
public byte ControlValue => _buffer.GetByte(2);

/// <summary>
/// Gets controller from 0-127 to receive this message.
/// </summary>
public byte Controller => _buffer.Data[1];
public byte Controller => _buffer.GetByte(1);

/// <summary>
/// Gets the array of bytes associated with the MIDI message, including status byte.
Expand Down
6 changes: 3 additions & 3 deletions src/Uno.UWP/Devices/Midi/MidiNoteOffMessage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,17 +50,17 @@ internal MidiNoteOffMessage(byte[] rawData, TimeSpan timestamp)
/// <summary>
/// Gets the channel from 0-15 that this message applies to.
/// </summary>
public byte Channel => MidiHelpers.GetChannel(_buffer.Data[0]);
public byte Channel => MidiHelpers.GetChannel(_buffer.GetByte(0));

/// <summary>
/// Gets the note to turn off which is specified as a value from 0-127.
/// </summary>
public byte Note => _buffer.Data[1];
public byte Note => _buffer.GetByte(1);

/// <summary>
/// Gets the value of the velocity from 0-127.
/// </summary>
public byte Velocity => _buffer.Data[2];
public byte Velocity => _buffer.GetByte(2);

/// <summary>
/// Gets the array of bytes associated with the MIDI message, including status byte.
Expand Down
6 changes: 3 additions & 3 deletions src/Uno.UWP/Devices/Midi/MidiNoteOnMessage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,17 +50,17 @@ internal MidiNoteOnMessage(byte[] rawData, TimeSpan timestamp)
/// <summary>
/// Gets the channel from 0-15 that this message applies to.
/// </summary>
public byte Channel => MidiHelpers.GetChannel(_buffer.Data[0]);
public byte Channel => MidiHelpers.GetChannel(_buffer.GetByte(0));

/// <summary>
/// Gets the note to turn off which is specified as a value from 0-127.
/// </summary>
public byte Note => _buffer.Data[1];
public byte Note => _buffer.GetByte(1);

/// <summary>
/// Gets the value of the velocity from 0-127.
/// </summary>
public byte Velocity => _buffer.Data[2];
public byte Velocity => _buffer.GetByte(2);

/// <summary>
/// Gets the array of bytes associated with the MIDI message, including status byte.
Expand Down
4 changes: 2 additions & 2 deletions src/Uno.UWP/Devices/Midi/MidiPitchBendChangeMessage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,12 @@ internal MidiPitchBendChangeMessage(byte[] rawData, TimeSpan timestamp)
/// <summary>
/// Gets the channel from 0-15 that this message applies to.
/// </summary>
public byte Channel => MidiHelpers.GetChannel(_buffer.Data[0]);
public byte Channel => MidiHelpers.GetChannel(_buffer.GetByte(0));

/// <summary>
/// Gets the pitch bend value which is specified as a 14-bit value from 0-16383.
/// </summary>
public ushort Bend => MidiHelpers.GetBend(_buffer.Data[1], _buffer.Data[2]);
public ushort Bend => MidiHelpers.GetBend(_buffer.GetByte(1), _buffer.GetByte(2));

/// <summary>
/// Gets the array of bytes associated with the MIDI message, including status byte.
Expand Down
6 changes: 3 additions & 3 deletions src/Uno.UWP/Devices/Midi/MidiPolyphonicKeyPressureMessage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,17 +51,17 @@ internal MidiPolyphonicKeyPressureMessage(byte[] rawData, TimeSpan timestamp)
/// <summary>
/// Gets the channel from 0-15 that this message applies to.
/// </summary>
public byte Channel => MidiHelpers.GetChannel(_buffer.Data[0]);
public byte Channel => MidiHelpers.GetChannel(_buffer.GetByte(0));

/// <summary>
/// Gets the note which is specified as a value from 0-127.
/// </summary>
public byte Note => _buffer.Data[1];
public byte Note => _buffer.GetByte(1);

/// <summary>
/// Gets the polyphonic key pressure which is specified as a value from 0-127.
/// </summary>
public byte Pressure => _buffer.Data[2];
public byte Pressure => _buffer.GetByte(2);

/// <summary>
/// Gets the array of bytes associated with the MIDI message, including status byte.
Expand Down
4 changes: 2 additions & 2 deletions src/Uno.UWP/Devices/Midi/MidiProgramChangeMessage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,12 @@ internal MidiProgramChangeMessage(byte[] rawData, TimeSpan timestamp)
/// <summary>
/// Gets the channel from 0-15 that this message applies to.
/// </summary>
public byte Channel => MidiHelpers.GetChannel(_buffer.Data[0]);
public byte Channel => MidiHelpers.GetChannel(_buffer.GetByte(0));

/// <summary>
/// Gets the program to change from 0-127.
/// </summary>
public byte Program => _buffer.Data[1];
public byte Program => _buffer.GetByte(1);

/// <summary>
/// Gets the array of bytes associated with the MIDI message, including status byte.
Expand Down
2 changes: 1 addition & 1 deletion src/Uno.UWP/Devices/Midi/MidiSongPositionPointerMessage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ internal MidiSongPositionPointerMessage(byte[] rawData, TimeSpan timestamp)
/// <summary>
/// Gets the song position pointer encoded in a 14-bit value from 0-16383.
/// </summary>
public ushort Beats => MidiHelpers.GetBeats(_buffer.Data[1], _buffer.Data[2]);
public ushort Beats => MidiHelpers.GetBeats(_buffer.GetByte(1), _buffer.GetByte(2));

/// <summary>
/// Gets the array of bytes associated with the MIDI message, including status byte.
Expand Down
2 changes: 1 addition & 1 deletion src/Uno.UWP/Devices/Midi/MidiSongSelectMessage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ internal MidiSongSelectMessage(byte[] rawData, TimeSpan timestamp)
/// <summary>
/// Gets the song to select from 0-127.
/// </summary>
public byte Song => _buffer.Data[1];
public byte Song => _buffer.GetByte(1);

/// <summary>
/// Gets the duration from when the MidiInPort was created to the time the message was received.
Expand Down
2 changes: 1 addition & 1 deletion src/Uno.UWP/Devices/Midi/MidiSystemExclusiveMessage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public MidiSystemExclusiveMessage(IBuffer rawData)
}

if (rawData is Storage.Streams.Buffer inMemory &&
inMemory.Data[0] == (byte)MidiMessageType.EndSystemExclusive)
inMemory.GetByte(0) == (byte)MidiMessageType.EndSystemExclusive)
{
Type = MidiMessageType.EndSystemExclusive;
}
Expand Down
4 changes: 2 additions & 2 deletions src/Uno.UWP/Devices/Midi/MidiTimeCodeMessage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,12 @@ internal MidiTimeCodeMessage(byte[] rawData, TimeSpan timestamp)
/// <summary>
/// Gets the value of the frame type from 0-7.
/// </summary>
public byte FrameType => MidiHelpers.GetFrame(_buffer.Data[1]);
public byte FrameType => MidiHelpers.GetFrame(_buffer.GetByte(1));

/// <summary>
/// Gets the time code value from 0-15.
/// </summary>
public byte Values => MidiHelpers.GetFrameValues(_buffer.Data[1]);
public byte Values => MidiHelpers.GetFrameValues(_buffer.GetByte(1));

/// <summary>
/// Gets the array of bytes associated with the MIDI message, including status byte.
Expand Down
12 changes: 4 additions & 8 deletions src/Uno.UWP/Storage/FileIO.cs
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ public static IAsyncAction AppendLinesAsync(IStorageFile file, IEnumerable<strin
/// <param name="buffer">The array of bytes to write.</param>
/// <returns>No object or value is returned when this method completes.</returns>
public static IAsyncAction WriteBytesAsync(IStorageFile file, byte[] buffer) =>
WriteBytesTaskAsync(file, buffer).AsAsyncAction();
WriteBytesTaskAsync(file, buffer, 0, buffer.Length).AsAsyncAction();

/// <summary>
/// Reads the contents of the specified file and returns a buffer.
Expand Down Expand Up @@ -249,7 +249,7 @@ private static async Task WriteTextTaskAsync(IStorageFile file, string contents,
await streamWriter.WriteAsync(contents);
}

private static async Task WriteBytesTaskAsync(IStorageFile file, byte[] buffer)
private static async Task WriteBytesTaskAsync(IStorageFile file, byte[] buffer, int index, int count)
{
if (file is null)
{
Expand All @@ -269,12 +269,8 @@ private static async Task<IBuffer> ReadBufferTaskAsync(IStorageFile file)

private static async Task WriteBufferTaskAsync(IStorageFile file, IBuffer buffer)
{
if (!(buffer is UwpBuffer inMemoryBuffer))
{
throw new NotSupportedException("The current implementation can only write a UwpBuffer");
}

await WriteBytesTaskAsync(file, inMemoryBuffer.Data);
var data = UwpBuffer.Cast(buffer).GetSegment();
await WriteBytesTaskAsync(file, data.Array!, data.Offset, data.Count);
}

private static async Task<Encoding> GetEncodingFromFileAsync(IStorageFile file)
Expand Down
77 changes: 70 additions & 7 deletions src/Uno.UWP/Storage/Streams/Buffer.cs
Original file line number Diff line number Diff line change
@@ -1,27 +1,90 @@
using System;
using System.Runtime.InteropServices;
using Windows.Foundation;

namespace Windows.Storage.Streams
{
public partial class Buffer : IBuffer
{
private readonly Memory<byte> _data;

internal static Buffer Cast(IBuffer impl)
{
if (impl is Buffer buffer)
{
return buffer;
}
else
{
throw new NotSupportedException("This type of buffer is not supported.");
}
}

public Buffer(uint capacity)
{
Data = new byte[capacity];
_data = new Memory<byte>(new byte[capacity]);
}

internal Buffer(byte[] data)
{
Data = data;
_data = new Memory<byte>(data);
Length = Capacity;
}

internal byte[] Data { get; }
internal Buffer(Memory<byte> data)
{
_data = data;
Length = (uint)data.Length;
}

public uint Capacity => (uint)Data.Length;
internal Span<byte> Span => _data.Span;

public uint Length
internal byte GetByte(int index)
{
get => (uint)Data.Length;
set => throw new NotSupportedException();
return _data.Span[index];
}

/// <summary>
/// Retrieve the underlying data array
/// </summary>
internal ArraySegment<byte> GetSegment()
{
if (MemoryMarshal.TryGetArray<byte>(_data, out var array))
{
return array;
}
else
{
throw new InvalidOperationException("Cannot get the segment from buffer.");
}
}

/// <summary>
/// **CLONES** the content of this buffer into a new byte[]
/// </summary>
internal byte[] ToArray()
{
return _data.ToArray();
}

/// <summary>
/// **CLONES** a part of the content of this buffer into a new byte[]
/// </summary>
internal byte[] ToArray(int start, int count)
{
return _data.Slice(start, count).ToArray();
}

internal void CopyTo(int index, byte[] destination, int destinationIndex, int count)
{
var src = _data.Slice(index, count);
var dst = new Memory<byte>(destination, destinationIndex, count);

src.CopyTo(dst);
}

public uint Capacity => (uint)_data.Length;

public uint Length { get; set; }
}
}
36 changes: 8 additions & 28 deletions src/Uno.UWP/Storage/Streams/DataReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ namespace Windows.Storage.Streams
public sealed partial class DataReader : IDataReader, IDisposable
{
private readonly static ArrayPool<byte> _pool = ArrayPool<byte>.Create();
private readonly IBuffer _buffer;
private readonly Buffer _buffer;

private int _bufferPosition = 0;

private DataReader(IBuffer buffer)
{
_buffer = buffer ?? throw new ArgumentNullException(nameof(buffer));
_buffer = Buffer.Cast(buffer ?? throw new ArgumentNullException(nameof(buffer)));
}

/// <summary>
Expand Down Expand Up @@ -247,22 +247,19 @@ public string ReadString(uint codeUnitCount)
int length = (int)codeUnitCount;
VerifyRead(length);

if (!(_buffer is Buffer buffer))
{
throw new NotSupportedException("This type of buffer is not supported.");
}
var data = _buffer.GetSegment();

string result;
switch (UnicodeEncoding)
{
case UnicodeEncoding.Utf8:
result = Encoding.UTF8.GetString(buffer.Data, _bufferPosition, length);
result = Encoding.UTF8.GetString(data.Array!, data.Offset + _bufferPosition, length);
break;
case UnicodeEncoding.Utf16LE:
result = Encoding.Unicode.GetString(buffer.Data, _bufferPosition, length * 2);
result = Encoding.Unicode.GetString(data.Array!, data.Offset + _bufferPosition, length * 2);
break;
case UnicodeEncoding.Utf16BE:
result = Encoding.BigEndianUnicode.GetString(buffer.Data, _bufferPosition, length * 2);
result = Encoding.BigEndianUnicode.GetString(data.Array!, data.Offset + _bufferPosition, length * 2);
break;
default:
throw new InvalidOperationException("Unsupported UnicodeEncoding value.");
Expand Down Expand Up @@ -301,29 +298,12 @@ private void VerifyRead(int count)

private byte ReadByteFromBuffer()
{
byte nextByte;
switch (_buffer)
{
case Buffer buffer:
nextByte = buffer.Data[_bufferPosition];
break;
default:
throw new NotSupportedException("This buffer is not supported");
}
_bufferPosition++;
return nextByte;
return _buffer.GetByte(_bufferPosition++);
}

private void ReadBytesFromBuffer(byte[] data, int length)
{
switch (_buffer)
{
case Buffer buffer:
Array.Copy(buffer.Data, _bufferPosition, data, 0, length);
break;
default:
throw new NotSupportedException("This buffer is not supported");
}
_buffer.CopyTo(_bufferPosition, data, 0, length);
_bufferPosition += length;
}

Expand Down
Loading

0 comments on commit 1080144

Please sign in to comment.