aboutsummaryrefslogtreecommitdiffhomepage
path: root/internal/store/data.go
blob: 00a23443f0e5ca656c959165ac6a72d9934128fc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
package store

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
	}
}

// entryDecodeHeader calls entryReadHeader, returning [hst.AppError] for a non-nil error.
func entryDecodeHeader(r io.Reader) (hst.Enablement, error) {
	if et, err := entryReadHeader(r); err != nil {
		return 0, &hst.AppError{Step: "decode state header", Err: err}
	} else {
		return et, 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) (hst.Enablement, error) {
	if et, err := entryDecodeHeader(r); err != nil {
		return et, err
	} else if err = gob.NewDecoder(r).Decode(&p); err != nil {
		return et, &hst.AppError{Step: "decode state body", Err: err}
	} else if err = p.Config.Validate(hst.VAllowInsecure); err != nil {
		return et, err
	} else if p.Enablements.Unwrap() != et {
		return et, &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 et, nil
	}
}