github.com/kontera-technologies/go-supervisor/v2@v2.1.0/parsers.go (about)

     1  package supervisor
     2  
     3  import (
     4  	"bufio"
     5  	"bytes"
     6  	"encoding/json"
     7  	"io"
     8  	"io/ioutil"
     9  	"strings"
    10  )
    11  
    12  // MakeJsonLineParser is called with an io.Reader, and returns a function, that when called will output references to
    13  // map[string]interface{} objects that contain the parsed json data.
    14  // If an invalid json is encountered, all the characters up until a new-line will be dropped.
    15  func MakeJsonLineParser(fromR io.Reader, bufferSize int) ProduceFn {
    16  	br := bufio.NewReaderSize(fromR, bufferSize)
    17  	dec := json.NewDecoder(br)
    18  	return func() (*interface{}, error) {
    19  		var v interface{}
    20  		if err := dec.Decode(&v); err == nil {
    21  			return &v, nil
    22  		} else if err == io.EOF {
    23  			return nil, err
    24  		}
    25  
    26  		rest, _ := ioutil.ReadAll(dec.Buffered())
    27  		restLines := bytes.SplitAfterN(rest, []byte{'\n'}, 2)
    28  		if len(restLines) > 1 {
    29  			// todo: test memory consumption on many mistakes (which will happen)
    30  			dec = json.NewDecoder(io.MultiReader(bytes.NewReader(restLines[1]), br))
    31  		} else {
    32  			dec = json.NewDecoder(br)
    33  		}
    34  		return nil, nil
    35  	}
    36  }
    37  
    38  // MakeLineParser is called with an io.Reader, and returns a function, that when called will output references to
    39  // strings that contain the bytes read from the io.Reader (without the new-line suffix).
    40  func MakeLineParser(fromR io.Reader, bufferSize int) ProduceFn {
    41  	br := bufio.NewReaderSize(fromR, bufferSize)
    42  	return func() (*interface{}, error) {
    43  		str, err := br.ReadString('\n')
    44  		if err == nil {
    45  			res := (interface{})(strings.TrimSuffix(str, string('\n')))
    46  			return &res, nil
    47  		}
    48  		return nil, err
    49  	}
    50  }
    51  
    52  // MakeBytesParser is called with an io.Reader, and returns a function, that when called will output references to
    53  // byte slices that contain the bytes read from the io.Reader.
    54  func MakeBytesParser(fromR io.Reader, bufferSize int) ProduceFn {
    55  	br := bufio.NewReaderSize(fromR, bufferSize)
    56  	return func() (*interface{}, error) {
    57  		v, err := br.ReadBytes('\n')
    58  		if err == nil {
    59  			res := (interface{})(bytes.TrimSuffix(v, []byte{'\n'}))
    60  			return &res, nil
    61  		}
    62  		return nil, err
    63  	}
    64  }