using System; using System.IO; using System.Runtime.Serialization; using System.Xml; using ProtoBuf.Meta; namespace ProtoBuf.ServiceModel; public sealed class XmlProtoSerializer : XmlObjectSerializer { private readonly TypeModel model; private readonly int key; private readonly bool isList; private readonly bool isEnum; private readonly Type type; private const string PROTO_ELEMENT = "proto"; internal XmlProtoSerializer(TypeModel model, int key, Type type, bool isList) { if (key < 0) { throw new ArgumentOutOfRangeException("key"); } this.model = model ?? throw new ArgumentNullException("model"); this.key = key; this.isList = isList; this.type = type ?? throw new ArgumentOutOfRangeException("type"); isEnum = Helpers.IsEnum(type); } public static XmlProtoSerializer TryCreate(TypeModel model, Type type) { if (model == null) { throw new ArgumentNullException("model"); } if ((object)type == null) { throw new ArgumentNullException("type"); } bool flag; int num = GetKey(model, ref type, out flag); if (num >= 0) { return new XmlProtoSerializer(model, num, type, flag); } return null; } public XmlProtoSerializer(TypeModel model, Type type) { if (model == null) { throw new ArgumentNullException("model"); } if ((object)type == null) { throw new ArgumentNullException("type"); } key = GetKey(model, ref type, out isList); this.model = model; this.type = type; isEnum = Helpers.IsEnum(type); if (key < 0) { throw new ArgumentOutOfRangeException("type", "Type not recognised by the model: " + type.FullName); } } private static int GetKey(TypeModel model, ref Type type, out bool isList) { if (model != null && (object)type != null) { int num = model.GetKey(ref type); if (num >= 0) { isList = false; return num; } Type listItemType = TypeModel.GetListItemType(model, type); if ((object)listItemType != null) { num = model.GetKey(ref listItemType); if (num >= 0) { isList = true; return num; } } } isList = false; return -1; } public override void WriteEndObject(XmlDictionaryWriter writer) { if (writer == null) { throw new ArgumentNullException("writer"); } ((XmlWriter)writer).WriteEndElement(); } public override void WriteStartObject(XmlDictionaryWriter writer, object graph) { if (writer == null) { throw new ArgumentNullException("writer"); } ((XmlWriter)writer).WriteStartElement("proto"); } public override void WriteObjectContent(XmlDictionaryWriter writer, object graph) { if (writer == null) { throw new ArgumentNullException("writer"); } if (graph == null) { ((XmlWriter)writer).WriteAttributeString("nil", "true"); return; } using MemoryStream memoryStream = new MemoryStream(); if (isList) { model.Serialize(memoryStream, graph, null); } else { using ProtoWriter dest = ProtoWriter.Create(memoryStream, model); model.Serialize(key, graph, dest); } byte[] buffer = memoryStream.GetBuffer(); ((XmlWriter)writer).WriteBase64(buffer, 0, (int)memoryStream.Length); } public override bool IsStartObject(XmlDictionaryReader reader) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Invalid comparison between Unknown and I4 if (reader == null) { throw new ArgumentNullException("reader"); } ((XmlReader)reader).MoveToContent(); if ((int)((XmlReader)reader).NodeType == 1) { return ((XmlReader)reader).Name == "proto"; } return false; } public override object ReadObject(XmlDictionaryReader reader, bool verifyObjectName) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) if (reader == null) { throw new ArgumentNullException("reader"); } ((XmlReader)reader).MoveToContent(); bool isEmptyElement = ((XmlReader)reader).IsEmptyElement; bool flag = ((XmlReader)reader).GetAttribute("nil") == "true"; ((XmlReader)reader).ReadStartElement("proto"); if (flag) { if (!isEmptyElement) { ((XmlReader)reader).ReadEndElement(); } return null; } if (isEmptyElement) { if (isList || isEnum) { return model.Deserialize(Stream.Null, null, type, null); } ProtoReader protoReader = null; try { protoReader = ProtoReader.Create(Stream.Null, model, null, -1L); return model.Deserialize(key, null, protoReader); } finally { ProtoReader.Recycle(protoReader); } } object result; using (MemoryStream source = new MemoryStream(reader.ReadContentAsBase64())) { if (isList || isEnum) { result = model.Deserialize(source, null, type, null); } else { ProtoReader protoReader2 = null; try { protoReader2 = ProtoReader.Create(source, model, null, -1L); result = model.Deserialize(key, null, protoReader2); } finally { ProtoReader.Recycle(protoReader2); } } } ((XmlReader)reader).ReadEndElement(); return result; } }