github.com/yankunsam/loki/v2@v2.6.3-0.20220817130409-389df5235c27/pkg/logql/log/logfmt/decode.go (about) 1 // Adapted from https://github.com/go-logfmt/logfmt/ but []byte as parameter instead 2 // Original license is MIT. 3 package logfmt 4 5 import ( 6 "bytes" 7 "fmt" 8 "unicode/utf8" 9 ) 10 11 // A Decoder reads and decodes logfmt records from an input stream. 12 type Decoder struct { 13 pos int 14 key []byte 15 value []byte 16 line []byte 17 err error 18 } 19 20 // NewDecoder returns a new decoder that reads from r. 21 // 22 // The decoder introduces its own buffering and may read data from r beyond 23 // the logfmt records requested. 24 func NewDecoder(line []byte) *Decoder { 25 dec := &Decoder{line: line} 26 return dec 27 } 28 29 func (dec *Decoder) Reset(line []byte) { 30 dec.pos = 0 31 dec.line = line 32 dec.err = nil 33 } 34 35 // ScanKeyval advances the Decoder to the next key/value pair of the current 36 // record, which can then be retrieved with the Key and Value methods. It 37 // returns false when decoding stops, either by reaching the end of the 38 // current record or an error. 39 func (dec *Decoder) ScanKeyval() bool { 40 dec.key, dec.value = nil, nil 41 42 line := dec.line 43 // garbage 44 for p, c := range line[dec.pos:] { 45 if c > ' ' { 46 dec.pos += p 47 goto key 48 } 49 } 50 dec.pos = len(line) 51 return false 52 53 key: 54 const invalidKeyError = "invalid key" 55 56 start, multibyte := dec.pos, false 57 for p, c := range line[dec.pos:] { 58 switch { 59 case c == '=': 60 dec.pos += p 61 if dec.pos > start { 62 dec.key = line[start:dec.pos] 63 if multibyte && bytes.ContainsRune(dec.key, utf8.RuneError) { 64 dec.syntaxError(invalidKeyError) 65 return false 66 } 67 } 68 if dec.key == nil { 69 dec.unexpectedByte(c) 70 return false 71 } 72 goto equal 73 case c == '"': 74 dec.pos += p 75 dec.unexpectedByte(c) 76 return false 77 case c <= ' ': 78 dec.pos += p 79 if dec.pos > start { 80 dec.key = line[start:dec.pos] 81 if multibyte && bytes.ContainsRune(dec.key, utf8.RuneError) { 82 dec.syntaxError(invalidKeyError) 83 return false 84 } 85 } 86 return true 87 case c >= utf8.RuneSelf: 88 multibyte = true 89 } 90 } 91 dec.pos = len(line) 92 if dec.pos > start { 93 dec.key = line[start:dec.pos] 94 if multibyte && bytes.ContainsRune(dec.key, utf8.RuneError) { 95 dec.syntaxError(invalidKeyError) 96 return false 97 } 98 } 99 return true 100 101 equal: 102 dec.pos++ 103 if dec.pos >= len(line) { 104 return true 105 } 106 switch c := line[dec.pos]; { 107 case c <= ' ': 108 return true 109 case c == '"': 110 goto qvalue 111 } 112 113 // value 114 start = dec.pos 115 for p, c := range line[dec.pos:] { 116 switch { 117 case c == '=' || c == '"': 118 dec.pos += p 119 dec.unexpectedByte(c) 120 return false 121 case c <= ' ': 122 dec.pos += p 123 if dec.pos > start { 124 dec.value = line[start:dec.pos] 125 } 126 return true 127 } 128 } 129 dec.pos = len(line) 130 if dec.pos > start { 131 dec.value = line[start:dec.pos] 132 } 133 return true 134 135 qvalue: 136 const ( 137 untermQuote = "unterminated quoted value" 138 invalidQuote = "invalid quoted value" 139 ) 140 141 hasEsc, esc := false, false 142 start = dec.pos 143 for p, c := range line[dec.pos+1:] { 144 switch { 145 case esc: 146 esc = false 147 case c == '\\': 148 hasEsc, esc = true, true 149 case c == '"': 150 dec.pos += p + 2 151 if hasEsc { 152 v, ok := unquoteBytes(line[start:dec.pos]) 153 if !ok { 154 dec.syntaxError(invalidQuote) 155 return false 156 } 157 dec.value = v 158 } else { 159 start++ 160 end := dec.pos - 1 161 if end > start { 162 dec.value = line[start:end] 163 } 164 } 165 return true 166 } 167 } 168 dec.pos = len(line) 169 dec.syntaxError(untermQuote) 170 return false 171 } 172 173 // Key returns the most recent key found by a call to ScanKeyval. The returned 174 // slice may point to internal buffers and is only valid until the next call 175 // to ScanRecord. It does no allocation. 176 func (dec *Decoder) Key() []byte { 177 return dec.key 178 } 179 180 // Value returns the most recent value found by a call to ScanKeyval. The 181 // returned slice may point to internal buffers and is only valid until the 182 // next call to ScanRecord. It does no allocation when the value has no 183 // escape sequences. 184 func (dec *Decoder) Value() []byte { 185 return dec.value 186 } 187 188 // Err returns the first non-EOF error that was encountered by the Scanner. 189 func (dec *Decoder) Err() error { 190 return dec.err 191 } 192 193 func (dec *Decoder) syntaxError(msg string) { 194 dec.err = &SyntaxError{ 195 Msg: msg, 196 Pos: dec.pos + 1, 197 } 198 } 199 200 func (dec *Decoder) unexpectedByte(c byte) { 201 dec.err = &SyntaxError{ 202 Msg: fmt.Sprintf("unexpected %q", c), 203 Pos: dec.pos + 1, 204 } 205 } 206 207 // A SyntaxError represents a syntax error in the logfmt input stream. 208 type SyntaxError struct { 209 Msg string 210 Pos int 211 } 212 213 func (e *SyntaxError) Error() string { 214 return fmt.Sprintf("logfmt syntax error at pos %d : %s", e.Pos, e.Msg) 215 }