/
rand.go
executable file
·88 lines (81 loc) · 1.61 KB
/
rand.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
package crypto
import (
"crypto/rand"
"log"
)
// RandInt returns a random int generated using crypto/rand
func RandInt(max int) int {
var (
bits uint = 32
ds uint = 32
)
for {
ms := max >> bits
if ms == 1 {
break
}
if ms > 1 {
bits += ds
} else {
bits -= ds
}
ds >>= 1
}
for {
r := randInt(bits + 1)
if r < max {
return r
}
}
}
func randInt(bits uint) int {
b := make([]byte, (bits/8)+1)
_, err := rand.Read(b)
randReadErr(err)
var i int
for ; bits > 8; bits -= 8 {
i <<= 8
i += int(b[0])
b = b[1:]
}
i <<= uint(bits)
var mask byte
for ; bits > 0; bits-- {
mask = (mask << 1) + 1
}
i += int(b[0] & mask)
return i
}
// RandUint32 returns a random int generated using crypto/rand
func RandUint32() uint32 {
b := make([]byte, 4)
_, err := rand.Read(b)
randReadErr(err)
return (uint32(b[0]) + uint32(b[1])<<8 + uint32(b[2])<<16 + uint32(b[3])<<24)
}
// RandUint16 returns a random int generated using crypto/rand
func RandUint16() uint16 {
b := make([]byte, 2)
_, err := rand.Read(b)
randReadErr(err)
return (uint16(b[0]) + uint16(b[1])<<8)
}
// InterruptHandler will be called in the case of a set of very rare errors. By
// default, the InterruptHandler will panic. Only main should change the
// InterruptHandler.
var InterruptHandler = func(err error) {
go func() {
// panic in goroutine so that it won't bubble and potentially be caught by
// resolve in another package
panic(err)
}()
<-make(chan bool) //block forever
}
func randReadErr(err error) bool {
if err != nil {
log.Print("ERROR", err)
InterruptHandler(err)
return true
}
return false
}