using System.Runtime.InteropServices; using Google.Protobuf; using Mediapipe.PInvoke; namespace Mediapipe.External; [StructLayout(LayoutKind.Sequential)] internal readonly struct SerializedProtoVector { private readonly nint _data; private readonly int _size; public void Dispose() { UnsafeNativeMethods.mp_api_SerializedProtoArray__delete(_data, _size); } public List Deserialize(MessageParser parser) where T : IMessage { List protos = new(_size); Deserialize(parser, protos); return protos; } /// /// Deserializes the data as a list of . /// /// A list of to populate public void Deserialize(MessageParser parser, List protos) where T : IMessage { protos.Clear(); _ = WriteTo(parser, protos); } /// /// Deserializes the data as a list of . /// /// /// The deserialized data will be merged into . /// You may want to clear each field of before calling this method. /// If is less than .Count, the superfluous elements in /// will be untouched. /// /// A list of to populate /// /// The number of written elements in . /// public int WriteTo(MessageParser parser, List protos) where T : IMessage { unsafe { SerializedProto* protoPtr = (SerializedProto*)_data; // overwrite the existing list int len = Math.Min(_size, protos.Count); for (int i = 0; i < len; i++) { SerializedProto serializedProto = Marshal.PtrToStructure((nint)protoPtr++); serializedProto.WriteTo(protos[i]); } for (int i = protos.Count; i < _size; i++) { SerializedProto serializedProto = Marshal.PtrToStructure((nint)protoPtr++); protos.Add(serializedProto.Deserialize(parser)); } } return _size; } }