forked from CommunityToolkit/WindowsCommunityToolkit
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathReadOnlyRef{T}.cs
More file actions
134 lines (121 loc) · 5.53 KB
/
ReadOnlyRef{T}.cs
File metadata and controls
134 lines (121 loc) · 5.53 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Runtime.CompilerServices;
#if SPAN_RUNTIME_SUPPORT
using System.Runtime.InteropServices;
#else
using Microsoft.Toolkit.HighPerformance.Extensions;
#endif
namespace Microsoft.Toolkit.HighPerformance
{
/// <summary>
/// A <see langword="struct"/> that can store a readonly reference to a value of a specified type.
/// </summary>
/// <typeparam name="T">The type of value to reference.</typeparam>
public readonly ref struct ReadOnlyRef<T>
{
#if SPAN_RUNTIME_SUPPORT
/// <summary>
/// The 1-length <see cref="ReadOnlySpan{T}"/> instance used to track the target <typeparamref name="T"/> value.
/// </summary>
internal readonly ReadOnlySpan<T> Span;
/// <summary>
/// Initializes a new instance of the <see cref="ReadOnlyRef{T}"/> struct.
/// </summary>
/// <param name="value">The readonly reference to the target <typeparamref name="T"/> value.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public ReadOnlyRef(in T value)
{
ref T r0 = ref Unsafe.AsRef(value);
Span = MemoryMarshal.CreateReadOnlySpan(ref r0, 1);
}
/// <summary>
/// Initializes a new instance of the <see cref="ReadOnlyRef{T}"/> struct.
/// </summary>
/// <param name="pointer">The pointer to the target value.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public unsafe ReadOnlyRef(void* pointer)
: this(Unsafe.AsRef<T>(pointer))
{
}
/// <summary>
/// Gets the readonly <typeparamref name="T"/> reference represented by the current <see cref="Ref{T}"/> instance.
/// </summary>
public ref readonly T Value
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => ref MemoryMarshal.GetReference(Span);
}
/// <summary>
/// Implicitly converts a <see cref="Ref{T}"/> instance into a <see cref="ReadOnlyRef{T}"/> one.
/// </summary>
/// <param name="reference">The input <see cref="Ref{T}"/> instance.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator ReadOnlyRef<T>(Ref<T> reference)
{
return new ReadOnlyRef<T>(reference.Value);
}
#else
/// <summary>
/// The owner <see cref="object"/> the current instance belongs to
/// </summary>
private readonly object owner;
/// <summary>
/// The target offset within <see cref="owner"/> the current instance is pointing to
/// </summary>
private readonly IntPtr offset;
/// <summary>
/// Initializes a new instance of the <see cref="ReadOnlyRef{T}"/> struct.
/// </summary>
/// <param name="owner">The owner <see cref="object"/> to create a portable reference for.</param>
/// <param name="offset">The target offset within <paramref name="owner"/> for the target reference.</param>
/// <remarks>The <paramref name="offset"/> parameter is not validated, and it's responsibility of the caller to ensure it's valid.</remarks>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private ReadOnlyRef(object owner, IntPtr offset)
{
this.owner = owner;
this.offset = offset;
}
/// <summary>
/// Initializes a new instance of the <see cref="ReadOnlyRef{T}"/> struct.
/// </summary>
/// <param name="owner">The owner <see cref="object"/> to create a portable reference for.</param>
/// <param name="value">The target reference to point to (it must be within <paramref name="owner"/>).</param>
/// <remarks>The <paramref name="value"/> parameter is not validated, and it's responsibility of the caller to ensure it's valid.</remarks>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public ReadOnlyRef(object owner, in T value)
{
this.owner = owner;
this.offset = owner.DangerousGetObjectDataByteOffset(ref Unsafe.AsRef(value));
}
/// <summary>
/// Gets the readonly <typeparamref name="T"/> reference represented by the current <see cref="Ref{T}"/> instance.
/// </summary>
public ref readonly T Value
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => ref this.owner.DangerousGetObjectDataReferenceAt<T>(this.offset);
}
/// <summary>
/// Implicitly converts a <see cref="Ref{T}"/> instance into a <see cref="ReadOnlyRef{T}"/> one.
/// </summary>
/// <param name="reference">The input <see cref="Ref{T}"/> instance.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator ReadOnlyRef<T>(Ref<T> reference)
{
return new ReadOnlyRef<T>(reference.Owner, reference.Offset);
}
#endif
/// <summary>
/// Implicitly gets the <typeparamref name="T"/> value from a given <see cref="ReadOnlyRef{T}"/> instance.
/// </summary>
/// <param name="reference">The input <see cref="ReadOnlyRef{T}"/> instance.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator T(ReadOnlyRef<T> reference)
{
return reference.Value;
}
}
}