You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

456 lines
11 KiB

  1. // Package denco provides fast URL router.
  2. package denco
  3. import (
  4. "fmt"
  5. "sort"
  6. "strings"
  7. )
  8. const (
  9. // ParamCharacter is a special character for path parameter.
  10. ParamCharacter = ':'
  11. // WildcardCharacter is a special character for wildcard path parameter.
  12. WildcardCharacter = '*'
  13. // TerminationCharacter is a special character for end of path.
  14. TerminationCharacter = '#'
  15. // SeparatorCharacter separates path segments.
  16. SeparatorCharacter = '/'
  17. // MaxSize is max size of records and internal slice.
  18. MaxSize = (1 << 22) - 1
  19. )
  20. // Router represents a URL router.
  21. type Router struct {
  22. // SizeHint expects the maximum number of path parameters in records to Build.
  23. // SizeHint will be used to determine the capacity of the memory to allocate.
  24. // By default, SizeHint will be determined from given records to Build.
  25. SizeHint int
  26. static map[string]interface{}
  27. param *doubleArray
  28. }
  29. // New returns a new Router.
  30. func New() *Router {
  31. return &Router{
  32. SizeHint: -1,
  33. static: make(map[string]interface{}),
  34. param: newDoubleArray(),
  35. }
  36. }
  37. // Lookup returns data and path parameters that associated with path.
  38. // params is a slice of the Param that arranged in the order in which parameters appeared.
  39. // e.g. when built routing path is "/path/to/:id/:name" and given path is "/path/to/1/alice". params order is [{"id": "1"}, {"name": "alice"}], not [{"name": "alice"}, {"id": "1"}].
  40. func (rt *Router) Lookup(path string) (data interface{}, params Params, found bool) {
  41. if data, found := rt.static[path]; found {
  42. return data, nil, true
  43. }
  44. if len(rt.param.node) == 1 {
  45. return nil, nil, false
  46. }
  47. nd, params, found := rt.param.lookup(path, make([]Param, 0, rt.SizeHint), 1)
  48. if !found {
  49. return nil, nil, false
  50. }
  51. for i := 0; i < len(params); i++ {
  52. params[i].Name = nd.paramNames[i]
  53. }
  54. return nd.data, params, true
  55. }
  56. // Build builds URL router from records.
  57. func (rt *Router) Build(records []Record) error {
  58. statics, params := makeRecords(records)
  59. if len(params) > MaxSize {
  60. return fmt.Errorf("denco: too many records")
  61. }
  62. if rt.SizeHint < 0 {
  63. rt.SizeHint = 0
  64. for _, p := range params {
  65. size := 0
  66. for _, k := range p.Key {
  67. if k == ParamCharacter || k == WildcardCharacter {
  68. size++
  69. }
  70. }
  71. if size > rt.SizeHint {
  72. rt.SizeHint = size
  73. }
  74. }
  75. }
  76. for _, r := range statics {
  77. rt.static[r.Key] = r.Value
  78. }
  79. if err := rt.param.build(params, 1, 0, make(map[int]struct{})); err != nil {
  80. return err
  81. }
  82. return nil
  83. }
  84. // Param represents name and value of path parameter.
  85. type Param struct {
  86. Name string
  87. Value string
  88. }
  89. // Params represents the name and value of path parameters.
  90. type Params []Param
  91. // Get gets the first value associated with the given name.
  92. // If there are no values associated with the key, Get returns "".
  93. func (ps Params) Get(name string) string {
  94. for _, p := range ps {
  95. if p.Name == name {
  96. return p.Value
  97. }
  98. }
  99. return ""
  100. }
  101. type doubleArray struct {
  102. bc []baseCheck
  103. node []*node
  104. }
  105. func newDoubleArray() *doubleArray {
  106. return &doubleArray{
  107. bc: []baseCheck{0},
  108. node: []*node{nil}, // A start index is adjusting to 1 because 0 will be used as a mark of non-existent node.
  109. }
  110. }
  111. // baseCheck contains BASE, CHECK and Extra flags.
  112. // From the top, 22bits of BASE, 2bits of Extra flags and 8bits of CHECK.
  113. //
  114. // BASE (22bit) | Extra flags (2bit) | CHECK (8bit)
  115. // |----------------------|--|--------|
  116. // 32 10 8 0
  117. type baseCheck uint32
  118. func (bc baseCheck) Base() int {
  119. return int(bc >> 10)
  120. }
  121. func (bc *baseCheck) SetBase(base int) {
  122. *bc |= baseCheck(base) << 10
  123. }
  124. func (bc baseCheck) Check() byte {
  125. return byte(bc)
  126. }
  127. func (bc *baseCheck) SetCheck(check byte) {
  128. *bc |= baseCheck(check)
  129. }
  130. func (bc baseCheck) IsEmpty() bool {
  131. return bc&0xfffffcff == 0
  132. }
  133. func (bc baseCheck) IsSingleParam() bool {
  134. return bc&paramTypeSingle == paramTypeSingle
  135. }
  136. func (bc baseCheck) IsWildcardParam() bool {
  137. return bc&paramTypeWildcard == paramTypeWildcard
  138. }
  139. func (bc baseCheck) IsAnyParam() bool {
  140. return bc&paramTypeAny != 0
  141. }
  142. func (bc *baseCheck) SetSingleParam() {
  143. *bc |= (1 << 8)
  144. }
  145. func (bc *baseCheck) SetWildcardParam() {
  146. *bc |= (1 << 9)
  147. }
  148. const (
  149. paramTypeSingle = 0x0100
  150. paramTypeWildcard = 0x0200
  151. paramTypeAny = 0x0300
  152. )
  153. func (da *doubleArray) lookup(path string, params []Param, idx int) (*node, []Param, bool) {
  154. indices := make([]uint64, 0, 1)
  155. for i := 0; i < len(path); i++ {
  156. if da.bc[idx].IsAnyParam() {
  157. indices = append(indices, (uint64(i)<<32)|(uint64(idx)&0xffffffff))
  158. }
  159. c := path[i]
  160. if idx = nextIndex(da.bc[idx].Base(), c); idx >= len(da.bc) || da.bc[idx].Check() != c {
  161. goto BACKTRACKING
  162. }
  163. }
  164. if next := nextIndex(da.bc[idx].Base(), TerminationCharacter); next < len(da.bc) && da.bc[next].Check() == TerminationCharacter {
  165. return da.node[da.bc[next].Base()], params, true
  166. }
  167. BACKTRACKING:
  168. for j := len(indices) - 1; j >= 0; j-- {
  169. i, idx := int(indices[j]>>32), int(indices[j]&0xffffffff)
  170. if da.bc[idx].IsSingleParam() {
  171. idx := nextIndex(da.bc[idx].Base(), ParamCharacter)
  172. if idx >= len(da.bc) {
  173. break
  174. }
  175. next := NextSeparator(path, i)
  176. params := append(params, Param{Value: path[i:next]})
  177. if nd, params, found := da.lookup(path[next:], params, idx); found {
  178. return nd, params, true
  179. }
  180. }
  181. if da.bc[idx].IsWildcardParam() {
  182. idx := nextIndex(da.bc[idx].Base(), WildcardCharacter)
  183. params := append(params, Param{Value: path[i:]})
  184. return da.node[da.bc[idx].Base()], params, true
  185. }
  186. }
  187. return nil, nil, false
  188. }
  189. // build builds double-array from records.
  190. func (da *doubleArray) build(srcs []*record, idx, depth int, usedBase map[int]struct{}) error {
  191. sort.Stable(recordSlice(srcs))
  192. base, siblings, leaf, err := da.arrange(srcs, idx, depth, usedBase)
  193. if err != nil {
  194. return err
  195. }
  196. if leaf != nil {
  197. nd, err := makeNode(leaf)
  198. if err != nil {
  199. return err
  200. }
  201. da.bc[idx].SetBase(len(da.node))
  202. da.node = append(da.node, nd)
  203. }
  204. for _, sib := range siblings {
  205. da.setCheck(nextIndex(base, sib.c), sib.c)
  206. }
  207. for _, sib := range siblings {
  208. records := srcs[sib.start:sib.end]
  209. switch sib.c {
  210. case ParamCharacter:
  211. for _, r := range records {
  212. next := NextSeparator(r.Key, depth+1)
  213. name := r.Key[depth+1 : next]
  214. r.paramNames = append(r.paramNames, name)
  215. r.Key = r.Key[next:]
  216. }
  217. da.bc[idx].SetSingleParam()
  218. if err := da.build(records, nextIndex(base, sib.c), 0, usedBase); err != nil {
  219. return err
  220. }
  221. case WildcardCharacter:
  222. r := records[0]
  223. name := r.Key[depth+1 : len(r.Key)-1]
  224. r.paramNames = append(r.paramNames, name)
  225. r.Key = ""
  226. da.bc[idx].SetWildcardParam()
  227. if err := da.build(records, nextIndex(base, sib.c), 0, usedBase); err != nil {
  228. return err
  229. }
  230. default:
  231. if err := da.build(records, nextIndex(base, sib.c), depth+1, usedBase); err != nil {
  232. return err
  233. }
  234. }
  235. }
  236. return nil
  237. }
  238. // setBase sets BASE.
  239. func (da *doubleArray) setBase(i, base int) {
  240. da.bc[i].SetBase(base)
  241. }
  242. // setCheck sets CHECK.
  243. func (da *doubleArray) setCheck(i int, check byte) {
  244. da.bc[i].SetCheck(check)
  245. }
  246. // findEmptyIndex returns an index of unused BASE/CHECK node.
  247. func (da *doubleArray) findEmptyIndex(start int) int {
  248. i := start
  249. for ; i < len(da.bc); i++ {
  250. if da.bc[i].IsEmpty() {
  251. break
  252. }
  253. }
  254. return i
  255. }
  256. // findBase returns good BASE.
  257. func (da *doubleArray) findBase(siblings []sibling, start int, usedBase map[int]struct{}) (base int) {
  258. for idx, firstChar := start+1, siblings[0].c; ; idx = da.findEmptyIndex(idx + 1) {
  259. base = nextIndex(idx, firstChar)
  260. if _, used := usedBase[base]; used {
  261. continue
  262. }
  263. i := 0
  264. for ; i < len(siblings); i++ {
  265. next := nextIndex(base, siblings[i].c)
  266. if len(da.bc) <= next {
  267. da.bc = append(da.bc, make([]baseCheck, next-len(da.bc)+1)...)
  268. }
  269. if !da.bc[next].IsEmpty() {
  270. break
  271. }
  272. }
  273. if i == len(siblings) {
  274. break
  275. }
  276. }
  277. usedBase[base] = struct{}{}
  278. return base
  279. }
  280. func (da *doubleArray) arrange(records []*record, idx, depth int, usedBase map[int]struct{}) (base int, siblings []sibling, leaf *record, err error) {
  281. siblings, leaf, err = makeSiblings(records, depth)
  282. if err != nil {
  283. return -1, nil, nil, err
  284. }
  285. if len(siblings) < 1 {
  286. return -1, nil, leaf, nil
  287. }
  288. base = da.findBase(siblings, idx, usedBase)
  289. if base > MaxSize {
  290. return -1, nil, nil, fmt.Errorf("denco: too many elements of internal slice")
  291. }
  292. da.setBase(idx, base)
  293. return base, siblings, leaf, err
  294. }
  295. // node represents a node of Double-Array.
  296. type node struct {
  297. data interface{}
  298. // Names of path parameters.
  299. paramNames []string
  300. }
  301. // makeNode returns a new node from record.
  302. func makeNode(r *record) (*node, error) {
  303. dups := make(map[string]bool)
  304. for _, name := range r.paramNames {
  305. if dups[name] {
  306. return nil, fmt.Errorf("denco: path parameter `%v' is duplicated in the key `%v'", name, r.Key)
  307. }
  308. dups[name] = true
  309. }
  310. return &node{data: r.Value, paramNames: r.paramNames}, nil
  311. }
  312. // sibling represents an intermediate data of build for Double-Array.
  313. type sibling struct {
  314. // An index of start of duplicated characters.
  315. start int
  316. // An index of end of duplicated characters.
  317. end int
  318. // A character of sibling.
  319. c byte
  320. }
  321. // nextIndex returns a next index of array of BASE/CHECK.
  322. func nextIndex(base int, c byte) int {
  323. return base ^ int(c)
  324. }
  325. // makeSiblings returns slice of sibling.
  326. func makeSiblings(records []*record, depth int) (sib []sibling, leaf *record, err error) {
  327. var (
  328. pc byte
  329. n int
  330. )
  331. for i, r := range records {
  332. if len(r.Key) <= depth {
  333. leaf = r
  334. continue
  335. }
  336. c := r.Key[depth]
  337. switch {
  338. case pc < c:
  339. sib = append(sib, sibling{start: i, c: c})
  340. case pc == c:
  341. continue
  342. default:
  343. return nil, nil, fmt.Errorf("denco: BUG: routing table hasn't been sorted")
  344. }
  345. if n > 0 {
  346. sib[n-1].end = i
  347. }
  348. pc = c
  349. n++
  350. }
  351. if n == 0 {
  352. return nil, leaf, nil
  353. }
  354. sib[n-1].end = len(records)
  355. return sib, leaf, nil
  356. }
  357. // Record represents a record data for router construction.
  358. type Record struct {
  359. // Key for router construction.
  360. Key string
  361. // Result value for Key.
  362. Value interface{}
  363. }
  364. // NewRecord returns a new Record.
  365. func NewRecord(key string, value interface{}) Record {
  366. return Record{
  367. Key: key,
  368. Value: value,
  369. }
  370. }
  371. // record represents a record that use to build the Double-Array.
  372. type record struct {
  373. Record
  374. paramNames []string
  375. }
  376. // makeRecords returns the records that use to build Double-Arrays.
  377. func makeRecords(srcs []Record) (statics, params []*record) {
  378. termChar := string(TerminationCharacter)
  379. paramPrefix := string(SeparatorCharacter) + string(ParamCharacter)
  380. wildcardPrefix := string(SeparatorCharacter) + string(WildcardCharacter)
  381. for _, r := range srcs {
  382. if strings.Contains(r.Key, paramPrefix) || strings.Contains(r.Key, wildcardPrefix) {
  383. r.Key += termChar
  384. params = append(params, &record{Record: r})
  385. } else {
  386. statics = append(statics, &record{Record: r})
  387. }
  388. }
  389. return statics, params
  390. }
  391. // recordSlice represents a slice of Record for sort and implements the sort.Interface.
  392. type recordSlice []*record
  393. // Len implements the sort.Interface.Len.
  394. func (rs recordSlice) Len() int {
  395. return len(rs)
  396. }
  397. // Less implements the sort.Interface.Less.
  398. func (rs recordSlice) Less(i, j int) bool {
  399. return rs[i].Key < rs[j].Key
  400. }
  401. // Swap implements the sort.Interface.Swap.
  402. func (rs recordSlice) Swap(i, j int) {
  403. rs[i], rs[j] = rs[j], rs[i]
  404. }