Skip to content

Instantly share code, notes, and snippets.

@Warpten
Created November 8, 2024 14:39
Show Gist options
  • Save Warpten/c7d127a43c31e012fd78566e08aa5caa to your computer and use it in GitHub Desktop.
Save Warpten/c7d127a43c31e012fd78566e08aa5caa to your computer and use it in GitHub Desktop.
diff --git a/wowzer.fs/CASC/FileSystem.cs b/wowzer.fs/CASC/FileSystem.cs
index 0f48d7d..157eff8 100644
--- a/wowzer.fs/CASC/FileSystem.cs
+++ b/wowzer.fs/CASC/FileSystem.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
@@ -82,9 +83,9 @@ private Stream FromArchive(Index.Entry indexEntry) {
}
private IEnumerable<Index.Entry> FindContentKey(ContentKey contentKey) {
- foreach (var encodingKey in _encoding.Find(contentKey))
- foreach (var indexEntry in FindEncodingKey(encodingKey))
- yield return indexEntry;
+ return _encoding.Find(contentKey)
+ .Select(encodingKey => FindEncodingKey(encodingKey))
+ .Flatten();
}
/// <summary>
diff --git a/wowzer.fs/CASC/Index.cs b/wowzer.fs/CASC/Index.cs
index de9e7b8..f315761 100644
--- a/wowzer.fs/CASC/Index.cs
+++ b/wowzer.fs/CASC/Index.cs
@@ -1,5 +1,6 @@
using System;
using System.Buffers;
+using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
@@ -100,16 +101,7 @@ public Entry this[int index]
}
}
- public IEnumerable<Entry> this[Range range]
- {
- get
- {
- for (var i = range.Start.Value; i < range.End.Value; ++i) {
- var projectedSpan = new Range(i * Spec.Length, (i + 1) * Spec.Length);
- yield return new Entry(_rawData[projectedSpan], Spec);
- }
- }
- }
+ public IEnumerable<Entry> this[Range range] => new EntryEnumerable(this, range.Start.Value, range.End.Value);
public int Bucket { get; init; }
public int Length { get; init; }
@@ -181,5 +173,35 @@ public EntrySpec(Stream dataStream)
public readonly int Length => Size.End.Value;
}
+ class EntryEnumerable(Index index, int lowerBound, int upperBound) : IEnumerable<Entry>, IEnumerator<Entry>
+ {
+ private readonly Index _index = index;
+ private readonly int _lowerBound = lowerBound;
+ private readonly int _upperBound = upperBound;
+ private int _current = lowerBound;
+
+ public Entry Current {
+ get {
+ var projectedSpan = new Range(_current * _index.Spec.Length, (_current + 1) * _index.Spec.Length);
+ return new Entry(_index._rawData[projectedSpan], _index.Spec);
+ }
+ }
+
+ object IEnumerator.Current => throw new InvalidOperationException();
+
+ public void Dispose() { }
+
+ public IEnumerator<Entry> GetEnumerator() => this;
+
+ public bool MoveNext()
+ {
+ ++_current;
+ return _current < _upperBound;
+ }
+
+ public void Reset() => _current = _lowerBound;
+
+ IEnumerator IEnumerable.GetEnumerator() => this;
+ }
}
}
diff --git a/wowzer.fs/Extensions/EnumerableExtensions.cs b/wowzer.fs/Extensions/EnumerableExtensions.cs
new file mode 100644
index 0000000..52f1ebb
--- /dev/null
+++ b/wowzer.fs/Extensions/EnumerableExtensions.cs
@@ -0,0 +1,57 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Runtime.CompilerServices;
+
+namespace wowzer.fs.Extensions
+{
+ public static class EnumerableExtensions
+ {
+ public static IEnumerable<T> Flatten<T>(this IEnumerable<IEnumerable<T>> source) where T : allows ref struct
+ => new FlatteningRefEnumerator<T>(source);
+
+ private class FlatteningRefEnumerator<T> : IEnumerable<T>, IEnumerator<T> where T : allows ref struct
+ {
+ private readonly IEnumerator<IEnumerable<T>> _source;
+ private IEnumerator<T> _current = null;
+
+ public FlatteningRefEnumerator(IEnumerable<IEnumerable<T>> source)
+ {
+ _source = source.GetEnumerator();
+ if (_source.MoveNext())
+ _current = _source.Current.GetEnumerator();
+ }
+
+ public T Current => _current.Current;
+
+ // object IEnumerator.Current => RuntimeHelpers.IsReferenceOrContainsReferences<T>()
+ // ? throw new InvalidOperationException()
+ // : _current.Current;
+ object IEnumerator.Current => throw new InvalidOperationException();
+
+
+ public void Dispose() { }
+
+ public bool MoveNext()
+ {
+ if (_current == null)
+ return false;
+
+ var movedNext = _current.MoveNext();
+ if (!movedNext) {
+ if (!_source.MoveNext())
+ return false;
+
+ _current = _source.Current.GetEnumerator();
+ }
+
+ return _current.MoveNext();
+ }
+
+ public void Reset() => throw new InvalidOperationException();
+
+ public IEnumerator<T> GetEnumerator() => this;
+ IEnumerator IEnumerable.GetEnumerator() => this;
+ }
+ }
+}
\ No newline at end of file
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment