140 lines
4.5 KiB
C#
Executable File
140 lines
4.5 KiB
C#
Executable File
using System.Collections;
|
|
|
|
namespace Nbt;
|
|
|
|
public static class NbtPath
|
|
{
|
|
public static readonly INbtPath Empty = new EmptyNbtPathImpl();
|
|
|
|
public static INbtPath CreatePath(INbtPathElement pathElement) => new NbtPathImpl([pathElement]);
|
|
|
|
public static INbtPath CreatePath(params INbtPathElement[] pathElements) => CreatePath(pathElements.AsEnumerable());
|
|
|
|
public static INbtPath CreatePath(IEnumerable<INbtPathElement> pathElements) => new NbtPathImpl(pathElements);
|
|
|
|
public static INbtPath CreatePath(params object[] pathElements) => CreatePath(pathElements.AsEnumerable());
|
|
|
|
public static INbtPath CreatePath(IEnumerable<object> pathElements) => CreatePath(pathElements.Select(WrapPathElement));
|
|
|
|
private static INbtPathElement WrapPathElement(object pathElement) => pathElement switch
|
|
{
|
|
null => throw new ArgumentNullException(nameof(pathElement)),
|
|
string name => new NbtName(name),
|
|
int index => new NbtIndex(index),
|
|
_ => throw new ArgumentException($"Invalid path element type: {pathElement.GetType().Name}", nameof(pathElement))
|
|
};
|
|
}
|
|
|
|
public interface INbtPath : IEnumerable<INbtPathElement>
|
|
{
|
|
int Count { get; }
|
|
|
|
bool IsEmpty { get; }
|
|
|
|
INbtPathElement PopFirst(out INbtPath rest);
|
|
|
|
INbtPathElement this[int index] { get; }
|
|
|
|
INbtPath Combine(INbtPath other);
|
|
|
|
INbtPath Append(INbtPathElement pathElement);
|
|
|
|
INbtPath Insert(int index, INbtPathElement pathElement);
|
|
|
|
INbtPath Replace(int index, INbtPathElement pathElement);
|
|
}
|
|
|
|
file class NbtPathImpl(IEnumerable<INbtPathElement> pathElements) : INbtPath
|
|
{
|
|
private readonly IList<INbtPathElement> _pathElements = pathElements.AsIList();
|
|
|
|
public int Count => _pathElements.Count;
|
|
|
|
public bool IsEmpty => Count == 0;
|
|
|
|
public INbtPathElement PopFirst(out INbtPath rest)
|
|
{
|
|
var count = Count;
|
|
|
|
if (count < 1)
|
|
{
|
|
throw new IndexOutOfRangeException();
|
|
}
|
|
|
|
rest = count > 1 ? new NbtPathImpl(_pathElements.Skip(1)) : NbtPath.Empty;
|
|
return _pathElements[0];
|
|
}
|
|
|
|
public INbtPathElement this[int index] => _pathElements[index];
|
|
|
|
public INbtPath Append(INbtPathElement pathElement) => new NbtPathImpl(_pathElements.Append(pathElement));
|
|
|
|
public INbtPath Insert(int index, INbtPathElement pathElement) => new NbtPathImpl(Utils.Insert(_pathElements, index, pathElement));
|
|
|
|
public INbtPath Replace(int index, INbtPathElement pathElement) => new NbtPathImpl(Utils.Replace(_pathElements, index, pathElement));
|
|
|
|
public INbtPath Combine(INbtPath other) => new NbtPathImpl(_pathElements.Concat(other));
|
|
|
|
public IEnumerator<INbtPathElement> GetEnumerator() => _pathElements.GetEnumerator();
|
|
|
|
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
|
}
|
|
|
|
file class EmptyNbtPathImpl : INbtPath
|
|
{
|
|
public int Count => 0;
|
|
|
|
public bool IsEmpty => true;
|
|
|
|
public INbtPathElement PopFirst(out INbtPath rest) => throw new IndexOutOfRangeException();
|
|
|
|
public INbtPathElement this[int index] => throw new IndexOutOfRangeException();
|
|
|
|
public INbtPath Append(INbtPathElement pathElement) => new NbtPathImpl(pathElement.Yield());
|
|
|
|
public INbtPath Insert(int index, INbtPathElement pathElement)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNotEqual(index, 0);
|
|
|
|
return new NbtPathImpl(pathElement.Yield());
|
|
}
|
|
|
|
public INbtPath Replace(int index, INbtPathElement pathElement)
|
|
{
|
|
throw new ArgumentOutOfRangeException(nameof(index));
|
|
}
|
|
|
|
public INbtPath Combine(INbtPath other) => other;
|
|
|
|
public IEnumerator<INbtPathElement> GetEnumerator() => Enumerable.Empty<INbtPathElement>().GetEnumerator();
|
|
|
|
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
|
}
|
|
|
|
public interface INbtPathElement
|
|
{
|
|
object Key { get; }
|
|
}
|
|
|
|
public readonly struct NbtName(string name) : INbtPathElement
|
|
{
|
|
public string Name { get; } = name;
|
|
|
|
object INbtPathElement.Key => Name;
|
|
|
|
public static implicit operator NbtName(string tagName) => new(tagName);
|
|
|
|
public static implicit operator string(NbtName nbtName) => nbtName.Name;
|
|
}
|
|
|
|
public readonly struct NbtIndex(int index) : INbtPathElement
|
|
{
|
|
public int Index { get; } = index;
|
|
|
|
object INbtPathElement.Key => Index;
|
|
|
|
public static implicit operator NbtIndex(int tagIndex) => new(tagIndex);
|
|
|
|
public static implicit operator int(NbtIndex nbtIndex) => nbtIndex.Index;
|
|
}
|