ARCollaborationData.cs
10.4 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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
using System;
using System.Runtime.InteropServices;
using Unity.Collections;
using Unity.Collections.LowLevel.Unsafe;
namespace UnityEngine.XR.ARKit
{
/// <summary>
/// Represents the Objective-C type ARCollaborationData.
/// </summary>
/// <remarks>
/// <para>
/// This struct mirrors the Objective-C type ARCollaborationData. Because it
/// represents a native resource, it must be explicitly disposed when no
/// longer needed.
/// </para><para>
/// ARCollaborationData can be constructed from a byte array, or from
/// <see cref="ARKitSessionSubsystem.DequeueCollaborationData"/>.
/// </para><para>
/// This struct is not thread-safe, but it may be constructed and disposed on any thread.
/// </para>
/// </remarks>
public struct ARCollaborationData : IDisposable, IEquatable<ARCollaborationData>
{
/// <summary>
/// Constructs an ARCollaborationData from a byte array.
/// Check <see cref="valid"/> after construction to ensure <paramref name="bytes"/> was successfully deserialized.
/// </summary>
/// <param name="bytes">An array of <c>byte</c>s to convert to <see cref="ARCollaborationData"/>.</param>
/// <exception cref="System.ArgumentNullException">Thrown if <paramref name="bytes"/> is null.</exception>
/// <seealso cref="ToSerialized"/>
public unsafe ARCollaborationData(byte[] bytes)
{
if (bytes == null)
throw new ArgumentNullException(nameof(bytes));
m_NativePtr = ConstructUnchecked(bytes, 0, bytes.Length);
}
/// <summary>
/// Constructs an ARCollaborationData from a byte array.
/// Check <see cref="valid"/> after construction to ensure <paramref name="bytes"/> was successfully deserialized.
/// </summary>
/// <param name="bytes">An array of <c>byte</c>s to convert to <see cref="ARCollaborationData"/>.</param>
/// <param name="offset">The offset into the <paramref name="bytes"/> array from which to start constructing <see cref="ARCollaborationData"/>.</param>
/// <param name="length">The number of bytes in <paramref name="bytes"/> to convert to <see cref="ARCollaborationData"/>.</param>
/// <exception cref="System.ArgumentNullException">Thrown if <paramref name="bytes"/> is null.</exception>
/// <exception cref="System.ArgumentOutOfRangeException">Thrown if <paramref name="offset"/> is outside the range [0..bytes.Length).</exception>
/// <exception cref="System.ArgumentOutOfRangeException">Thrown if <paramref name="length"/> is outside the range [0..(bytes.Length - offset)].</exception>
/// <seealso cref="ToSerialized"/>
public unsafe ARCollaborationData(byte[] bytes, int offset, int length)
{
if (bytes == null)
throw new ArgumentNullException(nameof(bytes));
if (offset < 0)
throw new ArgumentOutOfRangeException(nameof(offset), offset, $"'{nameof(offset)}' must be greater than or equal to zero.");
if (offset >= bytes.Length)
throw new ArgumentOutOfRangeException(nameof(offset), offset, $"'{nameof(offset)}' must be less than the length of the byte array ({bytes.Length}).");
if (length <= 0)
throw new ArgumentOutOfRangeException(nameof(length), length, $"'{nameof(length)}' must be greater than zero.");
if (length > (bytes.Length - offset))
throw new ArgumentOutOfRangeException(nameof(length), length, $"'{nameof(length)}' is greater than the number of available bytes in the buffer ({bytes.Length - offset})");
m_NativePtr = ConstructUnchecked(bytes, offset, length);
}
/// <summary>
/// Constructs an ARCollaborationData from a <c>NativeSlice</c> of <c>byte</c>s.
/// Check <see cref="valid"/> after construction to ensure <paramref name="bytes"/> was successfully deserialized.
/// </summary>
/// <param name="bytes">An array of <c>byte</c>s to convert to <see cref="ARCollaborationData"/>.</param>
/// <exception cref="System.ArgumentException">Thrown if <paramref name="bytes"/> does not refer to valid data.</exception>
/// <seealso cref="ToSerialized"/>
public unsafe ARCollaborationData(NativeSlice<byte> bytes)
{
void* ptr = bytes.GetUnsafePtr();
if ((ptr == null) || (bytes.Length == 0))
throw new ArgumentException("Invalid NativeSlice", nameof(bytes));
m_NativePtr = ConstructUnchecked(ptr, bytes.Length);
}
/// <summary>
/// True if the data is valid. The data may be invalid if this object was constructed
/// with an invalid byte array, or if it has been disposed.
/// </summary>
public bool valid => m_NativePtr != IntPtr.Zero;
/// <summary>
/// Gets the priority of the collaboration data. Use this to determine how
/// you should send the information to peers in a collaborative session,
/// e.g., reliably vs unreliably.
/// </summary>
/// <exception cref="System.InvalidOperationException">Thrown if <see cref="valid"/> is false.</exception>
public ARCollaborationDataPriority priority
{
get
{
ValidateAndThrow();
return UnityARKit_CollaborationData_GetPriority(m_NativePtr);
}
}
/// <summary>
/// Dispose the native ARCollaborationData. <see cref="valid"/> will be false after disposal.
/// It is safe to dispose an invalid or already disposed ARCollaborationData.
/// </summary>
public void Dispose()
{
UnityARKit_CFRelease(m_NativePtr);
m_NativePtr = IntPtr.Zero;
}
/// <summary>
/// Copies the bytes representing the serialized <see cref="ARCollaborationData"/> to a
/// <see cref="SerializedARCollaborationData"/>.
/// A common use case would be to send these bytes to another device over a network.
/// </summary>
/// <returns>A container representing the serialized bytes of this <see cref="ARCollaborationData"/>.</returns>
/// <exception cref="System.InvalidOperationException">Thrown if <see cref="valid"/> is false.</exception>
public unsafe SerializedARCollaborationData ToSerialized()
{
ValidateAndThrow();
var nsData = new NSData(UnityARKit_CollaborationData_SerializeToNSData(m_NativePtr));
return new SerializedARCollaborationData(nsData);
}
/// <summary>
/// Generates a hash code suitable for use in <c>HashSet</c> and <c>Dictionary</c>.
/// </summary>
/// <returns>A hash of the <see cref="ARCollaborationData"/>.</returns>
public override int GetHashCode() => m_NativePtr.GetHashCode();
/// <summary>
/// Compares for equality.
/// </summary>
/// <param name="obj">An <c>object</c> to compare against.</param>
/// <returns><c>true</c> if <paramref name="obj"/> is an <see cref="ARCollaborationData"/> and
/// <see cref="Equals(ARCollaborationData)"/> is also <c>true</c>. Otherwise, <c>false</c>.</returns>
public override bool Equals(object obj) => (obj is ARCollaborationData) && Equals((ARCollaborationData)obj);
/// <summary>
/// Compares for equality.
/// </summary>
/// <param name="other">The other <see cref="ARCollaborationData"/> to compare against.</param>
/// <returns><c>true</c> if the <see cref="ARCollaborationData"/> represents the same object.</returns>
public bool Equals(ARCollaborationData other) => m_NativePtr == other.m_NativePtr;
/// <summary>
/// Compares <paramref name="lhs"/> and <paramref name="rhs"/> for equality using <see cref="Equals(ARCollaborationData)"/>.
/// </summary>
/// <param name="lhs">The left-hand-side <see cref="ARCollaborationData"/> of the comparison.</param>
/// <param name="rhs">The right-hand-side <see cref="ARCollaborationData"/> of the comparison.</param>
/// <returns><c>true</c> if <paramref name="lhs"/> compares equal to <paramref name="rhs"/>, <c>false</c> otherwise.</returns>
public static bool operator ==(ARCollaborationData lhs, ARCollaborationData rhs) => lhs.Equals(rhs);
/// <summary>
/// Compares <paramref name="lhs"/> and <paramref name="rhs"/> for inequality using <see cref="Equals(ARCollaborationData)"/>.
/// </summary>
/// <param name="lhs">The left-hand-side <see cref="ARCollaborationData"/> of the comparison.</param>
/// <param name="rhs">The right-hand-side <see cref="ARCollaborationData"/> of the comparison.</param>
/// <returns><c>false</c> if <paramref name="lhs"/> compares equal to <paramref name="rhs"/>, <c>true</c> otherwise.</returns>
public static bool operator !=(ARCollaborationData lhs, ARCollaborationData rhs) => !lhs.Equals(rhs);
internal ARCollaborationData(IntPtr data) => m_NativePtr = data;
internal ARCollaborationData(NSData data) => m_NativePtr = UnityARKit_CollaborationData_DeserializeFromNSData(data);
void ValidateAndThrow()
{
if (!valid)
throw new InvalidOperationException("ARCollaborationData has already been disposed.");
}
unsafe static IntPtr ConstructUnchecked(void* bytes, int length)
{
using (var nsData = NSData.CreateWithBytesNoCopy(bytes, length))
{
return UnityARKit_CollaborationData_DeserializeFromNSData(nsData);
}
}
unsafe static IntPtr ConstructUnchecked(byte[] bytes, int offset, int length)
{
fixed(void* ptr = &bytes[offset])
{
return ConstructUnchecked(ptr, length);
}
}
[DllImport("__Internal")]
static extern void UnityARKit_CFRelease(IntPtr ptr);
[DllImport("__Internal")]
static extern IntPtr UnityARKit_CollaborationData_DeserializeFromNSData(IntPtr nsData);
[DllImport("__Internal")]
static extern IntPtr UnityARKit_CollaborationData_SerializeToNSData(IntPtr collaborationData);
[DllImport("__Internal")]
static extern ARCollaborationDataPriority UnityARKit_CollaborationData_GetPriority(IntPtr collaborationData);
internal IntPtr m_NativePtr;
}
}