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 }