aboutsummaryrefslogtreecommitdiffhomepage
path: root/hst
diff options
context:
space:
mode:
authorOphestra <cat@gensokyo.uk>2025-08-15 04:57:37 +0900
committerOphestra <cat@gensokyo.uk>2025-08-15 05:16:51 +0900
commit4ffeec3004607b76f73e504da220a1490c598348 (patch)
tree68cca16c22814b13974db0f19c151f8eb31e2dae /hst
parent9ed3ba85eaba4bc4bd12b290dc4daf00ffe159dc (diff)
hst/enablement: editor friendly enablement adaptor
Having the bit field value here (in decimal, no less) is unfriendly to text editors. Use a bunch of booleans here to improve ease of use. Signed-off-by: Ophestra <cat@gensokyo.uk>
Diffstat (limited to 'hst')
-rw-r--r--hst/config.go3
-rw-r--r--hst/enablement.go69
-rw-r--r--hst/enablement_test.go108
-rw-r--r--hst/template.go2
-rw-r--r--hst/template_test.go6
5 files changed, 184 insertions, 4 deletions
diff --git a/hst/config.go b/hst/config.go
index c34ecb1e..44d36380 100644
--- a/hst/config.go
+++ b/hst/config.go
@@ -3,7 +3,6 @@ package hst
import (
"hakurei.app/container"
- "hakurei.app/system"
"hakurei.app/system/dbus"
)
@@ -24,7 +23,7 @@ type Config struct {
Args []string `json:"args"`
// system services to make available in the container
- Enablements system.Enablement `json:"enablements"`
+ Enablements *Enablements `json:"enablements,omitempty"`
// session D-Bus proxy configuration;
// nil makes session bus proxy assume built-in defaults
diff --git a/hst/enablement.go b/hst/enablement.go
new file mode 100644
index 00000000..021288b3
--- /dev/null
+++ b/hst/enablement.go
@@ -0,0 +1,69 @@
+package hst
+
+import (
+ "encoding/json"
+ "syscall"
+
+ "hakurei.app/system"
+)
+
+// NewEnablements returns the address of [system.Enablement] as [Enablements].
+func NewEnablements(e system.Enablement) *Enablements { return (*Enablements)(&e) }
+
+// enablementsJSON is the [json] representation of the [system.Enablement] bit field.
+type enablementsJSON struct {
+ Wayland bool `json:"wayland,omitempty"`
+ X11 bool `json:"x11,omitempty"`
+ DBus bool `json:"dbus,omitempty"`
+ Pulse bool `json:"pulse,omitempty"`
+}
+
+// Enablements is the [json] adapter for [system.Enablement].
+type Enablements system.Enablement
+
+// Unwrap returns the underlying [system.Enablement].
+func (e *Enablements) Unwrap() system.Enablement {
+ if e == nil {
+ return 0
+ }
+ return system.Enablement(*e)
+}
+
+func (e *Enablements) MarshalJSON() ([]byte, error) {
+ if e == nil {
+ return nil, syscall.EINVAL
+ }
+ return json.Marshal(&enablementsJSON{
+ Wayland: system.Enablement(*e)&system.EWayland != 0,
+ X11: system.Enablement(*e)&system.EX11 != 0,
+ DBus: system.Enablement(*e)&system.EDBus != 0,
+ Pulse: system.Enablement(*e)&system.EPulse != 0,
+ })
+}
+
+func (e *Enablements) UnmarshalJSON(data []byte) error {
+ if e == nil {
+ return syscall.EINVAL
+ }
+
+ v := new(enablementsJSON)
+ if err := json.Unmarshal(data, &v); err != nil {
+ return err
+ }
+
+ var ve system.Enablement
+ if v.Wayland {
+ ve |= system.EWayland
+ }
+ if v.X11 {
+ ve |= system.EX11
+ }
+ if v.DBus {
+ ve |= system.EDBus
+ }
+ if v.Pulse {
+ ve |= system.EPulse
+ }
+ *e = Enablements(ve)
+ return nil
+}
diff --git a/hst/enablement_test.go b/hst/enablement_test.go
new file mode 100644
index 00000000..c132dd37
--- /dev/null
+++ b/hst/enablement_test.go
@@ -0,0 +1,108 @@
+package hst_test
+
+import (
+ "encoding/json"
+ "errors"
+ "syscall"
+ "testing"
+
+ "hakurei.app/hst"
+ "hakurei.app/system"
+)
+
+func TestEnablements(t *testing.T) {
+ testCases := []struct {
+ name string
+ e *hst.Enablements
+ data string
+ sData string
+ }{
+ {"nil", nil, "null", `{"value":null,"magic":3236757504}`},
+ {"zero", hst.NewEnablements(0), `{}`, `{"value":{},"magic":3236757504}`},
+ {"wayland", hst.NewEnablements(system.EWayland), `{"wayland":true}`, `{"value":{"wayland":true},"magic":3236757504}`},
+ {"x11", hst.NewEnablements(system.EX11), `{"x11":true}`, `{"value":{"x11":true},"magic":3236757504}`},
+ {"dbus", hst.NewEnablements(system.EDBus), `{"dbus":true}`, `{"value":{"dbus":true},"magic":3236757504}`},
+ {"pulse", hst.NewEnablements(system.EPulse), `{"pulse":true}`, `{"value":{"pulse":true},"magic":3236757504}`},
+ {"all", hst.NewEnablements(system.EWayland | system.EX11 | system.EDBus | system.EPulse), `{"wayland":true,"x11":true,"dbus":true,"pulse":true}`, `{"value":{"wayland":true,"x11":true,"dbus":true,"pulse":true},"magic":3236757504}`},
+ }
+
+ for _, tc := range testCases {
+ t.Run(tc.name, func(t *testing.T) {
+ t.Run("marshal", func(t *testing.T) {
+ if got, err := json.Marshal(tc.e); err != nil {
+ t.Fatalf("Marshal: error = %v", err)
+ } else if string(got) != tc.data {
+ t.Errorf("Marshal:\n%s, want\n%s", string(got), tc.data)
+ }
+
+ if got, err := json.Marshal(struct {
+ Value *hst.Enablements `json:"value"`
+ Magic int `json:"magic"`
+ }{tc.e, syscall.MS_MGC_VAL}); err != nil {
+ t.Fatalf("Marshal: error = %v", err)
+ } else if string(got) != tc.sData {
+ t.Errorf("Marshal:\n%s, want\n%s", string(got), tc.sData)
+ }
+ })
+
+ t.Run("unmarshal", func(t *testing.T) {
+ {
+ got := new(hst.Enablements)
+ if err := json.Unmarshal([]byte(tc.data), &got); err != nil {
+ t.Fatalf("Unmarshal: error = %v", err)
+ }
+ if tc.e == nil {
+ if got != nil {
+ t.Errorf("Unmarshal: %v", got)
+ }
+ } else if *got != *tc.e {
+ t.Errorf("Unmarshal: %v, want %v", got, tc.e)
+ }
+ }
+
+ {
+ got := *(new(struct {
+ Value *hst.Enablements `json:"value"`
+ Magic int `json:"magic"`
+ }))
+ if err := json.Unmarshal([]byte(tc.sData), &got); err != nil {
+ t.Fatalf("Unmarshal: error = %v", err)
+ }
+ if tc.e == nil {
+ if got.Value != nil {
+ t.Errorf("Unmarshal: %v", got)
+ }
+ } else if *got.Value != *tc.e {
+ t.Errorf("Unmarshal: %v, want %v", got.Value, tc.e)
+ }
+ }
+ })
+ })
+ }
+
+ t.Run("unwrap", func(t *testing.T) {
+ t.Run("nil", func(t *testing.T) {
+ if got := (*hst.Enablements)(nil).Unwrap(); got != 0 {
+ t.Errorf("Unwrap: %v", got)
+ }
+ })
+
+ t.Run("val", func(t *testing.T) {
+ if got := hst.NewEnablements(system.EWayland | system.EPulse).Unwrap(); got != system.EWayland|system.EPulse {
+ t.Errorf("Unwrap: %v", got)
+ }
+ })
+ })
+
+ t.Run("passthrough", func(t *testing.T) {
+ if _, err := (*hst.Enablements)(nil).MarshalJSON(); !errors.Is(err, syscall.EINVAL) {
+ t.Errorf("MarshalJSON: error = %v", err)
+ }
+ if err := (*hst.Enablements)(nil).UnmarshalJSON(nil); !errors.Is(err, syscall.EINVAL) {
+ t.Errorf("UnmarshalJSON: error = %v", err)
+ }
+ if err := new(hst.Enablements).UnmarshalJSON([]byte{}); err == nil {
+ t.Errorf("UnmarshalJSON: error = %v", err)
+ }
+ })
+}
diff --git a/hst/template.go b/hst/template.go
index 82e0b7d9..ea27fbb4 100644
--- a/hst/template.go
+++ b/hst/template.go
@@ -21,7 +21,7 @@ func Template() *Config {
"--ozone-platform=wayland",
},
- Enablements: system.EWayland | system.EDBus | system.EPulse,
+ Enablements: NewEnablements(system.EWayland | system.EDBus | system.EPulse),
SessionBus: &dbus.Config{
See: nil,
diff --git a/hst/template_test.go b/hst/template_test.go
index 76933783..31b9013e 100644
--- a/hst/template_test.go
+++ b/hst/template_test.go
@@ -18,7 +18,11 @@ func TestTemplate(t *testing.T) {
"--enable-features=UseOzonePlatform",
"--ozone-platform=wayland"
],
- "enablements": 13,
+ "enablements": {
+ "wayland": true,
+ "dbus": true,
+ "pulse": true
+ },
"session_bus": {
"see": null,
"talk": [