cloudflared-mirror/vendor/zombiezen.com/go/capnproto2/capnpc-go/fileparts.go

195 lines
4.1 KiB
Go

package main
import (
"fmt"
"strconv"
"strings"
"unicode"
"zombiezen.com/go/capnproto2"
)
type staticData struct {
name string
buf []byte
}
func (sd *staticData) init(fileID uint64) {
sd.name = fmt.Sprintf("x_%x", fileID)
sd.buf = make([]byte, 0, 4096)
}
func (sd *staticData) copyData(obj capnp.Ptr) (staticDataRef, error) {
m, _, err := capnp.NewMessage(capnp.SingleSegment(nil))
if err != nil {
return staticDataRef{}, err
}
err = m.SetRootPtr(obj)
if err != nil {
return staticDataRef{}, err
}
data, err := m.Marshal()
if err != nil {
return staticDataRef{}, err
}
ref := staticDataRef{data: sd}
ref.Start = len(sd.buf)
sd.buf = append(sd.buf, data...)
ref.End = len(sd.buf)
return ref, nil
}
type staticDataRef struct {
data *staticData
Start, End int
}
func (ref staticDataRef) IsValid() bool {
return ref.Start < ref.End
}
func (ref staticDataRef) String() string {
return fmt.Sprintf("%s[%d:%d]", ref.data.name, ref.Start, ref.End)
}
type imports struct {
specs []importSpec
used map[string]bool // keyed on import path
}
var capnpImportSpec = importSpec{path: capnpImport, name: "capnp"}
func (i *imports) init() {
i.specs = nil
i.used = make(map[string]bool)
i.reserve(capnpImportSpec)
i.reserve(importSpec{path: schemasImport, name: "schemas"})
i.reserve(importSpec{path: serverImport, name: "server"})
i.reserve(importSpec{path: textImport, name: "text"})
i.reserve(importSpec{path: contextImport, name: "context"})
i.reserve(importSpec{path: "math", name: "math"})
i.reserve(importSpec{path: "strconv", name: "strconv"})
}
func (i *imports) Capnp() string {
return i.add(importSpec{path: capnpImport, name: "capnp"})
}
func (i *imports) Schemas() string {
return i.add(importSpec{path: schemasImport, name: "schemas"})
}
func (i *imports) Server() string {
return i.add(importSpec{path: serverImport, name: "server"})
}
func (i *imports) Text() string {
return i.add(importSpec{path: textImport, name: "text"})
}
func (i *imports) Context() string {
return i.add(importSpec{path: contextImport, name: "context"})
}
func (i *imports) Math() string {
return i.add(importSpec{path: "math", name: "math"})
}
func (i *imports) Strconv() string {
return i.add(importSpec{path: "strconv", name: "strconv"})
}
func (i *imports) usedImports() []importSpec {
specs := make([]importSpec, 0, len(i.specs))
for _, s := range i.specs {
if i.used[s.path] {
specs = append(specs, s)
}
}
return specs
}
func (i *imports) byPath(path string) (spec importSpec, ok bool) {
for _, spec = range i.specs {
if spec.path == path {
return spec, true
}
}
return importSpec{}, false
}
func (i *imports) byName(name string) (spec importSpec, ok bool) {
for _, spec = range i.specs {
if spec.name == name {
return spec, true
}
}
return importSpec{}, false
}
func (i *imports) add(spec importSpec) (name string) {
name = i.reserve(spec)
i.used[spec.path] = true
return name
}
// reserve adds an import spec without marking it as used.
func (i *imports) reserve(spec importSpec) (name string) {
if ispec, ok := i.byPath(spec.path); ok {
return ispec.name
}
if spec.name == "" {
spec.name = pkgFromImport(spec.path)
}
if _, found := i.byName(spec.name); found {
for base, n := spec.name, uint64(2); ; n++ {
spec.name = base + strconv.FormatUint(n, 10)
if _, found = i.byName(spec.name); !found {
break
}
}
}
i.specs = append(i.specs, spec)
return spec.name
}
func pkgFromImport(path string) string {
if i := strings.LastIndex(path, "/"); i != -1 {
path = path[i+1:]
}
p := []rune(path)
n := 0
for _, r := range p {
if isIdent(r) {
p[n] = r
n++
}
}
if n == 0 || !isLower(p[0]) {
return "pkg" + string(p[:n])
}
return string(p[:n])
}
func isLower(r rune) bool {
return 'a' <= r && r <= 'z' || r == '_'
}
func isIdent(r rune) bool {
return isLower(r) || 'A' <= r && r <= 'Z' || r >= 0x80 && unicode.IsLetter(r)
}
type importSpec struct {
path string
name string
}
func (spec importSpec) String() string {
if spec.name == "" {
return strconv.Quote(spec.path)
}
return spec.name + " " + strconv.Quote(spec.path)
}