value.go 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. // Copyright (C) 2016 Kohei YOSHIDA. All rights reserved.
  2. //
  3. // This program is free software; you can redistribute it and/or
  4. // modify it under the terms of The BSD 3-Clause License
  5. // that can be found in the LICENSE file.
  6. package uritemplate
  7. import "strings"
  8. // A varname containing pct-encoded characters is not the same variable as
  9. // a varname with those same characters decoded.
  10. //
  11. // -- https://tools.ietf.org/html/rfc6570#section-2.3
  12. type Values map[string]Value
  13. func (v Values) Set(name string, value Value) {
  14. v[name] = value
  15. }
  16. func (v Values) Get(name string) Value {
  17. if v == nil {
  18. return Value{}
  19. }
  20. return v[name]
  21. }
  22. type ValueType uint8
  23. const (
  24. ValueTypeString = iota
  25. ValueTypeList
  26. ValueTypeKV
  27. valueTypeLast
  28. )
  29. var valueTypeNames = []string{
  30. "String",
  31. "List",
  32. "KV",
  33. }
  34. func (vt ValueType) String() string {
  35. if vt < valueTypeLast {
  36. return valueTypeNames[vt]
  37. }
  38. return ""
  39. }
  40. type Value struct {
  41. T ValueType
  42. V []string
  43. }
  44. func (v Value) String() string {
  45. if v.Valid() && v.T == ValueTypeString {
  46. return v.V[0]
  47. }
  48. return ""
  49. }
  50. func (v Value) List() []string {
  51. if v.Valid() && v.T == ValueTypeList {
  52. return v.V
  53. }
  54. return nil
  55. }
  56. func (v Value) KV() []string {
  57. if v.Valid() && v.T == ValueTypeKV {
  58. return v.V
  59. }
  60. return nil
  61. }
  62. func (v Value) Valid() bool {
  63. switch v.T {
  64. default:
  65. return false
  66. case ValueTypeString:
  67. return len(v.V) > 0
  68. case ValueTypeList:
  69. return len(v.V) > 0
  70. case ValueTypeKV:
  71. return len(v.V) > 0 && len(v.V)%2 == 0
  72. }
  73. }
  74. func (v Value) expand(w *strings.Builder, spec varspec, exp *expression) error {
  75. switch v.T {
  76. case ValueTypeString:
  77. val := v.V[0]
  78. var maxlen int
  79. if max := len(val); spec.maxlen < 1 || spec.maxlen > max {
  80. maxlen = max
  81. } else {
  82. maxlen = spec.maxlen
  83. }
  84. if exp.named {
  85. w.WriteString(spec.name)
  86. if val == "" {
  87. w.WriteString(exp.ifemp)
  88. return nil
  89. }
  90. w.WriteByte('=')
  91. }
  92. return exp.escape(w, val[:maxlen])
  93. case ValueTypeList:
  94. var sep string
  95. if spec.explode {
  96. sep = exp.sep
  97. } else {
  98. sep = ","
  99. }
  100. var pre string
  101. var preifemp string
  102. if spec.explode && exp.named {
  103. pre = spec.name + "="
  104. preifemp = spec.name + exp.ifemp
  105. }
  106. if !spec.explode && exp.named {
  107. w.WriteString(spec.name)
  108. w.WriteByte('=')
  109. }
  110. for i := range v.V {
  111. val := v.V[i]
  112. if i > 0 {
  113. w.WriteString(sep)
  114. }
  115. if val == "" {
  116. w.WriteString(preifemp)
  117. continue
  118. }
  119. w.WriteString(pre)
  120. if err := exp.escape(w, val); err != nil {
  121. return err
  122. }
  123. }
  124. case ValueTypeKV:
  125. var sep string
  126. var kvsep string
  127. if spec.explode {
  128. sep = exp.sep
  129. kvsep = "="
  130. } else {
  131. sep = ","
  132. kvsep = ","
  133. }
  134. var ifemp string
  135. var kescape escapeFunc
  136. if spec.explode && exp.named {
  137. ifemp = exp.ifemp
  138. kescape = escapeLiteral
  139. } else {
  140. ifemp = ","
  141. kescape = exp.escape
  142. }
  143. if !spec.explode && exp.named {
  144. w.WriteString(spec.name)
  145. w.WriteByte('=')
  146. }
  147. for i := 0; i < len(v.V); i += 2 {
  148. if i > 0 {
  149. w.WriteString(sep)
  150. }
  151. if err := kescape(w, v.V[i]); err != nil {
  152. return err
  153. }
  154. if v.V[i+1] == "" {
  155. w.WriteString(ifemp)
  156. continue
  157. }
  158. w.WriteString(kvsep)
  159. if err := exp.escape(w, v.V[i+1]); err != nil {
  160. return err
  161. }
  162. }
  163. }
  164. return nil
  165. }
  166. // String returns Value that represents string.
  167. func String(v string) Value {
  168. return Value{
  169. T: ValueTypeString,
  170. V: []string{v},
  171. }
  172. }
  173. // List returns Value that represents list.
  174. func List(v ...string) Value {
  175. return Value{
  176. T: ValueTypeList,
  177. V: v,
  178. }
  179. }
  180. // KV returns Value that represents associative list.
  181. // KV panics if len(kv) is not even.
  182. func KV(kv ...string) Value {
  183. if len(kv)%2 != 0 {
  184. panic("uritemplate.go: count of the kv must be even number")
  185. }
  186. return Value{
  187. T: ValueTypeKV,
  188. V: kv,
  189. }
  190. }