// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
// See the LICENSE file in the project root for more information.
// Copied from https://github.com/dotnet/corefx/blob/f17f1e847aeab830de77f8a46656339d7b0f1b43/src/System.Linq/src/System/Linq/SingleLinkedNode.cs
using System.Collections.Generic;
using System.Diagnostics;
namespace System.Linq
{
///
/// An immutable node in a singly-linked list of items.
///
/// The type of the node's item.
internal sealed class SingleLinkedNode
{
///
/// Constructs a tail node.
///
/// The item to place in the tail node.
public SingleLinkedNode(TSource item)
{
Item = item;
}
///
/// Constructs a node linked to the specified node.
///
/// The linked node.
/// The item to place in this node.
private SingleLinkedNode(SingleLinkedNode linked, TSource item)
{
Debug.Assert(linked != null);
Linked = linked;
Item = item;
}
///
/// The item held by this node.
///
public TSource Item { get; }
///
/// The next node in the singly-linked list.
///
public SingleLinkedNode Linked { get; }
///
/// Creates a new node that holds the specified item and is linked to this node.
///
/// The item to place in the new node.
public SingleLinkedNode Add(TSource item) => new SingleLinkedNode(this, item);
///
/// Gets the number of items in this and subsequent nodes by walking the linked list.
///
public int GetCount()
{
var count = 0;
for (var node = this; node != null; node = node.Linked)
{
count++;
}
return count;
}
///
/// Gets an that enumerates the items of this node's singly-linked list in reverse.
///
/// The number of items in this node.
public IEnumerator GetEnumerator(int count)
{
return ((IEnumerable)ToArray(count)).GetEnumerator();
}
///
/// Gets the node at a logical index by walking the linked list.
///
/// The logical index.
///
/// The caller should make sure is less than this node's count.
///
public SingleLinkedNode GetNode(int index)
{
Debug.Assert(index >= 0 && index < GetCount());
var node = this;
for (; index > 0; index--)
{
node = node.Linked;
}
Debug.Assert(node != null);
return node;
}
///
/// Returns an that contains the items of this node's singly-linked list in reverse.
///
/// The number of items in this node.
private TSource[] ToArray(int count)
{
Debug.Assert(count == GetCount());
var array = new TSource[count];
var index = count;
for (var node = this; node != null; node = node.Linked)
{
--index;
array[index] = node.Item;
}
Debug.Assert(index == 0);
return array;
}
}
}