slidge-whatsapp 0.2.6__cp313-cp313-manylinux_2_36_aarch64.whl → 0.3.0__cp313-cp313-manylinux_2_36_aarch64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of slidge-whatsapp might be problematic. Click here for more details.
- slidge_whatsapp/contact.py +15 -3
- slidge_whatsapp/event.go +152 -50
- slidge_whatsapp/gateway.go +7 -63
- slidge_whatsapp/gateway.py +2 -3
- slidge_whatsapp/generated/_whatsapp.cpython-313-aarch64-linux-gnu.h +180 -163
- slidge_whatsapp/generated/_whatsapp.cpython-313-aarch64-linux-gnu.so +0 -0
- slidge_whatsapp/generated/build.py +145 -131
- slidge_whatsapp/generated/whatsapp.c +1669 -1397
- slidge_whatsapp/generated/whatsapp.go +1209 -1098
- slidge_whatsapp/generated/whatsapp.py +1175 -1050
- slidge_whatsapp/generated/whatsapp_go.h +180 -163
- slidge_whatsapp/go.mod +18 -15
- slidge_whatsapp/go.sum +38 -32
- slidge_whatsapp/group.py +34 -30
- slidge_whatsapp/media/media.go +6 -2
- slidge_whatsapp/session.go +34 -17
- slidge_whatsapp/session.py +46 -14
- slidge_whatsapp/vendor/github.com/beeper/argo-go/LICENSE +9 -0
- slidge_whatsapp/vendor/github.com/beeper/argo-go/block/blockreader.go +329 -0
- slidge_whatsapp/vendor/github.com/beeper/argo-go/block/blockwriter.go +417 -0
- slidge_whatsapp/vendor/github.com/beeper/argo-go/codec/decoder.go +652 -0
- slidge_whatsapp/vendor/github.com/beeper/argo-go/codec/encoder.go +985 -0
- slidge_whatsapp/vendor/github.com/beeper/argo-go/header/header.go +135 -0
- slidge_whatsapp/vendor/github.com/beeper/argo-go/internal/util/util.go +133 -0
- slidge_whatsapp/vendor/github.com/beeper/argo-go/label/label.go +384 -0
- slidge_whatsapp/vendor/github.com/beeper/argo-go/label/wiremarkers.go +37 -0
- slidge_whatsapp/vendor/github.com/beeper/argo-go/pkg/bitset/bitset.go +197 -0
- slidge_whatsapp/vendor/github.com/beeper/argo-go/pkg/buf/buf.go +420 -0
- slidge_whatsapp/vendor/github.com/beeper/argo-go/pkg/varint/varint.go +246 -0
- slidge_whatsapp/vendor/github.com/beeper/argo-go/wire/wire.go +614 -0
- slidge_whatsapp/vendor/github.com/beeper/argo-go/wirecodec/decode.go +341 -0
- slidge_whatsapp/vendor/github.com/elliotchance/orderedmap/v3/LICENSE +21 -0
- slidge_whatsapp/vendor/github.com/elliotchance/orderedmap/v3/list.go +95 -0
- slidge_whatsapp/vendor/github.com/elliotchance/orderedmap/v3/orderedmap.go +187 -0
- slidge_whatsapp/vendor/github.com/gen2brain/go-fitz/fitz.go +1 -0
- slidge_whatsapp/vendor/github.com/gen2brain/go-fitz/fitz_cgo.go +3 -0
- slidge_whatsapp/vendor/github.com/gen2brain/go-fitz/fitz_nocgo.go +4 -5
- slidge_whatsapp/vendor/github.com/gen2brain/go-fitz/purego_darwin.go +11 -1
- slidge_whatsapp/vendor/github.com/gen2brain/go-fitz/purego_linux.go +10 -0
- slidge_whatsapp/vendor/github.com/gen2brain/go-fitz/purego_windows.go +12 -0
- slidge_whatsapp/vendor/github.com/jupiterrider/ffi/.gitignore +0 -2
- slidge_whatsapp/vendor/github.com/jupiterrider/ffi/CHANGELOG.md +30 -0
- slidge_whatsapp/vendor/github.com/jupiterrider/ffi/COPYRIGHT.txt +6 -1
- slidge_whatsapp/vendor/github.com/jupiterrider/ffi/README.md +14 -17
- slidge_whatsapp/vendor/github.com/jupiterrider/ffi/abi.go +1 -1
- slidge_whatsapp/vendor/github.com/jupiterrider/ffi/abi2.go +7 -0
- slidge_whatsapp/vendor/github.com/jupiterrider/ffi/assets/libffi/LICENSE +21 -0
- slidge_whatsapp/vendor/github.com/jupiterrider/ffi/assets/libffi/darwin_amd64/libffi.8.dylib +0 -0
- slidge_whatsapp/vendor/github.com/jupiterrider/ffi/assets/libffi/darwin_arm64/libffi.8.dylib +0 -0
- slidge_whatsapp/vendor/github.com/jupiterrider/ffi/assets/libffi/windows_amd64/libffi-8.dll +0 -0
- slidge_whatsapp/vendor/github.com/jupiterrider/ffi/cif.go +15 -0
- slidge_whatsapp/vendor/github.com/jupiterrider/ffi/cif_arm64.go +16 -0
- slidge_whatsapp/vendor/github.com/jupiterrider/ffi/embed.go +49 -0
- slidge_whatsapp/vendor/github.com/jupiterrider/ffi/embed_darwin_amd64.go +10 -0
- slidge_whatsapp/vendor/github.com/jupiterrider/ffi/embed_darwin_arm64.go +10 -0
- slidge_whatsapp/vendor/github.com/jupiterrider/ffi/embed_windows_amd64.go +10 -0
- slidge_whatsapp/vendor/github.com/jupiterrider/ffi/ffi.go +51 -13
- slidge_whatsapp/vendor/github.com/jupiterrider/ffi/init.go +22 -9
- slidge_whatsapp/vendor/github.com/mattn/go-sqlite3/README.md +2 -0
- slidge_whatsapp/vendor/github.com/mattn/go-sqlite3/sqlite3-binding.c +3096 -1651
- slidge_whatsapp/vendor/github.com/mattn/go-sqlite3/sqlite3-binding.h +188 -128
- slidge_whatsapp/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_userauth.go +13 -140
- slidge_whatsapp/vendor/github.com/mattn/go-sqlite3/sqlite3ext.h +4 -0
- slidge_whatsapp/vendor/github.com/petermattis/goid/runtime_go1.23.go +2 -2
- slidge_whatsapp/vendor/github.com/petermattis/goid/runtime_go1.25.go +37 -0
- slidge_whatsapp/vendor/github.com/vektah/gqlparser/v2/LICENSE +19 -0
- slidge_whatsapp/vendor/github.com/vektah/gqlparser/v2/ast/argmap.go +37 -0
- slidge_whatsapp/vendor/github.com/vektah/gqlparser/v2/ast/collections.go +148 -0
- slidge_whatsapp/vendor/github.com/vektah/gqlparser/v2/ast/comment.go +31 -0
- slidge_whatsapp/vendor/github.com/vektah/gqlparser/v2/ast/decode.go +216 -0
- slidge_whatsapp/vendor/github.com/vektah/gqlparser/v2/ast/definition.go +110 -0
- slidge_whatsapp/vendor/github.com/vektah/gqlparser/v2/ast/directive.go +43 -0
- slidge_whatsapp/vendor/github.com/vektah/gqlparser/v2/ast/document.go +89 -0
- slidge_whatsapp/vendor/github.com/vektah/gqlparser/v2/ast/dumper.go +159 -0
- slidge_whatsapp/vendor/github.com/vektah/gqlparser/v2/ast/fragment.go +41 -0
- slidge_whatsapp/vendor/github.com/vektah/gqlparser/v2/ast/operation.go +32 -0
- slidge_whatsapp/vendor/github.com/vektah/gqlparser/v2/ast/path.go +72 -0
- slidge_whatsapp/vendor/github.com/vektah/gqlparser/v2/ast/selection.go +41 -0
- slidge_whatsapp/vendor/github.com/vektah/gqlparser/v2/ast/source.go +19 -0
- slidge_whatsapp/vendor/github.com/vektah/gqlparser/v2/ast/type.go +68 -0
- slidge_whatsapp/vendor/github.com/vektah/gqlparser/v2/ast/value.go +122 -0
- slidge_whatsapp/vendor/go.mau.fi/util/exhttp/handleerrors.go +60 -26
- slidge_whatsapp/vendor/go.mau.fi/util/exhttp/json.go +1 -6
- slidge_whatsapp/vendor/go.mau.fi/util/exhttp/networkerror.go +2 -1
- slidge_whatsapp/vendor/go.mau.fi/util/exstrings/stringutil.go +104 -0
- slidge_whatsapp/vendor/go.mau.fi/util/exsync/event.go +19 -3
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/.pre-commit-config.yaml +3 -3
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/appstate/decode.go +1 -1
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/appstate/hash.go +1 -1
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/appstate.go +5 -1
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/argo/argo-wire-type-store.argo +63 -0
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/argo/argo.go +62 -0
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/argo/name-to-queryids.json +306 -0
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/armadillomessage.go +40 -7
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/binary/encoder.go +1 -1
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/call.go +2 -1
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/client.go +79 -45
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/connectionevents.go +13 -6
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/download-to-file.go +19 -12
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/download.go +26 -6
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/errors.go +3 -0
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/group.go +99 -27
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/internals.go +54 -26
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/keepalive.go +1 -0
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/message.go +208 -57
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/msgsecret.go +2 -14
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/newsletter.go +83 -7
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/notification.go +17 -8
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/pair-code.go +2 -2
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/presence.go +15 -6
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/extra.go +7 -0
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloAddMessage/InstamadilloAddMessage.pb.go +983 -0
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloAddMessage/InstamadilloAddMessage.proto +85 -0
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloAddMessage/extra.go +3 -0
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloCoreTypeActionLog/InstamadilloCoreTypeActionLog.pb.go +197 -0
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloCoreTypeActionLog/InstamadilloCoreTypeActionLog.proto +13 -0
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloCoreTypeAdminMessage/InstamadilloCoreTypeAdminMessage.pb.go +279 -0
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloCoreTypeAdminMessage/InstamadilloCoreTypeAdminMessage.proto +21 -0
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloCoreTypeCollection/InstamadilloCoreTypeCollection.pb.go +137 -0
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloCoreTypeCollection/InstamadilloCoreTypeCollection.proto +10 -0
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloCoreTypeLink/InstamadilloCoreTypeLink.pb.go +313 -0
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloCoreTypeLink/InstamadilloCoreTypeLink.proto +27 -0
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloCoreTypeMedia/InstamadilloCoreTypeMedia.pb.go +1299 -0
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloCoreTypeMedia/InstamadilloCoreTypeMedia.proto +112 -0
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloCoreTypeText/InstamadilloCoreTypeText.pb.go +514 -0
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloCoreTypeText/InstamadilloCoreTypeText.proto +47 -0
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloDeleteMessage/InstamadilloDeleteMessage.pb.go +123 -0
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloDeleteMessage/InstamadilloDeleteMessage.proto +7 -0
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloDeleteMessage/extra.go +3 -0
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloSupplementMessage/InstamadilloSupplementMessage.pb.go +720 -0
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloSupplementMessage/InstamadilloSupplementMessage.proto +59 -0
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloSupplementMessage/extra.go +3 -0
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloTransportPayload/InstamadilloTransportPayload.pb.go +365 -0
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloTransportPayload/InstamadilloTransportPayload.proto +33 -0
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloXmaContentRef/InstamadilloXmaContentRef.pb.go +1238 -0
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloXmaContentRef/InstamadilloXmaContentRef.proto +105 -0
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waArmadilloXMA/WAArmadilloXMA.pb.go +16 -4
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waArmadilloXMA/WAArmadilloXMA.proto +3 -0
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waBotMetadata/WABotMetadata.pb.go +5156 -0
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waBotMetadata/WABotMetadata.proto +516 -0
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waCompanionReg/WACompanionReg.pb.go +46 -10
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waCompanionReg/WACompanionReg.proto +4 -0
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waE2E/WAWebProtobufsE2E.pb.go +8975 -11209
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waE2E/WAWebProtobufsE2E.proto +193 -421
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waHistorySync/WAWebProtobufsHistorySync.pb.go +52 -23
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waHistorySync/WAWebProtobufsHistorySync.proto +3 -0
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waLidMigrationSyncPayload/WAWebProtobufLidMigrationSyncPayload.pb.go +198 -0
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waLidMigrationSyncPayload/WAWebProtobufLidMigrationSyncPayload.proto +14 -0
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waMsgTransport/extra.go +7 -6
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waStatusAttributions/WAStatusAttributions.pb.go +952 -0
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waStatusAttributions/WAStatusAttributions.proto +88 -0
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waSyncAction/WASyncAction.pb.go +1143 -463
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waSyncAction/WASyncAction.proto +60 -0
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waWa6/WAWebProtobufsWa6.pb.go +60 -38
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waWa6/WAWebProtobufsWa6.proto +3 -0
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waWeb/WAWebProtobufsWeb.pb.go +11 -3
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waWeb/WAWebProtobufsWeb.proto +2 -0
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/receipt.go +20 -7
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/reportingfields.json +1 -0
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/reportingtoken.go +176 -0
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/retry.go +10 -2
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/send.go +38 -21
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/sendfb.go +1 -0
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/store/clientpayload.go +1 -1
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/store/noop.go +3 -2
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/store/sqlstore/container.go +9 -6
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/store/sqlstore/store.go +25 -5
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/store/sqlstore/upgrades/00-latest-schema.sql +4 -2
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/store/sqlstore/upgrades/10-chat-db-lid-migration-ts.sql +2 -0
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/store/store.go +5 -1
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/types/call.go +1 -0
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/types/events/events.go +13 -2
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/types/jid.go +2 -1
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/types/message.go +1 -0
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/types/user.go +2 -0
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/user.go +14 -8
- slidge_whatsapp/vendor/golang.org/x/crypto/curve25519/curve25519.go +1 -1
- slidge_whatsapp/vendor/golang.org/x/net/http2/config.go +44 -2
- slidge_whatsapp/vendor/golang.org/x/net/http2/frame.go +8 -8
- slidge_whatsapp/vendor/golang.org/x/net/http2/gotrack.go +14 -3
- slidge_whatsapp/vendor/golang.org/x/net/http2/http2.go +7 -29
- slidge_whatsapp/vendor/golang.org/x/net/http2/server.go +53 -71
- slidge_whatsapp/vendor/golang.org/x/net/http2/transport.go +20 -74
- slidge_whatsapp/vendor/golang.org/x/sys/unix/affinity_linux.go +1 -3
- slidge_whatsapp/vendor/golang.org/x/sys/unix/mkerrors.sh +3 -0
- slidge_whatsapp/vendor/golang.org/x/sys/unix/syscall_darwin.go +1 -55
- slidge_whatsapp/vendor/golang.org/x/sys/unix/syscall_solaris.go +1 -1
- slidge_whatsapp/vendor/golang.org/x/sys/unix/zerrors_linux.go +47 -16
- slidge_whatsapp/vendor/golang.org/x/sys/unix/zerrors_linux_386.go +3 -0
- slidge_whatsapp/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go +3 -0
- slidge_whatsapp/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go +3 -0
- slidge_whatsapp/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go +3 -0
- slidge_whatsapp/vendor/golang.org/x/sys/unix/zerrors_linux_loong64.go +3 -0
- slidge_whatsapp/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go +3 -0
- slidge_whatsapp/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go +3 -0
- slidge_whatsapp/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go +3 -0
- slidge_whatsapp/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go +3 -0
- slidge_whatsapp/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go +3 -0
- slidge_whatsapp/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go +3 -0
- slidge_whatsapp/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go +3 -0
- slidge_whatsapp/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go +3 -0
- slidge_whatsapp/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go +3 -0
- slidge_whatsapp/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go +3 -0
- slidge_whatsapp/vendor/golang.org/x/sys/unix/zsyscall_solaris_amd64.go +4 -4
- slidge_whatsapp/vendor/golang.org/x/sys/unix/zsysnum_linux_386.go +1 -0
- slidge_whatsapp/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go +1 -0
- slidge_whatsapp/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go +1 -0
- slidge_whatsapp/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go +1 -0
- slidge_whatsapp/vendor/golang.org/x/sys/unix/zsysnum_linux_loong64.go +1 -0
- slidge_whatsapp/vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go +1 -0
- slidge_whatsapp/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go +1 -0
- slidge_whatsapp/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go +1 -0
- slidge_whatsapp/vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go +1 -0
- slidge_whatsapp/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc.go +1 -0
- slidge_whatsapp/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go +1 -0
- slidge_whatsapp/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go +1 -0
- slidge_whatsapp/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go +1 -0
- slidge_whatsapp/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go +1 -0
- slidge_whatsapp/vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go +1 -0
- slidge_whatsapp/vendor/golang.org/x/sys/unix/ztypes_linux.go +168 -12
- slidge_whatsapp/vendor/golang.org/x/sys/unix/ztypes_linux_386.go +17 -1
- slidge_whatsapp/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go +16 -0
- slidge_whatsapp/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go +18 -2
- slidge_whatsapp/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go +16 -0
- slidge_whatsapp/vendor/golang.org/x/sys/unix/ztypes_linux_loong64.go +16 -0
- slidge_whatsapp/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go +17 -1
- slidge_whatsapp/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go +16 -0
- slidge_whatsapp/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go +16 -0
- slidge_whatsapp/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go +17 -1
- slidge_whatsapp/vendor/golang.org/x/sys/unix/ztypes_linux_ppc.go +18 -2
- slidge_whatsapp/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go +16 -0
- slidge_whatsapp/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go +16 -0
- slidge_whatsapp/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go +16 -0
- slidge_whatsapp/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go +16 -0
- slidge_whatsapp/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go +16 -0
- slidge_whatsapp/vendor/golang.org/x/sys/windows/types_windows.go +6 -0
- slidge_whatsapp/vendor/golang.org/x/sys/windows/zsyscall_windows.go +483 -483
- slidge_whatsapp/vendor/google.golang.org/protobuf/encoding/protowire/wire.go +25 -1
- slidge_whatsapp/vendor/google.golang.org/protobuf/internal/editiondefaults/editions_defaults.binpb +0 -0
- slidge_whatsapp/vendor/google.golang.org/protobuf/internal/filedesc/editions.go +10 -5
- slidge_whatsapp/vendor/google.golang.org/protobuf/internal/filedesc/presence.go +33 -0
- slidge_whatsapp/vendor/google.golang.org/protobuf/internal/genid/api_gen.go +6 -0
- slidge_whatsapp/vendor/google.golang.org/protobuf/internal/genid/descriptor_gen.go +68 -22
- slidge_whatsapp/vendor/google.golang.org/protobuf/internal/impl/codec_message_opaque.go +2 -1
- slidge_whatsapp/vendor/google.golang.org/protobuf/internal/impl/message_opaque.go +8 -37
- slidge_whatsapp/vendor/google.golang.org/protobuf/internal/impl/presence.go +0 -3
- slidge_whatsapp/vendor/google.golang.org/protobuf/internal/version/version.go +1 -1
- slidge_whatsapp/vendor/google.golang.org/protobuf/reflect/protoreflect/source_gen.go +8 -0
- slidge_whatsapp/vendor/modules.txt +57 -23
- {slidge_whatsapp-0.2.6.dist-info → slidge_whatsapp-0.3.0.dist-info}/METADATA +5 -4
- {slidge_whatsapp-0.2.6.dist-info → slidge_whatsapp-0.3.0.dist-info}/RECORD +254 -174
- {slidge_whatsapp-0.2.6.dist-info → slidge_whatsapp-0.3.0.dist-info}/WHEEL +1 -1
- slidge_whatsapp/vendor/github.com/jupiterrider/ffi/abi_amd64.go +0 -7
- slidge_whatsapp/vendor/golang.org/x/net/http2/config_go124.go +0 -61
- slidge_whatsapp/vendor/golang.org/x/net/http2/config_pre_go124.go +0 -16
- slidge_whatsapp/vendor/golang.org/x/net/http2/timer.go +0 -20
- {slidge_whatsapp-0.2.6.dist-info → slidge_whatsapp-0.3.0.dist-info}/entry_points.txt +0 -0
- {slidge_whatsapp-0.2.6.dist-info → slidge_whatsapp-0.3.0.dist-info/licenses}/LICENSE +0 -0
|
@@ -0,0 +1,985 @@
|
|
|
1
|
+
package codec
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"encoding/binary"
|
|
5
|
+
"encoding/json"
|
|
6
|
+
"fmt"
|
|
7
|
+
"math"
|
|
8
|
+
"math/big"
|
|
9
|
+
"os"
|
|
10
|
+
"reflect"
|
|
11
|
+
"sort"
|
|
12
|
+
|
|
13
|
+
"github.com/beeper/argo-go/block"
|
|
14
|
+
"github.com/beeper/argo-go/header"
|
|
15
|
+
"github.com/beeper/argo-go/internal/util"
|
|
16
|
+
"github.com/beeper/argo-go/label"
|
|
17
|
+
"github.com/beeper/argo-go/pkg/buf"
|
|
18
|
+
"github.com/beeper/argo-go/pkg/varint"
|
|
19
|
+
"github.com/beeper/argo-go/wire"
|
|
20
|
+
"github.com/elliotchance/orderedmap/v3"
|
|
21
|
+
"github.com/vektah/gqlparser/v2/ast"
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
// writerEntry stores an association between a block.AnyBlockWriter and the
|
|
25
|
+
// original wire.Type of the values it's intended to write. This is important for
|
|
26
|
+
// type-specific operations, such as determining if null termination is needed for string blocks.
|
|
27
|
+
type writerEntry struct {
|
|
28
|
+
Writer block.AnyBlockWriter // The type-erased block writer instance.
|
|
29
|
+
OriginalValueType wire.Type // The original wire type this writer was created for (e.g., wire.String, wire.Bytes).
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// ArgoEncoder handles the conversion of Go data structures, typically representing
|
|
33
|
+
// GraphQL query results, into the Argo binary message format. It manages a core
|
|
34
|
+
// buffer for labels and inline data, a collection of block writers for scalar
|
|
35
|
+
// values that are not inlined, and an Argo header.
|
|
36
|
+
// The encoder supports various Argo features like deduplication, different block types,
|
|
37
|
+
// and self-describing values, controlled by header flags and wire type definitions.
|
|
38
|
+
type ArgoEncoder struct {
|
|
39
|
+
coreBuf *buf.Buf // Buffer for the core message data, primarily labels and inlined scalar values.
|
|
40
|
+
// writers stores block writers, keyed by their wire.BlockKey. Each entry contains the
|
|
41
|
+
// AnyBlockWriter and the original wire.Type for which it was created.
|
|
42
|
+
writers *orderedmap.OrderedMap[wire.BlockKey, writerEntry]
|
|
43
|
+
header *header.Header // The Argo header for the message being encoded.
|
|
44
|
+
|
|
45
|
+
// Debug fields, used when ArgoEncoder.Debug is true.
|
|
46
|
+
Debug bool // If true, enables tracking of encoding steps.
|
|
47
|
+
// tracked stores a log of encoding operations when Debug is true.
|
|
48
|
+
// Each entry is an ordered map representing a single tracked step.
|
|
49
|
+
tracked []*orderedmap.OrderedMap[string, interface{}]
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// NewArgoEncoder initializes and returns a new ArgoEncoder.
|
|
53
|
+
// It sets up the core buffer, the map for block writers, and a new Argo header.
|
|
54
|
+
func NewArgoEncoder() *ArgoEncoder {
|
|
55
|
+
// Initial capacity for coreBuf; it will grow as needed.
|
|
56
|
+
// The final message buffer is constructed in GetResult by combining the header,
|
|
57
|
+
// block data (if not inlined), and the core buffer contents.
|
|
58
|
+
coreBuffer := buf.NewBuf(1024) // Default initial capacity.
|
|
59
|
+
hdr := header.NewHeader()
|
|
60
|
+
|
|
61
|
+
return &ArgoEncoder{
|
|
62
|
+
coreBuf: coreBuffer,
|
|
63
|
+
writers: orderedmap.NewOrderedMap[wire.BlockKey, writerEntry](),
|
|
64
|
+
header: hdr,
|
|
65
|
+
tracked: []*orderedmap.OrderedMap[string, interface{}]{}, // Initialize an empty slice for tracking.
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Header returns the encoder's *header.Header instance, allowing the caller
|
|
70
|
+
// to set Argo header flags or other header properties before finalizing the message.
|
|
71
|
+
func (ae *ArgoEncoder) Header() *header.Header {
|
|
72
|
+
return ae.header
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Track records an encoding step for debugging purposes if ae.Debug is true.
|
|
76
|
+
// It captures the GraphQL path, a descriptive message, the current buffer (if any),
|
|
77
|
+
// and the value being processed.
|
|
78
|
+
func (ae *ArgoEncoder) Track(path ast.Path, msg string, b buf.Write, value interface{}) {
|
|
79
|
+
if ae.Debug {
|
|
80
|
+
entry := orderedmap.NewOrderedMap[string, interface{}]()
|
|
81
|
+
entry.Set("path", util.FormatPath(path))
|
|
82
|
+
entry.Set("msg", msg)
|
|
83
|
+
if b != nil { // Buffer might be nil for some tracking events (e.g., header bytes)
|
|
84
|
+
entry.Set("pos", b.Position())
|
|
85
|
+
} else {
|
|
86
|
+
entry.Set("pos", -1) // Indicate no buffer position
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Avoid deep copying complex values or handle them carefully
|
|
90
|
+
if s, ok := value.(string); ok && len(s) > 100 {
|
|
91
|
+
entry.Set("value", s[:100]+"...")
|
|
92
|
+
} else if b, ok := value.([]byte); ok && len(b) > 100 {
|
|
93
|
+
entry.Set("value", fmt.Sprintf("bytes[%d]", len(b)))
|
|
94
|
+
} else {
|
|
95
|
+
entry.Set("value", value)
|
|
96
|
+
}
|
|
97
|
+
ae.tracked = append(ae.tracked, entry)
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Log provides a more generic logging mechanism for debugging, used when ae.Debug is true.
|
|
102
|
+
// It records the current position in the core buffer and a message or detailed object.
|
|
103
|
+
func (ae *ArgoEncoder) Log(msg interface{}) {
|
|
104
|
+
if ae.Debug {
|
|
105
|
+
entry := orderedmap.NewOrderedMap[string, interface{}]()
|
|
106
|
+
entry.Set("pos", ae.coreBuf.Position())
|
|
107
|
+
|
|
108
|
+
if s, ok := msg.(string); ok {
|
|
109
|
+
entry.Set("msg", s)
|
|
110
|
+
} else if om, ok := msg.(*orderedmap.OrderedMap[string, interface{}]); ok {
|
|
111
|
+
// If msg is an OrderedMap, merge its fields.
|
|
112
|
+
for el := om.Front(); el != nil; el = el.Next() {
|
|
113
|
+
entry.Set(el.Key, el.Value)
|
|
114
|
+
}
|
|
115
|
+
} else {
|
|
116
|
+
entry.Set("detail", msg)
|
|
117
|
+
}
|
|
118
|
+
ae.tracked = append(ae.tracked, entry)
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// nullTerminator is a pre-allocated byte slice for null-terminating strings.
|
|
123
|
+
var nullTerminator = []byte{0x00}
|
|
124
|
+
|
|
125
|
+
// makeBlockWriter creates and returns a block.AnyBlockWriter suitable for the given wire.Type `t`
|
|
126
|
+
// and deduplication setting. It handles various scalar types by configuring appropriate
|
|
127
|
+
// ValueToBytesFunc and MakeLabelFunc for the underlying block.BlockWriter or
|
|
128
|
+
// block.DeduplicatingBlockWriter.
|
|
129
|
+
// For BytesType with deduplication, it uses a specialized bytesDeduplicatingAdapter.
|
|
130
|
+
func (ae *ArgoEncoder) makeBlockWriter(t wire.Type, dedupe bool) (block.AnyBlockWriter, error) {
|
|
131
|
+
switch t.(type) {
|
|
132
|
+
case wire.StringType:
|
|
133
|
+
stringVTB := func(s string) ([]byte, error) { // ValueToBytesFunc for string
|
|
134
|
+
return []byte(s), nil
|
|
135
|
+
}
|
|
136
|
+
if dedupe {
|
|
137
|
+
// For strings, deduplication uses the string itself as the key.
|
|
138
|
+
dbw := block.NewLengthOfBytesDeduplicatingBlockWriter[string](stringVTB)
|
|
139
|
+
return block.NewAnyDeduplicatingBlockWriter(dbw), nil
|
|
140
|
+
}
|
|
141
|
+
// Non-deduplicating string writer also uses length-based labels.
|
|
142
|
+
bw := block.NewLengthOfBytesBlockWriter[string](stringVTB)
|
|
143
|
+
return block.NewAnyBlockWriter(bw), nil
|
|
144
|
+
|
|
145
|
+
case wire.BytesType:
|
|
146
|
+
bytesVTB := func(b []byte) ([]byte, error) { // ValueToBytesFunc for []byte
|
|
147
|
+
return b, nil
|
|
148
|
+
}
|
|
149
|
+
if dedupe {
|
|
150
|
+
// For BytesType with deduplication, the underlying DeduplicatingBlockWriter[string]
|
|
151
|
+
// uses string(originalBytes) as the deduplication key.
|
|
152
|
+
// The bytesDeduplicatingAdapter handles the conversion from []byte input (in its Write method)
|
|
153
|
+
// to the string key expected by the core writer.
|
|
154
|
+
dedupeKeyedVTB := func(sKey string) ([]byte, error) { // ValueToBytes for the string-keyed deduplicator
|
|
155
|
+
return []byte(sKey), nil
|
|
156
|
+
}
|
|
157
|
+
dbw := block.NewLengthOfBytesDeduplicatingBlockWriter[string](dedupeKeyedVTB)
|
|
158
|
+
return &bytesDeduplicatingAdapter{dbw}, nil // Specialized adapter for []byte with string-keyed dedupe.
|
|
159
|
+
}
|
|
160
|
+
// Non-deduplicating bytes writer.
|
|
161
|
+
bw := block.NewLengthOfBytesBlockWriter[[]byte](bytesVTB)
|
|
162
|
+
return block.NewAnyBlockWriter(bw), nil
|
|
163
|
+
|
|
164
|
+
case wire.VarintType:
|
|
165
|
+
if dedupe { // Deduplication for Varint is not standard/implemented.
|
|
166
|
+
return nil, fmt.Errorf("unimplemented: deduping VARINT")
|
|
167
|
+
}
|
|
168
|
+
// Varint values are written without length labels by default (label is nil from NewAnyNoLabelBlockWriter).
|
|
169
|
+
// The actual Varint encoding happens in this ValueToBytesFunc.
|
|
170
|
+
varintVTB := func(v interface{}) ([]byte, error) {
|
|
171
|
+
switch val := v.(type) {
|
|
172
|
+
case int:
|
|
173
|
+
return varint.ZigZagEncodeInt64(int64(val)), nil
|
|
174
|
+
case int64:
|
|
175
|
+
return varint.ZigZagEncodeInt64(val), nil
|
|
176
|
+
case *big.Int:
|
|
177
|
+
return varint.ZigZagEncode(val), nil
|
|
178
|
+
case float64:
|
|
179
|
+
// Check if float64 is a whole number
|
|
180
|
+
if val == math.Trunc(val) {
|
|
181
|
+
return varint.ZigZagEncodeInt64(int64(val)), nil
|
|
182
|
+
}
|
|
183
|
+
return nil, fmt.Errorf("float64 value %v is not a whole number for VarintType block", val)
|
|
184
|
+
default:
|
|
185
|
+
return nil, fmt.Errorf("expected int, int64, *big.Int or whole float64 for VarintType block, got %T for value %v", v, v)
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
// Varints are not labeled with their length; their encoding is self-terminating.
|
|
189
|
+
return block.NewAnyNoLabelBlockWriter(varintVTB), nil
|
|
190
|
+
|
|
191
|
+
case wire.Float64Type:
|
|
192
|
+
if dedupe { // Deduplication for Float64 is not standard/implemented.
|
|
193
|
+
return nil, fmt.Errorf("unimplemented: deduping FLOAT64")
|
|
194
|
+
}
|
|
195
|
+
// Float64 values are written without length labels by default.
|
|
196
|
+
floatVTB := func(v interface{}) ([]byte, error) {
|
|
197
|
+
var f float64
|
|
198
|
+
switch val := v.(type) {
|
|
199
|
+
case float64:
|
|
200
|
+
f = val
|
|
201
|
+
case float32:
|
|
202
|
+
f = float64(val)
|
|
203
|
+
case int:
|
|
204
|
+
f = float64(val)
|
|
205
|
+
case int64:
|
|
206
|
+
f = float64(val)
|
|
207
|
+
default:
|
|
208
|
+
return nil, fmt.Errorf("expected float64 compatible type for Float64Type block, got %T for value %v", v, v)
|
|
209
|
+
}
|
|
210
|
+
var b [8]byte // Float64 is 8 bytes.
|
|
211
|
+
binary.LittleEndian.PutUint64(b[:], math.Float64bits(f))
|
|
212
|
+
return b[:], nil
|
|
213
|
+
}
|
|
214
|
+
// Floats are fixed-width, so no length label is needed.
|
|
215
|
+
return block.NewAnyNoLabelBlockWriter(floatVTB), nil
|
|
216
|
+
|
|
217
|
+
case wire.FixedType:
|
|
218
|
+
fixedType := t.(wire.FixedType)
|
|
219
|
+
if dedupe { // Deduplication for FixedType is not standard/implemented.
|
|
220
|
+
return nil, fmt.Errorf("unimplemented: deduping FIXED")
|
|
221
|
+
}
|
|
222
|
+
fixedVTB := func(v interface{}) ([]byte, error) {
|
|
223
|
+
b, ok := v.([]byte)
|
|
224
|
+
if !ok {
|
|
225
|
+
return nil, fmt.Errorf("expected []byte for FixedType block, got %T for value %v", v, v)
|
|
226
|
+
}
|
|
227
|
+
if len(b) != fixedType.Length {
|
|
228
|
+
return nil, fmt.Errorf("fixedType expected %d bytes, got %d for value %v", fixedType.Length, len(b), b)
|
|
229
|
+
}
|
|
230
|
+
return b, nil
|
|
231
|
+
}
|
|
232
|
+
// Fixed-length types do not need length labels.
|
|
233
|
+
return block.NewAnyNoLabelBlockWriter(fixedVTB), nil
|
|
234
|
+
|
|
235
|
+
default:
|
|
236
|
+
return nil, fmt.Errorf("unsupported block writer type %s (underlying Go type: %T)", wire.Print(t), t)
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// bytesDeduplicatingAdapter is a specialized AnyBlockWriter adapter for BytesType when deduplication is enabled.
|
|
241
|
+
// It wraps a DeduplicatingBlockWriter[string] and handles the conversion of input []byte values
|
|
242
|
+
// to string keys for the underlying deduplicator.
|
|
243
|
+
type bytesDeduplicatingAdapter struct {
|
|
244
|
+
coreWriter *block.DeduplicatingBlockWriter[string] // Underlying writer uses string keys for deduplication.
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// Write converts the input value `v` (expected to be []byte or string) to a string key
|
|
248
|
+
// and passes it to the underlying string-keyed DeduplicatingBlockWriter.
|
|
249
|
+
func (a *bytesDeduplicatingAdapter) Write(v interface{}) (*label.Label, error) {
|
|
250
|
+
bytesVal, ok := v.([]byte)
|
|
251
|
+
if !ok {
|
|
252
|
+
// Allow string input as well, interpreting it as bytes.
|
|
253
|
+
if strVal, okStr := v.(string); okStr {
|
|
254
|
+
bytesVal = []byte(strVal)
|
|
255
|
+
} else {
|
|
256
|
+
return nil, fmt.Errorf("bytesDeduplicatingAdapter expected []byte or string, got %T for value %v", v, v)
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
// The coreWriter expects a string for deduplication; string(bytesVal) serves as the key.
|
|
260
|
+
return a.coreWriter.Write(string(bytesVal))
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
// AllValuesAsBytes delegates to the underlying coreWriter.
|
|
264
|
+
func (a *bytesDeduplicatingAdapter) AllValuesAsBytes() [][]byte {
|
|
265
|
+
return a.coreWriter.AllValuesAsBytes()
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
// WriteLastToBuf delegates to the underlying coreWriter.
|
|
269
|
+
func (a *bytesDeduplicatingAdapter) WriteLastToBuf(buf buf.Write) error {
|
|
270
|
+
return a.coreWriter.WriteLastToBuf(buf)
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// getWriter retrieves an existing block.AnyBlockWriter for the given blockDef.Key, or creates
|
|
274
|
+
// a new one if it doesn't exist. Created writers are stored in ae.writers for reuse.
|
|
275
|
+
// `valueWireType` is typically the `Of` type of the `blockDef` (e.g., wire.String for a block of strings).
|
|
276
|
+
func (ae *ArgoEncoder) getWriter(blockDef wire.BlockType, valueWireType wire.Type) (block.AnyBlockWriter, error) {
|
|
277
|
+
if entry, found := ae.writers.Get(blockDef.Key); found {
|
|
278
|
+
return entry.Writer, nil
|
|
279
|
+
}
|
|
280
|
+
// Create a new writer if one doesn't exist for this block key.
|
|
281
|
+
writer, err := ae.makeBlockWriter(valueWireType, blockDef.Dedupe)
|
|
282
|
+
if err != nil {
|
|
283
|
+
return nil, fmt.Errorf("failed to make block writer for key '%s' (value type %s): %w", blockDef.Key, wire.Print(valueWireType), err)
|
|
284
|
+
}
|
|
285
|
+
ae.writers.Set(blockDef.Key, writerEntry{Writer: writer, OriginalValueType: valueWireType})
|
|
286
|
+
return writer, nil
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
// Write is a core method for handling scalar values that are part of a block.
|
|
290
|
+
// It retrieves or creates the appropriate block writer for `blockDef`,
|
|
291
|
+
// writes the value `v` to this writer (which generates a label and stores bytes),
|
|
292
|
+
// and then writes the label (if any) to the encoder's coreBuf.
|
|
293
|
+
// If the `HeaderInlineEverythingFlag` is set, it also writes the value's bytes directly
|
|
294
|
+
// to the coreBuf for certain types of labels (e.g., length labels, non-null markers for unlabeled types).
|
|
295
|
+
func (ae *ArgoEncoder) Write(blockDef wire.BlockType, valueWireType wire.Type, v interface{}) (*label.Label, error) {
|
|
296
|
+
writer, err := ae.getWriter(blockDef, valueWireType)
|
|
297
|
+
if err != nil {
|
|
298
|
+
return nil, err // Error from getWriter already has context.
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
lbl, err := writer.Write(v) // Value `v` is written to the chosen block writer.
|
|
302
|
+
if err != nil {
|
|
303
|
+
return nil, fmt.Errorf("block writer for key '%s' (value type %s) failed: %w", blockDef.Key, wire.Print(valueWireType), err)
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
// Part 1: Write the label to the core buffer.
|
|
307
|
+
// This happens regardless of InlineEverything, as labels are part of the core stream.
|
|
308
|
+
if lbl != nil {
|
|
309
|
+
encodedLabel := lbl.Encode()
|
|
310
|
+
if _, err := ae.coreBuf.Write(encodedLabel); err != nil {
|
|
311
|
+
// Error context for label writing.
|
|
312
|
+
mode := "non-inline"
|
|
313
|
+
if ae.header.GetFlag(header.HeaderInlineEverythingFlag) {
|
|
314
|
+
mode = "inline"
|
|
315
|
+
}
|
|
316
|
+
return nil, fmt.Errorf("failed to write label to core buffer (mode: %s): %w", mode, err)
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
// Part 2: If InlineEverything is active, write the data bytes to coreBuf if appropriate.
|
|
321
|
+
if ae.header.GetFlag(header.HeaderInlineEverythingFlag) {
|
|
322
|
+
shouldWriteDataInline := false
|
|
323
|
+
if lbl == nil {
|
|
324
|
+
// For unlabeled types (e.g., FLOAT64, FIXED non-nullable), their data is always written inline.
|
|
325
|
+
shouldWriteDataInline = true
|
|
326
|
+
} else {
|
|
327
|
+
// For labeled types, data is written inline only if the label isn't a "standalone" one
|
|
328
|
+
// (i.e., if it implies data should follow, like a length or NonNull marker).
|
|
329
|
+
// Backreferences, Null, Absent, Error labels do not have following data in the core stream.
|
|
330
|
+
isStandaloneLabel := lbl.IsBackref() || lbl.IsNull() || lbl.IsAbsent() || lbl.IsError()
|
|
331
|
+
if !isStandaloneLabel {
|
|
332
|
+
shouldWriteDataInline = true
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
if shouldWriteDataInline {
|
|
337
|
+
// WriteLastToBuf gets the most recent value from the block writer and writes it to coreBuf.
|
|
338
|
+
if err := writer.WriteLastToBuf(ae.coreBuf); err != nil {
|
|
339
|
+
return nil, fmt.Errorf("failed to write value data to core buffer in inline mode: %w", err)
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
// If not InlineEverything, value bytes remain in their respective block writers (writer.valuesAsBytes)
|
|
344
|
+
// and are assembled into the final message by GetResult().
|
|
345
|
+
|
|
346
|
+
return lbl, nil
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
// ValueToArgoWithType is the primary entry point for encoding a Go data structure (typically from JSON-like input)
|
|
350
|
+
// into the Argo format based on a provided wire.Type schema.
|
|
351
|
+
// The `v` interface{} is expected to conform to the structure defined by `wt`.
|
|
352
|
+
// For example, if `wt` is a RecordType, `v` should be an *orderedmap.OrderedMap[string, interface{}].
|
|
353
|
+
// If `wt` is an ArrayType, `v` should be a slice or array.
|
|
354
|
+
// Debugging information, if enabled, is written to "tmp-gowritelog.json".
|
|
355
|
+
func (ae *ArgoEncoder) ValueToArgoWithType(v interface{}, wt wire.Type) error {
|
|
356
|
+
// Start recursive encoding. currentPath is initially nil, currentBlock is initially nil.
|
|
357
|
+
err := ae.writeArgo(nil, v, wt, nil)
|
|
358
|
+
|
|
359
|
+
// If debugging is enabled, write the tracked encoding steps to a JSON file.
|
|
360
|
+
if ae.Debug {
|
|
361
|
+
jsony := make([]*util.OrderedMapJSON[string, any], len(ae.tracked))
|
|
362
|
+
for i, obj := range ae.tracked {
|
|
363
|
+
jsony[i] = util.NewOrderedMapJSON(obj)
|
|
364
|
+
}
|
|
365
|
+
trackedJSON, jsonErr := json.MarshalIndent(jsony, "", " ")
|
|
366
|
+
if jsonErr != nil {
|
|
367
|
+
// Log marshalling error, but don't let it hide the main encoding error.
|
|
368
|
+
fmt.Fprintf(os.Stderr, "Error marshalling debug tracking data: %v\n", jsonErr)
|
|
369
|
+
} else {
|
|
370
|
+
_ = os.WriteFile("tmp-gowritelog.json", trackedJSON, 0644) // Error is ignored for debug artifact.
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
return err
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
// writeArgo is the main recursive workhorse for encoding. It traverses the input data `v`
|
|
377
|
+
// according to the structure defined by the wire.Type `wt`.
|
|
378
|
+
// `currentPath` tracks the path within the data structure for debugging.
|
|
379
|
+
// `currentBlock` points to the wire.BlockType definition if the current context is writing
|
|
380
|
+
// elements into a specific block (e.g., a block of strings or varints).
|
|
381
|
+
func (ae *ArgoEncoder) writeArgo(currentPath ast.Path, v interface{}, wt wire.Type, currentBlock *wire.BlockType) error {
|
|
382
|
+
ae.Track(currentPath, "writeArgo type: "+string(wt.GetTypeKey()), ae.coreBuf, v)
|
|
383
|
+
|
|
384
|
+
switch typedWt := wt.(type) {
|
|
385
|
+
case wire.NullableType:
|
|
386
|
+
if v == nil { // Handle explicit Go nil for a nullable type.
|
|
387
|
+
ae.Track(currentPath, "null", ae.coreBuf, label.Null)
|
|
388
|
+
_, err := ae.coreBuf.Write(label.Null)
|
|
389
|
+
return err
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
// Handle inline errors: if `v` is an error or []error, write Argo error representation.
|
|
393
|
+
// This needs to check various ways an error or slice of errors might be represented in `v`.
|
|
394
|
+
var errorArray []error
|
|
395
|
+
if errVal, ok := v.(error); ok {
|
|
396
|
+
errorArray = []error{errVal} // Single error.
|
|
397
|
+
} else if errSlice, ok := v.([]error); ok {
|
|
398
|
+
errorArray = errSlice // Already a slice of errors.
|
|
399
|
+
} else if interfaceSlice, ok := v.([]interface{}); ok {
|
|
400
|
+
// Check if []interface{} contains only errors.
|
|
401
|
+
canBeErrorArray := true
|
|
402
|
+
for _, item := range interfaceSlice {
|
|
403
|
+
if errVal, itemIsErr := item.(error); itemIsErr {
|
|
404
|
+
errorArray = append(errorArray, errVal)
|
|
405
|
+
} else {
|
|
406
|
+
canBeErrorArray = false // Found a non-error item.
|
|
407
|
+
break
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
if !canBeErrorArray {
|
|
411
|
+
errorArray = nil // Not a pure error array.
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
if len(errorArray) > 0 {
|
|
416
|
+
// Value is an error or slice of errors, write it in Argo error format.
|
|
417
|
+
ae.Track(currentPath, "error value encountered", ae.coreBuf, v)
|
|
418
|
+
if _, err := ae.coreBuf.Write(label.Error); err != nil { // Write the Error marker label.
|
|
419
|
+
return err
|
|
420
|
+
}
|
|
421
|
+
// Write the number of errors as a length label.
|
|
422
|
+
lenLabel := label.NewFromInt64(int64(len(errorArray)))
|
|
423
|
+
if _, err := ae.coreBuf.Write(lenLabel.Encode()); err != nil {
|
|
424
|
+
return err
|
|
425
|
+
}
|
|
426
|
+
// Write each error.
|
|
427
|
+
for i, e := range errorArray {
|
|
428
|
+
errPath := util.AddPathIndex(currentPath, i) // Path for this specific error in the array.
|
|
429
|
+
if ae.header.GetFlag(header.HeaderSelfDescribingErrorsFlag) {
|
|
430
|
+
// Use self-describing format for errors.
|
|
431
|
+
if err := ae.writeSelfDescribing(errPath, e); err != nil {
|
|
432
|
+
return fmt.Errorf("failed to write self-describing error item at index %d: %w", i, err)
|
|
433
|
+
}
|
|
434
|
+
} else {
|
|
435
|
+
// Use structured Argo error format (defined by wire.Error type).
|
|
436
|
+
if err := ae.writeGoError(errPath, e); err != nil {
|
|
437
|
+
return fmt.Errorf("failed to write structured error item at index %d: %w", i, err)
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
return nil // Successfully wrote error(s).
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
// If not nil and not an error, it's a non-null instance of the underlying type.
|
|
445
|
+
// If the underlying type is not intrinsically labeled (e.g. scalars in blocks often are),
|
|
446
|
+
// a NonNull marker is needed here before writing the actual value.
|
|
447
|
+
if !wire.IsLabeled(typedWt.Of) {
|
|
448
|
+
ae.Track(currentPath, "non-null marker for nullable type", ae.coreBuf, label.NonNull)
|
|
449
|
+
if _, err := ae.coreBuf.Write(label.NonNull); err != nil {
|
|
450
|
+
return err
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
// Continue writing with the underlying type.
|
|
454
|
+
return ae.writeArgo(currentPath, v, typedWt.Of, currentBlock)
|
|
455
|
+
|
|
456
|
+
case wire.BlockType:
|
|
457
|
+
if currentBlock != nil {
|
|
458
|
+
// This should not happen if wire types are structured correctly (no nested blocks).
|
|
459
|
+
return fmt.Errorf("encoder error: already processing block '%s', cannot switch to new block '%s' at path %s. Wire type: %s",
|
|
460
|
+
currentBlock.Key, typedWt.Key, util.FormatPath(currentPath), wire.Print(wt))
|
|
461
|
+
}
|
|
462
|
+
ae.Track(currentPath, "entering block with key", ae.coreBuf, typedWt.Key)
|
|
463
|
+
// Recursively call writeArgo with the block's element type (`typedWt.Of`)
|
|
464
|
+
// and pass `&typedWt` as the new `currentBlock` context.
|
|
465
|
+
return ae.writeArgo(currentPath, v, typedWt.Of, &typedWt)
|
|
466
|
+
|
|
467
|
+
case wire.RecordType:
|
|
468
|
+
ae.Track(currentPath, "record with number of fields", ae.coreBuf, len(typedWt.Fields))
|
|
469
|
+
// Expect v to be an *orderedmap.OrderedMap for records to maintain field order.
|
|
470
|
+
om, ok := v.(*orderedmap.OrderedMap[string, interface{}])
|
|
471
|
+
if !ok && v != nil { // If v is not nil, it must be the correct map type.
|
|
472
|
+
return fmt.Errorf("type error: expected *orderedmap.OrderedMap[string, interface{}] for record, got %T at path %s", v, util.FormatPath(currentPath))
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
// Iterate through fields as defined in the wire.RecordType to ensure correct order and handling of all defined fields.
|
|
476
|
+
for _, field := range typedWt.Fields {
|
|
477
|
+
fieldPath := util.AddPathName(currentPath, field.Name)
|
|
478
|
+
var fieldValue interface{}
|
|
479
|
+
var fieldExists bool
|
|
480
|
+
if om != nil { // If input map is nil (because parent was nil), all fields are treated as absent.
|
|
481
|
+
fieldValue, fieldExists = om.Get(field.Name)
|
|
482
|
+
} else {
|
|
483
|
+
fieldValue = nil // Effectively absent.
|
|
484
|
+
fieldExists = false
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
if fieldExists && fieldValue != nil && fieldValue != wire.AbsentValue {
|
|
488
|
+
// Field is present and has a non-nil, non-absent value.
|
|
489
|
+
// If omittable and its underlying type isn't self-labeling (like a BlockType often is),
|
|
490
|
+
// write a NonNull marker to indicate its presence.
|
|
491
|
+
if field.Omittable && !wire.IsLabeled(field.Of) {
|
|
492
|
+
ae.Track(fieldPath, "omittable record field present, writing NonNull marker", ae.coreBuf, field.Name)
|
|
493
|
+
if _, err := ae.coreBuf.Write(label.NonNull); err != nil {
|
|
494
|
+
return err
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
// Recursively write the field's value.
|
|
498
|
+
if err := ae.writeArgo(fieldPath, fieldValue, field.Of, currentBlock); err != nil {
|
|
499
|
+
return err
|
|
500
|
+
}
|
|
501
|
+
} else if field.Omittable && (!fieldExists || fieldValue == wire.AbsentValue) {
|
|
502
|
+
// Field is omittable and is effectively absent (either not in map or explicit AbsentValue).
|
|
503
|
+
ae.Track(fieldPath, "omittable record field absent, writing Absent marker", ae.coreBuf, field.Name)
|
|
504
|
+
if _, err := ae.coreBuf.Write(label.Absent); err != nil {
|
|
505
|
+
return err
|
|
506
|
+
}
|
|
507
|
+
} else if wire.IsNullable(field.Of) {
|
|
508
|
+
// Field is not omittable (or omittable but present as nil) AND its type is nullable.
|
|
509
|
+
// This handles cases where an explicit JSON null was provided for a nullable field,
|
|
510
|
+
// or a non-omittable field is nil (which is only valid if its type is nullable).
|
|
511
|
+
ae.Track(fieldPath, "record field is nil and type is nullable (or non-omittable field is nil), recursing", ae.coreBuf, field.Name)
|
|
512
|
+
// Recursively call writeArgo. If fieldValue is nil, this will correctly write a Null label via the NullableType case.
|
|
513
|
+
if err := ae.writeArgo(fieldPath, fieldValue, field.Of, currentBlock); err != nil {
|
|
514
|
+
return err
|
|
515
|
+
}
|
|
516
|
+
} else if wire.IsBlock(field.Of) && wire.IsDesc(field.Of.(wire.BlockType).Of) {
|
|
517
|
+
// Special case: field is a Block of SelfDescribing (DESC) type and is absent/nil.
|
|
518
|
+
// SelfDescribing types can represent null, so we recurse to let DESC handle the nil.
|
|
519
|
+
ae.Track(fieldPath, "record field is nil/absent but is Block<DESC>, recursing for self-describing null", ae.coreBuf, field.Name)
|
|
520
|
+
if err := ae.writeArgo(fieldPath, nil, field.Of, currentBlock); err != nil {
|
|
521
|
+
return err
|
|
522
|
+
}
|
|
523
|
+
} else {
|
|
524
|
+
// Field is absent/nil, but it's not omittable, not nullable, and not Block<DESC>.
|
|
525
|
+
// This is a data-schema mismatch.
|
|
526
|
+
return fmt.Errorf("schema error: record field '%s' is absent/nil but its type (%s) is not omittable, not nullable, and not Block<DESC> at path %s", field.Name, wire.Print(field.Of), util.FormatPath(fieldPath))
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
return nil
|
|
530
|
+
|
|
531
|
+
case wire.ArrayType:
|
|
532
|
+
reflectVal := reflect.ValueOf(v)
|
|
533
|
+
if reflectVal.Kind() != reflect.Slice && reflectVal.Kind() != reflect.Array {
|
|
534
|
+
// If `v` is nil for an ArrayType, it's an error because ArrayType itself is not nullable.
|
|
535
|
+
// A nullable array would be NullableType{Of: ArrayType{...}}.
|
|
536
|
+
if v == nil {
|
|
537
|
+
return fmt.Errorf("type error: cannot encode Go nil as non-nullable Argo array at path %s. WireType: %s", util.FormatPath(currentPath), wire.Print(wt))
|
|
538
|
+
}
|
|
539
|
+
return fmt.Errorf("type error: expected slice or array for ArrayType, got %T at path %s", v, util.FormatPath(currentPath))
|
|
540
|
+
}
|
|
541
|
+
length := reflectVal.Len()
|
|
542
|
+
ae.Track(currentPath, "array with length", ae.coreBuf, length)
|
|
543
|
+
lenLabel := label.NewFromInt64(int64(length)) // Label for array length.
|
|
544
|
+
if _, err := ae.coreBuf.Write(lenLabel.Encode()); err != nil {
|
|
545
|
+
return err
|
|
546
|
+
}
|
|
547
|
+
// Recursively write each element of the array.
|
|
548
|
+
for i := 0; i < length; i++ {
|
|
549
|
+
itemPath := util.AddPathIndex(currentPath, i)
|
|
550
|
+
itemValue := reflectVal.Index(i).Interface()
|
|
551
|
+
if err := ae.writeArgo(itemPath, itemValue, typedWt.Of, currentBlock); err != nil {
|
|
552
|
+
return err
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
return nil
|
|
556
|
+
|
|
557
|
+
case wire.BooleanType:
|
|
558
|
+
bVal, ok := v.(bool)
|
|
559
|
+
if !ok {
|
|
560
|
+
return fmt.Errorf("expected bool for BooleanType, got %T at path %s", v, util.FormatPath(currentPath))
|
|
561
|
+
}
|
|
562
|
+
ae.Track(currentPath, "boolean", ae.coreBuf, bVal)
|
|
563
|
+
if bVal {
|
|
564
|
+
_, err := ae.coreBuf.Write(label.True)
|
|
565
|
+
return err
|
|
566
|
+
}
|
|
567
|
+
_, err := ae.coreBuf.Write(label.False)
|
|
568
|
+
return err
|
|
569
|
+
|
|
570
|
+
case wire.StringType, wire.BytesType, wire.VarintType, wire.Float64Type, wire.FixedType:
|
|
571
|
+
// Logic for types which may use blocks for data
|
|
572
|
+
if currentBlock == nil {
|
|
573
|
+
return fmt.Errorf("programmer error: need block for %s at path %s", wire.Print(wt), util.FormatPath(currentPath))
|
|
574
|
+
}
|
|
575
|
+
_, err := ae.Write(*currentBlock, wt, v)
|
|
576
|
+
if err != nil {
|
|
577
|
+
return err
|
|
578
|
+
}
|
|
579
|
+
ae.Track(currentPath, string(wt.GetTypeKey()), ae.coreBuf, v)
|
|
580
|
+
return nil
|
|
581
|
+
|
|
582
|
+
case wire.DescType:
|
|
583
|
+
ae.Track(currentPath, "self-describing", ae.coreBuf, v)
|
|
584
|
+
return ae.writeSelfDescribing(currentPath, v)
|
|
585
|
+
|
|
586
|
+
case wire.PathType: // Argo spec: PATH values ... encoded exactly as an ARRAY of VARINT values.
|
|
587
|
+
// This should be handled by the Error type definition, which includes a PATH field.
|
|
588
|
+
// If we encounter a raw PathType, treat it as Array{Of: Varint}.
|
|
589
|
+
pathSlice, ok := v.([]interface{})
|
|
590
|
+
if !ok {
|
|
591
|
+
if intSlice, isIntSlice := v.([]int); isIntSlice {
|
|
592
|
+
pathSlice = make([]interface{}, len(intSlice))
|
|
593
|
+
for i, v := range intSlice {
|
|
594
|
+
pathSlice[i] = v
|
|
595
|
+
}
|
|
596
|
+
ok = true
|
|
597
|
+
} else if int64Slice, isInt64Slice := v.([]int64); isInt64Slice {
|
|
598
|
+
pathSlice = make([]interface{}, len(int64Slice))
|
|
599
|
+
for i, v := range int64Slice {
|
|
600
|
+
pathSlice[i] = v
|
|
601
|
+
}
|
|
602
|
+
ok = true
|
|
603
|
+
} else {
|
|
604
|
+
return fmt.Errorf("expected []interface{} or []int or []int64 for PathType, got %T at path %s", v, util.FormatPath(currentPath))
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
// The actual transformation from GraphQL path to wire path (list of integers) happens
|
|
608
|
+
// before this point if we are encoding a structured Error.
|
|
609
|
+
// Here, we assume 'v' is already the list of integers for the wire.
|
|
610
|
+
return ae.writeArgo(currentPath, pathSlice, wire.ArrayType{Of: wire.Varint}, currentBlock)
|
|
611
|
+
|
|
612
|
+
default:
|
|
613
|
+
return fmt.Errorf("unsupported wire type %T (%s) for encoding at path %s", wt, wire.Print(wt), util.FormatPath(currentPath))
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
// writeSelfDescribing writes a Go value in Argo's self-describing format.
|
|
618
|
+
// This format uses specific leading bytes to indicate the type of the following data.
|
|
619
|
+
// It's used for errors when HeaderSelfDescribingErrorsFlag is set, or for fields of type wire.Desc.
|
|
620
|
+
func (ae *ArgoEncoder) writeSelfDescribing(currentPath ast.Path, v interface{}) error {
|
|
621
|
+
ae.Track(currentPath, "writeSelfDescribing value", ae.coreBuf, v)
|
|
622
|
+
if v == nil {
|
|
623
|
+
_, err := ae.coreBuf.Write(wire.SelfDescribingNull) // Write the null marker.
|
|
624
|
+
return err
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
// Optimized path for *orderedmap.OrderedMap (common for objects).
|
|
628
|
+
if om, ok := v.(*orderedmap.OrderedMap[string, interface{}]); ok {
|
|
629
|
+
if _, err := ae.coreBuf.Write(wire.SelfDescribingObject); err != nil { // Object marker.
|
|
630
|
+
return err
|
|
631
|
+
}
|
|
632
|
+
numFields := om.Len()
|
|
633
|
+
lenLabel := label.NewFromInt64(int64(numFields)) // Length of object (number of fields).
|
|
634
|
+
if _, err := ae.coreBuf.Write(lenLabel.Encode()); err != nil {
|
|
635
|
+
return err
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
// Iterate through fields of the ordered map.
|
|
639
|
+
for el := om.Front(); el != nil; el = el.Next() {
|
|
640
|
+
k := el.Key // Field name
|
|
641
|
+
v := el.Value // Field value
|
|
642
|
+
fieldPath := util.AddPathName(currentPath, k)
|
|
643
|
+
|
|
644
|
+
// Write field name (as a self-describing string).
|
|
645
|
+
stringBlockKey := wire.BlockKey("String") // Standard key for self-describing strings.
|
|
646
|
+
stringElementType, blockDefOk := wire.SelfDescribingBlocks[stringBlockKey]
|
|
647
|
+
if !blockDefOk {
|
|
648
|
+
return fmt.Errorf("internal error: self-describing string block key ('%s') not found in wire.SelfDescribingBlocks map for field name '%s'", stringBlockKey, k)
|
|
649
|
+
}
|
|
650
|
+
selfDescribingStringBlock := wire.NewBlockType(stringElementType, stringBlockKey, wire.MustDeduplicateByDefault(stringElementType))
|
|
651
|
+
if _, err := ae.Write(selfDescribingStringBlock, wire.String, k); err != nil {
|
|
652
|
+
return fmt.Errorf("failed to write self-describing object field name '%s': %w", k, err)
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
// Recursively write field value in self-describing format.
|
|
656
|
+
if err := ae.writeSelfDescribing(fieldPath, v); err != nil {
|
|
657
|
+
return fmt.Errorf("failed to write self-describing object field value for '%s': %w", k, err)
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
return nil
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
// General path using reflection for other types.
|
|
664
|
+
val := reflect.ValueOf(v)
|
|
665
|
+
switch val.Kind() {
|
|
666
|
+
case reflect.Map:
|
|
667
|
+
// Handles native Go maps (e.g., map[string]interface{}).
|
|
668
|
+
// For determinism, these are converted to *orderedmap.OrderedMap before recursive call.
|
|
669
|
+
if val.Type().Key().Kind() != reflect.String {
|
|
670
|
+
return fmt.Errorf("type error: cannot encode map with non-string keys in self-describing object at path %s (type: %T)", util.FormatPath(currentPath), v)
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
ae.Track(currentPath, "converting native map to OrderedMap for self-describing encoding", ae.coreBuf, v)
|
|
674
|
+
tempOM := orderedmap.NewOrderedMap[string, interface{}]()
|
|
675
|
+
var stringKeys []string
|
|
676
|
+
for _, kVal := range val.MapKeys() {
|
|
677
|
+
stringKeys = append(stringKeys, kVal.String())
|
|
678
|
+
}
|
|
679
|
+
sort.Strings(stringKeys) // Sort keys for deterministic order in the temporary OrderedMap.
|
|
680
|
+
|
|
681
|
+
for _, sk := range stringKeys {
|
|
682
|
+
mapValue := val.MapIndex(reflect.ValueOf(sk)).Interface()
|
|
683
|
+
tempOM.Set(sk, mapValue)
|
|
684
|
+
}
|
|
685
|
+
return ae.writeSelfDescribing(currentPath, tempOM) // Recurse with the ordered map.
|
|
686
|
+
|
|
687
|
+
case reflect.Slice, reflect.Array:
|
|
688
|
+
// Handle []byte separately as SelfDescribingBytes.
|
|
689
|
+
if byteSlice, isBytes := v.([]byte); isBytes {
|
|
690
|
+
if _, err := ae.coreBuf.Write(wire.SelfDescribingBytes); err != nil { // Bytes marker.
|
|
691
|
+
return err
|
|
692
|
+
}
|
|
693
|
+
bytesBlockKey := wire.BlockKey("Bytes") // Standard key for self-describing byte arrays.
|
|
694
|
+
bytesElementType, blockDefOk := wire.SelfDescribingBlocks[bytesBlockKey]
|
|
695
|
+
if !blockDefOk {
|
|
696
|
+
return fmt.Errorf("internal error: self-describing bytes block key ('%s') not found in wire.SelfDescribingBlocks map", bytesBlockKey)
|
|
697
|
+
}
|
|
698
|
+
selfDescribingBytesBlock := wire.NewBlockType(bytesElementType, bytesBlockKey, wire.MustDeduplicateByDefault(bytesElementType))
|
|
699
|
+
_, err := ae.Write(selfDescribingBytesBlock, wire.Bytes, byteSlice)
|
|
700
|
+
return err
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
// Other slices/arrays are SelfDescribingList.
|
|
704
|
+
if _, err := ae.coreBuf.Write(wire.SelfDescribingList); err != nil { // List marker.
|
|
705
|
+
return err
|
|
706
|
+
}
|
|
707
|
+
length := val.Len()
|
|
708
|
+
lenLabel := label.NewFromInt64(int64(length)) // Length of list.
|
|
709
|
+
if _, err := ae.coreBuf.Write(lenLabel.Encode()); err != nil {
|
|
710
|
+
return err
|
|
711
|
+
}
|
|
712
|
+
// Recursively write each list item in self-describing format.
|
|
713
|
+
for i := 0; i < length; i++ {
|
|
714
|
+
itemPath := util.AddPathIndex(currentPath, i)
|
|
715
|
+
if err := ae.writeSelfDescribing(itemPath, val.Index(i).Interface()); err != nil {
|
|
716
|
+
return fmt.Errorf("error writing self-describing list item at index %d (path %s): %w", i, util.FormatPath(itemPath), err)
|
|
717
|
+
}
|
|
718
|
+
}
|
|
719
|
+
return nil
|
|
720
|
+
|
|
721
|
+
case reflect.String:
|
|
722
|
+
if _, err := ae.coreBuf.Write(wire.SelfDescribingString); err != nil { // String marker.
|
|
723
|
+
return err
|
|
724
|
+
}
|
|
725
|
+
stringBlockKey := wire.BlockKey("String")
|
|
726
|
+
stringElementType, blockDefOk := wire.SelfDescribingBlocks[stringBlockKey]
|
|
727
|
+
if !blockDefOk {
|
|
728
|
+
return fmt.Errorf("internal error: self-describing string block key ('%s') not found in wire.SelfDescribingBlocks map", stringBlockKey)
|
|
729
|
+
}
|
|
730
|
+
selfDescribingStringBlock := wire.NewBlockType(stringElementType, stringBlockKey, wire.MustDeduplicateByDefault(stringElementType))
|
|
731
|
+
_, err := ae.Write(selfDescribingStringBlock, wire.String, v.(string))
|
|
732
|
+
return err
|
|
733
|
+
|
|
734
|
+
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
|
735
|
+
if _, err := ae.coreBuf.Write(wire.SelfDescribingInt); err != nil { // Integer marker.
|
|
736
|
+
return err
|
|
737
|
+
}
|
|
738
|
+
varintBlockKey := wire.BlockKey("Int") // Standard key for self-describing integers.
|
|
739
|
+
varintElementType, blockDefOk := wire.SelfDescribingBlocks[varintBlockKey]
|
|
740
|
+
if !blockDefOk {
|
|
741
|
+
return fmt.Errorf("internal error: self-describing varint block key ('%s') not found in wire.SelfDescribingBlocks map", varintBlockKey)
|
|
742
|
+
}
|
|
743
|
+
selfDescribingVarintBlock := wire.NewBlockType(varintElementType, varintBlockKey, wire.MustDeduplicateByDefault(varintElementType))
|
|
744
|
+
_, err := ae.Write(selfDescribingVarintBlock, wire.Varint, val.Int()) // val.Int() converts various int types to int64 for varint encoder.
|
|
745
|
+
return err
|
|
746
|
+
|
|
747
|
+
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
|
748
|
+
uVal := val.Uint()
|
|
749
|
+
if _, err := ae.coreBuf.Write(wire.SelfDescribingInt); err != nil {
|
|
750
|
+
return err
|
|
751
|
+
}
|
|
752
|
+
varintBlockKey := wire.BlockKey("Int")
|
|
753
|
+
varintElementType, blockDefOk := wire.SelfDescribingBlocks[varintBlockKey]
|
|
754
|
+
if !blockDefOk {
|
|
755
|
+
return fmt.Errorf("internal error: self-describing varint block key ('%s') not found for uint value", varintBlockKey)
|
|
756
|
+
}
|
|
757
|
+
selfDescribingVarintBlock := wire.NewBlockType(varintElementType, varintBlockKey, wire.MustDeduplicateByDefault(varintElementType))
|
|
758
|
+
if uVal <= math.MaxInt64 { // If fits in int64, use that directly for varint encoder.
|
|
759
|
+
_, err := ae.Write(selfDescribingVarintBlock, wire.Varint, int64(uVal))
|
|
760
|
+
return err
|
|
761
|
+
}
|
|
762
|
+
// Otherwise, use *big.Int for varint encoding.
|
|
763
|
+
bigUVal := new(big.Int).SetUint64(uVal)
|
|
764
|
+
_, err := ae.Write(selfDescribingVarintBlock, wire.Varint, bigUVal)
|
|
765
|
+
return err
|
|
766
|
+
|
|
767
|
+
case reflect.Float32, reflect.Float64:
|
|
768
|
+
fVal := val.Float()
|
|
769
|
+
if fVal == math.Trunc(fVal) && fVal >= float64(math.MinInt64) && fVal <= float64(math.MaxInt64) {
|
|
770
|
+
// If float is a whole number and fits in int64, encode as SelfDescribingInt.
|
|
771
|
+
if _, err := ae.coreBuf.Write(wire.SelfDescribingInt); err != nil {
|
|
772
|
+
return err
|
|
773
|
+
}
|
|
774
|
+
varintBlockKey := wire.BlockKey("Int")
|
|
775
|
+
varintElementType, blockDefOk := wire.SelfDescribingBlocks[varintBlockKey]
|
|
776
|
+
if !blockDefOk {
|
|
777
|
+
return fmt.Errorf("internal error: self-describing varint block key ('%s') not found for whole float", varintBlockKey)
|
|
778
|
+
}
|
|
779
|
+
selfDescribingVarintBlock := wire.NewBlockType(varintElementType, varintBlockKey, wire.MustDeduplicateByDefault(varintElementType))
|
|
780
|
+
_, err := ae.Write(selfDescribingVarintBlock, wire.Varint, int64(fVal))
|
|
781
|
+
return err
|
|
782
|
+
}
|
|
783
|
+
// Otherwise, encode as SelfDescribingFloat.
|
|
784
|
+
if _, err := ae.coreBuf.Write(wire.SelfDescribingFloat); err != nil { // Float marker.
|
|
785
|
+
return err
|
|
786
|
+
}
|
|
787
|
+
floatBlockKey := wire.BlockKey("Float") // Standard key for self-describing floats.
|
|
788
|
+
floatElementType, blockDefOk := wire.SelfDescribingBlocks[floatBlockKey]
|
|
789
|
+
if !blockDefOk {
|
|
790
|
+
return fmt.Errorf("internal error: self-describing float block key ('%s') not found in wire.SelfDescribingBlocks map", floatBlockKey)
|
|
791
|
+
}
|
|
792
|
+
selfDescribingFloatBlock := wire.NewBlockType(floatElementType, floatBlockKey, wire.MustDeduplicateByDefault(floatElementType))
|
|
793
|
+
_, err := ae.Write(selfDescribingFloatBlock, wire.Float64, fVal)
|
|
794
|
+
return err
|
|
795
|
+
|
|
796
|
+
case reflect.Bool:
|
|
797
|
+
if v.(bool) {
|
|
798
|
+
_, err := ae.coreBuf.Write(wire.SelfDescribingTrue) // True marker.
|
|
799
|
+
return err
|
|
800
|
+
}
|
|
801
|
+
_, err := ae.coreBuf.Write(wire.SelfDescribingFalse) // False marker.
|
|
802
|
+
return err
|
|
803
|
+
|
|
804
|
+
case reflect.Ptr, reflect.Interface:
|
|
805
|
+
if val.IsNil() { // Handle nil pointer or nil interface.
|
|
806
|
+
_, err := ae.coreBuf.Write(wire.SelfDescribingNull)
|
|
807
|
+
return err
|
|
808
|
+
}
|
|
809
|
+
// Dereference pointer/interface and recurse with the element.
|
|
810
|
+
return ae.writeSelfDescribing(currentPath, val.Elem().Interface())
|
|
811
|
+
|
|
812
|
+
default:
|
|
813
|
+
// Handle *big.Int specifically, as it's a common type for large integers not caught by reflect.Int types.
|
|
814
|
+
if bigIntValue, isBigInt := v.(*big.Int); isBigInt {
|
|
815
|
+
if _, err := ae.coreBuf.Write(wire.SelfDescribingInt); err != nil {
|
|
816
|
+
return err
|
|
817
|
+
}
|
|
818
|
+
varintBlockKey := wire.BlockKey("Int")
|
|
819
|
+
varintElementType, blockDefOk := wire.SelfDescribingBlocks[varintBlockKey]
|
|
820
|
+
if !blockDefOk {
|
|
821
|
+
return fmt.Errorf("internal error: self-describing varint block key ('%s') not found for *big.Int", varintBlockKey)
|
|
822
|
+
}
|
|
823
|
+
selfDescribingVarintBlock := wire.NewBlockType(varintElementType, varintBlockKey, wire.MustDeduplicateByDefault(varintElementType))
|
|
824
|
+
_, err := ae.Write(selfDescribingVarintBlock, wire.Varint, bigIntValue)
|
|
825
|
+
return err
|
|
826
|
+
}
|
|
827
|
+
return fmt.Errorf("type error: cannot encode unsupported Go type %T (Kind: %s) in self-describing format at path %s", v, val.Kind(), util.FormatPath(currentPath))
|
|
828
|
+
}
|
|
829
|
+
}
|
|
830
|
+
|
|
831
|
+
// ArgoErrorValue defines the structure for representing GraphQL errors in Argo format when not using self-describing errors.
|
|
832
|
+
// It includes standard GraphQL error fields. The `Path` is transformed into a list of integers/strings for Argo.
|
|
833
|
+
type ArgoErrorValue struct {
|
|
834
|
+
Message string // The error message.
|
|
835
|
+
Locations []ArgoErrorLocation // Source locations of the error in the query.
|
|
836
|
+
Path []interface{} // Path to the field where the error occurred, as a list of string field names and integer indices.
|
|
837
|
+
Extensions *orderedmap.OrderedMap[string, interface{}] // Custom error data.
|
|
838
|
+
}
|
|
839
|
+
|
|
840
|
+
// ArgoErrorLocation represents a single source location (line and column) for an error.
|
|
841
|
+
type ArgoErrorLocation struct {
|
|
842
|
+
Line int `json:"line"` // 1-indexed line number.
|
|
843
|
+
Column int `json:"column"` // 1-indexed column number.
|
|
844
|
+
}
|
|
845
|
+
|
|
846
|
+
// writeGoError converts a standard Go `error` into an ArgoErrorValue (represented as an *orderedmap.OrderedMap for deterministic field order)
|
|
847
|
+
// and then writes this map using the structured `wire.Error` type definition.
|
|
848
|
+
// This is invoked when the `HeaderSelfDescribingErrorsFlag` is false.
|
|
849
|
+
// `currentPath` is the GraphQL path to where the error label itself is being written.
|
|
850
|
+
func (ae *ArgoEncoder) writeGoError(currentPath ast.Path, goErr error) error {
|
|
851
|
+
// Construct the ArgoErrorValue.
|
|
852
|
+
argoErrVal := ArgoErrorValue{
|
|
853
|
+
Message: goErr.Error(),
|
|
854
|
+
// Locations and Path are typically not available from a generic Go error directly.
|
|
855
|
+
// These would need to be populated if `goErr` is a more structured error type
|
|
856
|
+
// that carries GraphQL-specific location/path information.
|
|
857
|
+
// For now, we add the Go error type to extensions for some context.
|
|
858
|
+
Extensions: orderedmap.NewOrderedMap[string, interface{}](),
|
|
859
|
+
}
|
|
860
|
+
argoErrVal.Extensions.Set("go_error_type", reflect.TypeOf(goErr).String())
|
|
861
|
+
|
|
862
|
+
// Convert ArgoErrorValue to an *orderedmap.OrderedMap for encoding with wire.Error type.
|
|
863
|
+
// The order of Set calls determines the field order in the Argo output if wire.Error is a RecordType.
|
|
864
|
+
errorMap := orderedmap.NewOrderedMap[string, interface{}]()
|
|
865
|
+
errorMap.Set("message", argoErrVal.Message)
|
|
866
|
+
if argoErrVal.Locations != nil { // Only include if present.
|
|
867
|
+
errorMap.Set("locations", argoErrVal.Locations)
|
|
868
|
+
}
|
|
869
|
+
if argoErrVal.Path != nil { // Only include if present.
|
|
870
|
+
errorMap.Set("path", argoErrVal.Path)
|
|
871
|
+
}
|
|
872
|
+
if argoErrVal.Extensions != nil && argoErrVal.Extensions.Len() > 0 { // Only include if non-empty.
|
|
873
|
+
errorMap.Set("extensions", argoErrVal.Extensions)
|
|
874
|
+
}
|
|
875
|
+
|
|
876
|
+
// Write the errorMap using the predefined wire.Error schema.
|
|
877
|
+
// currentBlock is nil as errors are part of the core stream, not typically within other blocks.
|
|
878
|
+
return ae.writeArgo(currentPath, errorMap, wire.Error, nil)
|
|
879
|
+
}
|
|
880
|
+
|
|
881
|
+
// GetResult finalizes the encoding process. It assembles the Argo header,
|
|
882
|
+
// data from all block writers (if not inlining everything), and the core buffer data
|
|
883
|
+
// into a single, final *buf.Buf containing the complete Argo message.
|
|
884
|
+
func (ae *ArgoEncoder) GetResult() (*buf.Buf, error) {
|
|
885
|
+
headerBytes, err := ae.header.AsBytes() // Serialize the header to bytes.
|
|
886
|
+
if err != nil {
|
|
887
|
+
return nil, fmt.Errorf("failed to serialize Argo header: %w", err)
|
|
888
|
+
}
|
|
889
|
+
ae.Track(nil, "header bytes written", nil, headerBytes) // For debugging, length of header.
|
|
890
|
+
|
|
891
|
+
shouldWriteBlocks := !ae.header.GetFlag(header.HeaderInlineEverythingFlag)
|
|
892
|
+
totalDataBytesFromBlocks := 0 // Total size of content from all blocks.
|
|
893
|
+
blockLengthLabelBytesTotal := 0 // Total size of all block length labels.
|
|
894
|
+
|
|
895
|
+
// blockToWrite temporarily stores data for each block before final assembly.
|
|
896
|
+
type blockToWrite struct {
|
|
897
|
+
key wire.BlockKey // The block's unique key.
|
|
898
|
+
lengthLabelData []byte // Encoded label for the total length of this block's content.
|
|
899
|
+
contentBytes [][]byte // Slice of byte slices, each representing a value in the block.
|
|
900
|
+
}
|
|
901
|
+
var blocksToWrite []blockToWrite // List of blocks to be written, in order.
|
|
902
|
+
|
|
903
|
+
if shouldWriteBlocks {
|
|
904
|
+
// Iterate through writers in the order they were created (preserved by OrderedMap).
|
|
905
|
+
// This ensures blocks are written in a deterministic order, matching reference implementations.
|
|
906
|
+
for el := ae.writers.Front(); el != nil; el = el.Next() {
|
|
907
|
+
key := el.Key
|
|
908
|
+
entry := el.Value // writerEntry
|
|
909
|
+
writer := entry.Writer
|
|
910
|
+
originalValueType := entry.OriginalValueType // e.g. wire.String, wire.Bytes
|
|
911
|
+
|
|
912
|
+
blockContentBytes := writer.AllValuesAsBytes() // Get all accumulated byte values for this block.
|
|
913
|
+
currentBlockTotalBytes := 0
|
|
914
|
+
|
|
915
|
+
isStringBlock := wire.IsString(originalValueType)
|
|
916
|
+
|
|
917
|
+
processedBlockContentBytes := make([][]byte, 0, len(blockContentBytes))
|
|
918
|
+
for _, valueBytes := range blockContentBytes {
|
|
919
|
+
currentBlockTotalBytes += len(valueBytes)
|
|
920
|
+
processedBlockContentBytes = append(processedBlockContentBytes, valueBytes)
|
|
921
|
+
// If it's a string block and null termination is enabled, add terminator.
|
|
922
|
+
if isStringBlock && ae.header.GetFlag(header.HeaderNullTerminatedStringsFlag) {
|
|
923
|
+
processedBlockContentBytes = append(processedBlockContentBytes, nullTerminator)
|
|
924
|
+
currentBlockTotalBytes += len(nullTerminator)
|
|
925
|
+
}
|
|
926
|
+
}
|
|
927
|
+
|
|
928
|
+
lengthLabel := label.NewFromInt64(int64(currentBlockTotalBytes)) // Label for total length of this block.
|
|
929
|
+
encodedLengthLabel := lengthLabel.Encode()
|
|
930
|
+
|
|
931
|
+
blocksToWrite = append(blocksToWrite, blockToWrite{
|
|
932
|
+
key: key,
|
|
933
|
+
lengthLabelData: encodedLengthLabel,
|
|
934
|
+
contentBytes: processedBlockContentBytes,
|
|
935
|
+
})
|
|
936
|
+
|
|
937
|
+
totalDataBytesFromBlocks += currentBlockTotalBytes
|
|
938
|
+
blockLengthLabelBytesTotal += len(encodedLengthLabel)
|
|
939
|
+
}
|
|
940
|
+
}
|
|
941
|
+
|
|
942
|
+
coreDataBytes := ae.coreBuf.Bytes() // Get all bytes from the core buffer (labels, inlined data).
|
|
943
|
+
coreDataLength := len(coreDataBytes)
|
|
944
|
+
var coreLengthLabelBytes []byte
|
|
945
|
+
if shouldWriteBlocks { // If blocks are written, the core data also needs a length label.
|
|
946
|
+
coreLengthLabel := label.NewFromInt64(int64(coreDataLength))
|
|
947
|
+
coreLengthLabelBytes = coreLengthLabel.Encode()
|
|
948
|
+
}
|
|
949
|
+
|
|
950
|
+
// Calculate the total size of the final Argo message.
|
|
951
|
+
finalSize := len(headerBytes)
|
|
952
|
+
if shouldWriteBlocks {
|
|
953
|
+
finalSize += blockLengthLabelBytesTotal // All block length labels.
|
|
954
|
+
finalSize += totalDataBytesFromBlocks // All block content.
|
|
955
|
+
finalSize += len(coreLengthLabelBytes) // Core data length label.
|
|
956
|
+
}
|
|
957
|
+
finalSize += coreDataLength // Core data itself.
|
|
958
|
+
|
|
959
|
+
// Allocate the final buffer and write all parts in order.
|
|
960
|
+
finalBuf := buf.NewBuf(finalSize)
|
|
961
|
+
|
|
962
|
+
_, _ = finalBuf.Write(headerBytes) // 1. Header
|
|
963
|
+
|
|
964
|
+
if shouldWriteBlocks {
|
|
965
|
+
// 2. For each block: its length label, then its content.
|
|
966
|
+
for _, btw := range blocksToWrite {
|
|
967
|
+
_, _ = finalBuf.Write(btw.lengthLabelData)
|
|
968
|
+
for _, valueData := range btw.contentBytes {
|
|
969
|
+
_, _ = finalBuf.Write(valueData)
|
|
970
|
+
}
|
|
971
|
+
}
|
|
972
|
+
// 3. Core data length label.
|
|
973
|
+
_, _ = finalBuf.Write(coreLengthLabelBytes)
|
|
974
|
+
}
|
|
975
|
+
|
|
976
|
+
// 4. Core data.
|
|
977
|
+
_, _ = finalBuf.Write(coreDataBytes)
|
|
978
|
+
|
|
979
|
+
// Sanity check the final length.
|
|
980
|
+
if finalBuf.Len() != finalSize {
|
|
981
|
+
return nil, fmt.Errorf("internal encoder error: incorrect result length. Wrote %d, expected %d", finalBuf.Len(), finalSize)
|
|
982
|
+
}
|
|
983
|
+
|
|
984
|
+
return finalBuf, nil
|
|
985
|
+
}
|