Skip to content

Commit

Permalink
Merge pull request #76 from Nexus-Mods/feat/better-enumerators
Browse files Browse the repository at this point in the history
Use custom enumerator implementation
  • Loading branch information
erri120 authored Jul 22, 2024
2 parents 118d4c9 + 347d9f0 commit 595bb60
Show file tree
Hide file tree
Showing 2 changed files with 131 additions and 37 deletions.
106 changes: 83 additions & 23 deletions src/NexusMods.MnemonicDB.Abstractions/IndexSegments/Entities.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
using System.Collections;
using System.Collections.Generic;
using JetBrains.Annotations;
using NexusMods.MnemonicDB.Abstractions.Models;

namespace NexusMods.MnemonicDB.Abstractions.IndexSegments;

/// <summary>
/// A subview of an IndexSegment that returns a specific entity type
/// </summary>
[PublicAPI]
public readonly struct Entities<TInner, TEntity>(TInner ids, IDb db) :
IReadOnlyCollection<TEntity>
where TEntity : IReadOnlyModel<TEntity>
Expand All @@ -22,22 +24,49 @@ public readonly struct Entities<TInner, TEntity>(TInner ids, IDb db) :
/// </summary>
public int Count => ids.Count;

/// <inheritdoc />
public IEnumerator<TEntity> GetEnumerator()
/// <summary>
/// Returns an enumerator.
/// </summary>
public Enumerator GetEnumerator() => new(db, ids);
IEnumerator<TEntity> IEnumerable<TEntity>.GetEnumerator() => GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();

/// <summary>
/// Enumerator.
/// </summary>
public struct Enumerator : IEnumerator<TEntity>
{
for (var i = 0; i < Count; i++)
private readonly IDb _db;
private readonly TInner _ids;
private int _index;

internal Enumerator(IDb db, TInner ids)
{
yield return this[i];
_db = db;
_ids = ids;
}
}

IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
/// <inheritdoc/>
public TEntity Current { get; private set; } = default!;
object IEnumerator.Current => Current;

/// <inheritdoc/>
public bool MoveNext()
{
if (_index >= _ids.Count) return false;

Current = TEntity.Create(_db, _ids[_index++]);
return true;
}

/// <inheritdoc/>
public void Reset() => _index = 0;

/// <inheritdoc/>
public void Dispose() { }
}
}


/// <summary>
/// A wrapper around EntityIds that auto-creates the given ReadModel on-the-fly
/// </summary>
Expand All @@ -58,27 +87,58 @@ public Entities(EntityIds ids, IDb db)
_db = db;
}

/// <inheritdoc />
public int Count => _ids.Count;

/// <summary>
/// Returns an enumerator.
/// </summary>
public Enumerator GetEnumerator() => new(_db, _ids);
IEnumerator<TModel> IEnumerable<TModel>.GetEnumerator() => GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();

/// <inheritdoc />
public IEnumerator<TModel> GetEnumerator()
public override string ToString()
{
foreach (var id in _ids)
{
yield return TModel.Create(_db, id);
}
return $"Entities<{typeof(TModel).FullName ?? typeof(TModel).Name}>({Count})";
}

IEnumerator IEnumerable.GetEnumerator()
/// <summary>
/// Enumerator.
/// </summary>
public struct Enumerator : IEnumerator<TModel>
{
return GetEnumerator();
}
private readonly EntityIds _ids;
private readonly IDb _db;
private int _index;

/// <inheritdoc />
public int Count => _ids.Count;
internal Enumerator(IDb db, EntityIds ids)
{
_db = db;
_ids = ids;
}

/// <inheritdoc />
public override string ToString()
{
return $"Entities<{typeof(TModel).FullName ?? typeof(TModel).Name}>({Count})";
/// <inheritdoc/>
public TModel Current { get; private set; } = default!;

object IEnumerator.Current => Current;

/// <inheritdoc/>
public bool MoveNext()
{
if (_index >= _ids.Count) return false;
var id = _ids[_index++];

Current = TModel.Create(_db, id);
return true;
}

/// <inheritdoc/>
public void Reset() => _index = 0;

/// <inheritdoc/>
public void Dispose()
{
}
}
}
62 changes: 48 additions & 14 deletions src/NexusMods.MnemonicDB.Abstractions/IndexSegments/EntityIds.cs
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
using System;
using System.Collections;
using System.Collections.Generic;
using JetBrains.Annotations;
using NexusMods.MnemonicDB.Abstractions.Models;

namespace NexusMods.MnemonicDB.Abstractions.IndexSegments;

/// <summary>
/// A subview of an IndexSegment that returns the entity ids of the segment
/// </summary>
public struct EntityIds(IndexSegment segment, int start, int end) :
[PublicAPI]
public readonly struct EntityIds(IndexSegment segment, int start, int end) :
IReadOnlyCollection<EntityId>, IIndexSegment<EntityId>
{
/// <summary>
Expand All @@ -34,19 +36,12 @@ public EntityId[] ToArray()
return arr;
}

/// <inheritdoc />
public IEnumerator<EntityId> GetEnumerator()
{
for (var i = start; i < end; i++)
{
yield return this[i];
}
}

IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
/// <summary>
/// Returns an enumerator.
/// </summary>
public Enumerator GetEnumerator() => new(segment, start, end);
IEnumerator<EntityId> IEnumerable<EntityId>.GetEnumerator() => GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();

/// <summary>
/// Creates a view of these Ids that auto-casts every Id into a model of the given model type
Expand All @@ -56,4 +51,43 @@ public Entities<TModel> AsModels<TModel>(IDb db)
{
return new Entities<TModel>(this, db);
}

/// <summary>
/// Enumerator.
/// </summary>
public struct Enumerator : IEnumerator<EntityId>
{
private readonly IndexSegment _segment;
private readonly int _start;
private readonly int _end;
private int _index;

internal Enumerator(IndexSegment segment, int start, int end)
{
_segment = segment;
_start = start;
_end = end;

_index = start;
}

/// <inheritdoc/>
public EntityId Current { get; private set; } = default!;
object IEnumerator.Current => Current;

/// <inheritdoc/>
public bool MoveNext()
{
if (_index >= _end) return false;
Current = _segment[_index + _start].E;
_index += 1;
return true;
}

/// <inheritdoc/>
public void Reset() => _index = 0;

/// <inheritdoc/>
public void Dispose() { }
}
}

0 comments on commit 595bb60

Please sign in to comment.