mirror of
https://github.com/AssetRipper/AssetRipper.git
synced 2025-12-11 20:15:29 +01:00
151 lines
3.0 KiB
C#
151 lines
3.0 KiB
C#
namespace AssetRipper.Numerics;
|
|
|
|
public readonly struct Range<T> : IEquatable<Range<T>> where T : notnull, IComparable<T>, IEquatable<T>
|
|
{
|
|
/// <summary>
|
|
/// Represents the inclusive start of the Range.
|
|
/// </summary>
|
|
public T Start { get; }
|
|
|
|
/// <summary>
|
|
/// Represents the exclusive end of the Range.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// This must be greater than <see cref="Start"/>.
|
|
/// </remarks>
|
|
public T End { get; }
|
|
|
|
public Range(T start, T end)
|
|
{
|
|
if (start.IsGreaterEqual(end))
|
|
{
|
|
throw new ArgumentException($"{nameof(start)} {start} must be less than {nameof(end)} {end}");
|
|
}
|
|
|
|
Start = start;
|
|
End = end;
|
|
}
|
|
|
|
public bool Contains(T value)
|
|
{
|
|
return Start.IsLessEqual(value) && End.IsGreater(value);
|
|
}
|
|
|
|
public bool Contains(Range<T> range)
|
|
{
|
|
return Start.IsLessEqual(range.Start) && End.IsGreaterEqual(range.End);
|
|
}
|
|
|
|
public bool IsStrictlyLess(Range<T> other)
|
|
{
|
|
return End.IsLessEqual(other.Start);
|
|
}
|
|
|
|
public bool IsStrictlyGreater(Range<T> other)
|
|
{
|
|
return Start.IsGreaterEqual(other.End);
|
|
}
|
|
|
|
public bool Intersects(Range<T> other)
|
|
{
|
|
return Contains(other.Start) || other.Contains(Start);
|
|
}
|
|
|
|
public bool Intersects(Range<T> other, out Range<T> intersection)
|
|
{
|
|
if (Intersects(other))
|
|
{
|
|
intersection = MakeIntersectionInternal(other);
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
intersection = default;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public bool CanUnion(Range<T> other)
|
|
{
|
|
return Intersects(other) || Start.Equals(other.End) || End.Equals(other.Start);
|
|
}
|
|
|
|
public bool CanUnion(Range<T> other, out Range<T> union)
|
|
{
|
|
if (CanUnion(other))
|
|
{
|
|
union = MakeUnionInternal(other);
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
union = default;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public Range<T> MakeUnion(Range<T> other)
|
|
{
|
|
return CanUnion(other)
|
|
? MakeUnionInternal(other)
|
|
: throw new ArgumentException("These ranges cannot be unioned", nameof(other));
|
|
}
|
|
|
|
private Range<T> MakeUnionInternal(Range<T> other)
|
|
{
|
|
return new Range<T>(Minimum(Start, other.Start), Maximum(End, other.End));
|
|
}
|
|
|
|
public Range<T> MakeIntersection(Range<T> other)
|
|
{
|
|
return Intersects(other)
|
|
? MakeIntersectionInternal(other)
|
|
: throw new ArgumentException("These ranges do not intersect", nameof(other));
|
|
}
|
|
|
|
private Range<T> MakeIntersectionInternal(Range<T> other)
|
|
{
|
|
return new Range<T>(Maximum(Start, other.Start), Minimum(End, other.End));
|
|
}
|
|
|
|
private static T Minimum(T left, T right)
|
|
{
|
|
return left.IsLess(right) ? left : right;
|
|
}
|
|
|
|
private static T Maximum(T left, T right)
|
|
{
|
|
return left.IsGreater(right) ? left : right;
|
|
}
|
|
|
|
public override bool Equals(object? obj)
|
|
{
|
|
return obj is Range<T> range && Equals(range);
|
|
}
|
|
|
|
public bool Equals(Range<T> other)
|
|
{
|
|
return Start.Equals(other.Start) && End.Equals(other.End);
|
|
}
|
|
|
|
public override int GetHashCode()
|
|
{
|
|
return HashCode.Combine(Start, End);
|
|
}
|
|
|
|
public static bool operator ==(Range<T> left, Range<T> right)
|
|
{
|
|
return left.Equals(right);
|
|
}
|
|
|
|
public static bool operator !=(Range<T> left, Range<T> right)
|
|
{
|
|
return !(left == right);
|
|
}
|
|
|
|
public override string ToString()
|
|
{
|
|
return $"{Start} : {End}";
|
|
}
|
|
}
|