using System;
using Unity.Collections;
using Unity.Collections.LowLevel.Unsafe;
namespace UnityEngine.XR.ARKit
{
///
/// Use this to construct an incrementally from serialized bytes.
///
///
/// This struct can be useful if you receive data through a stream. If you already have all
/// the bytes, use a constructor instead.
/// This struct represents a native resource and must be explicitly disposed when no longer needed.
/// While this struct is not thread safe, you can construct, Dispose, and Append from any thread.
///
public struct ARCollaborationDataBuilder : IDisposable, IEquatable
{
internal NSMutableData m_NSMutableData;
///
/// Whether the has allocated any data. If true,
/// this struct must be disposed to avoid leaking native resources. If false, this struct
/// either never allocated memory
/// (with or )
/// or it has already been d.
///
public bool hasData => m_NSMutableData.created;
///
/// The number of bytes owned by this struct.
///
///
///
///
public int length => m_NSMutableData.created ? m_NSMutableData.length : 0;
///
/// Converts the bytes accumulated through calls to to an .
/// The caller is responsible for disposing the returned .
///
/// A new constructed from the bytes added to this .
/// Thrown if is not supported.
/// Check for support with .
/// Thrown if is false.
public ARCollaborationData ToCollaborationData()
{
if (!ARKitSessionSubsystem.supportsCollaboration)
throw new NotSupportedException("ARCollaborationData is not supported by this version of iOS.");
if (!hasData)
throw new InvalidOperationException("No data to convert to ARCollaborationData.");
return new ARCollaborationData(m_NSMutableData);
}
///
/// Appends bytes of the array to an existing array of bytes.
///
/// A buffer containing bytes to append.
/// The offset within to start appending bytes to the internal array.
/// The number of bytes from to append. Must be less than `.Length` + .
/// Thrown if is .
/// Thrown if is less than zero.
/// Thrown if is less than zero.
/// Thrown if is less than zero or greater than the length of .
public unsafe void Append(byte[] buffer, int offset, int size)
{
if (buffer == null)
throw new ArgumentNullException(nameof(buffer));
if (size < 0)
throw new ArgumentOutOfRangeException(nameof(size), size, $"'{nameof(size)}' must be greater than or equal to zero.");
if (offset < 0)
throw new ArgumentOutOfRangeException(nameof(offset), offset, $"'{nameof(offset)}' must be greater than or equal to zero.");
if (buffer.Length < size + offset)
throw new InvalidOperationException($"Reading {size} bytes starting at offset {offset} would write past the end of '{nameof(buffer)}' (buffer length = {buffer.Length}).");
fixed (byte* ptr = &buffer[offset])
{
AppendUnchecked(ptr, size);
}
}
///
/// Appends all bytes of the array to an existing array of bytes.
///
/// A buffer containing bytes to append.
/// Thrown if is .
public unsafe void Append(byte[] buffer)
{
if (buffer == null)
throw new ArgumentNullException(nameof(buffer));
fixed (byte* ptr = buffer)
{
AppendUnchecked(ptr, buffer.Length);
}
}
///
/// Appends to an existing array of bytes.
///
/// An array of bytes to append to the existing data.
/// Thrown if does not reference valid data.
public unsafe void Append(NativeSlice bytes)
{
void* ptr = bytes.GetUnsafePtr();
if (ptr == null)
throw new ArgumentException("Invalid NativeSlice", nameof(bytes));
AppendUnchecked(ptr, bytes.Length);
}
///
/// Releases the native resource.
///
public void Dispose() => m_NSMutableData.Dispose();
///
/// Appends data to the underlying `NSMutableData` array.
///
/// A pointer to an array of bytes to append to the existing data.
/// The number of bytes pointed to by .
unsafe void AppendUnchecked(void* bytes, int size)
{
if (m_NSMutableData.created)
{
m_NSMutableData.AppendBytes(bytes, size);
}
else
{
m_NSMutableData = new NSMutableData(bytes, size);
}
}
///
/// Computes a hash code suitable for use in a Dictionary or HashSet.
///
/// The hash code for this instance.
public override int GetHashCode() => m_NSMutableData.GetHashCode();
///
/// Compares for equality.
///
/// The object to compare for equality.
/// if is of type `ARCollaborationDataBuilder` and
/// compares equal to this instance with .
/// Otherwise, returns .
public override bool Equals(object obj) => (obj is ARCollaborationDataBuilder) && Equals((ARCollaborationDataBuilder)obj);
///
/// Compares for equality.
///
/// The to compare against.
/// if all fields of this instance compare equal to .
/// Otherwise, returns .
public bool Equals(ARCollaborationDataBuilder other) => m_NSMutableData.Equals(other.m_NSMutableData);
///
/// Compares for equality. Equivalent to .
///
/// The left-hand side of the comparison.
/// The right-hand side of the comparison.
/// if all fields of the instances are equal. Otherwise, returns .
public static bool operator ==(ARCollaborationDataBuilder lhs, ARCollaborationDataBuilder rhs) => lhs.Equals(rhs);
///
/// Compares for inequality. Equivalent to !.
///
/// The left-hand side of the comparison.
/// The right-hand side of the comparison.
/// if any of the fields of the instances are not equal. Otherwise, returns .
public static bool operator !=(ARCollaborationDataBuilder lhs, ARCollaborationDataBuilder rhs) => !lhs.Equals(rhs);
}
}