mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-01-24 21:42:51 -05:00
core/server: add generic dbus service
- Add QML client with subscribe/introspect/getprop/setprop/call - Add CLI helper `dms notify` that allows async calls with action handlers.
This commit is contained in:
69
core/pkg/dbusutil/variant.go
Normal file
69
core/pkg/dbusutil/variant.go
Normal file
@@ -0,0 +1,69 @@
|
||||
package dbusutil
|
||||
|
||||
import "github.com/godbus/dbus/v5"
|
||||
|
||||
func As[T any](v dbus.Variant) (T, bool) {
|
||||
val, ok := v.Value().(T)
|
||||
return val, ok
|
||||
}
|
||||
|
||||
func AsOr[T any](v dbus.Variant, def T) T {
|
||||
if val, ok := v.Value().(T); ok {
|
||||
return val
|
||||
}
|
||||
return def
|
||||
}
|
||||
|
||||
func Get[T any](m map[string]dbus.Variant, key string) (T, bool) {
|
||||
v, ok := m[key]
|
||||
if !ok {
|
||||
var zero T
|
||||
return zero, false
|
||||
}
|
||||
return As[T](v)
|
||||
}
|
||||
|
||||
func GetOr[T any](m map[string]dbus.Variant, key string, def T) T {
|
||||
v, ok := m[key]
|
||||
if !ok {
|
||||
return def
|
||||
}
|
||||
return AsOr(v, def)
|
||||
}
|
||||
|
||||
func Normalize(v any) any {
|
||||
switch val := v.(type) {
|
||||
case dbus.Variant:
|
||||
return Normalize(val.Value())
|
||||
case dbus.ObjectPath:
|
||||
return string(val)
|
||||
case []dbus.ObjectPath:
|
||||
result := make([]string, len(val))
|
||||
for i, p := range val {
|
||||
result[i] = string(p)
|
||||
}
|
||||
return result
|
||||
case map[string]dbus.Variant:
|
||||
result := make(map[string]any)
|
||||
for k, vv := range val {
|
||||
result[k] = Normalize(vv.Value())
|
||||
}
|
||||
return result
|
||||
case []any:
|
||||
result := make([]any, len(val))
|
||||
for i, item := range val {
|
||||
result[i] = Normalize(item)
|
||||
}
|
||||
return result
|
||||
default:
|
||||
return v
|
||||
}
|
||||
}
|
||||
|
||||
func NormalizeSlice(values []any) []any {
|
||||
result := make([]any, len(values))
|
||||
for i, v := range values {
|
||||
result[i] = Normalize(v)
|
||||
}
|
||||
return result
|
||||
}
|
||||
155
core/pkg/dbusutil/variant_test.go
Normal file
155
core/pkg/dbusutil/variant_test.go
Normal file
@@ -0,0 +1,155 @@
|
||||
package dbusutil
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/godbus/dbus/v5"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestAs(t *testing.T) {
|
||||
t.Run("string", func(t *testing.T) {
|
||||
v := dbus.MakeVariant("hello")
|
||||
val, ok := As[string](v)
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, "hello", val)
|
||||
})
|
||||
|
||||
t.Run("bool", func(t *testing.T) {
|
||||
v := dbus.MakeVariant(true)
|
||||
val, ok := As[bool](v)
|
||||
assert.True(t, ok)
|
||||
assert.True(t, val)
|
||||
})
|
||||
|
||||
t.Run("int32", func(t *testing.T) {
|
||||
v := dbus.MakeVariant(int32(42))
|
||||
val, ok := As[int32](v)
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, int32(42), val)
|
||||
})
|
||||
|
||||
t.Run("wrong type", func(t *testing.T) {
|
||||
v := dbus.MakeVariant("hello")
|
||||
_, ok := As[int](v)
|
||||
assert.False(t, ok)
|
||||
})
|
||||
}
|
||||
|
||||
func TestAsOr(t *testing.T) {
|
||||
t.Run("exists", func(t *testing.T) {
|
||||
v := dbus.MakeVariant("hello")
|
||||
val := AsOr(v, "default")
|
||||
assert.Equal(t, "hello", val)
|
||||
})
|
||||
|
||||
t.Run("wrong type uses default", func(t *testing.T) {
|
||||
v := dbus.MakeVariant(123)
|
||||
val := AsOr(v, "default")
|
||||
assert.Equal(t, "default", val)
|
||||
})
|
||||
}
|
||||
|
||||
func TestGet(t *testing.T) {
|
||||
m := map[string]dbus.Variant{
|
||||
"name": dbus.MakeVariant("test"),
|
||||
"enabled": dbus.MakeVariant(true),
|
||||
"count": dbus.MakeVariant(int32(5)),
|
||||
}
|
||||
|
||||
t.Run("exists", func(t *testing.T) {
|
||||
val, ok := Get[string](m, "name")
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, "test", val)
|
||||
})
|
||||
|
||||
t.Run("missing key", func(t *testing.T) {
|
||||
_, ok := Get[string](m, "missing")
|
||||
assert.False(t, ok)
|
||||
})
|
||||
|
||||
t.Run("wrong type", func(t *testing.T) {
|
||||
_, ok := Get[int](m, "name")
|
||||
assert.False(t, ok)
|
||||
})
|
||||
}
|
||||
|
||||
func TestGetOr(t *testing.T) {
|
||||
m := map[string]dbus.Variant{
|
||||
"name": dbus.MakeVariant("test"),
|
||||
}
|
||||
|
||||
t.Run("exists", func(t *testing.T) {
|
||||
val := GetOr(m, "name", "default")
|
||||
assert.Equal(t, "test", val)
|
||||
})
|
||||
|
||||
t.Run("missing uses default", func(t *testing.T) {
|
||||
val := GetOr(m, "missing", "default")
|
||||
assert.Equal(t, "default", val)
|
||||
})
|
||||
|
||||
t.Run("wrong type uses default", func(t *testing.T) {
|
||||
val := GetOr(m, "name", 42)
|
||||
assert.Equal(t, 42, val)
|
||||
})
|
||||
}
|
||||
|
||||
func TestNormalize(t *testing.T) {
|
||||
t.Run("variant unwrap", func(t *testing.T) {
|
||||
v := dbus.MakeVariant("hello")
|
||||
result := Normalize(v)
|
||||
assert.Equal(t, "hello", result)
|
||||
})
|
||||
|
||||
t.Run("nested variant", func(t *testing.T) {
|
||||
v := dbus.MakeVariant(dbus.MakeVariant("nested"))
|
||||
result := Normalize(v)
|
||||
assert.Equal(t, "nested", result)
|
||||
})
|
||||
|
||||
t.Run("object path", func(t *testing.T) {
|
||||
v := dbus.ObjectPath("/org/test")
|
||||
result := Normalize(v)
|
||||
assert.Equal(t, "/org/test", result)
|
||||
})
|
||||
|
||||
t.Run("object path slice", func(t *testing.T) {
|
||||
v := []dbus.ObjectPath{"/org/a", "/org/b"}
|
||||
result := Normalize(v)
|
||||
assert.Equal(t, []string{"/org/a", "/org/b"}, result)
|
||||
})
|
||||
|
||||
t.Run("variant map", func(t *testing.T) {
|
||||
v := map[string]dbus.Variant{
|
||||
"key": dbus.MakeVariant("value"),
|
||||
}
|
||||
result := Normalize(v)
|
||||
expected := map[string]any{"key": "value"}
|
||||
assert.Equal(t, expected, result)
|
||||
})
|
||||
|
||||
t.Run("any slice", func(t *testing.T) {
|
||||
v := []any{dbus.MakeVariant("a"), dbus.ObjectPath("/b")}
|
||||
result := Normalize(v)
|
||||
expected := []any{"a", "/b"}
|
||||
assert.Equal(t, expected, result)
|
||||
})
|
||||
|
||||
t.Run("passthrough primitives", func(t *testing.T) {
|
||||
assert.Equal(t, "hello", Normalize("hello"))
|
||||
assert.Equal(t, 42, Normalize(42))
|
||||
assert.Equal(t, true, Normalize(true))
|
||||
})
|
||||
}
|
||||
|
||||
func TestNormalizeSlice(t *testing.T) {
|
||||
input := []any{
|
||||
dbus.MakeVariant("a"),
|
||||
dbus.ObjectPath("/b"),
|
||||
"c",
|
||||
}
|
||||
result := NormalizeSlice(input)
|
||||
expected := []any{"a", "/b", "c"}
|
||||
assert.Equal(t, expected, result)
|
||||
}
|
||||
Reference in New Issue
Block a user