bitbucket.org/ai69/amoy@v0.2.3/channel.go (about)

     1  package amoy
     2  
     3  import "errors"
     4  
     5  // BlockForever blocks current goroutine forever.
     6  func BlockForever() {
     7  	<-make(chan struct{})
     8  }
     9  
    10  // AccumulatedChannel returns a channel that accumulates values from given channel.
    11  func AccumulatedChannel(inCh <-chan []byte, size int) <-chan []byte {
    12  	if size <= 0 {
    13  		panic(errors.New("invalid slice size"))
    14  	}
    15  
    16  	outCh := make(chan []byte, 1024)
    17  	go func(in <-chan []byte, out chan []byte) {
    18  		// close output channel on exit
    19  		defer close(out)
    20  
    21  		var (
    22  			buffer = make([]byte, size, size)
    23  			pos    = 0
    24  		)
    25  		for {
    26  			select {
    27  			case data, ok := <-in:
    28  				// once the input channel is closed, we should dump left and exit
    29  				if !ok {
    30  					if pos > 0 {
    31  						out <- buffer[:pos]
    32  					}
    33  					return
    34  				}
    35  
    36  				for dataSize := len(data); dataSize > 0; dataSize = len(data) {
    37  					// calculate rest space in buffer
    38  					remainSize := size - pos
    39  
    40  					// if data is not bigger than rest, append to buffer
    41  					if dataSize <= remainSize {
    42  						copy(buffer[pos:pos+dataSize], data)
    43  						data = nil
    44  						pos += dataSize
    45  					} else {
    46  						// if data is bigger than rest, append first part to buffer, and keep the rest in data
    47  						copy(buffer[pos:size], data[:remainSize])
    48  						data = data[remainSize:]
    49  						pos += remainSize
    50  					}
    51  
    52  					// if buffer is full, send to output channel, and reset buffer
    53  					if pos == size {
    54  						out <- buffer
    55  						buffer = make([]byte, size, size)
    56  						pos = 0
    57  					}
    58  				}
    59  			}
    60  		}
    61  	}(inCh, outCh)
    62  	return outCh
    63  }