aboutsummaryrefslogtreecommitdiffhomepage
path: root/internal/app/state/data.go
diff options
context:
space:
mode:
authorOphestra <cat@gensokyo.uk>2025-10-26 01:49:14 +0900
committerOphestra <cat@gensokyo.uk>2025-10-26 01:49:14 +0900
commit86f4219062ae4787ac9478b025abf8416e5593a2 (patch)
tree6585322aa8f8234c42b355982c6dd66917220600 /internal/app/state/data.go
parentfe2929d5f7249f8593923446e1c327bf503cc8a0 (diff)
internal/app/state/data: check full entry behaviour
This eventually gets relocated to internal/app. Signed-off-by: Ophestra <cat@gensokyo.uk>
Diffstat (limited to 'internal/app/state/data.go')
-rw-r--r--internal/app/state/data.go43
1 files changed, 43 insertions, 0 deletions
diff --git a/internal/app/state/data.go b/internal/app/state/data.go
new file mode 100644
index 00000000..3c289f94
--- /dev/null
+++ b/internal/app/state/data.go
@@ -0,0 +1,43 @@
+package state
+
+import (
+ "encoding/gob"
+ "fmt"
+ "io"
+ "os"
+
+ "hakurei.app/hst"
+)
+
+// entryEncode encodes [hst.State] into [io.Writer] with the state entry header.
+// entryEncode does not validate the embedded [hst.Config] value.
+//
+// A non-nil error returned by entryEncode is of type [hst.AppError].
+func entryEncode(w io.Writer, s *hst.State) error {
+ if err := entryWriteHeader(w, s.Enablements.Unwrap()); err != nil {
+ return &hst.AppError{Step: "encode state header", Err: err}
+ } else if err = gob.NewEncoder(w).Encode(s); err != nil {
+ return &hst.AppError{Step: "encode state body", Err: err}
+ } else {
+ return nil
+ }
+}
+
+// entryDecode decodes [hst.State] from [io.Reader] and stores the result in the value pointed to by p.
+// entryDecode validates the embedded [hst.Config] value.
+//
+// A non-nil error returned by entryDecode is of type [hst.AppError].
+func entryDecode(r io.Reader, p *hst.State) error {
+ if et, err := entryReadHeader(r); err != nil {
+ return &hst.AppError{Step: "decode state header", Err: err}
+ } else if err = gob.NewDecoder(r).Decode(&p); err != nil {
+ return &hst.AppError{Step: "decode state body", Err: err}
+ } else if err = p.Config.Validate(); err != nil {
+ return err
+ } else if p.Enablements.Unwrap() != et {
+ return &hst.AppError{Step: "validate state enablement", Err: os.ErrInvalid,
+ Msg: fmt.Sprintf("state entry %s has unexpected enablement byte %#x, %#x", p.ID.String(), byte(p.Enablements.Unwrap()), byte(et))}
+ } else {
+ return nil
+ }
+}