public async Task SerializeAsync(Stream stream, object message, Type type, CancellationToken cancellationToken = default)
        {
            using (var serializedMemory = SerializeCore(message, type))
            {
                var uncompressed = serializedMemory.Memory;

                var compressedBuff = ArrayPool <byte> .Shared.Rent(LZ4Codec.MaximumOutputSize(uncompressed.Length) + HeaderLength);

                try
                {
                    //write body, skip header
                    var compressedLength = LZ4Codec.Encode(
                        uncompressed.Span,
                        new Span <byte>(compressedBuff, HeaderLength, compressedBuff.Length - HeaderLength));

                    //write header
                    var offset = 0;
                    SerializerBinary.WriteByte(ref compressedBuff, ref offset, Header);
                    SerializerBinary.WriteInt32Fixed(ref compressedBuff, ref offset, compressedLength);
                    SerializerBinary.WriteInt32Fixed(ref compressedBuff, ref offset, uncompressed.Length);

                    await stream.WriteAsync(compressedBuff, 0, compressedLength + HeaderLength, cancellationToken).ConfigureAwait(false);
                }
                finally
                {
                    ArrayPool <byte> .Shared.Return(compressedBuff);
                }
            }
        }
예제 #2
0
        public void Serialize(ref byte[] buffer, ref int offset, IPAddress value)
        {
            var isIPv4 = value.AddressFamily == AddressFamily.InterNetwork;

            SerializerBinary.WriteByte(ref buffer, ref offset, (byte)(isIPv4 ? 0 : 1));
            var ip = value.GetAddressBytes();

            for (var i = 0; i < ip.Length; i++)
            {
                SerializerBinary.WriteByte(ref buffer, ref offset, ip[i]);
            }
        }
예제 #3
0
        public void Serialize(ref byte[] buffer, ref int offset, Color value)
        {
            bool isKnown = value.IsKnownColor;

            SerializerBinary.WriteByte(ref buffer, ref offset, isKnown ? (byte)1 : (byte)0);

            if (isKnown)
            {
                int knownColor = (int)value.ToKnownColor();
                SerializerBinary.WriteInt32Fixed(ref buffer, ref offset, knownColor);
            }
            else
            {
                SerializerBinary.WriteInt32Fixed(ref buffer, ref offset, value.ToArgb());
            }
        }
예제 #4
0
        public void Serialize(ref byte[] buffer, ref int offset, Type type)
        {
            // Null
            if (type == null)
            {
                SerializerBinary.WriteUInt32Bias(ref buffer, ref offset, Null, Bias);
                return;
            }

            var typeCache = _serializer.InstanceData.TypeCache;

            // Existing
            if (typeCache.TryGetExistingObjectId(type, out int id))
            {
                SerializerBinary.WriteUInt32Bias(ref buffer, ref offset, id, Bias);
                return;
            }


            // Mode: New


            // Is it a composite type that we have to split into its parts? (aka any generic)
            bool isClosed = !type.ContainsGenericParameters;

            if (isClosed && type.IsGenericType)
            {
                SerializerBinary.WriteUInt32Bias(ref buffer, ref offset, NewGeneric, Bias);

                // Split and write

                // Base
                var baseType = type.GetGenericTypeDefinition();
                Serialize(ref buffer, ref offset, baseType);

                // Args
                var genericArgs = type.GetGenericArguments();

                SerializerBinary.WriteByte(ref buffer, ref offset, (byte)(genericArgs.Length));                 // We need count. Ex: Action<T1> and Action<T1, T2> share the name
                for (int i = 0; i < genericArgs.Length; i++)
                {
                    Serialize(ref buffer, ref offset, genericArgs[i]);
                }

                // Register composite type
                typeCache.RegisterObject(type);
            }
            else
            {
                SerializerBinary.WriteUInt32Bias(ref buffer, ref offset, NewSingle, Bias);

                // Open generic, something that can be serialized alone
                var typeName = _typeBinder.GetBaseName(type);

                // Name
                SerializerBinary.WriteString(ref buffer, ref offset, typeName);

                // Register single type
                typeCache.RegisterObject(type);
            }

            // todo: do we put this only in the if or else part? or is it ok here? it should be ok, since we want to embed the schema of every type
            if (_serializer.Config.VersionTolerance == VersionTolerance.AutomaticEmbedded)
            {
                if (!CerasSerializer.FrameworkAssemblies.Contains(type.Assembly))
                {
                    _serializer.WriteSchemaForType(ref buffer, ref offset, type);
                }
            }
        }
