| // Copyright 2015 The Vanadium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| // Utilities for building and parsing Sensor Log data keys. |
| package keyutil |
| |
| import ( |
| "crypto/rand" |
| "encoding/hex" |
| "fmt" |
| "strconv" |
| "strings" |
| "time" |
| ) |
| |
| const Sep = '$' |
| |
| // Join joins key parts into key. |
| func Join(parts ...string) string { |
| return strings.Join(parts, string(Sep)) |
| } |
| |
| // Split splits key into parts and verifies that the number of parts matches |
| // the expected number, returning an error otherwise. |
| func Split(key string, expectParts int) ([]string, error) { |
| parts := strings.Split(key, string(Sep)) |
| if gotParts := len(parts); expectParts != gotParts { |
| return nil, fmt.Errorf("invalid key %q: expected %d parts, got %d", key, expectParts, gotParts) |
| } |
| return parts, nil |
| } |
| |
| func StringifyTime(t time.Time) string { |
| return fmt.Sprintf("%016x", t.UnixNano()) |
| } |
| |
| func ParseTime(t string) (time.Time, error) { |
| nsec, err := strconv.ParseInt(t, 16, 64) |
| if err != nil { |
| return time.Time{}, fmt.Errorf("failed parsing time: %v", err) |
| } |
| return time.Unix(0, nsec), nil |
| } |
| |
| // ValidateId returns an error if the argument is not a valid identifier. |
| func ValidateId(id string) error { |
| if id == "" { |
| return fmt.Errorf("cannot be empty") |
| } |
| if strings.Contains(id, string(Sep)) { |
| return fmt.Errorf("cannot contain %q", Sep) |
| } |
| return nil |
| } |
| |
| // UUID generates a random UUID. |
| func UUID() string { |
| uuid := make([]byte, 16) |
| if _, err := rand.Read(uuid); err != nil { |
| panic(fmt.Errorf("rng failed: %v", err)) |
| } |
| // TODO(ivanpi): Use base64 once Syncbase keys are less restricted. |
| return hex.EncodeToString(uuid) |
| } |