Beispiel #1
0
        static T GetScheme <T>(IContract contract, DsdlType derivedScheme) where T : DsdlType
        {
            T   result             = null;
            var schemeFromContract = contract.DsdlType;

            if (schemeFromContract != null)
            {
                result = schemeFromContract as T;
                if (result == null)
                {
                    throw new InvalidOperationException($"Unexpected DSDL type for type '{contract.UnderlyingType.FullName}'.");
                }
            }

            if (derivedScheme != null)
            {
                if (result != null && result != derivedScheme)
                {
                    throw new InvalidOperationException($"DSDL scheme mismatch for type '{contract.UnderlyingType.FullName}'.");
                }

                result = derivedScheme as T;
                if (result == null)
                {
                    throw new InvalidOperationException($"Unexpected DSDL type for type '{contract.UnderlyingType.FullName}'.");
                }
            }

            if (result == null)
            {
                throw new InvalidOperationException($"Unexpected DSDL type for type '{contract.UnderlyingType.FullName}'.");
            }

            return(result);
        }
Beispiel #2
0
        object CreateValueInternal(
            BitStreamReader reader,
            IContract contract,
            DsdlProperty member,
            ContainerContract containerContract,
            DsdlProperty containerMember,
            object existingValue,
            DsdlType scheme,
            Type objectType,
            bool tailArrayOptimization = false)
        {
            switch (scheme)
            {
            case VoidDsdlType t:
                ReadAlignment(reader, t);
                return(null);

            case PrimitiveDsdlType t:
                var primitive = ReadPrimitiveType(reader, t);
                return(EnsureType(reader, primitive, CultureInfo.InvariantCulture, contract, objectType));

            case ArrayDsdlType t when t.IsStringLike && contract.UnderlyingType == typeof(string):
                var list = CreateList(reader, StringContract, member, null, t, tailArrayOptimization) as IEnumerable <byte>;
                return(_encoding.GetString(list.ToArray()));

            case ArrayDsdlType t:
                return(CreateList(reader, contract, member, existingValue, t, tailArrayOptimization));

            case CompositeDsdlTypeBase t:
                return(CreateObject(reader, contract, member, containerContract, containerMember, existingValue, objectType, t, tailArrayOptimization));

            default:
                throw new ArgumentOutOfRangeException(nameof(scheme));
            }
        }
Beispiel #3
0
        static void Print(object obj, StringBuilder sb, int tabs, DsdlType scheme)
        {
            if (obj is null)
            {
                return;
            }

            switch (scheme)
            {
            case CompositeDsdlTypeBase t:
                PrintObject(obj, sb, tabs, t);
                break;

            case ArrayDsdlType t when t.IsStringLike:
                PrintString(obj, sb);
                break;

            case ArrayDsdlType t:
                PrintArray(obj, sb, tabs, t);
                break;

            default:
                PrintPrimitive(obj, sb);
                break;
            }
        }
Beispiel #4
0
        string GetCSharpType(DsdlType type, bool nullable, string name)
        {
            if (name != null)
            {
                if (IsEnum(name, type))
                {
                    var enumType = GetOrCreateEnum(name, type);
                    return(nullable ? enumType + "?" : enumType);
                }
                if (IsString(name, type))
                {
                    return("string");
                }
            }

            switch (type)
            {
            case VoidDsdlType _:
                return(null);

            case PrimitiveDsdlType t:
                return(nullable ? GetCSharpType(t) + "?" : GetCSharpType(t));

            case ArrayDsdlType t:
                return(GetCSharpType(t.ElementType, false, name) + "[]");

            case CompositeDsdlTypeBase t:
                return(_compoundTypesLookup[t].CSharpName);

            default:
                throw new InvalidOperationException();
            }
        }
Beispiel #5
0
        static bool CheckDsdlTypeCompatibility(DsdlType schemeType, IContract actualContract)
        {
            switch (schemeType)
            {
            case PrimitiveDsdlType _:
                if (!(actualContract is PrimitiveContract))
                {
                    return(false);
                }
                break;

            case ArrayDsdlType adt when adt.IsStringLike && actualContract.UnderlyingType == typeof(string):
                break;

            case ArrayDsdlType _:
                if (!(actualContract is ArrayContract))
                {
                    return(false);
                }
                break;

            case CompositeDsdlTypeBase dt:
                if (dt != actualContract.DsdlType)
                {
                    return(false);
                }
                break;
            }

            return(true);
        }
