ranger.go 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. package jet
  2. import (
  3. "fmt"
  4. "reflect"
  5. "sync"
  6. )
  7. // Ranger describes an interface for types that iterate over something.
  8. // Implementing this interface means the ranger will be used when it's
  9. // encountered on the right hand side of a range's "let" expression.
  10. type Ranger interface {
  11. Range() (reflect.Value, reflect.Value, bool)
  12. ProvidesIndex() bool
  13. }
  14. type intsRanger struct {
  15. i, from, to int
  16. }
  17. var _ Ranger = &intsRanger{}
  18. func (r *intsRanger) Range() (index, value reflect.Value, end bool) {
  19. index = reflect.ValueOf(r.i)
  20. value = reflect.ValueOf(r.from + r.i)
  21. end = r.i == r.to-r.from
  22. r.i++
  23. return
  24. }
  25. func (r *intsRanger) ProvidesIndex() bool { return true }
  26. type pooledRanger interface {
  27. Ranger
  28. Setup(reflect.Value)
  29. }
  30. type sliceRanger struct {
  31. v reflect.Value
  32. i int
  33. }
  34. var _ Ranger = &sliceRanger{}
  35. var _ pooledRanger = &sliceRanger{}
  36. func (r *sliceRanger) Setup(v reflect.Value) {
  37. r.i = 0
  38. r.v = v
  39. }
  40. func (r *sliceRanger) Range() (index, value reflect.Value, end bool) {
  41. if r.i == r.v.Len() {
  42. end = true
  43. return
  44. }
  45. index = reflect.ValueOf(r.i)
  46. value = r.v.Index(r.i)
  47. r.i++
  48. return
  49. }
  50. func (r *sliceRanger) ProvidesIndex() bool { return true }
  51. type mapRanger struct {
  52. iter *reflect.MapIter
  53. hasMore bool
  54. }
  55. var _ Ranger = &mapRanger{}
  56. var _ pooledRanger = &mapRanger{}
  57. func (r *mapRanger) Setup(v reflect.Value) {
  58. r.iter = v.MapRange()
  59. r.hasMore = r.iter.Next()
  60. }
  61. func (r *mapRanger) Range() (key, value reflect.Value, end bool) {
  62. if !r.hasMore {
  63. end = true
  64. return
  65. }
  66. key, value = r.iter.Key(), r.iter.Value()
  67. r.hasMore = r.iter.Next()
  68. return
  69. }
  70. func (r *mapRanger) ProvidesIndex() bool { return true }
  71. type chanRanger struct {
  72. v reflect.Value
  73. }
  74. var _ Ranger = &chanRanger{}
  75. var _ pooledRanger = &chanRanger{}
  76. func (r *chanRanger) Setup(v reflect.Value) {
  77. r.v = v
  78. }
  79. func (r *chanRanger) Range() (_, value reflect.Value, end bool) {
  80. v, ok := r.v.Recv()
  81. value, end = v, !ok
  82. return
  83. }
  84. func (r *chanRanger) ProvidesIndex() bool { return false }
  85. // ranger pooling
  86. var (
  87. poolSliceRanger = &sync.Pool{
  88. New: func() interface{} {
  89. return new(sliceRanger)
  90. },
  91. }
  92. poolsByKind = map[reflect.Kind]*sync.Pool{
  93. reflect.Slice: poolSliceRanger,
  94. reflect.Array: poolSliceRanger,
  95. reflect.Map: &sync.Pool{
  96. New: func() interface{} {
  97. return new(mapRanger)
  98. },
  99. },
  100. reflect.Chan: &sync.Pool{
  101. New: func() interface{} {
  102. return new(chanRanger)
  103. },
  104. },
  105. }
  106. )
  107. func getRanger(v reflect.Value) (r Ranger, cleanup func()) {
  108. t := v.Type()
  109. if t.Implements(rangerType) {
  110. return v.Interface().(Ranger), func() { /* no cleanup needed */ }
  111. }
  112. v, isNil := indirect(v)
  113. if isNil {
  114. panic(fmt.Errorf("cannot range over nil pointer/interface (%s)", t))
  115. }
  116. pool, ok := poolsByKind[v.Kind()]
  117. if !ok {
  118. panic(fmt.Errorf("value %v (type %s) is not rangeable", v, t))
  119. }
  120. pr := pool.Get().(pooledRanger)
  121. pr.Setup(v)
  122. return pr, func() { pool.Put(pr) }
  123. }