Skip to content

Commit

Permalink
Add remaining GetRightsId methods and U8StringBuilder
Browse files Browse the repository at this point in the history
  • Loading branch information
Thealexbarney committed Oct 4, 2019
1 parent fdd7eeb commit 9934f47
Show file tree
Hide file tree
Showing 5 changed files with 180 additions and 6 deletions.
38 changes: 38 additions & 0 deletions src/LibHac/Common/PaddingStructs.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
using System.Diagnostics;
using System.Runtime.InteropServices;

namespace LibHac.Common
{
// In order for the Visual Studio debugger to accurately display a struct, every offset
// in the struct that is used for the debugger display must be part of a field.
// These padding structs make it easier to accomplish that.
[StructLayout(LayoutKind.Sequential, Size = 0x20)]
internal struct Padding20
{
[DebuggerBrowsable(DebuggerBrowsableState.Never)] private readonly ulong Padding00;
[DebuggerBrowsable(DebuggerBrowsableState.Never)] private readonly ulong Padding08;
[DebuggerBrowsable(DebuggerBrowsableState.Never)] private readonly ulong Padding10;
[DebuggerBrowsable(DebuggerBrowsableState.Never)] private readonly ulong Padding18;
}

[StructLayout(LayoutKind.Sequential, Size = 0x40)]
internal struct Padding40
{
[DebuggerBrowsable(DebuggerBrowsableState.Never)] private readonly Padding20 Padding00;
[DebuggerBrowsable(DebuggerBrowsableState.Never)] private readonly Padding20 Padding20;
}

[StructLayout(LayoutKind.Sequential, Size = 0x80)]
internal struct Padding80
{
[DebuggerBrowsable(DebuggerBrowsableState.Never)] private readonly Padding40 Padding00;
[DebuggerBrowsable(DebuggerBrowsableState.Never)] private readonly Padding40 Padding40;
}

[StructLayout(LayoutKind.Sequential, Size = 0x100)]
internal struct Padding100
{
[DebuggerBrowsable(DebuggerBrowsableState.Never)] private readonly Padding80 Padding00;
[DebuggerBrowsable(DebuggerBrowsableState.Never)] private readonly Padding80 Padding80;
}
}
86 changes: 86 additions & 0 deletions src/LibHac/Common/U8StringBuilder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
using System;
using System.Diagnostics;

namespace LibHac.Common
{
[DebuggerDisplay("{ToString()}")]
public ref struct U8StringBuilder
{
private const int NullTerminatorLength = 1;

private readonly Span<byte> _buffer;
private int _length;

public bool Overflowed { get; private set; }
public int Capacity => _buffer.Length - NullTerminatorLength;

public U8StringBuilder(Span<byte> buffer)
{
_buffer = buffer;
_length = 0;
Overflowed = false;

ThrowIfBufferLengthIsZero();

AddNullTerminator();
}

public U8StringBuilder Append(ReadOnlySpan<byte> value)
{
if (Overflowed) return this;

int valueLength = StringUtils.GetLength(value);

if (!HasAdditionalCapacity(valueLength))
{
Overflowed = true;
return this;
}

value.Slice(0, valueLength).CopyTo(_buffer.Slice(_length));
_length += valueLength;
AddNullTerminator();

return this;
}

public U8StringBuilder Append(byte value)
{
if (Overflowed) return this;

if (!HasAdditionalCapacity(1))
{
Overflowed = true;
return this;
}

_buffer[_length] = value;
_length++;
AddNullTerminator();

return this;
}

private bool HasCapacity(int requiredCapacity)
{
return requiredCapacity <= Capacity;
}

private bool HasAdditionalCapacity(int requiredAdditionalCapacity)
{
return HasCapacity(_length + requiredAdditionalCapacity);
}

private void AddNullTerminator()
{
_buffer[_length] = 0;
}

private void ThrowIfBufferLengthIsZero()
{
if (_buffer.Length == 0) throw new ArgumentException("Buffer length must be greater than 0.");
}

public override string ToString() => StringUtils.Utf8ZToString(_buffer);
}
}
29 changes: 28 additions & 1 deletion src/LibHac/Fs/ExternalKeys.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using LibHac.FsService;
using LibHac.Common;
using LibHac.FsService;
using LibHac.FsSystem;
using LibHac.Ncm;
using LibHac.Spl;

