Files
Explorer-Workbench/src/Explorer.Domain/VolumeIdentityMatcher.cs
netquick e9aba73552 Add Explorer Workbench with hierarchical, off-UI Storage analysis.
Storage queries run in the background with cancellation and covering indexes so switching views no longer freezes the UI.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-22 12:43:05 +02:00

83 lines
2.9 KiB
C#

namespace Explorer.Domain;
public static class VolumeIdentityMatcher
{
public sealed record MatchResult(Source? Source, MatchStrength Strength, bool Ambiguous);
public enum MatchStrength
{
None,
Weak,
SerialCapacity,
Guid
}
public static MatchResult Match(VolumeFingerprint fingerprint, IReadOnlyList<Source> known)
{
if (!string.IsNullOrWhiteSpace(fingerprint.VolumeGuid))
{
var guidHits = known
.Where(s => !string.IsNullOrEmpty(s.VolumeGuid)
&& string.Equals(s.VolumeGuid, fingerprint.VolumeGuid, StringComparison.OrdinalIgnoreCase))
.ToList();
if (guidHits.Count == 1)
{
return new MatchResult(guidHits[0], MatchStrength.Guid, false);
}
if (guidHits.Count > 1)
{
return new MatchResult(guidHits[0], MatchStrength.Guid, true);
}
}
if (fingerprint.VolumeSerial is > 0)
{
var serialHits = known.Where(s =>
s.VolumeSerial == fingerprint.VolumeSerial
&& string.Equals(s.Filesystem, fingerprint.Filesystem, StringComparison.OrdinalIgnoreCase)
&& s.CapacityBytes == fingerprint.CapacityBytes)
.ToList();
if (serialHits.Count == 1)
{
return new MatchResult(serialHits[0], MatchStrength.SerialCapacity, false);
}
if (serialHits.Count == 0 && !string.IsNullOrEmpty(fingerprint.Label))
{
serialHits = known.Where(s =>
s.VolumeSerial == fingerprint.VolumeSerial
&& string.Equals(s.Label, fingerprint.Label, StringComparison.OrdinalIgnoreCase)
&& s.CapacityBytes == fingerprint.CapacityBytes)
.ToList();
}
if (serialHits.Count == 1)
{
return new MatchResult(serialHits[0], MatchStrength.Weak, false);
}
if (serialHits.Count > 1)
{
return new MatchResult(serialHits[0], MatchStrength.Weak, true);
}
}
if (fingerprint.Kind is SourceKind.Smb or SourceKind.Nfs)
{
var unc = PathRules.CanonicalUncRoot(fingerprint.RootPath);
var uncHits = known.Where(s =>
s.Kind == fingerprint.Kind
&& s.LastRootPath is not null
&& string.Equals(PathRules.CanonicalUncRoot(s.LastRootPath), unc, StringComparison.OrdinalIgnoreCase))
.ToList();
if (uncHits.Count == 1)
{
return new MatchResult(uncHits[0], MatchStrength.SerialCapacity, false);
}
}
return new MatchResult(null, MatchStrength.None, false);
}
}