mirror of
https://github.com/nspcc-dev/neo-go.git
synced 2025-01-09 11:19:06 +00:00
cf4d3b25d7
``` pkg/smartcontract/rpcbinding/binding.go:523:2 exhaustive missing cases in switch of type smartcontract.ParamType: smartcontract .UnknownType pkg/smartcontract/rpcbinding/binding.go:572:2 exhaustive missing cases in switch of type smartcontract.ParamType: smartcontract .UnknownType pkg/smartcontract/rpcbinding/binding.go:862:2 exhaustive missing cases in switch of type smartcontract.ParamType: smartcontract .UnknownType, smartcontract.AnyType, smartcontract.BoolType, smartcontract.IntegerType, smartcontract.ByteArrayType, smartcontract .Hash160Type, smartcontract.Hash256Type, smartcontract.SignatureType, smartcontract.InteropInterfaceType, smartcontract.VoidType pkg/smartcontract/param_type.go:165:2 exhaustive missing cases in switch of type smartcontract.ParamType: smartcontract .UnknownType pkg/smartcontract/manifest/permission.go:103:2 exhaustive missing cases in switch of type manifest.PermissionType: manifest .PermissionWildcard pkg/services/notary/core_test.go:223:4 exhaustive missing cases in switch of type notary.RequestType: notary.Contract pkg/services/notary/core_test.go:292:4 exhaustive missing cases in switch of type notary.RequestType: notary.Contract pkg/services/oracle/jsonpath/jsonpath.go:62:3 exhaustive missing cases in switch of type jsonpath.pathTokenType: jsonpath.pathInvalid, jsonpath.pathRoot, jsonpath.pathRightBracket, jsonpath.pathAsterisk, jsonpath.pathComma, jsonpath.pathColon, jsonpath.pathIdentifier, jsonpath.pathString, jsonpath.pathNumber pkg/services/rpcsrv/server.go:2740:3 exhaustive missing cases in switch of type neorpc.EventID: neorpc.InvalidEventID, neorpc .MissedEventID pkg/services/rpcsrv/server.go:2804:2 exhaustive missing cases in switch of type neorpc.EventID: neorpc.InvalidEventID, neorpc .MissedEventID pkg/services/rpcsrv/server.go:2864:2 exhaustive missing cases in switch of type neorpc.EventID: neorpc.InvalidEventID, neorpc .MissedEventID pkg/vm/contract_checks.go:153:3 exhaustive missing cases in switch of type opcode.Opcode: opcode.PUSHINT8, opcode .PUSHINT16, opcode.PUSHINT32, opcode.PUSHINT64, opcode.PUSHINT128, opcode.PUSHINT256, opcode.PUSHT, opcode.PUSHF, opcode.PUSHNULL, opcode .PUSHDATA1, opcode.PUSHDATA2, opcode.PUSHDATA4, opcode.PUSHM1, opcode .PUSH0, opcode.PUSH1, opcode.PUSH2, opcode.PUSH3, opcode.PUSH4, opcode .PUSH5, opcode.PUSH6, opcode.PUSH7, opcode.PUSH8, opcode.PUSH9, opcode .PUSH10, opcode.PUSH11, opcode.PUSH12, opcode.PUSH13, opcode.PUSH14, opcode.PUSH15, opcode.PUSH16, opcode.NOP, opcode.CALLA, opcode.CALLT, opcode.ABORT, opcode.ASSERT, opcode.THROW, opcode.ENDFINALLY, opcode .RET, opcode.SYSCALL, opcode.DEPTH, opcode.DROP, opcode.NIP, opcode .XDROP, opcode.CLEAR, opcode.DUP, opcode.OVER, opcode.PICK, opcode.TUCK, opcode.SWAP, opcode.ROT, opcode.ROLL, opcode.REVERSE3, opcode.REVERSE4, opcode.REVERSEN, opcode.INITSSLOT, opcode.INITSLOT, opcode.LDSFLD0, opcode.LDSFLD1, opcode.LDSFLD2, opcode.LDSFLD3, opcode.LDSFLD4, opcode .LDSFLD5, opcode.LDSFLD6, opcode.LDSFLD, opcode.STSFLD0, opcode .STSFLD1, opcode.STSFLD2, opcode.STSFLD3, opcode.STSFLD4, opcode .STSFLD5, opcode.STSFLD6, opcode.STSFLD, opcode.LDLOC0, opcode.LDLOC1, opcode.LDLOC2, opcode.LDLOC3, opcode.LDLOC4, opcode.LDLOC5, opcode .LDLOC6, opcode.LDLOC, opcode.STLOC0, opcode.STLOC1, opcode.STLOC2, opcode.STLOC3, opcode.STLOC4, opcode.STLOC5, opcode.STLOC6, opcode .STLOC, opcode.LDARG0, opcode.LDARG1, opcode.LDARG2, opcode.LDARG3, opcode.LDARG4, opcode.LDARG5, opcode.LDARG6, opcode.LDARG, opcode .STARG0, opcode.STARG1, opcode.STARG2, opcode.STARG3, opcode.STARG4, opcode.STARG5, opcode.STARG6, opcode.STARG, opcode.NEWBUFFER, opcode .MEMCPY, opcode.CAT, opcode.SUBSTR, opcode.LEFT, opcode.RIGHT, opcode .INVERT, opcode.AND, opcode.OR, opcode.XOR, opcode.EQUAL, opcode .NOTEQUAL, opcode.SIGN, opcode.ABS, opcode.NEGATE, opcode.INC, opcode .DEC, opcode.ADD, opcode.SUB, opcode.MUL, opcode.DIV, opcode.MOD, opcode.POW, opcode.SQRT, opcode.MODMUL, opcode.MODPOW, opcode.SHL, opcode.SHR, opcode.NOT, opcode.BOOLAND, opcode.BOOLOR, opcode.NZ, opcode.NUMEQUAL, opcode.NUMNOTEQUAL, opcode.LT, opcode.LE, opcode.GT, opcode.GE, opcode.MIN, opcode.MAX, opcode.WITHIN, opcode.PACKMAP, opcode.PACKSTRUCT, opcode.PACK, opcode.UNPACK, opcode.NEWARRAY0, opcode.NEWARRAY, opcode.NEWSTRUCT0, opcode.NEWSTRUCT, opcode.NEWMAP, opcode.SIZE, opcode.HASKEY, opcode.KEYS, opcode.VALUES, opcode .PICKITEM, opcode.APPEND, opcode.SETITEM, opcode.REVERSEITEMS, opcode.REMOVE, opcode.CLEARITEMS, opcode.POPITEM, opcode.ISNULL, opcode.ABORTMSG, opcode.ASSERTMSG pkg/vm/vm.go:912:3 exhaustive missing cases in switch of type opcode.Opcode: opcode.PUSHINT8, opcode .PUSHINT16, opcode.PUSHINT32, opcode.PUSHINT64, opcode.PUSHINT128, opcode.PUSHINT256, opcode.PUSHT, opcode.PUSHF, opcode.PUSHA, opcode .PUSHNULL, opcode.PUSHDATA1, opcode.PUSHDATA2, opcode.PUSHDATA4, opcode .PUSHM1, opcode.PUSH0, opcode.PUSH1, opcode.PUSH2, opcode.PUSH3, opcode .PUSH4, opcode.PUSH5, opcode.PUSH6, opcode.PUSH7, opcode.PUSH8, opcode .PUSH9, opcode.PUSH10, opcode.PUSH11, opcode.PUSH12, opcode.PUSH13, opcode.PUSH14, opcode.PUSH15, opcode.PUSH16, opcode.NOP, opcode.JMP, opcode.JMPL, opcode.JMPIF, opcode.JMPIFL, opcode.JMPIFNOT, opcode .JMPIFNOTL, opcode.JMPEQ, opcode.JMPEQL, opcode.JMPNE, opcode.JMPNEL, opcode.JMPGT, opcode.JMPGTL, opcode.JMPGE, opcode.JMPGEL, opcode.JMPLT, opcode.JMPLTL, opcode.JMPLE, opcode.JMPLEL, opcode.CALL, opcode.CALLL, opcode.CALLA, opcode.CALLT, opcode.ABORT, opcode.ASSERT, opcode.THROW, opcode.TRY, opcode.TRYL, opcode.ENDTRY, opcode.ENDTRYL, opcode .ENDFINALLY, opcode.RET, opcode.SYSCALL, opcode.DEPTH, opcode.DROP, opcode.NIP, opcode.XDROP, opcode.CLEAR, opcode.DUP, opcode.OVER, opcode .PICK, opcode.TUCK, opcode.SWAP, opcode.ROT, opcode.ROLL, opcode .REVERSE3, opcode.INITSSLOT, opcode.INITSLOT, opcode.LDSFLD0, opcode .LDSFLD1, opcode.LDSFLD2, opcode.LDSFLD3, opcode.LDSFLD4, opcode .LDSFLD5, opcode.LDSFLD6, opcode.LDSFLD, opcode.STSFLD0, opcode.STSFLD1, opcode.STSFLD2, opcode.STSFLD3, opcode.STSFLD4, opcode.STSFLD5, opcode .STSFLD6, opcode.STSFLD, opcode.LDLOC0, opcode.LDLOC1, opcode.LDLOC2, opcode.LDLOC3, opcode.LDLOC4, opcode.LDLOC5, opcode.LDLOC6, opcode .LDLOC, opcode.STLOC0, opcode.STLOC1, opcode.STLOC2, opcode.STLOC3, opcode.STLOC4, opcode.STLOC5, opcode.STLOC6, opcode.STLOC, opcode .LDARG0, opcode.LDARG1, opcode.LDARG2, opcode.LDARG3, opcode.LDARG4, opcode.LDARG5, opcode.LDARG6, opcode.LDARG, opcode.STARG0, opcode .STARG1, opcode.STARG2, opcode.STARG3, opcode.STARG4, opcode.STARG5, opcode.STARG6, opcode.STARG, opcode.NEWBUFFER, opcode.MEMCPY, opcode .CAT, opcode.SUBSTR, opcode.LEFT, opcode.RIGHT, opcode.INVERT, opcode .AND, opcode.OR, opcode.XOR, opcode.EQUAL, opcode.NOTEQUAL, opcode .SIGN, opcode.ABS, opcode.NEGATE, opcode.INC, opcode.DEC, opcode.ADD, opcode.SUB, opcode.MUL, opcode.DIV, opcode.MOD, opcode.POW, opcode .SQRT, opcode.MODMUL, opcode.MODPOW, opcode.SHL, opcode.SHR, opcode .NOT, opcode.BOOLAND, opcode.BOOLOR, opcode.NZ, opcode.NUMEQUAL, opcode .NUMNOTEQUAL, opcode.LT, opcode.LE, opcode.GT, opcode.GE, opcode.MIN, opcode.MAX, opcode.WITHIN, opcode.PACKMAP, opcode.PACKSTRUCT, opcode .PACK, opcode.UNPACK, opcode.NEWARRAY0, opcode.NEWARRAY, opcode .NEWARRAYT, opcode.NEWSTRUCT0, opcode.NEWSTRUCT, opcode.NEWMAP, opcode .SIZE, opcode.HASKEY, opcode.KEYS, opcode.VALUES, opcode.PICKITEM, opcode.APPEND, opcode.SETITEM, opcode.REVERSEITEMS, opcode.REMOVE, opcode.CLEARITEMS, opcode.POPITEM, opcode.ISNULL, opcode.ISTYPE, opcode .CONVERT, opcode.ABORTMSG, opcode.ASSERTMSG pkg/vm/vm.go:1116:4 exhaustive missing cases in switch of type opcode.Opcode: opcode.PUSHINT8, opcode .PUSHINT16, opcode.PUSHINT32, opcode.PUSHINT64, opcode.PUSHINT128, opcode.PUSHINT256, opcode.PUSHT, opcode.PUSHF, opcode.PUSHA, opcode .PUSHNULL, opcode.PUSHDATA1, opcode.PUSHDATA2, opcode.PUSHDATA4, opcode .PUSHM1, opcode.PUSH0, opcode.PUSH1, opcode.PUSH2, opcode.PUSH3, opcode .PUSH4, opcode.PUSH5, opcode.PUSH6, opcode.PUSH7, opcode.PUSH8, opcode .PUSH9, opcode.PUSH10, opcode.PUSH11, opcode.PUSH12, opcode.PUSH13, opcode.PUSH14, opcode.PUSH15, opcode.PUSH16, opcode.NOP, opcode.JMP, opcode.JMPL, opcode.JMPIF, opcode.JMPIFL, opcode.JMPIFNOT, opcode .JMPIFNOTL, opcode.JMPEQ, opcode.JMPEQL, opcode.JMPNE, opcode.JMPNEL, opcode.JMPGT, opcode.JMPGTL, opcode.JMPGE, opcode.JMPGEL, opcode.JMPLT, opcode.JMPLTL, opcode.JMPLE, opcode.JMPLEL, opcode.CALL, opcode.CALLL, opcode.CALLA, opcode.CALLT, opcode.ABORT, opcode.ASSERT, opcode.THROW, opcode.TRY, opcode.TRYL, opcode.ENDTRY, opcode.ENDTRYL, opcode .ENDFINALLY, opcode.RET, opcode.SYSCALL, opcode.DEPTH, opcode.DROP, opcode.NIP, opcode.XDROP, opcode.CLEAR, opcode.DUP, opcode.OVER, opcode .PICK, opcode.TUCK, opcode.SWAP, opcode.ROT, opcode.ROLL, opcode .REVERSE3, opcode.REVERSE4, opcode.REVERSEN, opcode.INITSSLOT, opcode .INITSLOT, opcode.LDSFLD0, opcode.LDSFLD1, opcode.LDSFLD2, opcode .LDSFLD3, opcode.LDSFLD4, opcode.LDSFLD5, opcode.LDSFLD6, opcode.LDSFLD, opcode.STSFLD0, opcode.STSFLD1, opcode.STSFLD2, opcode.STSFLD3, opcode .STSFLD4, opcode.STSFLD5, opcode.STSFLD6, opcode.STSFLD, opcode.LDLOC0, opcode.LDLOC1, opcode.LDLOC2, opcode.LDLOC3, opcode.LDLOC4, opcode .LDLOC5, opcode.LDLOC6, opcode.LDLOC, opcode.STLOC0, opcode.STLOC1, opcode.STLOC2, opcode.STLOC3, opcode.STLOC4, opcode.STLOC5, opcode .STLOC6, opcode.STLOC, opcode.LDARG0, opcode.LDARG1, opcode.LDARG2, opcode.LDARG3, opcode.LDARG4, opcode.LDARG5, opcode.LDARG6, opcode .LDARG, opcode.STARG0, opcode.STARG1, opcode.STARG2, opcode.STARG3, opcode.STARG4, opcode.STARG5, opcode.STARG6, opcode.STARG, opcode .NEWBUFFER, opcode.MEMCPY, opcode.CAT, opcode.SUBSTR, opcode.LEFT, opcode.RIGHT, opcode.INVERT, opcode.AND, opcode.OR, opcode.XOR, opcode .EQUAL, opcode.NOTEQUAL, opcode.SIGN, opcode.ABS, opcode.NEGATE, opcode.INC, opcode.DEC, opcode.ADD, opcode.SUB, opcode.MUL, opcode .DIV, opcode.MOD, opcode.POW, opcode.SQRT, opcode.MODMUL, opcode .MODPOW, opcode.SHL, opcode.SHR, opcode.NOT, opcode.BOOLAND, opcode .BOOLOR, opcode.NZ, opcode.NUMEQUAL, opcode.NUMNOTEQUAL, opcode.MIN, opcode.MAX, opcode.WITHIN, opcode.PACKMAP, opcode.PACKSTRUCT, opcode .PACK, opcode.UNPACK, opcode.NEWARRAY0, opcode.NEWARRAY, opcode .NEWARRAYT, opcode.NEWSTRUCT0, opcode.NEWSTRUCT, opcode.NEWMAP, opcode .SIZE, opcode.HASKEY, opcode.KEYS, opcode.VALUES, opcode.PICKITEM, opcode.APPEND, opcode.SETITEM, opcode.REVERSEITEMS, opcode.REMOVE, opcode.CLEARITEMS, opcode.POPITEM, opcode.ISNULL, opcode.ISTYPE, opcode.CONVERT, opcode.ABORTMSG, opcode.ASSERTMSG pkg/compiler/codegen.go:944:5 exhaustive missing cases in switch of type smartcontract.ParamType: smartcontract .UnknownType, smartcontract.AnyType, smartcontract.BoolType, smartcontract.IntegerType, smartcontract.ByteArrayType, smartcontract .StringType, smartcontract.PublicKeyType, smartcontract.SignatureType, smartcontract.ArrayType, smartcontract.MapType, smartcontract .InteropInterfaceType, smartcontract.VoidType pkg/compiler/codegen.go:1221:3 exhaustive missing cases in switch of type token.Token: token.ILLEGAL, token.EOF, token .COMMENT, token.IDENT, token.INT, token.FLOAT, token.IMAG, token.CHAR, token.STRING, token.ADD, token.SUB, token.MUL, token.QUO, token.REM, token.AND, token.OR, token.XOR, token.SHL, token.SHR, token.AND_NOT, token.ADD_ASSIGN, token.SUB_ASSIGN, token.MUL_ASSIGN, token.QUO_ASSIGN, token.REM_ASSIGN, token.AND_ASSIGN, token.OR_ASSIGN, token.XOR_ASSIGN, token.SHL_ASSIGN, token.SHR_ASSIGN, token.AND_NOT_ASSIGN, token.LAND, token.LOR, token.ARROW, token.INC, token.DEC, token.EQL, token.LSS, token.GTR, token.ASSIGN, token.NOT, token.NEQ, token.LEQ, token.GEQ, token.DEFINE, token.ELLIPSIS, token.LPAREN, token.LBRACK, token.LBRACE, token.COMMA, token.PERIOD, token.RPAREN, token.RBRACK, token.RBRACE, token.SEMICOLON, token.COLON, token.CASE, token.CHAN, token.CONST, token .DEFAULT, token.DEFER, token.ELSE, token.FALLTHROUGH, token.FOR, token .FUNC, token.GO, token.GOTO, token.IF, token.IMPORT, token.INTERFACE, token.MAP, token.PACKAGE, token.RANGE, token.RETURN, token.SELECT, token .STRUCT, token.SWITCH, token.TYPE, token.VAR, token.TILDE pkg/compiler/codegen.go:1709:2 exhaustive missing cases in switch of type token.Token: token.ILLEGAL, token.EOF, token .COMMENT, token.IDENT, token.INT, token.FLOAT, token.IMAG, token.CHAR, token.STRING, token.ADD, token.SUB, token.MUL, token.QUO, token.REM, token.AND, token.OR, token.XOR, token.SHL, token.SHR, token.AND_NOT, token.ADD_ASSIGN, token.SUB_ASSIGN, token.MUL_ASSIGN, token.QUO_ASSIGN, token.REM_ASSIGN, token.AND_ASSIGN, token.OR_ASSIGN, token.XOR_ASSIGN, token.SHL_ASSIGN, token.SHR_ASSIGN, token.AND_NOT_ASSIGN, token.LAND, token.LOR, token.ARROW, token.INC, token.DEC, token.ASSIGN, token.NOT, token.DEFINE, token.ELLIPSIS, token.LPAREN, token.LBRACK, token.LBRACE, token.COMMA, token.PERIOD, token.RPAREN, token.RBRACK, token.RBRACE, token.SEMICOLON, token.COLON, token.BREAK, token.CASE, token.CHAN, token .CONST, token.CONTINUE, token.DEFAULT, token.DEFER, token.ELSE, token .FALLTHROUGH, token.FOR, token.FUNC, token.GO, token.GOTO, token.IF, token.IMPORT, token.INTERFACE, token.MAP, token.PACKAGE, token.RANGE, token.RETURN, token.SELECT, token.STRUCT, token.SWITCH, token.TYPE, token.VAR, token.TILDE pkg/compiler/codegen.go:2353:3 exhaustive missing cases in switch of type opcode.Opcode: opcode.PUSHINT8, opcode .PUSHINT16, opcode.PUSHINT32, opcode.PUSHINT64, opcode.PUSHINT128, opcode.PUSHINT256, opcode.PUSHT, opcode.PUSHF, opcode.PUSHNULL, opcode .PUSHDATA1, opcode.PUSHDATA2, opcode.PUSHDATA4, opcode.PUSHM1, opcode .PUSH0, opcode.PUSH1, opcode.PUSH2, opcode.PUSH3, opcode.PUSH4, opcode .PUSH5, opcode.PUSH6, opcode.PUSH7, opcode.PUSH8, opcode.PUSH9, opcode .PUSH10, opcode.PUSH11, opcode.PUSH12, opcode.PUSH13, opcode.PUSH14, opcode.PUSH15, opcode.PUSH16, opcode.NOP, opcode.CALLA, opcode.CALLT, opcode.ABORT, opcode.ASSERT, opcode.THROW, opcode.TRY, opcode.ENDTRY, opcode.ENDFINALLY, opcode.RET, opcode.SYSCALL, opcode.DEPTH, opcode .DROP, opcode.NIP, opcode.XDROP, opcode.CLEAR, opcode.DUP, opcode.OVER, opcode.PICK, opcode.TUCK, opcode.SWAP, opcode.ROT, opcode.ROLL, opcode .REVERSE3, opcode.REVERSE4, opcode.REVERSEN, opcode.INITSSLOT, opcode .LDSFLD0, opcode.LDSFLD1, opcode.LDSFLD2, opcode.LDSFLD3, opcode .LDSFLD4, opcode.LDSFLD5, opcode.LDSFLD6, opcode.LDSFLD, opcode.STSFLD0, opcode.STSFLD1, opcode.STSFLD2, opcode.STSFLD3, opcode.STSFLD4, opcode .STSFLD5, opcode.STSFLD6, opcode.STSFLD, opcode.LDLOC0, opcode.LDLOC1, opcode.LDLOC2, opcode.LDLOC3, opcode.LDLOC4, opcode.LDLOC5, opcode .LDLOC6, opcode.LDLOC, opcode.STLOC0, opcode.STLOC1, opcode.STLOC2, opcode.STLOC3, opcode.STLOC4, opcode.STLOC5, opcode.STLOC6, opcode .STLOC, opcode.LDARG0, opcode.LDARG1, opcode.LDARG2, opcode.LDARG3, opcode.LDARG4, opcode.LDARG5, opcode.LDARG6, opcode.LDARG, opcode .STARG0, opcode.STARG1, opcode.STARG2, opcode.STARG3, opcode.STARG4, opcode.STARG5, opcode.STARG6, opcode.STARG, opcode.NEWBUFFER, opcode .MEMCPY, opcode.CAT, opcode.SUBSTR, opcode.LEFT, opcode.RIGHT, opcode .INVERT, opcode.AND, opcode.OR, opcode.XOR, opcode.EQUAL, opcode .NOTEQUAL, opcode.SIGN, opcode.ABS, opcode.NEGATE, opcode.INC, opcode .DEC, opcode.ADD, opcode.SUB, opcode.MUL, opcode.DIV, opcode.MOD, opcode.POW, opcode.SQRT, opcode.MODMUL, opcode.MODPOW, opcode.SHL, opcode.SHR, opcode.NOT, opcode.BOOLAND, opcode.BOOLOR, opcode.NZ, opcode.NUMEQUAL, opcode.NUMNOTEQUAL, opcode.LT, opcode.LE, opcode.GT, opcode.GE, opcode.MIN, opcode.MAX, opcode.WITHIN, opcode.PACKMAP, opcode.PACKSTRUCT, opcode.PACK, opcode.UNPACK, opcode.NEWARRAY0, opcode .NEWARRAY, opcode.NEWARRAYT, opcode.NEWSTRUCT0, opcode.NEWSTRUCT, opcode.NEWMAP, opcode.SIZE, opcode.HASKEY, opcode.KEYS, opcode.VALUES, opcode.PICKITEM, opcode.APPEND, opcode.SETITEM, opcode.REVERSEITEMS, opcode.REMOVE, opcode.CLEARITEMS, opcode.POPITEM, opcode.ISNULL, opcode .ISTYPE, opcode.CONVERT, opcode.ABORTMSG, opcode.ASSERTMSG pkg/compiler/codegen.go:2474:3 exhaustive missing cases in switch of type opcode.Opcode: opcode.PUSHINT8, opcode .PUSHINT16, opcode.PUSHINT32, opcode.PUSHINT64, opcode.PUSHINT128, opcode.PUSHINT256, opcode.PUSHT, opcode.PUSHF, opcode.PUSHNULL, opcode .PUSHDATA1, opcode.PUSHDATA2, opcode.PUSHDATA4, opcode.PUSHM1, opcode .PUSH0, opcode.PUSH1, opcode.PUSH2, opcode.PUSH3, opcode.PUSH4, opcode .PUSH5, opcode.PUSH6, opcode.PUSH7, opcode.PUSH8, opcode.PUSH9, opcode .PUSH10, opcode.PUSH11, opcode.PUSH12, opcode.PUSH13, opcode.PUSH14, opcode.PUSH15, opcode.PUSH16, opcode.NOP, opcode.CALLA, opcode.CALLT, opcode.ABORT, opcode.ASSERT, opcode.THROW, opcode.ENDFINALLY, opcode .RET, opcode.SYSCALL, opcode.DEPTH, opcode.DROP, opcode.NIP, opcode .XDROP, opcode.CLEAR, opcode.DUP, opcode.OVER, opcode.PICK, opcode.TUCK, opcode.SWAP, opcode.ROT, opcode.ROLL, opcode.REVERSE3, opcode.REVERSE4, opcode.REVERSEN, opcode.INITSSLOT, opcode.INITSLOT, opcode.LDSFLD0, opcode.LDSFLD1, opcode.LDSFLD2, opcode.LDSFLD3, opcode.LDSFLD4, opcode .LDSFLD5, opcode.LDSFLD6, opcode.LDSFLD, opcode.STSFLD0, opcode .STSFLD1, opcode.STSFLD2, opcode.STSFLD3, opcode.STSFLD4, opcode .STSFLD5, opcode.STSFLD6, opcode.STSFLD, opcode.LDLOC0, opcode.LDLOC1, opcode.LDLOC2, opcode.LDLOC3, opcode.LDLOC4, opcode.LDLOC5, opcode .LDLOC6, opcode.LDLOC, opcode.STLOC0, opcode.STLOC1, opcode.STLOC2, opcode.STLOC3, opcode.STLOC4, opcode.STLOC5, opcode.STLOC6, opcode .STLOC, opcode.LDARG0, opcode.LDARG1, opcode.LDARG2, opcode.LDARG3, opcode.LDARG4, opcode.LDARG5, opcode.LDARG6, opcode.LDARG, opcode .STARG0, opcode.STARG1, opcode.STARG2, opcode.STARG3, opcode.STARG4, opcode.STARG5, opcode.STARG6, opcode.STARG, opcode.NEWBUFFER, opcode .MEMCPY, opcode.CAT, opcode.SUBSTR, opcode.LEFT, opcode.RIGHT, opcode .INVERT, opcode.AND, opcode.OR, opcode.XOR, opcode.EQUAL, opcode .NOTEQUAL, opcode.SIGN, opcode.ABS, opcode.NEGATE, opcode.INC, opcode .DEC, opcode.ADD, opcode.SUB, opcode.MUL, opcode.DIV, opcode.MOD, opcode.POW, opcode.SQRT, opcode.MODMUL, opcode.MODPOW, opcode.SHL, opcode.SHR, opcode.NOT, opcode.BOOLAND, opcode.BOOLOR, opcode.NZ, opcode.NUMEQUAL, opcode.NUMNOTEQUAL, opcode.LT, opcode.LE, opcode.GT, opcode.GE, opcode.MIN, opcode.MAX, opcode.WITHIN, opcode.PACKMAP, opcode.PACKSTRUCT, opcode.PACK, opcode.UNPACK, opcode.NEWARRAY0, opcode.NEWARRAY, opcode.NEWARRAYT, opcode.NEWSTRUCT0, opcode .NEWSTRUCT, opcode.NEWMAP, opcode.SIZE, opcode.HASKEY, opcode.KEYS, opcode.VALUES, opcode.PICKITEM, opcode.APPEND, opcode.SETITEM, opcode.REVERSEITEMS, opcode.REMOVE, opcode.CLEARITEMS, opcode .POPITEM, opcode.ISNULL, opcode.ISTYPE, opcode.CONVERT, opcode .ABORTMSG, opcode.ASSERTMSG pkg/compiler/inline_test.go:34:3 exhaustive missing cases in switch of type opcode.Opcode: opcode.PUSHINT8, opcode .PUSHINT16, opcode.PUSHINT32, opcode.PUSHINT64, opcode.PUSHINT128, opcode.PUSHINT256, opcode.PUSHT, opcode.PUSHF, opcode.PUSHA, opcode .PUSHNULL, opcode.PUSHDATA1, opcode.PUSHDATA2, opcode.PUSHDATA4, opcode .PUSHM1, opcode.PUSH0, opcode.PUSH1, opcode.PUSH2, opcode.PUSH3, opcode .PUSH4, opcode.PUSH5, opcode.PUSH6, opcode.PUSH7, opcode.PUSH8, opcode .PUSH9, opcode.PUSH10, opcode.PUSH11, opcode.PUSH12, opcode.PUSH13, opcode.PUSH14, opcode.PUSH15, opcode.PUSH16, opcode.NOP, opcode.JMP, opcode.JMPL, opcode.JMPIF, opcode.JMPIFL, opcode.JMPIFNOT, opcode .JMPIFNOTL, opcode.JMPEQ, opcode.JMPEQL, opcode.JMPNE, opcode.JMPNEL, opcode.JMPGT, opcode.JMPGTL, opcode.JMPGE, opcode.JMPGEL, opcode.JMPLT, opcode.JMPLTL, opcode.JMPLE, opcode.JMPLEL, opcode.CALLA, opcode.CALLT, opcode.ABORT, opcode.ASSERT, opcode.THROW, opcode.TRY, opcode.TRYL, opcode.ENDTRY, opcode.ENDTRYL, opcode.ENDFINALLY, opcode.RET, opcode .SYSCALL, opcode.DEPTH, opcode.DROP, opcode.NIP, opcode.XDROP, opcode .CLEAR, opcode.DUP, opcode.OVER, opcode.PICK, opcode.TUCK, opcode.SWAP, opcode.ROT, opcode.ROLL, opcode.REVERSE3, opcode.REVERSE4, opcode .REVERSEN, opcode.LDSFLD0, opcode.LDSFLD1, opcode.LDSFLD2, opcode .LDSFLD3, opcode.LDSFLD4, opcode.LDSFLD5, opcode.LDSFLD6, opcode.LDSFLD, opcode.STSFLD0, opcode.STSFLD1, opcode.STSFLD2, opcode.STSFLD3, opcode .STSFLD4, opcode.STSFLD5, opcode.STSFLD6, opcode.STSFLD, opcode.LDLOC0, opcode.LDLOC1, opcode.LDLOC2, opcode.LDLOC3, opcode.LDLOC4, opcode .LDLOC5, opcode.LDLOC6, opcode.LDLOC, opcode.STLOC0, opcode.STLOC1, opcode.STLOC2, opcode.STLOC3, opcode.STLOC4, opcode.STLOC5, opcode .STLOC6, opcode.STLOC, opcode.LDARG0, opcode.LDARG1, opcode.LDARG2, opcode.LDARG3, opcode.LDARG4, opcode.LDARG5, opcode.LDARG6, opcode .LDARG, opcode.STARG0, opcode.STARG1, opcode.STARG2, opcode.STARG3, opcode.STARG4, opcode.STARG5, opcode.STARG6, opcode.STARG, opcode .NEWBUFFER, opcode.MEMCPY, opcode.CAT, opcode.SUBSTR, opcode.LEFT, opcode.RIGHT, opcode.INVERT, opcode.AND, opcode.OR, opcode.XOR, opcode .EQUAL, opcode.NOTEQUAL, opcode.SIGN, opcode.ABS, opcode.NEGATE, opcode.INC, opcode.DEC, opcode.ADD, opcode.SUB, opcode.MUL, opcode .DIV, opcode.MOD, opcode.POW, opcode.SQRT, opcode.MODMUL, opcode .MODPOW, opcode.SHL, opcode.SHR, opcode.NOT, opcode.BOOLAND, opcode .BOOLOR, opcode.NZ, opcode.NUMEQUAL, opcode.NUMNOTEQUAL, opcode.LT, opcode.LE, opcode.GT, opcode.GE, opcode.MIN, opcode.MAX, opcode .WITHIN, opcode.PACKMAP, opcode.PACKSTRUCT, opcode.PACK, opcode .UNPACK, opcode.NEWARRAY0, opcode.NEWARRAY, opcode.NEWARRAYT, opcode .NEWSTRUCT0, opcode.NEWSTRUCT, opcode.NEWMAP, opcode.SIZE, opcode .HASKEY, opcode.KEYS, opcode.VALUES, opcode.PICKITEM, opcode.APPEND, opcode.SETITEM, opcode.REVERSEITEMS, opcode.REMOVE, opcode.CLEARITEMS, opcode.POPITEM, opcode.ISNULL, opcode.ISTYPE, opcode.CONVERT, opcode .ABORTMSG, opcode.ASSERTMSG pkg/network/server.go:1395:3 exhaustive missing cases in switch of type network.CommandType: network.CMDNotFound, network.CMDReject, network.CMDFilterLoad, network.CMDFilterAdd, network .CMDFilterClear, network.CMDMerkleBlock, network.CMDAlert pkg/network/server_test.go:532:3 exhaustive missing cases in switch of type network.CommandType: network.CMDVersion, network .CMDVerack, network.CMDGetAddr, network.CMDAddr, network.CMDPing, network.CMDPong, network.CMDGetHeaders, network.CMDHeaders, network .CMDGetBlocks, network.CMDMempool, network.CMDInv, network.CMDGetData, network.CMDGetBlockByIndex, network.CMDGetMPTData, network.CMDMPTData, network.CMDReject, network.CMDFilterLoad, network.CMDFilterAdd, network .CMDFilterClear, network.CMDMerkleBlock, network.CMDAlert pkg/network/server_test.go:817:4 exhaustive missing cases in switch of type network.CommandType: network.CMDVersion, network .CMDVerack, network.CMDGetAddr, network.CMDAddr, network.CMDPing, network.CMDPong, network.CMDGetHeaders, network.CMDHeaders, network .CMDGetBlocks, network.CMDMempool, network.CMDInv, network.CMDGetData, network.CMDGetBlockByIndex, network.CMDNotFound, network.CMDTX, network .CMDBlock, network.CMDExtensible, network.CMDP2PNotaryRequest, network .CMDGetMPTData, network.CMDReject, network.CMDFilterLoad, network .CMDFilterAdd, network.CMDFilterClear, network.CMDMerkleBlock, network .CMDAlert pkg/core/native/designate.go:262:2 exhaustive missing cases in switch of type noderoles.Role: noderoles.NeoFSAlphabet pkg/neorpc/rpcevent/filter.go:36:2 exhaustive missing cases in switch of type neorpc.EventID: neorpc.InvalidEventID, neorpc.MissedEventID pkg/consensus/recovery_message.go:145:2 exhaustive missing cases in switch of type dbft.MessageType: dbft.PreCommitType, dbft .RecoveryRequestType, dbft.RecoveryMessageType cli/cmdargs/parser.go:202:3 exhaustive missing cases in switch of type transaction.WitnessScope: transaction.None, transaction.CalledByEntry, transaction.Rules, transaction.Global ``` Signed-off-by: Ekaterina Pavlova <ekt@morphbits.io>
465 lines
9.3 KiB
Go
465 lines
9.3 KiB
Go
package jsonpath
|
|
|
|
import (
|
|
"strconv"
|
|
"strings"
|
|
|
|
json "github.com/nspcc-dev/go-ordered-json"
|
|
)
|
|
|
|
type (
|
|
// pathTokenType represents a single JSONPath token.
|
|
pathTokenType byte
|
|
|
|
// pathParser combines a JSONPath and a position to start parsing from.
|
|
pathParser struct {
|
|
s string
|
|
i int
|
|
depth int
|
|
}
|
|
)
|
|
|
|
const (
|
|
pathInvalid pathTokenType = iota
|
|
pathRoot
|
|
pathDot
|
|
pathLeftBracket
|
|
pathRightBracket
|
|
pathAsterisk
|
|
pathComma
|
|
pathColon
|
|
pathIdentifier
|
|
pathString
|
|
pathNumber
|
|
)
|
|
|
|
const (
|
|
maxNestingDepth = 6
|
|
maxObjects = 1024
|
|
)
|
|
|
|
// Get returns substructures of value selected by path.
|
|
// The result is always non-nil unless the path is invalid.
|
|
func Get(path string, value any) ([]any, bool) {
|
|
if path == "" {
|
|
return []any{value}, true
|
|
}
|
|
|
|
p := pathParser{
|
|
depth: maxNestingDepth,
|
|
s: path,
|
|
}
|
|
|
|
typ, _ := p.nextToken()
|
|
if typ != pathRoot {
|
|
return nil, false
|
|
}
|
|
|
|
objs := []any{value}
|
|
for p.i < len(p.s) {
|
|
var ok bool
|
|
|
|
switch typ, _ := p.nextToken(); typ {
|
|
case pathDot:
|
|
objs, ok = p.processDot(objs)
|
|
case pathLeftBracket:
|
|
objs, ok = p.processLeftBracket(objs)
|
|
default:
|
|
}
|
|
|
|
if !ok || maxObjects < len(objs) {
|
|
return nil, false
|
|
}
|
|
}
|
|
|
|
if objs == nil {
|
|
objs = []any{}
|
|
}
|
|
return objs, true
|
|
}
|
|
|
|
func (p *pathParser) nextToken() (pathTokenType, string) {
|
|
var (
|
|
typ pathTokenType
|
|
value string
|
|
ok = true
|
|
numRead = 1
|
|
)
|
|
|
|
if p.i >= len(p.s) {
|
|
return pathInvalid, ""
|
|
}
|
|
|
|
switch c := p.s[p.i]; c {
|
|
case '$':
|
|
typ = pathRoot
|
|
case '.':
|
|
typ = pathDot
|
|
case '[':
|
|
typ = pathLeftBracket
|
|
case ']':
|
|
typ = pathRightBracket
|
|
case '*':
|
|
typ = pathAsterisk
|
|
case ',':
|
|
typ = pathComma
|
|
case ':':
|
|
typ = pathColon
|
|
case '\'':
|
|
typ = pathString
|
|
value, numRead, ok = p.parseString()
|
|
default:
|
|
switch {
|
|
case c == '_' || ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z'):
|
|
typ = pathIdentifier
|
|
value, numRead, ok = p.parseIdent()
|
|
case c == '-' || ('0' <= c && c <= '9'):
|
|
typ = pathNumber
|
|
value, numRead, ok = p.parseNumber()
|
|
default:
|
|
return pathInvalid, ""
|
|
}
|
|
}
|
|
|
|
if !ok {
|
|
return pathInvalid, ""
|
|
}
|
|
|
|
p.i += numRead
|
|
return typ, value
|
|
}
|
|
|
|
// parseString parses a JSON string surrounded by single quotes.
|
|
// It returns the number of characters consumed and true on success.
|
|
func (p *pathParser) parseString() (string, int, bool) {
|
|
var end int
|
|
for end = p.i + 1; end < len(p.s); end++ {
|
|
if p.s[end] == '\'' {
|
|
return p.s[p.i : end+1], end + 1 - p.i, true
|
|
}
|
|
}
|
|
|
|
return "", 0, false
|
|
}
|
|
|
|
// parseIdent parses an alphanumeric identifier.
|
|
// It returns the number of characters consumed and true on success.
|
|
func (p *pathParser) parseIdent() (string, int, bool) {
|
|
var end int
|
|
for end = p.i + 1; end < len(p.s); end++ {
|
|
c := p.s[end]
|
|
if c != '_' && !('a' <= c && c <= 'z') &&
|
|
!('A' <= c && c <= 'Z') && !('0' <= c && c <= '9') {
|
|
break
|
|
}
|
|
}
|
|
|
|
return p.s[p.i:end], end - p.i, true
|
|
}
|
|
|
|
// parseNumber parses an integer number.
|
|
// Only string representation is returned, size-checking is done on the first use.
|
|
// It also returns the number of characters consumed and true on success.
|
|
func (p *pathParser) parseNumber() (string, int, bool) {
|
|
var end int
|
|
for end = p.i + 1; end < len(p.s); end++ {
|
|
c := p.s[end]
|
|
if c < '0' || '9' < c {
|
|
break
|
|
}
|
|
}
|
|
|
|
return p.s[p.i:end], end - p.i, true
|
|
}
|
|
|
|
// processDot handles `.` operator.
|
|
// It either descends 1 level down or performs recursive descent.
|
|
func (p *pathParser) processDot(objs []any) ([]any, bool) {
|
|
typ, value := p.nextToken()
|
|
switch typ {
|
|
case pathAsterisk:
|
|
return p.descend(objs)
|
|
case pathDot:
|
|
return p.descendRecursive(objs)
|
|
case pathIdentifier:
|
|
return p.descendByIdent(objs, value)
|
|
default:
|
|
return nil, false
|
|
}
|
|
}
|
|
|
|
// descend descends 1 level down.
|
|
// It flattens arrays and returns map values for maps.
|
|
func (p *pathParser) descend(objs []any) ([]any, bool) {
|
|
if p.depth <= 0 {
|
|
return nil, false
|
|
}
|
|
p.depth--
|
|
|
|
var values []any
|
|
for i := range objs {
|
|
switch obj := objs[i].(type) {
|
|
case []any:
|
|
if maxObjects < len(values)+len(obj) {
|
|
return nil, false
|
|
}
|
|
values = append(values, obj...)
|
|
case json.OrderedObject:
|
|
if maxObjects < len(values)+len(obj) {
|
|
return nil, false
|
|
}
|
|
for i := range obj {
|
|
values = append(values, obj[i].Value)
|
|
}
|
|
}
|
|
}
|
|
|
|
return values, true
|
|
}
|
|
|
|
// descendRecursive performs recursive descent.
|
|
func (p *pathParser) descendRecursive(objs []any) ([]any, bool) {
|
|
typ, val := p.nextToken()
|
|
if typ != pathIdentifier {
|
|
return nil, false
|
|
}
|
|
|
|
var values []any
|
|
|
|
for len(objs) > 0 {
|
|
newObjs, _ := p.descendByIdentAux(objs, false, val)
|
|
if maxObjects < len(values)+len(newObjs) {
|
|
return nil, false
|
|
}
|
|
values = append(values, newObjs...)
|
|
objs, _ = p.descend(objs)
|
|
}
|
|
|
|
return values, true
|
|
}
|
|
|
|
// descendByIdent performs map's field access by name.
|
|
func (p *pathParser) descendByIdent(objs []any, names ...string) ([]any, bool) {
|
|
return p.descendByIdentAux(objs, true, names...)
|
|
}
|
|
|
|
func (p *pathParser) descendByIdentAux(objs []any, checkDepth bool, names ...string) ([]any, bool) {
|
|
if checkDepth {
|
|
if p.depth <= 0 {
|
|
return nil, false
|
|
}
|
|
p.depth--
|
|
}
|
|
|
|
var values []any
|
|
for i := range objs {
|
|
obj, ok := objs[i].(json.OrderedObject)
|
|
if !ok {
|
|
continue
|
|
}
|
|
|
|
for j := range names {
|
|
for k := range obj {
|
|
if obj[k].Key == names[j] {
|
|
if maxObjects < len(values)+1 {
|
|
return nil, false
|
|
}
|
|
values = append(values, obj[k].Value)
|
|
break
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return values, true
|
|
}
|
|
|
|
// descendByIndex performs array access by index.
|
|
func (p *pathParser) descendByIndex(objs []any, indices ...int) ([]any, bool) {
|
|
if p.depth <= 0 {
|
|
return nil, false
|
|
}
|
|
p.depth--
|
|
|
|
var values []any
|
|
for i := range objs {
|
|
obj, ok := objs[i].([]any)
|
|
if !ok {
|
|
continue
|
|
}
|
|
|
|
for _, j := range indices {
|
|
if j < 0 {
|
|
j += len(obj)
|
|
}
|
|
if 0 <= j && j < len(obj) {
|
|
if maxObjects < len(values)+1 {
|
|
return nil, false
|
|
}
|
|
values = append(values, obj[j])
|
|
}
|
|
}
|
|
}
|
|
|
|
return values, true
|
|
}
|
|
|
|
// processLeftBracket processes index expressions which can be either
|
|
// array/map access, array sub-slice or union of indices.
|
|
func (p *pathParser) processLeftBracket(objs []any) ([]any, bool) {
|
|
typ, value := p.nextToken()
|
|
switch typ {
|
|
case pathAsterisk:
|
|
typ, _ := p.nextToken()
|
|
if typ != pathRightBracket {
|
|
return nil, false
|
|
}
|
|
|
|
return p.descend(objs)
|
|
case pathColon:
|
|
return p.processSlice(objs, 0)
|
|
case pathNumber:
|
|
subTyp, _ := p.nextToken()
|
|
switch subTyp {
|
|
case pathColon:
|
|
index, err := strconv.ParseInt(value, 10, 32)
|
|
if err != nil {
|
|
return nil, false
|
|
}
|
|
|
|
return p.processSlice(objs, int(index))
|
|
case pathComma:
|
|
return p.processUnion(objs, pathNumber, value)
|
|
case pathRightBracket:
|
|
index, err := strconv.ParseInt(value, 10, 32)
|
|
if err != nil {
|
|
return nil, false
|
|
}
|
|
|
|
return p.descendByIndex(objs, int(index))
|
|
default:
|
|
return nil, false
|
|
}
|
|
case pathString:
|
|
subTyp, _ := p.nextToken()
|
|
switch subTyp {
|
|
case pathComma:
|
|
return p.processUnion(objs, pathString, value)
|
|
case pathRightBracket:
|
|
s := strings.Trim(value, "'")
|
|
err := json.Unmarshal([]byte(`"`+s+`"`), &s)
|
|
if err != nil {
|
|
return nil, false
|
|
}
|
|
return p.descendByIdent(objs, s)
|
|
default:
|
|
return nil, false
|
|
}
|
|
default:
|
|
return nil, false
|
|
}
|
|
}
|
|
|
|
// processUnion processes union of multiple indices.
|
|
// firstTyp is assumed to be either pathNumber or pathString.
|
|
func (p *pathParser) processUnion(objs []any, firstTyp pathTokenType, firstVal string) ([]any, bool) {
|
|
items := []string{firstVal}
|
|
for {
|
|
typ, val := p.nextToken()
|
|
if typ != firstTyp {
|
|
return nil, false
|
|
}
|
|
|
|
items = append(items, val)
|
|
typ, _ = p.nextToken()
|
|
if typ == pathRightBracket {
|
|
break
|
|
} else if typ != pathComma {
|
|
return nil, false
|
|
}
|
|
}
|
|
|
|
switch firstTyp {
|
|
case pathNumber:
|
|
values := make([]int, len(items))
|
|
for i := range items {
|
|
index, err := strconv.ParseInt(items[i], 10, 32)
|
|
if err != nil {
|
|
return nil, false
|
|
}
|
|
values[i] = int(index)
|
|
}
|
|
return p.descendByIndex(objs, values...)
|
|
case pathString:
|
|
for i := range items {
|
|
s := strings.Trim(items[i], "'")
|
|
err := json.Unmarshal([]byte(`"`+s+`"`), &items[i])
|
|
if err != nil {
|
|
return nil, false
|
|
}
|
|
}
|
|
return p.descendByIdent(objs, items...)
|
|
default:
|
|
panic("token in union must be either number or string")
|
|
}
|
|
}
|
|
|
|
// processSlice processes a slice with the specified start index.
|
|
func (p *pathParser) processSlice(objs []any, start int) ([]any, bool) {
|
|
typ, val := p.nextToken()
|
|
switch typ {
|
|
case pathNumber:
|
|
typ, _ := p.nextToken()
|
|
if typ != pathRightBracket {
|
|
return nil, false
|
|
}
|
|
|
|
index, err := strconv.ParseInt(val, 10, 32)
|
|
if err != nil {
|
|
return nil, false
|
|
}
|
|
|
|
return p.descendByRange(objs, start, int(index))
|
|
case pathRightBracket:
|
|
return p.descendByRange(objs, start, 0)
|
|
default:
|
|
return nil, false
|
|
}
|
|
}
|
|
|
|
// descendByRange is similar to descend but skips maps and returns sub-slices for arrays.
|
|
func (p *pathParser) descendByRange(objs []any, start, end int) ([]any, bool) {
|
|
if p.depth <= 0 {
|
|
return nil, false
|
|
}
|
|
p.depth--
|
|
|
|
var values []any
|
|
for i := range objs {
|
|
arr, ok := objs[i].([]any)
|
|
if !ok {
|
|
continue
|
|
}
|
|
|
|
subStart := start
|
|
if subStart < 0 {
|
|
subStart += len(arr)
|
|
}
|
|
|
|
subEnd := end
|
|
if subEnd <= 0 {
|
|
subEnd += len(arr)
|
|
}
|
|
|
|
subEnd = min(subEnd, len(arr))
|
|
|
|
if subEnd <= subStart {
|
|
continue
|
|
}
|
|
if maxObjects < len(values)+subEnd-subStart {
|
|
return nil, false
|
|
}
|
|
values = append(values, arr[subStart:subEnd]...)
|
|
}
|
|
|
|
return values, true
|
|
}
|