string.go raw

   1  // Copyright 2017 The Go Authors. 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 cryptobyte contains types that help with parsing and constructing
   6  // length-prefixed, binary messages, including ASN.1 DER. (The asn1 subpackage
   7  // contains useful ASN.1 constants.)
   8  //
   9  // The String type is for parsing. It wraps a []byte slice and provides helper
  10  // functions for consuming structures, value by value.
  11  //
  12  // The Builder type is for constructing messages. It providers helper functions
  13  // for appending values and also for appending length-prefixed submessages –
  14  // without having to worry about calculating the length prefix ahead of time.
  15  //
  16  // See the documentation and examples for the Builder and String types to get
  17  // started.
  18  package cryptobyte
  19  
  20  // String represents a string of bytes. It provides methods for parsing
  21  // fixed-length and length-prefixed values from it.
  22  type String []byte
  23  
  24  // read advances a String by n bytes and returns them. If less than n bytes
  25  // remain, it returns nil.
  26  func (s *String) read(n int) []byte {
  27  	if len(*s) < n || n < 0 {
  28  		return nil
  29  	}
  30  	v := (*s)[:n]
  31  	*s = (*s)[n:]
  32  	return v
  33  }
  34  
  35  // Skip advances the String by n byte and reports whether it was successful.
  36  func (s *String) Skip(n int) bool {
  37  	return s.read(n) != nil
  38  }
  39  
  40  // ReadUint8 decodes an 8-bit value into out and advances over it.
  41  // It reports whether the read was successful.
  42  func (s *String) ReadUint8(out *uint8) bool {
  43  	v := s.read(1)
  44  	if v == nil {
  45  		return false
  46  	}
  47  	*out = uint8(v[0])
  48  	return true
  49  }
  50  
  51  // ReadUint16 decodes a big-endian, 16-bit value into out and advances over it.
  52  // It reports whether the read was successful.
  53  func (s *String) ReadUint16(out *uint16) bool {
  54  	v := s.read(2)
  55  	if v == nil {
  56  		return false
  57  	}
  58  	*out = uint16(v[0])<<8 | uint16(v[1])
  59  	return true
  60  }
  61  
  62  // ReadUint24 decodes a big-endian, 24-bit value into out and advances over it.
  63  // It reports whether the read was successful.
  64  func (s *String) ReadUint24(out *uint32) bool {
  65  	v := s.read(3)
  66  	if v == nil {
  67  		return false
  68  	}
  69  	*out = uint32(v[0])<<16 | uint32(v[1])<<8 | uint32(v[2])
  70  	return true
  71  }
  72  
  73  // ReadUint32 decodes a big-endian, 32-bit value into out and advances over it.
  74  // It reports whether the read was successful.
  75  func (s *String) ReadUint32(out *uint32) bool {
  76  	v := s.read(4)
  77  	if v == nil {
  78  		return false
  79  	}
  80  	*out = uint32(v[0])<<24 | uint32(v[1])<<16 | uint32(v[2])<<8 | uint32(v[3])
  81  	return true
  82  }
  83  
  84  // ReadUint48 decodes a big-endian, 48-bit value into out and advances over it.
  85  // It reports whether the read was successful.
  86  func (s *String) ReadUint48(out *uint64) bool {
  87  	v := s.read(6)
  88  	if v == nil {
  89  		return false
  90  	}
  91  	*out = uint64(v[0])<<40 | uint64(v[1])<<32 | uint64(v[2])<<24 | uint64(v[3])<<16 | uint64(v[4])<<8 | uint64(v[5])
  92  	return true
  93  }
  94  
  95  // ReadUint64 decodes a big-endian, 64-bit value into out and advances over it.
  96  // It reports whether the read was successful.
  97  func (s *String) ReadUint64(out *uint64) bool {
  98  	v := s.read(8)
  99  	if v == nil {
 100  		return false
 101  	}
 102  	*out = uint64(v[0])<<56 | uint64(v[1])<<48 | uint64(v[2])<<40 | uint64(v[3])<<32 | uint64(v[4])<<24 | uint64(v[5])<<16 | uint64(v[6])<<8 | uint64(v[7])
 103  	return true
 104  }
 105  
 106  func (s *String) readUnsigned(out *uint32, length int) bool {
 107  	v := s.read(length)
 108  	if v == nil {
 109  		return false
 110  	}
 111  	var result uint32
 112  	for i := 0; i < length; i++ {
 113  		result <<= 8
 114  		result |= uint32(v[i])
 115  	}
 116  	*out = result
 117  	return true
 118  }
 119  
 120  func (s *String) readLengthPrefixed(lenLen int, outChild *String) bool {
 121  	lenBytes := s.read(lenLen)
 122  	if lenBytes == nil {
 123  		return false
 124  	}
 125  	var length uint32
 126  	for _, b := range lenBytes {
 127  		length = length << 8
 128  		length = length | uint32(b)
 129  	}
 130  	v := s.read(int(length))
 131  	if v == nil {
 132  		return false
 133  	}
 134  	*outChild = v
 135  	return true
 136  }
 137  
 138  // ReadUint8LengthPrefixed reads the content of an 8-bit length-prefixed value
 139  // into out and advances over it. It reports whether the read was successful.
 140  func (s *String) ReadUint8LengthPrefixed(out *String) bool {
 141  	return s.readLengthPrefixed(1, out)
 142  }
 143  
 144  // ReadUint16LengthPrefixed reads the content of a big-endian, 16-bit
 145  // length-prefixed value into out and advances over it. It reports whether the
 146  // read was successful.
 147  func (s *String) ReadUint16LengthPrefixed(out *String) bool {
 148  	return s.readLengthPrefixed(2, out)
 149  }
 150  
 151  // ReadUint24LengthPrefixed reads the content of a big-endian, 24-bit
 152  // length-prefixed value into out and advances over it. It reports whether
 153  // the read was successful.
 154  func (s *String) ReadUint24LengthPrefixed(out *String) bool {
 155  	return s.readLengthPrefixed(3, out)
 156  }
 157  
 158  // ReadBytes reads n bytes into out and advances over them. It reports
 159  // whether the read was successful.
 160  func (s *String) ReadBytes(out *[]byte, n int) bool {
 161  	v := s.read(n)
 162  	if v == nil {
 163  		return false
 164  	}
 165  	*out = v
 166  	return true
 167  }
 168  
 169  // CopyBytes copies len(out) bytes into out and advances over them. It reports
 170  // whether the copy operation was successful
 171  func (s *String) CopyBytes(out []byte) bool {
 172  	n := len(out)
 173  	v := s.read(n)
 174  	if v == nil {
 175  		return false
 176  	}
 177  	return copy(out, v) == n
 178  }
 179  
 180  // Empty reports whether the string does not contain any bytes.
 181  func (s String) Empty() bool {
 182  	return len(s) == 0
 183  }
 184