github.com/gnolang/gno@v0.0.0-20240520182011-228e9d0192ce/examples/gno.land/p/demo/json/decode.gno (about) 1 // ref: https://github.com/spyzhov/ajson/blob/master/decode.go 2 3 package json 4 5 import ( 6 "errors" 7 "io" 8 9 "gno.land/p/demo/ufmt" 10 ) 11 12 // This limits the max nesting depth to prevent stack overflow. 13 // This is permitted by https://tools.ietf.org/html/rfc7159#section-9 14 const maxNestingDepth = 10000 15 16 // Unmarshal parses the JSON-encoded data and returns a Node. 17 // The data must be a valid JSON-encoded value. 18 // 19 // Usage: 20 // 21 // node, err := json.Unmarshal([]byte(`{"key": "value"}`)) 22 // if err != nil { 23 // ufmt.Println(err) 24 // } 25 // println(node) // {"key": "value"} 26 func Unmarshal(data []byte) (*Node, error) { 27 buf := newBuffer(data) 28 29 var ( 30 state States 31 key *string 32 current *Node 33 nesting int 34 useKey = func() **string { 35 tmp := cptrs(key) 36 key = nil 37 return &tmp 38 } 39 err error 40 ) 41 42 if _, err = buf.first(); err != nil { 43 return nil, io.EOF 44 } 45 46 for { 47 state = buf.getState() 48 if state == __ { 49 return nil, unexpectedTokenError(buf.data, buf.index) 50 } 51 52 // region state machine 53 if state >= GO { 54 switch buf.state { 55 case ST: // string 56 if current != nil && current.IsObject() && key == nil { 57 // key detected 58 if key, err = getString(buf); err != nil { 59 return nil, err 60 } 61 62 buf.state = CO 63 } else { 64 current, nesting, err = createNestedNode(current, buf, String, nesting, useKey()) 65 if err != nil { 66 return nil, err 67 } 68 69 err = buf.string(doubleQuote, false) 70 if err != nil { 71 return nil, err 72 } 73 74 current, nesting = updateNode(current, buf, nesting, true) 75 buf.state = OK 76 } 77 78 case MI, ZE, IN: // number 79 current, err = processNumericNode(current, buf, useKey()) 80 if err != nil { 81 return nil, err 82 } 83 84 case T1, F1: // boolean 85 literal := falseLiteral 86 if buf.state == T1 { 87 literal = trueLiteral 88 } 89 90 current, nesting, err = processLiteralNode(current, buf, Boolean, literal, useKey(), nesting) 91 if err != nil { 92 return nil, err 93 } 94 95 case N1: // null 96 current, nesting, err = processLiteralNode(current, buf, Null, nullLiteral, useKey(), nesting) 97 if err != nil { 98 return nil, err 99 } 100 } 101 } else { 102 // region action 103 switch state { 104 case ec, cc: // <empty> } 105 if key != nil { 106 return nil, unexpectedTokenError(buf.data, buf.index) 107 } 108 109 current, nesting, err = updateNodeAndSetBufferState(current, buf, nesting, Object) 110 if err != nil { 111 return nil, err 112 } 113 114 case bc: // ] 115 current, nesting, err = updateNodeAndSetBufferState(current, buf, nesting, Array) 116 if err != nil { 117 return nil, err 118 } 119 120 case co, bo: // { [ 121 valTyp, bState := Object, OB 122 if state == bo { 123 valTyp, bState = Array, AR 124 } 125 126 current, nesting, err = createNestedNode(current, buf, valTyp, nesting, useKey()) 127 if err != nil { 128 return nil, err 129 } 130 131 buf.state = bState 132 133 case cm: // , 134 if current == nil { 135 return nil, unexpectedTokenError(buf.data, buf.index) 136 } 137 138 if !current.isContainer() { 139 return nil, unexpectedTokenError(buf.data, buf.index) 140 } 141 142 if current.IsObject() { 143 buf.state = KE // key expected 144 } else { 145 buf.state = VA // value expected 146 } 147 148 case cl: // : 149 if current == nil || !current.IsObject() || key == nil { 150 return nil, unexpectedTokenError(buf.data, buf.index) 151 } 152 153 buf.state = VA 154 155 default: 156 return nil, unexpectedTokenError(buf.data, buf.index) 157 } 158 } 159 160 if buf.step() != nil { 161 break 162 } 163 164 if _, err = buf.first(); err != nil { 165 err = nil 166 break 167 } 168 } 169 170 if current == nil || buf.state != OK { 171 return nil, io.EOF 172 } 173 174 root := current.root() 175 if !root.ready() { 176 return nil, io.EOF 177 } 178 179 return root, err 180 } 181 182 // UnmarshalSafe parses the JSON-encoded data and returns a Node. 183 func UnmarshalSafe(data []byte) (*Node, error) { 184 var safe []byte 185 safe = append(safe, data...) 186 return Unmarshal(safe) 187 } 188 189 // processNumericNode creates a new node, processes a numeric value, 190 // sets the node's borders, and moves to the previous node. 191 func processNumericNode(current *Node, buf *buffer, key **string) (*Node, error) { 192 var err error 193 current, err = createNode(current, buf, Number, key) 194 if err != nil { 195 return nil, err 196 } 197 198 if err = buf.numeric(false); err != nil { 199 return nil, err 200 } 201 202 current.borders[1] = buf.index 203 if current.prev != nil { 204 current = current.prev 205 } 206 207 buf.index -= 1 208 buf.state = OK 209 210 return current, nil 211 } 212 213 // processLiteralNode creates a new node, processes a literal value, 214 // sets the node's borders, and moves to the previous node. 215 func processLiteralNode( 216 current *Node, 217 buf *buffer, 218 literalType ValueType, 219 literalValue []byte, 220 useKey **string, 221 nesting int, 222 ) (*Node, int, error) { 223 var err error 224 current, nesting, err = createLiteralNode(current, buf, literalType, literalValue, useKey, nesting) 225 if err != nil { 226 return nil, nesting, err 227 } 228 return current, nesting, nil 229 } 230 231 // isValidContainerType checks if the current node is a valid container (object or array). 232 // The container must satisfy the following conditions: 233 // 1. The current node must not be nil. 234 // 2. The current node must be an object or array. 235 // 3. The current node must not be ready. 236 func isValidContainerType(current *Node, nodeType ValueType) bool { 237 switch nodeType { 238 case Object: 239 return current != nil && current.IsObject() && !current.ready() 240 case Array: 241 return current != nil && current.IsArray() && !current.ready() 242 default: 243 return false 244 } 245 } 246 247 // getString extracts a string from the buffer and advances the buffer index past the string. 248 func getString(b *buffer) (*string, error) { 249 start := b.index 250 if err := b.string(doubleQuote, false); err != nil { 251 return nil, err 252 } 253 254 value, ok := Unquote(b.data[start:b.index+1], doubleQuote) 255 if !ok { 256 return nil, unexpectedTokenError(b.data, start) 257 } 258 259 return &value, nil 260 } 261 262 // createNode creates a new node and sets the key if it is not nil. 263 func createNode( 264 current *Node, 265 buf *buffer, 266 nodeType ValueType, 267 key **string, 268 ) (*Node, error) { 269 var err error 270 current, err = NewNode(current, buf, nodeType, key) 271 if err != nil { 272 return nil, err 273 } 274 275 return current, nil 276 } 277 278 // createNestedNode creates a new nested node (array or object) and sets the key if it is not nil. 279 func createNestedNode( 280 current *Node, 281 buf *buffer, 282 nodeType ValueType, 283 nesting int, 284 key **string, 285 ) (*Node, int, error) { 286 var err error 287 if nesting, err = checkNestingDepth(nesting); err != nil { 288 return nil, nesting, err 289 } 290 291 if current, err = createNode(current, buf, nodeType, key); err != nil { 292 return nil, nesting, err 293 } 294 295 return current, nesting, nil 296 } 297 298 // createLiteralNode creates a new literal node and sets the key if it is not nil. 299 // The literal is a byte slice that represents a boolean or null value. 300 func createLiteralNode( 301 current *Node, 302 buf *buffer, 303 literalType ValueType, 304 literal []byte, 305 useKey **string, 306 nesting int, 307 ) (*Node, int, error) { 308 var err error 309 if current, err = createNode(current, buf, literalType, useKey); err != nil { 310 return nil, 0, err 311 } 312 313 if err = buf.word(literal); err != nil { 314 return nil, 0, err 315 } 316 317 current, nesting = updateNode(current, buf, nesting, false) 318 buf.state = OK 319 320 return current, nesting, nil 321 } 322 323 // updateNode updates the current node and returns the previous node. 324 func updateNode( 325 current *Node, buf *buffer, nesting int, decreaseLevel bool, 326 ) (*Node, int) { 327 current.borders[1] = buf.index + 1 328 329 prev := current.prev 330 if prev == nil { 331 return current, nesting 332 } 333 334 current = prev 335 if decreaseLevel { 336 nesting-- 337 } 338 339 return current, nesting 340 } 341 342 // updateNodeAndSetBufferState updates the current node and sets the buffer state to OK. 343 func updateNodeAndSetBufferState( 344 current *Node, 345 buf *buffer, 346 nesting int, 347 typ ValueType, 348 ) (*Node, int, error) { 349 if !isValidContainerType(current, typ) { 350 return nil, nesting, unexpectedTokenError(buf.data, buf.index) 351 } 352 353 current, nesting = updateNode(current, buf, nesting, true) 354 buf.state = OK 355 356 return current, nesting, nil 357 } 358 359 // checkNestingDepth checks if the nesting depth is within the maximum allowed depth. 360 func checkNestingDepth(nesting int) (int, error) { 361 if nesting >= maxNestingDepth { 362 return nesting, errors.New("maximum nesting depth exceeded") 363 } 364 365 return nesting + 1, nil 366 } 367 368 func unexpectedTokenError(data []byte, index int) error { 369 return ufmt.Errorf("unexpected token at index %d. data %b", index, data) 370 }