ad273dbe5d
git-subtree-dir: backend/goldmark git-subtree-split: 379bf24a47e6ef07f34d7536aead86d8792ac300
144 lines
3.2 KiB
Go
144 lines
3.2 KiB
Go
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"flag"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
)
|
|
|
|
func embStructsSubCommand(args []string) {
|
|
cmdName := "emb-structs"
|
|
cmd := flag.NewFlagSet(cmdName, flag.ExitOnError)
|
|
cmd.Usage = func() {
|
|
_, _ = fmt.Fprintf(cmd.Output(), `Usage of %s:
|
|
|
|
Embed Go structs as compact format in the binary.
|
|
JSON file format:
|
|
{
|
|
"prefix": "html5entities", // prefix for the generated const/var
|
|
"types": { // struct field types
|
|
"Name": "string", // struct fields
|
|
"CodePoints": "[]int",
|
|
"Characters": "[]byte"
|
|
},
|
|
|
|
// array of struct data
|
|
// all data must be a string
|
|
"data": [
|
|
{"Name": "AElig", "CodePoints": ["198"], "Characters": ["0xc3", "0x86"]},
|
|
{"Name": "AMP", "CodePoints": ["38"], "Characters": ["0x26"]},
|
|
]
|
|
}
|
|
|
|
`, cmdName)
|
|
cmd.PrintDefaults()
|
|
}
|
|
|
|
inputJSONPath := cmd.String("i", "", "source JSON file path(required)")
|
|
outputPath := cmd.String("o", "", "output file path(required)")
|
|
|
|
if err := cmd.Parse(args); err != nil ||
|
|
len(*inputJSONPath) == 0 ||
|
|
len(*outputPath) == 0 {
|
|
usage(cmd.Usage, err)
|
|
}
|
|
var source map[string]any
|
|
inputJSONSource, err := os.ReadFile(*inputJSONPath)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
if err := json.Unmarshal(inputJSONSource, &source); err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
f, err := os.Create(*outputPath)
|
|
if err != nil {
|
|
fmt.Printf("Failed to open %s: %v\n", *outputPath, err)
|
|
os.Exit(1)
|
|
}
|
|
defer f.Close()
|
|
|
|
abs, _ := filepath.Abs(*outputPath)
|
|
pkg := filepath.Base(filepath.Dir(abs))
|
|
|
|
write := func(ft string, v ...any) {
|
|
if len(v) == 0 {
|
|
_, _ = f.WriteString(ft)
|
|
return
|
|
}
|
|
_, _ = f.WriteString(fmt.Sprintf(ft, v...))
|
|
}
|
|
writeln := func(ft string, v ...any) {
|
|
write(ft+"\n", v...)
|
|
}
|
|
|
|
writeln("// Code generated by _tools; DO NOT EDIT.")
|
|
writeln("package " + pkg)
|
|
|
|
prefix := source["prefix"].(string)
|
|
types := source["types"].(map[string]any)
|
|
data := source["data"].([]any)
|
|
|
|
writeln("const _%sLength = %d", prefix, len(data))
|
|
|
|
for prop, _typ := range types {
|
|
typ := _typ.(string)
|
|
if typ == "string" {
|
|
write("const _%s%s string = \"", prefix, prop)
|
|
for _, _d := range data {
|
|
d := _d.(map[string]any)
|
|
v := d[prop].(string)
|
|
write(v)
|
|
}
|
|
writeln(`"`)
|
|
write("const _%s%sIndex = \"", prefix, prop)
|
|
for _, _d := range data {
|
|
d := _d.(map[string]any)
|
|
v := d[prop].(string)
|
|
write("\\x%02x", len(v))
|
|
}
|
|
writeln(`"`)
|
|
continue
|
|
}
|
|
|
|
if strings.HasPrefix(typ, "[]") {
|
|
elmTyp := typ[2:]
|
|
write("var _%s%s = [...]%s{", prefix, prop, elmTyp)
|
|
for i, _d := range data {
|
|
d := _d.(map[string]any)
|
|
arr := d[prop].([]any)
|
|
for j, a := range arr {
|
|
v := a.(string)
|
|
write(v)
|
|
if i != len(data)-1 || j != len(arr)-1 {
|
|
write(", ")
|
|
}
|
|
}
|
|
}
|
|
writeln("}")
|
|
write("var _%s%sIndex = \"", prefix, prop)
|
|
for _, _d := range data {
|
|
d := _d.(map[string]any)
|
|
arr := d[prop].([]any)
|
|
write("\\x%02x", len(arr))
|
|
}
|
|
writeln(`"`)
|
|
continue
|
|
}
|
|
|
|
write("var _%s%s = [...]%s{", prefix, prop, typ)
|
|
for i, _d := range data {
|
|
d := _d.(map[string]any)
|
|
v := d[prop].(string)
|
|
write(v)
|
|
if i != len(data)-1 {
|
|
write(", ")
|
|
}
|
|
}
|
|
writeln(`}`)
|
|
}
|
|
}
|