github.com/viant/toolbox@v0.34.5/iterator.go (about) 1 package toolbox 2 3 import ( 4 "reflect" 5 "time" 6 ) 7 8 //Iterator represents generic iterator. 9 type Iterator interface { 10 //HasNext returns true if iterator has next element. 11 HasNext() bool 12 13 //Next sets item pointer with next element. 14 Next(itemPointer interface{}) error 15 } 16 17 type sliceIterator struct { 18 sliceValue reflect.Value 19 index int 20 } 21 22 func (i *sliceIterator) HasNext() bool { 23 return i.index < i.sliceValue.Len() 24 } 25 26 func (i *sliceIterator) Next(itemPointer interface{}) error { 27 value := i.sliceValue.Index(i.index) 28 i.index++ 29 itemPointerValue := reflect.ValueOf(itemPointer) 30 itemPointerValue.Elem().Set(value) 31 return nil 32 } 33 34 type stringSliceIterator struct { 35 sliceValue []string 36 index int 37 } 38 39 func (i *stringSliceIterator) HasNext() bool { 40 return i.index < len(i.sliceValue) 41 } 42 43 func (i *stringSliceIterator) Next(itemPointer interface{}) error { 44 value := i.sliceValue[i.index] 45 i.index++ 46 if stringPointer, ok := itemPointer.(*string); ok { 47 *stringPointer = value 48 return nil 49 } 50 interfacePointer := itemPointer.(*interface{}) 51 *interfacePointer = value 52 return nil 53 } 54 55 type interfaceSliceIterator struct { 56 sliceValue []interface{} 57 index int 58 } 59 60 func (i *interfaceSliceIterator) HasNext() bool { 61 return i.index < len(i.sliceValue) 62 } 63 64 func (i *interfaceSliceIterator) Next(itemPointer interface{}) error { 65 value := i.sliceValue[i.index] 66 i.index++ 67 68 switch actual := itemPointer.(type) { 69 case *interface{}: 70 *actual = value 71 return nil 72 case *string: 73 *actual = AsString(value) 74 return nil 75 case *int: 76 *actual = AsInt(value) 77 return nil 78 case *int64: 79 *actual = int64(AsInt(value)) 80 return nil 81 case *time.Time: 82 var timestamp = AsTime(value, DefaultDateLayout) 83 if timestamp != nil { 84 *actual = *timestamp 85 } 86 return nil 87 88 } 89 itemPointerValue := reflect.ValueOf(itemPointer) 90 if value != nil { 91 itemPointerValue.Elem().Set(reflect.ValueOf(value)) 92 } else { 93 itemPointerValue.Elem().Set(reflect.Zero(reflect.TypeOf(itemPointer).Elem())) 94 95 } 96 return nil 97 } 98 99 //NewSliceIterator creates a new slice iterator. 100 func NewSliceIterator(slice interface{}) Iterator { 101 if aSlice, ok := slice.([]interface{}); ok { 102 return &interfaceSliceIterator{aSlice, 0} 103 } 104 if aSlice, ok := slice.([]string); ok { 105 return &stringSliceIterator{aSlice, 0} 106 } 107 sliceValue := DiscoverValueByKind(reflect.ValueOf(slice), reflect.Slice) 108 return &sliceIterator{sliceValue: sliceValue} 109 }