< Summary

Information
Class: Trailblazer.Pathing.NavigationFlowFieldPayload
Assembly: Trailblazer
File(s): /home/runner/work/Trailblazer/Trailblazer/src/Trailblazer/Pathing/Search/Flow/NavigationFlowFieldPayload.cs
Line coverage
100%
Covered lines: 89
Uncovered lines: 0
Coverable lines: 89
Total lines: 153
Line coverage: 100%
Branch coverage
100%
Covered branches: 12
Total branches: 12
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.cctor()100%11100%
.ctor(...)100%22100%
get_LastSettledCost()100%11100%
get_LastSettledAddress()100%11100%
get_RetainedBytes()100%11100%
TryGetNode(...)100%88100%
GetRetainedBytes(...)100%11100%
GetMaximumRetainedBytes(...)100%11100%
GetArrayRetainedBytes(...)100%22100%
Align8(...)100%11100%

File(s)

/home/runner/work/Trailblazer/Trailblazer/src/Trailblazer/Pathing/Search/Flow/NavigationFlowFieldPayload.cs

#LineLine coverage
 1//=======================================================================
 2// NavigationFlowFieldPayload.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;
 9using System.Runtime.CompilerServices;
 10using FixedMathSharp;
 11
 12namespace Trailblazer.Pathing;
 13
 14/// <summary>Stores one immutable stable-address flow-field prefix.</summary>
 15internal sealed class NavigationFlowFieldPayload
 16{
 17    private const long ObjectHeaderBytes = 16L;
 18    private const long ArrayHeaderBytes = 24L;
 19    private const long ReferenceSlotBytes = 8L;
 20    private const long Int32Bytes = 4L;
 21    private const long NullableUInt64Bytes = 16L;
 22    private const long BooleanBytes = 1L;
 123    private static readonly long BaseRetainedBytes = Align8(
 124        ObjectHeaderBytes
 125        + Unsafe.SizeOf<NavigationFlowFieldPayloadKey>()
 126        + (4L * ReferenceSlotBytes)
 127        + NullableUInt64Bytes
 128        + BooleanBytes);
 29
 76730    internal NavigationFlowFieldPayload(
 76731        NavigationFlowFieldPayloadKey key,
 76732        NavigationFlowFieldNode[] nodes,
 76733        int[] addressLookupOrdinals,
 76734        NavigationTransitionInstruction[] transitionInstructions,
 76735        GraphDependencyStamp dependencies,
 76736        bool isComplete,
 76737        ulong? worldChangeSequence)
 38    {
 76739        SwiftThrowHelper.ThrowIfNull(nodes, nameof(nodes));
 76740        SwiftThrowHelper.ThrowIfNull(addressLookupOrdinals, nameof(addressLookupOrdinals));
 76741        SwiftThrowHelper.ThrowIfNull(
 76742            transitionInstructions,
 76743            nameof(transitionInstructions));
 76744        SwiftThrowHelper.ThrowIfNull(dependencies, nameof(dependencies));
 76745        SwiftThrowHelper.ThrowIfArgument(
 76746            nodes.Length == 0 || addressLookupOrdinals.Length != nodes.Length,
 76747            paramName: null,
 76748            message: "Flow payload arrays must be non-empty and aligned.");
 76549        Key = key;
 76550        Nodes = nodes;
 76551        AddressLookupOrdinals = addressLookupOrdinals;
 76552        TransitionInstructions = transitionInstructions;
 76553        Dependencies = dependencies;
 76554        IsComplete = isComplete;
 76555        WorldChangeSequence = worldChangeSequence;
 76556    }
 57
 58    internal NavigationFlowFieldPayloadKey Key { get; }
 59    internal NavigationFlowFieldNode[] Nodes { get; }
 60    internal int[] AddressLookupOrdinals { get; }
 61    internal NavigationTransitionInstruction[] TransitionInstructions { get; }
 62    internal GraphDependencyStamp Dependencies { get; }
 63    internal bool IsComplete { get; }
 64    internal ulong? WorldChangeSequence { get; }
 147665    internal Fixed64 LastSettledCost => Nodes[Nodes.Length - 1].IntegrationCost;
 266    internal NavigationCellAddress LastSettledAddress => Nodes[Nodes.Length - 1].Address;
 67
 684268    internal long RetainedBytes => GetRetainedBytes(
 684269        Nodes.Length,
 684270        TransitionInstructions.Length,
 684271        Dependencies);
 72
 73    internal bool TryGetNode(
 74        NavigationCellAddress address,
 75        TraversalMedium medium,
 76        out NavigationFlowFieldNode node)
 77    {
 287878        int low = 0;
 287879        int high = AddressLookupOrdinals.Length - 1;
 826280        while (low <= high)
 81        {
 824382            int middle = low + ((high - low) >> 1);
 824383            NavigationFlowFieldNode candidate = Nodes[AddressLookupOrdinals[middle]];
 824384            int comparison = candidate.Address.CompareTo(address);
 824385            if (comparison == 0)
 286086                comparison = ((int)candidate.Medium).CompareTo((int)medium);
 824387            if (comparison == 0)
 88            {
 285989                node = candidate;
 285990                return true;
 91            }
 538492            if (comparison < 0)
 528993                low = middle + 1;
 94            else
 9595                high = middle - 1;
 96        }
 1997        node = default;
 1998        return false;
 99    }
 100
 101    internal static long GetRetainedBytes(
 102        int nodeCount,
 103        int transitionInstructionCount,
 104        GraphDependencyStamp dependencies)
 105    {
 6842106        SwiftThrowHelper.ThrowIfNegative(nodeCount, nameof(nodeCount));
 6842107        SwiftThrowHelper.ThrowIfNegative(
 6842108            transitionInstructionCount,
 6842109            nameof(transitionInstructionCount));
 6842110        SwiftThrowHelper.ThrowIfNull(dependencies, nameof(dependencies));
 6842111        return checked(
 6842112            BaseRetainedBytes
 6842113            + GetArrayRetainedBytes(
 6842114                nodeCount,
 6842115                Unsafe.SizeOf<NavigationFlowFieldNode>())
 6842116            + GetArrayRetainedBytes(nodeCount, Int32Bytes)
 6842117            + GetArrayRetainedBytes(
 6842118                transitionInstructionCount,
 6842119                Unsafe.SizeOf<NavigationTransitionInstruction>())
 6842120            + dependencies.RetainedBytes);
 121    }
 122
 123    internal static long GetMaximumRetainedBytes(
 124        int nodeCount,
 125        int transitionInstructionCount,
 126        int componentCount,
 127        int pageCount)
 128    {
 762129        SwiftThrowHelper.ThrowIfNegative(nodeCount, nameof(nodeCount));
 761130        SwiftThrowHelper.ThrowIfNegative(
 761131            transitionInstructionCount,
 761132            nameof(transitionInstructionCount));
 760133        SwiftThrowHelper.ThrowIfNegative(componentCount, nameof(componentCount));
 759134        SwiftThrowHelper.ThrowIfNegative(pageCount, nameof(pageCount));
 758135        return checked(
 758136            BaseRetainedBytes
 758137            + GetArrayRetainedBytes(
 758138                nodeCount,
 758139                Unsafe.SizeOf<NavigationFlowFieldNode>())
 758140            + GetArrayRetainedBytes(nodeCount, Int32Bytes)
 758141            + GetArrayRetainedBytes(
 758142                transitionInstructionCount,
 758143                Unsafe.SizeOf<NavigationTransitionInstruction>())
 758144            + GraphDependencyStamp.GetRetainedBytes(componentCount, pageCount));
 145    }
 146
 147    private static long GetArrayRetainedBytes(int length, long elementBytes) =>
 22800148        length == 0
 22800149            ? 0L
 22800150            : Align8(checked(ArrayHeaderBytes + ((long)length * elementBytes)));
 151
 15455152    private static long Align8(long value) => checked((value + 7L) & ~7L);
 153}