go-hep.org/x/hep@v0.38.1/rio/reader.go (about)

     1  // Copyright ©2015 The go-hep Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package rio
     6  
     7  import (
     8  	"bufio"
     9  	"fmt"
    10  	"io"
    11  
    12  	riobin "codeberg.org/gonuts/binary"
    13  )
    14  
    15  // Reader is a rio read-only stream
    16  type Reader struct {
    17  	r io.Reader
    18  
    19  	options Options
    20  	version Version
    21  
    22  	recs map[string]*Record // map of all connected records
    23  }
    24  
    25  type bufioReader struct {
    26  	*bufio.Reader
    27  }
    28  
    29  func (r *bufioReader) Read(p []byte) (int, error) {
    30  	n, err := r.Reader.Read(p)
    31  	if n < len(p) && err == nil {
    32  		// retry. buffer was perhaps depleted.
    33  		var nn int
    34  		nn, err = r.Reader.Read(p[n:])
    35  		if nn > 0 {
    36  			n += nn
    37  		}
    38  	}
    39  	return n, err
    40  }
    41  
    42  // NewReader returns a new read-only rio stream
    43  func NewReader(r io.Reader) (*Reader, error) {
    44  	// a rio stream starts with rio magic
    45  	hdr := [4]byte{}
    46  	_, err := r.Read(hdr[:])
    47  	if err != nil {
    48  		return nil, fmt.Errorf("rio: error reading magic-header: %w", err)
    49  	}
    50  	if hdr != rioMagic {
    51  		return nil, fmt.Errorf("rio: not a rio-stream. magic-header=%q. want=%q",
    52  			string(hdr[:]),
    53  			string(rioMagic[:]),
    54  		)
    55  	}
    56  	return newReader(r)
    57  }
    58  
    59  // newReader returns a new read-only rio stream
    60  func newReader(r io.Reader) (*Reader, error) {
    61  	//r = bufio.NewReaderSize(r, 10*1024*1024)
    62  	//r = bufio.NewReader(r)
    63  	r = &bufioReader{bufio.NewReader(r)}
    64  	return &Reader{
    65  		r:       r,
    66  		options: 0,
    67  		version: rioHdrVersion,
    68  		recs:    make(map[string]*Record),
    69  	}, nil
    70  }
    71  
    72  // Record adds a Record to the list of records to read or
    73  // returns the Record with that name.
    74  func (r *Reader) Record(name string) *Record {
    75  	rec, ok := r.recs[name]
    76  	if !ok {
    77  		rec = newRecord(name, r.options)
    78  		rec.r = r
    79  		rec.unpack = true
    80  		r.recs[name] = rec
    81  	}
    82  	return rec
    83  }
    84  
    85  // Records returns the list of connected Records
    86  func (r *Reader) Records() []*Record {
    87  	recs := make([]*Record, 0, len(r.recs))
    88  	for _, rec := range r.recs {
    89  		recs = append(recs, rec)
    90  	}
    91  	return recs
    92  }
    93  
    94  // Close finishes reading the rio read-only stream.
    95  // It does not (and can not) close the underlying reader.
    96  func (r *Reader) Close() error {
    97  	var err error
    98  	return err
    99  }
   100  
   101  // decoder manages the decoding of data values from rioRecords
   102  type decoder struct {
   103  	r io.Reader
   104  }
   105  
   106  func (dec *decoder) Decode(v any) error {
   107  	switch v := v.(type) {
   108  	case Unmarshaler:
   109  		return v.RioUnmarshal(dec.r)
   110  	}
   111  
   112  	d := riobin.NewDecoder(dec.r)
   113  	d.Order = Endian
   114  	return d.Decode(v)
   115  }