func (c NullClause) String() string {
	return ""
}
Err for NullClause always returns an empty string.
package qframe
import (
	"fmt"
	"strings"
	"github.com/tobgu/qframe/filter"
	"github.com/tobgu/qframe/internal/index"
	"github.com/tobgu/qframe/internal/math/integer"
	"github.com/tobgu/qframe/qerrors"
)
type FilterClause interface {
	fmt.Stringer
	filter(qf QFrame) QFrame
	Err() error
}
type Filter filter.Filter
type comboClause struct {
	err        error           
	subClauses []FilterClause  
}
type AndClause comboClause
type OrClause comboClause
type NotClause struct {
	subClause FilterClause
}
type NullClause struct{}
func anyFilterErr(clauses []FilterClause) error {
	for _, c := range clauses {
		if c.Err() != nil {
			return c.Err()
		}
	}
	return nil
}
func And(clauses ...FilterClause) AndClause {
	if len(clauses) == 0 {
		return AndClause{err: qerrors.New("new AND clause", "zero subclauses not allowed")}
	}
	return AndClause{subClauses: clauses, err: anyFilterErr(clauses)}
}
func clauseString(clauses []FilterClause) string {
	reps := make([]string, 0, len(clauses))
	for _, c := range clauses {
		reps = append(reps, c.String())
	}
	return strings.Join(reps, ", ")
}
func (c AndClause) String() string {
	if c.Err() != nil {
		return c.Err().Error()
	}
	return fmt.Sprintf(`["and", %s]`, clauseString(c.subClauses))
}
func (c AndClause) filter(qf QFrame) QFrame {
	if qf.Err != nil {
		return qf
	}
	if c.Err() != nil {
		return qf.withErr(c.Err())
	}
	filteredQf := &qf
	for _, c := range c.subClauses {
		newQf := c.filter(*filteredQf)
		filteredQf = &newQf
	}
	return *filteredQf
}
func (c AndClause) Err() error {
	return c.err
}
func Or(clauses ...FilterClause) OrClause {
	if len(clauses) == 0 {
		return OrClause{err: qerrors.New("new OR clause", "zero subclauses not allowed")}
	}
	return OrClause{subClauses: clauses, err: anyFilterErr(clauses)}
}
func (c OrClause) String() string {
	if c.Err() != nil {
		return c.Err().Error()
	}
	return fmt.Sprintf(`["or", %s]`, clauseString(c.subClauses))
}
func orFrames(original, lhs, rhs *QFrame) *QFrame {
	if lhs == nil {
		return rhs
	}
	if lhs.Err != nil {
		return lhs
	}
	if rhs.Err != nil {
		return rhs
	}
	resultIx := make(index.Int, 0, integer.Max(len(lhs.index), len(rhs.index)))
	lhsI, rhsI := 0, 0
	for _, ix := range original.index {
		found := false
		if lhsI < len(lhs.index) && lhs.index[lhsI] == ix {
			found = true
			lhsI++
		}
		if rhsI < len(rhs.index) && rhs.index[rhsI] == ix {
			found = true
			rhsI++
		}
		if found {
			resultIx = append(resultIx, ix)
		}
	}
	newFrame := original.withIndex(resultIx)
	return &newFrame
}
func (c OrClause) filter(qf QFrame) QFrame {
	if qf.Err != nil {
		return qf
	}
	if c.Err() != nil {
		return qf.withErr(c.Err())
	}
	filters := make([]filter.Filter, 0)
	var filteredQf *QFrame
	for _, c := range c.subClauses {
		if f, ok := c.(Filter); ok {
			filters = append(filters, filter.Filter(f))
		} else {
			if len(filters) > 0 {
				newQf := qf.filter(filters...)
				filteredQf = orFrames(&qf, filteredQf, &newQf)
				filters = filters[:0]
			}
			newQf := c.filter(qf)
			filteredQf = orFrames(&qf, filteredQf, &newQf)
		}
	}
	if len(filters) > 0 {
		newQf := qf.filter(filters...)
		filteredQf = orFrames(&qf, filteredQf, &newQf)
	}
	return *filteredQf
}
func (c OrClause) Err() error {
	return c.err
}
func (c Filter) String() string {
	if c.Err() != nil {
		return c.Err().Error()
	}
	return filter.Filter(c).String()
}
func (c Filter) filter(qf QFrame) QFrame {
	return qf.filter(filter.Filter(c))
}
func (c Filter) Err() error {
	return nil
}
func Not(c FilterClause) NotClause {
	return NotClause{subClause: c}
}
func (c NotClause) String() string {
	if c.Err() != nil {
		return c.Err().Error()
	}
	return fmt.Sprintf(`["!", %s]`, c.subClause.String())
}
func (c NotClause) filter(qf QFrame) QFrame {
	if qf.Err != nil {
		return qf
	}
	if c.Err() != nil {
		return qf.withErr(c.Err())
	}
	if fc, ok := c.subClause.(Filter); ok {
		f := filter.Filter(fc)
		f.Inverse = !f.Inverse
		return qf.filter(f)
	}
	newQf := c.subClause.filter(qf)
	if newQf.Err != nil {
		return newQf
	}
	newIx := make(index.Int, 0, qf.index.Len()-newQf.index.Len())
	newQfI := 0
	for _, ix := range qf.index {
		if newQfI < newQf.index.Len() && newQf.index[newQfI] == ix {
			newQfI++
		} else {
			newIx = append(newIx, ix)
		}
	}
	return qf.withIndex(newIx)
}
func (c NotClause) Err() error {
	return c.subClause.Err()
}
func Null() NullClause {
	return NullClause{}
}