From d08a1081bd8131a2708f4cb934f060760371d114 Mon Sep 17 00:00:00 2001 From: Ophestra Date: Fri, 28 Nov 2025 01:25:18 +0900 Subject: [PATCH] internal/pipewire: do not store spa_dict fields This is effectively a poor man's slice, it is entirely unnecessary here and can be handled internally. Signed-off-by: Ophestra --- internal/pipewire/client_test.go | 16 +++++++-------- internal/pipewire/core_test.go | 8 ++++---- internal/pipewire/pod.go | 34 +++++++++++++++----------------- 3 files changed, 28 insertions(+), 30 deletions(-) diff --git a/internal/pipewire/client_test.go b/internal/pipewire/client_test.go index 5ba2ff9..ffdffb2 100644 --- a/internal/pipewire/client_test.go +++ b/internal/pipewire/client_test.go @@ -13,7 +13,7 @@ func TestClientInfo(t *testing.T) { {"sample", samplePWContainer[1][2][1], pipewire.ClientInfo{ ID: 34, ChangeMask: pipewire.PW_CLIENT_CHANGE_MASK_PROPS, - Props: &pipewire.SPADict{NItems: 9, Items: []pipewire.SPADictItem{ + Props: &pipewire.SPADict{ {Key: "pipewire.protocol", Value: "protocol-native"}, {Key: "core.name", Value: "pipewire-0"}, {Key: "pipewire.sec.socket", Value: "pipewire-0-manager"}, @@ -23,12 +23,12 @@ func TestClientInfo(t *testing.T) { {Key: "module.id", Value: "2"}, {Key: "object.id", Value: "34"}, {Key: "object.serial", Value: "34"}, - }}}, nil}, + }}, nil}, {"sample*", samplePWContainer[1][3][1], pipewire.ClientInfo{ ID: 34, ChangeMask: pipewire.PW_CLIENT_CHANGE_MASK_PROPS, - Props: &pipewire.SPADict{NItems: 38, Items: []pipewire.SPADictItem{ + Props: &pipewire.SPADict{ {Key: "pipewire.protocol", Value: "protocol-native"}, {Key: "core.name", Value: "pipewire-alice-1443"}, {Key: "pipewire.sec.socket", Value: "pipewire-0-manager"}, @@ -67,12 +67,12 @@ func TestClientInfo(t *testing.T) { {Key: "settings.check-quantum", Value: "false"}, {Key: "settings.check-rate", Value: "false"}, {Key: "core.version", Value: "1.4.7"}, - }}}, nil}, + }}, nil}, {"sample**", samplePWContainer[1][4][1], pipewire.ClientInfo{ ID: 34, ChangeMask: pipewire.PW_CLIENT_CHANGE_MASK_PROPS, - Props: &pipewire.SPADict{NItems: 39, Items: []pipewire.SPADictItem{ + Props: &pipewire.SPADict{ {Key: "pipewire.protocol", Value: "protocol-native"}, {Key: "core.name", Value: "pipewire-alice-1443"}, {Key: "pipewire.sec.socket", Value: "pipewire-0-manager"}, @@ -112,7 +112,7 @@ func TestClientInfo(t *testing.T) { {Key: "settings.check-rate", Value: "false"}, {Key: "core.version", Value: "1.4.7"}, {Key: "pipewire.access", Value: "unrestricted"}, - }}}, nil}, + }}, nil}, }.run(t) } @@ -120,7 +120,7 @@ func TestClientUpdateProperties(t *testing.T) { t.Parallel() encodingTestCases[pipewire.ClientUpdateProperties, *pipewire.ClientUpdateProperties]{ - {"sample", samplePWContainer[0][1][1], pipewire.ClientUpdateProperties{Props: &pipewire.SPADict{NItems: 0x1e, Items: []pipewire.SPADictItem{ + {"sample", samplePWContainer[0][1][1], pipewire.ClientUpdateProperties{Props: &pipewire.SPADict{ {Key: "remote.intention", Value: "manager"}, {Key: "application.name", Value: "pw-container"}, {Key: "application.process.binary", Value: "pw-container"}, @@ -151,6 +151,6 @@ func TestClientUpdateProperties(t *testing.T) { {Key: "settings.check-rate", Value: "false"}, {Key: "core.version", Value: "1.4.7"}, {Key: "core.name", Value: "pipewire-alice-1443"}, - }}}, nil}, + }}, nil}, }.run(t) } diff --git a/internal/pipewire/core_test.go b/internal/pipewire/core_test.go index 5b2f6c2..05f19eb 100644 --- a/internal/pipewire/core_test.go +++ b/internal/pipewire/core_test.go @@ -34,7 +34,7 @@ func TestCoreInfo(t *testing.T) { Version: "1.4.7", Name: "pipewire-0", ChangeMask: pipewire.PW_CORE_CHANGE_MASK_PROPS, - Props: &pipewire.SPADict{NItems: 31, Items: []pipewire.SPADictItem{ + Props: &pipewire.SPADict{ {Key: "config.name", Value: "pipewire.conf"}, {Key: "application.name", Value: "pipewire"}, {Key: "application.process.binary", Value: "pipewire"}, @@ -66,7 +66,7 @@ func TestCoreInfo(t *testing.T) { {Key: "settings.check-rate", Value: "false"}, {Key: "object.id", Value: "0"}, {Key: "object.serial", Value: "0"}}, - }}, nil}, + }, nil}, }.run(t) } @@ -88,7 +88,7 @@ func TestCoreBoundProps(t *testing.T) { {"sample", samplePWContainer[1][1][1], pipewire.CoreBoundProps{ ID: pipewire.PW_ID_CLIENT, GlobalID: 34, - Props: &pipewire.SPADict{NItems: 7, Items: []pipewire.SPADictItem{ + Props: &pipewire.SPADict{ {Key: "object.serial", Value: "34"}, {Key: "module.id", Value: "2"}, {Key: "pipewire.protocol", Value: "protocol-native"}, @@ -96,7 +96,7 @@ func TestCoreBoundProps(t *testing.T) { {Key: "pipewire.sec.uid", Value: "1000"}, {Key: "pipewire.sec.gid", Value: "100"}, {Key: "pipewire.sec.socket", Value: "pipewire-0-manager"}}, - }}, nil}, + }, nil}, }.run(t) } diff --git a/internal/pipewire/pod.go b/internal/pipewire/pod.go index 2e04f44..42055e1 100644 --- a/internal/pipewire/pod.go +++ b/internal/pipewire/pod.go @@ -456,14 +456,11 @@ func (f *Footer[T]) MarshalBinary() ([]byte, error) { return Marshal(f) } // UnmarshalBinary satisfies [encoding.BinaryUnmarshaler] via [Unmarshal]. func (f *Footer[T]) UnmarshalBinary(data []byte) error { return Unmarshal(data, f) } -// SPADictItem is an encoding-compatible representation of spa_dict_item. +// SPADictItem represents spa_dict_item. type SPADictItem struct{ Key, Value string } -// SPADict is an encoding-compatible representation of spa_dict. -type SPADict struct { - NItems Int - Items []SPADictItem -} +// SPADict represents spa_dict. +type SPADict []SPADictItem // Size satisfies [KnownSize] with a value computed at runtime. func (d *SPADict) Size() Word { @@ -473,9 +470,9 @@ func (d *SPADict) Size() Word { // struct prefix, NItems value size := SizePrefix + int(Size(SizeInt)) - for i := range d.Items { - size += SizeString[int](d.Items[i].Key) - size += SizeString[int](d.Items[i].Value) + for i := range *d { + size += SizeString[int]((*d)[i].Key) + size += SizeString[int]((*d)[i].Value) } return Word(size) } @@ -484,14 +481,14 @@ func (d *SPADict) Size() Word { func (d *SPADict) MarshalPOD(data []byte) ([]byte, error) { return appendInner(data, func(dataPrefix []byte) (data []byte, err error) { data = binary.NativeEndian.AppendUint32(dataPrefix, SPA_TYPE_Struct) - if data, err = MarshalAppend(data, d.NItems); err != nil { + if data, err = MarshalAppend(data, Int(len(*d))); err != nil { return } - for i := range d.Items { - if data, err = MarshalAppend(data, d.Items[i].Key); err != nil { + for i := range *d { + if data, err = MarshalAppend(data, (*d)[i].Key); err != nil { return } - if data, err = MarshalAppend(data, d.Items[i].Value); err != nil { + if data, err = MarshalAppend(data, (*d)[i].Value); err != nil { return } } @@ -508,22 +505,23 @@ func (d *SPADict) UnmarshalPOD(data []byte) (Word, error) { // bounds check completed in successful call to unmarshalCheckTypeBounds data = data[:wireSize] - if size, err := UnmarshalNext(data, &d.NItems); err != nil { + var count Int + if size, err := UnmarshalNext(data, &count); err != nil { return wireSize, err } else { // bounds check completed in successful call to Unmarshal data = data[size:] } - d.Items = make([]SPADictItem, d.NItems) - for i := range d.Items { - if size, err := UnmarshalNext(data, &d.Items[i].Key); err != nil { + *d = make([]SPADictItem, count) + for i := range *d { + if size, err := UnmarshalNext(data, &(*d)[i].Key); err != nil { return wireSize, err } else { // bounds check completed in successful call to Unmarshal data = data[size:] } - if size, err := UnmarshalNext(data, &d.Items[i].Value); err != nil { + if size, err := UnmarshalNext(data, &(*d)[i].Value); err != nil { return wireSize, err } else { // bounds check completed in successful call to Unmarshal