Nullable: System.Runtime.InteropServices.CustomMarshalers/WindowsRuntime (#23930)
[platform/upstream/coreclr.git] / src / System.Private.CoreLib / src / System / Runtime / InteropServices / WindowsRuntime / VectorToCollectionAdapter.cs
1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
4
5 #nullable enable
6 using System.Diagnostics;
7 using Internal.Runtime.CompilerServices;
8
9 namespace System.Runtime.InteropServices.WindowsRuntime
10 {
11     // This is a set of stub methods implementing the support for the ICollection`1 interface on WinRT
12     // objects that support IVector`1. Used by the interop mashaling infrastructure.
13     //
14     // The methods on this class must be written VERY carefully to avoid introducing security holes.
15     // That's because they are invoked with special "this"! The "this" object
16     // for all of these methods are not VectorToCollectionAdapter objects. Rather, they are of type
17     // IVector<T>. No actual VectorToCollectionAdapter object is ever instantiated. Thus, you will see
18     // a lot of expressions that cast "this" to "IVector<T>".
19     internal sealed class VectorToCollectionAdapter
20     {
21         private VectorToCollectionAdapter()
22         {
23             Debug.Fail("This class is never instantiated");
24         }
25
26         // int Count { get }
27         internal int Count<T>()
28         {
29             IVector<T> _this = Unsafe.As<IVector<T>>(this);
30             uint size = _this.Size;
31             if (((uint)int.MaxValue) < size)
32             {
33                 throw new InvalidOperationException(SR.InvalidOperation_CollectionBackingListTooLarge);
34             }
35
36             return (int)size;
37         }
38
39         // bool IsReadOnly { get }
40         internal bool IsReadOnly<T>()
41         {
42             return false;
43         }
44
45         // void Add(T item)
46         internal void Add<T>(T item)
47         {
48             IVector<T> _this = Unsafe.As<IVector<T>>(this);
49             _this.Append(item);
50         }
51
52         // void Clear()
53         internal void Clear<T>()
54         {
55             IVector<T> _this = Unsafe.As<IVector<T>>(this);
56             _this.Clear();
57         }
58
59         // bool Contains(T item)
60         internal bool Contains<T>(T item)
61         {
62             IVector<T> _this = Unsafe.As<IVector<T>>(this);
63
64             uint index;
65             return _this.IndexOf(item, out index);
66         }
67
68         // void CopyTo(T[] array, int arrayIndex)
69         internal void CopyTo<T>(T[] array, int arrayIndex)
70         {
71             if (array == null)
72                 throw new ArgumentNullException(nameof(array));
73
74             if (arrayIndex < 0)
75                 throw new ArgumentOutOfRangeException(nameof(arrayIndex));
76
77             if (array.Length <= arrayIndex && Count<T>() > 0)
78                 throw new ArgumentException(SR.Argument_IndexOutOfArrayBounds);
79
80             if (array.Length - arrayIndex < Count<T>())
81                 throw new ArgumentException(SR.Argument_InsufficientSpaceToCopyCollection);
82
83
84             IVector<T> _this = Unsafe.As<IVector<T>>(this);
85             int count = Count<T>();
86             for (int i = 0; i < count; i++)
87             {
88                 array[i + arrayIndex] = VectorToListAdapter.GetAt<T>(_this, (uint)i);
89             }
90         }
91
92         // bool Remove(T item)
93         internal bool Remove<T>(T item)
94         {
95             IVector<T> _this = Unsafe.As<IVector<T>>(this);
96
97             uint index;
98             bool exists = _this.IndexOf(item, out index);
99
100             if (!exists)
101                 return false;
102
103             if (((uint)int.MaxValue) < index)
104             {
105                 throw new InvalidOperationException(SR.InvalidOperation_CollectionBackingListTooLarge);
106             }
107
108             VectorToListAdapter.RemoveAtHelper<T>(_this, index);
109             return true;
110         }
111     }
112 }