// Copyright (c) Facebook, Inc. and its affiliates // SPDX-License-Identifier: MIT OR Apache-2.0 using System; using System.Collections; using System.Collections.Generic; using System.Linq; namespace Serde { /// /// Immutable wrapper class around T[]. Implements value semantics for /// and . /// public class ValueArray : IEquatable>, IReadOnlyList, IStructuralEquatable where T: IEquatable { private readonly T[] array; private int? hashCode; public int Count => array.Length; public T this[int index] => array[index]; public ValueArray(T[] data) { array = data ?? throw new ArgumentNullException(nameof(data)); hashCode = null; } public T[] ToArray() => array.ToArray(); public static implicit operator ReadOnlySpan(ValueArray bytes) => bytes.array; public ReadOnlySpan AsReadOnlySpan() => array; public override bool Equals(object obj) => obj is ValueArray bytes && Equals(bytes); public bool Equals(ValueArray other) { if (other == null) return false; if (ReferenceEquals(this, other)) return true; if (Count != other.Count) return false; for (int i = 0; i < Count; i++) if (!array[i].Equals(other[i])) return false; return true; } public static bool operator ==(ValueArray left, ValueArray right) => Equals(left, right); public static bool operator !=(ValueArray left, ValueArray right) => !Equals(left, right); public IEnumerator GetEnumerator() => ((IEnumerable)array).GetEnumerator(); IEnumerator IEnumerable.GetEnumerator() => array.GetEnumerator(); public override int GetHashCode() { unchecked { if (hashCode.HasValue) return hashCode.Value; int code = 1849862467; foreach (T elem in array) code = code * 31 + elem.GetHashCode(); hashCode = code; return code; } } public bool Equals(object other, IEqualityComparer comparer) { return ((IStructuralEquatable)array).Equals(other, comparer); } public int GetHashCode(IEqualityComparer comparer) { return ((IStructuralEquatable)array).GetHashCode(comparer); } } }