-
Notifications
You must be signed in to change notification settings - Fork 224
/
graph.go
70 lines (64 loc) · 2.22 KB
/
graph.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
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package codegen
import (
"crypto/sha256"
"fmt"
"regexp"
"sort"
)
// Component graph edges are embedded in the generated binary as
// specially formatted strings. These strings can be extracted from
// the binary to get the communication graph without having to execute
// the binary.
//
// Each edge is represented by a string fragment that looks like:
// ⟦checksum:wEaVeReDgE:src→dst⟧
//
// checksum is the first 8 bytes of the hex encoding of the SHA-256 of
// the string "wEaVeReDgE:src→dst" and src and dst are the fully qualified
// component type names.
// MakeEdgeString returns a string that should be emitted into generated
// code to represent an edge from src to dst.
func MakeEdgeString(src, dst string) string {
return fmt.Sprintf("⟦%s:wEaVeReDgE:%s→%s⟧\n", checksum(src, dst), src, dst)
}
// ExtractEdges returns the edges corresponding to MakeEdgeString() results
// that occur in data.
func ExtractEdges(data []byte) [][2]string {
var result [][2]string
re := regexp.MustCompile(`⟦([0-9a-fA-F]+):wEaVeReDgE:([a-zA-Z0-9\-.~_/]*?)→([a-zA-Z0-9\-.~_/]*?)⟧`)
for _, m := range re.FindAllSubmatch(data, -1) {
if len(m) != 4 {
continue
}
sum, src, dst := string(m[1]), string(m[2]), string(m[3])
if sum != checksum(src, dst) {
continue
}
result = append(result, [2]string{src, dst})
}
sort.Slice(result, func(i, j int) bool {
if a, b := result[i][0], result[j][0]; a != b {
return a < b
}
return result[i][1] < result[j][1]
})
return result
}
func checksum(src, dst string) string {
edge := fmt.Sprintf("wEaVeReDgE:%s→%s", src, dst)
sum := sha256.Sum256([]byte(edge))
return fmt.Sprintf("%0x", sum)[:8]
}