#nullable enable
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System.Collections.Generic;
using System.Runtime.CompilerServices;
namespace System.Runtime.InteropServices
{
///
/// An unsafe class that provides a set of methods to access the underlying data representations of collections.
///
public static class CollectionsMarshal
{
private class ListView
{
public T[] _items;
public int _size;
public int _version;
private static readonly T[] s_emptyArray = new T[0];
public void EnsureCapacity(int min)
{
if (this._items.Length >= min)
return;
int num = this._items.Length == 0 ? 4 : this._items.Length * 2;
if ((uint)num > 2146435071U)
num = 2146435071;
if (num < min)
num = min;
this.Capacity = num;
}
public int Capacity
{
get => this._items.Length;
set
{
if (value < this._size)
throw new ArgumentOutOfRangeException(nameof(value), "Capacity is set too small");
if (value == this._items.Length)
return;
if (value > 0)
{
T[] destinationArray = new T[value];
if (this._size > 0)
Array.Copy((Array)this._items, 0, (Array)destinationArray, 0, this._size);
this._items = destinationArray;
}
else
this._items = s_emptyArray;
}
}
}
///
/// Get a view over a 's data.
/// Items should not be added or removed from the while the is in use.
///
/// The list to get the data view over.
/// The type of the elements in the list.
public static Span AsSpan(this List? list)
{
if (list is null)
return default;
var listView = Unsafe.As>(list);
return listView._items.AsSpan();
}
public static void SetCount(this List list, int count)
{
ForceSetCount(list, count);
}
///
/// Sets the count of the to the specified value.
///
/// The list to set the count of.
/// The value to set the list's count to.
/// The type of the elements in the list.
///
/// is .
///
///
/// is negative.
///
///
/// When increasing the count, uninitialized data is being exposed.
///
public static void ForceSetCount(this List list, int count)
{
if (list is null)
throw new NullReferenceException("list is null.");
var listView = Unsafe.As>(list);
if (count < 0)
{
throw new ArgumentOutOfRangeException(nameof(count), $"{nameof(count)} must be more than 0!");
}
listView._version++;
if (count > list.Capacity)
{
listView.EnsureCapacity(count);
}
else if (count < listView._size && RuntimeHelpers.IsReferenceOrContainsReferences())
{
Array.Clear(listView._items, count, listView._size - count);
}
listView._size = count;
}
}
}