EncryptionDataSerializer
using Azure.Core;
using System;
using System.Collections.Generic;
using System.Text;
using System.Text.Json;
namespace Azure.Storage.Cryptography.Models
{
    internal static class EncryptionDataSerializer
    {
        private const string EncryptionAgent_EncryptionVersionName = "Protocol";
        public static string Serialize(EncryptionData data)
        {
            return Encoding.UTF8.GetString(SerializeEncryptionData(data).ToArray());
        }
        private static ReadOnlyMemory<byte> SerializeEncryptionData(EncryptionData data)
        {
            ArrayBufferWriter<byte> arrayBufferWriter = new ArrayBufferWriter<byte>();
            using (Utf8JsonWriter utf8JsonWriter = new Utf8JsonWriter(arrayBufferWriter, default(JsonWriterOptions))) {
                utf8JsonWriter.WriteStartObject();
                WriteEncryptionData(utf8JsonWriter, data);
                utf8JsonWriter.WriteEndObject();
                utf8JsonWriter.Flush();
                return arrayBufferWriter.WrittenMemory;
            }
        }
        public static void WriteEncryptionData(Utf8JsonWriter json, EncryptionData data)
        {
            json.WriteString("EncryptionMode", data.EncryptionMode);
            json.WriteStartObject("WrappedContentKey");
            WriteWrappedKey(json, data.WrappedContentKey);
            json.WriteEndObject();
            json.WriteStartObject("EncryptionAgent");
            WriteEncryptionAgent(json, data.EncryptionAgent);
            json.WriteEndObject();
            if (data.ContentEncryptionIV != null)
                json.WriteString("ContentEncryptionIV", Convert.ToBase64String(data.ContentEncryptionIV));
            if (data.EncryptedRegionInfo != null) {
                json.WriteStartObject("EncryptedRegionInfo");
                WriteEncryptedRegionInfo(json, data.EncryptedRegionInfo);
                json.WriteEndObject();
            }
            json.WriteStartObject("KeyWrappingMetadata");
            WriteDictionary(json, data.KeyWrappingMetadata);
            json.WriteEndObject();
        }
        private static void WriteEncryptedRegionInfo(Utf8JsonWriter json, EncryptedRegionInfo encryptedRegionInfo)
        {
            json.WriteNumber("DataLength", encryptedRegionInfo.DataLength);
            json.WriteNumber("NonceLength", encryptedRegionInfo.NonceLength);
        }
        private static void WriteWrappedKey(Utf8JsonWriter json, KeyEnvelope key)
        {
            json.WriteString("KeyId", key.KeyId);
            json.WriteString("EncryptedKey", Convert.ToBase64String(key.EncryptedKey));
            json.WriteString("Algorithm", key.Algorithm);
        }
        private static void WriteEncryptionAgent(Utf8JsonWriter json, EncryptionAgent encryptionAgent)
        {
            json.WriteString("Protocol", encryptionAgent.EncryptionVersion.Serialize());
            json.WriteString("EncryptionAlgorithm", encryptionAgent.EncryptionAlgorithm.ToString());
        }
        private static void WriteDictionary(Utf8JsonWriter json, IDictionary<string, string> dictionary)
        {
            foreach (KeyValuePair<string, string> item in dictionary) {
                json.WriteString(item.Key, item.Value);
            }
        }
        public static EncryptionData Deserialize(string serializedData)
        {
            Utf8JsonReader reader = new Utf8JsonReader(Encoding.UTF8.GetBytes(serializedData), default(JsonReaderOptions));
            return DeserializeEncryptionData(ref reader);
        }
        public static EncryptionData DeserializeEncryptionData(ref Utf8JsonReader reader)
        {
            using (JsonDocument jsonDocument = JsonDocument.ParseValue(ref reader))
                return ReadEncryptionData(jsonDocument.RootElement);
        }
        public static EncryptionData ReadEncryptionData(JsonElement root)
        {
            EncryptionData encryptionData = new EncryptionData();
            foreach (JsonProperty item in root.EnumerateObject()) {
                ReadPropertyValue(encryptionData, item);
            }
            return encryptionData;
        }
        private static void ReadPropertyValue(EncryptionData data, JsonProperty property)
        {
            JsonElement value;
            JsonElement.ObjectEnumerator objectEnumerator;
            JsonElement.ObjectEnumerator enumerator;
            if (property.Name.Equals("EncryptionMode", StringComparison.InvariantCultureIgnoreCase)) {
                value = property.Value;
                data.EncryptionMode = value.GetString();
            } else if (property.Name.Equals("WrappedContentKey", StringComparison.InvariantCultureIgnoreCase)) {
                KeyEnvelope keyEnvelope = new KeyEnvelope();
                value = property.Value;
                objectEnumerator = value.EnumerateObject();
                enumerator = objectEnumerator.GetEnumerator();
                try {
                    while (enumerator.MoveNext()) {
                        JsonProperty current = enumerator.Current;
                        ReadPropertyValue(keyEnvelope, current);
                    }
                } finally {
                    ((IDisposable)enumerator).Dispose();
                }
                data.WrappedContentKey = keyEnvelope;
            } else if (property.Name.Equals("EncryptionAgent", StringComparison.InvariantCultureIgnoreCase)) {
                EncryptionAgent encryptionAgent = new EncryptionAgent();
                value = property.Value;
                objectEnumerator = value.EnumerateObject();
                enumerator = objectEnumerator.GetEnumerator();
                try {
                    while (enumerator.MoveNext()) {
                        JsonProperty current2 = enumerator.Current;
                        ReadPropertyValue(encryptionAgent, current2);
                    }
                } finally {
                    ((IDisposable)enumerator).Dispose();
                }
                data.EncryptionAgent = encryptionAgent;
            } else if (property.Name.Equals("ContentEncryptionIV", StringComparison.InvariantCultureIgnoreCase)) {
                value = property.Value;
                data.ContentEncryptionIV = Convert.FromBase64String(value.GetString());
            } else if (property.Name.Equals("KeyWrappingMetadata", StringComparison.InvariantCultureIgnoreCase)) {
                Dictionary<string, string> dictionary = new Dictionary<string, string>();
                value = property.Value;
                objectEnumerator = value.EnumerateObject();
                enumerator = objectEnumerator.GetEnumerator();
                try {
                    while (enumerator.MoveNext()) {
                        JsonProperty current3 = enumerator.Current;
                        Dictionary<string, string> dictionary2 = dictionary;
                        string name = current3.Name;
                        value = current3.Value;
                        dictionary2.Add(name, value.GetString());
                    }
                } finally {
                    ((IDisposable)enumerator).Dispose();
                }
                data.KeyWrappingMetadata = dictionary;
            } else if (property.Name.Equals("EncryptedRegionInfo", StringComparison.InvariantCultureIgnoreCase)) {
                EncryptedRegionInfo encryptedRegionInfo = new EncryptedRegionInfo();
                value = property.Value;
                objectEnumerator = value.EnumerateObject();
                enumerator = objectEnumerator.GetEnumerator();
                try {
                    while (enumerator.MoveNext()) {
                        JsonProperty current4 = enumerator.Current;
                        ReadPropertyValue(encryptedRegionInfo, current4);
                    }
                } finally {
                    ((IDisposable)enumerator).Dispose();
                }
                data.EncryptedRegionInfo = encryptedRegionInfo;
            }
        }
        private static void ReadPropertyValue(KeyEnvelope key, JsonProperty property)
        {
            JsonElement value;
            if (property.Name.Equals("Algorithm", StringComparison.InvariantCultureIgnoreCase)) {
                value = property.Value;
                key.Algorithm = value.GetString();
            } else if (property.Name.Equals("EncryptedKey", StringComparison.InvariantCultureIgnoreCase)) {
                value = property.Value;
                key.EncryptedKey = Convert.FromBase64String(value.GetString());
            } else if (property.Name.Equals("KeyId", StringComparison.InvariantCultureIgnoreCase)) {
                value = property.Value;
                key.KeyId = value.GetString();
            }
        }
        private static void ReadPropertyValue(EncryptionAgent agent, JsonProperty property)
        {
            JsonElement value;
            if (property.Name.Equals("EncryptionAlgorithm", StringComparison.InvariantCultureIgnoreCase)) {
                value = property.Value;
                agent.EncryptionAlgorithm = new ClientSideEncryptionAlgorithm(value.GetString());
            } else if (property.Name.Equals("Protocol", StringComparison.InvariantCultureIgnoreCase)) {
                value = property.Value;
                agent.EncryptionVersion = value.GetString().ToClientSideEncryptionVersion();
            }
        }
        private static void ReadPropertyValue(EncryptedRegionInfo info, JsonProperty property)
        {
            JsonElement value;
            if (property.Name.Equals("NonceLength", StringComparison.InvariantCultureIgnoreCase)) {
                value = property.Value;
                info.NonceLength = value.GetInt32();
            } else if (property.Name.Equals("DataLength", StringComparison.InvariantCultureIgnoreCase)) {
                value = property.Value;
                info.DataLength = value.GetInt32();
            }
        }
    }
}