ObjectParser(ObjectParser that, Expression value, Type schemaType) { typeAlias = that.typeAlias; objParam = that.objParam; this.value = value; this.schemaType = schemaType; objectType = value.Type; hierarchyDepth = schemaType.GetHierarchyDepth(); }
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 Nullable(ContainerHandler handler) { Debug.Assert(schemaType.IsBondNullable()); var valueType = schemaType.GetValueType(); var count = Expression.Variable(typeof(int), "count"); ParameterExpression convertedBlob = null; var nullableValue = value; var valueParser = new ObjectParser(this, value, valueType); if (valueType.IsBondBlob()) { convertedBlob = Expression.Variable(typeof(ArraySegment <byte>), "convertedBlob"); nullableValue = Expression.Property(convertedBlob, "Array"); valueParser = new ObjectParser(this, convertedBlob, convertedBlob.Type); } var notNull = Expression.NotEqual(nullableValue, Expression.Constant(null)); var loop = handler( valueParser, Expression.Constant(valueType.GetBondDataType()), Expression.NotEqual(Expression.PostDecrementAssign(count), Expression.Constant(0)), count, null); if (convertedBlob != null) { return(Expression.Block( new[] { convertedBlob, count }, Expression.Assign(convertedBlob, typeAlias.Convert(value, valueType)), Expression.Assign(count, Expression.Condition(notNull, Expression.Constant(1), Expression.Constant(0))), loop)); } else { return(Expression.Block( new[] { count }, Expression.Assign(count, Expression.Condition(notNull, Expression.Constant(1), Expression.Constant(0))), loop)); } }
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 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)); }