Path: blob/main/vendor/github.com/google/uuid/version7.go
2875 views
// Copyright 2023 Google Inc. All rights reserved.1// Use of this source code is governed by a BSD-style2// license that can be found in the LICENSE file.34package uuid56import (7"io"8)910// UUID version 7 features a time-ordered value field derived from the widely11// implemented and well known Unix Epoch timestamp source,12// the number of milliseconds seconds since midnight 1 Jan 1970 UTC, leap seconds excluded.13// As well as improved entropy characteristics over versions 1 or 6.14//15// see https://datatracker.ietf.org/doc/html/draft-peabody-dispatch-new-uuid-format-03#name-uuid-version-716//17// Implementations SHOULD utilize UUID version 7 over UUID version 1 and 6 if possible.18//19// NewV7 returns a Version 7 UUID based on the current time(Unix Epoch).20// Uses the randomness pool if it was enabled with EnableRandPool.21// On error, NewV7 returns Nil and an error22func NewV7() (UUID, error) {23uuid, err := NewRandom()24if err != nil {25return uuid, err26}27makeV7(uuid[:])28return uuid, nil29}3031// NewV7FromReader returns a Version 7 UUID based on the current time(Unix Epoch).32// it use NewRandomFromReader fill random bits.33// On error, NewV7FromReader returns Nil and an error.34func NewV7FromReader(r io.Reader) (UUID, error) {35uuid, err := NewRandomFromReader(r)36if err != nil {37return uuid, err38}3940makeV7(uuid[:])41return uuid, nil42}4344// makeV7 fill 48 bits time (uuid[0] - uuid[5]), set version b0111 (uuid[6])45// uuid[8] already has the right version number (Variant is 10)46// see function NewV7 and NewV7FromReader47func makeV7(uuid []byte) {48/*490 1 2 3500 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 151+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+52| unix_ts_ms |53+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+54| unix_ts_ms | ver | rand_a (12 bit seq) |55+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+56|var| rand_b |57+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+58| rand_b |59+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+60*/61_ = uuid[15] // bounds check6263t, s := getV7Time()6465uuid[0] = byte(t >> 40)66uuid[1] = byte(t >> 32)67uuid[2] = byte(t >> 24)68uuid[3] = byte(t >> 16)69uuid[4] = byte(t >> 8)70uuid[5] = byte(t)7172uuid[6] = 0x70 | (0x0F & byte(s>>8))73uuid[7] = byte(s)74}7576// lastV7time is the last time we returned stored as:77//78// 52 bits of time in milliseconds since epoch79// 12 bits of (fractional nanoseconds) >> 880var lastV7time int648182const nanoPerMilli = 10000008384// getV7Time returns the time in milliseconds and nanoseconds / 256.85// The returned (milli << 12 + seq) is guarenteed to be greater than86// (milli << 12 + seq) returned by any previous call to getV7Time.87func getV7Time() (milli, seq int64) {88timeMu.Lock()89defer timeMu.Unlock()9091nano := timeNow().UnixNano()92milli = nano / nanoPerMilli93// Sequence number is between 0 and 3906 (nanoPerMilli>>8)94seq = (nano - milli*nanoPerMilli) >> 895now := milli<<12 + seq96if now <= lastV7time {97now = lastV7time + 198milli = now >> 1299seq = now & 0xfff100}101lastV7time = now102return milli, seq103}104105106