http urls monitor.

marshal.go 17KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610
  1. package toml
  2. import (
  3. "bytes"
  4. "errors"
  5. "fmt"
  6. "io"
  7. "reflect"
  8. "strconv"
  9. "strings"
  10. "time"
  11. )
  12. const tagKeyMultiline = "multiline"
  13. type tomlOpts struct {
  14. name string
  15. comment string
  16. commented bool
  17. multiline bool
  18. include bool
  19. omitempty bool
  20. }
  21. type encOpts struct {
  22. quoteMapKeys bool
  23. arraysOneElementPerLine bool
  24. }
  25. var encOptsDefaults = encOpts{
  26. quoteMapKeys: false,
  27. }
  28. var timeType = reflect.TypeOf(time.Time{})
  29. var marshalerType = reflect.TypeOf(new(Marshaler)).Elem()
  30. // Check if the given marshall type maps to a Tree primitive
  31. func isPrimitive(mtype reflect.Type) bool {
  32. switch mtype.Kind() {
  33. case reflect.Ptr:
  34. return isPrimitive(mtype.Elem())
  35. case reflect.Bool:
  36. return true
  37. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  38. return true
  39. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
  40. return true
  41. case reflect.Float32, reflect.Float64:
  42. return true
  43. case reflect.String:
  44. return true
  45. case reflect.Struct:
  46. return mtype == timeType || isCustomMarshaler(mtype)
  47. default:
  48. return false
  49. }
  50. }
  51. // Check if the given marshall type maps to a Tree slice
  52. func isTreeSlice(mtype reflect.Type) bool {
  53. switch mtype.Kind() {
  54. case reflect.Slice:
  55. return !isOtherSlice(mtype)
  56. default:
  57. return false
  58. }
  59. }
  60. // Check if the given marshall type maps to a non-Tree slice
  61. func isOtherSlice(mtype reflect.Type) bool {
  62. switch mtype.Kind() {
  63. case reflect.Ptr:
  64. return isOtherSlice(mtype.Elem())
  65. case reflect.Slice:
  66. return isPrimitive(mtype.Elem()) || isOtherSlice(mtype.Elem())
  67. default:
  68. return false
  69. }
  70. }
  71. // Check if the given marshall type maps to a Tree
  72. func isTree(mtype reflect.Type) bool {
  73. switch mtype.Kind() {
  74. case reflect.Map:
  75. return true
  76. case reflect.Struct:
  77. return !isPrimitive(mtype)
  78. default:
  79. return false
  80. }
  81. }
  82. func isCustomMarshaler(mtype reflect.Type) bool {
  83. return mtype.Implements(marshalerType)
  84. }
  85. func callCustomMarshaler(mval reflect.Value) ([]byte, error) {
  86. return mval.Interface().(Marshaler).MarshalTOML()
  87. }
  88. // Marshaler is the interface implemented by types that
  89. // can marshal themselves into valid TOML.
  90. type Marshaler interface {
  91. MarshalTOML() ([]byte, error)
  92. }
  93. /*
  94. Marshal returns the TOML encoding of v. Behavior is similar to the Go json
  95. encoder, except that there is no concept of a Marshaler interface or MarshalTOML
  96. function for sub-structs, and currently only definite types can be marshaled
  97. (i.e. no `interface{}`).
  98. The following struct annotations are supported:
  99. toml:"Field" Overrides the field's name to output.
  100. omitempty When set, empty values and groups are not emitted.
  101. comment:"comment" Emits a # comment on the same line. This supports new lines.
  102. commented:"true" Emits the value as commented.
  103. Note that pointers are automatically assigned the "omitempty" option, as TOML
  104. explicitly does not handle null values (saying instead the label should be
  105. dropped).
  106. Tree structural types and corresponding marshal types:
  107. *Tree (*)struct, (*)map[string]interface{}
  108. []*Tree (*)[](*)struct, (*)[](*)map[string]interface{}
  109. []interface{} (as interface{}) (*)[]primitive, (*)[]([]interface{})
  110. interface{} (*)primitive
  111. Tree primitive types and corresponding marshal types:
  112. uint64 uint, uint8-uint64, pointers to same
  113. int64 int, int8-uint64, pointers to same
  114. float64 float32, float64, pointers to same
  115. string string, pointers to same
  116. bool bool, pointers to same
  117. time.Time time.Time{}, pointers to same
  118. */
  119. func Marshal(v interface{}) ([]byte, error) {
  120. return NewEncoder(nil).marshal(v)
  121. }
  122. // Encoder writes TOML values to an output stream.
  123. type Encoder struct {
  124. w io.Writer
  125. encOpts
  126. }
  127. // NewEncoder returns a new encoder that writes to w.
  128. func NewEncoder(w io.Writer) *Encoder {
  129. return &Encoder{
  130. w: w,
  131. encOpts: encOptsDefaults,
  132. }
  133. }
  134. // Encode writes the TOML encoding of v to the stream.
  135. //
  136. // See the documentation for Marshal for details.
  137. func (e *Encoder) Encode(v interface{}) error {
  138. b, err := e.marshal(v)
  139. if err != nil {
  140. return err
  141. }
  142. if _, err := e.w.Write(b); err != nil {
  143. return err
  144. }
  145. return nil
  146. }
  147. // QuoteMapKeys sets up the encoder to encode
  148. // maps with string type keys with quoted TOML keys.
  149. //
  150. // This relieves the character limitations on map keys.
  151. func (e *Encoder) QuoteMapKeys(v bool) *Encoder {
  152. e.quoteMapKeys = v
  153. return e
  154. }
  155. // ArraysWithOneElementPerLine sets up the encoder to encode arrays
  156. // with more than one element on multiple lines instead of one.
  157. //
  158. // For example:
  159. //
  160. // A = [1,2,3]
  161. //
  162. // Becomes
  163. //
  164. // A = [
  165. // 1,
  166. // 2,
  167. // 3,
  168. // ]
  169. func (e *Encoder) ArraysWithOneElementPerLine(v bool) *Encoder {
  170. e.arraysOneElementPerLine = v
  171. return e
  172. }
  173. func (e *Encoder) marshal(v interface{}) ([]byte, error) {
  174. mtype := reflect.TypeOf(v)
  175. if mtype.Kind() != reflect.Struct {
  176. return []byte{}, errors.New("Only a struct can be marshaled to TOML")
  177. }
  178. sval := reflect.ValueOf(v)
  179. if isCustomMarshaler(mtype) {
  180. return callCustomMarshaler(sval)
  181. }
  182. t, err := e.valueToTree(mtype, sval)
  183. if err != nil {
  184. return []byte{}, err
  185. }
  186. var buf bytes.Buffer
  187. _, err = t.writeTo(&buf, "", "", 0, e.arraysOneElementPerLine)
  188. return buf.Bytes(), err
  189. }
  190. // Convert given marshal struct or map value to toml tree
  191. func (e *Encoder) valueToTree(mtype reflect.Type, mval reflect.Value) (*Tree, error) {
  192. if mtype.Kind() == reflect.Ptr {
  193. return e.valueToTree(mtype.Elem(), mval.Elem())
  194. }
  195. tval := newTree()
  196. switch mtype.Kind() {
  197. case reflect.Struct:
  198. for i := 0; i < mtype.NumField(); i++ {
  199. mtypef, mvalf := mtype.Field(i), mval.Field(i)
  200. opts := tomlOptions(mtypef)
  201. if opts.include && (!opts.omitempty || !isZero(mvalf)) {
  202. val, err := e.valueToToml(mtypef.Type, mvalf)
  203. if err != nil {
  204. return nil, err
  205. }
  206. tval.SetWithOptions(opts.name, SetOptions{
  207. Comment: opts.comment,
  208. Commented: opts.commented,
  209. Multiline: opts.multiline,
  210. }, val)
  211. }
  212. }
  213. case reflect.Map:
  214. for _, key := range mval.MapKeys() {
  215. mvalf := mval.MapIndex(key)
  216. val, err := e.valueToToml(mtype.Elem(), mvalf)
  217. if err != nil {
  218. return nil, err
  219. }
  220. if e.quoteMapKeys {
  221. keyStr, err := tomlValueStringRepresentation(key.String(), "", e.arraysOneElementPerLine)
  222. if err != nil {
  223. return nil, err
  224. }
  225. tval.SetPath([]string{keyStr}, val)
  226. } else {
  227. tval.Set(key.String(), val)
  228. }
  229. }
  230. }
  231. return tval, nil
  232. }
  233. // Convert given marshal slice to slice of Toml trees
  234. func (e *Encoder) valueToTreeSlice(mtype reflect.Type, mval reflect.Value) ([]*Tree, error) {
  235. tval := make([]*Tree, mval.Len(), mval.Len())
  236. for i := 0; i < mval.Len(); i++ {
  237. val, err := e.valueToTree(mtype.Elem(), mval.Index(i))
  238. if err != nil {
  239. return nil, err
  240. }
  241. tval[i] = val
  242. }
  243. return tval, nil
  244. }
  245. // Convert given marshal slice to slice of toml values
  246. func (e *Encoder) valueToOtherSlice(mtype reflect.Type, mval reflect.Value) (interface{}, error) {
  247. tval := make([]interface{}, mval.Len(), mval.Len())
  248. for i := 0; i < mval.Len(); i++ {
  249. val, err := e.valueToToml(mtype.Elem(), mval.Index(i))
  250. if err != nil {
  251. return nil, err
  252. }
  253. tval[i] = val
  254. }
  255. return tval, nil
  256. }
  257. // Convert given marshal value to toml value
  258. func (e *Encoder) valueToToml(mtype reflect.Type, mval reflect.Value) (interface{}, error) {
  259. if mtype.Kind() == reflect.Ptr {
  260. return e.valueToToml(mtype.Elem(), mval.Elem())
  261. }
  262. switch {
  263. case isCustomMarshaler(mtype):
  264. return callCustomMarshaler(mval)
  265. case isTree(mtype):
  266. return e.valueToTree(mtype, mval)
  267. case isTreeSlice(mtype):
  268. return e.valueToTreeSlice(mtype, mval)
  269. case isOtherSlice(mtype):
  270. return e.valueToOtherSlice(mtype, mval)
  271. default:
  272. switch mtype.Kind() {
  273. case reflect.Bool:
  274. return mval.Bool(), nil
  275. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  276. return mval.Int(), nil
  277. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
  278. return mval.Uint(), nil
  279. case reflect.Float32, reflect.Float64:
  280. return mval.Float(), nil
  281. case reflect.String:
  282. return mval.String(), nil
  283. case reflect.Struct:
  284. return mval.Interface().(time.Time), nil
  285. default:
  286. return nil, fmt.Errorf("Marshal can't handle %v(%v)", mtype, mtype.Kind())
  287. }
  288. }
  289. }
  290. // Unmarshal attempts to unmarshal the Tree into a Go struct pointed by v.
  291. // Neither Unmarshaler interfaces nor UnmarshalTOML functions are supported for
  292. // sub-structs, and only definite types can be unmarshaled.
  293. func (t *Tree) Unmarshal(v interface{}) error {
  294. d := Decoder{tval: t}
  295. return d.unmarshal(v)
  296. }
  297. // Marshal returns the TOML encoding of Tree.
  298. // See Marshal() documentation for types mapping table.
  299. func (t *Tree) Marshal() ([]byte, error) {
  300. var buf bytes.Buffer
  301. err := NewEncoder(&buf).Encode(t)
  302. return buf.Bytes(), err
  303. }
  304. // Unmarshal parses the TOML-encoded data and stores the result in the value
  305. // pointed to by v. Behavior is similar to the Go json encoder, except that there
  306. // is no concept of an Unmarshaler interface or UnmarshalTOML function for
  307. // sub-structs, and currently only definite types can be unmarshaled to (i.e. no
  308. // `interface{}`).
  309. //
  310. // The following struct annotations are supported:
  311. //
  312. // toml:"Field" Overrides the field's name to map to.
  313. //
  314. // See Marshal() documentation for types mapping table.
  315. func Unmarshal(data []byte, v interface{}) error {
  316. t, err := LoadReader(bytes.NewReader(data))
  317. if err != nil {
  318. return err
  319. }
  320. return t.Unmarshal(v)
  321. }
  322. // Decoder reads and decodes TOML values from an input stream.
  323. type Decoder struct {
  324. r io.Reader
  325. tval *Tree
  326. encOpts
  327. }
  328. // NewDecoder returns a new decoder that reads from r.
  329. func NewDecoder(r io.Reader) *Decoder {
  330. return &Decoder{
  331. r: r,
  332. encOpts: encOptsDefaults,
  333. }
  334. }
  335. // Decode reads a TOML-encoded value from it's input
  336. // and unmarshals it in the value pointed at by v.
  337. //
  338. // See the documentation for Marshal for details.
  339. func (d *Decoder) Decode(v interface{}) error {
  340. var err error
  341. d.tval, err = LoadReader(d.r)
  342. if err != nil {
  343. return err
  344. }
  345. return d.unmarshal(v)
  346. }
  347. func (d *Decoder) unmarshal(v interface{}) error {
  348. mtype := reflect.TypeOf(v)
  349. if mtype.Kind() != reflect.Ptr || mtype.Elem().Kind() != reflect.Struct {
  350. return errors.New("Only a pointer to struct can be unmarshaled from TOML")
  351. }
  352. sval, err := d.valueFromTree(mtype.Elem(), d.tval)
  353. if err != nil {
  354. return err
  355. }
  356. reflect.ValueOf(v).Elem().Set(sval)
  357. return nil
  358. }
  359. // Convert toml tree to marshal struct or map, using marshal type
  360. func (d *Decoder) valueFromTree(mtype reflect.Type, tval *Tree) (reflect.Value, error) {
  361. if mtype.Kind() == reflect.Ptr {
  362. return d.unwrapPointer(mtype, tval)
  363. }
  364. var mval reflect.Value
  365. switch mtype.Kind() {
  366. case reflect.Struct:
  367. mval = reflect.New(mtype).Elem()
  368. for i := 0; i < mtype.NumField(); i++ {
  369. mtypef := mtype.Field(i)
  370. opts := tomlOptions(mtypef)
  371. if opts.include {
  372. baseKey := opts.name
  373. keysToTry := []string{baseKey, strings.ToLower(baseKey), strings.ToTitle(baseKey)}
  374. for _, key := range keysToTry {
  375. exists := tval.Has(key)
  376. if !exists {
  377. continue
  378. }
  379. val := tval.Get(key)
  380. mvalf, err := d.valueFromToml(mtypef.Type, val)
  381. if err != nil {
  382. return mval, formatError(err, tval.GetPosition(key))
  383. }
  384. mval.Field(i).Set(mvalf)
  385. break
  386. }
  387. }
  388. }
  389. case reflect.Map:
  390. mval = reflect.MakeMap(mtype)
  391. for _, key := range tval.Keys() {
  392. // TODO: path splits key
  393. val := tval.GetPath([]string{key})
  394. mvalf, err := d.valueFromToml(mtype.Elem(), val)
  395. if err != nil {
  396. return mval, formatError(err, tval.GetPosition(key))
  397. }
  398. mval.SetMapIndex(reflect.ValueOf(key), mvalf)
  399. }
  400. }
  401. return mval, nil
  402. }
  403. // Convert toml value to marshal struct/map slice, using marshal type
  404. func (d *Decoder) valueFromTreeSlice(mtype reflect.Type, tval []*Tree) (reflect.Value, error) {
  405. mval := reflect.MakeSlice(mtype, len(tval), len(tval))
  406. for i := 0; i < len(tval); i++ {
  407. val, err := d.valueFromTree(mtype.Elem(), tval[i])
  408. if err != nil {
  409. return mval, err
  410. }
  411. mval.Index(i).Set(val)
  412. }
  413. return mval, nil
  414. }
  415. // Convert toml value to marshal primitive slice, using marshal type
  416. func (d *Decoder) valueFromOtherSlice(mtype reflect.Type, tval []interface{}) (reflect.Value, error) {
  417. mval := reflect.MakeSlice(mtype, len(tval), len(tval))
  418. for i := 0; i < len(tval); i++ {
  419. val, err := d.valueFromToml(mtype.Elem(), tval[i])
  420. if err != nil {
  421. return mval, err
  422. }
  423. mval.Index(i).Set(val)
  424. }
  425. return mval, nil
  426. }
  427. // Convert toml value to marshal value, using marshal type
  428. func (d *Decoder) valueFromToml(mtype reflect.Type, tval interface{}) (reflect.Value, error) {
  429. if mtype.Kind() == reflect.Ptr {
  430. return d.unwrapPointer(mtype, tval)
  431. }
  432. switch tval.(type) {
  433. case *Tree:
  434. if isTree(mtype) {
  435. return d.valueFromTree(mtype, tval.(*Tree))
  436. }
  437. return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to a tree", tval, tval)
  438. case []*Tree:
  439. if isTreeSlice(mtype) {
  440. return d.valueFromTreeSlice(mtype, tval.([]*Tree))
  441. }
  442. return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to trees", tval, tval)
  443. case []interface{}:
  444. if isOtherSlice(mtype) {
  445. return d.valueFromOtherSlice(mtype, tval.([]interface{}))
  446. }
  447. return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to a slice", tval, tval)
  448. default:
  449. switch mtype.Kind() {
  450. case reflect.Bool, reflect.Struct:
  451. val := reflect.ValueOf(tval)
  452. // if this passes for when mtype is reflect.Struct, tval is a time.Time
  453. if !val.Type().ConvertibleTo(mtype) {
  454. return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to %v", tval, tval, mtype.String())
  455. }
  456. return val.Convert(mtype), nil
  457. case reflect.String:
  458. val := reflect.ValueOf(tval)
  459. // stupidly, int64 is convertible to string. So special case this.
  460. if !val.Type().ConvertibleTo(mtype) || val.Kind() == reflect.Int64 {
  461. return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to %v", tval, tval, mtype.String())
  462. }
  463. return val.Convert(mtype), nil
  464. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  465. val := reflect.ValueOf(tval)
  466. if !val.Type().ConvertibleTo(mtype) {
  467. return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to %v", tval, tval, mtype.String())
  468. }
  469. if reflect.Indirect(reflect.New(mtype)).OverflowInt(val.Int()) {
  470. return reflect.ValueOf(nil), fmt.Errorf("%v(%T) would overflow %v", tval, tval, mtype.String())
  471. }
  472. return val.Convert(mtype), nil
  473. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
  474. val := reflect.ValueOf(tval)
  475. if !val.Type().ConvertibleTo(mtype) {
  476. return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to %v", tval, tval, mtype.String())
  477. }
  478. if val.Int() < 0 {
  479. return reflect.ValueOf(nil), fmt.Errorf("%v(%T) is negative so does not fit in %v", tval, tval, mtype.String())
  480. }
  481. if reflect.Indirect(reflect.New(mtype)).OverflowUint(uint64(val.Int())) {
  482. return reflect.ValueOf(nil), fmt.Errorf("%v(%T) would overflow %v", tval, tval, mtype.String())
  483. }
  484. return val.Convert(mtype), nil
  485. case reflect.Float32, reflect.Float64:
  486. val := reflect.ValueOf(tval)
  487. if !val.Type().ConvertibleTo(mtype) {
  488. return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to %v", tval, tval, mtype.String())
  489. }
  490. if reflect.Indirect(reflect.New(mtype)).OverflowFloat(val.Float()) {
  491. return reflect.ValueOf(nil), fmt.Errorf("%v(%T) would overflow %v", tval, tval, mtype.String())
  492. }
  493. return val.Convert(mtype), nil
  494. default:
  495. return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to %v(%v)", tval, tval, mtype, mtype.Kind())
  496. }
  497. }
  498. }
  499. func (d *Decoder) unwrapPointer(mtype reflect.Type, tval interface{}) (reflect.Value, error) {
  500. val, err := d.valueFromToml(mtype.Elem(), tval)
  501. if err != nil {
  502. return reflect.ValueOf(nil), err
  503. }
  504. mval := reflect.New(mtype.Elem())
  505. mval.Elem().Set(val)
  506. return mval, nil
  507. }
  508. func tomlOptions(vf reflect.StructField) tomlOpts {
  509. tag := vf.Tag.Get("toml")
  510. parse := strings.Split(tag, ",")
  511. var comment string
  512. if c := vf.Tag.Get("comment"); c != "" {
  513. comment = c
  514. }
  515. commented, _ := strconv.ParseBool(vf.Tag.Get("commented"))
  516. multiline, _ := strconv.ParseBool(vf.Tag.Get(tagKeyMultiline))
  517. result := tomlOpts{name: vf.Name, comment: comment, commented: commented, multiline: multiline, include: true, omitempty: false}
  518. if parse[0] != "" {
  519. if parse[0] == "-" && len(parse) == 1 {
  520. result.include = false
  521. } else {
  522. result.name = strings.Trim(parse[0], " ")
  523. }
  524. }
  525. if vf.PkgPath != "" {
  526. result.include = false
  527. }
  528. if len(parse) > 1 && strings.Trim(parse[1], " ") == "omitempty" {
  529. result.omitempty = true
  530. }
  531. if vf.Type.Kind() == reflect.Ptr {
  532. result.omitempty = true
  533. }
  534. return result
  535. }
  536. func isZero(val reflect.Value) bool {
  537. switch val.Type().Kind() {
  538. case reflect.Map:
  539. fallthrough
  540. case reflect.Array:
  541. fallthrough
  542. case reflect.Slice:
  543. return val.Len() == 0
  544. default:
  545. return reflect.DeepEqual(val.Interface(), reflect.Zero(val.Type()).Interface())
  546. }
  547. }
  548. func formatError(err error, pos Position) error {
  549. if err.Error()[0] == '(' { // Error already contains position information
  550. return err
  551. }
  552. return fmt.Errorf("%s: %s", pos, err)
  553. }