74 lines
2.5 KiB
Go
74 lines
2.5 KiB
Go
// Package kept holds what the layouts of the Delivery domain's kept values share: the version check on reading one, the
|
|
// rule a name must keep to be a key part, and the form of a digest. It names no seat and no module (ADR 0634 §2). The
|
|
// version itself (keys.Version) and the escaping of a name (keys.EscapeName) are mesh-sdk's, since more than one domain uses
|
|
// them.
|
|
package kept
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"regexp"
|
|
|
|
"git.novox.be/novox/mesh-sdk/go/keys"
|
|
)
|
|
|
|
// ErrUnknownVersion is what Decode returns for a value whose version is missing or not keys.Version. Test it with errors.Is.
|
|
var ErrUnknownVersion = errors.New("kept: unknown value version")
|
|
|
|
var nameOK = regexp.MustCompile(`^[-/_=a-zA-Z0-9]+$`)
|
|
|
|
// CheckName refuses a name that is empty or holds a dot, a wildcard, whitespace or a character a bus key refuses.
|
|
func CheckName(kind, name string) error {
|
|
if name == "" {
|
|
return fmt.Errorf("kept: the %s name is empty", kind)
|
|
}
|
|
if !nameOK.MatchString(name) {
|
|
return fmt.Errorf("kept: the %s name %q holds a dot, a wildcard, whitespace or a character a key refuses", kind, name)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
var hex64 = regexp.MustCompile(`^[0-9a-f]{64}$`)
|
|
|
|
// IsHex64 says whether s is 64 lowercase hex digits.
|
|
func IsHex64(s string) bool { return hex64.MatchString(s) }
|
|
|
|
// CheckVersion refuses a value with no version or one this reader does not read.
|
|
func CheckVersion(data []byte) error {
|
|
var probe struct {
|
|
V *int `json:"v"`
|
|
}
|
|
if err := json.Unmarshal(data, &probe); err != nil {
|
|
return fmt.Errorf("kept: value is not JSON: %w", err)
|
|
}
|
|
if probe.V == nil {
|
|
return fmt.Errorf("%w: no version in the value, this reader reads %d", ErrUnknownVersion, keys.Version)
|
|
}
|
|
if *probe.V != keys.Version {
|
|
return fmt.Errorf("%w: the value is version %d, this reader reads %d", ErrUnknownVersion, *probe.V, keys.Version)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// Decode reads data into into after CheckVersion.
|
|
func Decode(data []byte, into any) error {
|
|
if err := CheckVersion(data); err != nil {
|
|
return err
|
|
}
|
|
if err := json.Unmarshal(data, into); err != nil {
|
|
return fmt.Errorf("kept: value does not fit its shape: %w", err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
var digestForm = regexp.MustCompile(`^sha256:[0-9a-f]{64}$`)
|
|
|
|
// CheckDigest refuses a digest that is not sha256:<64 lowercase hex digits>, saying what it is of.
|
|
func CheckDigest(digest, of string) error {
|
|
if !digestForm.MatchString(digest) {
|
|
return fmt.Errorf("kept: %s %q is not sha256:<64 lowercase hex digits>", of, digest)
|
|
}
|
|
return nil
|
|
}
|