usb-ks

USB Killswitch
git clone git://git.laack.co/usb-ks.git
Log | Files | Refs | README | LICENSE

iterator.go (3801B)


      1 package iter
      2 
      3 import "errors"
      4 
      5 // Error returned from Iterator.Next() when iteration is done.
      6 var FINISHED = errors.New("FINISHED")
      7 
      8 // Iterator letting you specify just two functions defining iteration. All
      9 // helper functions utilize this.
     10 //
     11 // Iterator is designed to avoid common pitfalls and to allow common Go patterns:
     12 // - errors can be yielded all the way up the chain to the caller
     13 // - safe iteration in background channels
     14 // - iterators are nil-clean (you can send nil values through the iterator)
     15 // - allows for cleanup when iteration ends early
     16 type Iterator struct {
     17 	// Get the next value (or error).
     18 	// nil, iter.FINISHED indicates iteration is complete.
     19 	Next func() (interface{}, error)
     20 	// Close out resources in case iteration terminates early. Callers are *not*
     21 	// required to call this if iteration completes cleanly (but they may).
     22 	Close func()
     23 }
     24 
     25 // Use to create an iterator from a single closure.  retun nil to stop iteration.
     26 //
     27 //   iter.NewSimple(func() interface{} { return x*2 })
     28 func NewSimple(f func() interface{}) Iterator {
     29 	return Iterator{
     30 		Next: func() (interface{}, error) {
     31 			val := f()
     32 			if val == nil {
     33 				return nil, FINISHED
     34 			} else {
     35 				return f, nil
     36 			}
     37 		},
     38 		Close: func() {},
     39 	}
     40 }
     41 
     42 // Transform values in the input.
     43 //   iterator.Map(func(item interface{}) interface{} { item.(int) * 2 })
     44 func (iterator Iterator) Map(mapper func(interface{}) interface{}) Iterator {
     45 	return Iterator{
     46 		Next: func() (interface{}, error) {
     47 			item, err := iterator.Next()
     48 			if err != nil {
     49 				return nil, err
     50 			}
     51 			return mapper(item), nil
     52 		},
     53 		Close: func() { iterator.Close() },
     54 	}
     55 }
     56 
     57 // Filter values from the input.
     58 //   iterator.Select(func(item interface{}) bool { item.(int) > 10 })
     59 func (iterator Iterator) Select(selector func(interface{}) bool) Iterator {
     60 	return Iterator{
     61 		Next: func() (interface{}, error) {
     62 			for {
     63 				item, err := iterator.Next()
     64 				if err != nil {
     65 					return nil, err
     66 				}
     67 				if selector(item) {
     68 					return item, nil
     69 				}
     70 			}
     71 		},
     72 		Close: func() { iterator.Close() },
     73 	}
     74 }
     75 
     76 // Concatenate multiple iterators together in one.
     77 //   d := iter.Concat(a, b, c)
     78 func Concat(iterators ...Iterator) Iterator {
     79 	i := 0
     80 	return Iterator{
     81 		Next: func() (interface{}, error) {
     82 			if i >= len(iterators) {
     83 				return nil, FINISHED
     84 			}
     85 			item, err := iterators[i].Next()
     86 			if err == FINISHED {
     87 				i++
     88 				return nil, err
     89 			} else if err != nil {
     90 				i = len(iterators)
     91 				return nil, err
     92 			}
     93 			return item, nil
     94 		},
     95 		Close: func() {
     96 			// Close out remaining iterators
     97 			for ; i < len(iterators); i++ {
     98 				iterators[i].Close()
     99 			}
    100 		},
    101 	}
    102 }
    103 
    104 // Iterate over all values, calling a user-defined function for each one.
    105 //   iterator.Each(func(item interface{}) { fmt.Println(item) })
    106 func (iterator Iterator) Each(processor func(interface{})) error {
    107 	defer iterator.Close()
    108 	item, err := iterator.Next()
    109 	for err == nil {
    110 		processor(item)
    111 		item, err = iterator.Next()
    112 	}
    113 	return err
    114 }
    115 
    116 // Iterate over all values, calling a user-defined function for each one.
    117 // If an error is returned from the function, iteration terminates early
    118 // and the EachWithError function returns the error.
    119 //   iterator.EachWithError(func(item interface{}) error { return http.Get(item.(string)) })
    120 func (iterator Iterator) EachWithError(processor func(interface{}) error) error {
    121 	defer iterator.Close()
    122 	item, err := iterator.Next()
    123 	for err == nil {
    124 		err = processor(item)
    125 		if err == nil {
    126 			item, err = iterator.Next()
    127 		}
    128 	}
    129 	return err
    130 }
    131 
    132 // Convert the iteration directly to a slice.
    133 //   var list []interface{}
    134 //   list, err := iterator.ToSlice()
    135 func (iterator Iterator) ToSlice() (list []interface{}, err error) {
    136 	err = iterator.Each(func(item interface{}) {
    137 		list = append(list, item)
    138 	})
    139 	return list, err
    140 }