// valueType maybe a ConstantExpression and then Prune optimizes unreachable branches out static Expression MatchOrElse(Expression valueType, BondDataType expectedType, TypeHandlerCompiletime handler, Expression orElse) { return(PrunedExpression.IfThenElse( Expression.Equal(valueType, Expression.Constant(expectedType)), handler(expectedType), orElse)); }
Expression FieldValue(IParser parser, Expression var, Expression valueType, Type schemaType, bool initialize) { Expression body; if (schemaType.IsBondStruct() && var.Type.IsValueType()) { // Special handling for properties of struct types: we deserialize into // a temp variable and then assign the value to the property. var temp = Expression.Variable(var.Type, "temp"); body = Expression.Block( new[] { temp }, Value(parser, temp, valueType, schemaType, true), Expression.Assign(var, temp)); } else { body = Value(parser, var, valueType, schemaType, initialize); } if (schemaType.IsBondContainer() || schemaType.IsBondStruct() || schemaType.IsBondNullable()) { var expectedType = Expression.Constant(schemaType.GetBondDataType()); return(PrunedExpression.IfThenElse( Expression.Equal(valueType, expectedType), body, ThrowExpression.InvalidTypeException(expectedType, valueType))); } return(body); }
public static Expression While(Expression whileCondition, Expression body, LabelTarget breakLabel) { return(Expression.Loop( PrunedExpression.IfThenElse( whileCondition, body, Expression.Break(breakLabel)), breakLabel)); }
Expression CheckedValue(IParser parser, Expression var, Expression valueType, Type schemaType, bool initialize) { var body = Value(parser, var, valueType, schemaType, initialize); if (schemaType.IsBondContainer() || schemaType.IsBondStruct() || schemaType.IsBondNullable()) { var expectedType = Expression.Constant(schemaType.GetBondDataType()); return(PrunedExpression.IfThenElse( Expression.Equal(valueType, expectedType), body, ThrowExpression.InvalidTypeException(expectedType, valueType))); } return(body); }
Expression Field(ITransform transform, Expression structVar, UInt16 id, ISchemaField schemaField, IField field) { var fieldSchemaType = schemaField.GetSchemaType(); var fieldId = Expression.Constant(id); var fieldType = Expression.Constant(fieldSchemaType.GetBondDataType()); var fieldValue = DataExpression.PropertyOrField(structVar, schemaField.Name); var parser = new ObjectParser(this, fieldValue, fieldSchemaType); var processField = field != null ? field.Value(parser, fieldType) : transform.UnknownField(parser, fieldType, fieldId) ?? Expression.Empty(); var omitField = field != null ? field.Omitted : Expression.Empty(); Expression cannotOmit; if (fieldSchemaType.IsBondStruct() || fieldSchemaType.IsBonded() || schemaField.GetModifier() != Modifier.Optional) { cannotOmit = Expression.Constant(true); } else { var defaultValue = schemaField.GetDefaultValue(); if (fieldSchemaType.IsBondBlob()) { cannotOmit = Expression.NotEqual( typeAlias.Convert(fieldValue, fieldSchemaType), Expression.Default(typeof(ArraySegment <byte>))); } else if (fieldSchemaType.IsBondContainer()) { cannotOmit = defaultValue == null ? Expression.NotEqual(fieldValue, Expression.Constant(null)) : Expression.NotEqual(ContainerCount(fieldValue), Expression.Constant(0)); } else { cannotOmit = Expression.NotEqual(fieldValue, Expression.Constant(defaultValue)); } } return(PrunedExpression.IfThenElse(cannotOmit, processField, omitField)); }
Expression Container(IParser parser, RuntimeSchema schema) { var expectedValueType = schema.HasValue ? schema.TypeDef.element.id : (BondDataType?)null; return(parser.Container(expectedValueType, (valueParser, elementType, next, count) => { var body = ControlExpression.While(next, Expression.Block( writer.WriteItemBegin(), schema.HasValue ? Value(valueParser, elementType, schema.GetElementSchema()) : Value(valueParser, elementType), writer.WriteItemEnd())); var blob = parser.Blob(count); if (blob != null) { body = PrunedExpression.IfThenElse( Expression.Equal(elementType, Expression.Constant(BondDataType.BT_INT8)), writer.WriteBytes(blob), body); // For binary protocols we can write blob directly using protocols's WriteBytes // even if the container is not a blob (blob is BT_LIST of BT_INT8). if (binaryWriter) { body = PrunedExpression.IfThenElse( Expression.Equal(elementType, Expression.Constant(BondDataType.BT_UINT8)), writer.WriteBytes(blob), body); } } return Expression.Block( writer.WriteContainerBegin(count, elementType), body, writer.WriteContainerEnd()); })); }
Expression Field(ITransform transform, Expression structVar, UInt16 id, ISchemaField schemaField, IField field) { var fieldSchemaType = schemaField.GetSchemaType(); var fieldId = Expression.Constant(id); var fieldType = Expression.Constant(fieldSchemaType.GetBondDataType()); var fieldValue = DataExpression.PropertyOrField(structVar, schemaField.Name); ObjectParser parser = null; Expression blob = null; ParameterExpression convertedBlob = null; // To avoid calling Convert multiple times on the same aliased Blob // we must construct a new ObjectParser with the expected return type of // of Convert if (fieldSchemaType.IsBondBlob()) { blob = typeAlias.Convert(fieldValue, fieldSchemaType); convertedBlob = Expression.Variable(blob.Type, "convertedBlob"); if (blob.Type != fieldValue.Type) { parser = new ObjectParser(this, convertedBlob, convertedBlob.Type); } } parser = parser ?? new ObjectParser(this, fieldValue, fieldSchemaType); var processField = field != null ? field.Value(parser, fieldType) : transform.UnknownField(parser, fieldType, fieldId) ?? Expression.Empty(); var omitField = field != null ? field.Omitted : Expression.Empty(); Expression cannotOmit; if (fieldSchemaType.IsBondStruct() || fieldSchemaType.IsBonded() || schemaField.GetModifier() != Modifier.Optional) { cannotOmit = Expression.Constant(true); if (fieldSchemaType.IsBondBlob()) { return(Expression.Block( new[] { convertedBlob }, Expression.Assign(convertedBlob, blob), processField)); } } else { var defaultValue = schemaField.GetDefaultValue(); if (fieldSchemaType.IsBondBlob()) { var notEqual = Expression.NotEqual( convertedBlob, Expression.Default(typeof(ArraySegment <byte>))); return(Expression.Block( new[] { convertedBlob }, Expression.Assign(convertedBlob, blob), PrunedExpression.IfThenElse(notEqual, processField, omitField))); } else if (fieldSchemaType.IsBondContainer()) { cannotOmit = defaultValue == null ? Expression.NotEqual(fieldValue, Expression.Constant(null)) : Expression.NotEqual(ContainerCount(fieldValue), Expression.Constant(0)); } else { cannotOmit = Expression.NotEqual(fieldValue, Expression.Constant(defaultValue)); } } return(PrunedExpression.IfThenElse(cannotOmit, processField, omitField)); }