// caller is responsible for ensuring constant is on the right
        public static AstFilter Translate(
            TranslationContext context,
            Expression expression,
            Expression leftExpression,
            AstComparisonFilterOperator comparisonOperator,
            Expression rightExpression)
        {
            if (leftExpression is MethodCallExpression leftMethodCallExpression &&
                IsCompareToMethod(leftMethodCallExpression.Method))
            {
                var fieldExpression = leftMethodCallExpression.Object;
                var field           = ExpressionToFilterFieldTranslator.Translate(context, fieldExpression);

                var valueExpression = leftMethodCallExpression.Arguments[0];
                var value           = valueExpression.GetConstantValue <object>(containingExpression: expression);
                var serializedValue = SerializationHelper.SerializeValue(field.Serializer, value);

                var rightValue = rightExpression.GetConstantValue <int>(containingExpression: expression);
                if (rightValue == 0)
                {
                    return(AstFilter.Compare(field, comparisonOperator, serializedValue));
                }
            }

            throw new ExpressionNotSupportedException(expression);
        }
        public static AstFilter Translate(TranslationContext context, BinaryExpression expression)
        {
            var comparisonOperator = GetComparisonOperator(expression);
            var leftExpression     = expression.Left;
            var rightExpression    = expression.Right;

            if (leftExpression.NodeType == ExpressionType.Constant && rightExpression.NodeType != ExpressionType.Constant)
            {
                comparisonOperator = GetComparisonOperatorForSwappedLeftAndRight(expression);
                (leftExpression, rightExpression) = (rightExpression, leftExpression);
            }

            if (ArrayLengthComparisonExpressionToFilterTranslator.CanTranslate(leftExpression, rightExpression, out var arrayLengthExpression, out var sizeExpression))
            {
                return(ArrayLengthComparisonExpressionToFilterTranslator.Translate(context, expression, arrayLengthExpression, sizeExpression));
            }

            if (BitMaskComparisonExpressionToFilterTranslator.CanTranslate(leftExpression))
            {
                return(BitMaskComparisonExpressionToFilterTranslator.Translate(context, expression, leftExpression, comparisonOperator, rightExpression));
            }

            if (CompareToComparisonExpressionToFilterTranslator.CanTranslate(leftExpression))
            {
                return(CompareToComparisonExpressionToFilterTranslator.Translate(context, expression, leftExpression, comparisonOperator, rightExpression));
            }

            if (CountComparisonExpressionToFilterTranslator.CanTranslate(leftExpression, rightExpression, out var countExpression, out sizeExpression))
            {
                return(CountComparisonExpressionToFilterTranslator.Translate(context, expression, countExpression, sizeExpression));
            }

            if (ModuloComparisonExpressionToFilterTranslator.CanTranslate(leftExpression, rightExpression, out var moduloExpression, out var remainderExpression))
            {
                return(ModuloComparisonExpressionToFilterTranslator.Translate(context, expression, moduloExpression, remainderExpression));
            }

            if (StringExpressionToRegexFilterTranslator.CanTranslateComparisonExpression(leftExpression, comparisonOperator, rightExpression))
            {
                return(StringExpressionToRegexFilterTranslator.TranslateComparisonExpression(context, expression, leftExpression, comparisonOperator, rightExpression));
            }

            var comparand = rightExpression.GetConstantValue <object>(containingExpression: expression);

            if (leftExpression.Type == typeof(bool) &&
                (comparisonOperator == AstComparisonFilterOperator.Eq || comparisonOperator == AstComparisonFilterOperator.Ne) &&
                rightExpression.Type == typeof(bool))
            {
                return(TranslateComparisonToBooleanConstant(context, expression, leftExpression, comparisonOperator, (bool)comparand));
            }

            var field = ExpressionToFilterFieldTranslator.Translate(context, leftExpression);
            var serializedComparand = SerializationHelper.SerializeValue(field.Serializer, comparand);

            return(AstFilter.Compare(field, comparisonOperator, serializedComparand));
        }