Pure package detail
json
gno.land/p/samcrew/deps/onbloc/json
Indexed deployment identity with independently loaded latest RPC source. Functions and Render are realm-only RPC capabilities.
Indexed deployment
Identity
- Package path
- gno.land/p/samcrew/deps/onbloc/json
- Block
- 98887
- Deployed (UTC)
- Transaction
- tKjntaAvNpAcDJkGy/yEZbVogDdEPG9qKod0oURnngA=
Latest RPC state
Source
package json
import (
"errors"
"io"
"gno.land/p/nt/ufmt/v0"
)
type buffer struct {
data []byte
length int
index int
last States
state States
class Classes
}
// newBuffer creates a new buffer with the given data
func newBuffer(data []byte) *buffer {
return &buffer{
data: data,
length: len(data),
last: GO,
state: GO,
}
}
// first retrieves the first non-whitespace (or other escaped) character in the buffer.
func (b *buffer) first() (byte, error) {
for ; b.index < b.length; b.index++ {
c := b.data[b.index]
if !(c == whiteSpace || c == carriageReturn || c == newLine || c == tab) {
return c, nil
}
}
return 0, io.EOF
}
// current returns the byte of the current index.
func (b *buffer) current() (byte, error) {
if b.index >= b.length {
return 0, io.EOF
}
return b.data[b.index], nil
}
// next moves to the next byte and returns it.
func (b *buffer) next() (byte, error) {
b.index++
return b.current()
}
// step just moves to the next position.
func (b *buffer) step() error {
_, err := b.next()
return err
}
// move moves the index by the given position.
func (b *buffer) move(pos int) error {
newIndex := b.index + pos
if newIndex > b.length {
return io.EOF
}
b.index = newIndex
return nil
}
// slice returns the slice from the current index to the given position.
func (b *buffer) slice(pos int) ([]byte, error) {
end := b.index + pos
if end > b.length {
return nil, io.EOF
}
return b.data[b.index:end], nil
}
// sliceFromIndices returns a slice of the buffer's data starting from 'start' up to (but not including) 'stop'.
func (b *buffer) sliceFromIndices(start, stop int) []byte {
if start > b.length {
start = b.length
}
if stop > b.length {
stop = b.length
}
return b.data[start:stop]
}
// skip moves the index to skip the given byte.
func (b *buffer) skip(bs byte) error {
for b.index < b.length {
if b.data[b.index] == bs && !b.backslash() {
return nil
}
b.index++
}
return io.EOF
}
// skipAndReturnIndex moves the buffer index forward by one and returns the new index.
func (b *buffer) skipAndReturnIndex() (int, error) {
err := b.step()
if err != nil {
return 0, err
}
return b.index, nil
}
// skipUntil moves the buffer index forward until it encounters a byte contained in the endTokens set.
func (b *buffer) skipUntil(endTokens map[byte]bool) (int, error) {
for b.index < b.length {
currentByte, err := b.current()
if err != nil {
return b.index, err
}
// Check if the current byte is in the set of end tokens.
if _, exists := endTokens[currentByte]; exists {
return b.index, nil
}
b.index++
}
return b.index, io.EOF
}
// significantTokens is a map where the keys are the significant characters in a JSON path.
// The values in the map are all true, which allows us to use the map as a set for quick lookups.
var significantTokens = [256]bool{
dot: true, // access properties of an object
dollarSign: true, // root object
atSign: true, // current object
bracketOpen: true, // start of an array index or filter expression
bracketClose: true, // end of an array index or filter expression
}
// filterTokens stores the filter expression tokens.
var filterTokens = [256]bool{
aesterisk: true, // wildcard
andSign: true,
orSign: true,
}
// skipToNextSignificantToken advances the buffer index to the next significant character.
// Significant characters are defined based on the JSON path syntax.
func (b *buffer) skipToNextSignificantToken() {
for b.index < b.length {
current := b.data[b.index]
if significantTokens[current] {
break
}
b.index++
}
}
// backslash checks to see if the number of backslashes before the current index is odd.
//
// This is used to check if the current character is escaped. However, unlike the "unescape" function,
// "backslash" only serves to check the number of backslashes.
func (b *buffer) backslash() bool {
if b.index == 0 {
return false
}
count := 0
for i := b.index - 1; ; i-- {
if b.data[i] != backSlash {
break
}
count++
if i == 0 {
break
}
}
return count%2 != 0
}
// numIndex holds a map of valid numeric characters
var numIndex = [256]bool{
'0': true,
'1': true,
'2': true,
'3': true,
'4': true,
'5': true,
'6': true,
'7': true,
'8': true,
'9': true,
'.': true,
'e': true,
'E': true,
}
// pathToken checks if the current token is a valid JSON path token.
func (b *buffer) pathToken() error {
var stack []byte
inToken := false
inNumber := false
first := b.index
for b.index < b.length {
c := b.data[b.index]
switch {
case c == doubleQuote || c == singleQuote:
inToken = true
if err := b.step(); err != nil {
return errors.New("error stepping through buffer")
}
if err := b.skip(c); err != nil {
return errUnmatchedQuotePath
}
if b.index >= b.length {
return errUnmatchedQuotePath
}
case c == bracketOpen || c == parenOpen:
inToken = true
stack = append(stack, c)
case c == bracketClose || c == parenClose:
inToken = true
if len(stack) == 0 || (c == bracketClose && stack[len(stack)-1] != bracketOpen) || (c == parenClose && stack[len(stack)-1] != parenOpen) {
return errUnmatchedParenthesis
}
stack = stack[:len(stack)-1]
case pathStateContainsValidPathToken(c):
inToken = true
case c == plus || c == minus:
if inNumber || (b.index > 0 && numIndex[b.data[b.index-1]]) {
inToken = true
} else if !inToken && (b.index+1 < b.length && numIndex[b.data[b.index+1]]) {
inToken = true
inNumber = true
} else if !inToken {
return errInvalidToken
}
default:
if len(stack) != 0 || inToken {
inToken = true
} else {
goto end
}
}
b.index++
}
end:
if len(stack) != 0 {
return errUnmatchedParenthesis
}
if first == b.index {
return errors.New("no token found")
}
if inNumber && !numIndex[b.data[b.index-1]] {
inNumber = false
}
return nil
}
func pathStateContainsValidPathToken(c byte) bool {
if significantTokens[c] {
return true
}
if filterTokens[c] {
return true
}
if numIndex[c] {
return true
}
if 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z' {
return true
}
return false
}
func (b *buffer) numeric(token bool) error {
if token {
b.last = GO
}
for ; b.index < b.length; b.index++ {
b.class = b.getClasses(doubleQuote)
if b.class == __ {
return errInvalidToken
}
b.state = StateTransitionTable[b.last][b.class]
if b.state == __ {
if token {
break
}
return errInvalidToken
}
if b.state < __ {
return nil
}
if b.state < MI || b.state > E3 {
return nil
}
b.last = b.state
}
if b.last != ZE && b.last != IN && b.last != FR && b.last != E3 {
return errInvalidToken
}
return nil
}
func (b *buffer) getClasses(c byte) Classes {
if b.data[b.index] >= 128 {
return C_ETC
}
if c == singleQuote {
return QuoteAsciiClasses[b.data[b.index]]
}
return AsciiClasses[b.data[b.index]]
}
func (b *buffer) getState() States {
b.last = b.state
b.class = b.getClasses(doubleQuote)
if b.class == __ {
return __
}
b.state = StateTransitionTable[b.last][b.class]
return b.state
}
// string parses a string token from the buffer.
func (b *buffer) string(search byte, token bool) error {
if token {
b.last = GO
}
for ; b.index < b.length; b.index++ {
b.class = b.getClasses(search)
if b.class == __ {
return errInvalidToken
}
b.state = StateTransitionTable[b.last][b.class]
if b.state == __ {
return errInvalidToken
}
if b.state < __ {
break
}
b.last = b.state
}
return nil
}
func (b *buffer) word(bs []byte) error {
var c byte
max := len(bs)
index := 0
for ; b.index < b.length && index < max; b.index++ {
c = b.data[b.index]
if c != bs[index] {
return errInvalidToken
}
index++
if index >= max {
break
}
}
if index != max {
return errInvalidToken
}
return nil
}
func numberKind2f64(value any) (result float64, err error) {
switch typed := value.(type) {
case float64:
result = typed
case float32:
result = float64(typed)
case int:
result = float64(typed)
case int8:
result = float64(typed)
case int16:
result = float64(typed)
case int32:
result = float64(typed)
case int64:
result = float64(typed)
case uint:
result = float64(typed)
case uint8:
result = float64(typed)
case uint16:
result = float64(typed)
case uint32:
result = float64(typed)
case uint64:
result = float64(typed)
default:
err = ufmt.Errorf("invalid number type: %T", value)
}
return
}
The verified vm/qfuncs operation accepts realm paths only.
Pure packages expose source files but do not have Realm Render.