PathrockNetwork Gno Explorer
HomeBlocksTransactionsTokensRealmsPackagesValidatorsAnalytics

PathrockNetwork Gno Explorer — an independent explorer for Gno.land Mainnet (gnoland-1), operated by PathrockNetwork. Not an official Gno.land service.

gnowebarchive RPC

gno.land/p/onbloc/json/v0

Package
Open in gnoweb ↗

Overview

Kind
Pure package
Name
v0
Namespace
onbloc / json
Files
24 (README)(gnomod.toml)
Exported functions
n/a — not supported for pure packages by the node (vm/qfuncs)
Module
gno.land/p/onbloc/json/v0
gno
0.9

Files (24)

  • README.mdmarkdown
  • gnomod.tomltoml
  • buffer.gnogno
  • builder.gnogno
  • decode.gnogno
  • encode.gnogno
  • errors.gnogno
  • escape.gnogno
  • indent.gnogno
  • internal.gnogno
  • node.gnogno
  • parser.gnogno
  • path.gnogno
  • token.gnogno
  • buffer_test.gnogno
  • builder_test.gnogno
  • decode_test.gnogno
  • encode_test.gnogno
  • escape_test.gnogno
  • indent_test.gnogno
  • node_test.gnogno
  • parser_test.gnogno
  • path_test.gnogno
  • LICENSEother
  • decode.gnogno
    1// ref: https://github.com/spyzhov/ajson/blob/master/decode.go23package json45import (6	"errors"7	"io"8

    Functions

    not supported for pure packages by the node (vm/qfuncs)

    Signatures reconstructed verbatim from vm/qfuncs — interface params keep their inline definitions.

    9 "gno.land/p/nt/ufmt/v0"
    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
    14const 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"}
    26func 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.
    183func 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.
    191func 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.
    215func 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.
    236func 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.
    248func 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.
    263func 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.
    279func 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.
    300func 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.
    324func 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.
    343func 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.
    360func 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
    368func unexpectedTokenError(data []byte, index int) error {
    369 return ufmt.Errorf("unexpected token at index %d. data %b", index, data)
    370}
    371