bool.go 1.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. // Copyright (c) 2020 Tailscale Inc & AUTHORS All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. // Package opt defines optional types.
  5. package opt
  6. import (
  7. "fmt"
  8. "strconv"
  9. )
  10. // Bool represents an optional boolean to be JSON-encoded.
  11. // The string can be empty (for unknown or unspecified), or
  12. // "true" or "false".
  13. type Bool string
  14. func (b *Bool) Set(v bool) {
  15. *b = Bool(strconv.FormatBool(v))
  16. }
  17. func (b *Bool) Clear() { *b = "" }
  18. func (b Bool) Get() (v bool, ok bool) {
  19. if b == "" {
  20. return
  21. }
  22. v, err := strconv.ParseBool(string(b))
  23. return v, err == nil
  24. }
  25. // EqualBool reports whether b is equal to v.
  26. // If b is empty or not a valid bool, it reports false.
  27. func (b Bool) EqualBool(v bool) bool {
  28. p, ok := b.Get()
  29. return ok && p == v
  30. }
  31. var (
  32. trueBytes = []byte("true")
  33. falseBytes = []byte("false")
  34. nullBytes = []byte("null")
  35. )
  36. func (b Bool) MarshalJSON() ([]byte, error) {
  37. switch b {
  38. case "true":
  39. return trueBytes, nil
  40. case "false":
  41. return falseBytes, nil
  42. case "":
  43. return nullBytes, nil
  44. }
  45. return nil, fmt.Errorf("invalid opt.Bool value %q", string(b))
  46. }
  47. func (b *Bool) UnmarshalJSON(j []byte) error {
  48. // Note: written with a bunch of ifs instead of a switch
  49. // because I'm sure the Go compiler optimizes away these
  50. // []byte->string allocations in an == comparison, but I'm too
  51. // lazy to check whether that's true in a switch also.
  52. if string(j) == "true" {
  53. *b = "true"
  54. return nil
  55. }
  56. if string(j) == "false" {
  57. *b = "false"
  58. return nil
  59. }
  60. if string(j) == "null" {
  61. *b = ""
  62. return nil
  63. }
  64. return fmt.Errorf("invalid opt.Bool value %q", j)
  65. }