Files
git.stella-ops.org/src/StellaOps.Concelier.Models/NormalizedVersionRule.cs
2025-10-18 20:46:16 +03:00

186 lines
5.0 KiB
C#

using System;
using System.Collections.Generic;
namespace StellaOps.Concelier.Models;
/// <summary>
/// Canonical normalized version rule emitted by range builders for analytical queries.
/// </summary>
public sealed record NormalizedVersionRule
{
public NormalizedVersionRule(
string scheme,
string type,
string? min = null,
bool? minInclusive = null,
string? max = null,
bool? maxInclusive = null,
string? value = null,
string? notes = null)
{
Scheme = Validation.EnsureNotNullOrWhiteSpace(scheme, nameof(scheme)).ToLowerInvariant();
Type = Validation.EnsureNotNullOrWhiteSpace(type, nameof(type)).Replace('_', '-').ToLowerInvariant();
Min = Validation.TrimToNull(min);
MinInclusive = minInclusive;
Max = Validation.TrimToNull(max);
MaxInclusive = maxInclusive;
Value = Validation.TrimToNull(value);
Notes = Validation.TrimToNull(notes);
}
public string Scheme { get; }
public string Type { get; }
public string? Min { get; }
public bool? MinInclusive { get; }
public string? Max { get; }
public bool? MaxInclusive { get; }
public string? Value { get; }
public string? Notes { get; }
}
public sealed class NormalizedVersionRuleEqualityComparer : IEqualityComparer<NormalizedVersionRule>
{
public static NormalizedVersionRuleEqualityComparer Instance { get; } = new();
public bool Equals(NormalizedVersionRule? x, NormalizedVersionRule? y)
{
if (ReferenceEquals(x, y))
{
return true;
}
if (x is null || y is null)
{
return false;
}
return string.Equals(x.Scheme, y.Scheme, StringComparison.Ordinal)
&& string.Equals(x.Type, y.Type, StringComparison.Ordinal)
&& string.Equals(x.Min, y.Min, StringComparison.Ordinal)
&& x.MinInclusive == y.MinInclusive
&& string.Equals(x.Max, y.Max, StringComparison.Ordinal)
&& x.MaxInclusive == y.MaxInclusive
&& string.Equals(x.Value, y.Value, StringComparison.Ordinal)
&& string.Equals(x.Notes, y.Notes, StringComparison.Ordinal);
}
public int GetHashCode(NormalizedVersionRule obj)
=> HashCode.Combine(
obj.Scheme,
obj.Type,
obj.Min,
obj.MinInclusive,
obj.Max,
obj.MaxInclusive,
obj.Value,
obj.Notes);
}
public sealed class NormalizedVersionRuleComparer : IComparer<NormalizedVersionRule>
{
public static NormalizedVersionRuleComparer Instance { get; } = new();
public int Compare(NormalizedVersionRule? x, NormalizedVersionRule? y)
{
if (ReferenceEquals(x, y))
{
return 0;
}
if (x is null)
{
return -1;
}
if (y is null)
{
return 1;
}
var schemeComparison = string.Compare(x.Scheme, y.Scheme, StringComparison.Ordinal);
if (schemeComparison != 0)
{
return schemeComparison;
}
var typeComparison = string.Compare(x.Type, y.Type, StringComparison.Ordinal);
if (typeComparison != 0)
{
return typeComparison;
}
var minComparison = string.Compare(x.Min, y.Min, StringComparison.Ordinal);
if (minComparison != 0)
{
return minComparison;
}
var minInclusiveComparison = NullableBoolCompare(x.MinInclusive, y.MinInclusive);
if (minInclusiveComparison != 0)
{
return minInclusiveComparison;
}
var maxComparison = string.Compare(x.Max, y.Max, StringComparison.Ordinal);
if (maxComparison != 0)
{
return maxComparison;
}
var maxInclusiveComparison = NullableBoolCompare(x.MaxInclusive, y.MaxInclusive);
if (maxInclusiveComparison != 0)
{
return maxInclusiveComparison;
}
var valueComparison = string.Compare(x.Value, y.Value, StringComparison.Ordinal);
if (valueComparison != 0)
{
return valueComparison;
}
return string.Compare(x.Notes, y.Notes, StringComparison.Ordinal);
}
private static int NullableBoolCompare(bool? x, bool? y)
{
if (x == y)
{
return 0;
}
return (x, y) switch
{
(null, not null) => -1,
(not null, null) => 1,
(false, true) => -1,
(true, false) => 1,
_ => 0,
};
}
}
public static class NormalizedVersionSchemes
{
public const string SemVer = "semver";
public const string Nevra = "nevra";
public const string Evr = "evr";
}
public static class NormalizedVersionRuleTypes
{
public const string Range = "range";
public const string Exact = "exact";
public const string LessThan = "lt";
public const string LessThanOrEqual = "lte";
public const string GreaterThan = "gt";
public const string GreaterThanOrEqual = "gte";
}