Skip to content

Commit ca21732

Browse files
committed
initial cli program
1 parent 08e28c6 commit ca21732

File tree

1 file changed

+97
-1
lines changed

1 file changed

+97
-1
lines changed

cmd/ulid/main.go

+97-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,99 @@
11
package main
22

3-
func main() {}
3+
import (
4+
cryptorand "crypto/rand"
5+
"flag"
6+
"fmt"
7+
mathrand "math/rand"
8+
"os"
9+
"strings"
10+
"time"
11+
12+
"go.rtnl.ai/ulid"
13+
)
14+
15+
const (
16+
defaultms = "Mon Jan 02 15:04:05.999 MST 2006"
17+
rfc3339ms = "2006-01-02T15:04:05.000Z07:00"
18+
)
19+
20+
func main() {
21+
var (
22+
format = flag.String("format", "default", "when parsing, show times in this format: default, rfc3339, unix, ms")
23+
local = flag.Bool("local", false, "when parsing, show local time instead of UTC")
24+
quick = flag.Bool("quick", false, "when generating, use non-crypto-grade entropy")
25+
zero = flag.Bool("zero", false, "when generating, fix entropy to all-zeroes")
26+
help = flag.Bool("help", false, "print this help text")
27+
)
28+
29+
flag.Parse()
30+
if *help {
31+
flag.Usage()
32+
os.Exit(0)
33+
}
34+
35+
var formatFunc func(time.Time) string
36+
switch strings.ToLower(*format) {
37+
case "default":
38+
formatFunc = func(t time.Time) string { return t.Format(defaultms) }
39+
case "rfc3339":
40+
formatFunc = func(t time.Time) string { return t.Format(rfc3339ms) }
41+
case "unix":
42+
formatFunc = func(t time.Time) string { return fmt.Sprint(t.Unix()) }
43+
case "ms":
44+
formatFunc = func(t time.Time) string { return fmt.Sprint(t.UnixNano() / 1e6) }
45+
default:
46+
fmt.Fprintf(os.Stderr, "invalid --format %s\n", *format)
47+
os.Exit(1)
48+
}
49+
50+
switch flag.NArg() {
51+
case 0:
52+
generate(*quick, *zero)
53+
default:
54+
parse(flag.Arg(0), *local, formatFunc)
55+
}
56+
}
57+
58+
func generate(quick, zero bool) {
59+
entropy := cryptorand.Reader
60+
if quick {
61+
seed := time.Now().UnixNano()
62+
source := mathrand.NewSource(seed)
63+
entropy = mathrand.New(source)
64+
}
65+
if zero {
66+
entropy = zeroReader{}
67+
}
68+
69+
id, err := ulid.New(ulid.Timestamp(time.Now()), entropy)
70+
if err != nil {
71+
fmt.Fprintf(os.Stderr, "%v\n", err)
72+
os.Exit(1)
73+
}
74+
75+
fmt.Fprintf(os.Stdout, "%s\n", id)
76+
}
77+
78+
func parse(s string, local bool, f func(time.Time) string) {
79+
id, err := ulid.Parse(s)
80+
if err != nil {
81+
fmt.Fprintf(os.Stderr, "%v\n", err)
82+
os.Exit(1)
83+
}
84+
85+
t := ulid.Time(id.Time())
86+
if !local {
87+
t = t.UTC()
88+
}
89+
fmt.Fprintf(os.Stderr, "%s\n", f(t))
90+
}
91+
92+
type zeroReader struct{}
93+
94+
func (zeroReader) Read(p []byte) (int, error) {
95+
for i := range p {
96+
p[i] = 0
97+
}
98+
return len(p), nil
99+
}

0 commit comments

Comments
 (0)