├── .gitignore ├── LICENSE ├── PointerToolkit.Generator ├── .gitignore ├── PointerToolkit.Generator.csproj └── Program.cs ├── PointerToolkit.sln ├── PointerToolkit ├── .gitignore ├── CastPtr`1.Generated.cs ├── CastPtr`10.Generated.cs ├── CastPtr`11.Generated.cs ├── CastPtr`12.Generated.cs ├── CastPtr`13.Generated.cs ├── CastPtr`14.Generated.cs ├── CastPtr`15.Generated.cs ├── CastPtr`16.Generated.cs ├── CastPtr`17.Generated.cs ├── CastPtr`2.Generated.cs ├── CastPtr`3.Generated.cs ├── CastPtr`4.Generated.cs ├── CastPtr`5.Generated.cs ├── CastPtr`6.Generated.cs ├── CastPtr`7.Generated.cs ├── CastPtr`8.Generated.cs ├── CastPtr`9.Generated.cs ├── FodyWeavers.xml ├── FodyWeavers.xsd ├── InterlockedPtr.cs ├── PointerToolkit.csproj ├── Ptr.cs ├── PtrOperators.cs ├── PtrPtr.cs ├── PtrPtrPtr.cs ├── PtrPtrPtr`1.cs ├── PtrPtr`1.cs ├── Ptr`1.cs ├── UnsafePtr.cs └── VolatilePtr.cs └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | .vs 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Rick Brewster 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /PointerToolkit.Generator/.gitignore: -------------------------------------------------------------------------------- 1 | bin 2 | obj 3 | PointerToolkit.Generator.csproj.user 4 | -------------------------------------------------------------------------------- /PointerToolkit.Generator/PointerToolkit.Generator.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net6.0 6 | enable 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /PointerToolkit.Generator/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | public static class Program 7 | { 8 | public static int Main(string[] args) 9 | { 10 | try 11 | { 12 | MainImpl(args[0]); 13 | return 0; 14 | } 15 | catch (Exception ex) 16 | { 17 | Console.WriteLine(); 18 | Console.WriteLine("*** Unhandled Exception: " + ex.ToString()); 19 | return ex.HResult; 20 | } 21 | } 22 | 23 | public static void MainImpl(string outputDirPath) 24 | { 25 | Console.WriteLine($"PointerToolkit generator, outputting to {outputDirPath}"); 26 | 27 | // This must be at least 1 plus the maximum number of base COM interfaces needed to support TerraFX.Interop.Windows 28 | // (currently 16 for 10.0.22621.2). 29 | const int maxBaseCount = 16; 30 | 31 | // CastPtr`N.Generated.cs 32 | for (int baseCount = 0; baseCount <= maxBaseCount; ++baseCount) 33 | { 34 | GenerateFile( 35 | Path.Combine(outputDirPath, $"CastPtr`{baseCount + 1}.Generated.cs"), 36 | delegate (TextWriter writer) 37 | { 38 | writer.WriteLine("#nullable enable"); 39 | writer.WriteLine(); 40 | writer.WriteLine("using System;"); 41 | writer.WriteLine("using System.Runtime.CompilerServices;"); 42 | writer.WriteLine(); 43 | writer.WriteLine("namespace PointerToolkit;"); 44 | 45 | string typeList; 46 | { 47 | StringBuilder builder = new(); 48 | builder.Append("T"); 49 | for (int i = 1; i <= baseCount; ++i) 50 | { 51 | builder.Append($", TBase{i}"); 52 | } 53 | 54 | typeList = builder.ToString(); 55 | } 56 | 57 | writer.WriteLine(); 58 | writer.WriteLine($"public unsafe readonly ref struct CastPtr<{typeList}>"); 59 | writer.WriteLine(" where T : unmanaged"); 60 | for (int i = 1; i <= baseCount; ++i) 61 | { 62 | writer.WriteLine($" where TBase{i} : unmanaged"); 63 | } 64 | writer.WriteLine("{"); 65 | writer.WriteLine(" private readonly T* p;"); 66 | writer.WriteLine(); 67 | writer.WriteLine(" [MethodImpl(MethodImplOptions.AggressiveInlining)]"); 68 | writer.WriteLine(" private CastPtr(T* p) => this.p = p;"); 69 | writer.WriteLine(); 70 | writer.WriteLine(" [MethodImpl(MethodImplOptions.AggressiveInlining)]"); 71 | writer.WriteLine($" public static implicit operator CastPtr<{typeList}>(T* p) => *(CastPtr<{typeList}>*)&p;"); 72 | writer.WriteLine(); 73 | writer.WriteLine(" [MethodImpl(MethodImplOptions.AggressiveInlining)]"); 74 | writer.WriteLine($" public static implicit operator T*(CastPtr<{typeList}> ptr) => ptr.p;"); 75 | for (int i = 1; i <= baseCount; ++i) 76 | { 77 | writer.WriteLine(); 78 | writer.WriteLine(" [MethodImpl(MethodImplOptions.AggressiveInlining)]"); 79 | writer.WriteLine($" public static implicit operator TBase{i}*(CastPtr<{typeList}> ptr) => (TBase{i}*)ptr.p;"); 80 | } 81 | writer.WriteLine(); 82 | writer.WriteLine(" [MethodImpl(MethodImplOptions.AggressiveInlining)]"); 83 | writer.WriteLine($" public static implicit operator void*(CastPtr<{typeList}> ptr) => ptr.p;"); 84 | 85 | // Casts to Ptr. Commented out because I don't really have a good justification for including them yet. 86 | /* 87 | writer.WriteLine(); 88 | writer.WriteLine(" [MethodImpl(MethodImplOptions.AggressiveInlining)]"); 89 | writer.WriteLine($" public static implicit operator Ptr(CastPtr<{typeList}> ptr) => ptr.p;"); 90 | for (int i = 1; i <= baseCount; ++i) 91 | { 92 | writer.WriteLine(); 93 | writer.WriteLine(" [MethodImpl(MethodImplOptions.AggressiveInlining)]"); 94 | writer.WriteLine($" public static implicit operator Ptr(CastPtr<{typeList}> ptr) => (TBase{i}*)ptr.p;"); 95 | } 96 | writer.WriteLine(); 97 | writer.WriteLine(" [MethodImpl(MethodImplOptions.AggressiveInlining)]"); 98 | writer.WriteLine($" public static implicit operator Ptr(CastPtr<{typeList}> ptr) => ptr.p;"); 99 | */ 100 | 101 | // It could also be reasonable to add implicit casts from CastPtr to CastPtr etc. 102 | // But I'd rather wait until there's an actual need for something like that. Otherwise it's just adding code for the sake 103 | // of adding code. 104 | 105 | writer.WriteLine("}"); 106 | }); 107 | } 108 | } 109 | 110 | public static void GenerateFile(string filePath, Action writeCallback) 111 | { 112 | Console.Write($"{filePath} ... "); 113 | 114 | using MemoryStream stream = new MemoryStream(); 115 | using (TextWriter writer = new StreamWriter(stream, Encoding.UTF8, leaveOpen: true)) 116 | { 117 | writeCallback(writer); 118 | } 119 | 120 | byte[] newBytes = stream.GetBuffer(); 121 | Array.Resize(ref newBytes, checked((int)stream.Length)); 122 | 123 | if (File.Exists(filePath)) 124 | { 125 | byte[] oldBytes = File.ReadAllBytes(filePath); 126 | 127 | if (oldBytes.SequenceEqual(newBytes)) 128 | { 129 | // don't write anything 130 | Console.WriteLine("unchanged"); 131 | return; 132 | } 133 | } 134 | 135 | File.WriteAllBytes(filePath, newBytes); 136 | Console.WriteLine(); 137 | } 138 | } -------------------------------------------------------------------------------- /PointerToolkit.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.0.31912.275 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PointerToolkit", "PointerToolkit\PointerToolkit.csproj", "{66D535EB-2199-4A92-BFAB-CBE02CE72185}" 7 | ProjectSection(ProjectDependencies) = postProject 8 | {1D436E15-06D0-4F5B-8779-6C45910BD134} = {1D436E15-06D0-4F5B-8779-6C45910BD134} 9 | EndProjectSection 10 | EndProject 11 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PointerToolkit.Generator", "PointerToolkit.Generator\PointerToolkit.Generator.csproj", "{1D436E15-06D0-4F5B-8779-6C45910BD134}" 12 | EndProject 13 | Global 14 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 15 | Debug|Any CPU = Debug|Any CPU 16 | Release|Any CPU = Release|Any CPU 17 | EndGlobalSection 18 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 19 | {66D535EB-2199-4A92-BFAB-CBE02CE72185}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 20 | {66D535EB-2199-4A92-BFAB-CBE02CE72185}.Debug|Any CPU.Build.0 = Debug|Any CPU 21 | {66D535EB-2199-4A92-BFAB-CBE02CE72185}.Release|Any CPU.ActiveCfg = Release|Any CPU 22 | {66D535EB-2199-4A92-BFAB-CBE02CE72185}.Release|Any CPU.Build.0 = Release|Any CPU 23 | {1D436E15-06D0-4F5B-8779-6C45910BD134}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 24 | {1D436E15-06D0-4F5B-8779-6C45910BD134}.Debug|Any CPU.Build.0 = Debug|Any CPU 25 | {1D436E15-06D0-4F5B-8779-6C45910BD134}.Release|Any CPU.ActiveCfg = Release|Any CPU 26 | {1D436E15-06D0-4F5B-8779-6C45910BD134}.Release|Any CPU.Build.0 = Release|Any CPU 27 | EndGlobalSection 28 | GlobalSection(SolutionProperties) = preSolution 29 | HideSolutionNode = FALSE 30 | EndGlobalSection 31 | GlobalSection(ExtensibilityGlobals) = postSolution 32 | SolutionGuid = {789C5031-8505-40E6-ABD9-2E73C30EA60A} 33 | EndGlobalSection 34 | EndGlobal 35 | -------------------------------------------------------------------------------- /PointerToolkit/.gitignore: -------------------------------------------------------------------------------- 1 | bin 2 | obj 3 | PointerToolkit.csproj.user 4 | -------------------------------------------------------------------------------- /PointerToolkit/CastPtr`1.Generated.cs: -------------------------------------------------------------------------------- 1 | #nullable enable 2 | 3 | using System; 4 | using System.Runtime.CompilerServices; 5 | 6 | namespace PointerToolkit; 7 | 8 | public unsafe readonly ref struct CastPtr 9 | where T : unmanaged 10 | { 11 | private readonly T* p; 12 | 13 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 14 | private CastPtr(T* p) => this.p = p; 15 | 16 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 17 | public static implicit operator CastPtr(T* p) => *(CastPtr*)&p; 18 | 19 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 20 | public static implicit operator T*(CastPtr ptr) => ptr.p; 21 | 22 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 23 | public static implicit operator void*(CastPtr ptr) => ptr.p; 24 | } 25 | -------------------------------------------------------------------------------- /PointerToolkit/CastPtr`10.Generated.cs: -------------------------------------------------------------------------------- 1 | #nullable enable 2 | 3 | using System; 4 | using System.Runtime.CompilerServices; 5 | 6 | namespace PointerToolkit; 7 | 8 | public unsafe readonly ref struct CastPtr 9 | where T : unmanaged 10 | where TBase1 : unmanaged 11 | where TBase2 : unmanaged 12 | where TBase3 : unmanaged 13 | where TBase4 : unmanaged 14 | where TBase5 : unmanaged 15 | where TBase6 : unmanaged 16 | where TBase7 : unmanaged 17 | where TBase8 : unmanaged 18 | where TBase9 : unmanaged 19 | { 20 | private readonly T* p; 21 | 22 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 23 | private CastPtr(T* p) => this.p = p; 24 | 25 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 26 | public static implicit operator CastPtr(T* p) => *(CastPtr*)&p; 27 | 28 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 29 | public static implicit operator T*(CastPtr ptr) => ptr.p; 30 | 31 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 32 | public static implicit operator TBase1*(CastPtr ptr) => (TBase1*)ptr.p; 33 | 34 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 35 | public static implicit operator TBase2*(CastPtr ptr) => (TBase2*)ptr.p; 36 | 37 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 38 | public static implicit operator TBase3*(CastPtr ptr) => (TBase3*)ptr.p; 39 | 40 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 41 | public static implicit operator TBase4*(CastPtr ptr) => (TBase4*)ptr.p; 42 | 43 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 44 | public static implicit operator TBase5*(CastPtr ptr) => (TBase5*)ptr.p; 45 | 46 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 47 | public static implicit operator TBase6*(CastPtr ptr) => (TBase6*)ptr.p; 48 | 49 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 50 | public static implicit operator TBase7*(CastPtr ptr) => (TBase7*)ptr.p; 51 | 52 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 53 | public static implicit operator TBase8*(CastPtr ptr) => (TBase8*)ptr.p; 54 | 55 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 56 | public static implicit operator TBase9*(CastPtr ptr) => (TBase9*)ptr.p; 57 | 58 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 59 | public static implicit operator void*(CastPtr ptr) => ptr.p; 60 | } 61 | -------------------------------------------------------------------------------- /PointerToolkit/CastPtr`11.Generated.cs: -------------------------------------------------------------------------------- 1 | #nullable enable 2 | 3 | using System; 4 | using System.Runtime.CompilerServices; 5 | 6 | namespace PointerToolkit; 7 | 8 | public unsafe readonly ref struct CastPtr 9 | where T : unmanaged 10 | where TBase1 : unmanaged 11 | where TBase2 : unmanaged 12 | where TBase3 : unmanaged 13 | where TBase4 : unmanaged 14 | where TBase5 : unmanaged 15 | where TBase6 : unmanaged 16 | where TBase7 : unmanaged 17 | where TBase8 : unmanaged 18 | where TBase9 : unmanaged 19 | where TBase10 : unmanaged 20 | { 21 | private readonly T* p; 22 | 23 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 24 | private CastPtr(T* p) => this.p = p; 25 | 26 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 27 | public static implicit operator CastPtr(T* p) => *(CastPtr*)&p; 28 | 29 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 30 | public static implicit operator T*(CastPtr ptr) => ptr.p; 31 | 32 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 33 | public static implicit operator TBase1*(CastPtr ptr) => (TBase1*)ptr.p; 34 | 35 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 36 | public static implicit operator TBase2*(CastPtr ptr) => (TBase2*)ptr.p; 37 | 38 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 39 | public static implicit operator TBase3*(CastPtr ptr) => (TBase3*)ptr.p; 40 | 41 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 42 | public static implicit operator TBase4*(CastPtr ptr) => (TBase4*)ptr.p; 43 | 44 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 45 | public static implicit operator TBase5*(CastPtr ptr) => (TBase5*)ptr.p; 46 | 47 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 48 | public static implicit operator TBase6*(CastPtr ptr) => (TBase6*)ptr.p; 49 | 50 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 51 | public static implicit operator TBase7*(CastPtr ptr) => (TBase7*)ptr.p; 52 | 53 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 54 | public static implicit operator TBase8*(CastPtr ptr) => (TBase8*)ptr.p; 55 | 56 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 57 | public static implicit operator TBase9*(CastPtr ptr) => (TBase9*)ptr.p; 58 | 59 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 60 | public static implicit operator TBase10*(CastPtr ptr) => (TBase10*)ptr.p; 61 | 62 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 63 | public static implicit operator void*(CastPtr ptr) => ptr.p; 64 | } 65 | -------------------------------------------------------------------------------- /PointerToolkit/CastPtr`12.Generated.cs: -------------------------------------------------------------------------------- 1 | #nullable enable 2 | 3 | using System; 4 | using System.Runtime.CompilerServices; 5 | 6 | namespace PointerToolkit; 7 | 8 | public unsafe readonly ref struct CastPtr 9 | where T : unmanaged 10 | where TBase1 : unmanaged 11 | where TBase2 : unmanaged 12 | where TBase3 : unmanaged 13 | where TBase4 : unmanaged 14 | where TBase5 : unmanaged 15 | where TBase6 : unmanaged 16 | where TBase7 : unmanaged 17 | where TBase8 : unmanaged 18 | where TBase9 : unmanaged 19 | where TBase10 : unmanaged 20 | where TBase11 : unmanaged 21 | { 22 | private readonly T* p; 23 | 24 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 25 | private CastPtr(T* p) => this.p = p; 26 | 27 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 28 | public static implicit operator CastPtr(T* p) => *(CastPtr*)&p; 29 | 30 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 31 | public static implicit operator T*(CastPtr ptr) => ptr.p; 32 | 33 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 34 | public static implicit operator TBase1*(CastPtr ptr) => (TBase1*)ptr.p; 35 | 36 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 37 | public static implicit operator TBase2*(CastPtr ptr) => (TBase2*)ptr.p; 38 | 39 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 40 | public static implicit operator TBase3*(CastPtr ptr) => (TBase3*)ptr.p; 41 | 42 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 43 | public static implicit operator TBase4*(CastPtr ptr) => (TBase4*)ptr.p; 44 | 45 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 46 | public static implicit operator TBase5*(CastPtr ptr) => (TBase5*)ptr.p; 47 | 48 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 49 | public static implicit operator TBase6*(CastPtr ptr) => (TBase6*)ptr.p; 50 | 51 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 52 | public static implicit operator TBase7*(CastPtr ptr) => (TBase7*)ptr.p; 53 | 54 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 55 | public static implicit operator TBase8*(CastPtr ptr) => (TBase8*)ptr.p; 56 | 57 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 58 | public static implicit operator TBase9*(CastPtr ptr) => (TBase9*)ptr.p; 59 | 60 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 61 | public static implicit operator TBase10*(CastPtr ptr) => (TBase10*)ptr.p; 62 | 63 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 64 | public static implicit operator TBase11*(CastPtr ptr) => (TBase11*)ptr.p; 65 | 66 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 67 | public static implicit operator void*(CastPtr ptr) => ptr.p; 68 | } 69 | -------------------------------------------------------------------------------- /PointerToolkit/CastPtr`13.Generated.cs: -------------------------------------------------------------------------------- 1 | #nullable enable 2 | 3 | using System; 4 | using System.Runtime.CompilerServices; 5 | 6 | namespace PointerToolkit; 7 | 8 | public unsafe readonly ref struct CastPtr 9 | where T : unmanaged 10 | where TBase1 : unmanaged 11 | where TBase2 : unmanaged 12 | where TBase3 : unmanaged 13 | where TBase4 : unmanaged 14 | where TBase5 : unmanaged 15 | where TBase6 : unmanaged 16 | where TBase7 : unmanaged 17 | where TBase8 : unmanaged 18 | where TBase9 : unmanaged 19 | where TBase10 : unmanaged 20 | where TBase11 : unmanaged 21 | where TBase12 : unmanaged 22 | { 23 | private readonly T* p; 24 | 25 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 26 | private CastPtr(T* p) => this.p = p; 27 | 28 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 29 | public static implicit operator CastPtr(T* p) => *(CastPtr*)&p; 30 | 31 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 32 | public static implicit operator T*(CastPtr ptr) => ptr.p; 33 | 34 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 35 | public static implicit operator TBase1*(CastPtr ptr) => (TBase1*)ptr.p; 36 | 37 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 38 | public static implicit operator TBase2*(CastPtr ptr) => (TBase2*)ptr.p; 39 | 40 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 41 | public static implicit operator TBase3*(CastPtr ptr) => (TBase3*)ptr.p; 42 | 43 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 44 | public static implicit operator TBase4*(CastPtr ptr) => (TBase4*)ptr.p; 45 | 46 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 47 | public static implicit operator TBase5*(CastPtr ptr) => (TBase5*)ptr.p; 48 | 49 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 50 | public static implicit operator TBase6*(CastPtr ptr) => (TBase6*)ptr.p; 51 | 52 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 53 | public static implicit operator TBase7*(CastPtr ptr) => (TBase7*)ptr.p; 54 | 55 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 56 | public static implicit operator TBase8*(CastPtr ptr) => (TBase8*)ptr.p; 57 | 58 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 59 | public static implicit operator TBase9*(CastPtr ptr) => (TBase9*)ptr.p; 60 | 61 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 62 | public static implicit operator TBase10*(CastPtr ptr) => (TBase10*)ptr.p; 63 | 64 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 65 | public static implicit operator TBase11*(CastPtr ptr) => (TBase11*)ptr.p; 66 | 67 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 68 | public static implicit operator TBase12*(CastPtr ptr) => (TBase12*)ptr.p; 69 | 70 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 71 | public static implicit operator void*(CastPtr ptr) => ptr.p; 72 | } 73 | -------------------------------------------------------------------------------- /PointerToolkit/CastPtr`14.Generated.cs: -------------------------------------------------------------------------------- 1 | #nullable enable 2 | 3 | using System; 4 | using System.Runtime.CompilerServices; 5 | 6 | namespace PointerToolkit; 7 | 8 | public unsafe readonly ref struct CastPtr 9 | where T : unmanaged 10 | where TBase1 : unmanaged 11 | where TBase2 : unmanaged 12 | where TBase3 : unmanaged 13 | where TBase4 : unmanaged 14 | where TBase5 : unmanaged 15 | where TBase6 : unmanaged 16 | where TBase7 : unmanaged 17 | where TBase8 : unmanaged 18 | where TBase9 : unmanaged 19 | where TBase10 : unmanaged 20 | where TBase11 : unmanaged 21 | where TBase12 : unmanaged 22 | where TBase13 : unmanaged 23 | { 24 | private readonly T* p; 25 | 26 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 27 | private CastPtr(T* p) => this.p = p; 28 | 29 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 30 | public static implicit operator CastPtr(T* p) => *(CastPtr*)&p; 31 | 32 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 33 | public static implicit operator T*(CastPtr ptr) => ptr.p; 34 | 35 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 36 | public static implicit operator TBase1*(CastPtr ptr) => (TBase1*)ptr.p; 37 | 38 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 39 | public static implicit operator TBase2*(CastPtr ptr) => (TBase2*)ptr.p; 40 | 41 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 42 | public static implicit operator TBase3*(CastPtr ptr) => (TBase3*)ptr.p; 43 | 44 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 45 | public static implicit operator TBase4*(CastPtr ptr) => (TBase4*)ptr.p; 46 | 47 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 48 | public static implicit operator TBase5*(CastPtr ptr) => (TBase5*)ptr.p; 49 | 50 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 51 | public static implicit operator TBase6*(CastPtr ptr) => (TBase6*)ptr.p; 52 | 53 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 54 | public static implicit operator TBase7*(CastPtr ptr) => (TBase7*)ptr.p; 55 | 56 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 57 | public static implicit operator TBase8*(CastPtr ptr) => (TBase8*)ptr.p; 58 | 59 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 60 | public static implicit operator TBase9*(CastPtr ptr) => (TBase9*)ptr.p; 61 | 62 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 63 | public static implicit operator TBase10*(CastPtr ptr) => (TBase10*)ptr.p; 64 | 65 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 66 | public static implicit operator TBase11*(CastPtr ptr) => (TBase11*)ptr.p; 67 | 68 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 69 | public static implicit operator TBase12*(CastPtr ptr) => (TBase12*)ptr.p; 70 | 71 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 72 | public static implicit operator TBase13*(CastPtr ptr) => (TBase13*)ptr.p; 73 | 74 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 75 | public static implicit operator void*(CastPtr ptr) => ptr.p; 76 | } 77 | -------------------------------------------------------------------------------- /PointerToolkit/CastPtr`15.Generated.cs: -------------------------------------------------------------------------------- 1 | #nullable enable 2 | 3 | using System; 4 | using System.Runtime.CompilerServices; 5 | 6 | namespace PointerToolkit; 7 | 8 | public unsafe readonly ref struct CastPtr 9 | where T : unmanaged 10 | where TBase1 : unmanaged 11 | where TBase2 : unmanaged 12 | where TBase3 : unmanaged 13 | where TBase4 : unmanaged 14 | where TBase5 : unmanaged 15 | where TBase6 : unmanaged 16 | where TBase7 : unmanaged 17 | where TBase8 : unmanaged 18 | where TBase9 : unmanaged 19 | where TBase10 : unmanaged 20 | where TBase11 : unmanaged 21 | where TBase12 : unmanaged 22 | where TBase13 : unmanaged 23 | where TBase14 : unmanaged 24 | { 25 | private readonly T* p; 26 | 27 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 28 | private CastPtr(T* p) => this.p = p; 29 | 30 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 31 | public static implicit operator CastPtr(T* p) => *(CastPtr*)&p; 32 | 33 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 34 | public static implicit operator T*(CastPtr ptr) => ptr.p; 35 | 36 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 37 | public static implicit operator TBase1*(CastPtr ptr) => (TBase1*)ptr.p; 38 | 39 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 40 | public static implicit operator TBase2*(CastPtr ptr) => (TBase2*)ptr.p; 41 | 42 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 43 | public static implicit operator TBase3*(CastPtr ptr) => (TBase3*)ptr.p; 44 | 45 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 46 | public static implicit operator TBase4*(CastPtr ptr) => (TBase4*)ptr.p; 47 | 48 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 49 | public static implicit operator TBase5*(CastPtr ptr) => (TBase5*)ptr.p; 50 | 51 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 52 | public static implicit operator TBase6*(CastPtr ptr) => (TBase6*)ptr.p; 53 | 54 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 55 | public static implicit operator TBase7*(CastPtr ptr) => (TBase7*)ptr.p; 56 | 57 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 58 | public static implicit operator TBase8*(CastPtr ptr) => (TBase8*)ptr.p; 59 | 60 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 61 | public static implicit operator TBase9*(CastPtr ptr) => (TBase9*)ptr.p; 62 | 63 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 64 | public static implicit operator TBase10*(CastPtr ptr) => (TBase10*)ptr.p; 65 | 66 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 67 | public static implicit operator TBase11*(CastPtr ptr) => (TBase11*)ptr.p; 68 | 69 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 70 | public static implicit operator TBase12*(CastPtr ptr) => (TBase12*)ptr.p; 71 | 72 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 73 | public static implicit operator TBase13*(CastPtr ptr) => (TBase13*)ptr.p; 74 | 75 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 76 | public static implicit operator TBase14*(CastPtr ptr) => (TBase14*)ptr.p; 77 | 78 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 79 | public static implicit operator void*(CastPtr ptr) => ptr.p; 80 | } 81 | -------------------------------------------------------------------------------- /PointerToolkit/CastPtr`16.Generated.cs: -------------------------------------------------------------------------------- 1 | #nullable enable 2 | 3 | using System; 4 | using System.Runtime.CompilerServices; 5 | 6 | namespace PointerToolkit; 7 | 8 | public unsafe readonly ref struct CastPtr 9 | where T : unmanaged 10 | where TBase1 : unmanaged 11 | where TBase2 : unmanaged 12 | where TBase3 : unmanaged 13 | where TBase4 : unmanaged 14 | where TBase5 : unmanaged 15 | where TBase6 : unmanaged 16 | where TBase7 : unmanaged 17 | where TBase8 : unmanaged 18 | where TBase9 : unmanaged 19 | where TBase10 : unmanaged 20 | where TBase11 : unmanaged 21 | where TBase12 : unmanaged 22 | where TBase13 : unmanaged 23 | where TBase14 : unmanaged 24 | where TBase15 : unmanaged 25 | { 26 | private readonly T* p; 27 | 28 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 29 | private CastPtr(T* p) => this.p = p; 30 | 31 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 32 | public static implicit operator CastPtr(T* p) => *(CastPtr*)&p; 33 | 34 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 35 | public static implicit operator T*(CastPtr ptr) => ptr.p; 36 | 37 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 38 | public static implicit operator TBase1*(CastPtr ptr) => (TBase1*)ptr.p; 39 | 40 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 41 | public static implicit operator TBase2*(CastPtr ptr) => (TBase2*)ptr.p; 42 | 43 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 44 | public static implicit operator TBase3*(CastPtr ptr) => (TBase3*)ptr.p; 45 | 46 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 47 | public static implicit operator TBase4*(CastPtr ptr) => (TBase4*)ptr.p; 48 | 49 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 50 | public static implicit operator TBase5*(CastPtr ptr) => (TBase5*)ptr.p; 51 | 52 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 53 | public static implicit operator TBase6*(CastPtr ptr) => (TBase6*)ptr.p; 54 | 55 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 56 | public static implicit operator TBase7*(CastPtr ptr) => (TBase7*)ptr.p; 57 | 58 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 59 | public static implicit operator TBase8*(CastPtr ptr) => (TBase8*)ptr.p; 60 | 61 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 62 | public static implicit operator TBase9*(CastPtr ptr) => (TBase9*)ptr.p; 63 | 64 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 65 | public static implicit operator TBase10*(CastPtr ptr) => (TBase10*)ptr.p; 66 | 67 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 68 | public static implicit operator TBase11*(CastPtr ptr) => (TBase11*)ptr.p; 69 | 70 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 71 | public static implicit operator TBase12*(CastPtr ptr) => (TBase12*)ptr.p; 72 | 73 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 74 | public static implicit operator TBase13*(CastPtr ptr) => (TBase13*)ptr.p; 75 | 76 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 77 | public static implicit operator TBase14*(CastPtr ptr) => (TBase14*)ptr.p; 78 | 79 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 80 | public static implicit operator TBase15*(CastPtr ptr) => (TBase15*)ptr.p; 81 | 82 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 83 | public static implicit operator void*(CastPtr ptr) => ptr.p; 84 | } 85 | -------------------------------------------------------------------------------- /PointerToolkit/CastPtr`17.Generated.cs: -------------------------------------------------------------------------------- 1 | #nullable enable 2 | 3 | using System; 4 | using System.Runtime.CompilerServices; 5 | 6 | namespace PointerToolkit; 7 | 8 | public unsafe readonly ref struct CastPtr 9 | where T : unmanaged 10 | where TBase1 : unmanaged 11 | where TBase2 : unmanaged 12 | where TBase3 : unmanaged 13 | where TBase4 : unmanaged 14 | where TBase5 : unmanaged 15 | where TBase6 : unmanaged 16 | where TBase7 : unmanaged 17 | where TBase8 : unmanaged 18 | where TBase9 : unmanaged 19 | where TBase10 : unmanaged 20 | where TBase11 : unmanaged 21 | where TBase12 : unmanaged 22 | where TBase13 : unmanaged 23 | where TBase14 : unmanaged 24 | where TBase15 : unmanaged 25 | where TBase16 : unmanaged 26 | { 27 | private readonly T* p; 28 | 29 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 30 | private CastPtr(T* p) => this.p = p; 31 | 32 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 33 | public static implicit operator CastPtr(T* p) => *(CastPtr*)&p; 34 | 35 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 36 | public static implicit operator T*(CastPtr ptr) => ptr.p; 37 | 38 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 39 | public static implicit operator TBase1*(CastPtr ptr) => (TBase1*)ptr.p; 40 | 41 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 42 | public static implicit operator TBase2*(CastPtr ptr) => (TBase2*)ptr.p; 43 | 44 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 45 | public static implicit operator TBase3*(CastPtr ptr) => (TBase3*)ptr.p; 46 | 47 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 48 | public static implicit operator TBase4*(CastPtr ptr) => (TBase4*)ptr.p; 49 | 50 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 51 | public static implicit operator TBase5*(CastPtr ptr) => (TBase5*)ptr.p; 52 | 53 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 54 | public static implicit operator TBase6*(CastPtr ptr) => (TBase6*)ptr.p; 55 | 56 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 57 | public static implicit operator TBase7*(CastPtr ptr) => (TBase7*)ptr.p; 58 | 59 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 60 | public static implicit operator TBase8*(CastPtr ptr) => (TBase8*)ptr.p; 61 | 62 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 63 | public static implicit operator TBase9*(CastPtr ptr) => (TBase9*)ptr.p; 64 | 65 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 66 | public static implicit operator TBase10*(CastPtr ptr) => (TBase10*)ptr.p; 67 | 68 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 69 | public static implicit operator TBase11*(CastPtr ptr) => (TBase11*)ptr.p; 70 | 71 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 72 | public static implicit operator TBase12*(CastPtr ptr) => (TBase12*)ptr.p; 73 | 74 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 75 | public static implicit operator TBase13*(CastPtr ptr) => (TBase13*)ptr.p; 76 | 77 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 78 | public static implicit operator TBase14*(CastPtr ptr) => (TBase14*)ptr.p; 79 | 80 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 81 | public static implicit operator TBase15*(CastPtr ptr) => (TBase15*)ptr.p; 82 | 83 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 84 | public static implicit operator TBase16*(CastPtr ptr) => (TBase16*)ptr.p; 85 | 86 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 87 | public static implicit operator void*(CastPtr ptr) => ptr.p; 88 | } 89 | -------------------------------------------------------------------------------- /PointerToolkit/CastPtr`2.Generated.cs: -------------------------------------------------------------------------------- 1 | #nullable enable 2 | 3 | using System; 4 | using System.Runtime.CompilerServices; 5 | 6 | namespace PointerToolkit; 7 | 8 | public unsafe readonly ref struct CastPtr 9 | where T : unmanaged 10 | where TBase1 : unmanaged 11 | { 12 | private readonly T* p; 13 | 14 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 15 | private CastPtr(T* p) => this.p = p; 16 | 17 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 18 | public static implicit operator CastPtr(T* p) => *(CastPtr*)&p; 19 | 20 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 21 | public static implicit operator T*(CastPtr ptr) => ptr.p; 22 | 23 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 24 | public static implicit operator TBase1*(CastPtr ptr) => (TBase1*)ptr.p; 25 | 26 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 27 | public static implicit operator void*(CastPtr ptr) => ptr.p; 28 | } 29 | -------------------------------------------------------------------------------- /PointerToolkit/CastPtr`3.Generated.cs: -------------------------------------------------------------------------------- 1 | #nullable enable 2 | 3 | using System; 4 | using System.Runtime.CompilerServices; 5 | 6 | namespace PointerToolkit; 7 | 8 | public unsafe readonly ref struct CastPtr 9 | where T : unmanaged 10 | where TBase1 : unmanaged 11 | where TBase2 : unmanaged 12 | { 13 | private readonly T* p; 14 | 15 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 16 | private CastPtr(T* p) => this.p = p; 17 | 18 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 19 | public static implicit operator CastPtr(T* p) => *(CastPtr*)&p; 20 | 21 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 22 | public static implicit operator T*(CastPtr ptr) => ptr.p; 23 | 24 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 25 | public static implicit operator TBase1*(CastPtr ptr) => (TBase1*)ptr.p; 26 | 27 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 28 | public static implicit operator TBase2*(CastPtr ptr) => (TBase2*)ptr.p; 29 | 30 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 31 | public static implicit operator void*(CastPtr ptr) => ptr.p; 32 | } 33 | -------------------------------------------------------------------------------- /PointerToolkit/CastPtr`4.Generated.cs: -------------------------------------------------------------------------------- 1 | #nullable enable 2 | 3 | using System; 4 | using System.Runtime.CompilerServices; 5 | 6 | namespace PointerToolkit; 7 | 8 | public unsafe readonly ref struct CastPtr 9 | where T : unmanaged 10 | where TBase1 : unmanaged 11 | where TBase2 : unmanaged 12 | where TBase3 : unmanaged 13 | { 14 | private readonly T* p; 15 | 16 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 17 | private CastPtr(T* p) => this.p = p; 18 | 19 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 20 | public static implicit operator CastPtr(T* p) => *(CastPtr*)&p; 21 | 22 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 23 | public static implicit operator T*(CastPtr ptr) => ptr.p; 24 | 25 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 26 | public static implicit operator TBase1*(CastPtr ptr) => (TBase1*)ptr.p; 27 | 28 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 29 | public static implicit operator TBase2*(CastPtr ptr) => (TBase2*)ptr.p; 30 | 31 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 32 | public static implicit operator TBase3*(CastPtr ptr) => (TBase3*)ptr.p; 33 | 34 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 35 | public static implicit operator void*(CastPtr ptr) => ptr.p; 36 | } 37 | -------------------------------------------------------------------------------- /PointerToolkit/CastPtr`5.Generated.cs: -------------------------------------------------------------------------------- 1 | #nullable enable 2 | 3 | using System; 4 | using System.Runtime.CompilerServices; 5 | 6 | namespace PointerToolkit; 7 | 8 | public unsafe readonly ref struct CastPtr 9 | where T : unmanaged 10 | where TBase1 : unmanaged 11 | where TBase2 : unmanaged 12 | where TBase3 : unmanaged 13 | where TBase4 : unmanaged 14 | { 15 | private readonly T* p; 16 | 17 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 18 | private CastPtr(T* p) => this.p = p; 19 | 20 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 21 | public static implicit operator CastPtr(T* p) => *(CastPtr*)&p; 22 | 23 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 24 | public static implicit operator T*(CastPtr ptr) => ptr.p; 25 | 26 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 27 | public static implicit operator TBase1*(CastPtr ptr) => (TBase1*)ptr.p; 28 | 29 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 30 | public static implicit operator TBase2*(CastPtr ptr) => (TBase2*)ptr.p; 31 | 32 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 33 | public static implicit operator TBase3*(CastPtr ptr) => (TBase3*)ptr.p; 34 | 35 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 36 | public static implicit operator TBase4*(CastPtr ptr) => (TBase4*)ptr.p; 37 | 38 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 39 | public static implicit operator void*(CastPtr ptr) => ptr.p; 40 | } 41 | -------------------------------------------------------------------------------- /PointerToolkit/CastPtr`6.Generated.cs: -------------------------------------------------------------------------------- 1 | #nullable enable 2 | 3 | using System; 4 | using System.Runtime.CompilerServices; 5 | 6 | namespace PointerToolkit; 7 | 8 | public unsafe readonly ref struct CastPtr 9 | where T : unmanaged 10 | where TBase1 : unmanaged 11 | where TBase2 : unmanaged 12 | where TBase3 : unmanaged 13 | where TBase4 : unmanaged 14 | where TBase5 : unmanaged 15 | { 16 | private readonly T* p; 17 | 18 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 19 | private CastPtr(T* p) => this.p = p; 20 | 21 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 22 | public static implicit operator CastPtr(T* p) => *(CastPtr*)&p; 23 | 24 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 25 | public static implicit operator T*(CastPtr ptr) => ptr.p; 26 | 27 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 28 | public static implicit operator TBase1*(CastPtr ptr) => (TBase1*)ptr.p; 29 | 30 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 31 | public static implicit operator TBase2*(CastPtr ptr) => (TBase2*)ptr.p; 32 | 33 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 34 | public static implicit operator TBase3*(CastPtr ptr) => (TBase3*)ptr.p; 35 | 36 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 37 | public static implicit operator TBase4*(CastPtr ptr) => (TBase4*)ptr.p; 38 | 39 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 40 | public static implicit operator TBase5*(CastPtr ptr) => (TBase5*)ptr.p; 41 | 42 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 43 | public static implicit operator void*(CastPtr ptr) => ptr.p; 44 | } 45 | -------------------------------------------------------------------------------- /PointerToolkit/CastPtr`7.Generated.cs: -------------------------------------------------------------------------------- 1 | #nullable enable 2 | 3 | using System; 4 | using System.Runtime.CompilerServices; 5 | 6 | namespace PointerToolkit; 7 | 8 | public unsafe readonly ref struct CastPtr 9 | where T : unmanaged 10 | where TBase1 : unmanaged 11 | where TBase2 : unmanaged 12 | where TBase3 : unmanaged 13 | where TBase4 : unmanaged 14 | where TBase5 : unmanaged 15 | where TBase6 : unmanaged 16 | { 17 | private readonly T* p; 18 | 19 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 20 | private CastPtr(T* p) => this.p = p; 21 | 22 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 23 | public static implicit operator CastPtr(T* p) => *(CastPtr*)&p; 24 | 25 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 26 | public static implicit operator T*(CastPtr ptr) => ptr.p; 27 | 28 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 29 | public static implicit operator TBase1*(CastPtr ptr) => (TBase1*)ptr.p; 30 | 31 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 32 | public static implicit operator TBase2*(CastPtr ptr) => (TBase2*)ptr.p; 33 | 34 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 35 | public static implicit operator TBase3*(CastPtr ptr) => (TBase3*)ptr.p; 36 | 37 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 38 | public static implicit operator TBase4*(CastPtr ptr) => (TBase4*)ptr.p; 39 | 40 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 41 | public static implicit operator TBase5*(CastPtr ptr) => (TBase5*)ptr.p; 42 | 43 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 44 | public static implicit operator TBase6*(CastPtr ptr) => (TBase6*)ptr.p; 45 | 46 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 47 | public static implicit operator void*(CastPtr ptr) => ptr.p; 48 | } 49 | -------------------------------------------------------------------------------- /PointerToolkit/CastPtr`8.Generated.cs: -------------------------------------------------------------------------------- 1 | #nullable enable 2 | 3 | using System; 4 | using System.Runtime.CompilerServices; 5 | 6 | namespace PointerToolkit; 7 | 8 | public unsafe readonly ref struct CastPtr 9 | where T : unmanaged 10 | where TBase1 : unmanaged 11 | where TBase2 : unmanaged 12 | where TBase3 : unmanaged 13 | where TBase4 : unmanaged 14 | where TBase5 : unmanaged 15 | where TBase6 : unmanaged 16 | where TBase7 : unmanaged 17 | { 18 | private readonly T* p; 19 | 20 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 21 | private CastPtr(T* p) => this.p = p; 22 | 23 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 24 | public static implicit operator CastPtr(T* p) => *(CastPtr*)&p; 25 | 26 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 27 | public static implicit operator T*(CastPtr ptr) => ptr.p; 28 | 29 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 30 | public static implicit operator TBase1*(CastPtr ptr) => (TBase1*)ptr.p; 31 | 32 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 33 | public static implicit operator TBase2*(CastPtr ptr) => (TBase2*)ptr.p; 34 | 35 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 36 | public static implicit operator TBase3*(CastPtr ptr) => (TBase3*)ptr.p; 37 | 38 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 39 | public static implicit operator TBase4*(CastPtr ptr) => (TBase4*)ptr.p; 40 | 41 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 42 | public static implicit operator TBase5*(CastPtr ptr) => (TBase5*)ptr.p; 43 | 44 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 45 | public static implicit operator TBase6*(CastPtr ptr) => (TBase6*)ptr.p; 46 | 47 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 48 | public static implicit operator TBase7*(CastPtr ptr) => (TBase7*)ptr.p; 49 | 50 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 51 | public static implicit operator void*(CastPtr ptr) => ptr.p; 52 | } 53 | -------------------------------------------------------------------------------- /PointerToolkit/CastPtr`9.Generated.cs: -------------------------------------------------------------------------------- 1 | #nullable enable 2 | 3 | using System; 4 | using System.Runtime.CompilerServices; 5 | 6 | namespace PointerToolkit; 7 | 8 | public unsafe readonly ref struct CastPtr 9 | where T : unmanaged 10 | where TBase1 : unmanaged 11 | where TBase2 : unmanaged 12 | where TBase3 : unmanaged 13 | where TBase4 : unmanaged 14 | where TBase5 : unmanaged 15 | where TBase6 : unmanaged 16 | where TBase7 : unmanaged 17 | where TBase8 : unmanaged 18 | { 19 | private readonly T* p; 20 | 21 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 22 | private CastPtr(T* p) => this.p = p; 23 | 24 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 25 | public static implicit operator CastPtr(T* p) => *(CastPtr*)&p; 26 | 27 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 28 | public static implicit operator T*(CastPtr ptr) => ptr.p; 29 | 30 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 31 | public static implicit operator TBase1*(CastPtr ptr) => (TBase1*)ptr.p; 32 | 33 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 34 | public static implicit operator TBase2*(CastPtr ptr) => (TBase2*)ptr.p; 35 | 36 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 37 | public static implicit operator TBase3*(CastPtr ptr) => (TBase3*)ptr.p; 38 | 39 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 40 | public static implicit operator TBase4*(CastPtr ptr) => (TBase4*)ptr.p; 41 | 42 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 43 | public static implicit operator TBase5*(CastPtr ptr) => (TBase5*)ptr.p; 44 | 45 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 46 | public static implicit operator TBase6*(CastPtr ptr) => (TBase6*)ptr.p; 47 | 48 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 49 | public static implicit operator TBase7*(CastPtr ptr) => (TBase7*)ptr.p; 50 | 51 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 52 | public static implicit operator TBase8*(CastPtr ptr) => (TBase8*)ptr.p; 53 | 54 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 55 | public static implicit operator void*(CastPtr ptr) => ptr.p; 56 | } 57 | -------------------------------------------------------------------------------- /PointerToolkit/FodyWeavers.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /PointerToolkit/FodyWeavers.xsd: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Defines if sequence points should be generated for each emitted IL instruction. Default value: Debug 12 | 13 | 14 | 15 | 16 | 17 | Insert sequence points in Debug builds only (this is the default). 18 | 19 | 20 | 21 | 22 | Insert sequence points in Release builds only. 23 | 24 | 25 | 26 | 27 | Always insert sequence points. 28 | 29 | 30 | 31 | 32 | Never insert sequence points. 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | Defines how warnings should be handled. Default value: Warnings 41 | 42 | 43 | 44 | 45 | 46 | Emit build warnings (this is the default). 47 | 48 | 49 | 50 | 51 | Do not emit warnings. 52 | 53 | 54 | 55 | 56 | Treat warnings as errors. 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed. 68 | 69 | 70 | 71 | 72 | A comma-separated list of error codes that can be safely ignored in assembly verification. 73 | 74 | 75 | 76 | 77 | 'false' to turn off automatic generation of the XML Schema file. 78 | 79 | 80 | 81 | 82 | -------------------------------------------------------------------------------- /PointerToolkit/InterlockedPtr.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.CompilerServices; 3 | using System.Threading; 4 | 5 | namespace PointerToolkit; 6 | 7 | public static unsafe class InterlockedPtr 8 | { 9 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 10 | public static void* CompareExchange(ref void* location1, void* value, void* comparand) 11 | { 12 | return (void*)Interlocked.CompareExchange(ref UnsafePtr.As(ref location1), (IntPtr)value, (IntPtr)comparand); 13 | } 14 | 15 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 16 | public static void** CompareExchange(ref void** location1, void** value, void** comparand) 17 | { 18 | return (void**)Interlocked.CompareExchange(ref UnsafePtr.As(ref location1), (IntPtr)value, (IntPtr)comparand); 19 | } 20 | 21 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 22 | public static void*** CompareExchange(ref void*** location1, void*** value, void*** comparand) 23 | { 24 | return (void***)Interlocked.CompareExchange(ref UnsafePtr.As(ref location1), (IntPtr)value, (IntPtr)comparand); 25 | } 26 | 27 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 28 | public static T* CompareExchange(ref T* location1, T* value, T* comparand) 29 | where T : unmanaged 30 | { 31 | return (T*)Interlocked.CompareExchange(ref UnsafePtr.As(ref location1), (IntPtr)value, (IntPtr)comparand); 32 | } 33 | 34 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 35 | public static T** CompareExchange(ref T** location1, T** value, T** comparand) 36 | where T : unmanaged 37 | { 38 | return (T**)Interlocked.CompareExchange(ref UnsafePtr.As(ref location1), (IntPtr)value, (IntPtr)comparand); 39 | } 40 | 41 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 42 | public static T*** CompareExchange(ref T*** location1, T*** value, T*** comparand) 43 | where T : unmanaged 44 | { 45 | return (T***)Interlocked.CompareExchange(ref UnsafePtr.As(ref location1), (IntPtr)value, (IntPtr)comparand); 46 | } 47 | 48 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 49 | public static void* Exchange(ref void* location1, void* value) 50 | { 51 | return (void*)Interlocked.Exchange(ref UnsafePtr.As(ref location1), (IntPtr)value); 52 | } 53 | 54 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 55 | public static void** Exchange(ref void** location1, void** value) 56 | { 57 | return (void**)Interlocked.Exchange(ref UnsafePtr.As(ref location1), (IntPtr)value); 58 | } 59 | 60 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 61 | public static void*** Exchange(ref void*** location1, void*** value) 62 | { 63 | return (void***)Interlocked.Exchange(ref UnsafePtr.As(ref location1), (IntPtr)value); 64 | } 65 | 66 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 67 | public static T* Exchange(ref T* location1, T* value) 68 | where T : unmanaged 69 | { 70 | return (T*)Interlocked.Exchange(ref UnsafePtr.As(ref location1), (IntPtr)value); 71 | } 72 | 73 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 74 | public static T** Exchange(ref T** location1, T** value) 75 | where T : unmanaged 76 | { 77 | return (T**)Interlocked.Exchange(ref UnsafePtr.As(ref location1), (IntPtr)value); 78 | } 79 | 80 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 81 | public static T*** Exchange(ref T*** location1, T*** value) 82 | where T : unmanaged 83 | { 84 | return (T***)Interlocked.Exchange(ref UnsafePtr.As(ref location1), (IntPtr)value); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /PointerToolkit/PointerToolkit.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | net6.0 4 | PointerToolkit 5 | enable 6 | strict 7 | true 8 | True 9 | OnOutputUpdated 10 | True 11 | Copyright ©️ Rick Brewster 12 | https://github.com/rickbrew/PointerToolkit 13 | https://github.com/rickbrew/PointerToolkit 14 | interlocked;pointer;pointers;unsafe;volatile 15 | 1.0.1 16 | $(VersionPrefix) 17 | README.md 18 | 19 | 20 | MIT 21 | Provides structs that wrap pointers, as well as Unsafe, Interlocked, and Volatile operations on ref pointers. 22 | Rick Brewster 23 | 24 | 25 | True 26 | 27 | 28 | True 29 | 30 | 31 | 32 | README.md 33 | True 34 | \ 35 | 36 | 37 | 38 | 39 | all 40 | runtime; build; native; contentfiles; analyzers; buildtransitive 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /PointerToolkit/Ptr.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.CompilerServices; 3 | 4 | namespace PointerToolkit; 5 | 6 | public unsafe readonly struct Ptr 7 | : IEquatable, 8 | IComparable, 9 | IFormattable 10 | { 11 | private readonly void* p; 12 | 13 | private Ptr(void* p) => this.p = p; 14 | 15 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 16 | public int CompareTo(Ptr other) => ((IntPtr)this.p).CompareTo(other); 17 | 18 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 19 | public override bool Equals(object? other) => (other is Ptr p) && (this.p == p.p); 20 | 21 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 22 | public bool Equals(Ptr other) => this.p == other.p; 23 | 24 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 25 | public void* Get() => this.p; 26 | 27 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 28 | public override int GetHashCode() => ((IntPtr)this.p).GetHashCode(); 29 | 30 | public override string ToString() 31 | { 32 | return ((UIntPtr)this.p).ToString(sizeof(IntPtr) == 4 ? "X8" : "X16"); 33 | } 34 | 35 | public string ToString(string? format, IFormatProvider? formatProvider) 36 | { 37 | return ((UIntPtr)this.p).ToString(format, formatProvider); 38 | } 39 | 40 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 41 | public static implicit operator Ptr(void* p) => UnsafePtr.As(ref p); 42 | 43 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 44 | public static implicit operator Ptr(void** p) => UnsafePtr.As(ref p); 45 | 46 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 47 | public static implicit operator Ptr(void*** p) => UnsafePtr.As(ref p); 48 | 49 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 50 | public static implicit operator Ptr(PtrPtr ptr) => Unsafe.As(ref ptr); 51 | 52 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 53 | public static implicit operator Ptr(PtrPtrPtr ptr) => Unsafe.As(ref ptr); 54 | 55 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 56 | public static implicit operator Ptr(IntPtr intPtr) => Unsafe.As(ref intPtr); 57 | 58 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 59 | public static implicit operator IntPtr(Ptr ptr) => Unsafe.As(ref ptr); 60 | 61 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 62 | public static implicit operator Ptr(UIntPtr intPtr) => Unsafe.As(ref intPtr); 63 | 64 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 65 | public static implicit operator UIntPtr(Ptr ptr) => Unsafe.As(ref ptr); 66 | 67 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 68 | public static implicit operator void*(Ptr ptr) => ptr.p; 69 | 70 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 71 | public static explicit operator void**(Ptr ptr) => (void**)ptr.p; 72 | 73 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 74 | public static explicit operator void***(Ptr ptr) => (void***)ptr.p; 75 | 76 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 77 | public static bool operator ==(Ptr ptr1, Ptr ptr2) => ptr1.p == ptr2.p; 78 | 79 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 80 | public static bool operator !=(Ptr ptr1, Ptr ptr2) => ptr1.p != ptr2.p; 81 | 82 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 83 | public static bool operator >(Ptr ptr1, Ptr ptr2) => ptr1.p > ptr2.p; 84 | 85 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 86 | public static bool operator <(Ptr ptr1, Ptr ptr2) => ptr1.p < ptr2.p; 87 | 88 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 89 | public static bool operator >=(Ptr ptr1, Ptr ptr2) => ptr1.p >= ptr2.p; 90 | 91 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 92 | public static bool operator <=(Ptr ptr1, Ptr ptr2) => ptr1.p <= ptr2.p; 93 | } 94 | -------------------------------------------------------------------------------- /PointerToolkit/PtrOperators.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.CompilerServices; 3 | 4 | namespace PointerToolkit; 5 | 6 | /// 7 | /// These methods are meant to be used in conjunction with a global `global using static PointerToolkit.PtrOperators;`. 8 | /// They make it easy to pass a pointer into places where you can't normally use them, such as in generics and delegate, 9 | /// without having to specify the Ptr type itself. 10 | /// 11 | public static unsafe class PtrOperators 12 | { 13 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 14 | public static Ptr __ptr(void* p) => (Ptr)p; 15 | 16 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 17 | public static PtrPtr __ptr(void** p) => (PtrPtr)p; 18 | 19 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 20 | public static PtrPtrPtr __ptr(void*** p) => (PtrPtrPtr)p; 21 | 22 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 23 | public static Ptr __ptr(T* p) where T : unmanaged => (Ptr)p; 24 | 25 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 26 | public static PtrPtr __ptr(T** p) where T : unmanaged => (PtrPtr)p; 27 | 28 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 29 | public static PtrPtrPtr __ptr(T*** p) where T : unmanaged => (PtrPtrPtr)p; 30 | } -------------------------------------------------------------------------------- /PointerToolkit/PtrPtr.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.CompilerServices; 3 | 4 | namespace PointerToolkit; 5 | 6 | public unsafe readonly struct PtrPtr 7 | : IEquatable, 8 | IComparable, 9 | IFormattable 10 | { 11 | private readonly void** p; 12 | 13 | private PtrPtr(void** p) => this.p = p; 14 | 15 | public ref Ptr Value 16 | { 17 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 18 | get => ref UnsafePtr.As(ref *this.p); 19 | } 20 | 21 | public ref Ptr this[int index] 22 | { 23 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 24 | get => ref UnsafePtr.As(ref *(this.p + index)); 25 | } 26 | 27 | public ref Ptr this[long index] 28 | { 29 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 30 | get => ref UnsafePtr.As(ref *(this.p + index)); 31 | } 32 | 33 | public ref Ptr this[nint index] 34 | { 35 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 36 | get => ref UnsafePtr.As(ref *(this.p + index)); 37 | } 38 | 39 | public ref Ptr this[uint index] 40 | { 41 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 42 | get => ref UnsafePtr.As(ref *(this.p + index)); 43 | } 44 | 45 | public ref Ptr this[ulong index] 46 | { 47 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 48 | get => ref UnsafePtr.As(ref *(this.p + index)); 49 | } 50 | 51 | public ref Ptr this[nuint index] 52 | { 53 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 54 | get => ref UnsafePtr.As(ref *(this.p + index)); 55 | } 56 | 57 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 58 | public int CompareTo(PtrPtr other) => ((IntPtr)this.p).CompareTo(other); 59 | 60 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 61 | public override bool Equals(object? other) => (other is PtrPtr p) && (this.p == p.p); 62 | 63 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 64 | public bool Equals(PtrPtr other) => this.p == other.p; 65 | 66 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 67 | public void** Get() => this.p; 68 | 69 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 70 | public override int GetHashCode() => ((IntPtr)this.p).GetHashCode(); 71 | 72 | public override string ToString() 73 | { 74 | return ((UIntPtr)this.p).ToString(sizeof(IntPtr) == 4 ? "X8" : "X16"); 75 | } 76 | 77 | public string ToString(string? format, IFormatProvider? formatProvider) 78 | { 79 | return ((UIntPtr)this.p).ToString(format, formatProvider); 80 | } 81 | 82 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 83 | public static explicit operator PtrPtr(void* p) => UnsafePtr.As(ref p); 84 | 85 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 86 | public static implicit operator PtrPtr(void** p) => UnsafePtr.As(ref p); 87 | 88 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 89 | public static explicit operator PtrPtr(void*** p) => UnsafePtr.As(ref p); 90 | 91 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 92 | public static explicit operator PtrPtr(Ptr ptr) => Unsafe.As(ref ptr); 93 | 94 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 95 | public static explicit operator PtrPtr(PtrPtrPtr ptr) => Unsafe.As(ref ptr); 96 | 97 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 98 | public static explicit operator PtrPtr(IntPtr intPtr) => Unsafe.As(ref intPtr); 99 | 100 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 101 | public static implicit operator IntPtr(PtrPtr ptr) => Unsafe.As(ref ptr); 102 | 103 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 104 | public static explicit operator PtrPtr(UIntPtr intPtr) => Unsafe.As(ref intPtr); 105 | 106 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 107 | public static implicit operator UIntPtr(PtrPtr ptr) => Unsafe.As(ref ptr); 108 | 109 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 110 | public static implicit operator void*(PtrPtr ptr) => ptr.p; 111 | 112 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 113 | public static implicit operator void**(PtrPtr ptr) => ptr.p; 114 | 115 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 116 | public static explicit operator void***(PtrPtr ptr) => (void***)ptr.p; 117 | 118 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 119 | public static bool operator ==(PtrPtr ptr1, PtrPtr ptr2) => ptr1.p == ptr2.p; 120 | 121 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 122 | public static bool operator !=(PtrPtr ptr1, PtrPtr ptr2) => ptr1.p != ptr2.p; 123 | 124 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 125 | public static bool operator >(PtrPtr ptr1, PtrPtr ptr2) => ptr1.p > ptr2.p; 126 | 127 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 128 | public static bool operator <(PtrPtr ptr1, PtrPtr ptr2) => ptr1.p < ptr2.p; 129 | 130 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 131 | public static bool operator >=(PtrPtr ptr1, PtrPtr ptr2) => ptr1.p >= ptr2.p; 132 | 133 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 134 | public static bool operator <=(PtrPtr ptr1, PtrPtr ptr2) => ptr1.p <= ptr2.p; 135 | 136 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 137 | public static PtrPtr operator +(PtrPtr ptr, int count) => ptr.p + count; 138 | 139 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 140 | public static PtrPtr operator +(int count, PtrPtr ptr) => count + ptr.p; 141 | 142 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 143 | public static PtrPtr operator +(PtrPtr ptr, long count) => ptr.p + count; 144 | 145 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 146 | public static PtrPtr operator +(long count, PtrPtr ptr) => count + ptr.p; 147 | 148 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 149 | public static PtrPtr operator +(PtrPtr ptr, nint count) => ptr.p + count; 150 | 151 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 152 | public static PtrPtr operator +(nint count, PtrPtr ptr) => count + ptr.p; 153 | 154 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 155 | public static PtrPtr operator +(PtrPtr ptr, uint count) => ptr.p + count; 156 | 157 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 158 | public static PtrPtr operator +(uint count, PtrPtr ptr) => count + ptr.p; 159 | 160 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 161 | public static PtrPtr operator +(PtrPtr ptr, ulong count) => ptr.p + count; 162 | 163 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 164 | public static PtrPtr operator +(ulong count, PtrPtr ptr) => count + ptr.p; 165 | 166 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 167 | public static PtrPtr operator +(PtrPtr ptr, nuint count) => ptr.p + count; 168 | 169 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 170 | public static PtrPtr operator +(nuint count, PtrPtr ptr) => count + ptr.p; 171 | 172 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 173 | public static PtrPtr operator -(PtrPtr ptr, int count) => ptr.p - count; 174 | 175 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 176 | public static PtrPtr operator -(PtrPtr ptr, long count) => ptr.p - count; 177 | 178 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 179 | public static PtrPtr operator -(PtrPtr ptr, nint count) => ptr.p - count; 180 | 181 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 182 | public static PtrPtr operator -(PtrPtr ptr, uint count) => ptr.p - count; 183 | 184 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 185 | public static PtrPtr operator -(PtrPtr ptr, ulong count) => ptr.p - count; 186 | 187 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 188 | public static PtrPtr operator -(PtrPtr ptr, nuint count) => ptr.p - count; 189 | 190 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 191 | public static long operator -(PtrPtr ptr1, PtrPtr ptr2) => ptr1.p - ptr2.p; 192 | } 193 | -------------------------------------------------------------------------------- /PointerToolkit/PtrPtrPtr.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.CompilerServices; 3 | 4 | namespace PointerToolkit; 5 | 6 | public unsafe readonly struct PtrPtrPtr 7 | : IEquatable, 8 | IComparable, 9 | IFormattable 10 | { 11 | private readonly void*** p; 12 | 13 | private PtrPtrPtr(void*** p) => this.p = p; 14 | 15 | public ref PtrPtr Value 16 | { 17 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 18 | get => ref UnsafePtr.As(ref *this.p); 19 | } 20 | 21 | public ref PtrPtr this[int index] 22 | { 23 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 24 | get => ref UnsafePtr.As(ref *(this.p + index)); 25 | } 26 | 27 | public ref PtrPtr this[long index] 28 | { 29 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 30 | get => ref UnsafePtr.As(ref *(this.p + index)); 31 | } 32 | 33 | public ref PtrPtr this[nint index] 34 | { 35 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 36 | get => ref UnsafePtr.As(ref *(this.p + index)); 37 | } 38 | 39 | public ref PtrPtr this[uint index] 40 | { 41 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 42 | get => ref UnsafePtr.As(ref *(this.p + index)); 43 | } 44 | 45 | public ref PtrPtr this[ulong index] 46 | { 47 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 48 | get => ref UnsafePtr.As(ref *(this.p + index)); 49 | } 50 | 51 | public ref PtrPtr this[nuint index] 52 | { 53 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 54 | get => ref UnsafePtr.As(ref *(this.p + index)); 55 | } 56 | 57 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 58 | public int CompareTo(PtrPtrPtr other) => ((IntPtr)this.p).CompareTo(other); 59 | 60 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 61 | public override bool Equals(object? other) => (other is PtrPtrPtr p) && (this.p == p.p); 62 | 63 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 64 | public bool Equals(PtrPtrPtr other) => this.p == other.p; 65 | 66 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 67 | public void*** Get() => this.p; 68 | 69 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 70 | public override int GetHashCode() => ((IntPtr)this.p).GetHashCode(); 71 | 72 | public override string ToString() 73 | { 74 | return ((UIntPtr)this.p).ToString(sizeof(IntPtr) == 4 ? "X8" : "X16"); 75 | } 76 | 77 | public string ToString(string? format, IFormatProvider? formatProvider) 78 | { 79 | return ((UIntPtr)this.p).ToString(format, formatProvider); 80 | } 81 | 82 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 83 | public static explicit operator PtrPtrPtr(void* p) => UnsafePtr.As(ref p); 84 | 85 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 86 | public static explicit operator PtrPtrPtr(void** p) => UnsafePtr.As(ref p); 87 | 88 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 89 | public static implicit operator PtrPtrPtr(void*** p) => UnsafePtr.As(ref p); 90 | 91 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 92 | public static explicit operator PtrPtrPtr(Ptr ptr) => Unsafe.As(ref ptr); 93 | 94 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 95 | public static explicit operator PtrPtrPtr(PtrPtr ptr) => Unsafe.As(ref ptr); 96 | 97 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 98 | public static explicit operator PtrPtrPtr(IntPtr intPtr) => Unsafe.As(ref intPtr); 99 | 100 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 101 | public static implicit operator IntPtr(PtrPtrPtr ptr) => Unsafe.As(ref ptr); 102 | 103 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 104 | public static explicit operator PtrPtrPtr(UIntPtr intPtr) => Unsafe.As(ref intPtr); 105 | 106 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 107 | public static implicit operator UIntPtr(PtrPtrPtr ptr) => Unsafe.As(ref ptr); 108 | 109 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 110 | public static implicit operator void*(PtrPtrPtr ptr) => ptr.p; 111 | 112 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 113 | public static explicit operator void**(PtrPtrPtr ptr) => (void**)ptr.p; 114 | 115 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 116 | public static implicit operator void***(PtrPtrPtr ptr) => ptr.p; 117 | 118 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 119 | public static bool operator ==(PtrPtrPtr ptr1, PtrPtrPtr ptr3) => ptr1.p == ptr3.p; 120 | 121 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 122 | public static bool operator !=(PtrPtrPtr ptr1, PtrPtrPtr ptr3) => ptr1.p != ptr3.p; 123 | 124 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 125 | public static bool operator >(PtrPtrPtr ptr1, PtrPtrPtr ptr2) => ptr1.p > ptr2.p; 126 | 127 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 128 | public static bool operator <(PtrPtrPtr ptr1, PtrPtrPtr ptr2) => ptr1.p < ptr2.p; 129 | 130 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 131 | public static bool operator >=(PtrPtrPtr ptr1, PtrPtrPtr ptr2) => ptr1.p >= ptr2.p; 132 | 133 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 134 | public static bool operator <=(PtrPtrPtr ptr1, PtrPtrPtr ptr2) => ptr1.p <= ptr2.p; 135 | 136 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 137 | public static PtrPtrPtr operator +(PtrPtrPtr ptr, int count) => ptr.p + count; 138 | 139 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 140 | public static PtrPtrPtr operator +(int count, PtrPtrPtr ptr) => count + ptr.p; 141 | 142 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 143 | public static PtrPtrPtr operator +(PtrPtrPtr ptr, long count) => ptr.p + count; 144 | 145 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 146 | public static PtrPtrPtr operator +(long count, PtrPtrPtr ptr) => count + ptr.p; 147 | 148 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 149 | public static PtrPtrPtr operator +(PtrPtrPtr ptr, nint count) => ptr.p + count; 150 | 151 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 152 | public static PtrPtrPtr operator +(nint count, PtrPtrPtr ptr) => count + ptr.p; 153 | 154 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 155 | public static PtrPtrPtr operator +(PtrPtrPtr ptr, uint count) => ptr.p + count; 156 | 157 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 158 | public static PtrPtrPtr operator +(uint count, PtrPtrPtr ptr) => count + ptr.p; 159 | 160 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 161 | public static PtrPtrPtr operator +(PtrPtrPtr ptr, ulong count) => ptr.p + count; 162 | 163 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 164 | public static PtrPtrPtr operator +(ulong count, PtrPtrPtr ptr) => count + ptr.p; 165 | 166 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 167 | public static PtrPtrPtr operator +(PtrPtrPtr ptr, nuint count) => ptr.p + count; 168 | 169 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 170 | public static PtrPtrPtr operator +(nuint count, PtrPtrPtr ptr) => count + ptr.p; 171 | 172 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 173 | public static PtrPtrPtr operator -(PtrPtrPtr ptr, int count) => ptr.p - count; 174 | 175 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 176 | public static PtrPtrPtr operator -(PtrPtrPtr ptr, long count) => ptr.p - count; 177 | 178 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 179 | public static PtrPtrPtr operator -(PtrPtrPtr ptr, nint count) => ptr.p - count; 180 | 181 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 182 | public static PtrPtrPtr operator -(PtrPtrPtr ptr, uint count) => ptr.p - count; 183 | 184 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 185 | public static PtrPtrPtr operator -(PtrPtrPtr ptr, ulong count) => ptr.p - count; 186 | 187 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 188 | public static PtrPtrPtr operator -(PtrPtrPtr ptr, nuint count) => ptr.p - count; 189 | 190 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 191 | public static long operator -(PtrPtrPtr ptr1, PtrPtrPtr ptr2) => ptr1.p - ptr2.p; 192 | } 193 | -------------------------------------------------------------------------------- /PointerToolkit/PtrPtrPtr`1.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.CompilerServices; 3 | 4 | namespace PointerToolkit; 5 | 6 | public unsafe readonly struct PtrPtrPtr 7 | : IEquatable>, 8 | IComparable>, 9 | IFormattable 10 | where T : unmanaged 11 | { 12 | private readonly T*** p; 13 | 14 | private PtrPtrPtr(T*** p) => this.p = p; 15 | 16 | public ref PtrPtr Value 17 | { 18 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 19 | get => ref UnsafePtr.As>(ref *this.p); 20 | } 21 | 22 | public ref PtrPtr this[int index] 23 | { 24 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 25 | get => ref UnsafePtr.As>(ref *(this.p + index)); 26 | } 27 | 28 | public ref PtrPtr this[long index] 29 | { 30 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 31 | get => ref UnsafePtr.As>(ref *(this.p + index)); 32 | } 33 | 34 | public ref PtrPtr this[nint index] 35 | { 36 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 37 | get => ref UnsafePtr.As>(ref *(this.p + index)); 38 | } 39 | 40 | public ref PtrPtr this[uint index] 41 | { 42 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 43 | get => ref UnsafePtr.As>(ref *(this.p + index)); 44 | } 45 | 46 | public ref PtrPtr this[ulong index] 47 | { 48 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 49 | get => ref UnsafePtr.As>(ref *(this.p + index)); 50 | } 51 | 52 | public ref PtrPtr this[nuint index] 53 | { 54 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 55 | get => ref UnsafePtr.As>(ref *(this.p + index)); 56 | } 57 | 58 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 59 | public int CompareTo(PtrPtrPtr other) => ((IntPtr)this.p).CompareTo(other); 60 | 61 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 62 | public override bool Equals(object? other) => (other is PtrPtrPtr p) && (this.p == p.p); 63 | 64 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 65 | public bool Equals(PtrPtrPtr other) => this.p == other.p; 66 | 67 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 68 | public T*** Get() => this.p; 69 | 70 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 71 | public override int GetHashCode() => ((IntPtr)this.p).GetHashCode(); 72 | 73 | public override string ToString() 74 | { 75 | return ((UIntPtr)this.p).ToString(sizeof(IntPtr) == 4 ? "X8" : "X16"); 76 | } 77 | 78 | public string ToString(string? format, IFormatProvider? formatProvider) 79 | { 80 | return ((UIntPtr)this.p).ToString(format, formatProvider); 81 | } 82 | 83 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 84 | public static explicit operator PtrPtrPtr(T* p) => UnsafePtr.As>(ref p); 85 | 86 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 87 | public static explicit operator PtrPtrPtr(T** p) => UnsafePtr.As>(ref p); 88 | 89 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 90 | public static implicit operator PtrPtrPtr(T*** p) => UnsafePtr.As>(ref p); 91 | 92 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 93 | public static explicit operator PtrPtrPtr(void* p) => UnsafePtr.As>(ref p); 94 | 95 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 96 | public static explicit operator PtrPtrPtr(void** p) => UnsafePtr.As>(ref p); 97 | 98 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 99 | public static explicit operator PtrPtrPtr(void*** p) => UnsafePtr.As>(ref p); 100 | 101 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 102 | public static explicit operator PtrPtrPtr(Ptr ptr) => Unsafe.As, PtrPtrPtr>(ref ptr); 103 | 104 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 105 | public static explicit operator PtrPtrPtr(PtrPtr ptr) => Unsafe.As, PtrPtrPtr>(ref ptr); 106 | 107 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 108 | public static explicit operator PtrPtrPtr(Ptr ptr) => Unsafe.As>(ref ptr); 109 | 110 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 111 | public static explicit operator PtrPtrPtr(PtrPtr ptr) => Unsafe.As>(ref ptr); 112 | 113 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 114 | public static explicit operator PtrPtrPtr(PtrPtrPtr ptr) => Unsafe.As>(ref ptr); 115 | 116 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 117 | public static implicit operator Ptr(PtrPtrPtr ptr) => Unsafe.As, Ptr>(ref ptr); 118 | 119 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 120 | public static explicit operator PtrPtr(PtrPtrPtr ptr) => Unsafe.As, PtrPtr>(ref ptr); 121 | 122 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 123 | public static explicit operator PtrPtrPtr(PtrPtrPtr ptr) => Unsafe.As, PtrPtrPtr>(ref ptr); 124 | 125 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 126 | public static explicit operator PtrPtrPtr(IntPtr intPtr) => Unsafe.As>(ref intPtr); 127 | 128 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 129 | public static implicit operator IntPtr(PtrPtrPtr ptr) => Unsafe.As, IntPtr>(ref ptr); 130 | 131 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 132 | public static explicit operator PtrPtrPtr(UIntPtr intPtr) => Unsafe.As>(ref intPtr); 133 | 134 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 135 | public static implicit operator UIntPtr(PtrPtrPtr ptr) => Unsafe.As, UIntPtr>(ref ptr); 136 | 137 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 138 | public static explicit operator T*(PtrPtrPtr ptr) => (T*)ptr.p; 139 | 140 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 141 | public static explicit operator T**(PtrPtrPtr ptr) => (T**)ptr.p; 142 | 143 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 144 | public static implicit operator T***(PtrPtrPtr ptr) => ptr.p; 145 | 146 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 147 | public static implicit operator void*(PtrPtrPtr ptr) => ptr.p; 148 | 149 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 150 | public static explicit operator void**(PtrPtrPtr ptr) => (void**)ptr.p; 151 | 152 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 153 | public static explicit operator void***(PtrPtrPtr ptr) => (void***)ptr.p; 154 | 155 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 156 | public static bool operator ==(PtrPtrPtr ptr1, PtrPtrPtr ptr3) => ptr1.p == ptr3.p; 157 | 158 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 159 | public static bool operator !=(PtrPtrPtr ptr1, PtrPtrPtr ptr3) => ptr1.p != ptr3.p; 160 | 161 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 162 | public static bool operator >(PtrPtrPtr ptr1, PtrPtrPtr ptr2) => ptr1.p > ptr2.p; 163 | 164 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 165 | public static bool operator <(PtrPtrPtr ptr1, PtrPtrPtr ptr2) => ptr1.p < ptr2.p; 166 | 167 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 168 | public static bool operator >=(PtrPtrPtr ptr1, PtrPtrPtr ptr2) => ptr1.p >= ptr2.p; 169 | 170 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 171 | public static bool operator <=(PtrPtrPtr ptr1, PtrPtrPtr ptr2) => ptr1.p <= ptr2.p; 172 | 173 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 174 | public static PtrPtrPtr operator +(PtrPtrPtr ptr, int count) => ptr.p + count; 175 | 176 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 177 | public static PtrPtrPtr operator +(int count, PtrPtrPtr ptr) => count + ptr.p; 178 | 179 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 180 | public static PtrPtrPtr operator +(PtrPtrPtr ptr, long count) => ptr.p + count; 181 | 182 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 183 | public static PtrPtrPtr operator +(long count, PtrPtrPtr ptr) => count + ptr.p; 184 | 185 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 186 | public static PtrPtrPtr operator +(PtrPtrPtr ptr, nint count) => ptr.p + count; 187 | 188 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 189 | public static PtrPtrPtr operator +(nint count, PtrPtrPtr ptr) => count + ptr.p; 190 | 191 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 192 | public static PtrPtrPtr operator +(PtrPtrPtr ptr, uint count) => ptr.p + count; 193 | 194 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 195 | public static PtrPtrPtr operator +(uint count, PtrPtrPtr ptr) => count + ptr.p; 196 | 197 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 198 | public static PtrPtrPtr operator +(PtrPtrPtr ptr, ulong count) => ptr.p + count; 199 | 200 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 201 | public static PtrPtrPtr operator +(ulong count, PtrPtrPtr ptr) => count + ptr.p; 202 | 203 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 204 | public static PtrPtrPtr operator +(PtrPtrPtr ptr, nuint count) => ptr.p + count; 205 | 206 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 207 | public static PtrPtrPtr operator +(nuint count, PtrPtrPtr ptr) => count + ptr.p; 208 | 209 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 210 | public static PtrPtrPtr operator -(PtrPtrPtr ptr, int count) => ptr.p - count; 211 | 212 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 213 | public static PtrPtrPtr operator -(PtrPtrPtr ptr, long count) => ptr.p - count; 214 | 215 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 216 | public static PtrPtrPtr operator -(PtrPtrPtr ptr, nint count) => ptr.p - count; 217 | 218 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 219 | public static PtrPtrPtr operator -(PtrPtrPtr ptr, uint count) => ptr.p - count; 220 | 221 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 222 | public static PtrPtrPtr operator -(PtrPtrPtr ptr, ulong count) => ptr.p - count; 223 | 224 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 225 | public static PtrPtrPtr operator -(PtrPtrPtr ptr, nuint count) => ptr.p - count; 226 | 227 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 228 | public static long operator -(PtrPtrPtr ptr1, PtrPtrPtr ptr2) => ptr1.p - ptr2.p; 229 | } 230 | -------------------------------------------------------------------------------- /PointerToolkit/PtrPtr`1.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.CompilerServices; 3 | 4 | namespace PointerToolkit; 5 | 6 | public unsafe readonly struct PtrPtr 7 | : IEquatable>, 8 | IComparable>, 9 | IFormattable 10 | where T : unmanaged 11 | { 12 | private readonly T** p; 13 | 14 | private PtrPtr(T** p) => this.p = p; 15 | 16 | public ref Ptr Value 17 | { 18 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 19 | get => ref UnsafePtr.As>(ref *this.p); 20 | } 21 | 22 | public ref Ptr this[int index] 23 | { 24 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 25 | get => ref UnsafePtr.As>(ref *(this.p + index)); 26 | } 27 | 28 | public ref Ptr this[long index] 29 | { 30 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 31 | get => ref UnsafePtr.As>(ref *(this.p + index)); 32 | } 33 | 34 | public ref Ptr this[nint index] 35 | { 36 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 37 | get => ref UnsafePtr.As>(ref *(this.p + index)); 38 | } 39 | 40 | public ref Ptr this[uint index] 41 | { 42 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 43 | get => ref UnsafePtr.As>(ref *(this.p + index)); 44 | } 45 | 46 | public ref Ptr this[ulong index] 47 | { 48 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 49 | get => ref UnsafePtr.As>(ref *(this.p + index)); 50 | } 51 | 52 | public ref Ptr this[nuint index] 53 | { 54 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 55 | get => ref UnsafePtr.As>(ref *(this.p + index)); 56 | } 57 | 58 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 59 | public int CompareTo(PtrPtr other) => ((IntPtr)this.p).CompareTo(other); 60 | 61 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 62 | public override bool Equals(object? other) => (other is PtrPtr p) && (this.p == p.p); 63 | 64 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 65 | public bool Equals(PtrPtr other) => this.p == other.p; 66 | 67 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 68 | public T** Get() => this.p; 69 | 70 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 71 | public override int GetHashCode() => ((IntPtr)this.p).GetHashCode(); 72 | 73 | public override string ToString() 74 | { 75 | return ((UIntPtr)this.p).ToString(sizeof(IntPtr) == 4 ? "X8" : "X16"); 76 | } 77 | 78 | public string ToString(string? format, IFormatProvider? formatProvider) 79 | { 80 | return ((UIntPtr)this.p).ToString(format, formatProvider); 81 | } 82 | 83 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 84 | public static explicit operator PtrPtr(T* p) => UnsafePtr.As>(ref p); 85 | 86 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 87 | public static implicit operator PtrPtr(T** p) => UnsafePtr.As>(ref p); 88 | 89 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 90 | public static explicit operator PtrPtr(T*** p) => UnsafePtr.As>(ref p); 91 | 92 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 93 | public static explicit operator PtrPtr(void* p) => UnsafePtr.As>(ref p); 94 | 95 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 96 | public static explicit operator PtrPtr(void** p) => UnsafePtr.As>(ref p); 97 | 98 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 99 | public static explicit operator PtrPtr(void*** p) => UnsafePtr.As>(ref p); 100 | 101 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 102 | public static explicit operator PtrPtr(Ptr ptr) => Unsafe.As, PtrPtr>(ref ptr); 103 | 104 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 105 | public static explicit operator PtrPtr(PtrPtrPtr ptr) => Unsafe.As, PtrPtr>(ref ptr); 106 | 107 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 108 | public static explicit operator PtrPtr(Ptr ptr) => Unsafe.As>(ref ptr); 109 | 110 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 111 | public static explicit operator PtrPtr(PtrPtr ptr) => Unsafe.As>(ref ptr); 112 | 113 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 114 | public static explicit operator PtrPtr(PtrPtrPtr ptr) => Unsafe.As>(ref ptr); 115 | 116 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 117 | public static implicit operator Ptr(PtrPtr ptr) => Unsafe.As, Ptr>(ref ptr); 118 | 119 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 120 | public static explicit operator PtrPtr(PtrPtr ptr) => Unsafe.As, PtrPtr>(ref ptr); 121 | 122 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 123 | public static explicit operator PtrPtrPtr(PtrPtr ptr) => Unsafe.As, PtrPtrPtr>(ref ptr); 124 | 125 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 126 | public static explicit operator PtrPtr(IntPtr intPtr) => Unsafe.As>(ref intPtr); 127 | 128 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 129 | public static implicit operator IntPtr(PtrPtr ptr) => Unsafe.As, IntPtr>(ref ptr); 130 | 131 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 132 | public static explicit operator PtrPtr(UIntPtr intPtr) => Unsafe.As>(ref intPtr); 133 | 134 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 135 | public static implicit operator UIntPtr(PtrPtr ptr) => Unsafe.As, UIntPtr>(ref ptr); 136 | 137 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 138 | public static explicit operator T*(PtrPtr ptr) => (T*)ptr.p; 139 | 140 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 141 | public static implicit operator T**(PtrPtr ptr) => ptr.p; 142 | 143 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 144 | public static explicit operator T***(PtrPtr ptr) => (T***)ptr.p; 145 | 146 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 147 | public static implicit operator void*(PtrPtr ptr) => ptr.p; 148 | 149 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 150 | public static explicit operator void**(PtrPtr ptr) => (void**)ptr.p; 151 | 152 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 153 | public static explicit operator void***(PtrPtr ptr) => (void***)ptr.p; 154 | 155 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 156 | public static bool operator ==(PtrPtr ptr1, PtrPtr ptr2) => ptr1.p == ptr2.p; 157 | 158 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 159 | public static bool operator !=(PtrPtr ptr1, PtrPtr ptr2) => ptr1.p != ptr2.p; 160 | 161 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 162 | public static bool operator >(PtrPtr ptr1, PtrPtr ptr2) => ptr1.p > ptr2.p; 163 | 164 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 165 | public static bool operator <(PtrPtr ptr1, PtrPtr ptr2) => ptr1.p < ptr2.p; 166 | 167 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 168 | public static bool operator >=(PtrPtr ptr1, PtrPtr ptr2) => ptr1.p >= ptr2.p; 169 | 170 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 171 | public static bool operator <=(PtrPtr ptr1, PtrPtr ptr2) => ptr1.p <= ptr2.p; 172 | 173 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 174 | public static PtrPtr operator +(PtrPtr ptr, int count) => ptr.p + count; 175 | 176 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 177 | public static PtrPtr operator +(int count, PtrPtr ptr) => count + ptr.p; 178 | 179 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 180 | public static PtrPtr operator +(PtrPtr ptr, long count) => ptr.p + count; 181 | 182 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 183 | public static PtrPtr operator +(long count, PtrPtr ptr) => count + ptr.p; 184 | 185 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 186 | public static PtrPtr operator +(PtrPtr ptr, nint count) => ptr.p + count; 187 | 188 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 189 | public static PtrPtr operator +(nint count, PtrPtr ptr) => count + ptr.p; 190 | 191 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 192 | public static PtrPtr operator +(PtrPtr ptr, uint count) => ptr.p + count; 193 | 194 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 195 | public static PtrPtr operator +(uint count, PtrPtr ptr) => count + ptr.p; 196 | 197 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 198 | public static PtrPtr operator +(PtrPtr ptr, ulong count) => ptr.p + count; 199 | 200 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 201 | public static PtrPtr operator +(ulong count, PtrPtr ptr) => count + ptr.p; 202 | 203 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 204 | public static PtrPtr operator +(PtrPtr ptr, nuint count) => ptr.p + count; 205 | 206 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 207 | public static PtrPtr operator +(nuint count, PtrPtr ptr) => count + ptr.p; 208 | 209 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 210 | public static PtrPtr operator -(PtrPtr ptr, int count) => ptr.p - count; 211 | 212 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 213 | public static PtrPtr operator -(PtrPtr ptr, long count) => ptr.p - count; 214 | 215 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 216 | public static PtrPtr operator -(PtrPtr ptr, nint count) => ptr.p - count; 217 | 218 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 219 | public static PtrPtr operator -(PtrPtr ptr, uint count) => ptr.p - count; 220 | 221 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 222 | public static PtrPtr operator -(PtrPtr ptr, ulong count) => ptr.p - count; 223 | 224 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 225 | public static PtrPtr operator -(PtrPtr ptr, nuint count) => ptr.p - count; 226 | 227 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 228 | public static long operator -(PtrPtr ptr1, PtrPtr ptr2) => ptr1.p - ptr2.p; 229 | } 230 | -------------------------------------------------------------------------------- /PointerToolkit/Ptr`1.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.CompilerServices; 3 | 4 | namespace PointerToolkit; 5 | 6 | public unsafe readonly struct Ptr 7 | : IEquatable>, 8 | IComparable>, 9 | IFormattable 10 | where T : unmanaged 11 | { 12 | private readonly T* p; 13 | 14 | private Ptr(T* p) => this.p = p; 15 | 16 | public ref T Value 17 | { 18 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 19 | get => ref *this.p; 20 | } 21 | 22 | public ref T this[int index] 23 | { 24 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 25 | get => ref *(this.p + index); 26 | } 27 | 28 | public ref T this[long index] 29 | { 30 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 31 | get => ref *(this.p + index); 32 | } 33 | 34 | public ref T this[nint index] 35 | { 36 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 37 | get => ref *(this.p + index); 38 | } 39 | 40 | public ref T this[uint index] 41 | { 42 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 43 | get => ref *(this.p + index); 44 | } 45 | 46 | public ref T this[ulong index] 47 | { 48 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 49 | get => ref *(this.p + index); 50 | } 51 | 52 | public ref T this[nuint index] 53 | { 54 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 55 | get => ref *(this.p + index); 56 | } 57 | 58 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 59 | public int CompareTo(Ptr other) => ((IntPtr)this.p).CompareTo(other); 60 | 61 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 62 | public override bool Equals(object? other) => (other is Ptr p) && (this.p == p.p); 63 | 64 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 65 | public bool Equals(Ptr other) => this.p == other.p; 66 | 67 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 68 | public T* Get() => this.p; 69 | 70 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 71 | public override int GetHashCode() => ((IntPtr)this.p).GetHashCode(); 72 | 73 | public override string ToString() 74 | { 75 | return ((UIntPtr)this.p).ToString(sizeof(IntPtr) == 4 ? "X8" : "X16"); 76 | } 77 | 78 | public string ToString(string? format, IFormatProvider? formatProvider) 79 | { 80 | return ((UIntPtr)this.p).ToString(format, formatProvider); 81 | } 82 | 83 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 84 | public static implicit operator Ptr(T* p) => UnsafePtr.As>(ref p); 85 | 86 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 87 | public static explicit operator Ptr(T** p) => UnsafePtr.As>(ref p); 88 | 89 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 90 | public static explicit operator Ptr(T*** p) => UnsafePtr.As>(ref p); 91 | 92 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 93 | public static explicit operator Ptr(void* p) => UnsafePtr.As>(ref p); 94 | 95 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 96 | public static explicit operator Ptr(void** p) => UnsafePtr.As>(ref p); 97 | 98 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 99 | public static explicit operator Ptr(void*** p) => UnsafePtr.As>(ref p); 100 | 101 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 102 | public static explicit operator Ptr(PtrPtr ptr) => Unsafe.As, Ptr>(ref ptr); 103 | 104 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 105 | public static explicit operator Ptr(PtrPtrPtr ptr) => Unsafe.As, Ptr>(ref ptr); 106 | 107 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 108 | public static explicit operator Ptr(Ptr ptr) => Unsafe.As>(ref ptr); 109 | 110 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 111 | public static explicit operator Ptr(PtrPtr ptr) => Unsafe.As>(ref ptr); 112 | 113 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 114 | public static explicit operator Ptr(PtrPtrPtr ptr) => Unsafe.As>(ref ptr); 115 | 116 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 117 | public static implicit operator Ptr(Ptr ptr) => Unsafe.As, Ptr>(ref ptr); 118 | 119 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 120 | public static explicit operator PtrPtr(Ptr ptr) => Unsafe.As, PtrPtr>(ref ptr); 121 | 122 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 123 | public static explicit operator PtrPtrPtr(Ptr ptr) => Unsafe.As, PtrPtrPtr>(ref ptr); 124 | 125 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 126 | public static explicit operator Ptr(IntPtr intPtr) => Unsafe.As>(ref intPtr); 127 | 128 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 129 | public static implicit operator IntPtr(Ptr ptr) => Unsafe.As, IntPtr>(ref ptr); 130 | 131 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 132 | public static explicit operator Ptr(UIntPtr intPtr) => Unsafe.As>(ref intPtr); 133 | 134 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 135 | public static implicit operator UIntPtr(Ptr ptr) => Unsafe.As, UIntPtr>(ref ptr); 136 | 137 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 138 | public static implicit operator T*(Ptr ptr) => ptr.p; 139 | 140 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 141 | public static explicit operator T**(Ptr ptr) => (T**)ptr.p; 142 | 143 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 144 | public static explicit operator T***(Ptr ptr) => (T***)ptr.p; 145 | 146 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 147 | public static implicit operator void*(Ptr ptr) => ptr.p; 148 | 149 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 150 | public static explicit operator void**(Ptr ptr) => (void**)ptr.p; 151 | 152 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 153 | public static explicit operator void***(Ptr ptr) => (void***)ptr.p; 154 | 155 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 156 | public static bool operator ==(Ptr ptr1, Ptr ptr2) => ptr1.p == ptr2.p; 157 | 158 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 159 | public static bool operator !=(Ptr ptr1, Ptr ptr2) => ptr1.p != ptr2.p; 160 | 161 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 162 | public static bool operator >(Ptr ptr1, Ptr ptr2) => ptr1.p > ptr2.p; 163 | 164 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 165 | public static bool operator <(Ptr ptr1, Ptr ptr2) => ptr1.p < ptr2.p; 166 | 167 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 168 | public static bool operator >=(Ptr ptr1, Ptr ptr2) => ptr1.p >= ptr2.p; 169 | 170 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 171 | public static bool operator <=(Ptr ptr1, Ptr ptr2) => ptr1.p <= ptr2.p; 172 | 173 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 174 | public static Ptr operator +(Ptr ptr, int count) => ptr.p + count; 175 | 176 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 177 | public static Ptr operator +(int count, Ptr ptr) => count + ptr.p; 178 | 179 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 180 | public static Ptr operator +(Ptr ptr, long count) => ptr.p + count; 181 | 182 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 183 | public static Ptr operator +(long count, Ptr ptr) => count + ptr.p; 184 | 185 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 186 | public static Ptr operator +(Ptr ptr, nint count) => ptr.p + count; 187 | 188 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 189 | public static Ptr operator +(nint count, Ptr ptr) => count + ptr.p; 190 | 191 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 192 | public static Ptr operator +(Ptr ptr, uint count) => ptr.p + count; 193 | 194 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 195 | public static Ptr operator +(uint count, Ptr ptr) => count + ptr.p; 196 | 197 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 198 | public static Ptr operator +(Ptr ptr, ulong count) => ptr.p + count; 199 | 200 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 201 | public static Ptr operator +(ulong count, Ptr ptr) => count + ptr.p; 202 | 203 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 204 | public static Ptr operator +(Ptr ptr, nuint count) => ptr.p + count; 205 | 206 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 207 | public static Ptr operator +(nuint count, Ptr ptr) => count + ptr.p; 208 | 209 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 210 | public static Ptr operator -(Ptr ptr, int count) => ptr.p - count; 211 | 212 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 213 | public static Ptr operator -(Ptr ptr, long count) => ptr.p - count; 214 | 215 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 216 | public static Ptr operator -(Ptr ptr, nint count) => ptr.p - count; 217 | 218 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 219 | public static Ptr operator -(Ptr ptr, uint count) => ptr.p - count; 220 | 221 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 222 | public static Ptr operator -(Ptr ptr, ulong count) => ptr.p - count; 223 | 224 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 225 | public static Ptr operator -(Ptr ptr, nuint count) => ptr.p - count; 226 | 227 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 228 | public static long operator -(Ptr ptr1, Ptr ptr2) => ptr1.p - ptr2.p; 229 | } 230 | -------------------------------------------------------------------------------- /PointerToolkit/UnsafePtr.cs: -------------------------------------------------------------------------------- 1 | using InlineIL; 2 | using System; 3 | using System.Runtime.CompilerServices; 4 | 5 | namespace PointerToolkit; 6 | 7 | public static unsafe class UnsafePtr 8 | { 9 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 10 | public static T* AddByteOffset(T* p, nuint offset) 11 | where T : unmanaged 12 | { 13 | return (T*)((byte*)p + offset); 14 | } 15 | 16 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 17 | public static T* AddByteOffset(T* p, nint offset) 18 | where T : unmanaged 19 | { 20 | return (T*)((byte*)p + offset); 21 | } 22 | 23 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 24 | public static T* SubtractByteOffset(T* p, nuint offset) 25 | where T : unmanaged 26 | { 27 | return unchecked((T*)((byte*)p - offset)); 28 | } 29 | 30 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 31 | public static T* SubtractByteOffset(T* p, nint offset) 32 | where T : unmanaged 33 | { 34 | return unchecked((T*)((byte*)p - offset)); 35 | } 36 | 37 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 38 | public static ref T As(ref void* source) 39 | where T : unmanaged 40 | { 41 | IL.Emit.Ldarg_0(); 42 | IL.Emit.Ret(); 43 | throw IL.Unreachable(); 44 | } 45 | 46 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 47 | public static ref T As(ref void** source) 48 | where T : unmanaged 49 | { 50 | IL.Emit.Ldarg_0(); 51 | IL.Emit.Ret(); 52 | throw IL.Unreachable(); 53 | } 54 | 55 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 56 | public static ref T As(ref void*** source) 57 | where T : unmanaged 58 | { 59 | IL.Emit.Ldarg_0(); 60 | IL.Emit.Ret(); 61 | throw IL.Unreachable(); 62 | } 63 | 64 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 65 | public static ref U As(ref T* source) 66 | where T : unmanaged 67 | where U : unmanaged 68 | { 69 | IL.Emit.Ldarg_0(); 70 | IL.Emit.Ret(); 71 | throw IL.Unreachable(); 72 | } 73 | 74 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 75 | public static ref U As(ref T** source) 76 | where T : unmanaged 77 | where U : unmanaged 78 | { 79 | IL.Emit.Ldarg_0(); 80 | IL.Emit.Ret(); 81 | throw IL.Unreachable(); 82 | } 83 | 84 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 85 | public static ref U As(ref T*** source) 86 | where T : unmanaged 87 | where U : unmanaged 88 | { 89 | IL.Emit.Ldarg_0(); 90 | IL.Emit.Ret(); 91 | throw IL.Unreachable(); 92 | } 93 | 94 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 95 | public static T* AsPointer(ref T source) 96 | where T : unmanaged 97 | { 98 | IL.Emit.Ldarg_0(); 99 | IL.Emit.Ret(); 100 | throw IL.Unreachable(); 101 | } 102 | 103 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 104 | public static T** AsPointer(ref T* source) 105 | where T : unmanaged 106 | { 107 | IL.Emit.Ldarg_0(); 108 | IL.Emit.Ret(); 109 | throw IL.Unreachable(); 110 | } 111 | 112 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 113 | public static T*** AsPointer(ref T** source) 114 | where T : unmanaged 115 | { 116 | IL.Emit.Ldarg_0(); 117 | IL.Emit.Ret(); 118 | throw IL.Unreachable(); 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /PointerToolkit/VolatilePtr.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.CompilerServices; 3 | using System.Threading; 4 | 5 | namespace PointerToolkit; 6 | 7 | public static unsafe class VolatilePtr 8 | { 9 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 10 | public static void* Read(ref void* location) 11 | { 12 | return (void*)Volatile.Read(ref UnsafePtr.As(ref location)); 13 | } 14 | 15 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 16 | public static void** Read(ref void** location) 17 | { 18 | return (void**)Volatile.Read(ref UnsafePtr.As(ref location)); 19 | } 20 | 21 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 22 | public static void*** Read(ref void*** location) 23 | { 24 | return (void***)Volatile.Read(ref UnsafePtr.As(ref location)); 25 | } 26 | 27 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 28 | public static T* Read(ref T* location) 29 | where T : unmanaged 30 | { 31 | return (T*)Volatile.Read(ref UnsafePtr.As(ref location)); 32 | } 33 | 34 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 35 | public static T** Read(ref T** location) 36 | where T : unmanaged 37 | { 38 | return (T**)Volatile.Read(ref UnsafePtr.As(ref location)); 39 | } 40 | 41 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 42 | public static T*** Read(ref T*** location) 43 | where T : unmanaged 44 | { 45 | return (T***)Volatile.Read(ref UnsafePtr.As(ref location)); 46 | } 47 | 48 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 49 | public static void Write(ref void* location, void* value) 50 | { 51 | Volatile.Write(ref UnsafePtr.As(ref location), (IntPtr)value); 52 | } 53 | 54 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 55 | public static void Write(ref void** location, void** value) 56 | { 57 | Volatile.Write(ref UnsafePtr.As(ref location), (IntPtr)value); 58 | } 59 | 60 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 61 | public static void Write(ref void*** location, void*** value) 62 | { 63 | Volatile.Write(ref UnsafePtr.As(ref location), (IntPtr)value); 64 | } 65 | 66 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 67 | public static void Write(ref T* location, T* value) 68 | where T : unmanaged 69 | { 70 | Volatile.Write(ref UnsafePtr.As(ref location), (IntPtr)value); 71 | } 72 | 73 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 74 | public static void Write(ref T** location, T** value) 75 | where T : unmanaged 76 | { 77 | Volatile.Write(ref UnsafePtr.As(ref location), (IntPtr)value); 78 | } 79 | 80 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 81 | public static void Write(ref T*** location, T*** value) 82 | where T : unmanaged 83 | { 84 | Volatile.Write(ref UnsafePtr.As(ref location), (IntPtr)value); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PointerToolkit 2 | Provides structs that wrap pointers, as well as `Unsafe`, `Interlocked`, and `Volatile` operations on ref pointers. 3 | 4 | All of the functionality contained within was used for my work during Paint.NET v5.0, released in January 2023. I ported 50,000 lines of C++/CLI, almost all classes that wrap native COM objects, to C#. This package, along with [TerraFX.Interop.Windows](https://github.com/terrafx/terrafx.interop.windows) and [PointerToolkit.TerraFX.Interop.Windows](https://github.com/rickbrew/PointerToolkit.TerraFX.Interop.Windows), were the foundation for that work. 5 | 6 | The `Ptr` and `Ptr` structs are straightforward enough, they simply wrap a pointer and provide all the casting operators you will need. Pointers up to 3 levels of indirection are supported, e.g. `void***` and `T***`, via`PtrPtr` and `PtrPtrPtr` and their generic versions. 7 | 8 | The `UnsafePtr`, `InterlockedPtr`, and `VolatilePtr` classes provided methods similar to what is available with `Unsafe`, `Interlocked`, and `Volatile`, except that they work on `ref` pointers (`ref void*`, `ref T*`, as well as `**` and `***` variants). Refs to pointers are otherwise impossible to work well with in C# without these methods. You can't break them out of their "jail"; refs to pointers just don't work with generics or other attempted tricks employing combinations of `&`, `*`, `ref`, `in`, `Unsafe`, etc. 9 | 10 | ```cs 11 | public static unsafe class UnsafePtr 12 | { 13 | public static ref T As(ref void* source) where T : unmanaged; 14 | public static ref U As(ref T* source) where T : unmanaged where U : unmanaged; 15 | // etc. 16 | } 17 | 18 | public static unsafe class InterlockedPtr 19 | { 20 | public static void* Exchange(ref void* location1, void* value); 21 | public static T* Exchange(ref T* location1, T* value) where T : unmanaged; 22 | // etc. 23 | } 24 | 25 | public static unsafe class VolatilePtr 26 | { 27 | public static void* Read(ref void* location); 28 | public static T* Read(ref T* location) where T : unmanaged; 29 | public static void Write(ref void* location, void* value); 30 | public static void Write(ref T* location, T* value) where T : unmanaged; 31 | 32 | // etc. 33 | } 34 | ``` 35 | 36 | These structs are supported by the `PtrOperators` class, which contains `__ptr()` methods meant to be used in conjunction with a `global using static PointerToolkit.PtrOperators;` statement. They make it easy to pass pointers into places where they normally can't be used, such as in generics and generic delegates. The name `__ptr()` was chosen to be similar to vendor-specific additions in various C++ compilers, such as how Microsoft has `__uuidof()` for working with COM interface identifiers. 37 | 38 | For instance, let's say you want to call a method on a COM object inside the delegate passed to `String.Create()`. Without PointerToolkit or your own struct wrappers, you'd have to pass it in as an `IntPtr`/`nint` and cast it back yourself because you can't specify a pointer type for the `T` in `SpanAction` . `Ptr` helps with that. In addition, the `__ptr()` "operator methods" help reduce the typing and duplication of types even further: 39 | 40 | (an example from my wrapper for Direct2D's [`ID2D1Properties`](https://docs.microsoft.com/en-us/windows/win32/api/d2d1_1/nn-d2d1_1-id2d1properties)) 41 | ```cs 42 | public string? TryGetPropertyName(int index) 43 | { 44 | using var @lock = EnterFactoryLock(); 45 | 46 | uint dwNameLength = this.pD2D1Properties->GetPropertyNameLength(unchecked((uint)index)); 47 | if (dwNameLength == 0) 48 | { 49 | return null; 50 | } 51 | 52 | return string.Create( 53 | checked((int)dwNameLength), 54 | // without __ptr(), I'd have to type (Ptr) 55 | (__ptr(this.pD2D1Properties), index), 56 | static (Span dst, (Ptr pD2D1Properties, int index) e) => 57 | { 58 | fixed (char* pDst = dst) 59 | { 60 | HRESULT hr = e.pD2D1Properties.Get()->GetPropertyName( 61 | unchecked((uint)e.index), 62 | (ushort*)pDst, 63 | (uint)(dst.Length + 1)); 64 | 65 | hr.ThrowOnError(); 66 | } 67 | }); 68 | } 69 | ``` 70 | 71 | `CastPtr<...>` is also provided, which can be used to generate static `__cast()` "method operators." This solves the problem where you have (e.g.) an `ID2D1SolidColorBrush*` that you need to pass to a method that takes a pointer to a base interface, such as `ID2D1Brush*` or even `IUnknown*`. C# does not have struct inheritance, so all of the COM interface structs in [TerraFX.Interop.Windows](https://github.com/terrafx/terrafx.interop.windows) are unrelated as far as it can tell. 72 | 73 | Instead of forcing a pointer cast with `(ID2D1Brush*)`, which denies the compiler a chance to verify that the cast is safe, you can use `__cast(p)` (along with an appropriate `using static` declaration). A temporary `CastPtr` will be created which will implicitly cast to pointers of all of those base interface pointer types. (Note that "interface" in this case refers to a COM interface, not a managed interface.) The generation of these `__cast()` operators is not provided by this package, but you can see the [PointerToolkit.TerraFX.Interop.Windows](https://github.com/rickbrew/PointerToolkit.TerraFX.Interop.Windows) package for a real world example. 74 | --------------------------------------------------------------------------------