2022-12-01 17:50:01 +00:00
|
|
|
package urlenc
|
2022-11-26 03:22:31 +00:00
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"bytes"
|
|
|
|
|
"compress/flate"
|
|
|
|
|
"encoding/base64"
|
|
|
|
|
"io"
|
2022-12-11 00:21:54 +00:00
|
|
|
"sort"
|
2022-11-26 03:22:31 +00:00
|
|
|
"strings"
|
|
|
|
|
|
2022-12-01 17:50:01 +00:00
|
|
|
"oss.terrastruct.com/util-go/xdefer"
|
|
|
|
|
|
2022-11-26 03:22:31 +00:00
|
|
|
"oss.terrastruct.com/d2/d2graph"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
var compressionDict = "->" +
|
|
|
|
|
"<-" +
|
|
|
|
|
"--" +
|
|
|
|
|
"<->"
|
|
|
|
|
|
2022-12-01 17:50:01 +00:00
|
|
|
func init() {
|
2022-12-11 00:21:54 +00:00
|
|
|
var common []string
|
2022-12-01 17:50:01 +00:00
|
|
|
for k := range d2graph.ReservedKeywords {
|
2022-12-11 00:21:54 +00:00
|
|
|
common = append(common, k)
|
2022-12-01 17:50:01 +00:00
|
|
|
}
|
2022-12-11 00:21:54 +00:00
|
|
|
sort.Strings(common)
|
|
|
|
|
for _, k := range common {
|
2022-12-01 17:50:01 +00:00
|
|
|
compressionDict += k
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Encode takes a D2 script and encodes it as a compressed base64 string for embedding in URLs.
|
|
|
|
|
func Encode(raw string) (_ string, err error) {
|
|
|
|
|
defer xdefer.Errorf(&err, "failed to encode d2 script")
|
2022-11-26 03:22:31 +00:00
|
|
|
|
2022-12-01 17:50:01 +00:00
|
|
|
b := &bytes.Buffer{}
|
2022-11-26 03:22:31 +00:00
|
|
|
|
2022-12-01 17:50:01 +00:00
|
|
|
zw, err := flate.NewWriterDict(b, flate.DefaultCompression, []byte(compressionDict))
|
2022-11-26 03:22:31 +00:00
|
|
|
if err != nil {
|
|
|
|
|
return "", err
|
|
|
|
|
}
|
|
|
|
|
if _, err := io.Copy(zw, strings.NewReader(raw)); err != nil {
|
|
|
|
|
return "", err
|
|
|
|
|
}
|
|
|
|
|
if err := zw.Close(); err != nil {
|
|
|
|
|
return "", err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
encoded := base64.URLEncoding.EncodeToString(b.Bytes())
|
|
|
|
|
return encoded, nil
|
|
|
|
|
}
|
|
|
|
|
|
2022-12-01 17:50:01 +00:00
|
|
|
// Decode decodes a compressed base64 D2 string.
|
|
|
|
|
func Decode(encoded string) (_ string, err error) {
|
|
|
|
|
defer xdefer.Errorf(&err, "failed to decode d2 script")
|
|
|
|
|
|
2022-11-26 03:22:31 +00:00
|
|
|
b64Decoded, err := base64.URLEncoding.DecodeString(encoded)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return "", err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
zr := flate.NewReaderDict(bytes.NewReader(b64Decoded), []byte(compressionDict))
|
|
|
|
|
var b bytes.Buffer
|
|
|
|
|
if _, err := io.Copy(&b, zr); err != nil {
|
|
|
|
|
return "", err
|
|
|
|
|
}
|
|
|
|
|
if err := zr.Close(); err != nil {
|
|
|
|
|
return "", nil
|
|
|
|
|
}
|
|
|
|
|
return b.String(), nil
|
|
|
|
|
}
|