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.
9 using System.Reflection;
10 using System.Collections;
11 using System.Collections.Generic;
12 using System.Collections.ObjectModel;
13 using System.Diagnostics;
14 using System.Runtime.InteropServices;
15 using System.Runtime.CompilerServices;
16 using Internal.Runtime.CompilerServices;
18 namespace System.Runtime.InteropServices.WindowsRuntime
20 // This is a set of stub methods implementing the support for the IBindableVector interface on managed
21 // objects that implement IList. Used by the interop mashaling infrastructure.
23 // The methods on this class must be written VERY carefully to avoid introducing security holes.
24 // That's because they are invoked with special "this"! The "this" object
25 // for all of these methods are not ListToBindableVectorAdapter objects. Rather, they are of type
26 // IList. No actual ListToVectorBindableAdapter object is ever instantiated. Thus, you will
27 // see a lot of expressions that cast "this" to "IList".
28 internal sealed class ListToBindableVectorAdapter
30 private ListToBindableVectorAdapter()
32 Debug.Fail("This class is never instantiated");
35 // object GetAt(uint index)
36 internal object GetAt(uint index)
38 IList _this = Unsafe.As<IList>(this);
39 EnsureIndexInt32(index, _this.Count);
43 return _this[(int)index];
45 catch (ArgumentOutOfRangeException ex)
47 throw WindowsRuntimeMarshal.GetExceptionForHR(HResults.E_BOUNDS, ex, "ArgumentOutOfRange_IndexOutOfRange");
54 IList _this = Unsafe.As<IList>(this);
55 return (uint)_this.Count;
58 // IBindableVectorView GetView()
59 internal IBindableVectorView GetView()
61 IList _this = Unsafe.As<IList>(this);
62 return new ListToBindableVectorViewAdapter(_this);
65 // bool IndexOf(object value, out uint index)
66 internal bool IndexOf(object value, out uint index)
68 IList _this = Unsafe.As<IList>(this);
69 int ind = _this.IndexOf(value);
81 // void SetAt(uint index, object value)
82 internal void SetAt(uint index, object value)
84 IList _this = Unsafe.As<IList>(this);
85 EnsureIndexInt32(index, _this.Count);
89 _this[(int)index] = value;
91 catch (ArgumentOutOfRangeException ex)
93 throw WindowsRuntimeMarshal.GetExceptionForHR(HResults.E_BOUNDS, ex, "ArgumentOutOfRange_IndexOutOfRange");
97 // void InsertAt(uint index, object value)
98 internal void InsertAt(uint index, object value)
100 IList _this = Unsafe.As<IList>(this);
102 // Inserting at an index one past the end of the list is equivalent to appending
103 // so we need to ensure that we're within (0, count + 1).
104 EnsureIndexInt32(index, _this.Count + 1);
108 _this.Insert((int)index, value);
110 catch (ArgumentOutOfRangeException ex)
112 // Change error code to match what WinRT expects
113 ex.HResult = HResults.E_BOUNDS;
118 // void RemoveAt(uint index)
119 internal void RemoveAt(uint index)
121 IList _this = Unsafe.As<IList>(this);
122 EnsureIndexInt32(index, _this.Count);
126 _this.RemoveAt((int)index);
128 catch (ArgumentOutOfRangeException ex)
130 // Change error code to match what WinRT expects
131 ex.HResult = HResults.E_BOUNDS;
136 // void Append(object value)
137 internal void Append(object value)
139 IList _this = Unsafe.As<IList>(this);
143 // void RemoveAtEnd()
144 internal void RemoveAtEnd()
146 IList _this = Unsafe.As<IList>(this);
147 if (_this.Count == 0)
149 Exception e = new InvalidOperationException(SR.InvalidOperation_CannotRemoveLastFromEmptyCollection);
150 e.HResult = HResults.E_BOUNDS;
154 uint size = (uint)_this.Count;
159 internal void Clear()
161 IList _this = Unsafe.As<IList>(this);
167 private static void EnsureIndexInt32(uint index, int listCapacity)
169 // We use '<=' and not '<' becasue int.MaxValue == index would imply
170 // that Size > int.MaxValue:
171 if (((uint)int.MaxValue) <= index || index >= (uint)listCapacity)
173 Exception e = new ArgumentOutOfRangeException(nameof(index), SR.ArgumentOutOfRange_IndexLargerThanMaxValue);
174 e.HResult = HResults.E_BOUNDS;