LCOV - code coverage report
Current view: top level - pebble/internal/dsl - predicates.go (source / functions) Hit Total Coverage
Test: 2024-06-28 08:15Z 3ef2e5b1 - tests only.lcov Lines: 61 69 88.4 %
Date: 2024-06-28 08:16:24 Functions: 0 0 -

          Line data    Source code
       1             : // Copyright 2023 The LevelDB-Go and Pebble Authors. All rights reserved. Use
       2             : // of this source code is governed by a BSD-style license that can be found in
       3             : // the LICENSE file.
       4             : 
       5             : package dsl
       6             : 
       7             : import (
       8             :         "fmt"
       9             :         "go/token"
      10             :         "strconv"
      11             :         "strings"
      12             :         "sync/atomic"
      13             : 
      14             :         "github.com/cockroachdb/errors"
      15             : )
      16             : 
      17             : // Predicate encodes conditional logic that yields a boolean.
      18             : type Predicate[E any] interface {
      19             :         Evaluate(E) bool
      20             :         String() string
      21             : }
      22             : 
      23             : // Not returns a Predicate that negates the provided predicate.
      24           0 : func Not[E any](p Predicate[E]) Predicate[E] { return not[E]{Predicate: p} }
      25             : 
      26             : // And returns a Predicate that evaluates to true if all its operands evaluate
      27             : // to true.
      28           1 : func And[E any](preds ...Predicate[E]) Predicate[E] { return and[E](preds) }
      29             : 
      30             : // Or returns a Predicate that evaluates to true if any of its operands evaluate
      31             : // true.
      32           1 : func Or[E any](preds ...Predicate[E]) Predicate[E] { return or[E](preds) }
      33             : 
      34             : // OnIndex returns a Predicate that evaluates to true on its N-th call.
      35           1 : func OnIndex[E any](n int32) *Index[E] {
      36           1 :         p := new(Index[E])
      37           1 :         p.Int32.Store(n)
      38           1 :         return p
      39           1 : }
      40             : 
      41             : // Index is a Predicate that evaluates to true only on its N-th invocation.
      42             : type Index[E any] struct {
      43             :         atomic.Int32
      44             : }
      45             : 
      46             : // String implements fmt.Stringer.
      47           1 : func (p *Index[E]) String() string {
      48           1 :         return fmt.Sprintf("(OnIndex %d)", p.Int32.Load())
      49           1 : }
      50             : 
      51             : // Evaluate implements Predicate.
      52           1 : func (p *Index[E]) Evaluate(E) bool { return p.Int32.Add(-1) == -1 }
      53             : 
      54             : type not[E any] struct {
      55             :         Predicate[E]
      56             : }
      57             : 
      58           0 : func (p not[E]) String() string    { return fmt.Sprintf("(Not %s)", p.Predicate.String()) }
      59           0 : func (p not[E]) Evaluate(e E) bool { return !p.Predicate.Evaluate(e) }
      60             : 
      61             : type and[E any] []Predicate[E]
      62             : 
      63           1 : func (p and[E]) String() string {
      64           1 :         var sb strings.Builder
      65           1 :         sb.WriteString("(And")
      66           1 :         for i := 0; i < len(p); i++ {
      67           1 :                 sb.WriteRune(' ')
      68           1 :                 sb.WriteString(p[i].String())
      69           1 :         }
      70           1 :         sb.WriteRune(')')
      71           1 :         return sb.String()
      72             : }
      73             : 
      74           1 : func (p and[E]) Evaluate(e E) bool {
      75           1 :         ok := true
      76           1 :         for i := range p {
      77           1 :                 ok = ok && p[i].Evaluate(e)
      78           1 :         }
      79           1 :         return ok
      80             : }
      81             : 
      82             : type or[E any] []Predicate[E]
      83             : 
      84           1 : func (p or[E]) String() string {
      85           1 :         var sb strings.Builder
      86           1 :         sb.WriteString("(Or")
      87           1 :         for i := 0; i < len(p); i++ {
      88           1 :                 sb.WriteRune(' ')
      89           1 :                 sb.WriteString(p[i].String())
      90           1 :         }
      91           1 :         sb.WriteRune(')')
      92           1 :         return sb.String()
      93             : }
      94             : 
      95           1 : func (p or[E]) Evaluate(e E) bool {
      96           1 :         ok := false
      97           1 :         for i := range p {
      98           1 :                 ok = ok || p[i].Evaluate(e)
      99           1 :         }
     100           1 :         return ok
     101             : }
     102             : 
     103           0 : func parseNot[E any](p *Parser[Predicate[E]], s *Scanner) Predicate[E] {
     104           0 :         preds := parseVariadicPredicate(p, s)
     105           0 :         if len(preds) != 1 {
     106           0 :                 panic(errors.Newf("dsl: not accepts exactly 1 argument, given %d", len(preds)))
     107             :         }
     108           0 :         return not[E]{Predicate: preds[0]}
     109             : }
     110             : 
     111           1 : func parseAnd[E any](p *Parser[Predicate[E]], s *Scanner) Predicate[E] {
     112           1 :         return And[E](parseVariadicPredicate[E](p, s)...)
     113           1 : }
     114             : 
     115           1 : func parseOr[E any](p *Parser[Predicate[E]], s *Scanner) Predicate[E] {
     116           1 :         return Or[E](parseVariadicPredicate[E](p, s)...)
     117           1 : }
     118             : 
     119           1 : func parseOnIndex[E any](p *Parser[Predicate[E]], s *Scanner) Predicate[E] {
     120           1 :         i, err := strconv.ParseInt(s.Consume(token.INT).Lit, 10, 32)
     121           1 :         if err != nil {
     122           1 :                 panic(err)
     123             :         }
     124           1 :         s.Consume(token.RPAREN)
     125           1 :         return OnIndex[E](int32(i))
     126             : }
     127             : 
     128           1 : func parseVariadicPredicate[E any](p *Parser[Predicate[E]], s *Scanner) (ret []Predicate[E]) {
     129           1 :         tok := s.Scan()
     130           1 :         for tok.Kind == token.LPAREN || tok.Kind == token.IDENT {
     131           1 :                 ret = append(ret, p.ParseFromPos(s, tok))
     132           1 :                 tok = s.Scan()
     133           1 :         }
     134           1 :         assertTok(tok, token.RPAREN)
     135           1 :         return ret
     136             : }

Generated by: LCOV version 1.14