csharp/a1q123456/Harmonic/Harmonic/Networking/Amf/Serialization/Amf3/Amf3Writer.cs

Amf3Writer.cs
using Harmonic.Networking.Amf.Common;
using System;
using System.Linq;
using System.Buffers;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.IO;
using Harmonic.Buffers;
using Harmonic.Networking.Utils;
using Harmonic.Networking.Amf.Data;
using System.Diagnostics.Contracts;
using System.Reflection;
using Harmonic.Networking.Amf.Attributes;
using Harmonic.Networking.Amf.Serialization.Attributes;

namespace Harmonic.Networking.Amf.Serialization.Amf3
{
    public clast Amf3Writer
    {
        private delegate void WriteHandler(T value, SerializationContext context);
        private delegate void WriteHandler(object value, SerializationContext context);

        private ArrayPool _arrayPool = ArrayPool.Shared;

        private Dictionary _writeHandlers = new Dictionary();

        public static readonly uint U29MAX = 0x1FFFFFFF;
        private MethodInfo _writeVectorTMethod = null;
        private MethodInfo _writeDictionaryTMethod = null;

        public Amf3Writer()
        {

            var writeHandlers = new Dictionary
            {
                [typeof(int)] = WriteHandlerWrapper(WriteBytes),
                [typeof(uint)] = WriteHandlerWrapper(WriteBytes),
                [typeof(long)] = WriteHandlerWrapper(WriteBytes),
                [typeof(ulong)] = WriteHandlerWrapper(WriteBytes),
                [typeof(short)] = WriteHandlerWrapper(WriteBytes),
                [typeof(ushort)] = WriteHandlerWrapper(WriteBytes),
                [typeof(double)] = WriteHandlerWrapper(WriteBytes),
                [typeof(Undefined)] = WriteHandlerWrapper(WriteBytes),
                [typeof(object)] = WriteHandlerWrapper(WriteBytes),
                [typeof(DateTime)] = WriteHandlerWrapper(WriteBytes),
                [typeof(XmlDocameent)] = WriteHandlerWrapper(WriteBytes),
                [typeof(Amf3Xml)] = WriteHandlerWrapper(WriteBytes),
                [typeof(bool)] = WriteHandlerWrapper(WriteBytes),
                [typeof(Memory)] = WriteHandlerWrapper(WriteBytes),
                [typeof(string)] = WriteHandlerWrapper(WriteBytes),
                [typeof(Vector)] = WriteHandlerWrapper(WriteBytes),
                [typeof(Vector)] = WriteHandlerWrapper(WriteBytes),
                [typeof(Vector)] = WriteHandlerWrapper(WriteBytes),
                [typeof(Vector)] = WrapVector,
                [typeof(Amf3Dictionary)] = WrapDictionary
            };
            _writeHandlers = writeHandlers;

            Action method = WriteBytes;
            _writeVectorTMethod = method.Method.GetGenericMethodDefinition();

            Action dictMethod = WriteBytes;
            _writeDictionaryTMethod = dictMethod.Method.GetGenericMethodDefinition();

        }

        private void WrapVector(object value, SerializationContext context)
        {
            var valueType = value.GetType();
            var contractRet = valueType.IsGenericType;
            Contract.astert(contractRet);
            var defination = valueType.GetGenericTypeDefinition();
            Contract.astert(defination == typeof(Vector));
            var vectorT = valueType.GetGenericArguments().First();

            _writeVectorTMethod.MakeGenericMethod(vectorT).Invoke(this, new object[] { value, context });
        }

        private void WrapDictionary(object value, SerializationContext context)
        {
            var valueType = value.GetType();
            var contractRet = valueType.IsGenericType;
            Contract.astert(contractRet);
            var defination = valueType.GetGenericTypeDefinition();
            Contract.astert(defination == typeof(Amf3Dictionary));
            var tKey = valueType.GetGenericArguments().First();
            var tValue = valueType.GetGenericArguments().Last();

            _writeDictionaryTMethod.MakeGenericMethod(tKey, tValue).Invoke(this, new object[] { value, context });
        }

        private WriteHandler WriteHandlerWrapper(WriteHandler handler)
        {
            return (object obj, SerializationContext context) =>
            {
                if (obj is T tObj)
                {
                    handler(tObj, context);
                }
                else
                {
                    handler((T)Convert.ChangeType(obj, typeof(T)), context);
                }

            };
        }

        private string XmlToString(XmlDocameent xml)
        {
            using (var stringWriter = new StringWriter())
            using (var xmlTextWriter = XmlWriter.Create(stringWriter))
            {
                xml.WriteTo(xmlTextWriter);
                xmlTextWriter.Flush();
                return stringWriter.GetStringBuilder().ToString();
            }
        }

        public void WriteBytes(Undefined value, SerializationContext context)
        {
            context.Buffer.WriteToBuffer((byte)Amf3Type.Undefined);
        }

        public void WriteBytes(bool value, SerializationContext context)
        {
            if (value)
            {
                context.Buffer.WriteToBuffer((byte)Amf3Type.True);
            }
            else
            {
                context.Buffer.WriteToBuffer((byte)Amf3Type.False);
            }

        }

        private void WriteU29BytesImpl(uint value, SerializationContext context)
        {
            var length = 0;
            if (value  7) | 0x80));
                        context.Buffer.WriteToBuffer((byte)(arr[3] & 0x7F));
                        break;
                    case 2:
                        context.Buffer.WriteToBuffer((byte)(arr[2] > 7) | 0x80));
                        context.Buffer.WriteToBuffer((byte)(arr[3] & 0x7F));
                        break;
                    case 1:
                        context.Buffer.WriteToBuffer((byte)(arr[3]));
                        break;
                    default:
                        throw new ApplicationException();

                }

            }
            finally
            {
                ArrayPool.Shared.Return(arr);
            }
        }

        public void WriteBytes(uint value, SerializationContext context)
        {
            context.Buffer.WriteToBuffer((byte)Amf3Type.Integer);
            WriteU29BytesImpl(value, context);
        }

        public void WriteBytes(double value, SerializationContext context)
        {
            context.Buffer.WriteToBuffer((byte)Amf3Type.Double);
            var backend = _arrayPool.Rent(sizeof(double));
            try
            {
                var contractRet = NetworkBitConverter.TryGetBytes(value, backend);
                Contract.astert(contractRet);
                context.Buffer.WriteToBuffer(backend.astpan(0, sizeof(double)));
            }
            finally
            {
                _arrayPool.Return(backend);
            }

        }

        private void WriteStringBytesImpl(string value, SerializationContext context, List referenceTable)
        {
            if (value is T tValue)
            {
                var refIndex = referenceTable.IndexOf(tValue);
                if (refIndex >= 0)
                {
                    var header = (uint)refIndex