Skip to content

Commit 2a45cc9

Browse files
author
Mykyta Zotov
committed
Feature: Refine documentation and logic in RangeData extensions for clarity and consistency
1 parent accaa4f commit 2a45cc9

4 files changed

Lines changed: 11 additions & 8 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1628,7 +1628,7 @@ public void ValidateCoordinates(double lat, double lon)
16281628

16291629
- **Lazy evaluation:** `RangeData` builds **iterator graphs** using `IEnumerable`. Data is only materialized when iterated. Operations like `Skip`, `Take`, `Concat` do **not allocate new arrays or lists**.
16301630
- **Domain-awareness:** Supports any discrete domain via `IRangeDomain<T>`. This allows flexible steps, custom metrics, and ensures consistent range arithmetic.
1631-
- **Strict invariant:** The **range length always equals the data sequence length**. Operations that would violate this invariant are not allowed.
1631+
- **Expected invariant/contract:** The **range length should equal the data sequence length**. `RangeData` and `RangeDataExtensions` do **not** enforce this at runtime for performance reasons; callers are responsible for providing consistent inputs or can validate them (for example with `IsValid`) when safety is more important than allocation/CPU overhead.
16321632
- **Right-biased operations:** `Union` and `Intersect` always take **data from the right operand** in overlapping regions, ideal for cache updates or incremental data ingestion.
16331633
- **Composable slices:** Supports trimming (`TrimStart`, `TrimEnd`) and projections while keeping laziness intact. You can work with a `RangeData` without ever iterating the data.
16341634
- **Trade-offs:** Zero allocation is **not fully achievable** because `IEnumerable` is a reference type. Some intermediate enumerables may exist, but memory usage remains minimal.

src/Intervals.NET.Data/Extensions/EnumerableExtensions.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using Intervals.NET;
12
using Intervals.NET.Domain.Abstractions;
23

34
namespace Intervals.NET.Data.Extensions;

src/Intervals.NET.Data/Extensions/RangeDataExtensions.cs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System.Runtime.CompilerServices;
2+
using Intervals.NET;
23
using Intervals.NET.Domain.Abstractions;
34
using Intervals.NET.Extensions;
45

@@ -23,7 +24,7 @@ namespace Intervals.NET.Data.Extensions;
2324
/// <list type="bullet">
2425
/// <item><description><strong>Immutability:</strong> All operations return new instances; no mutation occurs.</description></item>
2526
/// <item><description><strong>Domain-Agnostic:</strong> Operations work with any <see cref="IRangeDomain{T}"/> implementation.</description></item>
26-
/// <item><description><strong>Consistency Guarantee:</strong> Extensions never create RangeData with mismatched range/data lengths.</description></item>
27+
/// <item><description><strong>Consistency Guarantee:</strong> Extensions are designed not to create RangeData with mismatched range/data lengths when the input RangeData instances satisfy the invariant.</description></item>
2728
/// <item><description><strong>Lazy Evaluation:</strong> Data sequences use LINQ operators; materialization is deferred.</description></item>
2829
/// </list>
2930
///
@@ -377,7 +378,6 @@ static IEnumerable<TDataType> HandleStaleWrapsFresh(
377378
/// Trims the start of the range to a new start value, adjusting data accordingly.
378379
/// <para>
379380
/// Returns a new RangeData with the trimmed range and sliced data.
380-
/// If trimming removes the entire range, returns null.
381381
/// </para>
382382
/// <para>
383383
/// ⚡ <strong>Performance:</strong> O(n) where n is the number of elements to skip.
@@ -394,8 +394,10 @@ static IEnumerable<TDataType> HandleStaleWrapsFresh(
394394
/// The type of the range domain that implements IRangeDomain&lt;TRangeType&gt;.
395395
/// </typeparam>
396396
/// <returns>
397-
/// A new RangeData with the trimmed range and sliced data,
398-
/// or null if the new start is not within the current range.
397+
/// A new RangeData with the trimmed range and sliced data if the new start is within the current range;
398+
/// <c>null</c> if the new start lies completely outside the original range;
399+
/// a non-null RangeData with an empty range and empty data sequence if trimming results in a logically empty
400+
/// but still in-bounds range (for example, the start equals the end with at least one boundary exclusive).
399401
/// </returns>
400402
/// <remarks>
401403
/// <para><strong>Example:</strong></para>

tests/Intervals.NET.Data.Tests/Extensions/RangeDataExtensionsTests.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -105,8 +105,8 @@ public void Intersect_WithOneRangeContainedInAnother_ReturnsSmaller()
105105
public void Union_WithAdjacentRanges_ReturnsUnion()
106106
{
107107
// Arrange
108-
var data1 = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; // [10, 20]
109-
var data2 = new[] { 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 }; // (20, 30]
108+
var data1 = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; // [10, 20] - 11 elements
109+
var data2 = new[] { 21, 22, 23, 24, 25, 26, 27, 28, 29, 30 }; // (20, 30] - 10 elements
110110

111111
var rd1 = new RangeData<int, int, IntegerFixedStepDomain>(
112112
Range.Closed<int>(10, 20), data1, _domain);
@@ -120,7 +120,7 @@ public void Union_WithAdjacentRanges_ReturnsUnion()
120120
Assert.NotNull(result);
121121
Assert.Equal(10, result.Range.Start.Value);
122122
Assert.Equal(30, result.Range.End.Value);
123-
Assert.Equal(22, result.Data.Count()); // 11 + 11 elements
123+
Assert.Equal(21, result.Data.Count()); // 11 + 10 elements
124124
}
125125

126126
[Fact]

0 commit comments

Comments
 (0)