github.com/secoba/wails/v2@v2.6.4/internal/binding/db.go (about) 1 package binding 2 3 import ( 4 "encoding/json" 5 "sort" 6 "sync" 7 "unsafe" 8 ) 9 10 // DB is our database of method bindings 11 type DB struct { 12 // map[packagename] -> map[structname] -> map[methodname]*method 13 store map[string]map[string]map[string]*BoundMethod 14 15 // This uses fully qualified method names as a shortcut for store traversal. 16 // It used for performance gains at runtime 17 methodMap map[string]*BoundMethod 18 19 // This uses ids to reference bound methods at runtime 20 obfuscatedMethodMap map[int]*BoundMethod 21 22 // Lock to ensure sync access to the data 23 lock sync.RWMutex 24 } 25 26 func newDB() *DB { 27 return &DB{ 28 store: make(map[string]map[string]map[string]*BoundMethod), 29 methodMap: make(map[string]*BoundMethod), 30 obfuscatedMethodMap: make(map[int]*BoundMethod), 31 } 32 } 33 34 // GetMethodFromStore returns the method for the given package/struct/method names 35 // nil is returned if any one of those does not exist 36 func (d *DB) GetMethodFromStore(packageName string, structName string, methodName string) *BoundMethod { 37 // Lock the db whilst processing and unlock on return 38 d.lock.RLock() 39 defer d.lock.RUnlock() 40 41 structMap, exists := d.store[packageName] 42 if !exists { 43 return nil 44 } 45 methodMap, exists := structMap[structName] 46 if !exists { 47 return nil 48 } 49 return methodMap[methodName] 50 } 51 52 // GetMethod returns the method for the given qualified method name 53 // qualifiedMethodName is "packagename.structname.methodname" 54 func (d *DB) GetMethod(qualifiedMethodName string) *BoundMethod { 55 // Lock the db whilst processing and unlock on return 56 d.lock.RLock() 57 defer d.lock.RUnlock() 58 59 return d.methodMap[qualifiedMethodName] 60 } 61 62 // GetObfuscatedMethod returns the method for the given ID 63 func (d *DB) GetObfuscatedMethod(id int) *BoundMethod { 64 // Lock the db whilst processing and unlock on return 65 d.lock.RLock() 66 defer d.lock.RUnlock() 67 68 return d.obfuscatedMethodMap[id] 69 } 70 71 // AddMethod adds the given method definition to the db using the given qualified path: packageName.structName.methodName 72 func (d *DB) AddMethod(packageName string, structName string, methodName string, methodDefinition *BoundMethod) { 73 // Lock the db whilst processing and unlock on return 74 d.lock.Lock() 75 defer d.lock.Unlock() 76 77 // Get the map associated with the package name 78 structMap, exists := d.store[packageName] 79 if !exists { 80 // Create a new map for this packagename 81 d.store[packageName] = make(map[string]map[string]*BoundMethod) 82 structMap = d.store[packageName] 83 } 84 85 // Get the map associated with the struct name 86 methodMap, exists := structMap[structName] 87 if !exists { 88 // Create a new map for this packagename 89 structMap[structName] = make(map[string]*BoundMethod) 90 methodMap = structMap[structName] 91 } 92 93 // Store the method definition 94 methodMap[methodName] = methodDefinition 95 96 // Store in the methodMap 97 key := packageName + "." + structName + "." + methodName 98 d.methodMap[key] = methodDefinition 99 } 100 101 // ToJSON converts the method map to JSON 102 func (d *DB) ToJSON() (string, error) { 103 // Lock the db whilst processing and unlock on return 104 d.lock.RLock() 105 defer d.lock.RUnlock() 106 107 d.UpdateObfuscatedCallMap() 108 109 bytes, err := json.Marshal(&d.store) 110 111 // Return zero copy string as this string will be read only 112 result := *(*string)(unsafe.Pointer(&bytes)) 113 return result, err 114 } 115 116 // UpdateObfuscatedCallMap sets up the secure call mappings 117 func (d *DB) UpdateObfuscatedCallMap() map[string]int { 118 mappings := make(map[string]int) 119 120 // Iterate map keys and sort them 121 keys := make([]string, 0, len(d.methodMap)) 122 for k := range d.methodMap { 123 keys = append(keys, k) 124 } 125 sort.Strings(keys) 126 127 // Iterate sorted keys and add to obfuscated method map 128 for id, k := range keys { 129 mappings[k] = id 130 d.obfuscatedMethodMap[id] = d.methodMap[k] 131 } 132 return mappings 133 }