Rewrite MemoryStorage

This commit is contained in:
Alex Barney 2020-01-07 22:47:48 -07:00
parent 857bde67ee
commit b742a37012
4 changed files with 60 additions and 124 deletions

View file

@ -0,0 +1,57 @@
using System;
namespace LibHac.Fs
{
public class MemoryStorage : StorageBase
{
private byte[] StorageBuffer { get; }
public MemoryStorage(byte[] buffer)
{
StorageBuffer = buffer;
}
protected override Result ReadImpl(long offset, Span<byte> destination)
{
if (destination.Length == 0)
return Result.Success;
if (!IsRangeValid(offset, destination.Length, StorageBuffer.Length))
return ResultFs.ValueOutOfRange.Log();
StorageBuffer.AsSpan((int)offset, destination.Length).CopyTo(destination);
return Result.Success;
}
protected override Result WriteImpl(long offset, ReadOnlySpan<byte> source)
{
if (source.Length == 0)
return Result.Success;
if (!IsRangeValid(offset, source.Length, StorageBuffer.Length))
return ResultFs.ValueOutOfRange.Log();
source.CopyTo(StorageBuffer.AsSpan((int)offset));
return Result.Success;
}
protected override Result FlushImpl()
{
return Result.Success;
}
protected override Result SetSizeImpl(long size)
{
return ResultFs.UnsupportedOperationInMemoryStorageSetSize.Log();
}
protected override Result GetSizeImpl(out long size)
{
size = StorageBuffer.Length;
return Result.Success;
}
}
}

View file

@ -1,4 +1,5 @@
using System;
using System.Runtime.CompilerServices;
using System.Threading;
namespace LibHac.Fs
@ -77,6 +78,7 @@ namespace LibHac.Fs
protected virtual void Dispose(bool disposing) { }
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsRangeValid(long offset, long size, long totalSize)
{
return offset >= 0 && size >= 0 && size <= totalSize && offset <= totalSize - size;

View file

@ -1,118 +0,0 @@
using System;
using LibHac.Fs;
namespace LibHac.FsSystem
{
public class MemoryStorage : StorageBase
{
private byte[] _buffer;
private int _start;
private int _length;
private int _capacity;
private bool _isExpandable;
public MemoryStorage() : this(0) { }
public MemoryStorage(int capacity)
{
if (capacity < 0) throw new ArgumentOutOfRangeException(nameof(capacity), "Argument must be positive");
_capacity = capacity;
_isExpandable = true;
_buffer = new byte[capacity];
}
public MemoryStorage(byte[] buffer) : this(buffer, 0, buffer.Length) { }
public MemoryStorage(byte[] buffer, int index, int count)
{
if (buffer == null) throw new NullReferenceException(nameof(buffer));
if (index < 0) throw new ArgumentOutOfRangeException(nameof(index), "Value must be non-negative.");
if (count < 0) throw new ArgumentOutOfRangeException(nameof(count), "Value must be non-negative.");
if (buffer.Length - index < count) throw new ArgumentException("Length, index and count parameters are invalid.");
_buffer = buffer;
_start = index;
_length = count;
_capacity = count;
_isExpandable = false;
}
protected override Result ReadImpl(long offset, Span<byte> destination)
{
if (!IsRangeValid(offset, destination.Length, _length))
return ResultFs.ValueOutOfRange.Log();
_buffer.AsSpan((int)(_start + offset), destination.Length).CopyTo(destination);
return Result.Success;
}
protected override Result WriteImpl(long offset, ReadOnlySpan<byte> source)
{
if (!IsRangeValid(offset, source.Length, _length))
return ResultFs.ValueOutOfRange.Log();
long requiredCapacity = _start + offset + source.Length;
if (requiredCapacity > _length)
{
if (requiredCapacity > _capacity) EnsureCapacity(requiredCapacity);
_length = (int)(requiredCapacity - _start);
}
source.CopyTo(_buffer.AsSpan((int)(_start + offset), source.Length));
return Result.Success;
}
public byte[] ToArray()
{
var array = new byte[_length];
Buffer.BlockCopy(_buffer, _start, array, 0, _length);
return array;
}
// returns a bool saying whether we allocated a new array.
private void EnsureCapacity(long value)
{
if (value < 0 || value > int.MaxValue) throw new ArgumentOutOfRangeException(nameof(value));
if (value <= _capacity) return;
long newCapacity = Math.Max(value, 256);
newCapacity = Math.Max(newCapacity, _capacity * 2);
SetCapacity((int)Math.Min(newCapacity, int.MaxValue));
}
private void SetCapacity(int value)
{
if (value < _length)
throw new ArgumentOutOfRangeException(nameof(value), "Capacity is smaller than the current length.");
if (!_isExpandable && value != _capacity) throw new NotSupportedException("MemoryStorage is not expandable.");
if (_isExpandable && value != _capacity)
{
var newBuffer = new byte[value];
Buffer.BlockCopy(_buffer, 0, newBuffer, 0, _length);
_buffer = newBuffer;
_capacity = value;
}
}
protected override Result FlushImpl() => Result.Success;
protected override Result GetSizeImpl(out long size)
{
size = _length;
return Result.Success;
}
protected override Result SetSizeImpl(long size)
{
return ResultFs.UnsupportedOperationInMemoryStorageSetSize.Log();
}
}
}

View file

@ -6,7 +6,6 @@ using System.Security.Cryptography;
using System.Text;
using LibHac.Fs;
using LibHac.FsService;
using LibHac.FsSystem;
using LibHac.Spl;
using Aes = LibHac.Crypto.Aes;
@ -305,11 +304,7 @@ namespace LibHac
Array.Copy(EncryptedKeyblobs[i], 0x10, counter, 0, 0x10);
using (var keyblobDec = new Aes128CtrStorage(
new MemoryStorage(EncryptedKeyblobs[i], 0x20, Keyblobs[i].Length), KeyblobKeys[i], counter, false))
{
keyblobDec.Read(0, Keyblobs[i]).ThrowIfFailure();
}
Aes.DecryptCtr128(EncryptedKeyblobs[i].AsSpan(0x20), Keyblobs[i], KeyblobKeys[i], counter);
}
}