...

Source file src/github.com/godbus/dbus/v5/variant.go

Documentation: github.com/godbus/dbus/v5

     1  package dbus
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"reflect"
     7  	"sort"
     8  	"strconv"
     9  )
    10  
    11  // Variant represents the D-Bus variant type.
    12  type Variant struct {
    13  	sig   Signature
    14  	value interface{}
    15  }
    16  
    17  // MakeVariant converts the given value to a Variant. It panics if v cannot be
    18  // represented as a D-Bus type.
    19  func MakeVariant(v interface{}) Variant {
    20  	return MakeVariantWithSignature(v, SignatureOf(v))
    21  }
    22  
    23  // MakeVariantWithSignature converts the given value to a Variant.
    24  func MakeVariantWithSignature(v interface{}, s Signature) Variant {
    25  	return Variant{s, v}
    26  }
    27  
    28  // ParseVariant parses the given string as a variant as described at
    29  // https://developer.gnome.org/glib/stable/gvariant-text.html. If sig is not
    30  // empty, it is taken to be the expected signature for the variant.
    31  func ParseVariant(s string, sig Signature) (Variant, error) {
    32  	tokens := varLex(s)
    33  	p := &varParser{tokens: tokens}
    34  	n, err := varMakeNode(p)
    35  	if err != nil {
    36  		return Variant{}, err
    37  	}
    38  	if sig.str == "" {
    39  		sig, err = varInfer(n)
    40  		if err != nil {
    41  			return Variant{}, err
    42  		}
    43  	}
    44  	v, err := n.Value(sig)
    45  	if err != nil {
    46  		return Variant{}, err
    47  	}
    48  	return MakeVariant(v), nil
    49  }
    50  
    51  // format returns a formatted version of v and whether this string can be parsed
    52  // unambiguously.
    53  func (v Variant) format() (string, bool) {
    54  	switch v.sig.str[0] {
    55  	case 'b', 'i':
    56  		return fmt.Sprint(v.value), true
    57  	case 'n', 'q', 'u', 'x', 't', 'd', 'h':
    58  		return fmt.Sprint(v.value), false
    59  	case 's':
    60  		return strconv.Quote(v.value.(string)), true
    61  	case 'o':
    62  		return strconv.Quote(string(v.value.(ObjectPath))), false
    63  	case 'g':
    64  		return strconv.Quote(v.value.(Signature).str), false
    65  	case 'v':
    66  		s, unamb := v.value.(Variant).format()
    67  		if !unamb {
    68  			return "<@" + v.value.(Variant).sig.str + " " + s + ">", true
    69  		}
    70  		return "<" + s + ">", true
    71  	case 'y':
    72  		return fmt.Sprintf("%#x", v.value.(byte)), false
    73  	}
    74  	rv := reflect.ValueOf(v.value)
    75  	switch rv.Kind() {
    76  	case reflect.Slice:
    77  		if rv.Len() == 0 {
    78  			return "[]", false
    79  		}
    80  		unamb := true
    81  		buf := bytes.NewBuffer([]byte("["))
    82  		for i := 0; i < rv.Len(); i++ {
    83  			// TODO: slooow
    84  			s, b := MakeVariant(rv.Index(i).Interface()).format()
    85  			unamb = unamb && b
    86  			buf.WriteString(s)
    87  			if i != rv.Len()-1 {
    88  				buf.WriteString(", ")
    89  			}
    90  		}
    91  		buf.WriteByte(']')
    92  		return buf.String(), unamb
    93  	case reflect.Map:
    94  		if rv.Len() == 0 {
    95  			return "{}", false
    96  		}
    97  		unamb := true
    98  		var buf bytes.Buffer
    99  		kvs := make([]string, rv.Len())
   100  		for i, k := range rv.MapKeys() {
   101  			s, b := MakeVariant(k.Interface()).format()
   102  			unamb = unamb && b
   103  			buf.Reset()
   104  			buf.WriteString(s)
   105  			buf.WriteString(": ")
   106  			s, b = MakeVariant(rv.MapIndex(k).Interface()).format()
   107  			unamb = unamb && b
   108  			buf.WriteString(s)
   109  			kvs[i] = buf.String()
   110  		}
   111  		buf.Reset()
   112  		buf.WriteByte('{')
   113  		sort.Strings(kvs)
   114  		for i, kv := range kvs {
   115  			if i > 0 {
   116  				buf.WriteString(", ")
   117  			}
   118  			buf.WriteString(kv)
   119  		}
   120  		buf.WriteByte('}')
   121  		return buf.String(), unamb
   122  	}
   123  	return `"INVALID"`, true
   124  }
   125  
   126  // Signature returns the D-Bus signature of the underlying value of v.
   127  func (v Variant) Signature() Signature {
   128  	return v.sig
   129  }
   130  
   131  // String returns the string representation of the underlying value of v as
   132  // described at https://developer.gnome.org/glib/stable/gvariant-text.html.
   133  func (v Variant) String() string {
   134  	s, unamb := v.format()
   135  	if !unamb {
   136  		return "@" + v.sig.str + " " + s
   137  	}
   138  	return s
   139  }
   140  
   141  // Value returns the underlying value of v.
   142  func (v Variant) Value() interface{} {
   143  	return v.value
   144  }
   145  
   146  // Store converts the variant into a native go type using the same
   147  // mechanism as the "Store" function.
   148  func (v Variant) Store(value interface{}) error {
   149  	return storeInterfaces(v.value, value)
   150  }
   151  

View as plain text