-
-
Save Warpten/c7d127a43c31e012fd78566e08aa5caa to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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