Beispiel #6
0
        public static string PrintToString(object obj, DsdlType scheme)
        {
            var sb = new StringBuilder();

            Print(obj, sb, 0, scheme);
            return(sb.ToString());
        }
Beispiel #7
0
        string GetOrCreateEnum(string name, DsdlType type)
        {
            var ut  = GetCSharpType(type as PrimitiveDsdlType);
            var key = "Enum_" + ut;

            if (!_helperTypes.ContainsKey(key))
            {
                _helperTypes[key] = $"    public enum {key} : {ut} {{}}";
            }
            return(key);
        }
Beispiel #8
0
        public object Deserialize(Memory <byte> memory, DsdlType dsdlScheme, IContract contract = null)
        {
            if (dsdlScheme == null)
            {
                throw new ArgumentNullException(nameof(dsdlScheme));
            }

            var stream = new BitStreamReader(memory);
            var reader = new DsdlSerializerReader(this);

            return(reader.Deserialize(stream, dsdlScheme, contract));
        }
Beispiel #9
0
        string BuildPythonInitializerMemberElement(DsdlType type, string fieldName, ParseTreeNode node)
        {
            switch (type)
            {
            case PrimitiveDsdlType _:
                var text = node.GetText(SourceText);
                switch (text)
                {
                case "true":
                    text = "True";
                    break;

                case "false":
                    text = "False";
                    break;

                case "null":
                    text = "None";
                    break;
                }

                if (text.EndsWith("f", StringComparison.OrdinalIgnoreCase) &&
                    node.FindToken()?.Value is float)     // Remove float 'f' suffix.
                {
                    text = text.Substring(0, text.Length - 1);
                }

                return(text);

            case ArrayDsdlType adt when IsString(fieldName, type):
                return(node.GetText(SourceText));

            case ArrayDsdlType adt:
                var nestesNodes = node.FindChild("members");
                if (nestesNodes == null)
                {
                    return("[]");
                }
                var arrayContent = nestesNodes.ChildNodes.Select(x => BuildPythonInitializerMemberElement(adt.ElementType, fieldName, x));
                return($"[{string.Join(", ", arrayContent)}]");

            case CompositeDsdlTypeBase cdt:
                var t = _compoundTypesLookup[cdt];
                return($"{t.Namespace}.{t.Name}(" +
                       string.Join(", ", BuildPythonInitializerMembers(cdt.Fields, node.FindChild("members"))) +
                       ")");

            default:
                throw new InvalidOperationException();
            }
        }
Beispiel #10
0
        static bool IsSingleLineType(DsdlType type)
        {
            switch (type)
            {
            case ArrayDsdlType t when t.IsStringLike:
                return(true);

            case PrimitiveDsdlType _:
                return(true);

            default:
                return(false);
            }
        }
Beispiel #11
0
        public int Serialize(object value, DsdlType dsdlScheme, Memory <byte> memory)
        {
            if (value == null)
            {
                throw new ArgumentNullException(nameof(value));
            }

            var streamWriter = new BitStreamWriter(memory);

            var writer = new DsdlSerializerWriter(this);

            writer.Serialize(streamWriter, value, dsdlScheme);

            return(streamWriter.Length);
        }
Beispiel #12
0
        public object Deserialize(BitStreamReader reader, DsdlType scheme, IContract contract)
        {
            if (reader == null)
            {
                throw new ArgumentNullException(nameof(reader));
            }
            if (scheme == null)
            {
                throw new ArgumentNullException(nameof(scheme));
            }

            if (HasNoDefinedType(contract))
            {
                return(CreateUnknownObject(reader, scheme, true));
            }

            return(CreateValueInternal(reader, contract, null, null, null, null, scheme, null, true));
        }
Beispiel #13
0
        static string GetCSharpType(DsdlType type, bool nullable)
        {
            switch (type)
            {
            case VoidDsdlType _:
                return(null);

            case PrimitiveDsdlType t:
                return(nullable ? GetCSharpType(t) + "?" : GetCSharpType(t));

            case ArrayDsdlType t:
                return(GetCSharpType(t.ElementType, false) + "[]");

            case CompositeDsdlTypeBase t:
                return(_namesTypesLookup[t]);

            default:
                throw new InvalidOperationException();
            }
        }