예제 #5
0
        public void Serialize(ref byte[] buffer, ref int offset, Type type)
        {
            // Null
            if (type == null)
            {
                SerializerBinary.WriteUInt32Bias(ref buffer, ref offset, Null, Bias);
                return;
            }

            var typeCache = _serializer.InstanceData.TypeCache;

            // Existing
            if (typeCache.TryGetExistingObjectId(type, out int id))
            {
                SerializerBinary.WriteUInt32Bias(ref buffer, ref offset, id, Bias);
                return;
            }


            // Mode: New


            // Is it a composite type that we have to split into its parts? (aka any generic)
            bool isClosed = !type.ContainsGenericParameters;

            if (isClosed && type.IsGenericType)
            {
                SerializerBinary.WriteUInt32Bias(ref buffer, ref offset, NewComposite, Bias);

                // Split and write

                // Base
                var baseType = type.GetGenericTypeDefinition();
                Serialize(ref buffer, ref offset, baseType);


                // Args
                var genericArgs = type.GetGenericArguments();

                SerializerBinary.WriteByte(ref buffer, ref offset, (byte)(genericArgs.Length));                 // We need count. Ex: Action<T1> and Action<T1, T2> share the name.
                for (int i = 0; i < genericArgs.Length; i++)
                {
                    Serialize(ref buffer, ref offset, genericArgs[i]);
                }


                // Register composite type
                typeCache.RegisterObject(type);
            }
            else
            {
                SerializerBinary.WriteUInt32Bias(ref buffer, ref offset, NewSingle, Bias);

                // Open generic, something that can be serialized alone

                var typeName = _typeBinder.GetBaseName(type);

                // Name
                SerializerBinary.WriteString(ref buffer, ref offset, typeName);


                // Register single type
                typeCache.RegisterObject(type);
            }
        }
예제 #6
0
        public void Serialize(ref byte[] buffer, ref int offset, T member)
        {
            // Declaring type
            _typeFormatter.Serialize(ref buffer, ref offset, member.DeclaringType);

            byte bindingData = 0;

            switch (member.MemberType)
            {
            // Write all the data we need to resolve overloads
            case MemberTypes.Constructor:
            case MemberTypes.Method:
                var method = (MethodBase)(MemberInfo)member;

                if (method.ContainsGenericParameters)
                {
                    throw new ArgumentException($"The method or constructor '{method.DeclaringType?.FullName}.{method.Name}' can not be serialized because it is not closed. If you need this functionality (or don't know what this means) please report an issue on GitHub.");
                }

                bindingData = PackBindingData(method.IsStatic, ReflectionTypeToCeras(member.MemberType));

                // 1. Binding data
                SerializerBinary.WriteByte(ref buffer, ref offset, bindingData);

                // 2. Method Name
                _stringFormatter.Serialize(ref buffer, ref offset, method.Name);

                // 3. Parameters
                var args = method.GetParameters();
                SerializerBinary.WriteInt32(ref buffer, ref offset, args.Length);
                for (int i = 0; i < args.Length; i++)
                {
                    _typeFormatter.Serialize(ref buffer, ref offset, args[i].ParameterType);
                }

                break;

            case MemberTypes.Property:
                PropertyInfo prop = (PropertyInfo)(MemberInfo)member;

                bindingData = PackBindingData(prop.GetAccessors(true)[0].IsStatic, ReflectionTypeToCeras(member.MemberType));

                // 1. Binding data
                SerializerBinary.WriteByte(ref buffer, ref offset, bindingData);

                // 2. Property Name
                _stringFormatter.Serialize(ref buffer, ref offset, prop.Name);

                // 3. Property Type
                _typeFormatter.Serialize(ref buffer, ref offset, prop.PropertyType);
                break;

            case MemberTypes.Field:
                FieldInfo field = (FieldInfo)(MemberInfo)member;

                bindingData = PackBindingData(field.IsStatic, ReflectionTypeToCeras(member.MemberType));

                // 1. Binding data
                SerializerBinary.WriteByte(ref buffer, ref offset, bindingData);

                // 2. Field Name
                _stringFormatter.Serialize(ref buffer, ref offset, field.Name);

                // 3. Field Type
                _typeFormatter.Serialize(ref buffer, ref offset, field.FieldType);

                break;

            case MemberTypes.TypeInfo:
            case MemberTypes.NestedType:
                // This should never happen, because root types as well as nested types are simply "Type",
                // so they should be handled by the TypeFormatter!
                goto default;

            default:
                throw new ArgumentOutOfRangeException("Cannot serialize member type '" + member.MemberType + "'");
            }
        }
