internal/pipewire: implement spa_dict type
All checks were successful
Test / Create distribution (push) Successful in 40s
Test / Sandbox (push) Successful in 2m33s
Test / Hakurei (push) Successful in 3m22s
Test / Hpkg (push) Successful in 4m18s
Test / Sandbox (race detector) (push) Successful in 4m35s
Test / Hakurei (race detector) (push) Successful in 5m18s
Test / Flake checks (push) Successful in 1m26s

This is a terrible type that defies the type system. It is implemented on the concrete type to avoid special cases.

Signed-off-by: Ophestra <cat@gensokyo.uk>
This commit is contained in:
Ophestra 2025-11-25 04:08:52 +09:00
parent 8f4a3bcf9f
commit e51e81bb22
Signed by: cat
SSH Key Fingerprint: SHA256:gQ67O0enBZ7UdZypgtspB2FDM1g3GVw8nX0XSdcFw8Q

View File

@ -360,6 +360,74 @@ func unmarshalCheckTypeBounds(data *[]byte, t Word, sizeP *Word) error {
return nil return nil
} }
// SPADictItem is an encoding-compatible representation of 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
}
func (d *SPADict) MarshalPOD() ([]byte, error) {
return appendInner(nil, func(data []byte) ([]byte, error) {
data = binary.NativeEndian.AppendUint32(data, SPA_TYPE_Struct)
if extraData, err := Marshal(d.NItems); err != nil {
return data, err
} else {
data = append(data, extraData...)
}
for i := range d.Items {
if extraData, err := Marshal(d.Items[i].Key); err != nil {
return data, err
} else {
data = append(data, extraData...)
}
if extraData, err := Marshal(d.Items[i].Value); err != nil {
return data, err
} else {
data = append(data, extraData...)
}
}
return data, nil
})
}
func (d *SPADict) UnmarshalPOD(data []byte) (Word, error) {
var wireSize Word
if err := unmarshalCheckTypeBounds(&data, SPA_TYPE_Struct, &wireSize); err != nil {
return wireSize, err
}
if size, err := Unmarshal(data, &d.NItems); 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 := Unmarshal(data, &d.Items[i].Key); err != nil {
return wireSize, err
} else {
// bounds check completed in successful call to Unmarshal
data = data[size:]
}
if size, err := Unmarshal(data, &d.Items[i].Value); err != nil {
return wireSize, err
} else {
// bounds check completed in successful call to Unmarshal
data = data[size:]
}
}
if len(data) != 0 {
return wireSize, &TrailingGarbageError{data}
}
return wireSize, nil
}
/* Pointers */ /* Pointers */
const ( const (
SPA_TYPE_POINTER_START = 0x10000 + iota SPA_TYPE_POINTER_START = 0x10000 + iota