< Summary

Information
Class: Trailblazer.Pathing.NavigationPagedSequence<T>
Assembly: Trailblazer
File(s): /home/runner/work/Trailblazer/Trailblazer/src/Trailblazer/Pathing/Graph/NavigationPagedSequence.cs
Line coverage
100%
Covered lines: 59
Uncovered lines: 0
Coverable lines: 59
Total lines: 146
Line coverage: 100%
Branch coverage
100%
Covered branches: 22
Total branches: 22
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%
get_RetainedBytes()100%22100%
get_PersistentPageCount()100%22100%
get_Item(...)100%44100%
GetEnumerator()100%11100%
.ctor(...)100%11100%
MoveNext()100%44100%
.ctor(...)100%22100%
get_RetainedBytes()100%11100%
get_PersistentPageCount()100%11100%
Append(...)100%66100%
Seal()100%22100%
.ctor()100%11100%

File(s)

/home/runner/work/Trailblazer/Trailblazer/src/Trailblazer/Pathing/Graph/NavigationPagedSequence.cs

#LineLine coverage
 1//=======================================================================
 2// NavigationPagedSequence.cs
 3//=======================================================================
 4// MIT License, Copyright (c) 2024-present David Oravsky (mrdav30)
 5// See LICENSE file in the project root for full license information.
 6//=======================================================================
 7
 8using System;
 9
 10namespace Trailblazer.Pathing;
 11
 12/// <summary>Stores an immutable ordered sequence in fixed-size allocation pages.</summary>
 13internal sealed class NavigationPagedSequence<T>
 14{
 15    private const int PageCapacity = 8;
 16    private const long WrapperBytes = 32L;
 17    private const long BuilderBytes = 40L;
 18    private const long PageAndArrayHeadersBytes = 56L;
 19
 20    internal static NavigationPagedSequence<T> Empty { get; } = new(null, 0, 0, 0);
 21
 22    private readonly Page? _head;
 23    private readonly int _pageCount;
 24    private readonly int _elementBytes;
 25
 2415226    private NavigationPagedSequence(Page? head, int count, int pageCount, int elementBytes)
 27    {
 2415228        _head = head;
 2415229        Count = count;
 2415230        _pageCount = pageCount;
 2415231        _elementBytes = elementBytes;
 2415232    }
 33
 34    internal int Count { get; }
 35
 9360436    internal long RetainedBytes => Count == 0
 9360437        ? 0L
 9360438        : checked(
 9360439            WrapperBytes
 9360440            + ((long)_pageCount
 9360441                * (PageAndArrayHeadersBytes + ((long)PageCapacity * _elementBytes))));
 42
 9359943    internal int PersistentPageCount => Count == 0 ? 0 : checked(1 + (_pageCount * 2));
 44
 45    internal T this[int index]
 46    {
 47        get
 48        {
 4849            if ((uint)index >= (uint)Count)
 250                throw new ArgumentOutOfRangeException(nameof(index));
 4651            Page page = _head!;
 4752            while (index >= page.Count)
 53            {
 154                index -= page.Count;
 155                page = page.Next!;
 56            }
 4657            return page.Values[index];
 58        }
 59    }
 60
 153369461    internal Enumerator GetEnumerator() => new(_head, Count);
 62
 63    internal struct Enumerator
 64    {
 65        private Page? _page;
 66        private int _pageIndex;
 67        private int _remaining;
 68
 69        internal Enumerator(Page? page, int count)
 70        {
 153369471            _page = page;
 153369472            _pageIndex = 0;
 153369473            _remaining = count;
 153369474            Current = default!;
 153369475        }
 76
 77        internal T Current { get; private set; }
 78
 79        internal bool MoveNext()
 80        {
 272090881            if (_remaining == 0)
 82            {
 135873683                Current = default!;
 135873684                return false;
 85            }
 136217286            if (_pageIndex == _page!.Count)
 87            {
 955688                _page = _page.Next;
 955689                _pageIndex = 0;
 90            }
 136217291            Current = _page!.Values[_pageIndex++];
 136217292            _remaining--;
 136217293            return true;
 94        }
 95    }
 96
 97    internal sealed class Builder
 98    {
 99        private readonly int _elementBytes;
 100        private Page? _head;
 101        private Page? _tail;
 102        private int _count;
 103        private int _pageCount;
 104
 24156105        internal Builder(int elementBytes)
 106        {
 24156107            if (elementBytes <= 0)
 2108                throw new ArgumentOutOfRangeException(nameof(elementBytes));
 24154109            _elementBytes = elementBytes;
 24154110        }
 111
 89431112        internal long RetainedBytes => checked(
 89431113            BuilderBytes
 89431114            + ((long)_pageCount
 89431115                * (PageAndArrayHeadersBytes + ((long)PageCapacity * _elementBytes))));
 116
 89557117        internal int PersistentPageCount => checked(1 + (_pageCount * 2));
 118
 119        internal void Append(T value)
 120        {
 110320121            if (_tail == null || _tail.Count == PageCapacity)
 122            {
 32115123                var page = new Page();
 32115124                if (_tail == null)
 24151125                    _head = page;
 126                else
 7964127                    _tail.Next = page;
 32115128                _tail = page;
 32115129                _pageCount++;
 130            }
 110320131            _tail.Values[_tail.Count++] = value;
 110320132            _count++;
 110320133        }
 134
 24148135        internal NavigationPagedSequence<T> Seal() => _count == 0
 24148136            ? Empty
 24148137            : new NavigationPagedSequence<T>(_head, _count, _pageCount, _elementBytes);
 138    }
 139
 140    internal sealed class Page
 141    {
 32115142        internal readonly T[] Values = new T[PageCapacity];
 143        internal Page? Next;
 144        internal int Count;
 145    }
 146}