go-tg-screenshot-bot
817 строк · 15.3 Кб
1package dbus2
3import (4"bytes"5"errors"6"fmt"7"io"8"reflect"9"strconv"10"strings"11"unicode/utf8"12)
13
14type varParser struct {15tokens []varToken16i int17}
18
19func (p *varParser) backup() {20p.i--21}
22
23func (p *varParser) next() varToken {24if p.i < len(p.tokens) {25t := p.tokens[p.i]26p.i++27return t28}29return varToken{typ: tokEOF}30}
31
32type varNode interface {33Infer() (Signature, error)34String() string35Sigs() sigSet36Value(Signature) (interface{}, error)37}
38
39func varMakeNode(p *varParser) (varNode, error) {40var sig Signature41
42for {43t := p.next()44switch t.typ {45case tokEOF:46return nil, io.ErrUnexpectedEOF47case tokError:48return nil, errors.New(t.val)49case tokNumber:50return varMakeNumNode(t, sig)51case tokString:52return varMakeStringNode(t, sig)53case tokBool:54if sig.str != "" && sig.str != "b" {55return nil, varTypeError{t.val, sig}56}57b, err := strconv.ParseBool(t.val)58if err != nil {59return nil, err60}61return boolNode(b), nil62case tokArrayStart:63return varMakeArrayNode(p, sig)64case tokVariantStart:65return varMakeVariantNode(p, sig)66case tokDictStart:67return varMakeDictNode(p, sig)68case tokType:69if sig.str != "" {70return nil, errors.New("unexpected type annotation")71}72if t.val[0] == '@' {73sig.str = t.val[1:]74} else {75sig.str = varTypeMap[t.val]76}77case tokByteString:78if sig.str != "" && sig.str != "ay" {79return nil, varTypeError{t.val, sig}80}81b, err := varParseByteString(t.val)82if err != nil {83return nil, err84}85return byteStringNode(b), nil86default:87return nil, fmt.Errorf("unexpected %q", t.val)88}89}90}
91
92type varTypeError struct {93val string94sig Signature
95}
96
97func (e varTypeError) Error() string {98return fmt.Sprintf("dbus: can't parse %q as type %q", e.val, e.sig.str)99}
100
101type sigSet map[Signature]bool102
103func (s sigSet) Empty() bool {104return len(s) == 0105}
106
107func (s sigSet) Intersect(s2 sigSet) sigSet {108r := make(sigSet)109for k := range s {110if s2[k] {111r[k] = true112}113}114return r115}
116
117func (s sigSet) Single() (Signature, bool) {118if len(s) == 1 {119for k := range s {120return k, true121}122}123return Signature{}, false124}
125
126func (s sigSet) ToArray() sigSet {127r := make(sigSet, len(s))128for k := range s {129r[Signature{"a" + k.str}] = true130}131return r132}
133
134type numNode struct {135sig Signature
136str string137val interface{}138}
139
140var numSigSet = sigSet{141Signature{"y"}: true,142Signature{"n"}: true,143Signature{"q"}: true,144Signature{"i"}: true,145Signature{"u"}: true,146Signature{"x"}: true,147Signature{"t"}: true,148Signature{"d"}: true,149}
150
151func (n numNode) Infer() (Signature, error) {152if strings.ContainsAny(n.str, ".e") {153return Signature{"d"}, nil154}155return Signature{"i"}, nil156}
157
158func (n numNode) String() string {159return n.str160}
161
162func (n numNode) Sigs() sigSet {163if n.sig.str != "" {164return sigSet{n.sig: true}165}166if strings.ContainsAny(n.str, ".e") {167return sigSet{Signature{"d"}: true}168}169return numSigSet170}
171
172func (n numNode) Value(sig Signature) (interface{}, error) {173if n.sig.str != "" && n.sig != sig {174return nil, varTypeError{n.str, sig}175}176if n.val != nil {177return n.val, nil178}179return varNumAs(n.str, sig)180}
181
182func varMakeNumNode(tok varToken, sig Signature) (varNode, error) {183if sig.str == "" {184return numNode{str: tok.val}, nil185}186num, err := varNumAs(tok.val, sig)187if err != nil {188return nil, err189}190return numNode{sig: sig, val: num}, nil191}
192
193func varNumAs(s string, sig Signature) (interface{}, error) {194isUnsigned := false195size := 32196switch sig.str {197case "n":198size = 16199case "i":200case "x":201size = 64202case "y":203size = 8204isUnsigned = true205case "q":206size = 16207isUnsigned = true208case "u":209isUnsigned = true210case "t":211size = 64212isUnsigned = true213case "d":214d, err := strconv.ParseFloat(s, 64)215if err != nil {216return nil, err217}218return d, nil219default:220return nil, varTypeError{s, sig}221}222base := 10223if strings.HasPrefix(s, "0x") {224base = 16225s = s[2:]226}227if strings.HasPrefix(s, "0") && len(s) != 1 {228base = 8229s = s[1:]230}231if isUnsigned {232i, err := strconv.ParseUint(s, base, size)233if err != nil {234return nil, err235}236var v interface{} = i237switch sig.str {238case "y":239v = byte(i)240case "q":241v = uint16(i)242case "u":243v = uint32(i)244}245return v, nil246}247i, err := strconv.ParseInt(s, base, size)248if err != nil {249return nil, err250}251var v interface{} = i252switch sig.str {253case "n":254v = int16(i)255case "i":256v = int32(i)257}258return v, nil259}
260
261type stringNode struct {262sig Signature
263str string // parsed264val interface{} // has correct type265}
266
267var stringSigSet = sigSet{268Signature{"s"}: true,269Signature{"g"}: true,270Signature{"o"}: true,271}
272
273func (n stringNode) Infer() (Signature, error) {274return Signature{"s"}, nil275}
276
277func (n stringNode) String() string {278return n.str279}
280
281func (n stringNode) Sigs() sigSet {282if n.sig.str != "" {283return sigSet{n.sig: true}284}285return stringSigSet286}
287
288func (n stringNode) Value(sig Signature) (interface{}, error) {289if n.sig.str != "" && n.sig != sig {290return nil, varTypeError{n.str, sig}291}292if n.val != nil {293return n.val, nil294}295switch {296case sig.str == "g":297return Signature{n.str}, nil298case sig.str == "o":299return ObjectPath(n.str), nil300case sig.str == "s":301return n.str, nil302default:303return nil, varTypeError{n.str, sig}304}305}
306
307func varMakeStringNode(tok varToken, sig Signature) (varNode, error) {308if sig.str != "" && sig.str != "s" && sig.str != "g" && sig.str != "o" {309return nil, fmt.Errorf("invalid type %q for string", sig.str)310}311s, err := varParseString(tok.val)312if err != nil {313return nil, err314}315n := stringNode{str: s}316if sig.str == "" {317return stringNode{str: s}, nil318}319n.sig = sig320switch sig.str {321case "o":322n.val = ObjectPath(s)323case "g":324n.val = Signature{s}325case "s":326n.val = s327}328return n, nil329}
330
331func varParseString(s string) (string, error) {332// quotes are guaranteed to be there333s = s[1 : len(s)-1]334buf := new(bytes.Buffer)335for len(s) != 0 {336r, size := utf8.DecodeRuneInString(s)337if r == utf8.RuneError && size == 1 {338return "", errors.New("invalid UTF-8")339}340s = s[size:]341if r != '\\' {342buf.WriteRune(r)343continue344}345r, size = utf8.DecodeRuneInString(s)346if r == utf8.RuneError && size == 1 {347return "", errors.New("invalid UTF-8")348}349s = s[size:]350switch r {351case 'a':352buf.WriteRune(0x7)353case 'b':354buf.WriteRune(0x8)355case 'f':356buf.WriteRune(0xc)357case 'n':358buf.WriteRune('\n')359case 'r':360buf.WriteRune('\r')361case 't':362buf.WriteRune('\t')363case '\n':364case 'u':365if len(s) < 4 {366return "", errors.New("short unicode escape")367}368r, err := strconv.ParseUint(s[:4], 16, 32)369if err != nil {370return "", err371}372buf.WriteRune(rune(r))373s = s[4:]374case 'U':375if len(s) < 8 {376return "", errors.New("short unicode escape")377}378r, err := strconv.ParseUint(s[:8], 16, 32)379if err != nil {380return "", err381}382buf.WriteRune(rune(r))383s = s[8:]384default:385buf.WriteRune(r)386}387}388return buf.String(), nil389}
390
391var boolSigSet = sigSet{Signature{"b"}: true}392
393type boolNode bool394
395func (boolNode) Infer() (Signature, error) {396return Signature{"b"}, nil397}
398
399func (b boolNode) String() string {400if b {401return "true"402}403return "false"404}
405
406func (boolNode) Sigs() sigSet {407return boolSigSet408}
409
410func (b boolNode) Value(sig Signature) (interface{}, error) {411if sig.str != "b" {412return nil, varTypeError{b.String(), sig}413}414return bool(b), nil415}
416
417type arrayNode struct {418set sigSet
419children []varNode420val interface{}421}
422
423func (n arrayNode) Infer() (Signature, error) {424for _, v := range n.children {425csig, err := varInfer(v)426if err != nil {427continue428}429return Signature{"a" + csig.str}, nil430}431return Signature{}, fmt.Errorf("can't infer type for %q", n.String())432}
433
434func (n arrayNode) String() string {435s := "["436for i, v := range n.children {437s += v.String()438if i != len(n.children)-1 {439s += ", "440}441}442return s + "]"443}
444
445func (n arrayNode) Sigs() sigSet {446return n.set447}
448
449func (n arrayNode) Value(sig Signature) (interface{}, error) {450if n.set.Empty() {451// no type information whatsoever, so this must be an empty slice452return reflect.MakeSlice(typeFor(sig.str), 0, 0).Interface(), nil453}454if !n.set[sig] {455return nil, varTypeError{n.String(), sig}456}457s := reflect.MakeSlice(typeFor(sig.str), len(n.children), len(n.children))458for i, v := range n.children {459rv, err := v.Value(Signature{sig.str[1:]})460if err != nil {461return nil, err462}463s.Index(i).Set(reflect.ValueOf(rv))464}465return s.Interface(), nil466}
467
468func varMakeArrayNode(p *varParser, sig Signature) (varNode, error) {469var n arrayNode470if sig.str != "" {471n.set = sigSet{sig: true}472}473if t := p.next(); t.typ == tokArrayEnd {474return n, nil475} else {476p.backup()477}478Loop:479for {480t := p.next()481switch t.typ {482case tokEOF:483return nil, io.ErrUnexpectedEOF484case tokError:485return nil, errors.New(t.val)486}487p.backup()488cn, err := varMakeNode(p)489if err != nil {490return nil, err491}492if cset := cn.Sigs(); !cset.Empty() {493if n.set.Empty() {494n.set = cset.ToArray()495} else {496nset := cset.ToArray().Intersect(n.set)497if nset.Empty() {498return nil, fmt.Errorf("can't parse %q with given type information", cn.String())499}500n.set = nset501}502}503n.children = append(n.children, cn)504switch t := p.next(); t.typ {505case tokEOF:506return nil, io.ErrUnexpectedEOF507case tokError:508return nil, errors.New(t.val)509case tokArrayEnd:510break Loop511case tokComma:512continue513default:514return nil, fmt.Errorf("unexpected %q", t.val)515}516}517return n, nil518}
519
520type variantNode struct {521n varNode
522}
523
524var variantSet = sigSet{525Signature{"v"}: true,526}
527
528func (variantNode) Infer() (Signature, error) {529return Signature{"v"}, nil530}
531
532func (n variantNode) String() string {533return "<" + n.n.String() + ">"534}
535
536func (variantNode) Sigs() sigSet {537return variantSet538}
539
540func (n variantNode) Value(sig Signature) (interface{}, error) {541if sig.str != "v" {542return nil, varTypeError{n.String(), sig}543}544sig, err := varInfer(n.n)545if err != nil {546return nil, err547}548v, err := n.n.Value(sig)549if err != nil {550return nil, err551}552return MakeVariant(v), nil553}
554
555func varMakeVariantNode(p *varParser, sig Signature) (varNode, error) {556n, err := varMakeNode(p)557if err != nil {558return nil, err559}560if t := p.next(); t.typ != tokVariantEnd {561return nil, fmt.Errorf("unexpected %q", t.val)562}563vn := variantNode{n}564if sig.str != "" && sig.str != "v" {565return nil, varTypeError{vn.String(), sig}566}567return variantNode{n}, nil568}
569
570type dictEntry struct {571key, val varNode572}
573
574type dictNode struct {575kset, vset sigSet576children []dictEntry577val interface{}578}
579
580func (n dictNode) Infer() (Signature, error) {581for _, v := range n.children {582ksig, err := varInfer(v.key)583if err != nil {584continue585}586vsig, err := varInfer(v.val)587if err != nil {588continue589}590return Signature{"a{" + ksig.str + vsig.str + "}"}, nil591}592return Signature{}, fmt.Errorf("can't infer type for %q", n.String())593}
594
595func (n dictNode) String() string {596s := "{"597for i, v := range n.children {598s += v.key.String() + ": " + v.val.String()599if i != len(n.children)-1 {600s += ", "601}602}603return s + "}"604}
605
606func (n dictNode) Sigs() sigSet {607r := sigSet{}608for k := range n.kset {609for v := range n.vset {610sig := "a{" + k.str + v.str + "}"611r[Signature{sig}] = true612}613}614return r615}
616
617func (n dictNode) Value(sig Signature) (interface{}, error) {618set := n.Sigs()619if set.Empty() {620// no type information -> empty dict621return reflect.MakeMap(typeFor(sig.str)).Interface(), nil622}623if !set[sig] {624return nil, varTypeError{n.String(), sig}625}626m := reflect.MakeMap(typeFor(sig.str))627ksig := Signature{sig.str[2:3]}628vsig := Signature{sig.str[3 : len(sig.str)-1]}629for _, v := range n.children {630kv, err := v.key.Value(ksig)631if err != nil {632return nil, err633}634vv, err := v.val.Value(vsig)635if err != nil {636return nil, err637}638m.SetMapIndex(reflect.ValueOf(kv), reflect.ValueOf(vv))639}640return m.Interface(), nil641}
642
643func varMakeDictNode(p *varParser, sig Signature) (varNode, error) {644var n dictNode645
646if sig.str != "" {647if len(sig.str) < 5 {648return nil, fmt.Errorf("invalid signature %q for dict type", sig)649}650ksig := Signature{string(sig.str[2])}651vsig := Signature{sig.str[3 : len(sig.str)-1]}652n.kset = sigSet{ksig: true}653n.vset = sigSet{vsig: true}654}655if t := p.next(); t.typ == tokDictEnd {656return n, nil657} else {658p.backup()659}660Loop:661for {662t := p.next()663switch t.typ {664case tokEOF:665return nil, io.ErrUnexpectedEOF666case tokError:667return nil, errors.New(t.val)668}669p.backup()670kn, err := varMakeNode(p)671if err != nil {672return nil, err673}674if kset := kn.Sigs(); !kset.Empty() {675if n.kset.Empty() {676n.kset = kset677} else {678n.kset = kset.Intersect(n.kset)679if n.kset.Empty() {680return nil, fmt.Errorf("can't parse %q with given type information", kn.String())681}682}683}684t = p.next()685switch t.typ {686case tokEOF:687return nil, io.ErrUnexpectedEOF688case tokError:689return nil, errors.New(t.val)690case tokColon:691default:692return nil, fmt.Errorf("unexpected %q", t.val)693}694t = p.next()695switch t.typ {696case tokEOF:697return nil, io.ErrUnexpectedEOF698case tokError:699return nil, errors.New(t.val)700}701p.backup()702vn, err := varMakeNode(p)703if err != nil {704return nil, err705}706if vset := vn.Sigs(); !vset.Empty() {707if n.vset.Empty() {708n.vset = vset709} else {710n.vset = n.vset.Intersect(vset)711if n.vset.Empty() {712return nil, fmt.Errorf("can't parse %q with given type information", vn.String())713}714}715}716n.children = append(n.children, dictEntry{kn, vn})717t = p.next()718switch t.typ {719case tokEOF:720return nil, io.ErrUnexpectedEOF721case tokError:722return nil, errors.New(t.val)723case tokDictEnd:724break Loop725case tokComma:726continue727default:728return nil, fmt.Errorf("unexpected %q", t.val)729}730}731return n, nil732}
733
734type byteStringNode []byte735
736var byteStringSet = sigSet{737Signature{"ay"}: true,738}
739
740func (byteStringNode) Infer() (Signature, error) {741return Signature{"ay"}, nil742}
743
744func (b byteStringNode) String() string {745return string(b)746}
747
748func (b byteStringNode) Sigs() sigSet {749return byteStringSet750}
751
752func (b byteStringNode) Value(sig Signature) (interface{}, error) {753if sig.str != "ay" {754return nil, varTypeError{b.String(), sig}755}756return []byte(b), nil757}
758
759func varParseByteString(s string) ([]byte, error) {760// quotes and b at start are guaranteed to be there761b := make([]byte, 0, 1)762s = s[2 : len(s)-1]763for len(s) != 0 {764c := s[0]765s = s[1:]766if c != '\\' {767b = append(b, c)768continue769}770c = s[0]771s = s[1:]772switch c {773case 'a':774b = append(b, 0x7)775case 'b':776b = append(b, 0x8)777case 'f':778b = append(b, 0xc)779case 'n':780b = append(b, '\n')781case 'r':782b = append(b, '\r')783case 't':784b = append(b, '\t')785case 'x':786if len(s) < 2 {787return nil, errors.New("short escape")788}789n, err := strconv.ParseUint(s[:2], 16, 8)790if err != nil {791return nil, err792}793b = append(b, byte(n))794s = s[2:]795case '0':796if len(s) < 3 {797return nil, errors.New("short escape")798}799n, err := strconv.ParseUint(s[:3], 8, 8)800if err != nil {801return nil, err802}803b = append(b, byte(n))804s = s[3:]805default:806b = append(b, c)807}808}809return append(b, 0), nil810}
811
812func varInfer(n varNode) (Signature, error) {813if sig, ok := n.Sigs().Single(); ok {814return sig, nil815}816return n.Infer()817}
818