|
@@ -1,817 +0,0 @@
|
|
|
-package dbus
|
|
|
-
|
|
|
-import (
|
|
|
- "bytes"
|
|
|
- "errors"
|
|
|
- "fmt"
|
|
|
- "io"
|
|
|
- "reflect"
|
|
|
- "strconv"
|
|
|
- "strings"
|
|
|
- "unicode/utf8"
|
|
|
-)
|
|
|
-
|
|
|
-type varParser struct {
|
|
|
- tokens []varToken
|
|
|
- i int
|
|
|
-}
|
|
|
-
|
|
|
-func (p *varParser) backup() {
|
|
|
- p.i--
|
|
|
-}
|
|
|
-
|
|
|
-func (p *varParser) next() varToken {
|
|
|
- if p.i < len(p.tokens) {
|
|
|
- t := p.tokens[p.i]
|
|
|
- p.i++
|
|
|
- return t
|
|
|
- }
|
|
|
- return varToken{typ: tokEOF}
|
|
|
-}
|
|
|
-
|
|
|
-type varNode interface {
|
|
|
- Infer() (Signature, error)
|
|
|
- String() string
|
|
|
- Sigs() sigSet
|
|
|
- Value(Signature) (interface{}, error)
|
|
|
-}
|
|
|
-
|
|
|
-func varMakeNode(p *varParser) (varNode, error) {
|
|
|
- var sig Signature
|
|
|
-
|
|
|
- for {
|
|
|
- t := p.next()
|
|
|
- switch t.typ {
|
|
|
- case tokEOF:
|
|
|
- return nil, io.ErrUnexpectedEOF
|
|
|
- case tokError:
|
|
|
- return nil, errors.New(t.val)
|
|
|
- case tokNumber:
|
|
|
- return varMakeNumNode(t, sig)
|
|
|
- case tokString:
|
|
|
- return varMakeStringNode(t, sig)
|
|
|
- case tokBool:
|
|
|
- if sig.str != "" && sig.str != "b" {
|
|
|
- return nil, varTypeError{t.val, sig}
|
|
|
- }
|
|
|
- b, err := strconv.ParseBool(t.val)
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
- return boolNode(b), nil
|
|
|
- case tokArrayStart:
|
|
|
- return varMakeArrayNode(p, sig)
|
|
|
- case tokVariantStart:
|
|
|
- return varMakeVariantNode(p, sig)
|
|
|
- case tokDictStart:
|
|
|
- return varMakeDictNode(p, sig)
|
|
|
- case tokType:
|
|
|
- if sig.str != "" {
|
|
|
- return nil, errors.New("unexpected type annotation")
|
|
|
- }
|
|
|
- if t.val[0] == '@' {
|
|
|
- sig.str = t.val[1:]
|
|
|
- } else {
|
|
|
- sig.str = varTypeMap[t.val]
|
|
|
- }
|
|
|
- case tokByteString:
|
|
|
- if sig.str != "" && sig.str != "ay" {
|
|
|
- return nil, varTypeError{t.val, sig}
|
|
|
- }
|
|
|
- b, err := varParseByteString(t.val)
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
- return byteStringNode(b), nil
|
|
|
- default:
|
|
|
- return nil, fmt.Errorf("unexpected %q", t.val)
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-type varTypeError struct {
|
|
|
- val string
|
|
|
- sig Signature
|
|
|
-}
|
|
|
-
|
|
|
-func (e varTypeError) Error() string {
|
|
|
- return fmt.Sprintf("dbus: can't parse %q as type %q", e.val, e.sig.str)
|
|
|
-}
|
|
|
-
|
|
|
-type sigSet map[Signature]bool
|
|
|
-
|
|
|
-func (s sigSet) Empty() bool {
|
|
|
- return len(s) == 0
|
|
|
-}
|
|
|
-
|
|
|
-func (s sigSet) Intersect(s2 sigSet) sigSet {
|
|
|
- r := make(sigSet)
|
|
|
- for k := range s {
|
|
|
- if s2[k] {
|
|
|
- r[k] = true
|
|
|
- }
|
|
|
- }
|
|
|
- return r
|
|
|
-}
|
|
|
-
|
|
|
-func (s sigSet) Single() (Signature, bool) {
|
|
|
- if len(s) == 1 {
|
|
|
- for k := range s {
|
|
|
- return k, true
|
|
|
- }
|
|
|
- }
|
|
|
- return Signature{}, false
|
|
|
-}
|
|
|
-
|
|
|
-func (s sigSet) ToArray() sigSet {
|
|
|
- r := make(sigSet, len(s))
|
|
|
- for k := range s {
|
|
|
- r[Signature{"a" + k.str}] = true
|
|
|
- }
|
|
|
- return r
|
|
|
-}
|
|
|
-
|
|
|
-type numNode struct {
|
|
|
- sig Signature
|
|
|
- str string
|
|
|
- val interface{}
|
|
|
-}
|
|
|
-
|
|
|
-var numSigSet = sigSet{
|
|
|
- Signature{"y"}: true,
|
|
|
- Signature{"n"}: true,
|
|
|
- Signature{"q"}: true,
|
|
|
- Signature{"i"}: true,
|
|
|
- Signature{"u"}: true,
|
|
|
- Signature{"x"}: true,
|
|
|
- Signature{"t"}: true,
|
|
|
- Signature{"d"}: true,
|
|
|
-}
|
|
|
-
|
|
|
-func (n numNode) Infer() (Signature, error) {
|
|
|
- if strings.ContainsAny(n.str, ".e") {
|
|
|
- return Signature{"d"}, nil
|
|
|
- }
|
|
|
- return Signature{"i"}, nil
|
|
|
-}
|
|
|
-
|
|
|
-func (n numNode) String() string {
|
|
|
- return n.str
|
|
|
-}
|
|
|
-
|
|
|
-func (n numNode) Sigs() sigSet {
|
|
|
- if n.sig.str != "" {
|
|
|
- return sigSet{n.sig: true}
|
|
|
- }
|
|
|
- if strings.ContainsAny(n.str, ".e") {
|
|
|
- return sigSet{Signature{"d"}: true}
|
|
|
- }
|
|
|
- return numSigSet
|
|
|
-}
|
|
|
-
|
|
|
-func (n numNode) Value(sig Signature) (interface{}, error) {
|
|
|
- if n.sig.str != "" && n.sig != sig {
|
|
|
- return nil, varTypeError{n.str, sig}
|
|
|
- }
|
|
|
- if n.val != nil {
|
|
|
- return n.val, nil
|
|
|
- }
|
|
|
- return varNumAs(n.str, sig)
|
|
|
-}
|
|
|
-
|
|
|
-func varMakeNumNode(tok varToken, sig Signature) (varNode, error) {
|
|
|
- if sig.str == "" {
|
|
|
- return numNode{str: tok.val}, nil
|
|
|
- }
|
|
|
- num, err := varNumAs(tok.val, sig)
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
- return numNode{sig: sig, val: num}, nil
|
|
|
-}
|
|
|
-
|
|
|
-func varNumAs(s string, sig Signature) (interface{}, error) {
|
|
|
- isUnsigned := false
|
|
|
- size := 32
|
|
|
- switch sig.str {
|
|
|
- case "n":
|
|
|
- size = 16
|
|
|
- case "i":
|
|
|
- case "x":
|
|
|
- size = 64
|
|
|
- case "y":
|
|
|
- size = 8
|
|
|
- isUnsigned = true
|
|
|
- case "q":
|
|
|
- size = 16
|
|
|
- isUnsigned = true
|
|
|
- case "u":
|
|
|
- isUnsigned = true
|
|
|
- case "t":
|
|
|
- size = 64
|
|
|
- isUnsigned = true
|
|
|
- case "d":
|
|
|
- d, err := strconv.ParseFloat(s, 64)
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
- return d, nil
|
|
|
- default:
|
|
|
- return nil, varTypeError{s, sig}
|
|
|
- }
|
|
|
- base := 10
|
|
|
- if strings.HasPrefix(s, "0x") {
|
|
|
- base = 16
|
|
|
- s = s[2:]
|
|
|
- }
|
|
|
- if strings.HasPrefix(s, "0") && len(s) != 1 {
|
|
|
- base = 8
|
|
|
- s = s[1:]
|
|
|
- }
|
|
|
- if isUnsigned {
|
|
|
- i, err := strconv.ParseUint(s, base, size)
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
- var v interface{} = i
|
|
|
- switch sig.str {
|
|
|
- case "y":
|
|
|
- v = byte(i)
|
|
|
- case "q":
|
|
|
- v = uint16(i)
|
|
|
- case "u":
|
|
|
- v = uint32(i)
|
|
|
- }
|
|
|
- return v, nil
|
|
|
- }
|
|
|
- i, err := strconv.ParseInt(s, base, size)
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
- var v interface{} = i
|
|
|
- switch sig.str {
|
|
|
- case "n":
|
|
|
- v = int16(i)
|
|
|
- case "i":
|
|
|
- v = int32(i)
|
|
|
- }
|
|
|
- return v, nil
|
|
|
-}
|
|
|
-
|
|
|
-type stringNode struct {
|
|
|
- sig Signature
|
|
|
- str string // parsed
|
|
|
- val interface{} // has correct type
|
|
|
-}
|
|
|
-
|
|
|
-var stringSigSet = sigSet{
|
|
|
- Signature{"s"}: true,
|
|
|
- Signature{"g"}: true,
|
|
|
- Signature{"o"}: true,
|
|
|
-}
|
|
|
-
|
|
|
-func (n stringNode) Infer() (Signature, error) {
|
|
|
- return Signature{"s"}, nil
|
|
|
-}
|
|
|
-
|
|
|
-func (n stringNode) String() string {
|
|
|
- return n.str
|
|
|
-}
|
|
|
-
|
|
|
-func (n stringNode) Sigs() sigSet {
|
|
|
- if n.sig.str != "" {
|
|
|
- return sigSet{n.sig: true}
|
|
|
- }
|
|
|
- return stringSigSet
|
|
|
-}
|
|
|
-
|
|
|
-func (n stringNode) Value(sig Signature) (interface{}, error) {
|
|
|
- if n.sig.str != "" && n.sig != sig {
|
|
|
- return nil, varTypeError{n.str, sig}
|
|
|
- }
|
|
|
- if n.val != nil {
|
|
|
- return n.val, nil
|
|
|
- }
|
|
|
- switch {
|
|
|
- case sig.str == "g":
|
|
|
- return Signature{n.str}, nil
|
|
|
- case sig.str == "o":
|
|
|
- return ObjectPath(n.str), nil
|
|
|
- case sig.str == "s":
|
|
|
- return n.str, nil
|
|
|
- default:
|
|
|
- return nil, varTypeError{n.str, sig}
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-func varMakeStringNode(tok varToken, sig Signature) (varNode, error) {
|
|
|
- if sig.str != "" && sig.str != "s" && sig.str != "g" && sig.str != "o" {
|
|
|
- return nil, fmt.Errorf("invalid type %q for string", sig.str)
|
|
|
- }
|
|
|
- s, err := varParseString(tok.val)
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
- n := stringNode{str: s}
|
|
|
- if sig.str == "" {
|
|
|
- return stringNode{str: s}, nil
|
|
|
- }
|
|
|
- n.sig = sig
|
|
|
- switch sig.str {
|
|
|
- case "o":
|
|
|
- n.val = ObjectPath(s)
|
|
|
- case "g":
|
|
|
- n.val = Signature{s}
|
|
|
- case "s":
|
|
|
- n.val = s
|
|
|
- }
|
|
|
- return n, nil
|
|
|
-}
|
|
|
-
|
|
|
-func varParseString(s string) (string, error) {
|
|
|
- // quotes are guaranteed to be there
|
|
|
- s = s[1 : len(s)-1]
|
|
|
- buf := new(bytes.Buffer)
|
|
|
- for len(s) != 0 {
|
|
|
- r, size := utf8.DecodeRuneInString(s)
|
|
|
- if r == utf8.RuneError && size == 1 {
|
|
|
- return "", errors.New("invalid UTF-8")
|
|
|
- }
|
|
|
- s = s[size:]
|
|
|
- if r != '\\' {
|
|
|
- buf.WriteRune(r)
|
|
|
- continue
|
|
|
- }
|
|
|
- r, size = utf8.DecodeRuneInString(s)
|
|
|
- if r == utf8.RuneError && size == 1 {
|
|
|
- return "", errors.New("invalid UTF-8")
|
|
|
- }
|
|
|
- s = s[size:]
|
|
|
- switch r {
|
|
|
- case 'a':
|
|
|
- buf.WriteRune(0x7)
|
|
|
- case 'b':
|
|
|
- buf.WriteRune(0x8)
|
|
|
- case 'f':
|
|
|
- buf.WriteRune(0xc)
|
|
|
- case 'n':
|
|
|
- buf.WriteRune('\n')
|
|
|
- case 'r':
|
|
|
- buf.WriteRune('\r')
|
|
|
- case 't':
|
|
|
- buf.WriteRune('\t')
|
|
|
- case '\n':
|
|
|
- case 'u':
|
|
|
- if len(s) < 4 {
|
|
|
- return "", errors.New("short unicode escape")
|
|
|
- }
|
|
|
- r, err := strconv.ParseUint(s[:4], 16, 32)
|
|
|
- if err != nil {
|
|
|
- return "", err
|
|
|
- }
|
|
|
- buf.WriteRune(rune(r))
|
|
|
- s = s[4:]
|
|
|
- case 'U':
|
|
|
- if len(s) < 8 {
|
|
|
- return "", errors.New("short unicode escape")
|
|
|
- }
|
|
|
- r, err := strconv.ParseUint(s[:8], 16, 32)
|
|
|
- if err != nil {
|
|
|
- return "", err
|
|
|
- }
|
|
|
- buf.WriteRune(rune(r))
|
|
|
- s = s[8:]
|
|
|
- default:
|
|
|
- buf.WriteRune(r)
|
|
|
- }
|
|
|
- }
|
|
|
- return buf.String(), nil
|
|
|
-}
|
|
|
-
|
|
|
-var boolSigSet = sigSet{Signature{"b"}: true}
|
|
|
-
|
|
|
-type boolNode bool
|
|
|
-
|
|
|
-func (boolNode) Infer() (Signature, error) {
|
|
|
- return Signature{"b"}, nil
|
|
|
-}
|
|
|
-
|
|
|
-func (b boolNode) String() string {
|
|
|
- if b {
|
|
|
- return "true"
|
|
|
- }
|
|
|
- return "false"
|
|
|
-}
|
|
|
-
|
|
|
-func (boolNode) Sigs() sigSet {
|
|
|
- return boolSigSet
|
|
|
-}
|
|
|
-
|
|
|
-func (b boolNode) Value(sig Signature) (interface{}, error) {
|
|
|
- if sig.str != "b" {
|
|
|
- return nil, varTypeError{b.String(), sig}
|
|
|
- }
|
|
|
- return bool(b), nil
|
|
|
-}
|
|
|
-
|
|
|
-type arrayNode struct {
|
|
|
- set sigSet
|
|
|
- children []varNode
|
|
|
- val interface{}
|
|
|
-}
|
|
|
-
|
|
|
-func (n arrayNode) Infer() (Signature, error) {
|
|
|
- for _, v := range n.children {
|
|
|
- csig, err := varInfer(v)
|
|
|
- if err != nil {
|
|
|
- continue
|
|
|
- }
|
|
|
- return Signature{"a" + csig.str}, nil
|
|
|
- }
|
|
|
- return Signature{}, fmt.Errorf("can't infer type for %q", n.String())
|
|
|
-}
|
|
|
-
|
|
|
-func (n arrayNode) String() string {
|
|
|
- s := "["
|
|
|
- for i, v := range n.children {
|
|
|
- s += v.String()
|
|
|
- if i != len(n.children)-1 {
|
|
|
- s += ", "
|
|
|
- }
|
|
|
- }
|
|
|
- return s + "]"
|
|
|
-}
|
|
|
-
|
|
|
-func (n arrayNode) Sigs() sigSet {
|
|
|
- return n.set
|
|
|
-}
|
|
|
-
|
|
|
-func (n arrayNode) Value(sig Signature) (interface{}, error) {
|
|
|
- if n.set.Empty() {
|
|
|
- // no type information whatsoever, so this must be an empty slice
|
|
|
- return reflect.MakeSlice(typeFor(sig.str), 0, 0).Interface(), nil
|
|
|
- }
|
|
|
- if !n.set[sig] {
|
|
|
- return nil, varTypeError{n.String(), sig}
|
|
|
- }
|
|
|
- s := reflect.MakeSlice(typeFor(sig.str), len(n.children), len(n.children))
|
|
|
- for i, v := range n.children {
|
|
|
- rv, err := v.Value(Signature{sig.str[1:]})
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
- s.Index(i).Set(reflect.ValueOf(rv))
|
|
|
- }
|
|
|
- return s.Interface(), nil
|
|
|
-}
|
|
|
-
|
|
|
-func varMakeArrayNode(p *varParser, sig Signature) (varNode, error) {
|
|
|
- var n arrayNode
|
|
|
- if sig.str != "" {
|
|
|
- n.set = sigSet{sig: true}
|
|
|
- }
|
|
|
- if t := p.next(); t.typ == tokArrayEnd {
|
|
|
- return n, nil
|
|
|
- } else {
|
|
|
- p.backup()
|
|
|
- }
|
|
|
-Loop:
|
|
|
- for {
|
|
|
- t := p.next()
|
|
|
- switch t.typ {
|
|
|
- case tokEOF:
|
|
|
- return nil, io.ErrUnexpectedEOF
|
|
|
- case tokError:
|
|
|
- return nil, errors.New(t.val)
|
|
|
- }
|
|
|
- p.backup()
|
|
|
- cn, err := varMakeNode(p)
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
- if cset := cn.Sigs(); !cset.Empty() {
|
|
|
- if n.set.Empty() {
|
|
|
- n.set = cset.ToArray()
|
|
|
- } else {
|
|
|
- nset := cset.ToArray().Intersect(n.set)
|
|
|
- if nset.Empty() {
|
|
|
- return nil, fmt.Errorf("can't parse %q with given type information", cn.String())
|
|
|
- }
|
|
|
- n.set = nset
|
|
|
- }
|
|
|
- }
|
|
|
- n.children = append(n.children, cn)
|
|
|
- switch t := p.next(); t.typ {
|
|
|
- case tokEOF:
|
|
|
- return nil, io.ErrUnexpectedEOF
|
|
|
- case tokError:
|
|
|
- return nil, errors.New(t.val)
|
|
|
- case tokArrayEnd:
|
|
|
- break Loop
|
|
|
- case tokComma:
|
|
|
- continue
|
|
|
- default:
|
|
|
- return nil, fmt.Errorf("unexpected %q", t.val)
|
|
|
- }
|
|
|
- }
|
|
|
- return n, nil
|
|
|
-}
|
|
|
-
|
|
|
-type variantNode struct {
|
|
|
- n varNode
|
|
|
-}
|
|
|
-
|
|
|
-var variantSet = sigSet{
|
|
|
- Signature{"v"}: true,
|
|
|
-}
|
|
|
-
|
|
|
-func (variantNode) Infer() (Signature, error) {
|
|
|
- return Signature{"v"}, nil
|
|
|
-}
|
|
|
-
|
|
|
-func (n variantNode) String() string {
|
|
|
- return "<" + n.n.String() + ">"
|
|
|
-}
|
|
|
-
|
|
|
-func (variantNode) Sigs() sigSet {
|
|
|
- return variantSet
|
|
|
-}
|
|
|
-
|
|
|
-func (n variantNode) Value(sig Signature) (interface{}, error) {
|
|
|
- if sig.str != "v" {
|
|
|
- return nil, varTypeError{n.String(), sig}
|
|
|
- }
|
|
|
- sig, err := varInfer(n.n)
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
- v, err := n.n.Value(sig)
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
- return MakeVariant(v), nil
|
|
|
-}
|
|
|
-
|
|
|
-func varMakeVariantNode(p *varParser, sig Signature) (varNode, error) {
|
|
|
- n, err := varMakeNode(p)
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
- if t := p.next(); t.typ != tokVariantEnd {
|
|
|
- return nil, fmt.Errorf("unexpected %q", t.val)
|
|
|
- }
|
|
|
- vn := variantNode{n}
|
|
|
- if sig.str != "" && sig.str != "v" {
|
|
|
- return nil, varTypeError{vn.String(), sig}
|
|
|
- }
|
|
|
- return variantNode{n}, nil
|
|
|
-}
|
|
|
-
|
|
|
-type dictEntry struct {
|
|
|
- key, val varNode
|
|
|
-}
|
|
|
-
|
|
|
-type dictNode struct {
|
|
|
- kset, vset sigSet
|
|
|
- children []dictEntry
|
|
|
- val interface{}
|
|
|
-}
|
|
|
-
|
|
|
-func (n dictNode) Infer() (Signature, error) {
|
|
|
- for _, v := range n.children {
|
|
|
- ksig, err := varInfer(v.key)
|
|
|
- if err != nil {
|
|
|
- continue
|
|
|
- }
|
|
|
- vsig, err := varInfer(v.val)
|
|
|
- if err != nil {
|
|
|
- continue
|
|
|
- }
|
|
|
- return Signature{"a{" + ksig.str + vsig.str + "}"}, nil
|
|
|
- }
|
|
|
- return Signature{}, fmt.Errorf("can't infer type for %q", n.String())
|
|
|
-}
|
|
|
-
|
|
|
-func (n dictNode) String() string {
|
|
|
- s := "{"
|
|
|
- for i, v := range n.children {
|
|
|
- s += v.key.String() + ": " + v.val.String()
|
|
|
- if i != len(n.children)-1 {
|
|
|
- s += ", "
|
|
|
- }
|
|
|
- }
|
|
|
- return s + "}"
|
|
|
-}
|
|
|
-
|
|
|
-func (n dictNode) Sigs() sigSet {
|
|
|
- r := sigSet{}
|
|
|
- for k := range n.kset {
|
|
|
- for v := range n.vset {
|
|
|
- sig := "a{" + k.str + v.str + "}"
|
|
|
- r[Signature{sig}] = true
|
|
|
- }
|
|
|
- }
|
|
|
- return r
|
|
|
-}
|
|
|
-
|
|
|
-func (n dictNode) Value(sig Signature) (interface{}, error) {
|
|
|
- set := n.Sigs()
|
|
|
- if set.Empty() {
|
|
|
- // no type information -> empty dict
|
|
|
- return reflect.MakeMap(typeFor(sig.str)).Interface(), nil
|
|
|
- }
|
|
|
- if !set[sig] {
|
|
|
- return nil, varTypeError{n.String(), sig}
|
|
|
- }
|
|
|
- m := reflect.MakeMap(typeFor(sig.str))
|
|
|
- ksig := Signature{sig.str[2:3]}
|
|
|
- vsig := Signature{sig.str[3 : len(sig.str)-1]}
|
|
|
- for _, v := range n.children {
|
|
|
- kv, err := v.key.Value(ksig)
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
- vv, err := v.val.Value(vsig)
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
- m.SetMapIndex(reflect.ValueOf(kv), reflect.ValueOf(vv))
|
|
|
- }
|
|
|
- return m.Interface(), nil
|
|
|
-}
|
|
|
-
|
|
|
-func varMakeDictNode(p *varParser, sig Signature) (varNode, error) {
|
|
|
- var n dictNode
|
|
|
-
|
|
|
- if sig.str != "" {
|
|
|
- if len(sig.str) < 5 {
|
|
|
- return nil, fmt.Errorf("invalid signature %q for dict type", sig)
|
|
|
- }
|
|
|
- ksig := Signature{string(sig.str[2])}
|
|
|
- vsig := Signature{sig.str[3 : len(sig.str)-1]}
|
|
|
- n.kset = sigSet{ksig: true}
|
|
|
- n.vset = sigSet{vsig: true}
|
|
|
- }
|
|
|
- if t := p.next(); t.typ == tokDictEnd {
|
|
|
- return n, nil
|
|
|
- } else {
|
|
|
- p.backup()
|
|
|
- }
|
|
|
-Loop:
|
|
|
- for {
|
|
|
- t := p.next()
|
|
|
- switch t.typ {
|
|
|
- case tokEOF:
|
|
|
- return nil, io.ErrUnexpectedEOF
|
|
|
- case tokError:
|
|
|
- return nil, errors.New(t.val)
|
|
|
- }
|
|
|
- p.backup()
|
|
|
- kn, err := varMakeNode(p)
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
- if kset := kn.Sigs(); !kset.Empty() {
|
|
|
- if n.kset.Empty() {
|
|
|
- n.kset = kset
|
|
|
- } else {
|
|
|
- n.kset = kset.Intersect(n.kset)
|
|
|
- if n.kset.Empty() {
|
|
|
- return nil, fmt.Errorf("can't parse %q with given type information", kn.String())
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- t = p.next()
|
|
|
- switch t.typ {
|
|
|
- case tokEOF:
|
|
|
- return nil, io.ErrUnexpectedEOF
|
|
|
- case tokError:
|
|
|
- return nil, errors.New(t.val)
|
|
|
- case tokColon:
|
|
|
- default:
|
|
|
- return nil, fmt.Errorf("unexpected %q", t.val)
|
|
|
- }
|
|
|
- t = p.next()
|
|
|
- switch t.typ {
|
|
|
- case tokEOF:
|
|
|
- return nil, io.ErrUnexpectedEOF
|
|
|
- case tokError:
|
|
|
- return nil, errors.New(t.val)
|
|
|
- }
|
|
|
- p.backup()
|
|
|
- vn, err := varMakeNode(p)
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
- if vset := vn.Sigs(); !vset.Empty() {
|
|
|
- if n.vset.Empty() {
|
|
|
- n.vset = vset
|
|
|
- } else {
|
|
|
- n.vset = n.vset.Intersect(vset)
|
|
|
- if n.vset.Empty() {
|
|
|
- return nil, fmt.Errorf("can't parse %q with given type information", vn.String())
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- n.children = append(n.children, dictEntry{kn, vn})
|
|
|
- t = p.next()
|
|
|
- switch t.typ {
|
|
|
- case tokEOF:
|
|
|
- return nil, io.ErrUnexpectedEOF
|
|
|
- case tokError:
|
|
|
- return nil, errors.New(t.val)
|
|
|
- case tokDictEnd:
|
|
|
- break Loop
|
|
|
- case tokComma:
|
|
|
- continue
|
|
|
- default:
|
|
|
- return nil, fmt.Errorf("unexpected %q", t.val)
|
|
|
- }
|
|
|
- }
|
|
|
- return n, nil
|
|
|
-}
|
|
|
-
|
|
|
-type byteStringNode []byte
|
|
|
-
|
|
|
-var byteStringSet = sigSet{
|
|
|
- Signature{"ay"}: true,
|
|
|
-}
|
|
|
-
|
|
|
-func (byteStringNode) Infer() (Signature, error) {
|
|
|
- return Signature{"ay"}, nil
|
|
|
-}
|
|
|
-
|
|
|
-func (b byteStringNode) String() string {
|
|
|
- return string(b)
|
|
|
-}
|
|
|
-
|
|
|
-func (b byteStringNode) Sigs() sigSet {
|
|
|
- return byteStringSet
|
|
|
-}
|
|
|
-
|
|
|
-func (b byteStringNode) Value(sig Signature) (interface{}, error) {
|
|
|
- if sig.str != "ay" {
|
|
|
- return nil, varTypeError{b.String(), sig}
|
|
|
- }
|
|
|
- return []byte(b), nil
|
|
|
-}
|
|
|
-
|
|
|
-func varParseByteString(s string) ([]byte, error) {
|
|
|
- // quotes and b at start are guaranteed to be there
|
|
|
- b := make([]byte, 0, 1)
|
|
|
- s = s[2 : len(s)-1]
|
|
|
- for len(s) != 0 {
|
|
|
- c := s[0]
|
|
|
- s = s[1:]
|
|
|
- if c != '\\' {
|
|
|
- b = append(b, c)
|
|
|
- continue
|
|
|
- }
|
|
|
- c = s[0]
|
|
|
- s = s[1:]
|
|
|
- switch c {
|
|
|
- case 'a':
|
|
|
- b = append(b, 0x7)
|
|
|
- case 'b':
|
|
|
- b = append(b, 0x8)
|
|
|
- case 'f':
|
|
|
- b = append(b, 0xc)
|
|
|
- case 'n':
|
|
|
- b = append(b, '\n')
|
|
|
- case 'r':
|
|
|
- b = append(b, '\r')
|
|
|
- case 't':
|
|
|
- b = append(b, '\t')
|
|
|
- case 'x':
|
|
|
- if len(s) < 2 {
|
|
|
- return nil, errors.New("short escape")
|
|
|
- }
|
|
|
- n, err := strconv.ParseUint(s[:2], 16, 8)
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
- b = append(b, byte(n))
|
|
|
- s = s[2:]
|
|
|
- case '0':
|
|
|
- if len(s) < 3 {
|
|
|
- return nil, errors.New("short escape")
|
|
|
- }
|
|
|
- n, err := strconv.ParseUint(s[:3], 8, 8)
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
- b = append(b, byte(n))
|
|
|
- s = s[3:]
|
|
|
- default:
|
|
|
- b = append(b, c)
|
|
|
- }
|
|
|
- }
|
|
|
- return append(b, 0), nil
|
|
|
-}
|
|
|
-
|
|
|
-func varInfer(n varNode) (Signature, error) {
|
|
|
- if sig, ok := n.Sigs().Single(); ok {
|
|
|
- return sig, nil
|
|
|
- }
|
|
|
- return n.Infer()
|
|
|
-}
|