예제 #7
0
        public void Serialize(ref byte[] buffer, ref int offset, T member)
        {
            // Declaring type
            _typeFormatter.Serialize(ref buffer, ref offset, member.DeclaringType);

            byte bindingData = 0;

            switch (member.MemberType)
            {
            // Write all the data we need to resolve overloads
            case MemberTypes.Constructor:
            case MemberTypes.Method:
                var method = (MethodBase)(MemberInfo)member;

                bindingData = PackBindingData(method.IsStatic, ReflectionTypeToCeras(member.MemberType));

                // 1. Binding data
                SerializerBinary.WriteByte(ref buffer, ref offset, bindingData);

                // 2. Method Name
                _stringFormatter.Serialize(ref buffer, ref offset, method.Name);

                // todo: parameter count can be merged into the unused bits of bindingData, but so much bit-packing makes things more complicated than they need to be;
                // it's extremely unlikely that anyone would notice the savings, even if they'd serialize tons of MemberInfos

                // 3. Parameters
                var args = method.GetParameters();
                SerializerBinary.WriteInt32(ref buffer, ref offset, args.Length);
                for (int i = 0; i < args.Length; i++)
                {
                    _typeFormatter.Serialize(ref buffer, ref offset, args[i].ParameterType);
                }

                break;

            case MemberTypes.Property:
                PropertyInfo prop = (PropertyInfo)(MemberInfo)member;

                bindingData = PackBindingData(prop.GetAccessors(true)[0].IsStatic, ReflectionTypeToCeras(member.MemberType));

                // 1. Binding data
                SerializerBinary.WriteByte(ref buffer, ref offset, bindingData);

                // 2. Property Name
                _stringFormatter.Serialize(ref buffer, ref offset, prop.Name);

                // 3. Property Type
                _typeFormatter.Serialize(ref buffer, ref offset, prop.PropertyType);
                break;

            case MemberTypes.Field:
                FieldInfo field = (FieldInfo)(MemberInfo)member;

                bindingData = PackBindingData(field.IsStatic, ReflectionTypeToCeras(member.MemberType));

                // 1. Binding data
                SerializerBinary.WriteByte(ref buffer, ref offset, bindingData);

                // 2. Field Name
                _stringFormatter.Serialize(ref buffer, ref offset, field.Name);

                // 3. Field Type
                _typeFormatter.Serialize(ref buffer, ref offset, field.FieldType);

                break;

            case MemberTypes.TypeInfo:
            case MemberTypes.NestedType:
                // This should never happen, because root types as well as nested types are simply "Type",
                // so they should be handled by the TypeFormatter!
                goto default;

            default:
                throw new ArgumentOutOfRangeException("Cannot serialize member type '" + member.MemberType + "'");
            }
        }
예제 #8
0
 public void Serialize(ref byte[] buffer, ref int offset, sbyte value)
 {
     SerializerBinary.WriteByte(ref buffer, ref offset, (byte)value);
 }