package builderimp import ( "reflect" "github.com/tech/sendico/pkg/db/repository/builder" "go.mongodb.org/mongo-driver/bson" ) type literalExpression struct { value any } func NewLiteralExpression(value any) builder.Expression { return &literalExpression{value: value} } func (e *literalExpression) Build() any { return bson.D{{Key: string(builder.Literal), Value: e.value}} } type variadicExpression struct { op builder.MongoOperation parts []builder.Expression } func (e *variadicExpression) Build() any { args := make([]any, 0, len(e.parts)) for _, p := range e.parts { args = append(args, p.Build()) } return bson.D{{Key: string(e.op), Value: args}} } func newVariadicExpression(op builder.MongoOperation, exprs ...builder.Expression) builder.Expression { return &variadicExpression{ op: op, parts: exprs, } } func newBinaryExpression(op builder.MongoOperation, left, right builder.Expression) builder.Expression { return &variadicExpression{ op: op, parts: []builder.Expression{left, right}, } } type unaryExpression struct { op builder.MongoOperation rhs builder.Expression } func (e *unaryExpression) Build() any { return bson.D{{Key: string(e.op), Value: e.rhs.Build()}} } func newUnaryExpression(op builder.MongoOperation, right builder.Expression) builder.Expression { return &unaryExpression{ op: op, rhs: right, } } type matchExpression struct { op builder.MongoOperation rhs builder.Expression } func (e *matchExpression) Build() any { return bson.E{Key: string(e.op), Value: e.rhs.Build()} } func newMatchExpression(op builder.MongoOperation, right builder.Expression) builder.Expression { return &matchExpression{ op: op, rhs: right, } } func InRef(value builder.Field) builder.Expression { return newMatchExpression(builder.In, NewValue(NewRefFieldImp(value).Build())) } type inImpl struct { values []any } func (e *inImpl) Build() any { return bson.D{{Key: string(builder.In), Value: e.values}} } func In(values ...any) builder.Expression { var flattenedValues []any for _, v := range values { switch reflect.TypeOf(v).Kind() { case reflect.Slice: slice := reflect.ValueOf(v) for i := range slice.Len() { flattenedValues = append(flattenedValues, slice.Index(i).Interface()) } default: flattenedValues = append(flattenedValues, v) } } return &inImpl{values: flattenedValues} }