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 }