stringid.go 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. // Package stringid provides helper functions for dealing with string identifiers
  2. package stringid
  3. import (
  4. "crypto/rand"
  5. "encoding/hex"
  6. "fmt"
  7. "io"
  8. "regexp"
  9. "strconv"
  10. "strings"
  11. "github.com/docker/docker/pkg/random"
  12. )
  13. const shortLen = 12
  14. var (
  15. validShortID = regexp.MustCompile("^[a-f0-9]{12}$")
  16. validHex = regexp.MustCompile(`^[a-f0-9]{64}$`)
  17. )
  18. // IsShortID determines if an arbitrary string *looks like* a short ID.
  19. func IsShortID(id string) bool {
  20. return validShortID.MatchString(id)
  21. }
  22. // TruncateID returns a shorthand version of a string identifier for convenience.
  23. // A collision with other shorthands is very unlikely, but possible.
  24. // In case of a collision a lookup with TruncIndex.Get() will fail, and the caller
  25. // will need to use a longer prefix, or the full-length Id.
  26. func TruncateID(id string) string {
  27. if i := strings.IndexRune(id, ':'); i >= 0 {
  28. id = id[i+1:]
  29. }
  30. if len(id) > shortLen {
  31. id = id[:shortLen]
  32. }
  33. return id
  34. }
  35. func generateID(crypto bool) string {
  36. b := make([]byte, 32)
  37. r := random.Reader
  38. if crypto {
  39. r = rand.Reader
  40. }
  41. for {
  42. if _, err := io.ReadFull(r, b); err != nil {
  43. panic(err) // This shouldn't happen
  44. }
  45. id := hex.EncodeToString(b)
  46. // if we try to parse the truncated for as an int and we don't have
  47. // an error then the value is all numeric and causes issues when
  48. // used as a hostname. ref #3869
  49. if _, err := strconv.ParseInt(TruncateID(id), 10, 64); err == nil {
  50. continue
  51. }
  52. return id
  53. }
  54. }
  55. // GenerateRandomID returns a unique id.
  56. func GenerateRandomID() string {
  57. return generateID(true)
  58. }
  59. // GenerateNonCryptoID generates unique id without using cryptographically
  60. // secure sources of random.
  61. // It helps you to save entropy.
  62. func GenerateNonCryptoID() string {
  63. return generateID(false)
  64. }
  65. // ValidateID checks whether an ID string is a valid image ID.
  66. func ValidateID(id string) error {
  67. if ok := validHex.MatchString(id); !ok {
  68. return fmt.Errorf("image ID %q is invalid", id)
  69. }
  70. return nil
  71. }