source:
code/trunk/vendor/google.golang.org/protobuf/internal/detrand/rand.go@
822
Last change on this file since 822 was 822, checked in by , 22 months ago | |
---|---|
File size: 1.6 KB |
Line | |
---|---|
1 | // Copyright 2018 The Go Authors. All rights reserved. |
2 | // Use of this source code is governed by a BSD-style |
3 | // license that can be found in the LICENSE file. |
4 | |
5 | // Package detrand provides deterministically random functionality. |
6 | // |
7 | // The pseudo-randomness of these functions is seeded by the program binary |
8 | // itself and guarantees that the output does not change within a program, |
9 | // while ensuring that the output is unstable across different builds. |
10 | package detrand |
11 | |
12 | import ( |
13 | "encoding/binary" |
14 | "hash/fnv" |
15 | "os" |
16 | ) |
17 | |
18 | // Disable disables detrand such that all functions returns the zero value. |
19 | // This function is not concurrent-safe and must be called during program init. |
20 | func Disable() { |
21 | randSeed = 0 |
22 | } |
23 | |
24 | // Bool returns a deterministically random boolean. |
25 | func Bool() bool { |
26 | return randSeed%2 == 1 |
27 | } |
28 | |
29 | // Intn returns a deterministically random integer between 0 and n-1, inclusive. |
30 | func Intn(n int) int { |
31 | if n <= 0 { |
32 | panic("must be positive") |
33 | } |
34 | return int(randSeed % uint64(n)) |
35 | } |
36 | |
37 | // randSeed is a best-effort at an approximate hash of the Go binary. |
38 | var randSeed = binaryHash() |
39 | |
40 | func binaryHash() uint64 { |
41 | // Open the Go binary. |
42 | s, err := os.Executable() |
43 | if err != nil { |
44 | return 0 |
45 | } |
46 | f, err := os.Open(s) |
47 | if err != nil { |
48 | return 0 |
49 | } |
50 | defer f.Close() |
51 | |
52 | // Hash the size and several samples of the Go binary. |
53 | const numSamples = 8 |
54 | var buf [64]byte |
55 | h := fnv.New64() |
56 | fi, err := f.Stat() |
57 | if err != nil { |
58 | return 0 |
59 | } |
60 | binary.LittleEndian.PutUint64(buf[:8], uint64(fi.Size())) |
61 | h.Write(buf[:8]) |
62 | for i := int64(0); i < numSamples; i++ { |
63 | if _, err := f.ReadAt(buf[:], i*fi.Size()/numSamples); err != nil { |
64 | return 0 |
65 | } |
66 | h.Write(buf[:]) |
67 | } |
68 | return h.Sum64() |
69 | } |
Note:
See TracBrowser
for help on using the repository browser.