// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. // using System; using System.Security; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.Contracts; using System.Runtime.InteropServices; using System.Runtime.CompilerServices; namespace System.Runtime.InteropServices.WindowsRuntime { // This is a set of stub methods implementing the support for the ICollection`1 interface on WinRT // objects that support IVector`1. Used by the interop mashaling infrastructure. // // The methods on this class must be written VERY carefully to avoid introducing security holes. // That's because they are invoked with special "this"! The "this" object // for all of these methods are not VectorToCollectionAdapter objects. Rather, they are of type // IVector. No actual VectorToCollectionAdapter object is ever instantiated. Thus, you will see // a lot of expressions that cast "this" to "IVector". internal sealed class VectorToCollectionAdapter { private VectorToCollectionAdapter() { Debug.Assert(false, "This class is never instantiated"); } // int Count { get } [Pure] internal int Count() { IVector _this = JitHelpers.UnsafeCast>(this); uint size = _this.Size; if (((uint)Int32.MaxValue) < size) { throw new InvalidOperationException(SR.InvalidOperation_CollectionBackingListTooLarge); } return (int)size; } // bool IsReadOnly { get } internal bool IsReadOnly() { return false; } // void Add(T item) internal void Add(T item) { IVector _this = JitHelpers.UnsafeCast>(this); _this.Append(item); } // void Clear() internal void Clear() { IVector _this = JitHelpers.UnsafeCast>(this); _this.Clear(); } // bool Contains(T item) internal bool Contains(T item) { IVector _this = JitHelpers.UnsafeCast>(this); uint index; return _this.IndexOf(item, out index); } // void CopyTo(T[] array, int arrayIndex) internal void CopyTo(T[] array, int arrayIndex) { if (array == null) throw new ArgumentNullException(nameof(array)); if (arrayIndex < 0) throw new ArgumentOutOfRangeException(nameof(arrayIndex)); if (array.Length <= arrayIndex && Count() > 0) throw new ArgumentException(SR.Argument_IndexOutOfArrayBounds); if (array.Length - arrayIndex < Count()) throw new ArgumentException(SR.Argument_InsufficientSpaceToCopyCollection); Contract.EndContractBlock(); IVector _this = JitHelpers.UnsafeCast>(this); int count = Count(); for (int i = 0; i < count; i++) { array[i + arrayIndex] = VectorToListAdapter.GetAt(_this, (uint)i); } } // bool Remove(T item) internal bool Remove(T item) { IVector _this = JitHelpers.UnsafeCast>(this); uint index; bool exists = _this.IndexOf(item, out index); if (!exists) return false; if (((uint)Int32.MaxValue) < index) { throw new InvalidOperationException(SR.InvalidOperation_CollectionBackingListTooLarge); } VectorToListAdapter.RemoveAtHelper(_this, index); return true; } } }