LCOV - code coverage report
Current view: top level - pebble/internal/datadrivenutil - datadrivenutil.go (source / functions) Hit Total Coverage
Test: 2024-04-01 08:16Z 1c7bcd1c - tests + meta.lcov Lines: 48 68 70.6 %
Date: 2024-04-01 08:17:59 Functions: 0 0 -

          Line data    Source code
       1             : // Package datadrivenutil defines facilities to improve ergonomics around
       2             : // parsing datadriven test input.
       3             : package datadrivenutil
       4             : 
       5             : import (
       6             :         "encoding/hex"
       7             :         "fmt"
       8             :         "strconv"
       9             :         "strings"
      10             :         "unicode"
      11             : )
      12             : 
      13             : // Lines wraps a string, providing facilities for parsing individual lines.
      14             : type Lines string
      15             : 
      16             : // Next returns the string up to the next newline. The receiver is modified to
      17             : // point to the string's contents immediately after the newline.
      18           1 : func (l *Lines) Next() (line Line) {
      19           1 :         i := strings.IndexByte(string(*l), '\n')
      20           1 :         if i == -1 {
      21           1 :                 line = Line(*l)
      22           1 :                 *l = ""
      23           1 :         } else {
      24           1 :                 line = Line((*l)[:i])
      25           1 :                 *l = (*l)[i+1:]
      26           1 :         }
      27           1 :         return line
      28             : }
      29             : 
      30             : // A Line is a string with no newlines.
      31             : type Line string
      32             : 
      33             : // Fields breaks the line into fields delimited by whitespace and any runes
      34             : // passed into the function.
      35           1 : func (l Line) Fields(delims ...rune) Fields {
      36           1 :         return Fields(strings.FieldsFunc(string(l), func(r rune) bool {
      37           1 :                 if unicode.IsSpace(r) {
      38           1 :                         return true
      39           1 :                 }
      40           1 :                 for _, delim := range delims {
      41           1 :                         if delim == r {
      42           1 :                                 return true
      43           1 :                         }
      44             :                 }
      45           1 :                 return false
      46             :         }))
      47             : }
      48             : 
      49             : // Fields wraps a []string with facilities for parsing out values.
      50             : type Fields []string
      51             : 
      52             : // String implements fmt.Stringer.
      53           0 : func (fs Fields) String() string {
      54           0 :         return strings.Join(fs, " ")
      55           0 : }
      56             : 
      57             : // HasValue searches for a field that is exactly the provided string.
      58           1 : func (fs Fields) HasValue(value string) bool {
      59           1 :         for i := range fs {
      60           1 :                 if fs[i] == value {
      61           1 :                         return true
      62           1 :                 }
      63             :         }
      64           1 :         return false
      65             : }
      66             : 
      67             : // Index returns the field at index i, or the empty string if there are i or
      68             : // fewer fields.
      69           1 : func (fs Fields) Index(i int) Value {
      70           1 :         if len(fs) <= i {
      71           0 :                 return ""
      72           0 :         }
      73           1 :         return Value(fs[i])
      74             : }
      75             : 
      76             : // KeyValue looks for a field containing a key=value pair with the provided key.
      77             : // If not found, KeyValue returns false for the second return value.
      78           1 : func (fs Fields) KeyValue(key string) (Value, bool) {
      79           1 :         for i := range fs {
      80           1 :                 if len(fs[i]) >= len(key) && strings.HasPrefix(fs[i], key) && fs[i][len(key)] == '=' {
      81           1 :                         return Value(fs[i][len(key)+1:]), true
      82           1 :                 }
      83             :         }
      84           0 :         return "", false
      85             : }
      86             : 
      87             : // MustKeyValue is like KeyValue but panics if the field is not found.
      88           1 : func (fs Fields) MustKeyValue(key string) Value {
      89           1 :         f, ok := fs.KeyValue(key)
      90           1 :         if !ok {
      91           0 :                 panic(fmt.Sprintf("unable to find required key-value pair %q", key))
      92             :         }
      93           1 :         return f
      94             : }
      95             : 
      96             : // HexBytes parses all the fields as hex-encoded bytes, returning the
      97             : // concatenated decoded bytes. It panics if any of the fields fail to parse as
      98             : // hex-encoded bytes.
      99           0 : func (fs Fields) HexBytes() []byte {
     100           0 :         var b []byte
     101           0 :         for _, f := range fs {
     102           0 :                 b = append(b, Value(f).HexBytes()...)
     103           0 :         }
     104           0 :         return b
     105             : }
     106             : 
     107             : // A Value represents a single string of unknown structure. A Value is sometimes
     108             : // used to represent an entire element of a Fields and other times a substring
     109             : // of an individual field. This blurring of semantics is convenient for
     110             : // parsing.
     111             : type Value string
     112             : 
     113             : // Str returns the value as a string.
     114           1 : func (v Value) Str() string { return string(v) }
     115             : 
     116             : // Bytes returns the value as a byte slice.
     117           1 : func (v Value) Bytes() []byte { return []byte(v) }
     118             : 
     119             : // Int parses the value as an int. It panics if the value fails to decode as an
     120             : // integer.
     121           1 : func (v Value) Int() int {
     122           1 :         vi, err := strconv.Atoi(string(v))
     123           1 :         if err != nil {
     124           0 :                 panic(err)
     125             :         }
     126           1 :         return vi
     127             : }
     128             : 
     129             : // Uint64 parses the value as an uint64. It panics if the value fails to decode
     130             : // as an uint64.
     131           1 : func (v Value) Uint64() uint64 {
     132           1 :         vi, err := strconv.ParseUint(string(v), 10, 64)
     133           1 :         if err != nil {
     134           0 :                 panic(err)
     135             :         }
     136           1 :         return vi
     137             : }
     138             : 
     139             : // HexBytes decodes the value as hex-encoded bytes. It panics if the value fails
     140             : // to decode as hex-encoded.
     141           0 : func (v Value) HexBytes() []byte {
     142           0 :         b, err := hex.DecodeString(string(v))
     143           0 :         if err != nil {
     144           0 :                 panic(err)
     145             :         }
     146           0 :         return b
     147             : }

Generated by: LCOV version 1.14