Beispiel #14
0
        static DsdlConstant CreateConstant(DsdlType attrType, string attrName, string expression)
        {
            if (!(attrType is PrimitiveDsdlType primitive))
            {
                throw new Exception($"Invalid type for constant {attrName}.");
            }

            var value = Evaluate(expression, primitive);

            if (!primitive.IsInRange(value))
            {
                throw new Exception($"Value {value} is out of range.");
            }

            return(new DsdlConstant
            {
                Name = attrName,
                Type = attrType,
                Value = value,
            });
        }
Beispiel #15
0
        private void SerializeValue(
            BitStreamWriter writer,
            object value,
            IContract valueContract,
            DsdlType derivedDsdlType,
            bool tailArrayOptimization = false)
        {
            if (value == null)
            {
                throw new ArgumentNullException(nameof(value), "Cannot serialize null value");
            }

            switch (valueContract)
            {
            case ObjectContract contract:
                SerializeObject(writer, value, contract, derivedDsdlType, tailArrayOptimization);
                break;

            case ArrayContract contract:
                if (contract.IsMultidimensionalArray)
                {
                    throw new NotSupportedException("Multidimensional arrays are not supported.");
                }
                SerializeList(writer, (IEnumerable)value, contract, contract.FinalItemContract, derivedDsdlType, tailArrayOptimization);
                break;

            case PrimitiveContract contract:
                SerializePrimitive(writer, value, contract, derivedDsdlType, tailArrayOptimization);
                break;

            case DictionaryContract contract:
                SerializeDictionary(writer, (value is IDictionary dictionary) ? dictionary : contract.CreateWrapper(value), contract, derivedDsdlType, tailArrayOptimization);
                break;

            default:
                throw new ArgumentOutOfRangeException(nameof(valueContract));
            }
        }
Beispiel #16
0
        string BuildTestMethodMemberElement(DsdlType type, string fieldName, ParseTreeNode node)
        {
            if (IsEnum(fieldName, type))
            {
                var enumType = GetOrCreateEnum(fieldName, type);
                return($"({enumType}){node.GetText(SourceText)}");
            }
            if (IsString(fieldName, type))
            {
                return(node.GetText(SourceText));
            }

            switch (type)
            {
            case PrimitiveDsdlType _:
                return(node.GetText(SourceText));

            case ArrayDsdlType adt:
                var nestesNodes = node.FindChild("members");
                if (nestesNodes == null)
                {
                    return($"new {GetCSharpType(adt, false, fieldName)} {{ }}");
                }
                var arrayContent = nestesNodes.ChildNodes.Select(x => BuildTestMethodMemberElement(adt.ElementType, fieldName, x));
                return($"new {GetCSharpType(adt, false, fieldName)} {{ {string.Join(", ", arrayContent)} }}");

            case CompositeDsdlTypeBase cdt:
                var t = _compoundTypesLookup[cdt];
                return($"new {t.CSharpName} {{ " +
                       string.Join(", ", BuildTestMethodMembers(cdt.Fields, node.FindChild("members"))) +
                       " }");

            default:
                throw new InvalidOperationException();
            }
        }
Beispiel #17
0
        void SerializeObject(BitStreamWriter writer, object value, ObjectContract contract, DsdlType derivedDsdlType, bool tailArrayOptimization)
        {
            var dsdlScheme = GetScheme <CompositeDsdlTypeBase>(contract, derivedDsdlType);

            _serializeStack.Push(value);

            SerializeObjectCore(
                writer,
                name => ResolveObjectProperty(value, contract, name),
                contract,
                derivedDsdlType,
                tailArrayOptimization);

            _serializeStack.Pop();
        }
