diff options
| author | Ophestra <cat@gensokyo.uk> | 2025-07-02 21:52:07 +0900 |
|---|---|---|
| committer | Ophestra <cat@gensokyo.uk> | 2025-07-02 21:52:07 +0900 |
| commit | 82561d62b66f17c05604e87f18187bb3a91f00d2 (patch) | |
| tree | c1543f85b4458b7d5cb2cf7b1baa9dee318debfe /dbus/address.go | |
| parent | eec021cc4b4eb42bc9c8311755826828bfba1996 (diff) | |
system: move system access packages
These packages loosely belong in the "system" package and "system" provides high level wrappers for all of them.
Signed-off-by: Ophestra <cat@gensokyo.uk>
Diffstat (limited to 'dbus/address.go')
| -rw-r--r-- | dbus/address.go | 186 |
1 files changed, 0 insertions, 186 deletions
diff --git a/dbus/address.go b/dbus/address.go deleted file mode 100644 index bec49e62..00000000 --- a/dbus/address.go +++ /dev/null @@ -1,186 +0,0 @@ -package dbus - -import ( - "bytes" - "encoding/hex" - "errors" - "fmt" - "slices" -) - -type AddrEntry struct { - Method string `json:"method"` - Values [][2]string `json:"values"` -} - -// Parse parses D-Bus address according to -// https://dbus.freedesktop.org/doc/dbus-specification.html#addresses -func Parse(addr []byte) ([]AddrEntry, error) { - // Look for a semicolon - address := bytes.Split(bytes.TrimSuffix(addr, []byte{';'}), []byte{';'}) - - // Allocate for entries - v := make([]AddrEntry, len(address)) - - for i, s := range address { - var pairs [][]byte - - // Look for the colon : - if method, list, ok := bytes.Cut(s, []byte{':'}); !ok { - return v, &BadAddressError{ErrNoColon, i, s, -1, nil} - } else { - pairs = bytes.Split(list, []byte{','}) - v[i].Method = string(method) - v[i].Values = make([][2]string, len(pairs)) - } - - for j, pair := range pairs { - key, value, ok := bytes.Cut(pair, []byte{'='}) - if !ok { - return v, &BadAddressError{ErrBadPairSep, i, s, j, pair} - } - if len(key) == 0 { - return v, &BadAddressError{ErrBadPairKey, i, s, j, pair} - } - if len(value) == 0 { - return v, &BadAddressError{ErrBadPairVal, i, s, j, pair} - } - v[i].Values[j][0] = string(key) - - if val, errno := unescapeValue(value); errno != errSuccess { - return v, &BadAddressError{errno, i, s, j, pair} - } else { - v[i].Values[j][1] = string(val) - } - } - } - - return v, nil -} - -func unescapeValue(v []byte) (val []byte, errno ParseError) { - if l := len(v) - (bytes.Count(v, []byte{'%'}) * 2); l < 0 { - errno = ErrBadValLength - return - } else { - val = make([]byte, l) - } - - var i, skip int - for iu, b := range v { - if skip > 0 { - skip-- - continue - } - - if ib := bytes.IndexByte([]byte("-_/.\\*"), b); ib != -1 { // - // _/.\* - goto opt - } else if b >= '0' && b <= '9' { // 0-9 - goto opt - } else if b >= 'A' && b <= 'Z' { // A-Z - goto opt - } else if b >= 'a' && b <= 'z' { // a-z - goto opt - } - - if b != '%' { - errno = ErrBadValByte - break - } - - skip += 2 - if iu+2 >= len(v) { - errno = ErrBadValHexLength - break - } - if c, err := hex.Decode(val[i:i+1], v[iu+1:iu+3]); err != nil { - if errors.As(err, new(hex.InvalidByteError)) { - errno = ErrBadValHexByte - break - } - // unreachable - panic(err.Error()) - } else if c != 1 { - // unreachable - panic(fmt.Sprintf("invalid decode length %d", c)) - } - i++ - continue - - opt: - val[i] = b - i++ - } - - return -} - -type ParseError uint8 - -func (e ParseError) Error() string { - switch e { - case errSuccess: - panic("attempted to return success as error") - case ErrNoColon: - return "address does not contain a colon" - case ErrBadPairSep: - return "'=' character not found" - case ErrBadPairKey: - return "'=' character has no key preceding it" - case ErrBadPairVal: - return "'=' character has no value following it" - case ErrBadValLength: - return "unescaped value has impossible length" - case ErrBadValByte: - return "in D-Bus address, characters other than [-0-9A-Za-z_/.\\*] should have been escaped" - case ErrBadValHexLength: - return "in D-Bus address, percent character was not followed by two hex digits" - case ErrBadValHexByte: - return "in D-Bus address, percent character was followed by characters other than hex digits" - - default: - return fmt.Sprintf("parse error %d", e) - } -} - -const ( - errSuccess ParseError = iota - ErrNoColon - ErrBadPairSep - ErrBadPairKey - ErrBadPairVal - ErrBadValLength - ErrBadValByte - ErrBadValHexLength - ErrBadValHexByte -) - -type BadAddressError struct { - // error type - Type ParseError - - // bad entry position - EntryPos int - // bad entry value - EntryVal []byte - - // bad pair position - PairPos int - // bad pair value - PairVal []byte -} - -func (a *BadAddressError) Is(err error) bool { - var b *BadAddressError - return errors.As(err, &b) && a.Type == b.Type && - a.EntryPos == b.EntryPos && slices.Equal(a.EntryVal, b.EntryVal) && - a.PairPos == b.PairPos && slices.Equal(a.PairVal, b.PairVal) -} - -func (a *BadAddressError) Error() string { - return a.Type.Error() -} - -func (a *BadAddressError) Unwrap() error { - return a.Type -} |
