commit 290e6e438afe5f422392452da03129afa2eae724
Author: david cochran <about.trout@gmail.com>
Date: Mon, 31 Jan 2022 02:45:58 +0000
add layer0 solution
Diffstat:
5 files changed, 66 insertions(+), 0 deletions(-)
diff --git a/README.md b/README.md
@@ -0,0 +1 @@
+My [Tom's Data Onion](https://www.tomdalling.com/toms-data-onion/) solutions.
diff --git a/cmd/layer0/decode.go b/cmd/layer0/decode.go
@@ -0,0 +1,19 @@
+package main
+
+import (
+ "log"
+ "os"
+
+ "github.com/abtrout/tdo"
+)
+
+func main() {
+ bs, err := tdo.DecodePipedInput()
+ if err != nil {
+ log.Fatalf("Failed to read layer input: %v\n", err)
+ }
+ // DecodePipedInput already ASCII85 decodes; no additional work to do.
+ if _, err := os.Stdout.Write(bs); err != nil {
+ log.Fatalf("Failed to write decoded output: %v\n", err)
+ }
+}
diff --git a/go.mod b/go.mod
@@ -0,0 +1,3 @@
+module github.com/abtrout/tdo
+
+go 1.24.0
diff --git a/go.sum b/go.sum
diff --git a/input.go b/input.go
@@ -0,0 +1,43 @@
+package tdo
+
+import (
+ "bytes"
+ "encoding/ascii85"
+ "errors"
+ "fmt"
+ "io"
+ "os"
+)
+
+// Read piped input from stdin and ascii85 decode.
+func DecodePipedInput() ([]byte, error) {
+ stat, err := os.Stdin.Stat()
+ if err != nil {
+ return nil, err
+ }
+ if (stat.Mode() & os.ModeCharDevice) != 0 {
+ return nil, errors.New("no piped input")
+ }
+ in, err := io.ReadAll(os.Stdin)
+ if err != nil {
+ return nil, err
+ }
+ return decode(in)
+}
+
+// decode is a convenience wrapper around encoding/ascii85, adding
+// support for Adobe version, which the TDO layer inputs use, and
+// enables easy decoding from layer inputs without extra parsing.
+//
+// https://en.wikipedia.org/wiki/Ascii85#Adobe_version
+func decode(bs []byte) ([]byte, error) {
+ _, bs, _ = bytes.Cut(bs, []byte("<~"))
+ bs, _, _ = bytes.Cut(bs, []byte("~>"))
+
+ res := make([]byte, 4*len(bs))
+ ndst, _, err := ascii85.Decode(res, bs, true)
+ if err != nil {
+ return nil, fmt.Errorf("failed to decode buffer: %v", err)
+ }
+ return res[:ndst], nil
+}