go4.org@v0.0.0-20230225012048-214862532bf5/types/types.go (about)

     1  /*
     2  Copyright 2013 Google Inc.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8       http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  // Package types provides various common types.
    18  package types // import "go4.org/types"
    19  
    20  import (
    21  	"bytes"
    22  	"encoding/json"
    23  	"fmt"
    24  	"io"
    25  	"io/ioutil"
    26  	"strings"
    27  	"sync"
    28  	"time"
    29  )
    30  
    31  var null_b = []byte("null")
    32  
    33  // NopCloser is an io.Closer that does nothing.
    34  var NopCloser io.Closer = CloseFunc(func() error { return nil })
    35  
    36  // EmptyBody is a ReadCloser that returns EOF on Read and does nothing
    37  // on Close.
    38  var EmptyBody io.ReadCloser = ioutil.NopCloser(strings.NewReader(""))
    39  
    40  // Time3339 is a time.Time which encodes to and from JSON
    41  // as an RFC 3339 time in UTC.
    42  type Time3339 time.Time
    43  
    44  var (
    45  	_ json.Marshaler   = Time3339{}
    46  	_ json.Unmarshaler = (*Time3339)(nil)
    47  )
    48  
    49  func (t Time3339) String() string {
    50  	return time.Time(t).UTC().Format(time.RFC3339Nano)
    51  }
    52  
    53  func (t Time3339) MarshalJSON() ([]byte, error) {
    54  	if t.Time().IsZero() {
    55  		return null_b, nil
    56  	}
    57  	return json.Marshal(t.String())
    58  }
    59  
    60  func (t *Time3339) UnmarshalJSON(b []byte) error {
    61  	if bytes.Equal(b, null_b) {
    62  		*t = Time3339{}
    63  		return nil
    64  	}
    65  	if len(b) < 2 || b[0] != '"' || b[len(b)-1] != '"' {
    66  		return fmt.Errorf("types: failed to unmarshal non-string value %q as an RFC 3339 time", b)
    67  	}
    68  	s := string(b[1 : len(b)-1])
    69  	if s == "" {
    70  		*t = Time3339{}
    71  		return nil
    72  	}
    73  	tm, err := time.Parse(time.RFC3339Nano, s)
    74  	if err != nil {
    75  		if strings.HasPrefix(s, "0000-00-00T00:00:00") {
    76  			*t = Time3339{}
    77  			return nil
    78  		}
    79  		return err
    80  	}
    81  	*t = Time3339(tm)
    82  	return nil
    83  }
    84  
    85  // ParseTime3339OrZero parses a string in RFC3339 format. If it's invalid,
    86  // the zero time value is returned instead.
    87  func ParseTime3339OrZero(v string) Time3339 {
    88  	t, err := time.Parse(time.RFC3339Nano, v)
    89  	if err != nil {
    90  		return Time3339{}
    91  	}
    92  	return Time3339(t)
    93  }
    94  
    95  func ParseTime3339OrNil(v string) *Time3339 {
    96  	t, err := time.Parse(time.RFC3339Nano, v)
    97  	if err != nil {
    98  		return nil
    99  	}
   100  	tm := Time3339(t)
   101  	return &tm
   102  }
   103  
   104  // Time returns the time as a time.Time with slightly less stutter
   105  // than a manual conversion.
   106  func (t Time3339) Time() time.Time {
   107  	return time.Time(t)
   108  }
   109  
   110  // IsAnyZero returns whether the time is Go zero or Unix zero.
   111  func (t *Time3339) IsAnyZero() bool {
   112  	return t == nil || time.Time(*t).IsZero() || time.Time(*t).Unix() == 0
   113  }
   114  
   115  // ByTime sorts times.
   116  type ByTime []time.Time
   117  
   118  func (s ByTime) Len() int           { return len(s) }
   119  func (s ByTime) Less(i, j int) bool { return s[i].Before(s[j]) }
   120  func (s ByTime) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
   121  
   122  // NewOnceCloser returns a Closer wrapping c which only calls Close on c
   123  // once. Subsequent calls to Close return nil.
   124  func NewOnceCloser(c io.Closer) io.Closer {
   125  	return &onceCloser{c: c}
   126  }
   127  
   128  type onceCloser struct {
   129  	mu sync.Mutex
   130  	c  io.Closer
   131  }
   132  
   133  func (c *onceCloser) Close() error {
   134  	c.mu.Lock()
   135  	defer c.mu.Unlock()
   136  	if c.c == nil {
   137  		return nil
   138  	}
   139  	err := c.c.Close()
   140  	c.c = nil
   141  	return err
   142  }
   143  
   144  // CloseFunc implements io.Closer with a function.
   145  type CloseFunc func() error
   146  
   147  func (fn CloseFunc) Close() error { return fn() }