github.com/m4gshm/gollections@v0.0.13-0.20240331203319-a34a86e58a24/break/predicate/api.go (about)

     1  // Package predicate provides breakable predicate builders
     2  package predicate
     3  
     4  // Predicate tests value (converts to true or false) or aborts by an error.
     5  type Predicate[T any] func(T) (bool, error)
     6  
     7  // Or makes disjunction
     8  func (p Predicate[T]) Or(or Predicate[T]) Predicate[T] { return Or(p, or) }
     9  
    10  // And makes conjunction
    11  func (p Predicate[T]) And(and Predicate[T]) Predicate[T] { return And(p, and) }
    12  
    13  // Xor makes exclusive OR
    14  func (p Predicate[T]) Xor(xor Predicate[T]) Predicate[T] { return Xor(p, xor) }
    15  
    16  // Of breakable Predicate constructor
    17  func Of[T comparable](predicate func(T) bool) Predicate[T] {
    18  	return func(c T) (bool, error) { return predicate(c), nil }
    19  }
    20  
    21  // Wrap converts the specified predicate to the erroreable one
    22  func Wrap[T any](predicate func(T) bool) Predicate[T] {
    23  	return func(t T) (bool, error) { return predicate(t), nil }
    24  }
    25  
    26  // Eq creates a predicate to test for equality
    27  func Eq[T comparable](v T) Predicate[T] {
    28  	return func(c T) (bool, error) { return v == c, nil }
    29  }
    30  
    31  // Not inverts a predicate
    32  func Not[T any](p Predicate[T]) Predicate[T] {
    33  	return func(v T) (bool, error) {
    34  		ok, err := p(v)
    35  		return !ok, err
    36  	}
    37  }
    38  
    39  // And makes a conjunction of two predicates
    40  func And[T any](p1, p2 Predicate[T]) Predicate[T] {
    41  	return func(v T) (bool, error) {
    42  		if ok, err := p1(v); err != nil || !ok {
    43  			return false, err
    44  		}
    45  		return p2(v)
    46  	}
    47  }
    48  
    49  // Or makes a disjunction of two predicates
    50  func Or[T any](p1, p2 Predicate[T]) Predicate[T] {
    51  	return func(v T) (bool, error) {
    52  		if ok, err := p1(v); err != nil || ok {
    53  			return ok, err
    54  		}
    55  		return p2(v)
    56  	}
    57  }
    58  
    59  // Xor makes an exclusive OR of two predicates
    60  func Xor[T any](p1, p2 Predicate[T]) Predicate[T] {
    61  	return func(v T) (bool, error) {
    62  		if ok, err := p1(v); err != nil {
    63  			return ok, err
    64  		} else if ok2, err := p2(v); err != nil {
    65  			return ok2, err
    66  		} else {
    67  			return ok != ok2, nil
    68  		}
    69  	}
    70  }
    71  
    72  // Union applies And to predicates
    73  func Union[T any](predicates ...Predicate[T]) Predicate[T] {
    74  	l := len(predicates)
    75  	if l == 0 {
    76  		return func(_ T) (bool, error) { return false, nil }
    77  	} else if l == 1 {
    78  		return predicates[0]
    79  	} else if l == 2 {
    80  		return And(predicates[0], predicates[1])
    81  	}
    82  	return func(v T) (bool, error) {
    83  		for i := 0; i < len(predicates); i++ {
    84  			if ok, err := predicates[i](v); err != nil {
    85  				return ok, err
    86  			} else if !ok {
    87  				return false, nil
    88  			}
    89  		}
    90  		return true, nil
    91  	}
    92  }
    93  
    94  // Always returns v every time.
    95  func Always[T any](v bool) Predicate[T] {
    96  	return func(_ T) (bool, error) { return v, nil }
    97  }
    98  
    99  // Never returns the negative of v every time
   100  func Never[T any](v bool) Predicate[T] {
   101  	return func(_ T) (bool, error) { return !v, nil }
   102  }