f6667acf72ff9a159e6da152a144aa45e9182090
[platform/upstream/dotnet/runtime.git] /
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 //
6
7 using System;
8 using System.Security;
9 using System.Collections;
10 using System.Collections.Generic;
11 using System.Diagnostics;
12 using System.Runtime.InteropServices;
13 using System.Runtime.CompilerServices;
14 using Internal.Runtime.CompilerServices;
15
16 namespace System.Runtime.InteropServices.WindowsRuntime
17 {
18     internal delegate T Indexer_Get_Delegate<out T>(int index);
19
20     // This is a set of stub methods implementing the support for the IReadOnlyList`1 interface on WinRT
21     // objects that support IVectorView`1. Used by the interop mashaling infrastructure.
22     //
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 IVectorViewToIReadOnlyListAdapter objects. Rather, they are of type
26     // IVectorView<T>. No actual IVectorViewToIReadOnlyListAdapter object is ever instantiated. Thus, you will see
27     // a lot of expressions that cast "this" to "IVectorView<T>".
28     [DebuggerDisplay("Count = {Count}")]
29     internal sealed class IVectorViewToIReadOnlyListAdapter
30     {
31         private IVectorViewToIReadOnlyListAdapter()
32         {
33             Debug.Fail("This class is never instantiated");
34         }
35
36         // T this[int index] { get }
37         internal T Indexer_Get<T>(int index)
38         {
39             if (index < 0)
40                 throw new ArgumentOutOfRangeException(nameof(index));
41
42             IVectorView<T> _this = Unsafe.As<IVectorView<T>>(this);
43
44             try
45             {
46                 return _this.GetAt((uint)index);
47
48                 // We delegate bounds checking to the underlying collection and if it detected a fault,
49                 // we translate it to the right exception:
50             }
51             catch (Exception ex)
52             {
53                 if (HResults.E_BOUNDS == ex.HResult)
54                     throw new ArgumentOutOfRangeException(nameof(index));
55
56                 throw;
57             }
58         }
59
60         // T this[int index] { get }
61         internal T Indexer_Get_Variance<T>(int index) where T : class
62         {
63             bool fUseString;
64             Delegate target = System.StubHelpers.StubHelpers.GetTargetForAmbiguousVariantCall(
65                 this,
66                 typeof(IReadOnlyList<T>).TypeHandle.Value,
67                 out fUseString);
68
69             if (target != null)
70             {
71                 return (Unsafe.As<Indexer_Get_Delegate<T>>(target))(index);
72             }
73
74             if (fUseString)
75             {
76                 return Unsafe.As<T>(Indexer_Get<string>(index));
77             }
78
79             return Indexer_Get<T>(index);
80         }
81     }
82 }