github.com/igggame/nebulas-go@v2.1.0+incompatible/nf/nvm/v8/lib/1.0.0/storage.js (about) 1 // Copyright (C) 2017 go-nebulas authors 2 // 3 // This file is part of the go-nebulas library. 4 // 5 // the go-nebulas library is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // the go-nebulas library is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU General Public License for more details. 14 // 15 // You should have received a copy of the GNU General Public License 16 // along with the go-nebulas library. If not, see <http://www.gnu.org/licenses/>. 17 // 18 19 'use strict'; 20 21 var fieldNameRe = /^[a-zA-Z_$][a-zA-Z0-9_]+$/; 22 23 var combineStorageMapKey = function (fieldName, key) { 24 return "@" + fieldName + "[" + key + "]"; 25 }; 26 27 var applyMapDescriptor = function (obj, descriptor) { 28 descriptor = Object.assign({ 29 stringify: JSON.stringify, 30 parse: JSON.parse 31 }, descriptor || {}); 32 33 if (typeof descriptor.stringify !== 'function' || typeof descriptor.parse !== 'function') { 34 throw new Error("descriptor.stringify and descriptor.parse must be function."); 35 } 36 37 Object.defineProperty(obj, "stringify", { 38 configurable: false, 39 enumerable: false, 40 get: function () { 41 return descriptor.stringify; 42 } 43 }); 44 45 Object.defineProperty(obj, "parse", { 46 configurable: false, 47 enumerable: false, 48 get: function () { 49 return descriptor.parse; 50 } 51 }); 52 }; 53 54 var applyFieldDescriptor = function (obj, fieldName, descriptor) { 55 descriptor = Object.assign({ 56 stringify: JSON.stringify, 57 parse: JSON.parse 58 }, descriptor || {}); 59 60 if (typeof descriptor.stringify !== 'function' || typeof descriptor.parse !== 'function') { 61 throw new Error("descriptor.stringify and descriptor.parse must be function."); 62 } 63 64 Object.defineProperty(obj, "__stringify__" + fieldName, { 65 configurable: false, 66 enumerable: false, 67 get: function () { 68 return descriptor.stringify; 69 } 70 }); 71 72 Object.defineProperty(obj, "__parse__" + fieldName, { 73 configurable: false, 74 enumerable: false, 75 get: function () { 76 return descriptor.parse; 77 } 78 }); 79 }; 80 81 var ContractStorage = function (handler) { 82 var ns = new NativeStorage(handler); 83 Object.defineProperty(this, "nativeStorage", { 84 configurable: false, 85 enumerable: false, 86 get: function () { 87 return ns; 88 } 89 }); 90 }; 91 92 var StorageMap = function (contractStorage, fieldName, descriptor) { 93 if (!contractStorage instanceof ContractStorage) { 94 throw new Error("StorageMap only accept instance of ContractStorage"); 95 } 96 97 if (typeof fieldName !== "string" || fieldNameRe.exec(fieldName) == null) { 98 throw new Error("StorageMap fieldName must match regex /^[a-zA-Z_$].*$/"); 99 } 100 101 Object.defineProperty(this, "contractStorage", { 102 configurable: false, 103 enumerable: false, 104 get: function () { 105 return contractStorage; 106 } 107 }); 108 Object.defineProperty(this, "fieldName", { 109 configurable: false, 110 enumerable: false, 111 get: function () { 112 return fieldName; 113 } 114 }); 115 116 applyMapDescriptor(this, descriptor); 117 }; 118 119 120 StorageMap.prototype = { 121 del: function (key) { 122 return this.contractStorage.del(combineStorageMapKey(this.fieldName, key)); 123 }, 124 get: function (key) { 125 var val = this.contractStorage.rawGet(combineStorageMapKey(this.fieldName, key)); 126 if (val != null) { 127 val = this.parse(val); 128 } 129 return val; 130 }, 131 set: function (key, value) { 132 var val = this.stringify(value); 133 return this.contractStorage.rawSet(combineStorageMapKey(this.fieldName, key), val); 134 } 135 }; 136 StorageMap.prototype.put = StorageMap.prototype.set; 137 StorageMap.prototype.delete = StorageMap.prototype.del; 138 139 140 ContractStorage.prototype = { 141 rawGet: function (key) { 142 return this.nativeStorage.get(key); 143 }, 144 rawSet: function (key, value) { 145 var ret = this.nativeStorage.set(key, value); 146 if (ret != 0) { 147 throw new Error("set key " + key + " failed."); 148 } 149 return ret; 150 }, 151 del: function (key) { 152 var ret = this.nativeStorage.del(key); 153 if (ret != 0) { 154 throw new Error("del key " + key + " failed."); 155 } 156 return ret; 157 }, 158 get: function (key) { 159 var val = this.rawGet(key); 160 if (val != null) { 161 val = JSON.parse(val); 162 } 163 return val; 164 }, 165 set: function (key, value) { 166 return this.rawSet(key, JSON.stringify(value)); 167 }, 168 defineProperty: function (obj, fieldName, descriptor) { 169 if (!obj || !fieldName) { 170 throw new Error("defineProperty requires at least two parameters."); 171 } 172 var $this = this; 173 Object.defineProperty(obj, fieldName, { 174 configurable: false, 175 enumerable: true, 176 get: function () { 177 var val = $this.rawGet(fieldName); 178 if (val != null) { 179 val = obj["__parse__" + fieldName](val); 180 } 181 return val; 182 }, 183 set: function (val) { 184 val = obj["__stringify__" + fieldName](val); 185 return $this.rawSet(fieldName, val); 186 } 187 }); 188 applyFieldDescriptor(obj, fieldName, descriptor); 189 return this; 190 }, 191 defineProperties: function (obj, props) { 192 if (!obj || !props) { 193 throw new Error("defineProperties requires two parameters."); 194 } 195 196 for (const fieldName in props) { 197 this.defineProperty(obj, fieldName, props[fieldName]); 198 } 199 return this; 200 }, 201 defineMapProperty: function (obj, fieldName, descriptor) { 202 if (!obj || !fieldName) { 203 throw new Error("defineMapProperty requires two parameters."); 204 } 205 206 var mapObj = new StorageMap(this, fieldName, descriptor); 207 Object.defineProperty(obj, fieldName, { 208 configurable: false, 209 enumerable: true, 210 get: function () { 211 return mapObj; 212 } 213 }); 214 return this; 215 }, 216 defineMapProperties: function (obj, props) { 217 if (!obj || !props) { 218 throw new Error("defineMapProperties requires two parameters."); 219 } 220 221 for (const fieldName in props) { 222 this.defineMapProperty(obj, fieldName, props[fieldName]); 223 } 224 return this; 225 } 226 }; 227 228 ContractStorage.prototype.put = ContractStorage.prototype.set; 229 ContractStorage.prototype.delete = ContractStorage.prototype.del; 230 231 var lcs = new ContractStorage(_native_storage_handlers.lcs); 232 var gcs = new ContractStorage(_native_storage_handlers.gcs); 233 var obj = {ContractStorage: ContractStorage}; 234 Object.defineProperty(obj, "lcs", { 235 configurable: false, 236 enumerable: false, 237 get: function () { 238 return lcs; 239 } 240 }); 241 242 Object.defineProperty(obj, "gcs", { 243 configurable: false, 244 enumerable: false, 245 get: function () { 246 return gcs; 247 } 248 }); 249 250 module.exports = Object.freeze(obj);