Expand All @@ -14,6 +16,31 @@ public static Result GetRightsId(this FileSystemClient fs, out RightsId rightsId
return fsProxy.GetRightsId(out rightsId, programId, storageId);
}

public static Result GetRightsId(this FileSystemClient fs, out RightsId rightsId, U8Span path)
{
rightsId = default;

IFileSystemProxy fsProxy = fs.GetFileSystemProxyServiceObject();

Result rc = FsPath.FromSpan(out FsPath fsPath, path);
if (rc.IsFailure()) return rc;

return fsProxy.GetRightsIdByPath(out rightsId, ref fsPath);
}

public static Result GetRightsId(this FileSystemClient fs, out RightsId rightsId, out byte keyGeneration, U8Span path)
{
rightsId = default;
keyGeneration = default;

IFileSystemProxy fsProxy = fs.GetFileSystemProxyServiceObject();

Result rc = FsPath.FromSpan(out FsPath fsPath, path);
if (rc.IsFailure()) return rc;

return fsProxy.GetRightsIdAndKeyGenerationByPath(out rightsId, out keyGeneration, ref fsPath);
}

public static Result RegisterExternalKey(this FileSystemClient fs, ref RightsId rightsId, ref AccessKey key)
{
IFileSystemProxy fsProxy = fs.GetFileSystemProxyServiceObject();
Expand Down
21 changes: 18 additions & 3 deletions src/LibHac/FsSystem/FsPath.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,33 @@
using System.Diagnostics;
using System.Runtime.InteropServices;
using LibHac.Common;
using LibHac.Fs;

namespace LibHac.FsSystem
{
[DebuggerDisplay("{ToString()}")]
[StructLayout(LayoutKind.Explicit, Size = MaxLength + 1)]
[StructLayout(LayoutKind.Sequential, Size = MaxLength + 1)]
public struct FsPath
{
internal const int MaxLength = 0x300;

[FieldOffset(0)] private byte _str;
#if DEBUG
[DebuggerBrowsable(DebuggerBrowsableState.Never)] private readonly Padding100 Padding000;
[DebuggerBrowsable(DebuggerBrowsableState.Never)] private readonly Padding100 Padding100;
[DebuggerBrowsable(DebuggerBrowsableState.Never)] private readonly Padding100 Padding200;
[DebuggerBrowsable(DebuggerBrowsableState.Never)] private readonly byte Padding300;
#endif

public Span<byte> Str => SpanHelpers.CreateSpan(ref _str, MaxLength + 1);
public Span<byte> Str => SpanHelpers.AsByteSpan(ref this);

public static Result FromSpan(out FsPath fsPath, ReadOnlySpan<byte> path)
{
fsPath = new FsPath();

U8StringBuilder builder = new U8StringBuilder(fsPath.Str).Append(path);

return builder.Overflowed ? ResultFs.TooLongPath : Result.Success;
}

public static implicit operator U8Span(FsPath value) => new U8Span(value.Str);
public override string ToString() => StringUtils.Utf8ZToString(Str);
Expand Down
12 changes: 10 additions & 2 deletions src/LibHac/Ncm/TitleId.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
namespace LibHac.Ncm
using System.Diagnostics;

namespace LibHac.Ncm
{
[DebuggerDisplay("{" + nameof(Value) + "}")]
public struct TitleId
{
public ulong Value;
public readonly ulong Value;

public TitleId(ulong value)
{
Value = value;
}

public static explicit operator ulong(TitleId titleId) => titleId.Value;
}
Expand Down

0 comments on commit 9934f47

Please sign in to comment.