Beispiel #18
0
        void SerializeDictionary(BitStreamWriter writer, IDictionary values, DictionaryContract contract, DsdlType derivedDsdlType, bool tailArrayOptimization)
        {
            object underlyingDictionary = values is IWrappedDictionary wrappedDictionary ? wrappedDictionary.UnderlyingDictionary : values;

            _serializeStack.Push(underlyingDictionary);

            if (contract.ItemContract == null)
            {
                contract.ItemContract = _serializer.ContractResolver.ResolveContract(contract.DictionaryValueType ?? typeof(object));
            }

            if (contract.KeyContract == null)
            {
                contract.KeyContract = _serializer.ContractResolver.ResolveContract(contract.DictionaryKeyType ?? typeof(object));
            }

            var dictionaryNormalized = PreprocessDictionary(values, contract);

            SerializeObjectCore(
                writer,
                name => ResolveDictionaryProperty(dictionaryNormalized, contract, name),
                contract,
                derivedDsdlType,
                tailArrayOptimization);

            _serializeStack.Pop();
        }
Beispiel #19
0
        void SerializeObjectCore(
            BitStreamWriter writer,
            Func <string, ResolvedProperty?> propertyResolver,
            ContainerContract containerContract,
            DsdlType derivedDsdlType,
            bool tailArrayOptimization)
        {
            var dsdlScheme = GetScheme <CompositeDsdlTypeBase>(containerContract, derivedDsdlType);

            //WriteObjectStart(writer, value, contract, member, collectionContract, containerProperty);

            VoidDsdlType voidDsdlType      = null;
            int          voidDsdlTypeIndex = -1;
            var          isUnion           = dsdlScheme.IsUnion;
            var          unionMemberFound  = false;

            for (int i = 0; i < dsdlScheme.Fields.Count; i++)
            {
                var dsdlMember   = dsdlScheme.Fields[i];
                var isLastMember = i == dsdlScheme.Fields.Count - 1;

                if ((voidDsdlType = (dsdlMember.Type as VoidDsdlType)) != null)
                {
                    voidDsdlTypeIndex = i;
                    if (!isUnion)
                    {
                        WriteAlignment(writer, voidDsdlType);
                    }
                    continue;
                }

                var resolvedProp = propertyResolver(dsdlMember.Name);

                if (isUnion)
                {
                    if (resolvedProp == null)
                    {
                        continue;
                    }
                    if (unionMemberFound)
                    {
                        throw new InvalidOperationException($"Cannot find single union value for type '{containerContract.UnderlyingType.FullName}'.");
                    }
                    unionMemberFound = true;
                    WriteUnionFieldIndex(writer, i, dsdlScheme);
                    var rp = resolvedProp.Value;
                    SerializeValue(writer, rp.MemberValue, rp.MemberContact, dsdlMember.Type);
                }
                else
                {
                    if (resolvedProp == null)
                    {
                        throw new InvalidOperationException($"Cannot resove member '{containerContract.UnderlyingType.FullName}.{dsdlMember.Name}'.");
                    }
                    var rp  = resolvedProp.Value;
                    var tao = tailArrayOptimization &&
                              isLastMember &&
                              dsdlMember.Type is ArrayDsdlType adt;
                    SerializeValue(writer, rp.MemberValue, rp.MemberContact, dsdlMember.Type, tao);
                }
            }

            if (isUnion && !unionMemberFound)
            {
                if (voidDsdlType != null)
                {
                    WriteUnionFieldIndex(writer, voidDsdlTypeIndex, dsdlScheme);
                    WriteAlignment(writer, voidDsdlType);
                }
                else
                {
                    throw new InvalidOperationException($"Cannot find union value for '{containerContract.UnderlyingType.FullName}' type.");
                }
            }
        }
