github.com/lmorg/murex@v0.0.0-20240217211045-e081c89cd4ef/builtins/pipes/streams/read.go (about)

     1  package streams
     2  
     3  import (
     4  	"bufio"
     5  	"context"
     6  	"fmt"
     7  	"io"
     8  
     9  	"github.com/lmorg/murex/config"
    10  	"github.com/lmorg/murex/lang/stdio"
    11  	"github.com/lmorg/murex/utils"
    12  )
    13  
    14  // Read is the standard Reader interface Read() method.
    15  func (stdin *Stdin) Read(p []byte) (i int, err error) {
    16  	for {
    17  		select {
    18  		case <-stdin.ctx.Done():
    19  			return 0, io.EOF
    20  		default:
    21  		}
    22  
    23  		stdin.mutex.Lock()
    24  		l := len(stdin.buffer)
    25  		deps := stdin.dependents
    26  
    27  		stdin.mutex.Unlock()
    28  
    29  		if l == 0 {
    30  			if deps < 1 {
    31  				return 0, io.EOF
    32  			}
    33  			//time.Sleep(3 * time.Millisecond)
    34  			continue
    35  		}
    36  
    37  		break
    38  	}
    39  
    40  	stdin.mutex.Lock()
    41  
    42  	if len(p) >= len(stdin.buffer) {
    43  		i = len(stdin.buffer)
    44  		copy(p, stdin.buffer)
    45  
    46  		stdin.buffer = make([]byte, 0)
    47  
    48  	} else {
    49  		i = len(p)
    50  		copy(p, stdin.buffer[:i])
    51  
    52  		stdin.buffer = stdin.buffer[i:]
    53  	}
    54  
    55  	stdin.bRead += uint64(i)
    56  	stdin.mutex.Unlock()
    57  
    58  	return i, err
    59  }
    60  
    61  // ReadLine returns each line in the stream as a callback function
    62  func (stdin *Stdin) ReadLine(callback func([]byte)) error {
    63  	scanner := bufio.NewScanner(stdin)
    64  	for scanner.Scan() {
    65  		b := scanner.Bytes()
    66  
    67  		callback(append(b, utils.NewLineByte...))
    68  	}
    69  
    70  	err := scanner.Err()
    71  	if err != nil {
    72  		return fmt.Errorf("error in stdin.ReadLine: %s", err.Error())
    73  	}
    74  	return nil
    75  }
    76  
    77  // ReadAll reads everything and dump it into one byte slice.
    78  func (stdin *Stdin) ReadAll() ([]byte, error) {
    79  	stdin.mutex.Lock()
    80  	stdin.max = 0
    81  	stdin.mutex.Unlock()
    82  
    83  	for {
    84  		select {
    85  		case <-stdin.ctx.Done():
    86  			goto read
    87  		default:
    88  		}
    89  
    90  		stdin.mutex.Lock()
    91  		closed := stdin.dependents < 1
    92  
    93  		stdin.mutex.Unlock() 
    94  
    95  		if closed {
    96  			break
    97  		}
    98  	}
    99  
   100  read:
   101  	stdin.mutex.Lock()
   102  	stdin.bRead = uint64(len(stdin.buffer))
   103  	b := stdin.buffer
   104  	stdin.mutex.Unlock()
   105  	return b, nil
   106  }
   107  
   108  // ReadArray returns a data type-specific array returned via a callback function
   109  func (stdin *Stdin) ReadArray(ctx context.Context, callback func([]byte)) error {
   110  	return stdio.ReadArray(ctx, stdin, callback)
   111  }
   112  
   113  // ReadArrayWithType returns an array like "ReadArray" plus data type via a callback function
   114  func (stdin *Stdin) ReadArrayWithType(ctx context.Context, callback func(interface{}, string)) error {
   115  	return stdio.ReadArrayWithType(ctx, stdin, callback)
   116  }
   117  
   118  // ReadMap returns a data type-specific key/values returned via a callback function
   119  func (stdin *Stdin) ReadMap(config *config.Config, callback func(*stdio.Map)) error {
   120  	return stdio.ReadMap(stdin, config, callback)
   121  }
   122  
   123  // WriteTo reads from the stream.Io interface and writes to a destination
   124  // io.Writer interface
   125  func (stdin *Stdin) WriteTo(w io.Writer) (int64, error) {
   126  	return stdio.WriteTo(stdin, w)
   127  }