diff options
| author | Taras Madan <tarasmadan@google.com> | 2024-06-24 14:30:25 +0200 |
|---|---|---|
| committer | Taras Madan <tarasmadan@google.com> | 2024-07-05 07:51:41 +0000 |
| commit | 5145b76b8a41b71a7b3c06373959c12f3a22014b (patch) | |
| tree | d87c1ca1d0979767cc07ace6c0a616ec311a8fc6 /vendor/cloud.google.com/go/internal | |
| parent | 7d7fe8807550c6e02def380d335ae0230f1e495c (diff) | |
vendor: add bigquery client library
Diffstat (limited to 'vendor/cloud.google.com/go/internal')
| -rw-r--r-- | vendor/cloud.google.com/go/internal/uid/uid.go | 149 |
1 files changed, 149 insertions, 0 deletions
diff --git a/vendor/cloud.google.com/go/internal/uid/uid.go b/vendor/cloud.google.com/go/internal/uid/uid.go new file mode 100644 index 000000000..2f229d647 --- /dev/null +++ b/vendor/cloud.google.com/go/internal/uid/uid.go @@ -0,0 +1,149 @@ +// Copyright 2017 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package uid supports generating unique IDs. Its chief purpose is to prevent +// multiple test executions from interfering with each other, and to facilitate +// cleanup of old entities that may remain if tests exit early. +package uid + +import ( + "fmt" + "regexp" + "strconv" + "sync/atomic" + "time" +) + +// A Space manages a set of unique IDs distinguished by a prefix. +type Space struct { + Prefix string // Prefix of UIDs. Read-only. + Sep rune // Separates UID parts. Read-only. + Time time.Time // Timestamp for UIDs. Read-only. + re *regexp.Regexp + count int32 // atomic + short bool +} + +// Options are optional values for a Space. +type Options struct { + Sep rune // Separates parts of the UID. Defaults to '-'. + Time time.Time // Timestamp for all UIDs made with this space. Defaults to current time. + + // Short, if true, makes the result of space.New shorter by 6 characters. + // This can be useful for character restricted IDs. It will use a shorter + // but less readable time representation, and will only use two characters + // for the count suffix instead of four. + // + // e.x. normal: gotest-20181030-59751273685000-0001 + // e.x. short: gotest-1540917351273685000-01 + Short bool +} + +// NewSpace creates a new UID space. A UID Space is used to generate unique IDs. +func NewSpace(prefix string, opts *Options) *Space { + var short bool + sep := '-' + tm := time.Now().UTC() + if opts != nil { + short = opts.Short + if opts.Sep != 0 { + sep = opts.Sep + } + if !opts.Time.IsZero() { + tm = opts.Time + } + } + var re string + + if short { + re = fmt.Sprintf(`^%s%[2]c(\d+)%[2]c\d+$`, regexp.QuoteMeta(prefix), sep) + } else { + re = fmt.Sprintf(`^%s%[2]c(\d{4})(\d{2})(\d{2})%[2]c(\d+)%[2]c\d+$`, + regexp.QuoteMeta(prefix), sep) + } + + return &Space{ + Prefix: prefix, + Sep: sep, + Time: tm, + re: regexp.MustCompile(re), + short: short, + } +} + +// New generates a new unique ID. The ID consists of the Space's prefix, a +// timestamp, and a counter value. All unique IDs generated in the same test +// execution will have the same timestamp. +// +// Aside from the characters in the prefix, IDs contain only letters, numbers +// and sep. +func (s *Space) New() string { + c := atomic.AddInt32(&s.count, 1) + + if s.short && c > 99 { + // Short spaces only have space for 99 IDs. (two characters) + panic("Short space called New more than 99 times. Ran out of IDs.") + } else if c > 9999 { + // Spaces only have space for 9999 IDs. (four characters) + panic("New called more than 9999 times. Ran out of IDs.") + } + + if s.short { + return fmt.Sprintf("%s%c%d%c%02d", s.Prefix, s.Sep, s.Time.UnixNano(), s.Sep, c) + } + + // Write the time as a date followed by nanoseconds from midnight of that date. + // That makes it easier to see the approximate time of the ID when it is displayed. + y, m, d := s.Time.Date() + ns := s.Time.Sub(time.Date(y, m, d, 0, 0, 0, 0, time.UTC)) + // Zero-pad the counter for lexical sort order for IDs with the same timestamp. + return fmt.Sprintf("%s%c%04d%02d%02d%c%d%c%04d", + s.Prefix, s.Sep, y, m, d, s.Sep, ns, s.Sep, c) +} + +// Timestamp extracts the timestamp of uid, which must have been generated by +// s. The second return value is true on success, false if there was a problem. +func (s *Space) Timestamp(uid string) (time.Time, bool) { + subs := s.re.FindStringSubmatch(uid) + if subs == nil { + return time.Time{}, false + } + + if s.short { + ns, err := strconv.ParseInt(subs[1], 10, 64) + if err != nil { + return time.Time{}, false + } + return time.Unix(ns/1e9, ns%1e9), true + } + + y, err1 := strconv.Atoi(subs[1]) + m, err2 := strconv.Atoi(subs[2]) + d, err3 := strconv.Atoi(subs[3]) + ns, err4 := strconv.Atoi(subs[4]) + if err1 != nil || err2 != nil || err3 != nil || err4 != nil { + return time.Time{}, false + } + return time.Date(y, time.Month(m), d, 0, 0, 0, ns, time.UTC), true +} + +// Older reports whether uid was created by m and has a timestamp older than +// the current time by at least d. +func (s *Space) Older(uid string, d time.Duration) bool { + ts, ok := s.Timestamp(uid) + if !ok { + return false + } + return time.Since(ts) > d +} |
