1package json23import (4 "bytes"5 "errors"6 "strconv"78 "gno.land/p/nt/ufmt/v0"9)1011// Marshal returns the JSON encoding of a Node.12func Marshal(node *Node) ([]byte, error) {13 var (14 buf bytes.Buffer15 sVal string16 bVal bool17 nVal float6418 oVal []byte19 err error20 )2122 if node == nil {23 return nil, errors.New("node is nil")24 }2526 if !node.modified && !node.ready() {27 return nil, errors.New("node is not ready")28 }2930 if !node.modified && node.ready() {31 buf.Write(node.source())32 }3334 if node.modified {35 switch node.nodeType {36 case Null:37 buf.Write(nullLiteral)3839 case Number:40 nVal, err = node.GetNumeric()41 if err != nil {42 return nil, err43 }4445 num := strconv.FormatFloat(nVal, 'f', -1, 64)46 buf.WriteString(num)4748 case String:49 sVal, err = node.GetString()50 if err != nil {51 return nil, err52 }5354 quoted := ufmt.Sprintf("%s", strconv.Quote(sVal))55 buf.WriteString(quoted)5657 case Boolean:58 bVal, err = node.GetBool()59 if err != nil {60 return nil, err61 }6263 bStr := ufmt.Sprintf("%t", bVal)64 buf.WriteString(bStr)6566 case Array:67 buf.WriteByte(bracketOpen)6869 for i := 0; i < len(node.next); i++ {70 if i != 0 {71 buf.WriteByte(comma)72 }7374 elem, ok := node.next[strconv.Itoa(i)]75 if !ok {76 return nil, ufmt.Errorf("array element %d is not found", i)77 }7879 oVal, err = Marshal(elem)80 if err != nil {81 return nil, err82 }8384 buf.Write(oVal)85 }8687 buf.WriteByte(bracketClose)8889 case Object:90 buf.WriteByte(curlyOpen)9192 bVal = false93 for k, v := range node.next {94 if bVal {95 buf.WriteByte(comma)96 } else {97 bVal = true98 }99100 key := ufmt.Sprintf("%s", strconv.Quote(k))101 buf.WriteString(key)102 buf.WriteByte(colon)103104 oVal, err = Marshal(v)105 if err != nil {106 return nil, err107 }108109 buf.Write(oVal)110 }111112 buf.WriteByte(curlyClose)113 }114 }115116 return buf.Bytes(), nil117}118Signatures reconstructed verbatim from vm/qfuncs — interface params keep their inline definitions.