Beispiel #20
0
        void SerializePrimitive(BitStreamWriter writer, object value, PrimitiveContract contract, DsdlType derivedDsdlType, bool tailArrayOptimization)
        {
            if (contract.TypeCode == PrimitiveTypeCode.String &&
                derivedDsdlType is ArrayDsdlType adt &&
                adt.IsStringLike)
            {
                byte[] stringBytes;
                if (value == null)
                {
                    stringBytes = _emptyByteArray;
                }
                else
                {
                    if (!(value is string stringValue))
                    {
                        throw new ArgumentException("Cannot cast value to string.", nameof(value));
                    }
                    stringBytes = _encoding.GetBytes(stringValue);
                }

                SerializeList(writer, stringBytes, contract, null, adt, tailArrayOptimization);
                return;
            }

            if (!(derivedDsdlType is PrimitiveDsdlType t))
            {
                throw new InvalidOperationException($"Primitive DSDL type expected for type '{contract.UnderlyingType.FullName}'.");
            }

            switch (t)
            {
            case BooleanDsdlType _:
                var boolValue = (bool)ConvertUtils.ConvertOrCast(value, CultureInfo.CurrentCulture, typeof(bool));
                BitSerializer.Write(writer, boolValue, t.MaxBitlen);
                break;

            case IntDsdlType idt:
                var longValue = (long)ConvertUtils.ConvertOrCast(value, CultureInfo.CurrentCulture, typeof(long));
                longValue = ApplyIntegerCastMode(longValue, idt);
                BitSerializer.Write(writer, longValue, t.MaxBitlen);
                break;

            case UIntDsdlType uidt:
                var ulongValue = (ulong)ConvertUtils.ConvertOrCast(value, CultureInfo.CurrentCulture, typeof(ulong));
                ulongValue = ApplyIntegerCastMode(ulongValue, uidt);
                BitSerializer.Write(writer, ulongValue, t.MaxBitlen);
                break;

            case FloatDsdlType fdt:
                var doubleValue = (double)ConvertUtils.ConvertOrCast(value, CultureInfo.CurrentCulture, typeof(double));
                WriteFloatPrimitive(writer, doubleValue, fdt);
                break;

            default:
                throw new ArgumentOutOfRangeException(nameof(t));
            }
        }
Beispiel #21
0
        object CreateUnknownObject(BitStreamReader reader, DsdlType scheme, bool tailArrayOptimization = false)
        {
            switch (scheme)
            {
            case VoidDsdlType t:
                ReadAlignment(reader, t);
                return(null);

            case PrimitiveDsdlType t:
                return(ReadPrimitiveType(reader, t));

            case ArrayDsdlType t:
                switch (t.Mode)
                {
                case ArrayDsdlTypeMode.Static:
                    return(ReadStaticArray(reader, t));

                case ArrayDsdlTypeMode.Dynamic:
                    return(ReadDynamicArray(reader, t, tailArrayOptimization));

                default:
                    throw new ArgumentOutOfRangeException(nameof(ArrayDsdlTypeMode));
                }

            case CompositeDsdlTypeBase t:
                var dictionary = new Dictionary <string, object>(StringComparer.Ordinal);

                if (t.IsUnion)
                {
                    var unionFieldIndex = ReadUnionFieldIndex(reader, t);
                    var field           = t.Fields[unionFieldIndex];
                    if (!(field.Type is VoidDsdlType))
                    {
                        dictionary[field.Name] = CreateUnknownObject(reader, field.Type);
                    }
                }
                else
                {
                    for (int i = 0; i < t.Fields.Count - 1; i++)
                    {
                        var field = t.Fields[i];
                        if (!(field.Type is VoidDsdlType))
                        {
                            dictionary[field.Name] = CreateUnknownObject(reader, field.Type);
                        }
                    }

                    if (t.Fields.Count > 0)
                    {
                        var field = t.Fields[t.Fields.Count - 1];
                        switch (field.Type)
                        {
                        case VoidDsdlType _:
                            break;

                        case ArrayDsdlType _:
                            dictionary[field.Name] = CreateUnknownObject(reader, field.Type, tailArrayOptimization);
                            break;

                        default:
                            dictionary[field.Name] = CreateUnknownObject(reader, field.Type);
                            break;
                        }
                    }
                }

                return(dictionary);

            default:
                throw new ArgumentOutOfRangeException(nameof(scheme));
            }
        }
