uri.go raw

   1  package httpbinding
   2  
   3  import (
   4  	"math"
   5  	"math/big"
   6  	"strconv"
   7  	"strings"
   8  )
   9  
  10  // URIValue is used to encode named URI parameters
  11  type URIValue struct {
  12  	path, rawPath, buffer *[]byte
  13  
  14  	key string
  15  }
  16  
  17  func newURIValue(path *[]byte, rawPath *[]byte, buffer *[]byte, key string) URIValue {
  18  	return URIValue{path: path, rawPath: rawPath, buffer: buffer, key: key}
  19  }
  20  
  21  func (u URIValue) modifyURI(value string) (err error) {
  22  	*u.path, *u.buffer, err = replacePathElement(*u.path, *u.buffer, u.key, value, false)
  23  	if err != nil {
  24  		return err
  25  	}
  26  	*u.rawPath, *u.buffer, err = replacePathElement(*u.rawPath, *u.buffer, u.key, value, true)
  27  	return err
  28  }
  29  
  30  // Boolean encodes v as a URI string value
  31  func (u URIValue) Boolean(v bool) error {
  32  	return u.modifyURI(strconv.FormatBool(v))
  33  }
  34  
  35  // String encodes v as a URI string value
  36  func (u URIValue) String(v string) error {
  37  	return u.modifyURI(v)
  38  }
  39  
  40  // Byte encodes v as a URI string value
  41  func (u URIValue) Byte(v int8) error {
  42  	return u.Long(int64(v))
  43  }
  44  
  45  // Short encodes v as a URI string value
  46  func (u URIValue) Short(v int16) error {
  47  	return u.Long(int64(v))
  48  }
  49  
  50  // Integer encodes v as a URI string value
  51  func (u URIValue) Integer(v int32) error {
  52  	return u.Long(int64(v))
  53  }
  54  
  55  // Long encodes v as a URI string value
  56  func (u URIValue) Long(v int64) error {
  57  	return u.modifyURI(strconv.FormatInt(v, 10))
  58  }
  59  
  60  // Float encodes v as a query string value
  61  func (u URIValue) Float(v float32) error {
  62  	return u.float(float64(v), 32)
  63  }
  64  
  65  // Double encodes v as a query string value
  66  func (u URIValue) Double(v float64) error {
  67  	return u.float(v, 64)
  68  }
  69  
  70  func (u URIValue) float(v float64, bitSize int) error {
  71  	switch {
  72  	case math.IsNaN(v):
  73  		return u.String(floatNaN)
  74  	case math.IsInf(v, 1):
  75  		return u.String(floatInfinity)
  76  	case math.IsInf(v, -1):
  77  		return u.String(floatNegInfinity)
  78  	default:
  79  		return u.modifyURI(strconv.FormatFloat(v, 'f', -1, bitSize))
  80  	}
  81  }
  82  
  83  // BigInteger encodes v as a query string value
  84  func (u URIValue) BigInteger(v *big.Int) error {
  85  	return u.modifyURI(v.String())
  86  }
  87  
  88  // BigDecimal encodes v as a query string value
  89  func (u URIValue) BigDecimal(v *big.Float) error {
  90  	if i, accuracy := v.Int64(); accuracy == big.Exact {
  91  		return u.Long(i)
  92  	}
  93  	return u.modifyURI(v.Text('e', -1))
  94  }
  95  
  96  // SplitURI parses a Smithy HTTP binding trait URI
  97  func SplitURI(uri string) (path, query string) {
  98  	queryStart := strings.IndexRune(uri, '?')
  99  	if queryStart == -1 {
 100  		path = uri
 101  		return path, query
 102  	}
 103  
 104  	path = uri[:queryStart]
 105  	if queryStart+1 >= len(uri) {
 106  		return path, query
 107  	}
 108  	query = uri[queryStart+1:]
 109  
 110  	return path, query
 111  }
 112