github.com/alejandroesc/spdy@v0.0.0-20200317064415-01a02f0eb389/common/utils.go (about) 1 // Copyright 2014 Jamie Hall. 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 common 6 7 import ( 8 "io" 9 "net/http" 10 ) 11 12 // CloneHeader returns a duplicate of the provided Header. 13 func CloneHeader(h http.Header) http.Header { 14 h2 := make(http.Header, len(h)) 15 for k, vv := range h { 16 vv2 := make([]string, len(vv)) 17 copy(vv2, vv) 18 h2[k] = vv2 19 } 20 return h2 21 } 22 23 // UpdateHeader adds and new name/value pairs and replaces 24 // those already existing in the older header. 25 func UpdateHeader(older, newer http.Header) { 26 for name, values := range newer { 27 for i, value := range values { 28 if i == 0 { 29 older.Set(name, value) 30 } else { 31 older.Add(name, value) 32 } 33 } 34 } 35 } 36 37 func BytesToUint16(b []byte) uint16 { 38 return (uint16(b[0]) << 8) + uint16(b[1]) 39 } 40 41 func BytesToUint24(b []byte) uint32 { 42 return (uint32(b[0]) << 16) + (uint32(b[1]) << 8) + uint32(b[2]) 43 } 44 45 func BytesToUint24Reverse(b []byte) uint32 { 46 return (uint32(b[2]) << 16) + (uint32(b[1]) << 8) + uint32(b[0]) 47 } 48 49 func BytesToUint32(b []byte) uint32 { 50 return (uint32(b[0]) << 24) + (uint32(b[1]) << 16) + (uint32(b[2]) << 8) + uint32(b[3]) 51 } 52 53 // ReadExactly is used to ensure that the given number of bytes 54 // are read if possible, even if multiple calls to Read 55 // are required. 56 func ReadExactly(r io.Reader, i int) ([]byte, error) { 57 out := make([]byte, i) 58 in := out[:] 59 for i > 0 { 60 if r == nil { 61 return nil, ErrConnNil 62 } 63 if n, err := r.Read(in); err != nil { 64 return nil, err 65 } else { 66 in = in[n:] 67 i -= n 68 } 69 } 70 return out, nil 71 } 72 73 // WriteExactly is used to ensure that the given data is written 74 // if possible, even if multiple calls to Write are 75 // required. 76 func WriteExactly(w io.Writer, data []byte) error { 77 i := len(data) 78 for i > 0 { 79 if w == nil { 80 return ErrConnNil 81 } 82 if n, err := w.Write(data); err != nil { 83 return err 84 } else { 85 data = data[n:] 86 i -= n 87 } 88 } 89 return nil 90 } 91 92 // ReadCloser is a helper structure to allow 93 // an io.Reader to satisfy the io.ReadCloser 94 // interface. 95 type ReadCloser struct { 96 io.Reader 97 } 98 99 func (r *ReadCloser) Close() error { 100 return nil 101 } 102 103 // ReadCounter is a helper structure for 104 // keeping track of the number of bytes 105 // read from an io.Reader 106 type ReadCounter struct { 107 N int64 108 R io.Reader 109 } 110 111 func (r *ReadCounter) Read(b []byte) (n int, err error) { 112 n, err = r.R.Read(b) 113 r.N += int64(n) 114 return 115 } 116 117 // WriteCounter is a helper structure for 118 // keeping track of the number of bytes 119 // written from an io.Writer 120 type WriteCounter struct { 121 N int64 122 W io.Writer 123 } 124 125 func (w *WriteCounter) Write(b []byte) (n int, err error) { 126 n, err = w.W.Write(b) 127 w.N += int64(n) 128 return 129 }