namespace Unity.Collections.LowLevel.Unsafe
{
    /// 
    /// Extension methods for DataStream.
    /// 
    [GenerateTestsForBurstCompatibility]
    public static class DataStreamExtensions
    {
        /// 
        /// Initializes a new instance of the DataStreamWriter struct with externally owned memory
        /// 
        /// Pointer to the data
        /// Length of the data
        /// A new instance of the 
        public static unsafe DataStreamWriter Create(byte* data, int length)
        {
            var na = NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray(data, length, Allocator.None);
#if ENABLE_UNITY_COLLECTIONS_CHECKS
            NativeArrayUnsafeUtility.SetAtomicSafetyHandle(ref na, AtomicSafetyHandle.GetTempMemoryHandle());
#endif
            return new DataStreamWriter(na);
        }
        /// 
        /// Appends a specified number of bytes from the buffer to the data stream.
        /// 
        /// Data stream writer.
        /// Pointer to the data.
        /// A positive number of bytes to write.
        /// Whether the write was successful
        public static unsafe bool WriteBytesUnsafe(this ref DataStreamWriter writer, byte* data, int bytes)
        {
            var dataArray = NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray(data, bytes, Allocator.None);
#if ENABLE_UNITY_COLLECTIONS_CHECKS
            NativeArrayUnsafeUtility.SetAtomicSafetyHandle(ref dataArray, AtomicSafetyHandle.GetTempMemoryHandle());
#endif
            return writer.WriteBytes(dataArray);
        }
        /// 
        /// Read and copy data to the memory location pointed to, an error will
        /// be logged if the  will put the reader out of bounds on the current read pointer.
        /// 
        /// Data stream reader.
        /// Pointer to the data.
        /// Number of bytes to read.
        public static unsafe void ReadBytesUnsafe(this ref DataStreamReader reader, byte* data, int length)
        {
            var dataArray = NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray(data, length, Allocator.None);
#if ENABLE_UNITY_COLLECTIONS_CHECKS
            NativeArrayUnsafeUtility.SetAtomicSafetyHandle(ref dataArray, AtomicSafetyHandle.GetTempMemoryHandle());
#endif
            reader.ReadBytes(dataArray);
        }
        /// 
        /// Reads a 2-byte length value from the current stream, reads the specified number of bytes
        /// to the buffer and advances the current position of the stream by the length of the string.
        /// 
        /// Data stream reader.
        /// Buffer to write the string bytes to.
        /// Max number of bytes allowed to be read into the buffer.
        /// The number of bytes written to the data buffer.
        public static unsafe ushort ReadFixedStringUnsafe(this ref DataStreamReader reader, byte* data, int maxLength)
        {
            var dataArray = NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray(data, maxLength, Allocator.Temp);
#if ENABLE_UNITY_COLLECTIONS_CHECKS
            NativeArrayUnsafeUtility.SetAtomicSafetyHandle(ref dataArray, AtomicSafetyHandle.GetTempMemoryHandle());
#endif
            return reader.ReadFixedString(dataArray);
        }
        /// 
        /// Writes a delta FixedString value to the data stream using a .
        ///
        /// If the value cannot be written  will return true.
        /// 
        /// Data stream reader.
        /// Pointer to a packed fixed string.
        /// Max number of bytes allowed to be read into the pointer.
        /// Pointer to the previous value, used to compute the diff.
        /// The length of the previous value.
        ///  model for writing value in a packed manner.
        /// Whether the write was successful
        public static unsafe ushort ReadPackedFixedStringDeltaUnsafe(this ref DataStreamReader reader, byte* data, int maxLength, byte* baseData, ushort baseLength, StreamCompressionModel model)
        {
            var current = NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray(data, maxLength, Allocator.Temp);
            var baseline = NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray(baseData, baseLength, Allocator.Temp);
#if ENABLE_UNITY_COLLECTIONS_CHECKS
            var safetyHandle = AtomicSafetyHandle.GetTempMemoryHandle();
            NativeArrayUnsafeUtility.SetAtomicSafetyHandle(ref current, safetyHandle);
            NativeArrayUnsafeUtility.SetAtomicSafetyHandle(ref baseline, safetyHandle);
#endif
            return reader.ReadPackedFixedStringDelta(current, baseline, model);
        }
        /// 
        /// Get a pointer to the stream's data. Note that the pointer always points at the
        /// beginning of the data, no matter how much was read from the stream.
        /// 
        /// Performs a job safety check for read-only access.
        /// Data stream reader.
        /// A pointer to the stream's data.
        public static unsafe void* GetUnsafeReadOnlyPtr(this ref DataStreamReader reader)
        {
            reader.CheckRead();
            return reader.m_BufferPtr;
        }
    }
}