github.com/kayoticsully/syncthing@v0.8.9-0.20140724133906-c45a2fdc03f8/xdr/writer.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  	"io"
     9  	"time"
    10  )
    11  
    12  func pad(l int) int {
    13  	d := l % 4
    14  	if d == 0 {
    15  		return 0
    16  	}
    17  	return 4 - d
    18  }
    19  
    20  var padBytes = []byte{0, 0, 0}
    21  
    22  type Writer struct {
    23  	w    io.Writer
    24  	tot  int
    25  	err  error
    26  	b    [8]byte
    27  	last time.Time
    28  }
    29  
    30  type AppendWriter []byte
    31  
    32  func (w *AppendWriter) Write(bs []byte) (int, error) {
    33  	*w = append(*w, bs...)
    34  	return len(bs), nil
    35  }
    36  
    37  func NewWriter(w io.Writer) *Writer {
    38  	return &Writer{
    39  		w: w,
    40  	}
    41  }
    42  
    43  func (w *Writer) WriteString(s string) (int, error) {
    44  	return w.WriteBytes([]byte(s))
    45  }
    46  
    47  func (w *Writer) WriteBytes(bs []byte) (int, error) {
    48  	if w.err != nil {
    49  		return 0, w.err
    50  	}
    51  
    52  	w.last = time.Now()
    53  	w.WriteUint32(uint32(len(bs)))
    54  	if w.err != nil {
    55  		return 0, w.err
    56  	}
    57  
    58  	if debug {
    59  		if len(bs) > maxDebugBytes {
    60  			dl.Debugf("wr bytes (%d): %x...", len(bs), bs[:maxDebugBytes])
    61  		} else {
    62  			dl.Debugf("wr bytes (%d): %x", len(bs), bs)
    63  		}
    64  	}
    65  
    66  	var l, n int
    67  	n, w.err = w.w.Write(bs)
    68  	l += n
    69  
    70  	if p := pad(len(bs)); w.err == nil && p > 0 {
    71  		n, w.err = w.w.Write(padBytes[:p])
    72  		l += n
    73  	}
    74  
    75  	w.tot += l
    76  	return l, w.err
    77  }
    78  
    79  func (w *Writer) WriteBool(v bool) (int, error) {
    80  	if v {
    81  		return w.WriteUint32(1)
    82  	} else {
    83  		return w.WriteUint32(0)
    84  	}
    85  }
    86  
    87  func (w *Writer) WriteUint16(v uint16) (int, error) {
    88  	return w.WriteUint32(uint32(v))
    89  }
    90  
    91  func (w *Writer) WriteUint32(v uint32) (int, error) {
    92  	if w.err != nil {
    93  		return 0, w.err
    94  	}
    95  
    96  	w.last = time.Now()
    97  	if debug {
    98  		dl.Debugf("wr uint32=%d", v)
    99  	}
   100  
   101  	w.b[0] = byte(v >> 24)
   102  	w.b[1] = byte(v >> 16)
   103  	w.b[2] = byte(v >> 8)
   104  	w.b[3] = byte(v)
   105  
   106  	var l int
   107  	l, w.err = w.w.Write(w.b[:4])
   108  	w.tot += l
   109  	return l, w.err
   110  }
   111  
   112  func (w *Writer) WriteUint64(v uint64) (int, error) {
   113  	if w.err != nil {
   114  		return 0, w.err
   115  	}
   116  
   117  	w.last = time.Now()
   118  	if debug {
   119  		dl.Debugf("wr uint64=%d", v)
   120  	}
   121  
   122  	w.b[0] = byte(v >> 56)
   123  	w.b[1] = byte(v >> 48)
   124  	w.b[2] = byte(v >> 40)
   125  	w.b[3] = byte(v >> 32)
   126  	w.b[4] = byte(v >> 24)
   127  	w.b[5] = byte(v >> 16)
   128  	w.b[6] = byte(v >> 8)
   129  	w.b[7] = byte(v)
   130  
   131  	var l int
   132  	l, w.err = w.w.Write(w.b[:8])
   133  	w.tot += l
   134  	return l, w.err
   135  }
   136  
   137  func (w *Writer) Tot() int {
   138  	return w.tot
   139  }
   140  
   141  func (w *Writer) Error() error {
   142  	return w.err
   143  }
   144  
   145  func (w *Writer) LastWrite() time.Time {
   146  	return w.last
   147  }