Nullable: System.Runtime.InteropServices.CustomMarshalers/WindowsRuntime (#23930)
[platform/upstream/coreclr.git] / src / System.Private.CoreLib / src / System / Runtime / InteropServices / WindowsRuntime / MapViewToReadOnlyCollectionAdapter.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.Collections.Generic;
7 using System.Diagnostics;
8 using Internal.Runtime.CompilerServices;
9
10 namespace System.Runtime.InteropServices.WindowsRuntime
11 {
12     // These stubs will be used when a call via IReadOnlyCollection<KeyValuePair<K, V>> is made in managed code.
13     // This can mean two things - either the underlying unmanaged object implements IMapView<K, V> or it
14     // implements IVectorView<IKeyValuePair<K, V>> and we cannot determine this statically in the general
15     // case so we have to cast at run-time. Used by the interop mashaling infrastructure.
16     //
17     // The methods on this class must be written VERY carefully to avoid introducing security holes.
18     // That's because they are invoked with special "this"! The "this" object
19     // for all of these methods are not MapViewToReadOnlyCollectionAdapter objects. Rather, they are of type
20     // IVectorView<KeyValuePair<K, V>> or IMapView<K, V>. No actual MapViewToReadOnlyCollectionAdapter object is ever
21     // instantiated. Thus, you will see a lot of expressions that cast "this" to "IVectorView<KeyValuePair<K, V>>"
22     // or "IMapView<K, V>".
23     internal sealed class MapViewToReadOnlyCollectionAdapter
24     {
25         private MapViewToReadOnlyCollectionAdapter()
26         {
27             Debug.Fail("This class is never instantiated");
28         }
29
30         // int Count { get }
31         internal int Count<K, V>()
32         {
33             object _this = Unsafe.As<object>(this);
34
35             if (_this is IMapView<K, V> _this_map)
36             {
37                 uint size = _this_map.Size;
38
39                 if (((uint)int.MaxValue) < size)
40                 {
41                     throw new InvalidOperationException(SR.InvalidOperation_CollectionBackingDictionaryTooLarge);
42                 }
43
44                 return (int)size;
45             }
46             else
47             {
48                 IVectorView<KeyValuePair<K, V>> _this_vector = Unsafe.As<IVectorView<KeyValuePair<K, V>>>(this);
49                 uint size = _this_vector.Size;
50
51                 if (((uint)int.MaxValue) < size)
52                 {
53                     throw new InvalidOperationException(SR.InvalidOperation_CollectionBackingListTooLarge);
54                 }
55
56                 return (int)size;
57             }
58         }
59     }
60 }