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.
6 using System.Collections;
7 using System.Diagnostics;
8 using Internal.Runtime.CompilerServices;
10 namespace System.Runtime.InteropServices.WindowsRuntime
12 // This is a set of stub methods implementing the support for the IBindableVector interface on managed
13 // objects that implement IList. Used by the interop mashaling infrastructure.
15 // The methods on this class must be written VERY carefully to avoid introducing security holes.
16 // That's because they are invoked with special "this"! The "this" object
17 // for all of these methods are not ListToBindableVectorAdapter objects. Rather, they are of type
18 // IList. No actual ListToVectorBindableAdapter object is ever instantiated. Thus, you will
19 // see a lot of expressions that cast "this" to "IList".
20 internal sealed class ListToBindableVectorAdapter
22 private ListToBindableVectorAdapter()
24 Debug.Fail("This class is never instantiated");
27 // object GetAt(uint index)
28 internal object GetAt(uint index)
30 IList _this = Unsafe.As<IList>(this);
31 EnsureIndexInt32(index, _this.Count);
35 return _this[(int)index];
37 catch (ArgumentOutOfRangeException ex)
39 throw WindowsRuntimeMarshal.GetExceptionForHR(HResults.E_BOUNDS, ex, "ArgumentOutOfRange_IndexOutOfRange");
46 IList _this = Unsafe.As<IList>(this);
47 return (uint)_this.Count;
50 // IBindableVectorView GetView()
51 internal IBindableVectorView GetView()
53 IList _this = Unsafe.As<IList>(this);
54 return new ListToBindableVectorViewAdapter(_this);
57 // bool IndexOf(object value, out uint index)
58 internal bool IndexOf(object value, out uint index)
60 IList _this = Unsafe.As<IList>(this);
61 int ind = _this.IndexOf(value);
73 // void SetAt(uint index, object value)
74 internal void SetAt(uint index, object value)
76 IList _this = Unsafe.As<IList>(this);
77 EnsureIndexInt32(index, _this.Count);
81 _this[(int)index] = value;
83 catch (ArgumentOutOfRangeException ex)
85 throw WindowsRuntimeMarshal.GetExceptionForHR(HResults.E_BOUNDS, ex, "ArgumentOutOfRange_IndexOutOfRange");
89 // void InsertAt(uint index, object value)
90 internal void InsertAt(uint index, object value)
92 IList _this = Unsafe.As<IList>(this);
94 // Inserting at an index one past the end of the list is equivalent to appending
95 // so we need to ensure that we're within (0, count + 1).
96 EnsureIndexInt32(index, _this.Count + 1);
100 _this.Insert((int)index, value);
102 catch (ArgumentOutOfRangeException ex)
104 // Change error code to match what WinRT expects
105 ex.HResult = HResults.E_BOUNDS;
110 // void RemoveAt(uint index)
111 internal void RemoveAt(uint index)
113 IList _this = Unsafe.As<IList>(this);
114 EnsureIndexInt32(index, _this.Count);
118 _this.RemoveAt((int)index);
120 catch (ArgumentOutOfRangeException ex)
122 // Change error code to match what WinRT expects
123 ex.HResult = HResults.E_BOUNDS;
128 // void Append(object value)
129 internal void Append(object value)
131 IList _this = Unsafe.As<IList>(this);
135 // void RemoveAtEnd()
136 internal void RemoveAtEnd()
138 IList _this = Unsafe.As<IList>(this);
139 if (_this.Count == 0)
141 Exception e = new InvalidOperationException(SR.InvalidOperation_CannotRemoveLastFromEmptyCollection);
142 e.HResult = HResults.E_BOUNDS;
146 uint size = (uint)_this.Count;
151 internal void Clear()
153 IList _this = Unsafe.As<IList>(this);
159 private static void EnsureIndexInt32(uint index, int listCapacity)
161 // We use '<=' and not '<' becasue int.MaxValue == index would imply
162 // that Size > int.MaxValue:
163 if (((uint)int.MaxValue) <= index || index >= (uint)listCapacity)
165 Exception e = new ArgumentOutOfRangeException(nameof(index), SR.ArgumentOutOfRange_IndexLargerThanMaxValue);
166 e.HResult = HResults.E_BOUNDS;