Giant blob of minor changes
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / golang.org / x / tools@v0.0.0-20201028153306-37f0764111ff / godoc / redirect / hash.go
1 // Copyright 2014 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 // This file provides a compact encoding of
6 // a map of Mercurial hashes to Git hashes.
7
8 package redirect
9
10 import (
11         "encoding/binary"
12         "fmt"
13         "io"
14         "os"
15         "sort"
16         "strconv"
17         "strings"
18 )
19
20 // hashMap is a map of Mercurial hashes to Git hashes.
21 type hashMap struct {
22         file    *os.File
23         entries int
24 }
25
26 // newHashMap takes a file handle that contains a map of Mercurial to Git
27 // hashes. The file should be a sequence of pairs of little-endian encoded
28 // uint32s, representing a hgHash and a gitHash respectively.
29 // The sequence must be sorted by hgHash.
30 // The file must remain open for as long as the returned hashMap is used.
31 func newHashMap(f *os.File) (*hashMap, error) {
32         fi, err := f.Stat()
33         if err != nil {
34                 return nil, err
35         }
36         return &hashMap{file: f, entries: int(fi.Size() / 8)}, nil
37 }
38
39 // Lookup finds an hgHash in the map that matches the given prefix, and returns
40 // its corresponding gitHash. The prefix must be at least 8 characters long.
41 func (m *hashMap) Lookup(s string) gitHash {
42         if m == nil {
43                 return 0
44         }
45         hg, err := hgHashFromString(s)
46         if err != nil {
47                 return 0
48         }
49         var git gitHash
50         b := make([]byte, 8)
51         sort.Search(m.entries, func(i int) bool {
52                 n, err := m.file.ReadAt(b, int64(i*8))
53                 if err != nil {
54                         panic(err)
55                 }
56                 if n != 8 {
57                         panic(io.ErrUnexpectedEOF)
58                 }
59                 v := hgHash(binary.LittleEndian.Uint32(b[:4]))
60                 if v == hg {
61                         git = gitHash(binary.LittleEndian.Uint32(b[4:]))
62                 }
63                 return v >= hg
64         })
65         return git
66 }
67
68 // hgHash represents the lower (leftmost) 32 bits of a Mercurial hash.
69 type hgHash uint32
70
71 func (h hgHash) String() string {
72         return intToHash(int64(h))
73 }
74
75 func hgHashFromString(s string) (hgHash, error) {
76         if len(s) < 8 {
77                 return 0, fmt.Errorf("string too small: len(s) = %d", len(s))
78         }
79         hash := s[:8]
80         i, err := strconv.ParseInt(hash, 16, 64)
81         if err != nil {
82                 return 0, err
83         }
84         return hgHash(i), nil
85 }
86
87 // gitHash represents the leftmost 28 bits of a Git hash in its upper 28 bits,
88 // and it encodes hash's repository in the lower 4  bits.
89 type gitHash uint32
90
91 func (h gitHash) Hash() string {
92         return intToHash(int64(h))[:7]
93 }
94
95 func (h gitHash) Repo() string {
96         return repo(h & 0xF).String()
97 }
98
99 func intToHash(i int64) string {
100         s := strconv.FormatInt(i, 16)
101         if len(s) < 8 {
102                 s = strings.Repeat("0", 8-len(s)) + s
103         }
104         return s
105 }
106
107 // repo represents a Go Git repository.
108 type repo byte
109
110 const (
111         repoGo repo = iota
112         repoBlog
113         repoCrypto
114         repoExp
115         repoImage
116         repoMobile
117         repoNet
118         repoSys
119         repoTalks
120         repoText
121         repoTools
122 )
123
124 func (r repo) String() string {
125         return map[repo]string{
126                 repoGo:     "go",
127                 repoBlog:   "blog",
128                 repoCrypto: "crypto",
129                 repoExp:    "exp",
130                 repoImage:  "image",
131                 repoMobile: "mobile",
132                 repoNet:    "net",
133                 repoSys:    "sys",
134                 repoTalks:  "talks",
135                 repoText:   "text",
136                 repoTools:  "tools",
137         }[r]
138 }