github.com/kayoticsully/syncthing@v0.8.9-0.20140724133906-c45a2fdc03f8/xdr/reader.go (about)

     1  // Copyright (C) 2014 Jakob Borg and Contributors (see the CONTRIBUTORS file).
     2  // All rights reserved. Use of this source code is governed by an MIT-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package xdr
     6  
     7  import (
     8  	"errors"
     9  	"io"
    10  	"time"
    11  )
    12  
    13  var ErrElementSizeExceeded = errors.New("element size exceeded")
    14  
    15  type Reader struct {
    16  	r    io.Reader
    17  	tot  int
    18  	err  error
    19  	b    [8]byte
    20  	sb   []byte
    21  	last time.Time
    22  }
    23  
    24  func NewReader(r io.Reader) *Reader {
    25  	return &Reader{
    26  		r: r,
    27  	}
    28  }
    29  
    30  func (r *Reader) ReadString() string {
    31  	if r.sb == nil {
    32  		r.sb = make([]byte, 64)
    33  	} else {
    34  		r.sb = r.sb[:cap(r.sb)]
    35  	}
    36  	r.sb = r.ReadBytesInto(r.sb)
    37  	return string(r.sb)
    38  }
    39  
    40  func (r *Reader) ReadStringMax(max int) string {
    41  	if r.sb == nil {
    42  		r.sb = make([]byte, 64)
    43  	} else {
    44  		r.sb = r.sb[:cap(r.sb)]
    45  	}
    46  	r.sb = r.ReadBytesMaxInto(max, r.sb)
    47  	return string(r.sb)
    48  }
    49  
    50  func (r *Reader) ReadBytes() []byte {
    51  	return r.ReadBytesInto(nil)
    52  }
    53  
    54  func (r *Reader) ReadBytesMax(max int) []byte {
    55  	return r.ReadBytesMaxInto(max, nil)
    56  }
    57  
    58  func (r *Reader) ReadBytesInto(dst []byte) []byte {
    59  	return r.ReadBytesMaxInto(0, dst)
    60  }
    61  
    62  func (r *Reader) ReadBytesMaxInto(max int, dst []byte) []byte {
    63  	if r.err != nil {
    64  		return nil
    65  	}
    66  	r.last = time.Now()
    67  	s := r.tot
    68  
    69  	l := int(r.ReadUint32())
    70  	if r.err != nil {
    71  		return nil
    72  	}
    73  	if max > 0 && l > max {
    74  		r.err = ErrElementSizeExceeded
    75  		return nil
    76  	}
    77  
    78  	if l+pad(l) > len(dst) {
    79  		dst = make([]byte, l+pad(l))
    80  	} else {
    81  		dst = dst[:l+pad(l)]
    82  	}
    83  
    84  	var n int
    85  	n, r.err = io.ReadFull(r.r, dst)
    86  	if r.err != nil {
    87  		if debug {
    88  			dl.Debugf("@0x%x: rd bytes (%d): %v", s, len(dst), r.err)
    89  		}
    90  		return nil
    91  	}
    92  	r.tot += n
    93  
    94  	if debug {
    95  		if n > maxDebugBytes {
    96  			dl.Debugf("@0x%x: rd bytes (%d): %x...", s, len(dst), dst[:maxDebugBytes])
    97  		} else {
    98  			dl.Debugf("@0x%x: rd bytes (%d): %x", s, len(dst), dst)
    99  		}
   100  	}
   101  	return dst[:l]
   102  }
   103  
   104  func (r *Reader) ReadBool() bool {
   105  	return r.ReadUint32() != 0
   106  }
   107  
   108  func (r *Reader) ReadUint16() uint16 {
   109  	return uint16(r.ReadUint32())
   110  }
   111  
   112  func (r *Reader) ReadUint32() uint32 {
   113  	if r.err != nil {
   114  		return 0
   115  	}
   116  	r.last = time.Now()
   117  	s := r.tot
   118  
   119  	var n int
   120  	n, r.err = io.ReadFull(r.r, r.b[:4])
   121  	r.tot += n
   122  	if r.err != nil {
   123  		if debug {
   124  			dl.Debugf("@0x%x: rd uint32: %v", r.tot, r.err)
   125  		}
   126  		return 0
   127  	}
   128  
   129  	v := uint32(r.b[3]) | uint32(r.b[2])<<8 | uint32(r.b[1])<<16 | uint32(r.b[0])<<24
   130  
   131  	if debug {
   132  		dl.Debugf("@0x%x: rd uint32=%d (0x%08x)", s, v, v)
   133  	}
   134  	return v
   135  }
   136  
   137  func (r *Reader) ReadUint64() uint64 {
   138  	if r.err != nil {
   139  		return 0
   140  	}
   141  	r.last = time.Now()
   142  	s := r.tot
   143  
   144  	var n int
   145  	n, r.err = io.ReadFull(r.r, r.b[:8])
   146  	r.tot += n
   147  	if r.err != nil {
   148  		if debug {
   149  			dl.Debugf("@0x%x: rd uint64: %v", r.tot, r.err)
   150  		}
   151  		return 0
   152  	}
   153  
   154  	v := uint64(r.b[7]) | uint64(r.b[6])<<8 | uint64(r.b[5])<<16 | uint64(r.b[4])<<24 |
   155  		uint64(r.b[3])<<32 | uint64(r.b[2])<<40 | uint64(r.b[1])<<48 | uint64(r.b[0])<<56
   156  
   157  	if debug {
   158  		dl.Debugf("@0x%x: rd uint64=%d (0x%016x)", s, v, v)
   159  	}
   160  	return v
   161  }
   162  
   163  func (r *Reader) Tot() int {
   164  	return r.tot
   165  }
   166  
   167  func (r *Reader) Error() error {
   168  	return r.err
   169  }
   170  
   171  func (r *Reader) LastRead() time.Time {
   172  	return r.last
   173  }