109 lines
2.5 KiB
Go
109 lines
2.5 KiB
Go
package options
|
|
|
|
import (
|
|
"fmt"
|
|
"strconv"
|
|
"unicode"
|
|
"unicode/utf8"
|
|
|
|
"github.com/influxdata/flux"
|
|
"github.com/influxdata/flux/ast"
|
|
"github.com/influxdata/flux/codes"
|
|
)
|
|
|
|
// TODO(jsternberg): This file copies over code from an internal package
|
|
// because we need them from an internal package and the only way they
|
|
// are exposed is through a package that depends on the core flux parser.
|
|
// We want to avoid a dependency on the core parser so we copy these
|
|
// implementations.
|
|
//
|
|
// In the future, we should consider exposing these functions from flux
|
|
// in a non-internal package outside of the parser package.
|
|
|
|
// ParseSignedDuration is a helper wrapper around parser.ParseSignedDuration.
|
|
// We use it because we need to clear the basenode, but flux does not.
|
|
func ParseSignedDuration(text string) (*ast.DurationLiteral, error) {
|
|
// TODO(jsternberg): This is copied from an internal package in flux to break a dependency
|
|
// on the parser package where this method is exposed.
|
|
// Consider exposing this properly in flux.
|
|
if r, s := utf8.DecodeRuneInString(text); r == '-' {
|
|
d, err := parseDuration(text[s:])
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
for i := range d {
|
|
d[i].Magnitude = -d[i].Magnitude
|
|
}
|
|
return &ast.DurationLiteral{Values: d}, nil
|
|
}
|
|
|
|
d, err := parseDuration(text)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &ast.DurationLiteral{Values: d}, nil
|
|
}
|
|
|
|
// parseDuration will convert a string into components of the duration.
|
|
func parseDuration(lit string) ([]ast.Duration, error) {
|
|
var values []ast.Duration
|
|
for len(lit) > 0 {
|
|
n := 0
|
|
for n < len(lit) {
|
|
ch, size := utf8.DecodeRuneInString(lit[n:])
|
|
if size == 0 {
|
|
panic("invalid rune in duration")
|
|
}
|
|
|
|
if !unicode.IsDigit(ch) {
|
|
break
|
|
}
|
|
n += size
|
|
}
|
|
|
|
if n == 0 {
|
|
return nil, &flux.Error{
|
|
Code: codes.Invalid,
|
|
Msg: fmt.Sprintf("invalid duration %s", lit),
|
|
}
|
|
}
|
|
|
|
magnitude, err := strconv.ParseInt(lit[:n], 10, 64)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
lit = lit[n:]
|
|
|
|
n = 0
|
|
for n < len(lit) {
|
|
ch, size := utf8.DecodeRuneInString(lit[n:])
|
|
if size == 0 {
|
|
panic("invalid rune in duration")
|
|
}
|
|
|
|
if !unicode.IsLetter(ch) {
|
|
break
|
|
}
|
|
n += size
|
|
}
|
|
|
|
if n == 0 {
|
|
return nil, &flux.Error{
|
|
Code: codes.Invalid,
|
|
Msg: fmt.Sprintf("duration is missing a unit: %s", lit),
|
|
}
|
|
}
|
|
|
|
unit := lit[:n]
|
|
if unit == "µs" {
|
|
unit = "us"
|
|
}
|
|
values = append(values, ast.Duration{
|
|
Magnitude: magnitude,
|
|
Unit: unit,
|
|
})
|
|
lit = lit[n:]
|
|
}
|
|
return values, nil
|
|
}
|