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  }