github.com/razvanm/vanadium-go-1.3@v0.0.0-20160721203343-4a65068e5915/src/runtime/ppapi/var_nacl.go (about)

     1  // Copyright 2014 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package ppapi
     6  
     7  import (
     8  	"errors"
     9  	"fmt"
    10  	"unsafe"
    11  )
    12  
    13  // Var represents a NaCl value of some kind.  The values include numbers,
    14  // string, objects, arrays, dictionaries, objects, and other resources.
    15  type Var pp_Var // Keep the raw pp_Var representation.
    16  
    17  var (
    18  	errVarNotBool           = errors.New("Var is not a bool")
    19  	errVarNotInt            = errors.New("Var is not an int")
    20  	errVarNotDouble         = errors.New("Var is not a double")
    21  	errVarNotString         = errors.New("Var is not a string")
    22  	errVarNotArrayBuffer    = errors.New("Var is not an array buffer")
    23  	errVarNotResource       = errors.New("Var is not a resource")
    24  	errFailedArrayBufferLen = errors.New("Failed to retrieve array buffer length")
    25  )
    26  
    27  var (
    28  	VarUndefined = varFromTypeAndValue(PP_VARTYPE_UNDEFINED, 0)
    29  	VarNull      = varFromTypeAndValue(PP_VARTYPE_NULL, 0)
    30  )
    31  
    32  func makeVar(vin pp_Var) Var {
    33  	return Var(vin)
    34  }
    35  
    36  func varFromTypeAndValue(t VarType, v int32) Var {
    37  	var pv pp_Var
    38  	*(*int32)(unsafe.Pointer(&pv[0])) = int32(t)
    39  	*(*uint64)(unsafe.Pointer(&pv[8])) = uint64(v)
    40  	return Var(pv)
    41  }
    42  
    43  // VarFromInt creates a variable from an int32.
    44  func VarFromInt(i int32) Var {
    45  	return varFromTypeAndValue(PP_VARTYPE_INT32, i)
    46  }
    47  
    48  // VarFromString creates a variable containing a string.
    49  func VarFromString(s string) Var {
    50  	var v pp_Var
    51  	b := []byte(s)
    52  	// TODO(bprosnitz) This doesn't work with the empty string.
    53  	ppb_var_from_utf8(&v, &b[0], uint32(len(s)))
    54  	return Var(v)
    55  }
    56  
    57  // VarFromByteSlice creates an arraybuffer variable corresponding to a byte slice.
    58  func VarFromByteSlice(b []byte) Var {
    59  	var pv pp_Var
    60  	ppb_vararraybuffer_create(&pv, uint32(len(b)))
    61  	rawBytes := ppb_vararraybuffer_map(pv)
    62  	ptrval := uintptr(unsafe.Pointer(rawBytes))
    63  	for i, val := range b {
    64  		*(*byte)(unsafe.Pointer(ptrval + uintptr(i))) = val
    65  	}
    66  	ppb_vararraybuffer_unmap(pv)
    67  	return Var(pv)
    68  }
    69  
    70  func NewDictVar() Var {
    71  	var pv pp_Var
    72  	ppb_vardictionary_create(&pv)
    73  	return Var(pv)
    74  }
    75  
    76  func (v *Var) fromPP(in pp_Var) {
    77  	*v = Var(in)
    78  }
    79  
    80  func (v Var) toPP(out *pp_Var) {
    81  	*out = pp_Var(v)
    82  	return
    83  }
    84  
    85  func (v Var) toPPVar() (out pp_Var) {
    86  	v.toPP(&out)
    87  	return
    88  }
    89  
    90  // AddRef increments the Var's reference count.
    91  func (v Var) AddRef() {
    92  	ppb_var_add_ref(pp_Var(v))
    93  }
    94  
    95  // Release decrements the Var's reference count.
    96  func (v Var) Release() {
    97  	ppb_var_release(pp_Var(v))
    98  }
    99  
   100  // Type returns the value's type.
   101  func (v Var) Type() VarType {
   102  	return VarType(*(*int32)(unsafe.Pointer(&v[0])))
   103  }
   104  
   105  // IsNull returns true iff the Var is NULL.
   106  func (v Var) IsNull() bool {
   107  	return v.Type() == PP_VARTYPE_NULL
   108  }
   109  
   110  // IsBool returns true iff the Var is a Boolean value.
   111  func (v Var) IsBool() bool {
   112  	return v.Type() == PP_VARTYPE_BOOL
   113  }
   114  
   115  // IsInt returns true iff the Var is of type int.
   116  func (v Var) IsInt() bool {
   117  	return v.Type() == PP_VARTYPE_INT32
   118  }
   119  
   120  // IsDouble returns true iff the Var is of type float64.
   121  func (v Var) IsDouble() bool {
   122  	return v.Type() == PP_VARTYPE_DOUBLE
   123  }
   124  
   125  // IsString returns true iff the Var is a string.
   126  func (v Var) IsString() bool {
   127  	return v.Type() == PP_VARTYPE_STRING
   128  }
   129  
   130  // IsObject returns true iff the Var is an object reference.
   131  func (v Var) IsObject() bool {
   132  	return v.Type() == PP_VARTYPE_OBJECT
   133  }
   134  
   135  // IsArray returns true iff the var is an array.
   136  func (v Var) IsArray() bool {
   137  	return v.Type() == PP_VARTYPE_ARRAY
   138  }
   139  
   140  // IsDictionary returns true iff the var is a dictionary.
   141  func (v Var) IsDictionary() bool {
   142  	return v.Type() == PP_VARTYPE_DICTIONARY
   143  }
   144  
   145  // IsResource returns true iff the var is a Resource.
   146  func (v Var) IsResource() bool {
   147  	return v.Type() == PP_VARTYPE_RESOURCE
   148  }
   149  
   150  // IsArrayBuffer returns true iff the var is an array buffer.
   151  func (v Var) IsArrayBuffer() bool {
   152  	return v.Type() == PP_VARTYPE_ARRAY_BUFFER
   153  }
   154  
   155  // AsBool returns the Boolean value stored in the Var.  Fails if the Var is not
   156  // a Boolean value.
   157  func (v Var) AsBool() (bool, error) {
   158  	if v.IsBool() {
   159  		i := *(*int32)(unsafe.Pointer(&v[8]))
   160  		return i != 0, nil
   161  	}
   162  	return false, errVarNotBool
   163  }
   164  
   165  // AsInt returns the int stored in the Var, or an error if the Var is not an int.
   166  func (v Var) AsInt() (int32, error) {
   167  	if v.IsInt() {
   168  		i := *(*int32)(unsafe.Pointer(&v[8]))
   169  		return i, nil
   170  	}
   171  	return 0, errVarNotInt
   172  }
   173  
   174  // AsDouble returns the double stored in the Var, or an error if the Var is not a double.
   175  func (v Var) AsDouble() (float64, error) {
   176  	if v.IsDouble() {
   177  		x := *(*float64)(unsafe.Pointer(&v[8]))
   178  		return x, nil
   179  	}
   180  	return 0, errVarNotDouble
   181  }
   182  
   183  // AsString returns the string stored in the Var, or an error if the Var is not a string.
   184  func (v Var) AsString() (string, error) {
   185  	if !v.IsString() {
   186  		return "", errVarNotString
   187  	}
   188  	var len uint32
   189  	b := ppb_var_to_utf8(pp_Var(v), &len)
   190  	if b == nil {
   191  		return "", errVarNotString
   192  	}
   193  	s := gostringn(b, int(len))
   194  	return s, nil
   195  }
   196  
   197  // AsByteSlice returns the bytes stored in the Var, or an error if the Var is not an array buffer.
   198  func (v Var) AsByteSlice() ([]byte, error) {
   199  	if v.IsArrayBuffer() {
   200  		var length uint32
   201  		if r := ppb_vararraybuffer_byte_length(pp_Var(v), &length); r != ppTrue {
   202  			return nil, errFailedArrayBufferLen
   203  		}
   204  		ret := make([]byte, length)
   205  		rawBytes := ppb_vararraybuffer_map(pp_Var(v))
   206  		ptrval := uintptr(unsafe.Pointer(rawBytes))
   207  		for i, _ := range ret {
   208  			ret[i] = *(*byte)(unsafe.Pointer(ptrval + uintptr(i)))
   209  		}
   210  		ppb_vararraybuffer_unmap(pp_Var(v))
   211  		return ret, nil
   212  	}
   213  	return nil, errVarNotArrayBuffer
   214  }
   215  
   216  // AsResource returns the Resource stored in the Var, or an error if the Var is not a Resource.
   217  func (v Var) AsResource() (Resource, error) {
   218  	if v.IsResource() {
   219  		r := makeResource(pp_Resource(*(*int32)(unsafe.Pointer(&v[8]))))
   220  		return r, nil
   221  	}
   222  	return Resource{}, errVarNotResource
   223  }
   224  
   225  // GetKeys returns a slice of the dictionary keys.
   226  func (v Var) GetKeys() ([]string, error) {
   227  	var array pp_Var
   228  	ppb_vardictionary_get_keys(&array, pp_Var(v))
   229  	length := ppb_vararray_get_length(array)
   230  	ret := make([]string, length)
   231  	for i := uint32(0); i < length; i++ {
   232  		var val pp_Var
   233  		ppb_vararray_get(&val, array, i)
   234  		var err error
   235  		ret[i], err = Var(val).AsString()
   236  		if err != nil {
   237  			return nil, err
   238  		}
   239  	}
   240  	return ret, nil
   241  }
   242  
   243  func (v Var) DictionarySet(key string, val Var) error {
   244  	keyVar := VarFromString(key)
   245  	defer keyVar.Release()
   246  	result := ppb_vardictionary_set(pp_Var(v), pp_Var(keyVar), pp_Var(val))
   247  	if result != ppTrue {
   248  		return fmt.Errorf("Error setting dictionary value")
   249  	}
   250  	return nil
   251  }
   252  
   253  // LookupKey looks up a key if var is a dictionary.
   254  func (v Var) LookupKey(key string) (Var, error) {
   255  	keyVar := VarFromString(key)
   256  	defer keyVar.Release()
   257  	hasKey := ppb_vardictionary_has_key(pp_Var(v), pp_Var(keyVar))
   258  	if hasKey != ppTrue {
   259  		return Var{}, fmt.Errorf("Key %q not found", key)
   260  	}
   261  	var pval pp_Var
   262  	ppb_vardictionary_get(&pval, pp_Var(v), pp_Var(keyVar))
   263  	return Var(pval), nil
   264  }
   265  
   266  // LookupKey looks up a key if var is a dictionary and converts it to a string.
   267  func (v Var) LookupStringValuedKey(key string) (string, error) {
   268  	val, err := v.LookupKey(key)
   269  	if err != nil {
   270  		return "", err
   271  	}
   272  	str, err := val.AsString()
   273  	if err != nil {
   274  		val.Release()
   275  		return "", err
   276  	}
   277  	val.Release()
   278  	return str, nil
   279  }
   280  
   281  // LookupKey looks up a key if var is a dictionary and converts it to an int.
   282  func (v Var) LookupIntValuedKey(key string) (int, error) {
   283  	val, err := v.LookupKey(key)
   284  	if err != nil {
   285  		return 0, err
   286  	}
   287  	i, err := val.AsInt()
   288  	if err != nil {
   289  		val.Release()
   290  		return 0, err
   291  	}
   292  	val.Release()
   293  	return int(i), nil
   294  }