Beispiel #22
0
        bool SetPropertyValue(
            DsdlProperty property,
            ContainerContract containerContract,
            DsdlProperty containerProperty,
            BitStreamReader reader,
            object target,
            DsdlType scheme,
            bool tailArrayOptimization)
        {
            if (property.Ignored)
            {
                return(true);
            }

            if (property.PropertyContract == null)
            {
                property.PropertyContract = GetContractSafe(property.PropertyType);
            }

            bool   useExistingValue = false;
            object currentValue     = null;

            if (property.Readable)
            {
                currentValue = property.ValueProvider.GetValue(target);
            }

            IContract propertyContract;

            if (currentValue == null)
            {
                propertyContract = property.PropertyContract;
            }
            else
            {
                propertyContract = GetContractSafe(currentValue.GetType());
                useExistingValue = (!propertyContract.IsReadOnlyOrFixedSize && !propertyContract.UnderlyingType.IsValueType());
            }

            var value = CreateValueInternal(
                reader,
                propertyContract,
                property,
                containerContract,
                containerProperty,
                (useExistingValue) ? currentValue : null,
                scheme,
                property.PropertyType,
                tailArrayOptimization);

            // always set the value if useExistingValue is false,
            // otherwise also set it if CreateValue returns a new value compared to the currentValue
            // this could happen because of a JsonConverter against the type
            if ((!useExistingValue || value != currentValue) &&
                ShouldSetPropertyValue(property, containerContract as ObjectContract, value))
            {
                property.ValueProvider.SetValue(target, value);

                return(true);
            }

            // the value wasn't set be JSON was populated onto the existing value
            return(useExistingValue);
        }
Beispiel #23
0
        void SerializeList(
            BitStreamWriter writer,
            IEnumerable values,
            IContract contract,
            IContract finalItemContract,
            DsdlType derivedDsdlType,
            bool tailArrayOptimization)
        {
            if (!(derivedDsdlType is ArrayDsdlType arrayDsdlType))
            {
                throw new InvalidOperationException($"Array DSDL type expected for type '{contract.UnderlyingType.FullName}'.");
            }

            object underlyingList = values is IWrappedCollection wrappedCollection ? wrappedCollection.UnderlyingCollection : values;

            _serializeStack.Push(underlyingList);

            var arrayCount = values.Count();

            switch (arrayDsdlType.Mode)
            {
            case ArrayDsdlTypeMode.Dynamic:
            {
                if (arrayCount > arrayDsdlType.MaxSize)
                {
                    throw new SerializationException($"'{contract.UnderlyingType.FullName}' is too big. MaxSize is {arrayDsdlType.MaxSize}.");
                }
                if (!tailArrayOptimization || arrayDsdlType.ElementType.MinBitlen < 8)
                {
                    WriteDynamicArraySize(writer, arrayCount, arrayDsdlType);
                }
                else
                {
                    tailArrayOptimization = false;
                }
                break;
            }

            case ArrayDsdlTypeMode.Static:
            {
                if (arrayCount != arrayDsdlType.MaxSize)
                {
                    throw new SerializationException($"'{contract.UnderlyingType.FullName}' expected size is {arrayDsdlType.MaxSize}.");
                }
                break;
            }
            }

            // Note: an exception from the IEnumerable won't be caught.
            int i = 0;

            foreach (object value in values)
            {
                i++;

                var valueContract = finalItemContract ??
                                    (value == null ? null : _serializer.ContractResolver.ResolveContract(value.GetType()));

                if (!CheckForCircularReference(value, null, valueContract))
                {
                    continue;
                }

                if (!CheckDsdlTypeCompatibility(arrayDsdlType.ElementType, valueContract))
                {
                    throw new InvalidOperationException(
                              $"DSDL type mismatch for enumerated item '{contract.UnderlyingType.FullName}.{valueContract.UnderlyingType}'.");
                }

                var tao = i == arrayCount ? tailArrayOptimization : false;
                SerializeValue(writer, value, valueContract, arrayDsdlType.ElementType, tao);
            }

            //writer.WriteEndArray();

            _serializeStack.Pop();
        }
Beispiel #24
0
 static bool IsString(string name, DsdlType type)
 {
     return(type is ArrayDsdlType adt && adt.IsStringLike && name.StartsWith("t_string_"));
 }
Beispiel #25
0
        public void Serialize(BitStreamWriter stream, object value, DsdlType dsdlScheme)
        {
            var contract = _serializer.ContractResolver.ResolveContract(value.GetType());

            SerializeValue(stream, value, contract, dsdlScheme, true);
        }
Beispiel #26
0
 static bool IsEnum(string name, DsdlType type)
 {
     return((type is IntDsdlType || type is UIntDsdlType) && name.StartsWith("t_enum_"));
 }