using System;
using System.Collections.Generic;
using Unity.Collections;
using Unity.Collections.LowLevel.Unsafe;
namespace UnityEngine.XR.ARSubsystems
{
///
/// Utilities for copying native arrays.
///
public static class NativeCopyUtility
{
///
/// Creates a NativeArray from a pointer by first copying
/// s into the NativeArray, and then overwriting the
/// data in the array with , assuming each element in
/// is bytes.
///
///
/// This is useful for native inter-operations with structs that might change over time. This allows
/// new fields to be added to the C# struct without breaking data obtained from data calls.
///
/// The type of struct to copy.
/// A default version of , which will be used to first fill the array
/// before copying from .
/// A pointer to a contiguous block of data of size * .
/// The size of one element in .
/// The number of elements to copy.
/// The allocator to use when creating the NativeArray.
///
/// A new NativeArray populating with and .
/// The caller owns the memory.
///
public static unsafe NativeArray PtrToNativeArrayWithDefault(
T defaultT,
void* source,
int sourceElementSize,
int length,
Allocator allocator) where T : struct
{
var array = CreateArrayFilledWithValue(defaultT, length, allocator);
// Then overwrite with the source data, which may have a different size
UnsafeUtility.MemCpyStride(
destination: array.GetUnsafePtr(),
destinationStride: UnsafeUtility.SizeOf(),
source: source,
sourceStride: sourceElementSize,
elementSize: sourceElementSize,
count: length);
return array;
}
///
/// Fills with repeated copies of .
///
/// The type of the NativeArray. Must be a struct.
/// The array to fill.
/// The value with which to fill the array.
public static unsafe void FillArrayWithValue(NativeArray array, T value) where T : struct
{
// Early out if array is zero, or iOS will crash in MemCpyReplicate.
if (array.Length == 0)
return;
UnsafeUtility.MemCpyReplicate(
array.GetUnsafePtr(),
UnsafeUtility.AddressOf(ref value),
UnsafeUtility.SizeOf(),
array.Length);
}
///
/// Creates a new array allocated with and initialized with
/// copies of .
///
/// The type of the NativeArray to create. Must be a struct.
/// The value with which to fill the array.
/// The length of the array to create.
/// The allocator with which to create the NativeArray.
/// A new NativeArray initialized with copies of .
public static NativeArray CreateArrayFilledWithValue(T value, int length, Allocator allocator) where T : struct
{
var array = new NativeArray(length, allocator, NativeArrayOptions.UninitializedMemory);
FillArrayWithValue(array, value);
return array;
}
///
/// Copies the contents of into the NativeArray .
/// The lengths of both collections must match.
///
/// The type of the NativeArray structs that will be copied
/// The IReadOnlyList that provides the data
/// The NativeArray that will be written to
/// Thrown when there is a mismatch between and sizes.
public static void CopyFromReadOnlyList(IReadOnlyList source, NativeArray destination)
where T : struct
{
if (source.Count != destination.Length)
throw new ArgumentException(
$"{nameof(source)} count {source.Count} doesn't match {nameof(destination)} length {destination.Length}!");
for (var i = 0; i < source.Count; i++)
{
destination[i] = source[i];
}
}
///
/// Copies the contents of into the NativeArray .
/// The lengths of both collections must match.
///
/// The type of the NativeArray structs that will be copied
/// The IReadOnlyCollection that provides the data
/// The NativeArray that will be written to
/// Thrown when there is a mismatch between and sizes.
/// Prefer IReadOnlyList over IReadOnlyCollection for copy performance where possible.
///
public static void CopyFromReadOnlyCollection(IReadOnlyCollection source, NativeArray destination)
where T : struct
{
if (source.Count != destination.Length)
throw new ArgumentException(
$"{nameof(source)} count {source.Count} doesn't match {nameof(destination)} length {destination.Length}!");
var index = 0;
foreach (var item in source)
{
destination[index] = item;
index++;
}
}
}
}