Nullable: System.Runtime.InteropServices.CustomMarshalers/WindowsRuntime (#23930)
[platform/upstream/coreclr.git] / src / System.Private.CoreLib / src / System / Runtime / InteropServices / WindowsRuntime / IReadOnlyDictionaryToIMapViewAdapter.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     // This is a set of stub methods implementing the support for the IMapView`2 interface on managed
13     // objects that implement IReadOnlyDictionary`2. Used by the interop mashaling infrastructure.
14     //
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 IReadOnlyDictionaryToIMapViewAdapter objects. Rather, they are of type
18     // IReadOnlyDictionary<K, V>. No actual IReadOnlyDictionaryToIMapViewAdapter object is ever instantiated. Thus, you will
19     // see a lot of expressions that cast "this" to "IReadOnlyDictionary<K, V>". 
20     [DebuggerDisplay("Size = {Size}")]
21     internal sealed class IReadOnlyDictionaryToIMapViewAdapter
22     {
23         private IReadOnlyDictionaryToIMapViewAdapter()
24         {
25             Debug.Fail("This class is never instantiated");
26         }
27
28         // V Lookup(K key)
29         internal V Lookup<K, V>(K key)
30         {
31             IReadOnlyDictionary<K, V> _this = Unsafe.As<IReadOnlyDictionary<K, V>>(this);
32             V value;
33             bool keyFound = _this.TryGetValue(key, out value);
34
35             if (!keyFound)
36             {
37                 Debug.Assert(key != null);
38                 Exception e = new KeyNotFoundException(SR.Format(SR.Arg_KeyNotFoundWithKey, key.ToString()));
39                 e.HResult = HResults.E_BOUNDS;
40                 throw e;
41             }
42
43             return value;
44         }
45
46         // uint Size { get }
47         internal uint Size<K, V>()
48         {
49             IReadOnlyDictionary<K, V> _this = Unsafe.As<IReadOnlyDictionary<K, V>>(this);
50             return (uint)_this.Count;
51         }
52
53         // bool HasKey(K key)
54         internal bool HasKey<K, V>(K key)
55         {
56             IReadOnlyDictionary<K, V> _this = Unsafe.As<IReadOnlyDictionary<K, V>>(this);
57             return _this.ContainsKey(key);
58         }
59
60         // void Split(out IMapView<K, V> first, out IMapView<K, V> second)
61         internal void Split<K, V>(out IMapView<K, V>? first, out IMapView<K, V>? second)
62         {
63             IReadOnlyDictionary<K, V> _this = Unsafe.As<IReadOnlyDictionary<K, V>>(this);
64
65             if (_this.Count < 2)
66             {
67                 first = null;
68                 second = null;
69                 return;
70             }
71
72             if (!(_this is ConstantSplittableMap<K, V> splittableMap))
73                 splittableMap = new ConstantSplittableMap<K, V>(_this);
74
75             splittableMap.Split(out first, out second);
76         }
77     }
78 }