encode_duration.go raw

   1  /*
   2   *
   3   * Copyright 2020 gRPC authors.
   4   *
   5   * Licensed under the Apache License, Version 2.0 (the "License");
   6   * you may not use this file except in compliance with the License.
   7   * You may obtain a copy of the License at
   8   *
   9   *     http://www.apache.org/licenses/LICENSE-2.0
  10   *
  11   * Unless required by applicable law or agreed to in writing, software
  12   * distributed under the License is distributed on an "AS IS" BASIS,
  13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14   * See the License for the specific language governing permissions and
  15   * limitations under the License.
  16   *
  17   */
  18  
  19  package grpcutil
  20  
  21  import (
  22  	"strconv"
  23  	"time"
  24  )
  25  
  26  const maxTimeoutValue int64 = 100000000 - 1
  27  
  28  // div does integer division and round-up the result. Note that this is
  29  // equivalent to (d+r-1)/r but has less chance to overflow.
  30  func div(d, r time.Duration) int64 {
  31  	if d%r > 0 {
  32  		return int64(d/r + 1)
  33  	}
  34  	return int64(d / r)
  35  }
  36  
  37  // EncodeDuration encodes the duration to the format grpc-timeout header
  38  // accepts.
  39  //
  40  // https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md#requests
  41  func EncodeDuration(t time.Duration) string {
  42  	// TODO: This is simplistic and not bandwidth efficient. Improve it.
  43  	if t <= 0 {
  44  		return "0n"
  45  	}
  46  	if d := div(t, time.Nanosecond); d <= maxTimeoutValue {
  47  		return strconv.FormatInt(d, 10) + "n"
  48  	}
  49  	if d := div(t, time.Microsecond); d <= maxTimeoutValue {
  50  		return strconv.FormatInt(d, 10) + "u"
  51  	}
  52  	if d := div(t, time.Millisecond); d <= maxTimeoutValue {
  53  		return strconv.FormatInt(d, 10) + "m"
  54  	}
  55  	if d := div(t, time.Second); d <= maxTimeoutValue {
  56  		return strconv.FormatInt(d, 10) + "S"
  57  	}
  58  	if d := div(t, time.Minute); d <= maxTimeoutValue {
  59  		return strconv.FormatInt(d, 10) + "M"
  60  	}
  61  	// Note that maxTimeoutValue * time.Hour > MaxInt64.
  62  	return strconv.FormatInt(div(t, time.Hour), 10) + "H"
  63  }
  64