private SignalServiceContent(SignalServiceReceiptMessage receiptMessage, SignalServiceAddress sender, int senderDevice, long timestamp, bool needsReceipt, SignalServiceContentProto serializedState)
        {
            Sender               = sender;
            SenderDevice         = senderDevice;
            Timestamp            = timestamp;
            NeedsReceipt         = needsReceipt;
            this.serializedState = serializedState;

            Message            = null;
            SynchronizeMessage = null;
            CallingMessage     = null;
            ReadMessage        = receiptMessage;
            TypingMessage      = null;
        }
        public static SignalServiceContent?Deserialize(byte[] data)
        {
            try
            {
                if (data == null)
                {
                    return(null);
                }

                SignalServiceContentProto signalServiceContentProto = SignalServiceContentProto.Parser.ParseFrom(data);

                return(CreateFromProto(signalServiceContentProto));
            }
            catch (Exception ex) when(ex is InvalidProtocolBufferException || ex is ProtocolInvalidMessageException ||
                                      ex is ProtocolInvalidKeyException)
            {
                // We do not expect any of these exceptions if this byte[] has come from serialize.
                throw new ArgumentException(null, ex);
            }
        }
        /// <summary>
        /// Decrypt a received <see cref="SignalServiceEnvelope"/>
        /// </summary>
        /// <param name="envelope">The received SignalServiceEnvelope</param>
        /// <returns>a decrypted SignalServiceContent</returns>
        public SignalServiceContent?Decrypt(SignalServiceEnvelope envelope)
        {
            try
            {
                if (envelope.HasLegacyMessage())
                {
                    Plaintext   plaintext   = Decrypt(envelope, envelope.GetLegacyMessage());
                    DataMessage dataMessage = DataMessage.Parser.ParseFrom(plaintext.data);

                    SignalServiceContentProto contentProto = new SignalServiceContentProto()
                    {
                        LocalAddress      = SignalServiceAddressProtobufSerializer.ToProtobuf(localAddress),
                        Metadata          = SignalServiceMetadataProtobufSerializer.ToProtobuf(plaintext.Metadata),
                        LegacyDataMessage = dataMessage
                    };

                    return(SignalServiceContent.CreateFromProto(contentProto));
                }
                else if (envelope.HasContent())
                {
                    Plaintext plaintext = Decrypt(envelope, envelope.Envelope.Content.ToByteArray());
                    Content   content   = Content.Parser.ParseFrom(plaintext.data);

                    SignalServiceContentProto contentProto = new SignalServiceContentProto()
                    {
                        LocalAddress = SignalServiceAddressProtobufSerializer.ToProtobuf(localAddress),
                        Metadata     = SignalServiceMetadataProtobufSerializer.ToProtobuf(plaintext.Metadata),
                        Content      = content
                    };

                    return(SignalServiceContent.CreateFromProto(contentProto));
                }
                return(null);
            }
            catch (InvalidProtocolBufferException e)
            {
                throw new InvalidMetadataMessageException(e);
            }
        }
        /// <summary>
        /// Takes internal protobuf serialization format and processes it into a <see cref="SignalServiceContent"/>.
        /// </summary>
        /// <param name="serviceContentProto"></param>
        /// <returns></returns>
        /// <exception cref="ProtocolInvalidMessageException"></exception>
        /// <exception cref="ProtocolInvalidKeyException"></exception>
        public static SignalServiceContent?CreateFromProto(SignalServiceContentProto serviceContentProto)
        {
            SignalServiceMetadata metadata     = SignalServiceMetadataProtobufSerializer.FromProtobuf(serviceContentProto.Metadata);
            SignalServiceAddress  localAddress = SignalServiceAddressProtobufSerializer.FromProtobuf(serviceContentProto.LocalAddress);

            if (serviceContentProto.DataCase == SignalServiceContentProto.DataOneofCase.LegacyDataMessage)
            {
                DataMessage message = serviceContentProto.LegacyDataMessage;

                return(new SignalServiceContent(CreateSignalServiceMessage(metadata, message),
                                                metadata.Sender,
                                                metadata.SenderDevice,
                                                metadata.Timestamp,
                                                metadata.NeedsReceipt,
                                                serviceContentProto));
            }
            else if (serviceContentProto.DataCase == SignalServiceContentProto.DataOneofCase.Content)
            {
                Content message = serviceContentProto.Content;

                if (message.DataMessage != null)
                {
                    return(new SignalServiceContent(CreateSignalServiceMessage(metadata, message.DataMessage),
                                                    metadata.Sender,
                                                    metadata.SenderDevice,
                                                    metadata.Timestamp,
                                                    metadata.NeedsReceipt,
                                                    serviceContentProto));
                }
                else if (message.SyncMessage != null && localAddress.Matches(metadata.Sender))
                {
                    return(new SignalServiceContent(CreateSynchronizeMessage(metadata, message.SyncMessage),
                                                    metadata.Sender,
                                                    metadata.SenderDevice,
                                                    metadata.Timestamp,
                                                    metadata.NeedsReceipt,
                                                    serviceContentProto));
                }
                else if (message.CallingMessage != null)
                {
                    return(new SignalServiceContent(CreateCallingMessage(message.CallingMessage),
                                                    metadata.Sender,
                                                    metadata.SenderDevice,
                                                    metadata.Timestamp,
                                                    metadata.NeedsReceipt,
                                                    serviceContentProto));
                }
                else if (message.ReceiptMessage != null)
                {
                    return(new SignalServiceContent(CreateReceiptMessage(metadata, message.ReceiptMessage),
                                                    metadata.Sender,
                                                    metadata.SenderDevice,
                                                    metadata.Timestamp,
                                                    metadata.NeedsReceipt,
                                                    serviceContentProto));
                }
                else if (message.TypingMessage != null)
                {
                    return(new SignalServiceContent(CreateTypingMessage(metadata, message.TypingMessage),
                                                    metadata.Sender,
                                                    metadata.SenderDevice,
                                                    metadata.Timestamp,
                                                    false,
                                                    serviceContentProto));
                }
            }

            return(null);
        }