From 2156a6bf737f1f85841c536839bbf02f771d00f0 Mon Sep 17 00:00:00 2001 From: Pavel Pogodaev Date: Mon, 7 Oct 2024 17:20:25 +0300 Subject: [PATCH] [#276] Merge repo with frostfs-api-go Signed-off-by: Pavel Pogodaev --- Makefile | 65 + accounting/decimal.go | 4 +- accounting/decimal_test.go | 2 +- accounting/doc.go | 2 +- ape/chain.go | 2 +- ape/chain_target.go | 2 +- ape/chain_target_test.go | 2 +- ape/chain_test.go | 2 +- ape/grpc/types_frostfs.pb.go | Bin 0 -> 8595 bytes ape/grpc/types_frostfs_fuzz.go | 45 + ape/grpc/types_frostfs_test.go | 31 + api/accounting/accounting.go | 104 + api/accounting/convert.go | 178 ++ api/accounting/grpc/service_frostfs.pb.go | Bin 0 -> 18911 bytes api/accounting/grpc/service_frostfs_fuzz.go | 45 + api/accounting/grpc/service_frostfs_test.go | 31 + api/accounting/grpc/service_grpc.pb.go | Bin 0 -> 4333 bytes api/accounting/grpc/types_frostfs.pb.go | Bin 0 -> 4327 bytes api/accounting/grpc/types_frostfs_fuzz.go | 26 + api/accounting/grpc/types_frostfs_test.go | 21 + api/accounting/json.go | 14 + api/accounting/marshal.go | 104 + api/accounting/message_test.go | 19 + api/accounting/test/generate.go | 64 + api/acl/bench_test.go | 51 + api/acl/convert.go | 592 ++++ api/acl/filters.go | 33 + api/acl/grpc/types_frostfs.pb.go | Bin 0 -> 48052 bytes api/acl/grpc/types_frostfs_fuzz.go | 64 + api/acl/grpc/types_frostfs_test.go | 41 + api/acl/json.go | 70 + api/acl/marshal.go | 350 +++ api/acl/message_test.go | 21 + api/acl/string.go | 110 + api/acl/test/generate.go | 144 + api/acl/types.go | 426 +++ api/ape/convert.go | 132 + api/ape/grpc/types_frostfs.pb.go | Bin 0 -> 8595 bytes api/ape/grpc/types_frostfs_fuzz.go | 45 + api/ape/grpc/types_frostfs_test.go | 31 + api/ape/json.go | 14 + api/ape/marshal.go | 92 + api/ape/message_test.go | 15 + api/ape/string.go | 18 + api/ape/test/generate.go | 71 + api/ape/types.go | 79 + api/apemanager/convert.go | 358 +++ api/apemanager/grpc/service_frostfs.pb.go | Bin 0 -> 57153 bytes api/apemanager/grpc/service_frostfs_fuzz.go | 121 + api/apemanager/grpc/service_frostfs_test.go | 71 + api/apemanager/grpc/service_grpc.pb.go | Bin 0 -> 9917 bytes api/apemanager/marshal.go | 205 ++ api/apemanager/message_test.go | 26 + api/apemanager/status.go | 76 + api/apemanager/status_test.go | 30 + api/apemanager/test/generate.go | 143 + api/apemanager/types.go | 226 ++ api/container/attributes.go | 90 + api/container/attributes_test.go | 59 + api/container/convert.go | 764 +++++ api/container/grpc/service_frostfs.pb.go | Bin 0 -> 76792 bytes api/container/grpc/service_frostfs_fuzz.go | 159 + api/container/grpc/service_frostfs_test.go | 91 + api/container/grpc/service_grpc.pb.go | Bin 0 -> 11737 bytes api/container/grpc/types_frostfs.pb.go | Bin 0 -> 12213 bytes api/container/grpc/types_frostfs_fuzz.go | 26 + api/container/grpc/types_frostfs_test.go | 21 + api/container/json.go | 22 + api/container/marshal.go | 345 +++ api/container/message_test.go | 36 + api/container/status.go | 33 + api/container/status_test.go | 15 + api/container/test/generate.go | 240 ++ api/container/types.go | 446 +++ api/lock/grpc/types_frostfs.pb.go | Bin 0 -> 3858 bytes api/lock/grpc/types_frostfs_fuzz.go | 26 + api/lock/grpc/types_frostfs_test.go | 21 + api/netmap/convert.go | 916 ++++++ api/netmap/grpc/service_frostfs.pb.go | Bin 0 -> 55007 bytes api/netmap/grpc/service_frostfs_fuzz.go | 121 + api/netmap/grpc/service_frostfs_test.go | 71 + api/netmap/grpc/service_grpc.pb.go | Bin 0 -> 9148 bytes api/netmap/grpc/types_frostfs.pb.go | Bin 0 -> 57425 bytes api/netmap/grpc/types_frostfs_fuzz.go | 159 + api/netmap/grpc/types_frostfs_test.go | 91 + api/netmap/json.go | 62 + api/netmap/marshal.go | 576 ++++ api/netmap/message_test.go | 32 + api/netmap/string.go | 68 + api/netmap/test/generate.go | 335 +++ api/netmap/types.go | 783 +++++ api/object/attributes.go | 187 ++ api/object/attributes_test.go | 89 + api/object/bench_test.go | 45 + api/object/convert.go | 2555 +++++++++++++++++ api/object/filters.go | 58 + api/object/grpc/service_frostfs.pb.go | Bin 0 -> 223725 bytes api/object/grpc/service_frostfs_fuzz.go | 387 +++ api/object/grpc/service_frostfs_test.go | 211 ++ api/object/grpc/service_grpc.pb.go | Bin 0 -> 45844 bytes api/object/grpc/types_frostfs.pb.go | Bin 0 -> 65153 bytes api/object/grpc/types_frostfs_fuzz.go | 102 + api/object/grpc/types_frostfs_test.go | 61 + api/object/json.go | 94 + api/object/lock.go | 160 ++ api/object/lock_test.go | 26 + api/object/marshal.go | 1428 +++++++++ api/object/message_test.go | 65 + api/object/status.go | 91 + api/object/status_test.go | 35 + api/object/string.go | 55 + api/object/test/generate.go | 766 +++++ api/object/types.go | 1650 +++++++++++ api/refs/bench_test.go | 53 + api/refs/convert.go | 264 ++ api/refs/grpc/types_frostfs.pb.go | Bin 0 -> 30571 bytes api/refs/grpc/types_frostfs_fuzz.go | 159 + api/refs/grpc/types_frostfs_test.go | 91 + api/refs/json.go | 62 + api/refs/marshal.go | 264 ++ api/refs/message_test.go | 21 + api/refs/string.go | 47 + api/refs/test/generate.go | 127 + api/refs/types.go | 194 ++ api/rpc/accounting.go | 29 + api/rpc/apemanager.go | 60 + api/rpc/client/call_options.go | 40 + api/rpc/client/client.go | 30 + api/rpc/client/conn.go | 24 + api/rpc/client/connect.go | 72 + api/rpc/client/flows.go | 124 + api/rpc/client/init.go | 69 + api/rpc/client/options.go | 129 + api/rpc/client/options_test.go | 197 ++ api/rpc/client/stream_wrapper.go | 58 + api/rpc/client/util.go | 13 + api/rpc/common.go | 10 + api/rpc/common/call.go | 75 + api/rpc/common/call_test.go | 49 + api/rpc/container.go | 82 + api/rpc/grpc/init.go | 4 + api/rpc/message/encoding.go | 40 + api/rpc/message/message.go | 43 + api/rpc/message/test/message.go | 126 + api/rpc/netmap.go | 62 + api/rpc/object.go | 243 ++ api/rpc/session.go | 28 + api/session/convert.go | 898 ++++++ api/session/grpc/service_frostfs.pb.go | Bin 0 -> 20200 bytes api/session/grpc/service_frostfs_fuzz.go | 45 + api/session/grpc/service_frostfs_test.go | 31 + api/session/grpc/service_grpc.pb.go | Bin 0 -> 4116 bytes api/session/grpc/types_frostfs.pb.go | Bin 0 -> 70740 bytes api/session/grpc/types_frostfs_fuzz.go | 159 + api/session/grpc/types_frostfs_test.go | 91 + api/session/json.go | 86 + api/session/marshal.go | 536 ++++ api/session/message_test.go | 27 + api/session/status.go | 32 + api/session/status_test.go | 15 + api/session/string.go | 47 + api/session/test/generate.go | 251 ++ api/session/types.go | 836 ++++++ api/session/util.go | 167 ++ api/session/xheaders.go | 34 + api/signature/body.go | 116 + api/signature/marshaller.go | 26 + api/signature/sign.go | 122 + api/signature/sign_test.go | 125 + api/signature/verify.go | 127 + api/status/convert.go | 95 + api/status/details.go | 8 + api/status/grpc/types_frostfs.pb.go | Bin 0 -> 14147 bytes api/status/grpc/types_frostfs_fuzz.go | 26 + api/status/grpc/types_frostfs_test.go | 21 + api/status/marshal.go | 92 + api/status/message_test.go | 16 + api/status/status.go | 103 + api/status/test/codes.go | 28 + api/status/test/generate.go | 44 + api/status/types.go | 124 + api/tombstone/convert.go | 41 + api/tombstone/grpc/types_frostfs.pb.go | Bin 0 -> 5770 bytes api/tombstone/grpc/types_frostfs_fuzz.go | 26 + api/tombstone/grpc/types_frostfs_test.go | 21 + api/tombstone/json.go | 14 + api/tombstone/marshal.go | 56 + api/tombstone/message_test.go | 15 + api/tombstone/test/generate.go | 23 + api/tombstone/types.go | 57 + api/util/pool/buffer.go | 54 + api/util/pool/marshal.go | 7 + api/util/proto/encoding/compat.go | 22 + api/util/proto/encoding/json.go | 48 + api/util/proto/encoding/proto.go | 57 + api/util/proto/marshal.go | 413 +++ api/util/proto/marshal_test.go | 255 ++ api/util/proto/test/custom/test_frostfs.pb.go | Bin 0 -> 34806 bytes api/util/proto/test/test.pb.go | Bin 0 -> 20911 bytes api/util/protogen/internalgengo/file.go | 245 ++ api/util/protogen/internalgengo/fuzz.go | 69 + api/util/protogen/internalgengo/getter.go | 14 + api/util/protogen/internalgengo/json.go | 270 ++ api/util/protogen/internalgengo/options.go | 7 + api/util/protogen/internalgengo/proto.go | 202 ++ .../internalgengo/proto_field_type.go | 59 + .../internalgengo/proto_stable_compat.go | 124 + api/util/protogen/internalgengo/writer.go | 30 + api/util/protogen/main.go | 27 + api/util/signature/data.go | 93 + api/util/signature/options.go | 77 + api/util/signature/sign_test.go | 44 + api/util/signature/walletconnect/sign.go | 142 + api/util/signature/walletconnect/sign_test.go | 112 + bearer/bearer.go | 8 +- bearer/bearer_test.go | 4 +- checksum/checksum.go | 4 +- checksum/checksum_test.go | 2 +- checksum/example_test.go | 2 +- client/accounting.go | 12 +- client/apemanager_add_chain.go | 10 +- client/apemanager_list_chains.go | 10 +- client/apemanager_remove_chain.go | 10 +- client/api.go | 6 +- client/client.go | 8 +- client/common.go | 12 +- client/container_delete.go | 12 +- client/container_get.go | 12 +- client/container_list.go | 12 +- client/container_put.go | 12 +- client/doc.go | 4 +- client/netmap.go | 10 +- client/netmap_test.go | 6 +- client/object_delete.go | 14 +- client/object_get.go | 14 +- client/object_hash.go | 14 +- client/object_patch.go | 12 +- client/object_patch_test.go | 2 +- client/object_put.go | 2 +- client/object_put_raw.go | 12 +- client/object_put_single.go | 12 +- client/object_put_transformer.go | 2 +- client/object_search.go | 14 +- client/object_search_test.go | 6 +- client/response.go | 2 +- client/session.go | 10 +- client/status/apemanager.go | 4 +- client/status/common.go | 6 +- client/status/common_test.go | 2 +- client/status/container.go | 4 +- client/status/object.go | 4 +- client/status/session.go | 4 +- client/status/success.go | 2 +- client/status/unrecognized.go | 2 +- client/status/v2.go | 12 +- container/container.go | 8 +- container/container_test.go | 6 +- container/doc.go | 2 +- container/id/id.go | 4 +- container/id/id_test.go | 2 +- crypto/crypto_test.go | 2 +- crypto/doc.go | 2 +- crypto/ecdsa/wallet_connect.go | 2 +- crypto/signature.go | 4 +- crypto/signer.go | 2 +- eacl/enums.go | 2 +- eacl/enums_test.go | 2 +- eacl/filter.go | 2 +- eacl/filter_test.go | 2 +- eacl/record.go | 2 +- eacl/record_test.go | 2 +- eacl/table.go | 4 +- eacl/table_test.go | 2 +- eacl/target.go | 2 +- eacl/target_test.go | 2 +- go.mod | 11 +- go.sum | Bin 17907 -> 17793 bytes netmap/context.go | 2 +- netmap/doc.go | 2 +- netmap/filter.go | 2 +- netmap/filter_test.go | 2 +- netmap/helper_test.go | 2 +- netmap/netmap.go | 4 +- netmap/netmap_test.go | 2 +- netmap/network_info.go | 4 +- netmap/network_info_test.go | 2 +- netmap/node_info.go | 4 +- netmap/node_info_test.go | 2 +- netmap/policy.go | 4 +- netmap/selector.go | 2 +- netmap/selector_test.go | 2 +- netmap/yml_unmarshal.go | 2 +- object/attribute.go | 2 +- object/attribute_test.go | 2 +- object/ecinfo.go | 4 +- object/erasure_code.go | 4 +- object/error_test.go | 4 +- object/fmt.go | 2 +- object/id/address.go | 4 +- object/id/address_test.go | 2 +- object/id/id.go | 4 +- object/id/id_test.go | 2 +- object/lock.go | 4 +- object/object.go | 8 +- object/object_test.go | 2 +- object/patch.go | 4 +- object/patch_test.go | 4 +- object/range.go | 2 +- object/range_test.go | 2 +- object/raw.go | 2 +- object/raw_test.go | 2 +- object/search.go | 2 +- object/search_test.go | 2 +- object/splitinfo.go | 4 +- object/splitinfo_test.go | 2 +- object/tombstone.go | 4 +- object/tombstone_test.go | 2 +- object/transformer/transformer.go | 2 +- object/type.go | 2 +- object/type_test.go | 2 +- pool/mock_test.go | 2 +- pool/tree/client.go | 2 +- pool/tree/service/service_frostfs.pb.go | Bin 60583 -> 60584 bytes pool/tree/service/types_frostfs.pb.go | Bin 3111 -> 3112 bytes prepare.sh | 39 + session/common.go | 4 +- session/container.go | 6 +- session/container_test.go | 4 +- session/doc.go | 2 +- session/object.go | 6 +- session/object_test.go | 4 +- user/doc.go | 2 +- user/id.go | 4 +- user/id_test.go | 2 +- version/version.go | 4 +- version/version_test.go | 2 +- 336 files changed, 28235 insertions(+), 279 deletions(-) create mode 100644 ape/grpc/types_frostfs.pb.go create mode 100644 ape/grpc/types_frostfs_fuzz.go create mode 100644 ape/grpc/types_frostfs_test.go create mode 100644 api/accounting/accounting.go create mode 100644 api/accounting/convert.go create mode 100644 api/accounting/grpc/service_frostfs.pb.go create mode 100644 api/accounting/grpc/service_frostfs_fuzz.go create mode 100644 api/accounting/grpc/service_frostfs_test.go create mode 100644 api/accounting/grpc/service_grpc.pb.go create mode 100644 api/accounting/grpc/types_frostfs.pb.go create mode 100644 api/accounting/grpc/types_frostfs_fuzz.go create mode 100644 api/accounting/grpc/types_frostfs_test.go create mode 100644 api/accounting/json.go create mode 100644 api/accounting/marshal.go create mode 100644 api/accounting/message_test.go create mode 100644 api/accounting/test/generate.go create mode 100644 api/acl/bench_test.go create mode 100644 api/acl/convert.go create mode 100644 api/acl/filters.go create mode 100644 api/acl/grpc/types_frostfs.pb.go create mode 100644 api/acl/grpc/types_frostfs_fuzz.go create mode 100644 api/acl/grpc/types_frostfs_test.go create mode 100644 api/acl/json.go create mode 100644 api/acl/marshal.go create mode 100644 api/acl/message_test.go create mode 100644 api/acl/string.go create mode 100644 api/acl/test/generate.go create mode 100644 api/acl/types.go create mode 100644 api/ape/convert.go create mode 100644 api/ape/grpc/types_frostfs.pb.go create mode 100644 api/ape/grpc/types_frostfs_fuzz.go create mode 100644 api/ape/grpc/types_frostfs_test.go create mode 100644 api/ape/json.go create mode 100644 api/ape/marshal.go create mode 100644 api/ape/message_test.go create mode 100644 api/ape/string.go create mode 100644 api/ape/test/generate.go create mode 100644 api/ape/types.go create mode 100644 api/apemanager/convert.go create mode 100644 api/apemanager/grpc/service_frostfs.pb.go create mode 100644 api/apemanager/grpc/service_frostfs_fuzz.go create mode 100644 api/apemanager/grpc/service_frostfs_test.go create mode 100644 api/apemanager/grpc/service_grpc.pb.go create mode 100644 api/apemanager/marshal.go create mode 100644 api/apemanager/message_test.go create mode 100644 api/apemanager/status.go create mode 100644 api/apemanager/status_test.go create mode 100644 api/apemanager/test/generate.go create mode 100644 api/apemanager/types.go create mode 100644 api/container/attributes.go create mode 100644 api/container/attributes_test.go create mode 100644 api/container/convert.go create mode 100644 api/container/grpc/service_frostfs.pb.go create mode 100644 api/container/grpc/service_frostfs_fuzz.go create mode 100644 api/container/grpc/service_frostfs_test.go create mode 100644 api/container/grpc/service_grpc.pb.go create mode 100644 api/container/grpc/types_frostfs.pb.go create mode 100644 api/container/grpc/types_frostfs_fuzz.go create mode 100644 api/container/grpc/types_frostfs_test.go create mode 100644 api/container/json.go create mode 100644 api/container/marshal.go create mode 100644 api/container/message_test.go create mode 100644 api/container/status.go create mode 100644 api/container/status_test.go create mode 100644 api/container/test/generate.go create mode 100644 api/container/types.go create mode 100644 api/lock/grpc/types_frostfs.pb.go create mode 100644 api/lock/grpc/types_frostfs_fuzz.go create mode 100644 api/lock/grpc/types_frostfs_test.go create mode 100644 api/netmap/convert.go create mode 100644 api/netmap/grpc/service_frostfs.pb.go create mode 100644 api/netmap/grpc/service_frostfs_fuzz.go create mode 100644 api/netmap/grpc/service_frostfs_test.go create mode 100644 api/netmap/grpc/service_grpc.pb.go create mode 100644 api/netmap/grpc/types_frostfs.pb.go create mode 100644 api/netmap/grpc/types_frostfs_fuzz.go create mode 100644 api/netmap/grpc/types_frostfs_test.go create mode 100644 api/netmap/json.go create mode 100644 api/netmap/marshal.go create mode 100644 api/netmap/message_test.go create mode 100644 api/netmap/string.go create mode 100644 api/netmap/test/generate.go create mode 100644 api/netmap/types.go create mode 100644 api/object/attributes.go create mode 100644 api/object/attributes_test.go create mode 100644 api/object/bench_test.go create mode 100644 api/object/convert.go create mode 100644 api/object/filters.go create mode 100644 api/object/grpc/service_frostfs.pb.go create mode 100644 api/object/grpc/service_frostfs_fuzz.go create mode 100644 api/object/grpc/service_frostfs_test.go create mode 100644 api/object/grpc/service_grpc.pb.go create mode 100644 api/object/grpc/types_frostfs.pb.go create mode 100644 api/object/grpc/types_frostfs_fuzz.go create mode 100644 api/object/grpc/types_frostfs_test.go create mode 100644 api/object/json.go create mode 100644 api/object/lock.go create mode 100644 api/object/lock_test.go create mode 100644 api/object/marshal.go create mode 100644 api/object/message_test.go create mode 100644 api/object/status.go create mode 100644 api/object/status_test.go create mode 100644 api/object/string.go create mode 100644 api/object/test/generate.go create mode 100644 api/object/types.go create mode 100644 api/refs/bench_test.go create mode 100644 api/refs/convert.go create mode 100644 api/refs/grpc/types_frostfs.pb.go create mode 100644 api/refs/grpc/types_frostfs_fuzz.go create mode 100644 api/refs/grpc/types_frostfs_test.go create mode 100644 api/refs/json.go create mode 100644 api/refs/marshal.go create mode 100644 api/refs/message_test.go create mode 100644 api/refs/string.go create mode 100644 api/refs/test/generate.go create mode 100644 api/refs/types.go create mode 100644 api/rpc/accounting.go create mode 100644 api/rpc/apemanager.go create mode 100644 api/rpc/client/call_options.go create mode 100644 api/rpc/client/client.go create mode 100644 api/rpc/client/conn.go create mode 100644 api/rpc/client/connect.go create mode 100644 api/rpc/client/flows.go create mode 100644 api/rpc/client/init.go create mode 100644 api/rpc/client/options.go create mode 100644 api/rpc/client/options_test.go create mode 100644 api/rpc/client/stream_wrapper.go create mode 100644 api/rpc/client/util.go create mode 100644 api/rpc/common.go create mode 100644 api/rpc/common/call.go create mode 100644 api/rpc/common/call_test.go create mode 100644 api/rpc/container.go create mode 100644 api/rpc/grpc/init.go create mode 100644 api/rpc/message/encoding.go create mode 100644 api/rpc/message/message.go create mode 100644 api/rpc/message/test/message.go create mode 100644 api/rpc/netmap.go create mode 100644 api/rpc/object.go create mode 100644 api/rpc/session.go create mode 100644 api/session/convert.go create mode 100644 api/session/grpc/service_frostfs.pb.go create mode 100644 api/session/grpc/service_frostfs_fuzz.go create mode 100644 api/session/grpc/service_frostfs_test.go create mode 100644 api/session/grpc/service_grpc.pb.go create mode 100644 api/session/grpc/types_frostfs.pb.go create mode 100644 api/session/grpc/types_frostfs_fuzz.go create mode 100644 api/session/grpc/types_frostfs_test.go create mode 100644 api/session/json.go create mode 100644 api/session/marshal.go create mode 100644 api/session/message_test.go create mode 100644 api/session/status.go create mode 100644 api/session/status_test.go create mode 100644 api/session/string.go create mode 100644 api/session/test/generate.go create mode 100644 api/session/types.go create mode 100644 api/session/util.go create mode 100644 api/session/xheaders.go create mode 100644 api/signature/body.go create mode 100644 api/signature/marshaller.go create mode 100644 api/signature/sign.go create mode 100644 api/signature/sign_test.go create mode 100644 api/signature/verify.go create mode 100644 api/status/convert.go create mode 100644 api/status/details.go create mode 100644 api/status/grpc/types_frostfs.pb.go create mode 100644 api/status/grpc/types_frostfs_fuzz.go create mode 100644 api/status/grpc/types_frostfs_test.go create mode 100644 api/status/marshal.go create mode 100644 api/status/message_test.go create mode 100644 api/status/status.go create mode 100644 api/status/test/codes.go create mode 100644 api/status/test/generate.go create mode 100644 api/status/types.go create mode 100644 api/tombstone/convert.go create mode 100644 api/tombstone/grpc/types_frostfs.pb.go create mode 100644 api/tombstone/grpc/types_frostfs_fuzz.go create mode 100644 api/tombstone/grpc/types_frostfs_test.go create mode 100644 api/tombstone/json.go create mode 100644 api/tombstone/marshal.go create mode 100644 api/tombstone/message_test.go create mode 100644 api/tombstone/test/generate.go create mode 100644 api/tombstone/types.go create mode 100644 api/util/pool/buffer.go create mode 100644 api/util/pool/marshal.go create mode 100644 api/util/proto/encoding/compat.go create mode 100644 api/util/proto/encoding/json.go create mode 100644 api/util/proto/encoding/proto.go create mode 100644 api/util/proto/marshal.go create mode 100644 api/util/proto/marshal_test.go create mode 100644 api/util/proto/test/custom/test_frostfs.pb.go create mode 100644 api/util/proto/test/test.pb.go create mode 100644 api/util/protogen/internalgengo/file.go create mode 100644 api/util/protogen/internalgengo/fuzz.go create mode 100644 api/util/protogen/internalgengo/getter.go create mode 100644 api/util/protogen/internalgengo/json.go create mode 100644 api/util/protogen/internalgengo/options.go create mode 100644 api/util/protogen/internalgengo/proto.go create mode 100644 api/util/protogen/internalgengo/proto_field_type.go create mode 100644 api/util/protogen/internalgengo/proto_stable_compat.go create mode 100644 api/util/protogen/internalgengo/writer.go create mode 100644 api/util/protogen/main.go create mode 100644 api/util/signature/data.go create mode 100644 api/util/signature/options.go create mode 100644 api/util/signature/sign_test.go create mode 100644 api/util/signature/walletconnect/sign.go create mode 100644 api/util/signature/walletconnect/sign_test.go create mode 100755 prepare.sh diff --git a/Makefile b/Makefile index 32b588e..6f62f6d 100755 --- a/Makefile +++ b/Makefile @@ -7,11 +7,76 @@ TRUECLOUDLAB_LINT_VERSION ?= 0.0.6 OUTPUT_LINT_DIR ?= $(shell pwd)/bin LINT_DIR = $(OUTPUT_LINT_DIR)/golangci-lint-$(LINT_VERSION)-v$(TRUECLOUDLAB_LINT_VERSION) +PROTOC_VERSION ?= 27.2 +PROTOC_GEN_GO_VERSION ?= $(shell go list -f '{{.Version}}' -m google.golang.org/protobuf) +PROTOC_OS_VERSION=osx-x86_64 +ifeq ($(shell uname), Linux) + PROTOC_OS_VERSION=linux-x86_64 +endif + +BIN = bin +PROTOBUF_DIR ?= $(abspath $(BIN))/protobuf +PROTOC_DIR ?= $(PROTOBUF_DIR)/protoc-v$(PROTOC_VERSION) +PROTOC_GEN_GO_DIR ?= $(PROTOBUF_DIR)/protoc-gen-go-$(PROTOC_GEN_GO_VERSION) + + +.PHONY: dep imports protoc test lint help $(BIN)/protogen protoc-test + # Run tests test: GOFLAGS ?= "-cover -count=1" test: @GOFLAGS=$(GOFLAGS) go test ./... +# Reformat imports +imports: + @echo "⇒ Processing goimports check" + @for f in `find . -type f -name '*.go' -not -name '*.pb.go' -prune`; do \ + goimports -w $$f; \ + done + +# Install protoc +protoc-install: + @rm -rf $(PROTOBUF_DIR) + @mkdir -p $(PROTOBUF_DIR) + @echo "⇒ Installing protoc... " + @wget -q -O $(PROTOBUF_DIR)/protoc-$(PROTOC_VERSION).zip 'https://github.com/protocolbuffers/protobuf/releases/download/v$(PROTOC_VERSION)/protoc-$(PROTOC_VERSION)-$(PROTOC_OS_VERSION).zip' + @unzip -q -o $(PROTOBUF_DIR)/protoc-$(PROTOC_VERSION).zip -d $(PROTOC_DIR) + @rm $(PROTOBUF_DIR)/protoc-$(PROTOC_VERSION).zip + @echo "⇒ Installing protoc-gen-go..." + @GOBIN=$(PROTOC_GEN_GO_DIR) go install -v google.golang.org/protobuf/...@$(PROTOC_GEN_GO_VERSION) + + +# Regenerate code for proto files +protoc: + @if [ ! -d "$(PROTOC_DIR)" ] || [ ! -d "$(PROTOC_GEN_GO_DIR)" ]; then \ + make protoc-install; \ + fi + # Protoc generate + @for f in `find . -type f -name '*.proto' -not -path './bin/*' -not -path './api/util/proto/test/*'`; do \ + echo "⇒ Processing $$f "; \ + $(PROTOC_DIR)/bin/protoc \ + --proto_path=.:$(PROTOC_DIR)/include:/usr/local/include \ + --plugin=protoc-gen-go-frostfs=$(abspath ./bin/protogen) \ + --go-frostfs_out=fuzz=true:. \ + --go-frostfs_opt=paths=source_relative \ + --go-grpc_opt=require_unimplemented_servers=false \ + --go-grpc_out=. --go-grpc_opt=paths=source_relative $$f; \ + done + +$(BIN)/protogen: + @go build -v -trimpath \ + -o $(BIN)/protogen \ + ./api/util/protogen + +protoc-test: protoc $(BIN)/protogen + @$(PROTOC_DIR)/bin/protoc \ + --go_out=. --go_opt=paths=source_relative \ + --plugin=protoc-gen-go-frostfs=$(abspath $(BIN)/protogen) \ + --go-frostfs_opt=Mapi/util/proto/test/test.proto=git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/util/proto/test/custom \ + --go-frostfs_opt=module=git.frostfs.info/TrueCloudLab/frostfs-sdk-go \ + --go-frostfs_out=. --go-frostfs_opt=paths=import \ + ./api/util/proto/test/test.proto + # Pull go dependencies dep: @printf "⇒ Download requirements: " diff --git a/accounting/decimal.go b/accounting/decimal.go index bb01f28..b6d7386 100644 --- a/accounting/decimal.go +++ b/accounting/decimal.go @@ -1,10 +1,10 @@ package accounting -import "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/accounting" +import "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/accounting" // Decimal represents decimal number for accounting operations. // -// Decimal is mutually compatible with git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/accounting.Decimal +// Decimal is mutually compatible with git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/accounting.Decimal // message. See ReadFromV2 / WriteToV2 methods. // // Instances can be created using built-in var declaration. diff --git a/accounting/decimal_test.go b/accounting/decimal_test.go index af46dd4..cdc6b69 100644 --- a/accounting/decimal_test.go +++ b/accounting/decimal_test.go @@ -3,8 +3,8 @@ package accounting_test import ( "testing" - v2accounting "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/accounting" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/accounting" + v2accounting "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/accounting" "github.com/stretchr/testify/require" ) diff --git a/accounting/doc.go b/accounting/doc.go index defcb0d..d5a9bfb 100644 --- a/accounting/doc.go +++ b/accounting/doc.go @@ -13,7 +13,7 @@ Instances can be also used to process FrostFS API V2 protocol messages On client side: - import "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/accounting" + import "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/accounting" var msg accounting.Decimal dec.WriteToV2(&msg) diff --git a/ape/chain.go b/ape/chain.go index eae441d..5a5548d 100644 --- a/ape/chain.go +++ b/ape/chain.go @@ -4,7 +4,7 @@ import ( "errors" "fmt" - apeV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/ape" + apeV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/ape" ) var ( diff --git a/ape/chain_target.go b/ape/chain_target.go index 13b7e87..cb63db7 100644 --- a/ape/chain_target.go +++ b/ape/chain_target.go @@ -1,7 +1,7 @@ package ape import ( - apeV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/ape" + apeV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/ape" ) // TargetType is an SDK representation for v2's TargetType. diff --git a/ape/chain_target_test.go b/ape/chain_target_test.go index 21a11b7..e7416d1 100644 --- a/ape/chain_target_test.go +++ b/ape/chain_target_test.go @@ -6,7 +6,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/ape" "github.com/stretchr/testify/require" - apeV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/ape" + apeV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/ape" ) var ( diff --git a/ape/chain_test.go b/ape/chain_test.go index 83991f6..4e47fc6 100644 --- a/ape/chain_test.go +++ b/ape/chain_test.go @@ -6,7 +6,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/ape" "github.com/stretchr/testify/require" - apeV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/ape" + apeV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/ape" ) const ( diff --git a/ape/grpc/types_frostfs.pb.go b/ape/grpc/types_frostfs.pb.go new file mode 100644 index 0000000000000000000000000000000000000000..c16e8673897c7071da1cb3c81841ec2663f0ef70 GIT binary patch literal 8595 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 literal 0 HcmV?d00001 diff --git a/ape/grpc/types_frostfs_fuzz.go b/ape/grpc/types_frostfs_fuzz.go new file mode 100644 index 0000000..b7bf367 --- /dev/null +++ b/ape/grpc/types_frostfs_fuzz.go @@ -0,0 +1,45 @@ +//go:build gofuzz +// +build gofuzz + +// Code generated by protoc-gen-go-frostfs. DO NOT EDIT. + +package ape + +func DoFuzzProtoChainTarget(data []byte) int { + msg := new(ChainTarget) + if err := msg.UnmarshalProtobuf(data); err != nil { + return 0 + } + _ = msg.MarshalProtobuf(nil) + return 1 +} +func DoFuzzJSONChainTarget(data []byte) int { + msg := new(ChainTarget) + if err := msg.UnmarshalJSON(data); err != nil { + return 0 + } + _, err := msg.MarshalJSON() + if err != nil { + panic(err) + } + return 1 +} +func DoFuzzProtoChain(data []byte) int { + msg := new(Chain) + if err := msg.UnmarshalProtobuf(data); err != nil { + return 0 + } + _ = msg.MarshalProtobuf(nil) + return 1 +} +func DoFuzzJSONChain(data []byte) int { + msg := new(Chain) + if err := msg.UnmarshalJSON(data); err != nil { + return 0 + } + _, err := msg.MarshalJSON() + if err != nil { + panic(err) + } + return 1 +} diff --git a/ape/grpc/types_frostfs_test.go b/ape/grpc/types_frostfs_test.go new file mode 100644 index 0000000..93d7eea --- /dev/null +++ b/ape/grpc/types_frostfs_test.go @@ -0,0 +1,31 @@ +//go:build gofuzz +// +build gofuzz + +// Code generated by protoc-gen-go-frostfs. DO NOT EDIT. + +package ape + +import ( + testing "testing" +) + +func FuzzProtoChainTarget(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzProtoChainTarget(data) + }) +} +func FuzzJSONChainTarget(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzJSONChainTarget(data) + }) +} +func FuzzProtoChain(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzProtoChain(data) + }) +} +func FuzzJSONChain(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzJSONChain(data) + }) +} diff --git a/api/accounting/accounting.go b/api/accounting/accounting.go new file mode 100644 index 0000000..04603cd --- /dev/null +++ b/api/accounting/accounting.go @@ -0,0 +1,104 @@ +package accounting + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" +) + +type BalanceRequestBody struct { + ownerID *refs.OwnerID +} + +type BalanceResponseBody struct { + bal *Decimal +} + +type Decimal struct { + val int64 + + prec uint32 +} + +type BalanceRequest struct { + body *BalanceRequestBody + + session.RequestHeaders +} + +type BalanceResponse struct { + body *BalanceResponseBody + + session.ResponseHeaders +} + +func (b *BalanceRequestBody) GetOwnerID() *refs.OwnerID { + if b != nil { + return b.ownerID + } + + return nil +} + +func (b *BalanceRequestBody) SetOwnerID(v *refs.OwnerID) { + b.ownerID = v +} + +func (b *BalanceRequest) GetBody() *BalanceRequestBody { + if b != nil { + return b.body + } + + return nil +} + +func (b *BalanceRequest) SetBody(v *BalanceRequestBody) { + b.body = v +} + +func (d *Decimal) GetValue() int64 { + if d != nil { + return d.val + } + + return 0 +} + +func (d *Decimal) SetValue(v int64) { + d.val = v +} + +func (d *Decimal) GetPrecision() uint32 { + if d != nil { + return d.prec + } + + return 0 +} + +func (d *Decimal) SetPrecision(v uint32) { + d.prec = v +} + +func (br *BalanceResponseBody) GetBalance() *Decimal { + if br != nil { + return br.bal + } + + return nil +} + +func (br *BalanceResponseBody) SetBalance(v *Decimal) { + br.bal = v +} + +func (br *BalanceResponse) GetBody() *BalanceResponseBody { + if br != nil { + return br.body + } + + return nil +} + +func (br *BalanceResponse) SetBody(v *BalanceResponseBody) { + br.body = v +} diff --git a/api/accounting/convert.go b/api/accounting/convert.go new file mode 100644 index 0000000..53b7491 --- /dev/null +++ b/api/accounting/convert.go @@ -0,0 +1,178 @@ +package accounting + +import ( + accounting "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/accounting/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" + refsGRPC "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/message" +) + +func (b *BalanceRequestBody) ToGRPCMessage() grpc.Message { + var m *accounting.BalanceRequest_Body + + if b != nil { + m = new(accounting.BalanceRequest_Body) + + m.SetOwnerId(b.ownerID.ToGRPCMessage().(*refsGRPC.OwnerID)) + } + + return m +} + +func (b *BalanceRequestBody) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*accounting.BalanceRequest_Body) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + ownerID := v.GetOwnerId() + if ownerID == nil { + b.ownerID = nil + } else { + if b.ownerID == nil { + b.ownerID = new(refs.OwnerID) + } + + err = b.ownerID.FromGRPCMessage(ownerID) + } + + return err +} + +func (b *BalanceRequest) ToGRPCMessage() grpc.Message { + var m *accounting.BalanceRequest + + if b != nil { + m = new(accounting.BalanceRequest) + + m.SetBody(b.body.ToGRPCMessage().(*accounting.BalanceRequest_Body)) + b.RequestHeaders.ToMessage(m) + } + + return m +} + +func (b *BalanceRequest) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*accounting.BalanceRequest) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + body := v.GetBody() + if body == nil { + b.body = nil + } else { + if b.body == nil { + b.body = new(BalanceRequestBody) + } + + err = b.body.FromGRPCMessage(body) + if err != nil { + return err + } + } + + return b.RequestHeaders.FromMessage(v) +} + +func (d *Decimal) ToGRPCMessage() grpc.Message { + var m *accounting.Decimal + + if d != nil { + m = new(accounting.Decimal) + + m.SetValue(d.val) + m.SetPrecision(d.prec) + } + + return m +} + +func (d *Decimal) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*accounting.Decimal) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + d.val = v.GetValue() + d.prec = v.GetPrecision() + + return nil +} + +func (br *BalanceResponseBody) ToGRPCMessage() grpc.Message { + var m *accounting.BalanceResponse_Body + + if br != nil { + m = new(accounting.BalanceResponse_Body) + + m.SetBalance(br.bal.ToGRPCMessage().(*accounting.Decimal)) + } + + return m +} + +func (br *BalanceResponseBody) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*accounting.BalanceResponse_Body) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + bal := v.GetBalance() + if bal == nil { + br.bal = nil + } else { + if br.bal == nil { + br.bal = new(Decimal) + } + + err = br.bal.FromGRPCMessage(bal) + } + + return err +} + +func (br *BalanceResponse) ToGRPCMessage() grpc.Message { + var m *accounting.BalanceResponse + + if br != nil { + m = new(accounting.BalanceResponse) + + m.SetBody(br.body.ToGRPCMessage().(*accounting.BalanceResponse_Body)) + br.ResponseHeaders.ToMessage(m) + } + + return m +} + +func (br *BalanceResponse) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*accounting.BalanceResponse) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + body := v.GetBody() + if body == nil { + br.body = nil + } else { + if br.body == nil { + br.body = new(BalanceResponseBody) + } + + err = br.body.FromGRPCMessage(body) + if err != nil { + return err + } + } + + return br.ResponseHeaders.FromMessage(v) +} diff --git a/api/accounting/grpc/service_frostfs.pb.go b/api/accounting/grpc/service_frostfs.pb.go new file mode 100644 index 0000000000000000000000000000000000000000..86502ef365180ca33406b23220db44436cfff1ad GIT binary patch literal 18911 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 BKuiDt literal 0 HcmV?d00001 diff --git a/api/accounting/grpc/types_frostfs_fuzz.go b/api/accounting/grpc/types_frostfs_fuzz.go new file mode 100644 index 0000000..5eb5e97 --- /dev/null +++ b/api/accounting/grpc/types_frostfs_fuzz.go @@ -0,0 +1,26 @@ +//go:build gofuzz +// +build gofuzz + +// Code generated by protoc-gen-go-frostfs. DO NOT EDIT. + +package accounting + +func DoFuzzProtoDecimal(data []byte) int { + msg := new(Decimal) + if err := msg.UnmarshalProtobuf(data); err != nil { + return 0 + } + _ = msg.MarshalProtobuf(nil) + return 1 +} +func DoFuzzJSONDecimal(data []byte) int { + msg := new(Decimal) + if err := msg.UnmarshalJSON(data); err != nil { + return 0 + } + _, err := msg.MarshalJSON() + if err != nil { + panic(err) + } + return 1 +} diff --git a/api/accounting/grpc/types_frostfs_test.go b/api/accounting/grpc/types_frostfs_test.go new file mode 100644 index 0000000..404b75e --- /dev/null +++ b/api/accounting/grpc/types_frostfs_test.go @@ -0,0 +1,21 @@ +//go:build gofuzz +// +build gofuzz + +// Code generated by protoc-gen-go-frostfs. DO NOT EDIT. + +package accounting + +import ( + testing "testing" +) + +func FuzzProtoDecimal(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzProtoDecimal(data) + }) +} +func FuzzJSONDecimal(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzJSONDecimal(data) + }) +} diff --git a/api/accounting/json.go b/api/accounting/json.go new file mode 100644 index 0000000..c5ff977 --- /dev/null +++ b/api/accounting/json.go @@ -0,0 +1,14 @@ +package accounting + +import ( + accounting "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/accounting/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/message" +) + +func (d *Decimal) MarshalJSON() ([]byte, error) { + return message.MarshalJSON(d) +} + +func (d *Decimal) UnmarshalJSON(data []byte) error { + return message.UnmarshalJSON(d, data, new(accounting.Decimal)) +} diff --git a/api/accounting/marshal.go b/api/accounting/marshal.go new file mode 100644 index 0000000..84771cc --- /dev/null +++ b/api/accounting/marshal.go @@ -0,0 +1,104 @@ +package accounting + +import ( + accounting "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/accounting/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/message" + protoutil "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/util/proto" +) + +const ( + decimalValueField = 1 + decimalPrecisionField = 2 + + balanceReqBodyOwnerField = 1 + + balanceRespBodyDecimalField = 1 +) + +func (d *Decimal) StableMarshal(buf []byte) []byte { + if d == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, d.StableSize()) + } + + var offset int + + offset += protoutil.Int64Marshal(decimalValueField, buf[offset:], d.val) + protoutil.UInt32Marshal(decimalPrecisionField, buf[offset:], d.prec) + + return buf +} + +func (d *Decimal) StableSize() (size int) { + if d == nil { + return 0 + } + + size += protoutil.Int64Size(decimalValueField, d.val) + size += protoutil.UInt32Size(decimalPrecisionField, d.prec) + + return size +} + +func (d *Decimal) Unmarshal(data []byte) error { + return message.Unmarshal(d, data, new(accounting.Decimal)) +} + +func (b *BalanceRequestBody) StableMarshal(buf []byte) []byte { + if b == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, b.StableSize()) + } + + protoutil.NestedStructureMarshal(balanceReqBodyOwnerField, buf, b.ownerID) + + return buf +} + +func (b *BalanceRequestBody) StableSize() (size int) { + if b == nil { + return 0 + } + + size = protoutil.NestedStructureSize(balanceReqBodyOwnerField, b.ownerID) + + return size +} + +func (b *BalanceRequestBody) Unmarshal(data []byte) error { + return message.Unmarshal(b, data, new(accounting.BalanceRequest_Body)) +} + +func (br *BalanceResponseBody) StableMarshal(buf []byte) []byte { + if br == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, br.StableSize()) + } + + protoutil.NestedStructureMarshal(balanceRespBodyDecimalField, buf, br.bal) + + return buf +} + +func (br *BalanceResponseBody) StableSize() (size int) { + if br == nil { + return 0 + } + + size = protoutil.NestedStructureSize(balanceRespBodyDecimalField, br.bal) + + return size +} + +func (br *BalanceResponseBody) Unmarshal(data []byte) error { + return message.Unmarshal(br, data, new(accounting.BalanceResponse_Body)) +} diff --git a/api/accounting/message_test.go b/api/accounting/message_test.go new file mode 100644 index 0000000..214c171 --- /dev/null +++ b/api/accounting/message_test.go @@ -0,0 +1,19 @@ +package accounting_test + +import ( + "testing" + + accountingtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/accounting/test" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/message" + messagetest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/message/test" +) + +func TestMessage(t *testing.T) { + messagetest.TestRPCMessage(t, + func(empty bool) message.Message { return accountingtest.GenerateDecimal(empty) }, + func(empty bool) message.Message { return accountingtest.GenerateBalanceRequestBody(empty) }, + func(empty bool) message.Message { return accountingtest.GenerateBalanceRequest(empty) }, + func(empty bool) message.Message { return accountingtest.GenerateBalanceResponseBody(empty) }, + func(empty bool) message.Message { return accountingtest.GenerateBalanceResponse(empty) }, + ) +} diff --git a/api/accounting/test/generate.go b/api/accounting/test/generate.go new file mode 100644 index 0000000..e9f45df --- /dev/null +++ b/api/accounting/test/generate.go @@ -0,0 +1,64 @@ +package accountingtest + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/accounting" + accountingtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs/test" + sessiontest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session/test" +) + +func GenerateBalanceRequest(empty bool) *accounting.BalanceRequest { + m := new(accounting.BalanceRequest) + + if !empty { + m.SetBody(GenerateBalanceRequestBody(false)) + } + + m.SetMetaHeader(sessiontest.GenerateRequestMetaHeader(empty)) + m.SetVerificationHeader(sessiontest.GenerateRequestVerificationHeader(empty)) + + return m +} + +func GenerateBalanceRequestBody(empty bool) *accounting.BalanceRequestBody { + m := new(accounting.BalanceRequestBody) + + if !empty { + m.SetOwnerID(accountingtest.GenerateOwnerID(false)) + } + + return m +} + +func GenerateBalanceResponse(empty bool) *accounting.BalanceResponse { + m := new(accounting.BalanceResponse) + + if !empty { + m.SetBody(GenerateBalanceResponseBody(false)) + } + + m.SetMetaHeader(sessiontest.GenerateResponseMetaHeader(empty)) + m.SetVerificationHeader(sessiontest.GenerateResponseVerificationHeader(empty)) + + return m +} + +func GenerateBalanceResponseBody(empty bool) *accounting.BalanceResponseBody { + m := new(accounting.BalanceResponseBody) + + if !empty { + m.SetBalance(GenerateDecimal(false)) + } + + return m +} + +func GenerateDecimal(empty bool) *accounting.Decimal { + m := new(accounting.Decimal) + + if !empty { + m.SetValue(1) + m.SetPrecision(2) + } + + return m +} diff --git a/api/acl/bench_test.go b/api/acl/bench_test.go new file mode 100644 index 0000000..200270c --- /dev/null +++ b/api/acl/bench_test.go @@ -0,0 +1,51 @@ +package acl_test + +import ( + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/acl" + aclGrpc "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/acl/grpc" + acltest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/acl/test" +) + +func BenchmarkTable_ToGRPCMessage(b *testing.B) { + const size = 4 + + tb := new(acl.Table) + rs := make([]acl.Record, size) + for i := range rs { + fs := make([]acl.HeaderFilter, size) + for j := range fs { + fs[j] = *acltest.GenerateFilter(false) + } + ts := make([]acl.Target, size) + for j := range ts { + ts[j] = *acltest.GenerateTarget(false) + } + + rs[i].SetFilters(fs) + rs[i].SetTargets(ts) + } + tb.SetRecords(rs) + + raw := tb.ToGRPCMessage() + + b.Run("to grpc message", func(b *testing.B) { + b.ReportAllocs() + for range b.N { + raw := tb.ToGRPCMessage() + if len(tb.GetRecords()) != len(raw.(*aclGrpc.EACLTable).Records) { + b.FailNow() + } + } + }) + b.Run("from grpc message", func(b *testing.B) { + b.ReportAllocs() + for range b.N { + tb := new(acl.Table) + if tb.FromGRPCMessage(raw) != nil { + b.FailNow() + } + } + }) +} diff --git a/api/acl/convert.go b/api/acl/convert.go new file mode 100644 index 0000000..3f389e3 --- /dev/null +++ b/api/acl/convert.go @@ -0,0 +1,592 @@ +package acl + +import ( + acl "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/acl/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/ape" + apeGRPC "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/ape/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" + refsGRPC "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/message" +) + +// RoleToGRPCField converts unified role enum into grpc enum. +func RoleToGRPCField(t Role) acl.Role { + switch t { + case RoleUser: + return acl.Role_USER + case RoleSystem: + return acl.Role_SYSTEM + case RoleOthers: + return acl.Role_OTHERS + default: + return acl.Role_ROLE_UNSPECIFIED + } +} + +// RoleFromGRPCField converts grpc enum into unified role enum. +func RoleFromGRPCField(t acl.Role) Role { + switch t { + case acl.Role_USER: + return RoleUser + case acl.Role_SYSTEM: + return RoleSystem + case acl.Role_OTHERS: + return RoleOthers + default: + return RoleUnknown + } +} + +// OperationToGRPCField converts unified operation enum into grpc enum. +func OperationToGRPCField(t Operation) acl.Operation { + switch t { + case OperationPut: + return acl.Operation_PUT + case OperationDelete: + return acl.Operation_DELETE + case OperationGet: + return acl.Operation_GET + case OperationHead: + return acl.Operation_HEAD + case OperationSearch: + return acl.Operation_SEARCH + case OperationRange: + return acl.Operation_GETRANGE + case OperationRangeHash: + return acl.Operation_GETRANGEHASH + default: + return acl.Operation_OPERATION_UNSPECIFIED + } +} + +// OperationFromGRPCField converts grpc enum into unified operation enum. +func OperationFromGRPCField(t acl.Operation) Operation { + switch t { + case acl.Operation_PUT: + return OperationPut + case acl.Operation_DELETE: + return OperationDelete + case acl.Operation_GET: + return OperationGet + case acl.Operation_HEAD: + return OperationHead + case acl.Operation_SEARCH: + return OperationSearch + case acl.Operation_GETRANGE: + return OperationRange + case acl.Operation_GETRANGEHASH: + return OperationRangeHash + default: + return OperationUnknown + } +} + +// ActionToGRPCField converts unified action enum into grpc enum. +func ActionToGRPCField(t Action) acl.Action { + switch t { + case ActionDeny: + return acl.Action_DENY + case ActionAllow: + return acl.Action_ALLOW + default: + return acl.Action_ACTION_UNSPECIFIED + } +} + +// ActionFromGRPCField converts grpc enum into unified action enum. +func ActionFromGRPCField(t acl.Action) Action { + switch t { + case acl.Action_DENY: + return ActionDeny + case acl.Action_ALLOW: + return ActionAllow + default: + return ActionUnknown + } +} + +// HeaderTypeToGRPCField converts unified header type enum into grpc enum. +func HeaderTypeToGRPCField(t HeaderType) acl.HeaderType { + switch t { + case HeaderTypeRequest: + return acl.HeaderType_REQUEST + case HeaderTypeObject: + return acl.HeaderType_OBJECT + case HeaderTypeService: + return acl.HeaderType_SERVICE + default: + return acl.HeaderType_HEADER_UNSPECIFIED + } +} + +// HeaderTypeFromGRPCField converts grpc enum into unified header type enum. +func HeaderTypeFromGRPCField(t acl.HeaderType) HeaderType { + switch t { + case acl.HeaderType_REQUEST: + return HeaderTypeRequest + case acl.HeaderType_OBJECT: + return HeaderTypeObject + case acl.HeaderType_SERVICE: + return HeaderTypeService + default: + return HeaderTypeUnknown + } +} + +// MatchTypeToGRPCField converts unified match type enum into grpc enum. +func MatchTypeToGRPCField(t MatchType) acl.MatchType { + switch t { + case MatchTypeStringEqual: + return acl.MatchType_STRING_EQUAL + case MatchTypeStringNotEqual: + return acl.MatchType_STRING_NOT_EQUAL + default: + return acl.MatchType_MATCH_TYPE_UNSPECIFIED + } +} + +// MatchTypeFromGRPCField converts grpc enum into unified match type enum. +func MatchTypeFromGRPCField(t acl.MatchType) MatchType { + switch t { + case acl.MatchType_STRING_EQUAL: + return MatchTypeStringEqual + case acl.MatchType_STRING_NOT_EQUAL: + return MatchTypeStringNotEqual + default: + return MatchTypeUnknown + } +} + +func (f *HeaderFilter) ToGRPCMessage() grpc.Message { + var m *acl.EACLRecord_Filter + + if f != nil { + m = new(acl.EACLRecord_Filter) + + m.SetKey(f.key) + m.SetValue(f.value) + m.SetHeaderType(HeaderTypeToGRPCField(f.hdrType)) + m.SetMatchType(MatchTypeToGRPCField(f.matchType)) + } + + return m +} + +func (f *HeaderFilter) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*acl.EACLRecord_Filter) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + f.key = v.GetKey() + f.value = v.GetValue() + f.hdrType = HeaderTypeFromGRPCField(v.GetHeaderType()) + f.matchType = MatchTypeFromGRPCField(v.GetMatchType()) + + return nil +} + +func HeaderFiltersToGRPC(fs []HeaderFilter) (res []acl.EACLRecord_Filter) { + if fs != nil { + res = make([]acl.EACLRecord_Filter, 0, len(fs)) + + for i := range fs { + res = append(res, *fs[i].ToGRPCMessage().(*acl.EACLRecord_Filter)) + } + } + + return +} + +func HeaderFiltersFromGRPC(fs []acl.EACLRecord_Filter) (res []HeaderFilter, err error) { + if fs != nil { + res = make([]HeaderFilter, len(fs)) + + for i := range fs { + err = res[i].FromGRPCMessage(&fs[i]) + if err != nil { + return + } + } + } + + return +} + +func (t *Target) ToGRPCMessage() grpc.Message { + var m *acl.EACLRecord_Target + + if t != nil { + m = new(acl.EACLRecord_Target) + + m.SetRole(RoleToGRPCField(t.role)) + m.SetKeys(t.keys) + } + + return m +} + +func (t *Target) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*acl.EACLRecord_Target) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + t.role = RoleFromGRPCField(v.GetRole()) + t.keys = v.GetKeys() + + return nil +} + +func TargetsToGRPC(ts []Target) (res []acl.EACLRecord_Target) { + if ts != nil { + res = make([]acl.EACLRecord_Target, 0, len(ts)) + + for i := range ts { + res = append(res, *ts[i].ToGRPCMessage().(*acl.EACLRecord_Target)) + } + } + + return +} + +func TargetsFromGRPC(fs []acl.EACLRecord_Target) (res []Target, err error) { + if fs != nil { + res = make([]Target, len(fs)) + + for i := range fs { + err = res[i].FromGRPCMessage(&fs[i]) + if err != nil { + return + } + } + } + + return +} + +func (r *Record) ToGRPCMessage() grpc.Message { + var m *acl.EACLRecord + + if r != nil { + m = new(acl.EACLRecord) + + m.SetOperation(OperationToGRPCField(r.op)) + m.SetAction(ActionToGRPCField(r.action)) + m.SetFilters(HeaderFiltersToGRPC(r.filters)) + m.SetTargets(TargetsToGRPC(r.targets)) + } + + return m +} + +func (r *Record) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*acl.EACLRecord) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + r.filters, err = HeaderFiltersFromGRPC(v.GetFilters()) + if err != nil { + return err + } + + r.targets, err = TargetsFromGRPC(v.GetTargets()) + if err != nil { + return err + } + + r.op = OperationFromGRPCField(v.GetOperation()) + r.action = ActionFromGRPCField(v.GetAction()) + + return nil +} + +func RecordsToGRPC(ts []Record) (res []acl.EACLRecord) { + if ts != nil { + res = make([]acl.EACLRecord, 0, len(ts)) + + for i := range ts { + res = append(res, *ts[i].ToGRPCMessage().(*acl.EACLRecord)) + } + } + + return +} + +func RecordsFromGRPC(fs []acl.EACLRecord) (res []Record, err error) { + if fs != nil { + res = make([]Record, len(fs)) + + for i := range fs { + err = res[i].FromGRPCMessage(&fs[i]) + if err != nil { + return + } + } + } + + return +} + +func (t *Table) ToGRPCMessage() grpc.Message { + var m *acl.EACLTable + + if t != nil { + m = new(acl.EACLTable) + + m.SetVersion(t.version.ToGRPCMessage().(*refsGRPC.Version)) + m.SetContainerId(t.cid.ToGRPCMessage().(*refsGRPC.ContainerID)) + m.SetRecords(RecordsToGRPC(t.records)) + } + + return m +} + +func (t *Table) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*acl.EACLTable) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + cid := v.GetContainerId() + if cid == nil { + t.cid = nil + } else { + if t.cid == nil { + t.cid = new(refs.ContainerID) + } + + err = t.cid.FromGRPCMessage(cid) + if err != nil { + return err + } + } + + version := v.GetVersion() + if version == nil { + t.version = nil + } else { + if t.version == nil { + t.version = new(refs.Version) + } + + err = t.version.FromGRPCMessage(version) + if err != nil { + return err + } + } + + t.records, err = RecordsFromGRPC(v.GetRecords()) + + return err +} + +func (l *TokenLifetime) ToGRPCMessage() grpc.Message { + var m *acl.BearerToken_Body_TokenLifetime + + if l != nil { + m = new(acl.BearerToken_Body_TokenLifetime) + + m.SetExp(l.exp) + m.SetIat(l.iat) + m.SetNbf(l.nbf) + } + + return m +} + +func (l *TokenLifetime) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*acl.BearerToken_Body_TokenLifetime) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + l.exp = v.GetExp() + l.iat = v.GetIat() + l.nbf = v.GetNbf() + + return nil +} + +func (c *APEOverride) ToGRPCMessage() grpc.Message { + var m *acl.BearerToken_Body_APEOverride + + if c != nil { + m = new(acl.BearerToken_Body_APEOverride) + + m.SetTarget(c.target.ToGRPCMessage().(*apeGRPC.ChainTarget)) + + if len(c.chains) > 0 { + apeChains := make([]apeGRPC.Chain, len(c.chains)) + for i := range c.chains { + apeChains[i] = *c.chains[i].ToGRPCMessage().(*apeGRPC.Chain) + } + m.SetChains(apeChains) + } + } + + return m +} + +func (c *APEOverride) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*acl.BearerToken_Body_APEOverride) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + if targetGRPC := v.GetTarget(); targetGRPC != nil { + if c.target == nil { + c.target = new(ape.ChainTarget) + } + if err := c.target.FromGRPCMessage(v.GetTarget()); err != nil { + return err + } + } + + if apeChains := v.GetChains(); len(apeChains) > 0 { + c.chains = make([]*ape.Chain, len(apeChains)) + for i := range apeChains { + c.chains[i] = new(ape.Chain) + if err := c.chains[i].FromGRPCMessage(&apeChains[i]); err != nil { + return err + } + } + } + + return nil +} + +func (bt *BearerTokenBody) ToGRPCMessage() grpc.Message { + var m *acl.BearerToken_Body + + if bt != nil { + m = new(acl.BearerToken_Body) + + m.SetOwnerId(bt.ownerID.ToGRPCMessage().(*refsGRPC.OwnerID)) + m.SetLifetime(bt.lifetime.ToGRPCMessage().(*acl.BearerToken_Body_TokenLifetime)) + m.SetEaclTable(bt.eacl.ToGRPCMessage().(*acl.EACLTable)) + m.SetAllowImpersonate(bt.impersonate) + m.SetApeOverride(bt.apeOverride.ToGRPCMessage().(*acl.BearerToken_Body_APEOverride)) + } + + return m +} + +func (bt *BearerTokenBody) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*acl.BearerToken_Body) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + ownerID := v.GetOwnerId() + if ownerID == nil { + bt.ownerID = nil + } else { + if bt.ownerID == nil { + bt.ownerID = new(refs.OwnerID) + } + + err = bt.ownerID.FromGRPCMessage(ownerID) + if err != nil { + return err + } + } + + lifetime := v.GetLifetime() + if lifetime == nil { + bt.lifetime = nil + } else { + if bt.lifetime == nil { + bt.lifetime = new(TokenLifetime) + } + + err = bt.lifetime.FromGRPCMessage(lifetime) + if err != nil { + return err + } + } + + eacl := v.GetEaclTable() + if eacl == nil { + bt.eacl = nil + } else { + if bt.eacl == nil { + bt.eacl = new(Table) + } + + if err = bt.eacl.FromGRPCMessage(eacl); err != nil { + return err + } + } + + if apeOverrideGRPC := v.GetApeOverride(); apeOverrideGRPC != nil { + if bt.apeOverride == nil { + bt.apeOverride = new(APEOverride) + } + err = bt.apeOverride.FromGRPCMessage(apeOverrideGRPC) + if err != nil { + return err + } + } + + bt.impersonate = v.GetAllowImpersonate() + + return err +} + +func (bt *BearerToken) ToGRPCMessage() grpc.Message { + var m *acl.BearerToken + + if bt != nil { + m = new(acl.BearerToken) + + m.SetBody(bt.body.ToGRPCMessage().(*acl.BearerToken_Body)) + m.SetSignature(bt.sig.ToGRPCMessage().(*refsGRPC.Signature)) + } + + return m +} + +func (bt *BearerToken) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*acl.BearerToken) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + body := v.GetBody() + if body == nil { + bt.body = nil + } else { + if bt.body == nil { + bt.body = new(BearerTokenBody) + } + + err = bt.body.FromGRPCMessage(body) + if err != nil { + return err + } + } + + sig := v.GetSignature() + if sig == nil { + bt.sig = nil + } else { + if bt.sig == nil { + bt.sig = new(refs.Signature) + } + + err = bt.sig.FromGRPCMessage(sig) + } + + return err +} diff --git a/api/acl/filters.go b/api/acl/filters.go new file mode 100644 index 0000000..c1d8afe --- /dev/null +++ b/api/acl/filters.go @@ -0,0 +1,33 @@ +package acl + +// ObjectFilterPrefix is a prefix of key to object header value or property. +const ObjectFilterPrefix = "$Object:" + +const ( + // FilterObjectVersion is a filter key to "version" field of the object header. + FilterObjectVersion = ObjectFilterPrefix + "version" + + // FilterObjectID is a filter key to "object_id" field of the object. + FilterObjectID = ObjectFilterPrefix + "objectID" + + // FilterObjectContainerID is a filter key to "container_id" field of the object header. + FilterObjectContainerID = ObjectFilterPrefix + "containerID" + + // FilterObjectOwnerID is a filter key to "owner_id" field of the object header. + FilterObjectOwnerID = ObjectFilterPrefix + "ownerID" + + // FilterObjectCreationEpoch is a filter key to "creation_epoch" field of the object header. + FilterObjectCreationEpoch = ObjectFilterPrefix + "creationEpoch" + + // FilterObjectPayloadLength is a filter key to "payload_length" field of the object header. + FilterObjectPayloadLength = ObjectFilterPrefix + "payloadLength" + + // FilterObjectPayloadHash is a filter key to "payload_hash" field of the object header. + FilterObjectPayloadHash = ObjectFilterPrefix + "payloadHash" + + // FilterObjectType is a filter key to "object_type" field of the object header. + FilterObjectType = ObjectFilterPrefix + "objectType" + + // FilterObjectHomomorphicHash is a filter key to "homomorphic_hash" field of the object header. + FilterObjectHomomorphicHash = ObjectFilterPrefix + "homomorphicHash" +) diff --git a/api/acl/grpc/types_frostfs.pb.go b/api/acl/grpc/types_frostfs.pb.go new file mode 100644 index 0000000000000000000000000000000000000000..76e460dc0c7c890feb390adc3320f3c21fbfff80 GIT binary patch literal 48052 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 VA;}|Kf~R@7jkQ6HozW#={}0mjby5HT literal 0 HcmV?d00001 diff --git a/api/acl/grpc/types_frostfs_fuzz.go b/api/acl/grpc/types_frostfs_fuzz.go new file mode 100644 index 0000000..5d5b763 --- /dev/null +++ b/api/acl/grpc/types_frostfs_fuzz.go @@ -0,0 +1,64 @@ +//go:build gofuzz +// +build gofuzz + +// Code generated by protoc-gen-go-frostfs. DO NOT EDIT. + +package acl + +func DoFuzzProtoEACLRecord(data []byte) int { + msg := new(EACLRecord) + if err := msg.UnmarshalProtobuf(data); err != nil { + return 0 + } + _ = msg.MarshalProtobuf(nil) + return 1 +} +func DoFuzzJSONEACLRecord(data []byte) int { + msg := new(EACLRecord) + if err := msg.UnmarshalJSON(data); err != nil { + return 0 + } + _, err := msg.MarshalJSON() + if err != nil { + panic(err) + } + return 1 +} +func DoFuzzProtoEACLTable(data []byte) int { + msg := new(EACLTable) + if err := msg.UnmarshalProtobuf(data); err != nil { + return 0 + } + _ = msg.MarshalProtobuf(nil) + return 1 +} +func DoFuzzJSONEACLTable(data []byte) int { + msg := new(EACLTable) + if err := msg.UnmarshalJSON(data); err != nil { + return 0 + } + _, err := msg.MarshalJSON() + if err != nil { + panic(err) + } + return 1 +} +func DoFuzzProtoBearerToken(data []byte) int { + msg := new(BearerToken) + if err := msg.UnmarshalProtobuf(data); err != nil { + return 0 + } + _ = msg.MarshalProtobuf(nil) + return 1 +} +func DoFuzzJSONBearerToken(data []byte) int { + msg := new(BearerToken) + if err := msg.UnmarshalJSON(data); err != nil { + return 0 + } + _, err := msg.MarshalJSON() + if err != nil { + panic(err) + } + return 1 +} diff --git a/api/acl/grpc/types_frostfs_test.go b/api/acl/grpc/types_frostfs_test.go new file mode 100644 index 0000000..c6d1c43 --- /dev/null +++ b/api/acl/grpc/types_frostfs_test.go @@ -0,0 +1,41 @@ +//go:build gofuzz +// +build gofuzz + +// Code generated by protoc-gen-go-frostfs. DO NOT EDIT. + +package acl + +import ( + testing "testing" +) + +func FuzzProtoEACLRecord(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzProtoEACLRecord(data) + }) +} +func FuzzJSONEACLRecord(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzJSONEACLRecord(data) + }) +} +func FuzzProtoEACLTable(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzProtoEACLTable(data) + }) +} +func FuzzJSONEACLTable(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzJSONEACLTable(data) + }) +} +func FuzzProtoBearerToken(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzProtoBearerToken(data) + }) +} +func FuzzJSONBearerToken(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzJSONBearerToken(data) + }) +} diff --git a/api/acl/json.go b/api/acl/json.go new file mode 100644 index 0000000..9192956 --- /dev/null +++ b/api/acl/json.go @@ -0,0 +1,70 @@ +package acl + +import ( + acl "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/acl/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/message" +) + +func (f *HeaderFilter) MarshalJSON() ([]byte, error) { + return message.MarshalJSON(f) +} + +func (f *HeaderFilter) UnmarshalJSON(data []byte) error { + return message.UnmarshalJSON(f, data, new(acl.EACLRecord_Filter)) +} + +func (t *Target) MarshalJSON() ([]byte, error) { + return message.MarshalJSON(t) +} + +func (t *Target) UnmarshalJSON(data []byte) error { + return message.UnmarshalJSON(t, data, new(acl.EACLRecord_Target)) +} + +func (a *APEOverride) MarshalJSON() ([]byte, error) { + return message.MarshalJSON(a) +} + +func (a *APEOverride) UnmarshalJSON(data []byte) error { + return message.UnmarshalJSON(a, data, new(acl.BearerToken_Body_APEOverride)) +} + +func (r *Record) MarshalJSON() ([]byte, error) { + return message.MarshalJSON(r) +} + +func (r *Record) UnmarshalJSON(data []byte) error { + return message.UnmarshalJSON(r, data, new(acl.EACLRecord)) +} + +func (t *Table) MarshalJSON() ([]byte, error) { + return message.MarshalJSON(t) +} + +func (t *Table) UnmarshalJSON(data []byte) error { + return message.UnmarshalJSON(t, data, new(acl.EACLTable)) +} + +func (l *TokenLifetime) MarshalJSON() ([]byte, error) { + return message.MarshalJSON(l) +} + +func (l *TokenLifetime) UnmarshalJSON(data []byte) error { + return message.UnmarshalJSON(l, data, new(acl.BearerToken_Body_TokenLifetime)) +} + +func (bt *BearerTokenBody) MarshalJSON() ([]byte, error) { + return message.MarshalJSON(bt) +} + +func (bt *BearerTokenBody) UnmarshalJSON(data []byte) error { + return message.UnmarshalJSON(bt, data, new(acl.BearerToken_Body)) +} + +func (bt *BearerToken) MarshalJSON() ([]byte, error) { + return message.MarshalJSON(bt) +} + +func (bt *BearerToken) UnmarshalJSON(data []byte) error { + return message.UnmarshalJSON(bt, data, new(acl.BearerToken)) +} diff --git a/api/acl/marshal.go b/api/acl/marshal.go new file mode 100644 index 0000000..29bfa06 --- /dev/null +++ b/api/acl/marshal.go @@ -0,0 +1,350 @@ +package acl + +import ( + acl "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/acl/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/message" + protoutil "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/util/proto" +) + +const ( + filterHeaderTypeField = 1 + filterMatchTypeField = 2 + filterNameField = 3 + filterValueField = 4 + + targetTypeField = 1 + targetKeysField = 2 + + recordOperationField = 1 + recordActionField = 2 + recordFiltersField = 3 + recordTargetsField = 4 + + tableVersionField = 1 + tableContainerIDField = 2 + tableRecordsField = 3 + + lifetimeExpirationField = 1 + lifetimeNotValidBeforeField = 2 + lifetimeIssuedAtField = 3 + + tokenAPEChainsTargetField = 1 + tokenAPEChainsChainsField = 2 + + bearerTokenBodyACLField = 1 + bearerTokenBodyOwnerField = 2 + bearerTokenBodyLifetimeField = 3 + bearerTokenBodyImpersonate = 4 + bearerTokenTokenAPEChainsField = 5 + + bearerTokenBodyField = 1 + bearerTokenSignatureField = 2 +) + +// StableMarshal marshals unified acl table structure in a protobuf +// compatible way without field order shuffle. +func (t *Table) StableMarshal(buf []byte) []byte { + if t == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, t.StableSize()) + } + + var offset int + + offset += protoutil.NestedStructureMarshal(tableVersionField, buf[offset:], t.version) + offset += protoutil.NestedStructureMarshal(tableContainerIDField, buf[offset:], t.cid) + + for i := range t.records { + offset += protoutil.NestedStructureMarshal(tableRecordsField, buf[offset:], &t.records[i]) + } + + return buf +} + +// StableSize of acl table structure marshalled by StableMarshal function. +func (t *Table) StableSize() (size int) { + if t == nil { + return 0 + } + + size += protoutil.NestedStructureSize(tableVersionField, t.version) + size += protoutil.NestedStructureSize(tableContainerIDField, t.cid) + + for i := range t.records { + size += protoutil.NestedStructureSize(tableRecordsField, &t.records[i]) + } + + return size +} + +func (t *Table) Unmarshal(data []byte) error { + return message.Unmarshal(t, data, new(acl.EACLTable)) +} + +// StableMarshal marshals unified acl record structure in a protobuf +// compatible way without field order shuffle. +func (r *Record) StableMarshal(buf []byte) []byte { + if r == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, r.StableSize()) + } + + var offset int + + offset += protoutil.EnumMarshal(recordOperationField, buf[offset:], int32(r.op)) + offset += protoutil.EnumMarshal(recordActionField, buf[offset:], int32(r.action)) + + for i := range r.filters { + offset += protoutil.NestedStructureMarshal(recordFiltersField, buf[offset:], &r.filters[i]) + } + + for i := range r.targets { + offset += protoutil.NestedStructureMarshal(recordTargetsField, buf[offset:], &r.targets[i]) + } + + return buf +} + +// StableSize of acl record structure marshalled by StableMarshal function. +func (r *Record) StableSize() (size int) { + if r == nil { + return 0 + } + + size += protoutil.EnumSize(recordOperationField, int32(r.op)) + size += protoutil.EnumSize(recordActionField, int32(r.action)) + + for i := range r.filters { + size += protoutil.NestedStructureSize(recordFiltersField, &r.filters[i]) + } + + for i := range r.targets { + size += protoutil.NestedStructureSize(recordTargetsField, &r.targets[i]) + } + + return size +} + +func (r *Record) Unmarshal(data []byte) error { + return message.Unmarshal(r, data, new(acl.EACLRecord)) +} + +// StableMarshal marshals unified header filter structure in a protobuf +// compatible way without field order shuffle. +func (f *HeaderFilter) StableMarshal(buf []byte) []byte { + if f == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, f.StableSize()) + } + + var offset int + + offset += protoutil.EnumMarshal(filterHeaderTypeField, buf[offset:], int32(f.hdrType)) + offset += protoutil.EnumMarshal(filterMatchTypeField, buf[offset:], int32(f.matchType)) + offset += protoutil.StringMarshal(filterNameField, buf[offset:], f.key) + protoutil.StringMarshal(filterValueField, buf[offset:], f.value) + + return buf +} + +// StableSize of header filter structure marshalled by StableMarshal function. +func (f *HeaderFilter) StableSize() (size int) { + if f == nil { + return 0 + } + + size += protoutil.EnumSize(filterHeaderTypeField, int32(f.hdrType)) + size += protoutil.EnumSize(filterMatchTypeField, int32(f.matchType)) + size += protoutil.StringSize(filterNameField, f.key) + size += protoutil.StringSize(filterValueField, f.value) + + return size +} + +func (f *HeaderFilter) Unmarshal(data []byte) error { + return message.Unmarshal(f, data, new(acl.EACLRecord_Filter)) +} + +// StableMarshal marshals unified role info structure in a protobuf +// compatible way without field order shuffle. +func (t *Target) StableMarshal(buf []byte) []byte { + if t == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, t.StableSize()) + } + + var offset int + + offset += protoutil.EnumMarshal(targetTypeField, buf[offset:], int32(t.role)) + protoutil.RepeatedBytesMarshal(targetKeysField, buf[offset:], t.keys) + + return buf +} + +// StableSize of role info structure marshalled by StableMarshal function. +func (t *Target) StableSize() (size int) { + if t == nil { + return 0 + } + + size += protoutil.EnumSize(targetTypeField, int32(t.role)) + size += protoutil.RepeatedBytesSize(targetKeysField, t.keys) + + return size +} + +func (t *Target) Unmarshal(data []byte) error { + return message.Unmarshal(t, data, new(acl.EACLRecord_Target)) +} + +func (l *TokenLifetime) StableMarshal(buf []byte) []byte { + if l == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, l.StableSize()) + } + + var offset int + + offset += protoutil.UInt64Marshal(lifetimeExpirationField, buf[offset:], l.exp) + offset += protoutil.UInt64Marshal(lifetimeNotValidBeforeField, buf[offset:], l.nbf) + protoutil.UInt64Marshal(lifetimeIssuedAtField, buf[offset:], l.iat) + + return buf +} + +func (l *TokenLifetime) StableSize() (size int) { + if l == nil { + return 0 + } + + size += protoutil.UInt64Size(lifetimeExpirationField, l.exp) + size += protoutil.UInt64Size(lifetimeNotValidBeforeField, l.nbf) + size += protoutil.UInt64Size(lifetimeIssuedAtField, l.iat) + + return size +} + +func (l *TokenLifetime) Unmarshal(data []byte) error { + return message.Unmarshal(l, data, new(acl.BearerToken_Body_TokenLifetime)) +} + +func (c *APEOverride) StableMarshal(buf []byte) []byte { + if c == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, c.StableSize()) + } + + var offset int + + offset += protoutil.NestedStructureMarshal(tokenAPEChainsTargetField, buf[offset:], c.target) + for i := range c.chains { + offset += protoutil.NestedStructureMarshal(tokenAPEChainsChainsField, buf[offset:], c.chains[i]) + } + + return buf +} + +func (c *APEOverride) StableSize() (size int) { + if c == nil { + return 0 + } + + size += protoutil.NestedStructureSize(tokenAPEChainsTargetField, c.target) + for i := range c.chains { + size += protoutil.NestedStructureSize(tokenAPEChainsChainsField, c.chains[i]) + } + + return size +} + +func (c *APEOverride) Unmarshal(data []byte) error { + return message.Unmarshal(c, data, new(acl.BearerToken_Body_APEOverride)) +} + +func (bt *BearerTokenBody) StableMarshal(buf []byte) []byte { + if bt == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, bt.StableSize()) + } + + var offset int + + offset += protoutil.NestedStructureMarshal(bearerTokenBodyACLField, buf[offset:], bt.eacl) + offset += protoutil.NestedStructureMarshal(bearerTokenBodyOwnerField, buf[offset:], bt.ownerID) + offset += protoutil.NestedStructureMarshal(bearerTokenBodyLifetimeField, buf[offset:], bt.lifetime) + offset += protoutil.BoolMarshal(bearerTokenBodyImpersonate, buf[offset:], bt.impersonate) + protoutil.NestedStructureMarshal(bearerTokenTokenAPEChainsField, buf[offset:], bt.apeOverride) + + return buf +} + +func (bt *BearerTokenBody) StableSize() (size int) { + if bt == nil { + return 0 + } + + size += protoutil.NestedStructureSize(bearerTokenBodyACLField, bt.eacl) + size += protoutil.NestedStructureSize(bearerTokenBodyOwnerField, bt.ownerID) + size += protoutil.NestedStructureSize(bearerTokenBodyLifetimeField, bt.lifetime) + size += protoutil.BoolSize(bearerTokenBodyImpersonate, bt.impersonate) + size += protoutil.NestedStructureSize(bearerTokenTokenAPEChainsField, bt.apeOverride) + + return size +} + +func (bt *BearerTokenBody) Unmarshal(data []byte) error { + return message.Unmarshal(bt, data, new(acl.BearerToken_Body)) +} + +func (bt *BearerToken) StableMarshal(buf []byte) []byte { + if bt == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, bt.StableSize()) + } + + var offset int + + offset += protoutil.NestedStructureMarshal(bearerTokenBodyField, buf[offset:], bt.body) + protoutil.NestedStructureMarshal(bearerTokenSignatureField, buf[offset:], bt.sig) + + return buf +} + +func (bt *BearerToken) StableSize() (size int) { + if bt == nil { + return 0 + } + + size += protoutil.NestedStructureSize(bearerTokenBodyField, bt.body) + size += protoutil.NestedStructureSize(bearerTokenSignatureField, bt.sig) + + return size +} + +func (bt *BearerToken) Unmarshal(data []byte) error { + return message.Unmarshal(bt, data, new(acl.BearerToken)) +} diff --git a/api/acl/message_test.go b/api/acl/message_test.go new file mode 100644 index 0000000..0131137 --- /dev/null +++ b/api/acl/message_test.go @@ -0,0 +1,21 @@ +package acl_test + +import ( + "testing" + + acltest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/acl/test" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/message" + messagetest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/message/test" +) + +func TestMessageConvert(t *testing.T) { + messagetest.TestRPCMessage(t, + func(empty bool) message.Message { return acltest.GenerateFilter(empty) }, + func(empty bool) message.Message { return acltest.GenerateTarget(empty) }, + func(empty bool) message.Message { return acltest.GenerateRecord(empty) }, + func(empty bool) message.Message { return acltest.GenerateTable(empty) }, + func(empty bool) message.Message { return acltest.GenerateTokenLifetime(empty) }, + func(empty bool) message.Message { return acltest.GenerateBearerTokenBody(empty) }, + func(empty bool) message.Message { return acltest.GenerateBearerToken(empty) }, + ) +} diff --git a/api/acl/string.go b/api/acl/string.go new file mode 100644 index 0000000..e5a4462 --- /dev/null +++ b/api/acl/string.go @@ -0,0 +1,110 @@ +package acl + +import ( + acl "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/acl/grpc" +) + +// String returns string representation of Action. +func (x Action) String() string { + return ActionToGRPCField(x).String() +} + +// FromString parses Action from a string representation. +// It is a reverse action to String(). +// +// Returns true if s was parsed successfully. +func (x *Action) FromString(s string) bool { + var g acl.Action + + ok := g.FromString(s) + + if ok { + *x = ActionFromGRPCField(g) + } + + return ok +} + +// String returns string representation of Role. +func (x Role) String() string { + return RoleToGRPCField(x).String() +} + +// FromString parses Role from a string representation. +// It is a reverse action to String(). +// +// Returns true if s was parsed successfully. +func (x *Role) FromString(s string) bool { + var g acl.Role + + ok := g.FromString(s) + + if ok { + *x = RoleFromGRPCField(g) + } + + return ok +} + +// String returns string representation of Operation. +func (x Operation) String() string { + return OperationToGRPCField(x).String() +} + +// FromString parses Operation from a string representation. +// It is a reverse action to String(). +// +// Returns true if s was parsed successfully. +func (x *Operation) FromString(s string) bool { + var g acl.Operation + + ok := g.FromString(s) + + if ok { + *x = OperationFromGRPCField(g) + } + + return ok +} + +// String returns string representation of MatchType. +func (x MatchType) String() string { + return MatchTypeToGRPCField(x).String() +} + +// FromString parses MatchType from a string representation. +// It is a reverse action to String(). +// +// Returns true if s was parsed successfully. +func (x *MatchType) FromString(s string) bool { + var g acl.MatchType + + ok := g.FromString(s) + + if ok { + *x = MatchTypeFromGRPCField(g) + } + + return ok +} + +// String returns string representation of HeaderType. +func (x HeaderType) String() string { + return HeaderTypeToGRPCField(x).String() +} + +// FromString parses HeaderType from a string representation. +// It is a reverse action to String(). +// +// Returns true if s was parsed successfully. +func (x *HeaderType) FromString(s string) bool { + var g acl.HeaderType + + ok := g.FromString(s) + + if ok { + *x = HeaderTypeFromGRPCField(g) + } + + return ok +} diff --git a/api/acl/test/generate.go b/api/acl/test/generate.go new file mode 100644 index 0000000..8b265ad --- /dev/null +++ b/api/acl/test/generate.go @@ -0,0 +1,144 @@ +package acltest + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/acl" + apetest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/ape/test" + accountingtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs/test" +) + +func GenerateBearerToken(empty bool) *acl.BearerToken { + m := new(acl.BearerToken) + + if !empty { + m.SetBody(GenerateBearerTokenBody(false)) + } + + m.SetSignature(accountingtest.GenerateSignature(empty)) + + return m +} + +func GenerateBearerTokenBody(empty bool) *acl.BearerTokenBody { + m := new(acl.BearerTokenBody) + + if !empty { + m.SetOwnerID(accountingtest.GenerateOwnerID(false)) + m.SetLifetime(GenerateTokenLifetime(false)) + m.SetAPEOverride(GenerateAPEOverride(empty)) + } + + return m +} + +func GenerateAPEOverride(empty bool) *acl.APEOverride { + var m *acl.APEOverride + + if !empty { + m = new(acl.APEOverride) + m.SetTarget(apetest.GenerateChainTarget(empty)) + m.SetChains(apetest.GenerateRawChains(false, 3)) + } + + return m +} + +func GenerateTable(empty bool) *acl.Table { + m := new(acl.Table) + + if !empty { + m.SetRecords(GenerateRecords(false)) + m.SetContainerID(accountingtest.GenerateContainerID(false)) + } + + m.SetVersion(accountingtest.GenerateVersion(empty)) + + return m +} + +func GenerateRecords(empty bool) []acl.Record { + var rs []acl.Record + + if !empty { + rs = append(rs, + *GenerateRecord(false), + *GenerateRecord(false), + ) + } + + return rs +} + +func GenerateRecord(empty bool) *acl.Record { + m := new(acl.Record) + + if !empty { + m.SetAction(acl.ActionAllow) + m.SetOperation(acl.OperationGet) + m.SetFilters(GenerateFilters(false)) + m.SetTargets(GenerateTargets(false)) + } + + return m +} + +func GenerateFilters(empty bool) []acl.HeaderFilter { + var fs []acl.HeaderFilter + + if !empty { + fs = append(fs, + *GenerateFilter(false), + *GenerateFilter(false), + ) + } + + return fs +} + +func GenerateFilter(empty bool) *acl.HeaderFilter { + m := new(acl.HeaderFilter) + + if !empty { + m.SetKey("key") + m.SetValue("val") + m.SetHeaderType(acl.HeaderTypeRequest) + m.SetMatchType(acl.MatchTypeStringEqual) + } + + return m +} + +func GenerateTargets(empty bool) []acl.Target { + var ts []acl.Target + + if !empty { + ts = append(ts, + *GenerateTarget(false), + *GenerateTarget(false), + ) + } + + return ts +} + +func GenerateTarget(empty bool) *acl.Target { + m := new(acl.Target) + + if !empty { + m.SetRole(acl.RoleSystem) + m.SetKeys([][]byte{{1}, {2}}) + } + + return m +} + +func GenerateTokenLifetime(empty bool) *acl.TokenLifetime { + m := new(acl.TokenLifetime) + + if !empty { + m.SetExp(1) + m.SetIat(2) + m.SetExp(3) + } + + return m +} diff --git a/api/acl/types.go b/api/acl/types.go new file mode 100644 index 0000000..e0bae3a --- /dev/null +++ b/api/acl/types.go @@ -0,0 +1,426 @@ +package acl + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/ape" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" +) + +// HeaderFilter is a unified structure of FilterInfo +// message from proto definition. +type HeaderFilter struct { + hdrType HeaderType + + matchType MatchType + + key, value string +} + +// Target is a unified structure of Target +// message from proto definition. +type Target struct { + role Role + + keys [][]byte +} + +// Record is a unified structure of EACLRecord +// message from proto definition. +type Record struct { + op Operation + + action Action + + filters []HeaderFilter + + targets []Target +} + +// Table is a unified structure of EACLTable +// message from proto definition. +type Table struct { + version *refs.Version + + cid *refs.ContainerID + + records []Record +} + +type TokenLifetime struct { + exp, nbf, iat uint64 +} + +type APEOverride struct { + target *ape.ChainTarget + + chains []*ape.Chain +} + +type BearerTokenBody struct { + eacl *Table + + ownerID *refs.OwnerID + + lifetime *TokenLifetime + + apeOverride *APEOverride + + impersonate bool +} + +type BearerToken struct { + body *BearerTokenBody + + sig *refs.Signature +} + +// Target is a unified enum of MatchType enum from proto definition. +type MatchType uint32 + +// HeaderType is a unified enum of HeaderType enum from proto definition. +type HeaderType uint32 + +// Action is a unified enum of Action enum from proto definition. +type Action uint32 + +// Operation is a unified enum of Operation enum from proto definition. +type Operation uint32 + +// Role is a unified enum of Role enum from proto definition. +type Role uint32 + +const ( + MatchTypeUnknown MatchType = iota + MatchTypeStringEqual + MatchTypeStringNotEqual +) + +const ( + HeaderTypeUnknown HeaderType = iota + HeaderTypeRequest + HeaderTypeObject + HeaderTypeService +) + +const ( + ActionUnknown Action = iota + ActionAllow + ActionDeny +) + +const ( + OperationUnknown Operation = iota + OperationGet + OperationHead + OperationPut + OperationDelete + OperationSearch + OperationRange + OperationRangeHash +) + +const ( + RoleUnknown Role = iota + RoleUser + RoleSystem + RoleOthers +) + +func (f *HeaderFilter) GetHeaderType() HeaderType { + if f != nil { + return f.hdrType + } + + return HeaderTypeUnknown +} + +func (f *HeaderFilter) SetHeaderType(v HeaderType) { + f.hdrType = v +} + +func (f *HeaderFilter) GetMatchType() MatchType { + if f != nil { + return f.matchType + } + + return MatchTypeUnknown +} + +func (f *HeaderFilter) SetMatchType(v MatchType) { + f.matchType = v +} + +func (f *HeaderFilter) GetKey() string { + if f != nil { + return f.key + } + + return "" +} + +func (f *HeaderFilter) SetKey(v string) { + f.key = v +} + +func (f *HeaderFilter) GetValue() string { + if f != nil { + return f.value + } + + return "" +} + +func (f *HeaderFilter) SetValue(v string) { + f.value = v +} + +func (t *Target) GetRole() Role { + if t != nil { + return t.role + } + + return RoleUnknown +} + +func (t *Target) SetRole(v Role) { + t.role = v +} + +func (t *Target) GetKeys() [][]byte { + if t != nil { + return t.keys + } + + return nil +} + +func (t *Target) SetKeys(v [][]byte) { + t.keys = v +} + +func (r *Record) GetOperation() Operation { + if r != nil { + return r.op + } + + return OperationUnknown +} + +func (r *Record) SetOperation(v Operation) { + r.op = v +} + +func (r *Record) GetAction() Action { + if r != nil { + return r.action + } + + return ActionUnknown +} + +func (r *Record) SetAction(v Action) { + r.action = v +} + +func (r *Record) GetFilters() []HeaderFilter { + if r != nil { + return r.filters + } + + return nil +} + +func (r *Record) SetFilters(v []HeaderFilter) { + r.filters = v +} + +func (r *Record) GetTargets() []Target { + if r != nil { + return r.targets + } + + return nil +} + +func (r *Record) SetTargets(v []Target) { + r.targets = v +} + +func (t *Table) GetVersion() *refs.Version { + if t != nil { + return t.version + } + + return nil +} + +func (t *Table) SetVersion(v *refs.Version) { + t.version = v +} + +func (t *Table) GetContainerID() *refs.ContainerID { + if t != nil { + return t.cid + } + + return nil +} + +func (t *Table) SetContainerID(v *refs.ContainerID) { + t.cid = v +} + +func (t *Table) GetRecords() []Record { + if t != nil { + return t.records + } + + return nil +} + +func (t *Table) SetRecords(v []Record) { + t.records = v +} + +func (l *TokenLifetime) GetExp() uint64 { + if l != nil { + return l.exp + } + + return 0 +} + +func (l *TokenLifetime) SetExp(v uint64) { + l.exp = v +} + +func (l *TokenLifetime) GetNbf() uint64 { + if l != nil { + return l.nbf + } + + return 0 +} + +func (l *TokenLifetime) SetNbf(v uint64) { + l.nbf = v +} + +func (l *TokenLifetime) GetIat() uint64 { + if l != nil { + return l.iat + } + + return 0 +} + +func (l *TokenLifetime) SetIat(v uint64) { + l.iat = v +} + +func (bt *BearerTokenBody) GetEACL() *Table { + if bt != nil { + return bt.eacl + } + + return nil +} + +func (bt *BearerTokenBody) SetEACL(v *Table) { + bt.eacl = v +} + +func (t *APEOverride) GetTarget() *ape.ChainTarget { + if t == nil { + return nil + } + + return t.target +} + +func (t *APEOverride) GetChains() []*ape.Chain { + if t == nil { + return nil + } + + return t.chains +} + +func (t *APEOverride) SetTarget(v *ape.ChainTarget) { + t.target = v +} + +func (t *APEOverride) SetChains(v []*ape.Chain) { + t.chains = v +} + +func (bt *BearerTokenBody) GetAPEOverride() *APEOverride { + if bt != nil { + return bt.apeOverride + } + + return nil +} + +func (bt *BearerTokenBody) SetAPEOverride(v *APEOverride) { + bt.apeOverride = v +} + +func (bt *BearerTokenBody) GetOwnerID() *refs.OwnerID { + if bt != nil { + return bt.ownerID + } + + return nil +} + +func (bt *BearerTokenBody) SetOwnerID(v *refs.OwnerID) { + bt.ownerID = v +} + +func (bt *BearerTokenBody) GetLifetime() *TokenLifetime { + if bt != nil { + return bt.lifetime + } + + return nil +} + +func (bt *BearerTokenBody) SetLifetime(v *TokenLifetime) { + bt.lifetime = v +} + +func (bt *BearerTokenBody) GetImpersonate() bool { + if bt != nil { + return bt.impersonate + } + + return false +} + +func (bt *BearerTokenBody) SetImpersonate(v bool) { + bt.impersonate = v +} + +func (bt *BearerToken) GetBody() *BearerTokenBody { + if bt != nil { + return bt.body + } + + return nil +} + +func (bt *BearerToken) SetBody(v *BearerTokenBody) { + bt.body = v +} + +func (bt *BearerToken) GetSignature() *refs.Signature { + if bt != nil { + return bt.sig + } + + return nil +} + +func (bt *BearerToken) SetSignature(v *refs.Signature) { + bt.sig = v +} diff --git a/api/ape/convert.go b/api/ape/convert.go new file mode 100644 index 0000000..7bb0bde --- /dev/null +++ b/api/ape/convert.go @@ -0,0 +1,132 @@ +package ape + +import ( + "fmt" + + ape "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/ape/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/message" +) + +func TargetTypeToGRPCField(typ TargetType) ape.TargetType { + switch typ { + case TargetTypeNamespace: + return ape.TargetType_NAMESPACE + case TargetTypeContainer: + return ape.TargetType_CONTAINER + case TargetTypeUser: + return ape.TargetType_USER + case TargetTypeGroup: + return ape.TargetType_GROUP + default: + return ape.TargetType_UNDEFINED + } +} + +func TargetTypeFromGRPCField(typ ape.TargetType) TargetType { + switch typ { + case ape.TargetType_NAMESPACE: + return TargetTypeNamespace + case ape.TargetType_CONTAINER: + return TargetTypeContainer + case ape.TargetType_USER: + return TargetTypeUser + case ape.TargetType_GROUP: + return TargetTypeGroup + default: + return TargetTypeUndefined + } +} + +func TargetTypeToGRPC(typ TargetType) ape.TargetType { + return ape.TargetType(typ) +} + +func TargetTypeFromGRPC(typ ape.TargetType) TargetType { + return TargetType(typ) +} + +func (v2 *ChainTarget) ToGRPCMessage() grpc.Message { + var mgrpc *ape.ChainTarget + + if v2 != nil { + mgrpc = new(ape.ChainTarget) + + mgrpc.SetType(TargetTypeToGRPC(v2.GetTargetType())) + mgrpc.SetName(v2.GetName()) + } + + return mgrpc +} + +func (v2 *ChainTarget) FromGRPCMessage(m grpc.Message) error { + mgrpc, ok := m.(*ape.ChainTarget) + if !ok { + return message.NewUnexpectedMessageType(m, mgrpc) + } + + v2.SetTargetType(TargetTypeFromGRPC(mgrpc.GetType())) + v2.SetName(mgrpc.GetName()) + + return nil +} + +func (v2 *ChainRaw) ToGRPCMessage() grpc.Message { + var mgrpc *ape.Chain_Raw + + if v2 != nil { + mgrpc = new(ape.Chain_Raw) + + mgrpc.SetRaw(v2.GetRaw()) + } + + return mgrpc +} + +func (v2 *ChainRaw) FromGRPCMessage(m grpc.Message) error { + mgrpc, ok := m.(*ape.Chain_Raw) + if !ok { + return message.NewUnexpectedMessageType(m, mgrpc) + } + + v2.SetRaw(mgrpc.GetRaw()) + + return nil +} + +func (v2 *Chain) ToGRPCMessage() grpc.Message { + var mgrpc *ape.Chain + + if v2 != nil { + mgrpc = new(ape.Chain) + + switch chainKind := v2.GetKind().(type) { + default: + panic(fmt.Sprintf("unsupported chain kind: %T", chainKind)) + case *ChainRaw: + mgrpc.SetKind(chainKind.ToGRPCMessage().(*ape.Chain_Raw)) + } + } + + return mgrpc +} + +func (v2 *Chain) FromGRPCMessage(m grpc.Message) error { + mgrpc, ok := m.(*ape.Chain) + if !ok { + return message.NewUnexpectedMessageType(m, mgrpc) + } + + switch chainKind := mgrpc.GetKind().(type) { + default: + return fmt.Errorf("unsupported chain kind: %T", chainKind) + case *ape.Chain_Raw: + chainRaw := new(ChainRaw) + if err := chainRaw.FromGRPCMessage(chainKind); err != nil { + return err + } + v2.SetKind(chainRaw) + } + + return nil +} diff --git a/api/ape/grpc/types_frostfs.pb.go b/api/ape/grpc/types_frostfs.pb.go new file mode 100644 index 0000000000000000000000000000000000000000..c16e8673897c7071da1cb3c81841ec2663f0ef70 GIT binary patch literal 8595 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 literal 0 HcmV?d00001 diff --git a/api/ape/grpc/types_frostfs_fuzz.go b/api/ape/grpc/types_frostfs_fuzz.go new file mode 100644 index 0000000..b7bf367 --- /dev/null +++ b/api/ape/grpc/types_frostfs_fuzz.go @@ -0,0 +1,45 @@ +//go:build gofuzz +// +build gofuzz + +// Code generated by protoc-gen-go-frostfs. DO NOT EDIT. + +package ape + +func DoFuzzProtoChainTarget(data []byte) int { + msg := new(ChainTarget) + if err := msg.UnmarshalProtobuf(data); err != nil { + return 0 + } + _ = msg.MarshalProtobuf(nil) + return 1 +} +func DoFuzzJSONChainTarget(data []byte) int { + msg := new(ChainTarget) + if err := msg.UnmarshalJSON(data); err != nil { + return 0 + } + _, err := msg.MarshalJSON() + if err != nil { + panic(err) + } + return 1 +} +func DoFuzzProtoChain(data []byte) int { + msg := new(Chain) + if err := msg.UnmarshalProtobuf(data); err != nil { + return 0 + } + _ = msg.MarshalProtobuf(nil) + return 1 +} +func DoFuzzJSONChain(data []byte) int { + msg := new(Chain) + if err := msg.UnmarshalJSON(data); err != nil { + return 0 + } + _, err := msg.MarshalJSON() + if err != nil { + panic(err) + } + return 1 +} diff --git a/api/ape/grpc/types_frostfs_test.go b/api/ape/grpc/types_frostfs_test.go new file mode 100644 index 0000000..93d7eea --- /dev/null +++ b/api/ape/grpc/types_frostfs_test.go @@ -0,0 +1,31 @@ +//go:build gofuzz +// +build gofuzz + +// Code generated by protoc-gen-go-frostfs. DO NOT EDIT. + +package ape + +import ( + testing "testing" +) + +func FuzzProtoChainTarget(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzProtoChainTarget(data) + }) +} +func FuzzJSONChainTarget(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzJSONChainTarget(data) + }) +} +func FuzzProtoChain(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzProtoChain(data) + }) +} +func FuzzJSONChain(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzJSONChain(data) + }) +} diff --git a/api/ape/json.go b/api/ape/json.go new file mode 100644 index 0000000..ffa3a8b --- /dev/null +++ b/api/ape/json.go @@ -0,0 +1,14 @@ +package ape + +import ( + ape "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/ape/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/message" +) + +func (t *ChainTarget) MarshalJSON() ([]byte, error) { + return message.MarshalJSON(t) +} + +func (t *ChainTarget) UnmarshalJSON(data []byte) error { + return message.UnmarshalJSON(t, data, new(ape.ChainTarget)) +} diff --git a/api/ape/marshal.go b/api/ape/marshal.go new file mode 100644 index 0000000..e8f377b --- /dev/null +++ b/api/ape/marshal.go @@ -0,0 +1,92 @@ +package ape + +import ( + "fmt" + + ape "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/ape/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/message" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/util/proto" +) + +const ( + chainTargetTargetTypeField = 1 + chainTargetNameField = 2 + + chainRawField = 1 +) + +func (t *ChainTarget) StableSize() (size int) { + if t == nil { + return 0 + } + + size += proto.EnumSize(chainTargetTargetTypeField, int32(t.targeType)) + size += proto.StringSize(chainTargetNameField, t.name) + + return size +} + +func (t *ChainTarget) StableMarshal(buf []byte) []byte { + if t == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, t.StableSize()) + } + + var offset int + + offset += proto.EnumMarshal(chainTargetTargetTypeField, buf[offset:], int32(t.targeType)) + proto.StringMarshal(chainTargetNameField, buf[offset:], t.name) + + return buf +} + +func (t *ChainTarget) Unmarshal(data []byte) error { + return message.Unmarshal(t, data, new(ape.ChainTarget)) +} + +func (c *Chain) StableSize() (size int) { + if c == nil { + return 0 + } + + switch v := c.GetKind().(type) { + case *ChainRaw: + if v != nil { + size += proto.BytesSize(chainRawField, v.GetRaw()) + } + default: + panic(fmt.Sprintf("unsupported chain kind: %T", v)) + } + + return size +} + +func (c *Chain) StableMarshal(buf []byte) []byte { + if c == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, c.StableSize()) + } + + var offset int + + switch v := c.GetKind().(type) { + case *ChainRaw: + if v != nil { + proto.BytesMarshal(chainRawField, buf[offset:], v.GetRaw()) + } + default: + panic(fmt.Sprintf("unsupported chain kind: %T", v)) + } + + return buf +} + +func (c *Chain) Unmarshal(data []byte) error { + return message.Unmarshal(c, data, new(ape.Chain)) +} diff --git a/api/ape/message_test.go b/api/ape/message_test.go new file mode 100644 index 0000000..23b929b --- /dev/null +++ b/api/ape/message_test.go @@ -0,0 +1,15 @@ +package ape_test + +import ( + "testing" + + apetest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/ape/test" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/message" + messagetest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/message/test" +) + +func TestMessageConvert(t *testing.T) { + messagetest.TestRPCMessage(t, + func(empty bool) message.Message { return apetest.GenerateChainTarget(empty) }, + ) +} diff --git a/api/ape/string.go b/api/ape/string.go new file mode 100644 index 0000000..1d26c28 --- /dev/null +++ b/api/ape/string.go @@ -0,0 +1,18 @@ +package ape + +import ( + apegrpc "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/ape/grpc" +) + +func (tt TargetType) String() string { + return TargetTypeToGRPCField(tt).String() +} + +func (tt *TargetType) FromString(s string) bool { + i, ok := apegrpc.TargetType_value[s] + if ok { + *tt = TargetType(i) + } + + return ok +} diff --git a/api/ape/test/generate.go b/api/ape/test/generate.go new file mode 100644 index 0000000..4fd3dc2 --- /dev/null +++ b/api/ape/test/generate.go @@ -0,0 +1,71 @@ +package test + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/ape" +) + +func GenerateRawChains(empty bool, n int) []*ape.Chain { + if empty { + return []*ape.Chain{} + } + + res := make([]*ape.Chain, n) + for i := range res { + res[i] = GenerateRawChain(empty) + } + return res +} + +func GenerateRawChain(empty bool) *ape.Chain { + chRaw := new(ape.ChainRaw) + + if empty { + chRaw.SetRaw([]byte("{}")) + } else { + chRaw.SetRaw([]byte(`{ + "ID": "", + "Rules": [ + { + "Status": "Allow", + "Actions": { + "Inverted": false, + "Names": [ + "GetObject" + ] + }, + "Resources": { + "Inverted": false, + "Names": [ + "native:object/*" + ] + }, + "Any": false, + "Condition": [ + { + "Op": "StringEquals", + "Object": "Resource", + "Key": "Department", + "Value": "HR" + } + ] + } + ], + "MatchType": "DenyPriority" + }`)) + } + + ch := new(ape.Chain) + ch.SetKind(chRaw) + return ch +} + +func GenerateChainTarget(empty bool) *ape.ChainTarget { + m := new(ape.ChainTarget) + + if !empty { + m.SetTargetType(ape.TargetTypeContainer) + m.SetName("BzQw5HH3feoxFDD5tCT87Y1726qzgLfxEE7wgtoRzB3R") + } + + return m +} diff --git a/api/ape/types.go b/api/ape/types.go new file mode 100644 index 0000000..467a441 --- /dev/null +++ b/api/ape/types.go @@ -0,0 +1,79 @@ +package ape + +type TargetType uint32 + +const ( + TargetTypeUndefined TargetType = iota + TargetTypeNamespace + TargetTypeContainer + TargetTypeUser + TargetTypeGroup +) + +type ChainTarget struct { + targeType TargetType + + name string +} + +func (ct *ChainTarget) SetTargetType(targeType TargetType) { + ct.targeType = targeType +} + +func (ct *ChainTarget) SetName(name string) { + ct.name = name +} + +func (ct *ChainTarget) GetTargetType() TargetType { + if ct != nil { + return ct.targeType + } + + return 0 +} + +func (ct *ChainTarget) GetName() string { + if ct != nil { + return ct.name + } + + return "" +} + +type chainKind interface { + isChainKind() +} + +type Chain struct { + kind chainKind +} + +func (c *Chain) SetKind(kind chainKind) { + c.kind = kind +} + +func (c *Chain) GetKind() chainKind { + if c == nil { + return nil + } + + return c.kind +} + +type ChainRaw struct { + Raw []byte +} + +func (*ChainRaw) isChainKind() {} + +func (c *ChainRaw) SetRaw(raw []byte) { + c.Raw = raw +} + +func (c *ChainRaw) GetRaw() []byte { + if c == nil { + return nil + } + + return c.Raw +} diff --git a/api/apemanager/convert.go b/api/apemanager/convert.go new file mode 100644 index 0000000..5591791 --- /dev/null +++ b/api/apemanager/convert.go @@ -0,0 +1,358 @@ +package apemanager + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/ape" + apeGRPC "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/ape/grpc" + apemanager "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/apemanager/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/message" +) + +func (reqBody *AddChainRequestBody) ToGRPCMessage() grpc.Message { + var reqBodygrpc *apemanager.AddChainRequest_Body + + if reqBody != nil { + reqBodygrpc = new(apemanager.AddChainRequest_Body) + + reqBodygrpc.SetTarget(reqBody.GetTarget().ToGRPCMessage().(*apeGRPC.ChainTarget)) + reqBodygrpc.SetChain(reqBody.GetChain().ToGRPCMessage().(*apeGRPC.Chain)) + } + + return reqBodygrpc +} + +func (reqBody *AddChainRequestBody) FromGRPCMessage(m grpc.Message) error { + reqBodygrpc, ok := m.(*apemanager.AddChainRequest_Body) + if !ok { + return message.NewUnexpectedMessageType(m, reqBodygrpc) + } + + if targetgrpc := reqBodygrpc.GetTarget(); targetgrpc != nil { + reqBody.target = new(ape.ChainTarget) + if err := reqBody.target.FromGRPCMessage(targetgrpc); err != nil { + return err + } + } + + if chaingrpc := reqBodygrpc.GetChain(); chaingrpc != nil { + reqBody.chain = new(ape.Chain) + if err := reqBody.GetChain().FromGRPCMessage(chaingrpc); err != nil { + return err + } + } + + return nil +} + +func (req *AddChainRequest) ToGRPCMessage() grpc.Message { + var reqgrpc *apemanager.AddChainRequest + + if req != nil { + reqgrpc = new(apemanager.AddChainRequest) + + reqgrpc.SetBody(req.GetBody().ToGRPCMessage().(*apemanager.AddChainRequest_Body)) + req.RequestHeaders.ToMessage(reqgrpc) + } + + return reqgrpc +} + +func (req *AddChainRequest) FromGRPCMessage(m grpc.Message) error { + reqgrpc, ok := m.(*apemanager.AddChainRequest) + if !ok { + return message.NewUnexpectedMessageType(m, reqgrpc) + } + + if reqBodygrpc := reqgrpc.GetBody(); reqBodygrpc != nil { + req.body = new(AddChainRequestBody) + if err := req.body.FromGRPCMessage(reqBodygrpc); err != nil { + return err + } + } + + return req.RequestHeaders.FromMessage(reqgrpc) +} + +func (respBody *AddChainResponseBody) ToGRPCMessage() grpc.Message { + var respBodygrpc *apemanager.AddChainResponse_Body + + if respBody != nil { + respBodygrpc = new(apemanager.AddChainResponse_Body) + + respBodygrpc.SetChainId(respBody.GetChainID()) + } + + return respBodygrpc +} + +func (respBody *AddChainResponseBody) FromGRPCMessage(m grpc.Message) error { + respBodygrpc, ok := m.(*apemanager.AddChainResponse_Body) + if !ok { + return message.NewUnexpectedMessageType(m, respBodygrpc) + } + + respBody.SetChainID(respBodygrpc.GetChainId()) + + return nil +} + +func (resp *AddChainResponse) ToGRPCMessage() grpc.Message { + var respgrpc *apemanager.AddChainResponse + + if resp != nil { + respgrpc = new(apemanager.AddChainResponse) + + respgrpc.SetBody(resp.body.ToGRPCMessage().(*apemanager.AddChainResponse_Body)) + resp.ResponseHeaders.ToMessage(respgrpc) + } + + return respgrpc +} + +func (resp *AddChainResponse) FromGRPCMessage(m grpc.Message) error { + respgrpc, ok := m.(*apemanager.AddChainResponse) + if !ok { + return message.NewUnexpectedMessageType(m, respgrpc) + } + + if respBodygrpc := respgrpc.GetBody(); respBodygrpc != nil { + resp.body = new(AddChainResponseBody) + if err := resp.body.FromGRPCMessage(respBodygrpc); err != nil { + return err + } + } + + return resp.ResponseHeaders.FromMessage(respgrpc) +} + +func (reqBody *RemoveChainRequestBody) ToGRPCMessage() grpc.Message { + var reqBodygrpc *apemanager.RemoveChainRequest_Body + + if reqBody != nil { + reqBodygrpc = new(apemanager.RemoveChainRequest_Body) + + reqBodygrpc.SetTarget(reqBody.target.ToGRPCMessage().(*apeGRPC.ChainTarget)) + reqBodygrpc.SetChainId(reqBody.GetChainID()) + } + + return reqBodygrpc +} + +func (reqBody *RemoveChainRequestBody) FromGRPCMessage(m grpc.Message) error { + reqBodygrpc, ok := m.(*apemanager.RemoveChainRequest_Body) + if !ok { + return message.NewUnexpectedMessageType(m, reqBodygrpc) + } + + if targetgrpc := reqBodygrpc.GetTarget(); targetgrpc != nil { + reqBody.target = new(ape.ChainTarget) + if err := reqBody.target.FromGRPCMessage(targetgrpc); err != nil { + return err + } + } + + reqBody.SetChainID(reqBodygrpc.GetChainId()) + + return nil +} + +func (req *RemoveChainRequest) ToGRPCMessage() grpc.Message { + var reqgrpc *apemanager.RemoveChainRequest + + if req != nil { + reqgrpc = new(apemanager.RemoveChainRequest) + + reqgrpc.SetBody(req.body.ToGRPCMessage().(*apemanager.RemoveChainRequest_Body)) + req.RequestHeaders.ToMessage(reqgrpc) + } + + return reqgrpc +} + +func (req *RemoveChainRequest) FromGRPCMessage(m grpc.Message) error { + reqgrpc, ok := m.(*apemanager.RemoveChainRequest) + if !ok { + return message.NewUnexpectedMessageType(m, reqgrpc) + } + + if reqBodygrpc := reqgrpc.GetBody(); reqBodygrpc != nil { + req.body = new(RemoveChainRequestBody) + if err := req.body.FromGRPCMessage(reqBodygrpc); err != nil { + return err + } + } + + return req.RequestHeaders.FromMessage(reqgrpc) +} + +func (respBody *RemoveChainResponseBody) ToGRPCMessage() grpc.Message { + var respBodygrpc *apemanager.RemoveChainResponse_Body + + if respBody != nil { + respBodygrpc = new(apemanager.RemoveChainResponse_Body) + } + + return respBodygrpc +} + +func (respBody *RemoveChainResponseBody) FromGRPCMessage(m grpc.Message) error { + respBodygrpc, ok := m.(*apemanager.RemoveChainResponse_Body) + if !ok { + return message.NewUnexpectedMessageType(m, respBodygrpc) + } + + return nil +} + +func (resp *RemoveChainResponse) ToGRPCMessage() grpc.Message { + var respgrpc *apemanager.RemoveChainResponse + + if resp != nil { + respgrpc = new(apemanager.RemoveChainResponse) + + respgrpc.SetBody(resp.body.ToGRPCMessage().(*apemanager.RemoveChainResponse_Body)) + resp.ResponseHeaders.ToMessage(respgrpc) + } + + return respgrpc +} + +func (resp *RemoveChainResponse) FromGRPCMessage(m grpc.Message) error { + respgrpc, ok := m.(*apemanager.RemoveChainResponse) + if !ok { + return message.NewUnexpectedMessageType(m, respgrpc) + } + + if respBodygrpc := respgrpc.GetBody(); respBodygrpc != nil { + resp.body = new(RemoveChainResponseBody) + if err := resp.body.FromGRPCMessage(respBodygrpc); err != nil { + return err + } + } + + return resp.ResponseHeaders.FromMessage(respgrpc) +} + +func (reqBody *ListChainsRequestBody) ToGRPCMessage() grpc.Message { + var reqBodygrpc *apemanager.ListChainsRequest_Body + + if reqBody != nil { + reqBodygrpc = new(apemanager.ListChainsRequest_Body) + + reqBodygrpc.SetTarget(reqBody.target.ToGRPCMessage().(*apeGRPC.ChainTarget)) + } + + return reqBodygrpc +} + +func (reqBody *ListChainsRequestBody) FromGRPCMessage(m grpc.Message) error { + reqBodygrpc, ok := m.(*apemanager.ListChainsRequest_Body) + if !ok { + return message.NewUnexpectedMessageType(m, reqBodygrpc) + } + + if targetgrpc := reqBodygrpc.GetTarget(); targetgrpc != nil { + reqBody.target = new(ape.ChainTarget) + if err := reqBody.target.FromGRPCMessage(targetgrpc); err != nil { + return err + } + } + + return nil +} + +func (req *ListChainsRequest) ToGRPCMessage() grpc.Message { + var reqgrpc *apemanager.ListChainsRequest + + if req != nil { + reqgrpc = new(apemanager.ListChainsRequest) + + reqgrpc.SetBody(req.body.ToGRPCMessage().(*apemanager.ListChainsRequest_Body)) + req.RequestHeaders.ToMessage(reqgrpc) + } + + return reqgrpc +} + +func (req *ListChainsRequest) FromGRPCMessage(m grpc.Message) error { + reqgrpc, ok := m.(*apemanager.ListChainsRequest) + if !ok { + return message.NewUnexpectedMessageType(m, reqgrpc) + } + + if reqBodygrpc := reqgrpc.GetBody(); reqBodygrpc != nil { + req.body = new(ListChainsRequestBody) + if err := req.body.FromGRPCMessage(reqBodygrpc); err != nil { + return err + } + } + + return req.RequestHeaders.FromMessage(reqgrpc) +} + +func (respBody *ListChainsResponseBody) ToGRPCMessage() grpc.Message { + var respBodygrpc *apemanager.ListChainsResponse_Body + + if respBody != nil { + respBodygrpc = new(apemanager.ListChainsResponse_Body) + + chainsgrpc := make([]apeGRPC.Chain, 0, len(respBody.GetChains())) + for _, chain := range respBody.GetChains() { + chainsgrpc = append(chainsgrpc, *chain.ToGRPCMessage().(*apeGRPC.Chain)) + } + + respBodygrpc.SetChains(chainsgrpc) + } + + return respBodygrpc +} + +func (respBody *ListChainsResponseBody) FromGRPCMessage(m grpc.Message) error { + respBodygrpc, ok := m.(*apemanager.ListChainsResponse_Body) + if !ok { + return message.NewUnexpectedMessageType(m, respBodygrpc) + } + + chains := make([]*ape.Chain, 0, len(respBodygrpc.GetChains())) + + for _, chaingrpc := range respBodygrpc.GetChains() { + chain := new(ape.Chain) + if err := chain.FromGRPCMessage(&chaingrpc); err != nil { + return err + } + chains = append(chains, chain) + } + + respBody.SetChains(chains) + + return nil +} + +func (resp *ListChainsResponse) ToGRPCMessage() grpc.Message { + var respgrpc *apemanager.ListChainsResponse + + if resp != nil { + respgrpc = new(apemanager.ListChainsResponse) + + respgrpc.SetBody(resp.body.ToGRPCMessage().(*apemanager.ListChainsResponse_Body)) + resp.ResponseHeaders.ToMessage(respgrpc) + } + + return respgrpc +} + +func (resp *ListChainsResponse) FromGRPCMessage(m grpc.Message) error { + respgrpc, ok := m.(*apemanager.ListChainsResponse) + if !ok { + return message.NewUnexpectedMessageType(m, respgrpc) + } + + if respBodygrpc := respgrpc.GetBody(); respBodygrpc != nil { + resp.body = new(ListChainsResponseBody) + if err := resp.body.FromGRPCMessage(respBodygrpc); err != nil { + return err + } + } + + return resp.ResponseHeaders.FromMessage(respgrpc) +} diff --git a/api/apemanager/grpc/service_frostfs.pb.go b/api/apemanager/grpc/service_frostfs.pb.go new file mode 100644 index 0000000000000000000000000000000000000000..b9e06704bc21332364533e49c4478cf2b1506e6e GIT binary patch literal 57153 zcmeHQTXWk+vVJCi#h6uzNv}-B$*J?8Ep64t_U_Rs$4Obv?n9E=g-B3BOoChhq@;EE zzi)TX9fQGzA|#Rvmu~{*(lgUD-TlosgVR&?dN~c*br^?9kcCrrbaoq2(g2|`gI%L5rTm&)vFX{KA#cG*kY}oJpo-SiH z2;<3e8pYSA_~W48n=LXnfWP3s*U4(a2G>zGmgPtBYJt z+S??`suJ@wgZ`-B&+bS?2bh-pX^ub8JjJWMUaglAJ2-TvQEO3-A36B&lfC0HjBdflx>1J zj3B!SHlcoX6~#dU0}92D`?GaCVZ%FC+_Q#g!x0;jL{XfLPz@rK?EIWT=i`q(E;{?B z-}}<cTU!AbKF;^TIyXy4cVtP_2NG|HaT&O(IhhpSN zX|S7MjhlyyFwS^i`m_of6DG4@Qr#1|3Wn1(W54`%b)SVJ@h|qmf}KI5VZG6+^b`K{ z*DxD`+|zIds$B5?r*$@5K!UsR+eMVgRty*8A7B}TRa+_MaD>G`-RBHma{WeGbf>@% z*e4YOYge;iFVqU-R9Q0GG}fpHVkFr!tq<~9u0@OSpI56eo{EMIUtxnlW2h9qU|5CF zqlz-VBlqV!=HCJBQ-%Y^z4*S6V&=^p+IPR`d$ z(7n41%Qo0_^tqEml1n z4kkeyFEdzFf+>rk2(c=_a`II=IAMdL)pP*Ef#cCjVL_SPVC_`%`}KkZn*?ddUY#+R zbA0wf(%v-4f)lpONL?lX9c%Y<4e3Itut6Ef#063$PAVEJLs^^05T-;yM)4${1=c3YUZ0xWY?S;l{0y zW~(e3v};qV0o19s{HW<Fgt5Ug z(HG#hk0ydx=5BGe35Rq1ck(+wgF4(vGxZicUCRCSEhwfK$lLMv>lqkD_$QiAzXx-g z4o4^Kmak#e{V$|aWiQv@nc6}W+Al~q{t(=PPXd9@a1gKObDB_GEE=6zlz^RuHi6#~ z_In}+ia31!`8hNJmopgUXFMS-ZdRfbOw{|r!Z|FN^qQxHH8Oxl_zwO|mN8VbO2S!m zhh8?w10y;3Rrt}r4$i=jm$eIdd1@?OYOB-9APKyO3R;$OfO610#WyazRg$ti|B(m6=`APG1f z>3R`P$t0&$0RoUA zsW@sVWczy%XRnv@WlYr+2y2Ojeodq?zQH-t8GY$%v;RBk(=oAfTDh$d5@KntUF0WKB@v2TSdc1E% zPr)-iayXB0eafi;Brvt$3(mEou-}OI2>_5WZDFJ+U*f+axW59_06_qNFoORB50qkf zvhlCR0$H$L@ghX#h026Q{4GqP*}W*lE`nY~lOO}ENF)$NY>Z3~!5FrL7j(9q#WlLB z0F}sPQ)>hDp2+IYw!e77sBI_#brkfyCXk>tuU4M#5PUGT5ORry-oPL}fR?GfY$)vL@E3)MbILMp-x@gC4wg489~G& zvq0KlK3{_Jhf@g%eGmXr5Z_~r0_!$HA8Uj;05!h7i6Eq#Mi34{T!@)(8KQsab0FkI zrV#K)z)rGoeorF)2rrV`C=E|6bV`T~rivG;vV&AuWERF!CI$R70I7`L@`F^MRI0mq z|6mAD)|H%7mU-xmEK>hX8oPCM6sL1+)yum3I)d8F8Ovm^)b9Y{YgAnUPgB z0>ry9KB<7ZEVxXsVkQy<0hh9#6{QK_jAB)5eY49mSH6l8zk56=Zp4&zl$v`CC|m;o z4)q0HN?f*EgWs?c3u_|15Mw^P)fbap8AepN^?TD-dAR2R&SXviu#M*TfV*1Z)Oqg^&Es%@LL$xa$Ix7 zl*duLr-t4M%#J&Ag;ge-Pw4t}0h)pqbTaqAP}Is+mhP*6`Q7sF?8g z>S1EaMI$h550G6Ykb+(S9y}IM_X?(KC0a@rvjEwKM})!X#dt&m4o$w-&N>=(L@TyMKKVva;(2JFjXyW zS`mcavZ9UJR3OkmHv@5lT}GW&OT}8V2eD_7Sjrtfq6lw4k1k5M5a#sg}Ygi?NEuQL5ENT3bX~LW$il zf-jc187K!BYsnr1dDfO!;2od@AIR5AuH6|wm&q)zo<)UNM6d(ICdaIC8 z!>8ssLDCTO)njmv#_R(H1nD)8=oMLL$i@RwQpEwN3_AI>nDP=OkG)YL>oGT zivZp5c{`^*<k32cf3JorIt=l8pa9K>-E#PT+ zeTCPPt&m9Qu6u9v%<0Zn= zt`PI^h-+SrQ)c;*L5pgE)Yy0AwJpeNe7d>ZHRl3ECk8hSSe=+#SsF!lIRs%5Df84x-58WiYwbOtl5yP1lm71yU5y=Cy|+?D7!nRG?%JR~k%k^Dylg>`(o zC+E`@X_zvZM+UGpz}7hX<_S4kURkjJ8ncQ6ovz*;d6wYS_d2zel+Itn3N z|K9;_&FG=Mo&zYx%W`vPfyJtGU-N(ppdAEO%*~LxmsYt&f@h@ft#V)UX^Hr3@zqss zjuLiVKDaAuh}P^hDeeypk17aukTPE-MN+t*S1IgG6xw=SA~%FTUpz`Envk;~Q^ z&(0lvvf374?MYJyw-%K89BOSKu?}!;L$RhMFQD4x%`z8TJ7mW82A4K>>10kWbJ}`P z{Ss?!^_e8v`Rr*8Npr?l$=WW@&Y)Xrv>xsasrg+;OIM7tH1ynn5?7eN0qE_|uNJsc z=-bV|uK>6y>DIKkRC zqrILUd9RX1@WQ8QGJzxsT;X|e@AtB}LTJA>pWE<_y(|S@2Kk59)v8hg%a7ffrod}? zfa9jKHul+aS=Gd;;jW3S`|YW9Tm@tIz2hqEf~z2=>rsA5t6=FptgmSmHsCnu3R3SH z#yor*>KqPAM04C+5cjImP6knb$@m%{Y{Km{YyQ5JlZ1-_nW2ie(s*RM3ttF-&S@Dp3S!`x`V={OTmZm;VK@Riv* zp0ME^D+;0ftOee#-O?7MvGVa2j5@_0KbfJj6JD}NINhZ+)7;$W3G}UFyLhN zZ?U5n3a)4OJuWu*b+9>93WJ=0%JY4C_}9RqJLDHW+KnXCc-#p2<;UHw5L$I913v#6 zE9%K_bNLdHI2Bjk2q!>o!Eid6MB}Vufcd+Q7uR*&82*sIb z3nJvt>Rs#83hTnxcr^zVQjsPT^`WLA9>{<{%Y@<-EMJ7id)wJisR#h_N7%Yj#oo+kyV5P2tr%-#gPdH;POiuV>zN{0js3lE> zRqY2VUfNNyRw>$$3|uHQ_Ogz0M0u6F!I#B6Om>f(eA+s4(is~DO}UI}{iuwW zM8@l{Zh8_ zxNwaIkOuAzv<_%sB^I0^b|mnYVP{l2ZjsuUfz1Ya5wkkEsW(n277)l7gxTid(DwK- zv_sQfhXN2_5dyiEB*!!M)h$4d09w*0VF1<$G_!a`#Z#n|pTeg#R4KrJpsDu1^c9oI zDbczM#d*u8BnQmI)V1!6b}~HXO(+GGd&xw(K(dlcR8V#algJlimRgrI&e!6s^AtATCK-Bd^xcjW_Up0Z`F4T?zUd0~6b}5>za+&}C!;p zov^QE-e02MK-+bc(ayKSeEN2{SFdD@bp%U8dl_!^{|&9u!_ zqr0P1Z?F#OrKkk(Fb0Eg3f@@ysFiMADY_yDrg?P`w2SICmN^!ox$5`bvyrS;?^9@A zB$#rij);#mxe1~;t+-FqVjKPP9A{YBLXI;lLR#cEsITzL%6~%nC54dd7MN@g06^)i z{J&v-&~fYGE^j~b+CgOjo-lf~^im0=G_xZ?Z9#(KbHF7*>2;U17#YNKI16Ddk@N=Q z=r`d!S`44_$-$?`GkAQFiWi`@Vlwpb@Qg0{GpI8DGE9&$nqG)@Am~c^m4O|X;KOw^0^IhUo|<47wKhZ z88r$7QOsa3Jxdn&i1$4et?*uk7MIVMO4yU;1OiQ}(>POc9_zLzPeUzHHcWjYgg3Qd z67VLQ*+iose$#uAi2DZycSJ3m#vYs&)(ymZ!Mt==JssLrPes#D;X_Z3bsLVi0gSR2 zzt6+FFd4tYzsbx*8l8l_KL95$(n~nsnjtm`dPxu7ujg}Ec!jDOIcTFI2WS$G3ePS- zMJu{tiCae6eSpUT*`-tCxE*5Qy#Sd~EuX@B+=+zbKgVe>3+V!h_wW_%A@TjtwSadV zw4N_xs-{5LN1|#OmK)vtp1kMD)e!A=mm=5dBbD2bwenWi5(yD>WEJNVVUL!h={dWd flWb$cyzaGFcD1gVERoSoTu0WN!Bx`k5VZdf>Ra>; literal 0 HcmV?d00001 diff --git a/api/apemanager/grpc/service_frostfs_fuzz.go b/api/apemanager/grpc/service_frostfs_fuzz.go new file mode 100644 index 0000000..08af63e --- /dev/null +++ b/api/apemanager/grpc/service_frostfs_fuzz.go @@ -0,0 +1,121 @@ +//go:build gofuzz +// +build gofuzz + +// Code generated by protoc-gen-go-frostfs. DO NOT EDIT. + +package apemanager + +func DoFuzzProtoAddChainRequest(data []byte) int { + msg := new(AddChainRequest) + if err := msg.UnmarshalProtobuf(data); err != nil { + return 0 + } + _ = msg.MarshalProtobuf(nil) + return 1 +} +func DoFuzzJSONAddChainRequest(data []byte) int { + msg := new(AddChainRequest) + if err := msg.UnmarshalJSON(data); err != nil { + return 0 + } + _, err := msg.MarshalJSON() + if err != nil { + panic(err) + } + return 1 +} +func DoFuzzProtoAddChainResponse(data []byte) int { + msg := new(AddChainResponse) + if err := msg.UnmarshalProtobuf(data); err != nil { + return 0 + } + _ = msg.MarshalProtobuf(nil) + return 1 +} +func DoFuzzJSONAddChainResponse(data []byte) int { + msg := new(AddChainResponse) + if err := msg.UnmarshalJSON(data); err != nil { + return 0 + } + _, err := msg.MarshalJSON() + if err != nil { + panic(err) + } + return 1 +} +func DoFuzzProtoRemoveChainRequest(data []byte) int { + msg := new(RemoveChainRequest) + if err := msg.UnmarshalProtobuf(data); err != nil { + return 0 + } + _ = msg.MarshalProtobuf(nil) + return 1 +} +func DoFuzzJSONRemoveChainRequest(data []byte) int { + msg := new(RemoveChainRequest) + if err := msg.UnmarshalJSON(data); err != nil { + return 0 + } + _, err := msg.MarshalJSON() + if err != nil { + panic(err) + } + return 1 +} +func DoFuzzProtoRemoveChainResponse(data []byte) int { + msg := new(RemoveChainResponse) + if err := msg.UnmarshalProtobuf(data); err != nil { + return 0 + } + _ = msg.MarshalProtobuf(nil) + return 1 +} +func DoFuzzJSONRemoveChainResponse(data []byte) int { + msg := new(RemoveChainResponse) + if err := msg.UnmarshalJSON(data); err != nil { + return 0 + } + _, err := msg.MarshalJSON() + if err != nil { + panic(err) + } + return 1 +} +func DoFuzzProtoListChainsRequest(data []byte) int { + msg := new(ListChainsRequest) + if err := msg.UnmarshalProtobuf(data); err != nil { + return 0 + } + _ = msg.MarshalProtobuf(nil) + return 1 +} +func DoFuzzJSONListChainsRequest(data []byte) int { + msg := new(ListChainsRequest) + if err := msg.UnmarshalJSON(data); err != nil { + return 0 + } + _, err := msg.MarshalJSON() + if err != nil { + panic(err) + } + return 1 +} +func DoFuzzProtoListChainsResponse(data []byte) int { + msg := new(ListChainsResponse) + if err := msg.UnmarshalProtobuf(data); err != nil { + return 0 + } + _ = msg.MarshalProtobuf(nil) + return 1 +} +func DoFuzzJSONListChainsResponse(data []byte) int { + msg := new(ListChainsResponse) + if err := msg.UnmarshalJSON(data); err != nil { + return 0 + } + _, err := msg.MarshalJSON() + if err != nil { + panic(err) + } + return 1 +} diff --git a/api/apemanager/grpc/service_frostfs_test.go b/api/apemanager/grpc/service_frostfs_test.go new file mode 100644 index 0000000..5c4653c --- /dev/null +++ b/api/apemanager/grpc/service_frostfs_test.go @@ -0,0 +1,71 @@ +//go:build gofuzz +// +build gofuzz + +// Code generated by protoc-gen-go-frostfs. DO NOT EDIT. + +package apemanager + +import ( + testing "testing" +) + +func FuzzProtoAddChainRequest(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzProtoAddChainRequest(data) + }) +} +func FuzzJSONAddChainRequest(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzJSONAddChainRequest(data) + }) +} +func FuzzProtoAddChainResponse(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzProtoAddChainResponse(data) + }) +} +func FuzzJSONAddChainResponse(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzJSONAddChainResponse(data) + }) +} +func FuzzProtoRemoveChainRequest(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzProtoRemoveChainRequest(data) + }) +} +func FuzzJSONRemoveChainRequest(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzJSONRemoveChainRequest(data) + }) +} +func FuzzProtoRemoveChainResponse(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzProtoRemoveChainResponse(data) + }) +} +func FuzzJSONRemoveChainResponse(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzJSONRemoveChainResponse(data) + }) +} +func FuzzProtoListChainsRequest(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzProtoListChainsRequest(data) + }) +} +func FuzzJSONListChainsRequest(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzJSONListChainsRequest(data) + }) +} +func FuzzProtoListChainsResponse(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzProtoListChainsResponse(data) + }) +} +func FuzzJSONListChainsResponse(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzJSONListChainsResponse(data) + }) +} diff --git a/api/apemanager/grpc/service_grpc.pb.go b/api/apemanager/grpc/service_grpc.pb.go new file mode 100644 index 0000000000000000000000000000000000000000..eb11f3fde9dc04cfb3eba36f2dc60edc0e6d9d2e GIT binary patch literal 9917 zcmeHN?Qh$-8UGyr6IK$1_#L5j($R z~JRK zEECa8W;~xoQqAn)SdPKGZd&izRX}OO&9WKHEg!ZzE#l^Oo@$1FoW*icq?tH2=>imM zuwo!GW+W52UMj)NoE!WCa3%jKcF-|+Nc*`-?=!(3QZol66h-`aDWrzL?nRoQ+$;qSA&<*r`1_x>*(^%_}G8k^YC% z^Sf3F2q~Xk4KJLEZk%!^XGt=c1MB4dGRrQ6nagC%!83kN*txlp!Z&B@- zo<9Z>uPsil#X_#cPBbsU5gfA<&CjVe7KyGg^Aa@GG2Sd{91XHmUj%}2J>ur>OeNe#Q`i98|m&_)Tqpii&_-DO24 zI3Sgn3PlzS}2Ua$BtgPTN&SoL;0P4BOU-=8Kj{ByWBjZUTk{`_A7Z;b~j)y-w z8eEQV&qm|n^#rkV^8WH}d`={N|MuNUMb#Q8po`dpIG~y~=yFo%uv{7l2#T&Sz)mI? zXXCS2Lv^Oe{U zr81ECY9h`=s>IuDAr;I%1` zTpHFtWx050Z-XH_AWP6{9K~@o%2)D(Ad0$m88p?Tl&X-KmSuWEcEYLYl+q9T6VRp^ z5#a@guQoHa4xZM+w0p6zpWuS<(k#0GXdm%yfIln29gr^)Vz7U!9R6?1vGT%ZF;+19 zNHK(dR)}@L7s;^N{zXMd)%124qW%muB&s@J%i-HzEe1QwGKR)F6AKhdwm3w^GndOO zVPbKQ9C(+nmqpTmnHm-9X7K-kEA%8~Lz`x)d2HwuJk35lzIF=h{^ftJQ`qhjg0kPX z2(O*MRwwpcFRJVSWZnDye|MunVrti#(W79s%mid<8&5YQzOBqDP`_6CV~jD%sYPI% z-{3%^%Bwpppjr$JAbhx`f7IZ}Rr};Lp9SxQON1B@+4&i@X4`oVW36?PbUCz~kL`!Z zcMrZnXz#Nvtkpj!{!-p8+Xq_(yCHWpq%qAD635&;+MuV)4i|RxyKWZjz-lc3ksNkV zGuu{YPfh}l-J#=PHBj=#(@iaZ21~)IpUqWehC7(576YEbhkqDL)uB5%a{i$CR5TQK zY{4HfjM(r3O#G;~qAA+8FW8#TR)hA!V?9_Tx5FSBJM8mxUH74CrGcjss2Wj(!q2+6 zL~$cojNs^!0d=ixta=~PEF&f`s$FK7v*+a%iJNrVaid@Xq3|#f+vjstFQTG<45K)h`Aa4q9>5Wm>J8SnQBN>&PEn?rp!R;h2<5=R(K! z#EPy-9oVz->8We)8ERQK5iuj@ZU>+pH`b+Q5xmEuFz5y>qjx!1 zk3^PGqiPLlI@s-p!o()jSDOmB8gkvfV;wZ$fXzZzyV_0-^ry;^p&UZR-!YI>6AZ0HsGKi_{VxVa)>{)XRLhmkJ-y{rr&zS|!qN)IKW$J^NqDJS#%Jv~^aPz8T}JND6JU zdg^uadrT8$PAyS|N#BnE!y1E%0b7sNc2>8(ICo_JqM6Kb8BTGW$}qbrNl};?`?i67 zH^rX3Rf%+|{GxXesE$LWhGG$C;AIe8@6)SBs09`>!9_nlx5WyV?^NHROe-Ectrg$# z7Q_Zm{*4t^G7&pSuw|t~ub=eU;ht}v93l;u#m+5WU+B{X_3l|}r;TQ)19112i|(_3 z{@b$dzL!KCP^K?IN=kgWK&TEpGFt}hQGwB(C;C-CH;8R}9UZ{?X!XqLm38iQcm=+F hHc{{15P`_N%-jPjGg^lTdBP2c-hT5s literal 0 HcmV?d00001 diff --git a/api/apemanager/marshal.go b/api/apemanager/marshal.go new file mode 100644 index 0000000..ac6fdde --- /dev/null +++ b/api/apemanager/marshal.go @@ -0,0 +1,205 @@ +package apemanager + +import ( + apemanager "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/apemanager/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/message" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/util/proto" +) + +const ( + addChainReqBodyTargetField = 1 + addChainReqBodyChainField = 2 + + addChainRespBodyChainIDField = 1 + + removeChainReqBodyTargetField = 1 + removeChainReqBodyChainField = 2 + + /* + Fields for RemoveResponseBody are missed since RemoveResponseBody is empty. + */ + + listChainsReqBodyTargetField = 1 + + listChainsRespBodyChainsField = 1 +) + +func (rb *AddChainRequestBody) StableSize() (size int) { + if rb == nil { + return 0 + } + + size += proto.NestedStructureSize(addChainReqBodyTargetField, rb.target) + size += proto.NestedStructureSize(addChainReqBodyChainField, rb.chain) + + return size +} + +func (rb *AddChainRequestBody) StableMarshal(buf []byte) []byte { + if rb == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, rb.StableSize()) + } + + var offset int + + offset += proto.NestedStructureMarshal(addChainReqBodyTargetField, buf[offset:], rb.target) + proto.NestedStructureMarshal(addChainReqBodyChainField, buf[offset:], rb.chain) + + return buf +} + +func (rb *AddChainRequestBody) Unmarshal(data []byte) error { + return message.Unmarshal(rb, data, new(apemanager.AddChainRequest_Body)) +} + +func (rb *AddChainResponseBody) StableSize() (size int) { + if rb == nil { + return 0 + } + + size += proto.BytesSize(addChainRespBodyChainIDField, rb.chainID) + + return size +} + +func (rb *AddChainResponseBody) StableMarshal(buf []byte) []byte { + if rb == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, rb.StableSize()) + } + + var offset int + + proto.BytesMarshal(addChainRespBodyChainIDField, buf[offset:], rb.chainID) + + return buf +} + +func (rb *AddChainResponseBody) Unmarshal(data []byte) error { + return message.Unmarshal(rb, data, new(apemanager.AddChainResponse_Body)) +} + +func (rb *RemoveChainRequestBody) StableSize() (size int) { + if rb == nil { + return 0 + } + + size += proto.NestedStructureSize(addChainReqBodyTargetField, rb.target) + size += proto.BytesSize(addChainReqBodyChainField, rb.chainID) + + return size +} + +func (rb *RemoveChainRequestBody) StableMarshal(buf []byte) []byte { + if rb == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, rb.StableSize()) + } + + var offset int + + offset += proto.NestedStructureMarshal(removeChainReqBodyTargetField, buf[offset:], rb.target) + proto.BytesMarshal(removeChainReqBodyChainField, buf[offset:], rb.chainID) + + return buf +} + +func (rb *RemoveChainRequestBody) Unmarshal(data []byte) error { + return message.Unmarshal(rb, data, new(apemanager.RemoveChainRequest_Body)) +} + +func (rb *RemoveChainResponseBody) StableSize() (size int) { + if rb == nil { + return 0 + } + + return size +} + +func (rb *RemoveChainResponseBody) StableMarshal(buf []byte) []byte { + if rb == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, rb.StableSize()) + } + + return buf +} + +func (rb *RemoveChainResponseBody) Unmarshal(data []byte) error { + return message.Unmarshal(rb, data, new(apemanager.RemoveChainResponse_Body)) +} + +func (rb *ListChainsRequestBody) StableSize() (size int) { + if rb == nil { + return 0 + } + + size += proto.NestedStructureSize(listChainsReqBodyTargetField, rb.target) + + return size +} + +func (rb *ListChainsRequestBody) StableMarshal(buf []byte) []byte { + if rb == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, rb.StableSize()) + } + + var offset int + proto.NestedStructureMarshal(addChainReqBodyTargetField, buf[offset:], rb.target) + + return buf +} + +func (rb *ListChainsRequestBody) Unmarshal(data []byte) error { + return message.Unmarshal(rb, data, new(apemanager.ListChainsRequest_Body)) +} + +func (rb *ListChainsResponseBody) StableSize() (size int) { + if rb == nil { + return 0 + } + + for _, chain := range rb.GetChains() { + size += proto.NestedStructureSize(listChainsRespBodyChainsField, chain) + } + + return size +} + +func (rb *ListChainsResponseBody) StableMarshal(buf []byte) []byte { + if rb == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, rb.StableSize()) + } + + var offset int + for _, chain := range rb.GetChains() { + offset += proto.NestedStructureMarshal(listChainsRespBodyChainsField, buf[offset:], chain) + } + + return buf +} + +func (rb *ListChainsResponseBody) Unmarshal(data []byte) error { + return message.Unmarshal(rb, data, new(apemanager.ListChainsResponse_Body)) +} diff --git a/api/apemanager/message_test.go b/api/apemanager/message_test.go new file mode 100644 index 0000000..d64688c --- /dev/null +++ b/api/apemanager/message_test.go @@ -0,0 +1,26 @@ +package apemanager_test + +import ( + "testing" + + apemanagertest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/apemanager/test" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/message" + messagetest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/message/test" +) + +func TestMessageConvert(t *testing.T) { + messagetest.TestRPCMessage(t, + func(empty bool) message.Message { return apemanagertest.GenerateAddChainRequestBody(empty) }, + func(empty bool) message.Message { return apemanagertest.GenerateAddChainRequest(empty) }, + func(empty bool) message.Message { return apemanagertest.GenerateAddChainResponseBody(empty) }, + func(empty bool) message.Message { return apemanagertest.GenerateAddChainResponse(empty) }, + func(empty bool) message.Message { return apemanagertest.GenerateRemoveChainRequestBody(empty) }, + func(empty bool) message.Message { return apemanagertest.GenerateRemoveChainRequest(empty) }, + func(empty bool) message.Message { return apemanagertest.GenerateRemoveChainResponseBody(empty) }, + func(empty bool) message.Message { return apemanagertest.GenerateRemoveChainResponse(empty) }, + func(empty bool) message.Message { return apemanagertest.GenerateListChainsRequestBody(empty) }, + func(empty bool) message.Message { return apemanagertest.GenerateListChainsRequest(empty) }, + func(empty bool) message.Message { return apemanagertest.GenerateListChainsResponseBody(empty) }, + func(empty bool) message.Message { return apemanagertest.GenerateListChainsResponse(empty) }, + ) +} diff --git a/api/apemanager/status.go b/api/apemanager/status.go new file mode 100644 index 0000000..3b7f435 --- /dev/null +++ b/api/apemanager/status.go @@ -0,0 +1,76 @@ +package apemanager + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/status" + statusgrpc "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/status/grpc" +) + +// LocalizeFailStatus checks if passed global status.Code is related to ape manager failure and: +// +// then localizes the code and returns true, +// else leaves the code unchanged and returns false. +// +// Arg must be non-nil. +func LocalizeFailStatus(c *status.Code) bool { + return status.LocalizeIfInSection(c, uint32(statusgrpc.Section_SECTION_APE_MANAGER)) +} + +// GlobalizeFail globalizes local code of ape manager failure. +// +// Arg must be non-nil. +func GlobalizeFail(c *status.Code) { + c.GlobalizeSection(uint32(statusgrpc.Section_SECTION_APE_MANAGER)) +} + +const ( + // StatusAPEManagerAccessDenied is a local status.Code value for + // ACCESS_DENIED ape manager failure. + StatusAPEManagerAccessDenied status.Code = iota +) + +const ( + // detailAccessDeniedDesc is a StatusAccessDenied detail ID for + // human-readable description. + detailAccessDeniedDesc = iota +) + +// WriteAccessDeniedDesc writes human-readable description of StatusAccessDenied +// into status.Status as a detail. The status must not be nil. +// +// Existing details are expected to be ID-unique, otherwise undefined behavior. +func WriteAccessDeniedDesc(st *status.Status, desc string) { + var found bool + + st.IterateDetails(func(d *status.Detail) bool { + if d.ID() == detailAccessDeniedDesc { + found = true + d.SetValue([]byte(desc)) + } + + return found + }) + + if !found { + var d status.Detail + + d.SetID(detailAccessDeniedDesc) + d.SetValue([]byte(desc)) + + st.AppendDetails(d) + } +} + +// ReadAccessDeniedDesc looks up for status detail with human-readable description +// of StatusAccessDenied. Returns empty string if detail is missing. +func ReadAccessDeniedDesc(st status.Status) (desc string) { + st.IterateDetails(func(d *status.Detail) bool { + if d.ID() == detailAccessDeniedDesc { + desc = string(d.Value()) + return true + } + + return false + }) + + return +} diff --git a/api/apemanager/status_test.go b/api/apemanager/status_test.go new file mode 100644 index 0000000..af6cd66 --- /dev/null +++ b/api/apemanager/status_test.go @@ -0,0 +1,30 @@ +package apemanager_test + +import ( + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/apemanager" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/status" + statustest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/status/test" + "github.com/stretchr/testify/require" +) + +func TestStatusCodes(t *testing.T) { + statustest.TestCodes(t, apemanager.LocalizeFailStatus, apemanager.GlobalizeFail, + apemanager.StatusAPEManagerAccessDenied, 5120, + ) +} + +func TestAccessDeniedDesc(t *testing.T) { + var st status.Status + + require.Empty(t, apemanager.ReadAccessDeniedDesc(st)) + + const desc = "some description" + + apemanager.WriteAccessDeniedDesc(&st, desc) + require.Equal(t, desc, apemanager.ReadAccessDeniedDesc(st)) + + apemanager.WriteAccessDeniedDesc(&st, desc+"1") + require.Equal(t, desc+"1", apemanager.ReadAccessDeniedDesc(st)) +} diff --git a/api/apemanager/test/generate.go b/api/apemanager/test/generate.go new file mode 100644 index 0000000..47427d7 --- /dev/null +++ b/api/apemanager/test/generate.go @@ -0,0 +1,143 @@ +package apemanagertest + +import ( + apetest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/ape/test" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/apemanager" + sessiontest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session/test" +) + +func generateChainID(empty bool) []byte { + if empty { + return []byte{} + } + + return []byte("616c6c6f774f626a476574436e72") +} + +func GenerateAddChainRequestBody(empty bool) *apemanager.AddChainRequestBody { + m := new(apemanager.AddChainRequestBody) + + if !empty { + m.SetTarget(apetest.GenerateChainTarget(empty)) + m.SetChain(apetest.GenerateRawChain(empty)) + } + + return m +} + +func GenerateAddChainRequest(empty bool) *apemanager.AddChainRequest { + m := new(apemanager.AddChainRequest) + + if !empty { + m.SetBody(GenerateAddChainRequestBody(empty)) + m.SetMetaHeader(sessiontest.GenerateRequestMetaHeader(empty)) + m.SetVerificationHeader(sessiontest.GenerateRequestVerificationHeader(empty)) + } + + return m +} + +func GenerateAddChainResponseBody(empty bool) *apemanager.AddChainResponseBody { + m := new(apemanager.AddChainResponseBody) + + if !empty { + m.SetChainID(generateChainID(empty)) + } + + return m +} + +func GenerateAddChainResponse(empty bool) *apemanager.AddChainResponse { + m := new(apemanager.AddChainResponse) + + if !empty { + m.SetBody(GenerateAddChainResponseBody(empty)) + m.SetMetaHeader(sessiontest.GenerateResponseMetaHeader(empty)) + m.SetVerificationHeader(sessiontest.GenerateResponseVerificationHeader(empty)) + } + + return m +} + +func GenerateRemoveChainRequestBody(empty bool) *apemanager.RemoveChainRequestBody { + m := new(apemanager.RemoveChainRequestBody) + + if !empty { + m.SetChainID(generateChainID(empty)) + m.SetTarget(apetest.GenerateChainTarget(empty)) + } + + return m +} + +func GenerateRemoveChainRequest(empty bool) *apemanager.RemoveChainRequest { + m := new(apemanager.RemoveChainRequest) + + if !empty { + m.SetBody(GenerateRemoveChainRequestBody(empty)) + m.SetMetaHeader(sessiontest.GenerateRequestMetaHeader(empty)) + m.SetVerificationHeader(sessiontest.GenerateRequestVerificationHeader(empty)) + } + + return m +} + +func GenerateRemoveChainResponseBody(_ bool) *apemanager.RemoveChainResponseBody { + return new(apemanager.RemoveChainResponseBody) +} + +func GenerateRemoveChainResponse(empty bool) *apemanager.RemoveChainResponse { + m := new(apemanager.RemoveChainResponse) + + if !empty { + m.SetBody(GenerateRemoveChainResponseBody(empty)) + m.SetMetaHeader(sessiontest.GenerateResponseMetaHeader(empty)) + m.SetVerificationHeader(sessiontest.GenerateResponseVerificationHeader(empty)) + } + + return m +} + +func GenerateListChainsRequestBody(empty bool) *apemanager.ListChainsRequestBody { + m := new(apemanager.ListChainsRequestBody) + + if !empty { + m.SetTarget(apetest.GenerateChainTarget(empty)) + } + + return m +} + +func GenerateListChainsRequest(empty bool) *apemanager.ListChainsRequest { + m := new(apemanager.ListChainsRequest) + + if !empty { + m.SetBody(GenerateListChainsRequestBody(empty)) + m.SetMetaHeader(sessiontest.GenerateRequestMetaHeader(empty)) + m.SetVerificationHeader(sessiontest.GenerateRequestVerificationHeader(empty)) + } + + return m +} + +func GenerateListChainsResponseBody(empty bool) *apemanager.ListChainsResponseBody { + m := new(apemanager.ListChainsResponseBody) + + if !empty { + m.SetChains(apetest.GenerateRawChains(empty, 10)) + } + + return m +} + +func GenerateListChainsResponse(empty bool) *apemanager.ListChainsResponse { + m := new(apemanager.ListChainsResponse) + + if !empty { + m.SetBody(GenerateListChainsResponseBody(empty)) + m.SetMetaHeader(sessiontest.GenerateResponseMetaHeader(empty)) + m.SetVerificationHeader(sessiontest.GenerateResponseVerificationHeader(empty)) + } + + return m +} diff --git a/api/apemanager/types.go b/api/apemanager/types.go new file mode 100644 index 0000000..077488b --- /dev/null +++ b/api/apemanager/types.go @@ -0,0 +1,226 @@ +package apemanager + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/ape" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" +) + +type AddChainRequest struct { + body *AddChainRequestBody + + session.RequestHeaders +} + +func (r *AddChainRequest) SetBody(body *AddChainRequestBody) { + r.body = body +} + +func (r *AddChainRequest) GetBody() *AddChainRequestBody { + if r == nil { + return nil + } + + return r.body +} + +type AddChainRequestBody struct { + target *ape.ChainTarget + + chain *ape.Chain +} + +func (rb *AddChainRequestBody) SetTarget(target *ape.ChainTarget) { + rb.target = target +} + +func (rb *AddChainRequestBody) GetTarget() *ape.ChainTarget { + if rb == nil { + return nil + } + + return rb.target +} + +func (rb *AddChainRequestBody) SetChain(chain *ape.Chain) { + rb.chain = chain +} + +func (rb *AddChainRequestBody) GetChain() *ape.Chain { + if rb == nil { + return nil + } + + return rb.chain +} + +type AddChainResponse struct { + body *AddChainResponseBody + + session.ResponseHeaders +} + +func (r *AddChainResponse) SetBody(body *AddChainResponseBody) { + r.body = body +} + +func (r *AddChainResponse) GetBody() *AddChainResponseBody { + if r == nil { + return nil + } + + return r.body +} + +type AddChainResponseBody struct { + chainID []byte +} + +func (rb *AddChainResponseBody) SetChainID(chainID []byte) { + rb.chainID = chainID +} + +func (rb *AddChainResponseBody) GetChainID() []byte { + if rb == nil { + return nil + } + + return rb.chainID +} + +type RemoveChainRequest struct { + body *RemoveChainRequestBody + + session.RequestHeaders +} + +func (r *RemoveChainRequest) SetBody(body *RemoveChainRequestBody) { + r.body = body +} + +func (r *RemoveChainRequest) GetBody() *RemoveChainRequestBody { + if r == nil { + return nil + } + + return r.body +} + +type RemoveChainRequestBody struct { + target *ape.ChainTarget + + chainID []byte +} + +func (rb *RemoveChainRequestBody) SetTarget(target *ape.ChainTarget) { + rb.target = target +} + +func (rb *RemoveChainRequestBody) GetTarget() *ape.ChainTarget { + if rb == nil { + return nil + } + + return rb.target +} + +func (rb *RemoveChainRequestBody) SetChainID(chainID []byte) { + rb.chainID = chainID +} + +func (rb *RemoveChainRequestBody) GetChainID() []byte { + if rb == nil { + return nil + } + + return rb.chainID +} + +type RemoveChainResponse struct { + body *RemoveChainResponseBody + + session.ResponseHeaders +} + +type RemoveChainResponseBody struct{} + +func (r *RemoveChainResponse) SetBody(body *RemoveChainResponseBody) { + r.body = body +} + +func (r *RemoveChainResponse) GetBody() *RemoveChainResponseBody { + if r == nil { + return nil + } + + return r.body +} + +type ListChainsRequest struct { + body *ListChainsRequestBody + + session.RequestHeaders +} + +func (r *ListChainsRequest) SetBody(body *ListChainsRequestBody) { + r.body = body +} + +func (r *ListChainsRequest) GetBody() *ListChainsRequestBody { + if r == nil { + return nil + } + + return r.body +} + +type ListChainsRequestBody struct { + target *ape.ChainTarget +} + +func (rb *ListChainsRequestBody) SetTarget(target *ape.ChainTarget) { + rb.target = target +} + +func (rb *ListChainsRequestBody) GetTarget() *ape.ChainTarget { + if rb == nil { + return nil + } + + return rb.target +} + +type ListChainsResponse struct { + body *ListChainsResponseBody + + session.ResponseHeaders +} + +func (r *ListChainsResponse) SetBody(body *ListChainsResponseBody) { + r.body = body +} + +func (r *ListChainsResponse) GetBody() *ListChainsResponseBody { + if r == nil { + return nil + } + + return r.body +} + +type ListChainsResponseBody struct { + chains []*ape.Chain + + session.RequestHeaders +} + +func (r *ListChainsResponseBody) SetChains(chains []*ape.Chain) { + r.chains = chains +} + +func (r *ListChainsResponseBody) GetChains() []*ape.Chain { + if r == nil { + return nil + } + + return r.chains +} diff --git a/api/container/attributes.go b/api/container/attributes.go new file mode 100644 index 0000000..288d048 --- /dev/null +++ b/api/container/attributes.go @@ -0,0 +1,90 @@ +package container + +// SysAttributePrefix is a prefix of key to system attribute. +const SysAttributePrefix = "__SYSTEM__" + +const ( + // SysAttributeName is a string of human-friendly container name registered as the domain in NNS contract. + SysAttributeName = SysAttributePrefix + "NAME" + + // SysAttributeZone is a string of zone for container name. + SysAttributeZone = SysAttributePrefix + "ZONE" + + // SysAttributeHomomorphicHashing is a container's homomorphic hashing state. + SysAttributeHomomorphicHashing = SysAttributePrefix + "DISABLE_HOMOMORPHIC_HASHING" +) + +// SysAttributePrefixNeoFS is a prefix of key to system attribute. +// Deprecated: use SysAttributePrefix. +const SysAttributePrefixNeoFS = "__NEOFS__" + +const ( + // SysAttributeNameNeoFS is a string of human-friendly container name registered as the domain in NNS contract. + // Deprecated: use SysAttributeName. + SysAttributeNameNeoFS = SysAttributePrefixNeoFS + "NAME" + + // SysAttributeZoneNeoFS is a string of zone for container name. + // Deprecated: use SysAttributeZone. + SysAttributeZoneNeoFS = SysAttributePrefixNeoFS + "ZONE" + + // SysAttributeHomomorphicHashingNeoFS is a container's homomorphic hashing state. + // Deprecated: use SysAttributeHomomorphicHashing. + SysAttributeHomomorphicHashingNeoFS = SysAttributePrefixNeoFS + "DISABLE_HOMOMORPHIC_HASHING" +) + +// SysAttributeZoneDefault is a default value for SysAttributeZone attribute. +const SysAttributeZoneDefault = "container" + +const disabledHomomorphicHashingValue = "true" + +// HomomorphicHashingState returns container's homomorphic +// hashing state: +// - true if hashing is enabled; +// - false if hashing is disabled. +// +// All container's attributes must be unique, otherwise behavior +// is undefined. +// +// See also SetHomomorphicHashingState. +func (c Container) HomomorphicHashingState() bool { + for i := range c.attr { + if c.attr[i].GetKey() == SysAttributeHomomorphicHashing || c.attr[i].GetKey() == SysAttributeHomomorphicHashingNeoFS { + return c.attr[i].GetValue() != disabledHomomorphicHashingValue + } + } + + return true +} + +// SetHomomorphicHashingState sets homomorphic hashing state for +// container. +// +// All container's attributes must be unique, otherwise behavior +// is undefined. +// +// See also HomomorphicHashingState. +func (c *Container) SetHomomorphicHashingState(enable bool) { + for i := range c.attr { + if c.attr[i].GetKey() == SysAttributeHomomorphicHashing || c.attr[i].GetKey() == SysAttributeHomomorphicHashingNeoFS { + if enable { + // approach without allocation/waste + // coping works since the attributes + // order is not important + c.attr[i] = c.attr[len(c.attr)-1] + c.attr = c.attr[:len(c.attr)-1] + } else { + c.attr[i].SetValue(disabledHomomorphicHashingValue) + } + + return + } + } + + if !enable { + attr := Attribute{} + attr.SetKey(SysAttributeHomomorphicHashing) + attr.SetValue(disabledHomomorphicHashingValue) + + c.attr = append(c.attr, attr) + } +} diff --git a/api/container/attributes_test.go b/api/container/attributes_test.go new file mode 100644 index 0000000..2b00d33 --- /dev/null +++ b/api/container/attributes_test.go @@ -0,0 +1,59 @@ +package container_test + +import ( + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/container" + containertest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/container/test" + "github.com/stretchr/testify/require" +) + +func TestContainer_HomomorphicHashingDisabled(t *testing.T) { + cnr := containertest.GenerateContainer(false) + + t.Run("defaults", func(t *testing.T) { + require.True(t, cnr.HomomorphicHashingState()) + }) + + t.Run("disabled", func(t *testing.T) { + attr := container.Attribute{} + attr.SetKey(container.SysAttributeHomomorphicHashing) + attr.SetValue("NOT_true") + + cnr.SetAttributes(append(cnr.GetAttributes(), attr)) + require.True(t, cnr.HomomorphicHashingState()) + + attr.SetValue("true") + + cnr.SetAttributes([]container.Attribute{attr}) + require.False(t, cnr.HomomorphicHashingState()) + }) +} + +func TestContainer_SetHomomorphicHashingState(t *testing.T) { + cnr := containertest.GenerateContainer(false) + attrs := cnr.GetAttributes() + attrLen := len(attrs) + + cnr.SetHomomorphicHashingState(true) + + // enabling hashing should not add any new attributes + require.Equal(t, attrLen, len(cnr.GetAttributes())) + require.True(t, cnr.HomomorphicHashingState()) + + cnr.SetHomomorphicHashingState(false) + + // disabling hashing should add exactly one attribute + require.Equal(t, attrLen+1, len(cnr.GetAttributes())) + require.False(t, cnr.HomomorphicHashingState()) + + cnr.SetHomomorphicHashingState(true) + + // enabling hashing should remove 1 attribute if + // hashing was disabled before + require.Equal(t, attrLen, len(cnr.GetAttributes())) + require.True(t, cnr.HomomorphicHashingState()) + + // hashing operations should not change any other attributes + require.ElementsMatch(t, attrs, cnr.GetAttributes()) +} diff --git a/api/container/convert.go b/api/container/convert.go new file mode 100644 index 0000000..c91bdfd --- /dev/null +++ b/api/container/convert.go @@ -0,0 +1,764 @@ +package container + +import ( + container "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/container/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/netmap" + netmapGRPC "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/netmap/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" + refsGRPC "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/message" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" + sessionGRPC "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session/grpc" +) + +func (a *Attribute) ToGRPCMessage() grpc.Message { + var m *container.Container_Attribute + + if a != nil { + m = new(container.Container_Attribute) + + m.SetKey(a.key) + m.SetValue(a.val) + } + + return m +} + +func (a *Attribute) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*container.Container_Attribute) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + a.key = v.GetKey() + a.val = v.GetValue() + + return nil +} + +func AttributesToGRPC(xs []Attribute) (res []container.Container_Attribute) { + if xs != nil { + res = make([]container.Container_Attribute, 0, len(xs)) + + for i := range xs { + res = append(res, *xs[i].ToGRPCMessage().(*container.Container_Attribute)) + } + } + + return +} + +func AttributesFromGRPC(xs []container.Container_Attribute) (res []Attribute, err error) { + if xs != nil { + res = make([]Attribute, len(xs)) + + for i := range xs { + err = res[i].FromGRPCMessage(&xs[i]) + if err != nil { + return + } + } + } + + return +} + +func (c *Container) ToGRPCMessage() grpc.Message { + var m *container.Container + + if c != nil { + m = new(container.Container) + + m.SetVersion(c.version.ToGRPCMessage().(*refsGRPC.Version)) + m.SetOwnerId(c.ownerID.ToGRPCMessage().(*refsGRPC.OwnerID)) + m.SetPlacementPolicy(c.policy.ToGRPCMessage().(*netmapGRPC.PlacementPolicy)) + m.SetAttributes(AttributesToGRPC(c.attr)) + m.SetBasicAcl(c.basicACL) + m.SetNonce(c.nonce) + } + + return m +} + +func (c *Container) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*container.Container) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + version := v.GetVersion() + if version == nil { + c.version = nil + } else { + if c.version == nil { + c.version = new(refs.Version) + } + + err = c.version.FromGRPCMessage(version) + if err != nil { + return err + } + } + + ownerID := v.GetOwnerId() + if ownerID == nil { + c.ownerID = nil + } else { + if c.ownerID == nil { + c.ownerID = new(refs.OwnerID) + } + + err = c.ownerID.FromGRPCMessage(ownerID) + if err != nil { + return err + } + } + + policy := v.GetPlacementPolicy() + if policy == nil { + c.policy = nil + } else { + if c.policy == nil { + c.policy = new(netmap.PlacementPolicy) + } + + err = c.policy.FromGRPCMessage(policy) + if err != nil { + return err + } + } + + c.attr, err = AttributesFromGRPC(v.GetAttributes()) + if err != nil { + return err + } + + c.basicACL = v.GetBasicAcl() + c.nonce = v.GetNonce() + + return nil +} + +func toSignatureRFC6979(s *refs.Signature) *refsGRPC.SignatureRFC6979 { + var res *refsGRPC.SignatureRFC6979 + + if s != nil { + res = new(refsGRPC.SignatureRFC6979) + res.SetKey(s.GetKey()) + res.SetSign(s.GetSign()) + } + + return res +} + +func (r *PutRequestBody) ToGRPCMessage() grpc.Message { + var m *container.PutRequest_Body + + if r != nil { + m = new(container.PutRequest_Body) + + m.SetContainer(r.cnr.ToGRPCMessage().(*container.Container)) + m.SetSignature(toSignatureRFC6979(r.sig)) + } + + return m +} + +func (r *PutRequestBody) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*container.PutRequest_Body) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + cnr := v.GetContainer() + if cnr == nil { + r.cnr = nil + } else { + if r.cnr == nil { + r.cnr = new(Container) + } + + err = r.cnr.FromGRPCMessage(cnr) + if err != nil { + return err + } + } + + sig := v.GetSignature() + if sig == nil { + r.sig = nil + } else { + if r.sig == nil { + r.sig = new(refs.Signature) + } + + r.sig.SetKey(sig.GetKey()) + r.sig.SetSign(sig.GetSign()) + } + + return err +} + +func (r *PutRequest) ToGRPCMessage() grpc.Message { + var m *container.PutRequest + + if r != nil { + m = new(container.PutRequest) + + m.SetBody(r.body.ToGRPCMessage().(*container.PutRequest_Body)) + r.RequestHeaders.ToMessage(m) + } + + return m +} + +func (r *PutRequest) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*container.PutRequest) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + body := v.GetBody() + if body == nil { + r.body = nil + } else { + if r.body == nil { + r.body = new(PutRequestBody) + } + + err = r.body.FromGRPCMessage(body) + if err != nil { + return err + } + } + + return r.RequestHeaders.FromMessage(v) +} + +func (r *PutResponseBody) ToGRPCMessage() grpc.Message { + var m *container.PutResponse_Body + + if r != nil { + m = new(container.PutResponse_Body) + + m.SetContainerId(r.cid.ToGRPCMessage().(*refsGRPC.ContainerID)) + } + + return m +} + +func (r *PutResponseBody) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*container.PutResponse_Body) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + cid := v.GetContainerId() + if cid == nil { + r.cid = nil + } else { + if r.cid == nil { + r.cid = new(refs.ContainerID) + } + + err = r.cid.FromGRPCMessage(cid) + } + + return err +} + +func (r *PutResponse) ToGRPCMessage() grpc.Message { + var m *container.PutResponse + + if r != nil { + m = new(container.PutResponse) + + m.SetBody(r.body.ToGRPCMessage().(*container.PutResponse_Body)) + r.ResponseHeaders.ToMessage(m) + } + + return m +} + +func (r *PutResponse) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*container.PutResponse) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + body := v.GetBody() + if body == nil { + r.body = nil + } else { + if r.body == nil { + r.body = new(PutResponseBody) + } + + err = r.body.FromGRPCMessage(body) + if err != nil { + return err + } + } + + return r.ResponseHeaders.FromMessage(v) +} + +func (r *GetRequestBody) ToGRPCMessage() grpc.Message { + var m *container.GetRequest_Body + + if r != nil { + m = new(container.GetRequest_Body) + + m.SetContainerId(r.cid.ToGRPCMessage().(*refsGRPC.ContainerID)) + } + + return m +} + +func (r *GetRequestBody) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*container.GetRequest_Body) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + cid := v.GetContainerId() + if cid == nil { + r.cid = nil + } else { + if r.cid == nil { + r.cid = new(refs.ContainerID) + } + + err = r.cid.FromGRPCMessage(cid) + } + + return err +} + +func (r *GetRequest) ToGRPCMessage() grpc.Message { + var m *container.GetRequest + + if r != nil { + m = new(container.GetRequest) + + m.SetBody(r.body.ToGRPCMessage().(*container.GetRequest_Body)) + r.RequestHeaders.ToMessage(m) + } + + return m +} + +func (r *GetRequest) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*container.GetRequest) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + body := v.GetBody() + if body == nil { + r.body = nil + } else { + if r.body == nil { + r.body = new(GetRequestBody) + } + + err = r.body.FromGRPCMessage(body) + if err != nil { + return err + } + } + + return r.RequestHeaders.FromMessage(v) +} + +func (r *GetResponseBody) ToGRPCMessage() grpc.Message { + var m *container.GetResponse_Body + + if r != nil { + m = new(container.GetResponse_Body) + + m.SetContainer(r.cnr.ToGRPCMessage().(*container.Container)) + m.SetSessionToken(r.token.ToGRPCMessage().(*sessionGRPC.SessionToken)) + m.SetSignature(toSignatureRFC6979(r.sig)) + } + + return m +} + +func (r *GetResponseBody) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*container.GetResponse_Body) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + cnr := v.GetContainer() + if cnr == nil { + r.cnr = nil + } else { + if r.cnr == nil { + r.cnr = new(Container) + } + + err = r.cnr.FromGRPCMessage(cnr) + } + + sig := v.GetSignature() + if sig == nil { + r.sig = nil + } else { + if r.sig == nil { + r.sig = new(refs.Signature) + } + + r.sig.SetKey(sig.GetKey()) + r.sig.SetSign(sig.GetSign()) + } + + token := v.GetSessionToken() + if token == nil { + r.token = nil + } else { + if r.token == nil { + r.token = new(session.Token) + } + + err = r.token.FromGRPCMessage(token) + } + + return err +} + +func (r *GetResponse) ToGRPCMessage() grpc.Message { + var m *container.GetResponse + + if r != nil { + m = new(container.GetResponse) + + m.SetBody(r.body.ToGRPCMessage().(*container.GetResponse_Body)) + r.ResponseHeaders.ToMessage(m) + } + + return m +} + +func (r *GetResponse) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*container.GetResponse) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + body := v.GetBody() + if body == nil { + r.body = nil + } else { + if r.body == nil { + r.body = new(GetResponseBody) + } + + err = r.body.FromGRPCMessage(body) + if err != nil { + return err + } + } + + return r.ResponseHeaders.FromMessage(v) +} + +func (r *DeleteRequestBody) ToGRPCMessage() grpc.Message { + var m *container.DeleteRequest_Body + + if r != nil { + m = new(container.DeleteRequest_Body) + + m.SetContainerId(r.cid.ToGRPCMessage().(*refsGRPC.ContainerID)) + m.SetSignature(toSignatureRFC6979(r.sig)) + } + + return m +} + +func (r *DeleteRequestBody) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*container.DeleteRequest_Body) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + cid := v.GetContainerId() + if cid == nil { + r.cid = nil + } else { + if r.cid == nil { + r.cid = new(refs.ContainerID) + } + + err = r.cid.FromGRPCMessage(cid) + if err != nil { + return err + } + } + + sig := v.GetSignature() + if sig == nil { + r.sig = nil + } else { + if r.sig == nil { + r.sig = new(refs.Signature) + } + + r.sig.SetKey(sig.GetKey()) + r.sig.SetSign(sig.GetSign()) + } + + return err +} + +func (r *DeleteRequest) ToGRPCMessage() grpc.Message { + var m *container.DeleteRequest + + if r != nil { + m = new(container.DeleteRequest) + + m.SetBody(r.body.ToGRPCMessage().(*container.DeleteRequest_Body)) + r.RequestHeaders.ToMessage(m) + } + + return m +} + +func (r *DeleteRequest) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*container.DeleteRequest) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + body := v.GetBody() + if body == nil { + r.body = nil + } else { + if r.body == nil { + r.body = new(DeleteRequestBody) + } + + err = r.body.FromGRPCMessage(body) + if err != nil { + return err + } + } + + return r.RequestHeaders.FromMessage(v) +} + +func (r *DeleteResponseBody) ToGRPCMessage() grpc.Message { + var m *container.DeleteResponse_Body + + if r != nil { + m = new(container.DeleteResponse_Body) + } + + return m +} + +func (r *DeleteResponseBody) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*container.DeleteResponse_Body) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + return nil +} + +func (r *DeleteResponse) ToGRPCMessage() grpc.Message { + var m *container.DeleteResponse + + if r != nil { + m = new(container.DeleteResponse) + + m.SetBody(r.body.ToGRPCMessage().(*container.DeleteResponse_Body)) + r.ResponseHeaders.ToMessage(m) + } + + return m +} + +func (r *DeleteResponse) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*container.DeleteResponse) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + body := v.GetBody() + if body == nil { + r.body = nil + } else { + if r.body == nil { + r.body = new(DeleteResponseBody) + } + + err = r.body.FromGRPCMessage(body) + if err != nil { + return err + } + } + + return r.ResponseHeaders.FromMessage(v) +} + +func (r *ListRequestBody) ToGRPCMessage() grpc.Message { + var m *container.ListRequest_Body + + if r != nil { + m = new(container.ListRequest_Body) + + m.SetOwnerId(r.ownerID.ToGRPCMessage().(*refsGRPC.OwnerID)) + } + + return m +} + +func (r *ListRequestBody) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*container.ListRequest_Body) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + ownerID := v.GetOwnerId() + if ownerID == nil { + r.ownerID = nil + } else { + if r.ownerID == nil { + r.ownerID = new(refs.OwnerID) + } + + err = r.ownerID.FromGRPCMessage(ownerID) + } + + return err +} + +func (r *ListRequest) ToGRPCMessage() grpc.Message { + var m *container.ListRequest + + if r != nil { + m = new(container.ListRequest) + + m.SetBody(r.body.ToGRPCMessage().(*container.ListRequest_Body)) + r.RequestHeaders.ToMessage(m) + } + + return m +} + +func (r *ListRequest) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*container.ListRequest) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + body := v.GetBody() + if body == nil { + r.body = nil + } else { + if r.body == nil { + r.body = new(ListRequestBody) + } + + err = r.body.FromGRPCMessage(body) + if err != nil { + return err + } + } + + return r.RequestHeaders.FromMessage(v) +} + +func (r *ListResponseBody) ToGRPCMessage() grpc.Message { + var m *container.ListResponse_Body + + if r != nil { + m = new(container.ListResponse_Body) + + m.SetContainerIds(refs.ContainerIDsToGRPCMessage(r.cidList)) + } + + return m +} + +func (r *ListResponseBody) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*container.ListResponse_Body) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + r.cidList, err = refs.ContainerIDsFromGRPCMessage(v.GetContainerIds()) + + return err +} + +func (r *ListResponse) ToGRPCMessage() grpc.Message { + var m *container.ListResponse + + if r != nil { + m = new(container.ListResponse) + + m.SetBody(r.body.ToGRPCMessage().(*container.ListResponse_Body)) + r.ResponseHeaders.ToMessage(m) + } + + return m +} + +func (r *ListResponse) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*container.ListResponse) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + body := v.GetBody() + if body == nil { + r.body = nil + } else { + if r.body == nil { + r.body = new(ListResponseBody) + } + + err = r.body.FromGRPCMessage(body) + if err != nil { + return err + } + } + + return r.ResponseHeaders.FromMessage(v) +} diff --git a/api/container/grpc/service_frostfs.pb.go b/api/container/grpc/service_frostfs.pb.go new file mode 100644 index 0000000000000000000000000000000000000000..07438240cec6d58629892f69a6f99c4f93142bbd GIT binary patch literal 76792 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 literal 0 HcmV?d00001 diff --git a/api/container/grpc/service_frostfs_fuzz.go b/api/container/grpc/service_frostfs_fuzz.go new file mode 100644 index 0000000..7e6d6e6 --- /dev/null +++ b/api/container/grpc/service_frostfs_fuzz.go @@ -0,0 +1,159 @@ +//go:build gofuzz +// +build gofuzz + +// Code generated by protoc-gen-go-frostfs. DO NOT EDIT. + +package container + +func DoFuzzProtoPutRequest(data []byte) int { + msg := new(PutRequest) + if err := msg.UnmarshalProtobuf(data); err != nil { + return 0 + } + _ = msg.MarshalProtobuf(nil) + return 1 +} +func DoFuzzJSONPutRequest(data []byte) int { + msg := new(PutRequest) + if err := msg.UnmarshalJSON(data); err != nil { + return 0 + } + _, err := msg.MarshalJSON() + if err != nil { + panic(err) + } + return 1 +} +func DoFuzzProtoPutResponse(data []byte) int { + msg := new(PutResponse) + if err := msg.UnmarshalProtobuf(data); err != nil { + return 0 + } + _ = msg.MarshalProtobuf(nil) + return 1 +} +func DoFuzzJSONPutResponse(data []byte) int { + msg := new(PutResponse) + if err := msg.UnmarshalJSON(data); err != nil { + return 0 + } + _, err := msg.MarshalJSON() + if err != nil { + panic(err) + } + return 1 +} +func DoFuzzProtoDeleteRequest(data []byte) int { + msg := new(DeleteRequest) + if err := msg.UnmarshalProtobuf(data); err != nil { + return 0 + } + _ = msg.MarshalProtobuf(nil) + return 1 +} +func DoFuzzJSONDeleteRequest(data []byte) int { + msg := new(DeleteRequest) + if err := msg.UnmarshalJSON(data); err != nil { + return 0 + } + _, err := msg.MarshalJSON() + if err != nil { + panic(err) + } + return 1 +} +func DoFuzzProtoDeleteResponse(data []byte) int { + msg := new(DeleteResponse) + if err := msg.UnmarshalProtobuf(data); err != nil { + return 0 + } + _ = msg.MarshalProtobuf(nil) + return 1 +} +func DoFuzzJSONDeleteResponse(data []byte) int { + msg := new(DeleteResponse) + if err := msg.UnmarshalJSON(data); err != nil { + return 0 + } + _, err := msg.MarshalJSON() + if err != nil { + panic(err) + } + return 1 +} +func DoFuzzProtoGetRequest(data []byte) int { + msg := new(GetRequest) + if err := msg.UnmarshalProtobuf(data); err != nil { + return 0 + } + _ = msg.MarshalProtobuf(nil) + return 1 +} +func DoFuzzJSONGetRequest(data []byte) int { + msg := new(GetRequest) + if err := msg.UnmarshalJSON(data); err != nil { + return 0 + } + _, err := msg.MarshalJSON() + if err != nil { + panic(err) + } + return 1 +} +func DoFuzzProtoGetResponse(data []byte) int { + msg := new(GetResponse) + if err := msg.UnmarshalProtobuf(data); err != nil { + return 0 + } + _ = msg.MarshalProtobuf(nil) + return 1 +} +func DoFuzzJSONGetResponse(data []byte) int { + msg := new(GetResponse) + if err := msg.UnmarshalJSON(data); err != nil { + return 0 + } + _, err := msg.MarshalJSON() + if err != nil { + panic(err) + } + return 1 +} +func DoFuzzProtoListRequest(data []byte) int { + msg := new(ListRequest) + if err := msg.UnmarshalProtobuf(data); err != nil { + return 0 + } + _ = msg.MarshalProtobuf(nil) + return 1 +} +func DoFuzzJSONListRequest(data []byte) int { + msg := new(ListRequest) + if err := msg.UnmarshalJSON(data); err != nil { + return 0 + } + _, err := msg.MarshalJSON() + if err != nil { + panic(err) + } + return 1 +} +func DoFuzzProtoListResponse(data []byte) int { + msg := new(ListResponse) + if err := msg.UnmarshalProtobuf(data); err != nil { + return 0 + } + _ = msg.MarshalProtobuf(nil) + return 1 +} +func DoFuzzJSONListResponse(data []byte) int { + msg := new(ListResponse) + if err := msg.UnmarshalJSON(data); err != nil { + return 0 + } + _, err := msg.MarshalJSON() + if err != nil { + panic(err) + } + return 1 +} diff --git a/api/container/grpc/service_frostfs_test.go b/api/container/grpc/service_frostfs_test.go new file mode 100644 index 0000000..804b89c --- /dev/null +++ b/api/container/grpc/service_frostfs_test.go @@ -0,0 +1,91 @@ +//go:build gofuzz +// +build gofuzz + +// Code generated by protoc-gen-go-frostfs. DO NOT EDIT. + +package container + +import ( + testing "testing" +) + +func FuzzProtoPutRequest(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzProtoPutRequest(data) + }) +} +func FuzzJSONPutRequest(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzJSONPutRequest(data) + }) +} +func FuzzProtoPutResponse(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzProtoPutResponse(data) + }) +} +func FuzzJSONPutResponse(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzJSONPutResponse(data) + }) +} +func FuzzProtoDeleteRequest(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzProtoDeleteRequest(data) + }) +} +func FuzzJSONDeleteRequest(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzJSONDeleteRequest(data) + }) +} +func FuzzProtoDeleteResponse(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzProtoDeleteResponse(data) + }) +} +func FuzzJSONDeleteResponse(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzJSONDeleteResponse(data) + }) +} +func FuzzProtoGetRequest(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzProtoGetRequest(data) + }) +} +func FuzzJSONGetRequest(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzJSONGetRequest(data) + }) +} +func FuzzProtoGetResponse(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzProtoGetResponse(data) + }) +} +func FuzzJSONGetResponse(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzJSONGetResponse(data) + }) +} +func FuzzProtoListRequest(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzProtoListRequest(data) + }) +} +func FuzzJSONListRequest(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzJSONListRequest(data) + }) +} +func FuzzProtoListResponse(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzProtoListResponse(data) + }) +} +func FuzzJSONListResponse(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzJSONListResponse(data) + }) +} diff --git a/api/container/grpc/service_grpc.pb.go b/api/container/grpc/service_grpc.pb.go new file mode 100644 index 0000000000000000000000000000000000000000..ea226043cebeb4a455708b9ae7f0e130a350a898 GIT binary patch literal 11737 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 DhTZCW literal 0 HcmV?d00001 diff --git a/api/container/grpc/types_frostfs_fuzz.go b/api/container/grpc/types_frostfs_fuzz.go new file mode 100644 index 0000000..5551978 --- /dev/null +++ b/api/container/grpc/types_frostfs_fuzz.go @@ -0,0 +1,26 @@ +//go:build gofuzz +// +build gofuzz + +// Code generated by protoc-gen-go-frostfs. DO NOT EDIT. + +package container + +func DoFuzzProtoContainer(data []byte) int { + msg := new(Container) + if err := msg.UnmarshalProtobuf(data); err != nil { + return 0 + } + _ = msg.MarshalProtobuf(nil) + return 1 +} +func DoFuzzJSONContainer(data []byte) int { + msg := new(Container) + if err := msg.UnmarshalJSON(data); err != nil { + return 0 + } + _, err := msg.MarshalJSON() + if err != nil { + panic(err) + } + return 1 +} diff --git a/api/container/grpc/types_frostfs_test.go b/api/container/grpc/types_frostfs_test.go new file mode 100644 index 0000000..64d840e --- /dev/null +++ b/api/container/grpc/types_frostfs_test.go @@ -0,0 +1,21 @@ +//go:build gofuzz +// +build gofuzz + +// Code generated by protoc-gen-go-frostfs. DO NOT EDIT. + +package container + +import ( + testing "testing" +) + +func FuzzProtoContainer(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzProtoContainer(data) + }) +} +func FuzzJSONContainer(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzJSONContainer(data) + }) +} diff --git a/api/container/json.go b/api/container/json.go new file mode 100644 index 0000000..838fb8d --- /dev/null +++ b/api/container/json.go @@ -0,0 +1,22 @@ +package container + +import ( + container "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/container/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/message" +) + +func (a *Attribute) MarshalJSON() ([]byte, error) { + return message.MarshalJSON(a) +} + +func (a *Attribute) UnmarshalJSON(data []byte) error { + return message.UnmarshalJSON(a, data, new(container.Container_Attribute)) +} + +func (c *Container) MarshalJSON() ([]byte, error) { + return message.MarshalJSON(c) +} + +func (c *Container) UnmarshalJSON(data []byte) error { + return message.UnmarshalJSON(c, data, new(container.Container)) +} diff --git a/api/container/marshal.go b/api/container/marshal.go new file mode 100644 index 0000000..2b16669 --- /dev/null +++ b/api/container/marshal.go @@ -0,0 +1,345 @@ +package container + +import ( + container "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/container/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/message" + protoutil "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/util/proto" +) + +const ( + attributeKeyField = 1 + attributeValueField = 2 + + containerVersionField = 1 + containerOwnerField = 2 + containerNonceField = 3 + containerBasicACLField = 4 + containerAttributesField = 5 + containerPlacementField = 6 + + putReqBodyContainerField = 1 + putReqBodySignatureField = 2 + + putRespBodyIDField = 1 + + deleteReqBodyIDField = 1 + deleteReqBodySignatureField = 2 + + getReqBodyIDField = 1 + + getRespBodyContainerField = 1 + getRespBodySignatureField = 2 + getRespBodyTokenField = 3 + + listReqBodyOwnerField = 1 + + listRespBodyIDsField = 1 +) + +func (a *Attribute) StableMarshal(buf []byte) []byte { + if a == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, a.StableSize()) + } + + var offset int + + offset += protoutil.StringMarshal(attributeKeyField, buf[offset:], a.key) + protoutil.StringMarshal(attributeValueField, buf[offset:], a.val) + + return buf +} + +func (a *Attribute) StableSize() (size int) { + if a == nil { + return 0 + } + + size += protoutil.StringSize(attributeKeyField, a.key) + size += protoutil.StringSize(attributeValueField, a.val) + + return size +} + +func (a *Attribute) Unmarshal(data []byte) error { + return message.Unmarshal(a, data, new(container.Container_Attribute)) +} + +func (c *Container) StableMarshal(buf []byte) []byte { + if c == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, c.StableSize()) + } + + var offset int + + offset += protoutil.NestedStructureMarshal(containerVersionField, buf[offset:], c.version) + offset += protoutil.NestedStructureMarshal(containerOwnerField, buf[offset:], c.ownerID) + offset += protoutil.BytesMarshal(containerNonceField, buf[offset:], c.nonce) + offset += protoutil.UInt32Marshal(containerBasicACLField, buf[offset:], c.basicACL) + + for i := range c.attr { + offset += protoutil.NestedStructureMarshal(containerAttributesField, buf[offset:], &c.attr[i]) + } + + protoutil.NestedStructureMarshal(containerPlacementField, buf[offset:], c.policy) + + return buf +} + +func (c *Container) StableSize() (size int) { + if c == nil { + return 0 + } + + size += protoutil.NestedStructureSize(containerVersionField, c.version) + size += protoutil.NestedStructureSize(containerOwnerField, c.ownerID) + size += protoutil.BytesSize(containerNonceField, c.nonce) + size += protoutil.UInt32Size(containerBasicACLField, c.basicACL) + + for i := range c.attr { + size += protoutil.NestedStructureSize(containerAttributesField, &c.attr[i]) + } + + size += protoutil.NestedStructureSize(containerPlacementField, c.policy) + + return size +} + +func (c *Container) Unmarshal(data []byte) error { + return message.Unmarshal(c, data, new(container.Container)) +} + +func (r *PutRequestBody) StableMarshal(buf []byte) []byte { + if r == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, r.StableSize()) + } + + var offset int + + offset += protoutil.NestedStructureMarshal(putReqBodyContainerField, buf[offset:], r.cnr) + protoutil.NestedStructureMarshal(putReqBodySignatureField, buf[offset:], r.sig) + + return buf +} + +func (r *PutRequestBody) StableSize() (size int) { + if r == nil { + return 0 + } + + size += protoutil.NestedStructureSize(putReqBodyContainerField, r.cnr) + size += protoutil.NestedStructureSize(putReqBodySignatureField, r.sig) + + return size +} + +func (r *PutRequestBody) Unmarshal(data []byte) error { + return message.Unmarshal(r, data, new(container.PutRequest_Body)) +} + +func (r *PutResponseBody) StableMarshal(buf []byte) []byte { + if r == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, r.StableSize()) + } + + protoutil.NestedStructureMarshal(putRespBodyIDField, buf, r.cid) + + return buf +} + +func (r *PutResponseBody) StableSize() (size int) { + if r == nil { + return 0 + } + + size += protoutil.NestedStructureSize(putRespBodyIDField, r.cid) + + return size +} + +func (r *PutResponseBody) Unmarshal(data []byte) error { + return message.Unmarshal(r, data, new(container.PutResponse_Body)) +} + +func (r *DeleteRequestBody) StableMarshal(buf []byte) []byte { + if r == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, r.StableSize()) + } + + var offset int + + offset += protoutil.NestedStructureMarshal(deleteReqBodyIDField, buf[offset:], r.cid) + protoutil.NestedStructureMarshal(deleteReqBodySignatureField, buf[offset:], r.sig) + + return buf +} + +func (r *DeleteRequestBody) StableSize() (size int) { + if r == nil { + return 0 + } + + size += protoutil.NestedStructureSize(deleteReqBodyIDField, r.cid) + size += protoutil.NestedStructureSize(deleteReqBodySignatureField, r.sig) + + return size +} + +func (r *DeleteRequestBody) Unmarshal(data []byte) error { + return message.Unmarshal(r, data, new(container.DeleteRequest_Body)) +} + +func (r *DeleteResponseBody) StableMarshal(_ []byte) []byte { + return nil +} + +func (r *DeleteResponseBody) StableSize() (size int) { + return 0 +} + +func (r *DeleteResponseBody) Unmarshal([]byte) error { + return nil +} + +func (r *GetRequestBody) StableMarshal(buf []byte) []byte { + if r == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, r.StableSize()) + } + + protoutil.NestedStructureMarshal(getReqBodyIDField, buf, r.cid) + + return buf +} + +func (r *GetRequestBody) StableSize() (size int) { + if r == nil { + return 0 + } + + size += protoutil.NestedStructureSize(getReqBodyIDField, r.cid) + + return size +} + +func (r *GetRequestBody) Unmarshal(data []byte) error { + return message.Unmarshal(r, data, new(container.GetRequest_Body)) +} + +func (r *GetResponseBody) StableMarshal(buf []byte) []byte { + if r == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, r.StableSize()) + } + + var offset int + + offset += protoutil.NestedStructureMarshal(getRespBodyContainerField, buf, r.cnr) + offset += protoutil.NestedStructureMarshal(getRespBodySignatureField, buf[offset:], r.sig) + protoutil.NestedStructureMarshal(getRespBodyTokenField, buf[offset:], r.token) + + return buf +} + +func (r *GetResponseBody) StableSize() (size int) { + if r == nil { + return 0 + } + + size += protoutil.NestedStructureSize(getRespBodyContainerField, r.cnr) + size += protoutil.NestedStructureSize(getRespBodySignatureField, r.sig) + size += protoutil.NestedStructureSize(getRespBodyTokenField, r.token) + + return size +} + +func (r *GetResponseBody) Unmarshal(data []byte) error { + return message.Unmarshal(r, data, new(container.GetResponse_Body)) +} + +func (r *ListRequestBody) StableMarshal(buf []byte) []byte { + if r == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, r.StableSize()) + } + + protoutil.NestedStructureMarshal(listReqBodyOwnerField, buf, r.ownerID) + + return buf +} + +func (r *ListRequestBody) StableSize() (size int) { + if r == nil { + return 0 + } + + size += protoutil.NestedStructureSize(listReqBodyOwnerField, r.ownerID) + + return size +} + +func (r *ListRequestBody) Unmarshal(data []byte) error { + return message.Unmarshal(r, data, new(container.ListRequest_Body)) +} + +func (r *ListResponseBody) StableMarshal(buf []byte) []byte { + if r == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, r.StableSize()) + } + + var offset int + + for i := range r.cidList { + offset += protoutil.NestedStructureMarshal(listRespBodyIDsField, buf[offset:], &r.cidList[i]) + } + + return buf +} + +func (r *ListResponseBody) StableSize() (size int) { + if r == nil { + return 0 + } + + for i := range r.cidList { + size += protoutil.NestedStructureSize(listRespBodyIDsField, &r.cidList[i]) + } + + return size +} + +func (r *ListResponseBody) Unmarshal(data []byte) error { + return message.Unmarshal(r, data, new(container.ListResponse_Body)) +} diff --git a/api/container/message_test.go b/api/container/message_test.go new file mode 100644 index 0000000..b32475d --- /dev/null +++ b/api/container/message_test.go @@ -0,0 +1,36 @@ +package container_test + +import ( + "testing" + + containertest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/container/test" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/message" + messagetest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/message/test" +) + +func TestMessageConvert(t *testing.T) { + messagetest.TestRPCMessage(t, + func(empty bool) message.Message { return containertest.GenerateAttribute(empty) }, + func(empty bool) message.Message { return containertest.GenerateContainer(empty) }, + func(empty bool) message.Message { return containertest.GeneratePutRequestBody(empty) }, + func(empty bool) message.Message { return containertest.GeneratePutRequest(empty) }, + func(empty bool) message.Message { return containertest.GeneratePutResponseBody(empty) }, + func(empty bool) message.Message { return containertest.GeneratePutResponse(empty) }, + func(empty bool) message.Message { return containertest.GenerateGetRequestBody(empty) }, + func(empty bool) message.Message { return containertest.GenerateGetRequest(empty) }, + func(empty bool) message.Message { return containertest.GenerateGetResponseBody(empty) }, + func(empty bool) message.Message { return containertest.GenerateGetResponse(empty) }, + func(empty bool) message.Message { return containertest.GenerateDeleteRequestBody(empty) }, + func(empty bool) message.Message { return containertest.GenerateDeleteRequest(empty) }, + func(empty bool) message.Message { return containertest.GenerateDeleteResponseBody(empty) }, + func(empty bool) message.Message { return containertest.GenerateDeleteResponse(empty) }, + func(empty bool) message.Message { return containertest.GenerateListRequestBody(empty) }, + func(empty bool) message.Message { return containertest.GenerateListRequest(empty) }, + func(empty bool) message.Message { return containertest.GenerateListResponseBody(empty) }, + func(empty bool) message.Message { return containertest.GenerateListResponse(empty) }, + func(empty bool) message.Message { return containertest.GenerateGetRequestBody(empty) }, + func(empty bool) message.Message { return containertest.GenerateGetRequest(empty) }, + func(empty bool) message.Message { return containertest.GenerateGetResponseBody(empty) }, + func(empty bool) message.Message { return containertest.GenerateGetResponse(empty) }, + ) +} diff --git a/api/container/status.go b/api/container/status.go new file mode 100644 index 0000000..93b2983 --- /dev/null +++ b/api/container/status.go @@ -0,0 +1,33 @@ +package container + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/status" + statusgrpc "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/status/grpc" +) + +// LocalizeFailStatus checks if passed global status.Code is related to container failure and: +// +// then localizes the code and returns true, +// else leaves the code unchanged and returns false. +// +// Arg must not be nil. +func LocalizeFailStatus(c *status.Code) bool { + return status.LocalizeIfInSection(c, uint32(statusgrpc.Section_SECTION_CONTAINER)) +} + +// GlobalizeFail globalizes local code of container failure. +// +// Arg must not be nil. +func GlobalizeFail(c *status.Code) { + c.GlobalizeSection(uint32(statusgrpc.Section_SECTION_CONTAINER)) +} + +const ( + // StatusNotFound is a local status.Code value for + // CONTAINER_NOT_FOUND container failure. + StatusNotFound status.Code = iota + + // StatusEACLNotFound is a local status.Code value for + // EACL_NOT_FOUND failure. + StatusEACLNotFound +) diff --git a/api/container/status_test.go b/api/container/status_test.go new file mode 100644 index 0000000..92c738d --- /dev/null +++ b/api/container/status_test.go @@ -0,0 +1,15 @@ +package container_test + +import ( + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/container" + statustest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/status/test" +) + +func TestStatusCodes(t *testing.T) { + statustest.TestCodes(t, container.LocalizeFailStatus, container.GlobalizeFail, + container.StatusNotFound, 3072, + container.StatusEACLNotFound, 3073, + ) +} diff --git a/api/container/test/generate.go b/api/container/test/generate.go new file mode 100644 index 0000000..f804da5 --- /dev/null +++ b/api/container/test/generate.go @@ -0,0 +1,240 @@ +package containertest + +import ( + "crypto/rand" + + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/container" + netmaptest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/netmap/test" + refstest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs/test" + sessiontest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session/test" +) + +func GenerateAttribute(empty bool) *container.Attribute { + m := new(container.Attribute) + + if !empty { + m.SetKey("key") + m.SetValue("val") + } + + return m +} + +func GenerateAttributes(empty bool) []container.Attribute { + var res []container.Attribute + + if !empty { + res = append(res, + *GenerateAttribute(false), + *GenerateAttribute(false), + ) + } + + return res +} + +func GenerateContainer(empty bool) *container.Container { + m := new(container.Container) + + if !empty { + nonce := make([]byte, 16) + _, _ = rand.Read(nonce) + + m.SetBasicACL(12) + m.SetNonce(nonce) + m.SetOwnerID(refstest.GenerateOwnerID(false)) + m.SetAttributes(GenerateAttributes(false)) + m.SetPlacementPolicy(netmaptest.GeneratePlacementPolicy(false)) + } + + m.SetVersion(refstest.GenerateVersion(empty)) + + return m +} + +func GeneratePutRequestBody(empty bool) *container.PutRequestBody { + m := new(container.PutRequestBody) + + if !empty { + m.SetContainer(GenerateContainer(false)) + } + + m.SetSignature(refstest.GenerateSignature(empty)) + + return m +} + +func GeneratePutRequest(empty bool) *container.PutRequest { + m := new(container.PutRequest) + + if !empty { + m.SetBody(GeneratePutRequestBody(false)) + } + + m.SetMetaHeader(sessiontest.GenerateRequestMetaHeader(empty)) + m.SetVerificationHeader(sessiontest.GenerateRequestVerificationHeader(empty)) + + return m +} + +func GeneratePutResponseBody(empty bool) *container.PutResponseBody { + m := new(container.PutResponseBody) + + if !empty { + m.SetContainerID(refstest.GenerateContainerID(false)) + } + + return m +} + +func GeneratePutResponse(empty bool) *container.PutResponse { + m := new(container.PutResponse) + + if !empty { + m.SetBody(GeneratePutResponseBody(false)) + } + + m.SetMetaHeader(sessiontest.GenerateResponseMetaHeader(empty)) + m.SetVerificationHeader(sessiontest.GenerateResponseVerificationHeader(empty)) + + return m +} + +func GenerateGetRequestBody(empty bool) *container.GetRequestBody { + m := new(container.GetRequestBody) + + if !empty { + m.SetContainerID(refstest.GenerateContainerID(false)) + } + + return m +} + +func GenerateGetRequest(empty bool) *container.GetRequest { + m := new(container.GetRequest) + + if !empty { + m.SetBody(GenerateGetRequestBody(false)) + } + + m.SetMetaHeader(sessiontest.GenerateRequestMetaHeader(empty)) + m.SetVerificationHeader(sessiontest.GenerateRequestVerificationHeader(empty)) + + return m +} + +func GenerateGetResponseBody(empty bool) *container.GetResponseBody { + m := new(container.GetResponseBody) + + if !empty { + m.SetContainer(GenerateContainer(false)) + } + + m.SetSignature(refstest.GenerateSignature(empty)) + m.SetSessionToken(sessiontest.GenerateSessionToken(empty)) + + return m +} + +func GenerateGetResponse(empty bool) *container.GetResponse { + m := new(container.GetResponse) + + if !empty { + m.SetBody(GenerateGetResponseBody(false)) + } + + m.SetMetaHeader(sessiontest.GenerateResponseMetaHeader(empty)) + m.SetVerificationHeader(sessiontest.GenerateResponseVerificationHeader(empty)) + + return m +} + +func GenerateDeleteRequestBody(empty bool) *container.DeleteRequestBody { + m := new(container.DeleteRequestBody) + + if !empty { + m.SetContainerID(refstest.GenerateContainerID(false)) + } + + m.SetSignature(refstest.GenerateSignature(empty)) + + return m +} + +func GenerateDeleteRequest(empty bool) *container.DeleteRequest { + m := new(container.DeleteRequest) + + if !empty { + m.SetBody(GenerateDeleteRequestBody(false)) + } + + m.SetMetaHeader(sessiontest.GenerateRequestMetaHeader(empty)) + m.SetVerificationHeader(sessiontest.GenerateRequestVerificationHeader(empty)) + + return m +} + +func GenerateDeleteResponseBody(_ bool) *container.DeleteResponseBody { + m := new(container.DeleteResponseBody) + + return m +} + +func GenerateDeleteResponse(empty bool) *container.DeleteResponse { + m := new(container.DeleteResponse) + + if !empty { + m.SetBody(GenerateDeleteResponseBody(false)) + } + + m.SetMetaHeader(sessiontest.GenerateResponseMetaHeader(empty)) + m.SetVerificationHeader(sessiontest.GenerateResponseVerificationHeader(empty)) + + return m +} + +func GenerateListRequestBody(empty bool) *container.ListRequestBody { + m := new(container.ListRequestBody) + + if !empty { + m.SetOwnerID(refstest.GenerateOwnerID(false)) + } + + return m +} + +func GenerateListRequest(empty bool) *container.ListRequest { + m := new(container.ListRequest) + + if !empty { + m.SetBody(GenerateListRequestBody(false)) + } + + m.SetMetaHeader(sessiontest.GenerateRequestMetaHeader(empty)) + m.SetVerificationHeader(sessiontest.GenerateRequestVerificationHeader(empty)) + + return m +} + +func GenerateListResponseBody(empty bool) *container.ListResponseBody { + m := new(container.ListResponseBody) + + if !empty { + m.SetContainerIDs(refstest.GenerateContainerIDs(false)) + } + + return m +} + +func GenerateListResponse(empty bool) *container.ListResponse { + m := new(container.ListResponse) + + if !empty { + m.SetBody(GenerateListResponseBody(false)) + } + + m.SetMetaHeader(sessiontest.GenerateResponseMetaHeader(empty)) + m.SetVerificationHeader(sessiontest.GenerateResponseVerificationHeader(empty)) + + return m +} diff --git a/api/container/types.go b/api/container/types.go new file mode 100644 index 0000000..92c4706 --- /dev/null +++ b/api/container/types.go @@ -0,0 +1,446 @@ +package container + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" +) + +type Attribute struct { + key, val string +} + +type Container struct { + version *refs.Version + + ownerID *refs.OwnerID + + nonce []byte + + basicACL uint32 + + attr []Attribute + + policy *netmap.PlacementPolicy +} + +type PutRequestBody struct { + cnr *Container + + sig *refs.Signature +} +type PutRequest struct { + body *PutRequestBody + + session.RequestHeaders +} + +type PutResponseBody struct { + cid *refs.ContainerID +} + +type PutResponse struct { + body *PutResponseBody + + session.ResponseHeaders +} + +type GetRequestBody struct { + cid *refs.ContainerID +} + +type GetRequest struct { + body *GetRequestBody + + session.RequestHeaders +} + +type GetResponseBody struct { + cnr *Container + + token *session.Token + + sig *refs.Signature +} + +type GetResponse struct { + body *GetResponseBody + + session.ResponseHeaders +} + +type DeleteRequestBody struct { + cid *refs.ContainerID + + sig *refs.Signature +} + +type DeleteRequest struct { + body *DeleteRequestBody + + session.RequestHeaders +} + +type DeleteResponseBody struct{} + +type DeleteResponse struct { + body *DeleteResponseBody + + session.ResponseHeaders +} + +type ListRequestBody struct { + ownerID *refs.OwnerID +} + +type ListRequest struct { + body *ListRequestBody + + session.RequestHeaders +} + +type ListResponseBody struct { + cidList []refs.ContainerID +} + +type ListResponse struct { + body *ListResponseBody + + session.ResponseHeaders +} + +func (a *Attribute) GetKey() string { + if a != nil { + return a.key + } + + return "" +} + +func (a *Attribute) SetKey(v string) { + a.key = v +} + +func (a *Attribute) GetValue() string { + if a != nil { + return a.val + } + + return "" +} + +func (a *Attribute) SetValue(v string) { + a.val = v +} + +func (c *Container) GetVersion() *refs.Version { + if c != nil { + return c.version + } + + return nil +} + +func (c *Container) SetVersion(v *refs.Version) { + c.version = v +} + +func (c *Container) GetOwnerID() *refs.OwnerID { + if c != nil { + return c.ownerID + } + + return nil +} + +func (c *Container) SetOwnerID(v *refs.OwnerID) { + c.ownerID = v +} + +func (c *Container) GetNonce() []byte { + if c != nil { + return c.nonce + } + + return nil +} + +func (c *Container) SetNonce(v []byte) { + c.nonce = v +} + +func (c *Container) GetBasicACL() uint32 { + if c != nil { + return c.basicACL + } + + return 0 +} + +func (c *Container) SetBasicACL(v uint32) { + c.basicACL = v +} + +func (c *Container) GetAttributes() []Attribute { + if c != nil { + return c.attr + } + + return nil +} + +func (c *Container) SetAttributes(v []Attribute) { + c.attr = v +} + +func (c *Container) GetPlacementPolicy() *netmap.PlacementPolicy { + if c != nil { + return c.policy + } + + return nil +} + +func (c *Container) SetPlacementPolicy(v *netmap.PlacementPolicy) { + c.policy = v +} + +func (r *PutRequestBody) GetContainer() *Container { + if r != nil { + return r.cnr + } + + return nil +} + +func (r *PutRequestBody) SetContainer(v *Container) { + r.cnr = v +} + +func (r *PutRequestBody) GetSignature() *refs.Signature { + if r != nil { + return r.sig + } + + return nil +} + +func (r *PutRequestBody) SetSignature(v *refs.Signature) { + // TODO: (neofs-api-go#381) avoid this hack (e.g. create refs.SignatureRFC6979 type) + v.SetScheme(0) + r.sig = v +} + +func (r *PutRequest) GetBody() *PutRequestBody { + if r != nil { + return r.body + } + + return nil +} + +func (r *PutRequest) SetBody(v *PutRequestBody) { + r.body = v +} + +func (r *PutResponseBody) GetContainerID() *refs.ContainerID { + if r != nil { + return r.cid + } + + return nil +} + +func (r *PutResponseBody) SetContainerID(v *refs.ContainerID) { + r.cid = v +} + +func (r *PutResponse) GetBody() *PutResponseBody { + if r != nil { + return r.body + } + + return nil +} + +func (r *PutResponse) SetBody(v *PutResponseBody) { + r.body = v +} + +func (r *GetRequestBody) GetContainerID() *refs.ContainerID { + if r != nil { + return r.cid + } + + return nil +} + +func (r *GetRequestBody) SetContainerID(v *refs.ContainerID) { + r.cid = v +} + +func (r *GetRequest) GetBody() *GetRequestBody { + if r != nil { + return r.body + } + + return nil +} + +func (r *GetRequest) SetBody(v *GetRequestBody) { + r.body = v +} + +func (r *GetResponseBody) GetContainer() *Container { + if r != nil { + return r.cnr + } + + return nil +} + +func (r *GetResponseBody) SetContainer(v *Container) { + r.cnr = v +} + +// GetSessionToken returns token of the session within which requested +// container was created. +func (r *GetResponseBody) GetSessionToken() *session.Token { + if r != nil { + return r.token + } + + return nil +} + +// SetSessionToken sets token of the session within which requested +// container was created. +func (r *GetResponseBody) SetSessionToken(v *session.Token) { + r.token = v +} + +// GetSignature returns signature of the requested container. +func (r *GetResponseBody) GetSignature() *refs.Signature { + if r != nil { + return r.sig + } + + return nil +} + +// SetSignature sets signature of the requested container. +func (r *GetResponseBody) SetSignature(v *refs.Signature) { + // TODO: (neofs-api-go#381) avoid this hack (e.g. create refs.SignatureRFC6979 type) + v.SetScheme(0) + r.sig = v +} + +func (r *GetResponse) GetBody() *GetResponseBody { + if r != nil { + return r.body + } + + return nil +} + +func (r *GetResponse) SetBody(v *GetResponseBody) { + r.body = v +} + +func (r *DeleteRequestBody) GetContainerID() *refs.ContainerID { + if r != nil { + return r.cid + } + + return nil +} + +func (r *DeleteRequestBody) SetContainerID(v *refs.ContainerID) { + r.cid = v +} + +func (r *DeleteRequestBody) GetSignature() *refs.Signature { + if r != nil { + return r.sig + } + + return nil +} + +func (r *DeleteRequestBody) SetSignature(v *refs.Signature) { + // TODO: (neofs-api-go#381) avoid this hack (e.g. create refs.SignatureRFC6979 type) + v.SetScheme(0) + r.sig = v +} + +func (r *DeleteRequest) GetBody() *DeleteRequestBody { + if r != nil { + return r.body + } + + return nil +} + +func (r *DeleteRequest) SetBody(v *DeleteRequestBody) { + r.body = v +} + +func (r *DeleteResponse) GetBody() *DeleteResponseBody { + if r != nil { + return r.body + } + + return nil +} + +func (r *DeleteResponse) SetBody(v *DeleteResponseBody) { + r.body = v +} + +func (r *ListRequestBody) GetOwnerID() *refs.OwnerID { + if r != nil { + return r.ownerID + } + + return nil +} + +func (r *ListRequestBody) SetOwnerID(v *refs.OwnerID) { + r.ownerID = v +} + +func (r *ListRequest) GetBody() *ListRequestBody { + if r != nil { + return r.body + } + + return nil +} + +func (r *ListRequest) SetBody(v *ListRequestBody) { + r.body = v +} + +func (r *ListResponseBody) GetContainerIDs() []refs.ContainerID { + if r != nil { + return r.cidList + } + + return nil +} + +func (r *ListResponseBody) SetContainerIDs(v []refs.ContainerID) { + r.cidList = v +} + +func (r *ListResponse) GetBody() *ListResponseBody { + if r != nil { + return r.body + } + + return nil +} + +func (r *ListResponse) SetBody(v *ListResponseBody) { + r.body = v +} diff --git a/api/lock/grpc/types_frostfs.pb.go b/api/lock/grpc/types_frostfs.pb.go new file mode 100644 index 0000000000000000000000000000000000000000..19e45b09bf6c399209c29217c9c474d0a341aacd GIT binary patch literal 3858 zcmbtW?{C{S5dCcZ6&C?*<;;7qm@99`D}Wy?11i&`C9ubSq1#g^@Fw-qTW7rb>^nc63`EWxA?OR>yRDNf(#b zbawjoIu3%RNEhN(QeLHtAW+4!(uSg7@U^Z=3T2sAGgaOu{22y=tS}VfAN==LFH;I{ zm5E!=s?4h7S~v0}ubSDpm?nPbsGcnVArVWJXqnXspM{HMRpme6qA@B@_$<5N9Dmpc zABK}Q%m3vkX}z#RQQvQn&6{bQRz>ocN=>DecqffkX`OUdIPo=?YpE@O*1QlZ*NwH} z>L<>GZC6^E?-@IrFc=1bxnD{;M}Mg{x=9T^1cP_7m`YvKryK4?d^!CpQ}gzezHq2< zSh(%*OYj&3cS18G{-!p=_&pcyozV4M; z%bHfo%-uOrNXnGVXLKj>23vD+CpTMDRSJD?-N!-Jlqp4Pa+TSF5)CP`2vli?+zrJ@ zCKE#O_;cW(((7RG2+dWR6pbgOMG2v<FxYsC|Z-nhJR|PX6mxU~iE8TM>KrT{eB9(iI_Z&vE+JJY{ zdn1SbHz!?iimd7l6W;UJ@6tqoI+Gcg_Qd}C#zX}S*6~@POp7`yP^P-ZWb1ep4cQH1 zPY9cij*JDXz6ki>8ua?M>$af7PPcm@zR}F@w{p8Ty{2OCYaO~UOHpK<6c3R6**m4ULwj7qrh(uAg8)ZvIi z9!Vie#Y7*}P;olvXg1PCQ&=FWs3jebiJ9-F9&86QVZ?~41(OmdeBn>A%4D?o4zSA- z?Bx0cvZkGT9+`vX<5*-C8pzvaaaZqO%Z z6YSzY#R@kD9(hq%HhFGY>0r2-r8H(Ha=@)3gMmN6kfK))uK<}ffc_n1*3c?q$7sYx zgGZ7%gl4y$B{(Utn#4;l(qz7HFqN# z`oy~d<+kc~Z^!tYADIt4#m2RcXUK0hWzA7@HGC;jam> z+NhFsW69*NAP&xn*{i1|csRz271Ll~FVx+!&zp8VSN8d|b0^r%P3n&S1N(B^$sV+{ zf#E8Hx^{f7lh+arI#ceK%O! TWX2M*(%oeU47LfvFQb0}-gwDh literal 0 HcmV?d00001 diff --git a/api/lock/grpc/types_frostfs_fuzz.go b/api/lock/grpc/types_frostfs_fuzz.go new file mode 100644 index 0000000..cb55151 --- /dev/null +++ b/api/lock/grpc/types_frostfs_fuzz.go @@ -0,0 +1,26 @@ +//go:build gofuzz +// +build gofuzz + +// Code generated by protoc-gen-go-frostfs. DO NOT EDIT. + +package lock + +func DoFuzzProtoLock(data []byte) int { + msg := new(Lock) + if err := msg.UnmarshalProtobuf(data); err != nil { + return 0 + } + _ = msg.MarshalProtobuf(nil) + return 1 +} +func DoFuzzJSONLock(data []byte) int { + msg := new(Lock) + if err := msg.UnmarshalJSON(data); err != nil { + return 0 + } + _, err := msg.MarshalJSON() + if err != nil { + panic(err) + } + return 1 +} diff --git a/api/lock/grpc/types_frostfs_test.go b/api/lock/grpc/types_frostfs_test.go new file mode 100644 index 0000000..7c69064 --- /dev/null +++ b/api/lock/grpc/types_frostfs_test.go @@ -0,0 +1,21 @@ +//go:build gofuzz +// +build gofuzz + +// Code generated by protoc-gen-go-frostfs. DO NOT EDIT. + +package lock + +import ( + testing "testing" +) + +func FuzzProtoLock(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzProtoLock(data) + }) +} +func FuzzJSONLock(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzJSONLock(data) + }) +} diff --git a/api/netmap/convert.go b/api/netmap/convert.go new file mode 100644 index 0000000..f8117a5 --- /dev/null +++ b/api/netmap/convert.go @@ -0,0 +1,916 @@ +package netmap + +import ( + netmap "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/netmap/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" + refsGRPC "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/message" +) + +func (f *Filter) ToGRPCMessage() grpc.Message { + var m *netmap.Filter + + if f != nil { + m = new(netmap.Filter) + + m.SetKey(f.key) + m.SetValue(f.value) + m.SetName(f.name) + m.SetOp(OperationToGRPCMessage(f.op)) + m.SetFilters(FiltersToGRPC(f.filters)) + } + + return m +} + +func (f *Filter) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*netmap.Filter) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + f.filters, err = FiltersFromGRPC(v.GetFilters()) + if err != nil { + return err + } + + f.key = v.GetKey() + f.value = v.GetValue() + f.name = v.GetName() + f.op = OperationFromGRPCMessage(v.GetOp()) + + return nil +} + +func FiltersToGRPC(fs []Filter) (res []netmap.Filter) { + if fs != nil { + res = make([]netmap.Filter, 0, len(fs)) + + for i := range fs { + res = append(res, *fs[i].ToGRPCMessage().(*netmap.Filter)) + } + } + + return +} + +func FiltersFromGRPC(fs []netmap.Filter) (res []Filter, err error) { + if fs != nil { + res = make([]Filter, len(fs)) + + for i := range fs { + err = res[i].FromGRPCMessage(&fs[i]) + if err != nil { + return + } + } + } + + return +} + +func (s *Selector) ToGRPCMessage() grpc.Message { + var m *netmap.Selector + + if s != nil { + m = new(netmap.Selector) + + m.SetName(s.name) + m.SetAttribute(s.attribute) + m.SetFilter(s.filter) + m.SetCount(s.count) + m.SetClause(ClauseToGRPCMessage(s.clause)) + } + + return m +} + +func (s *Selector) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*netmap.Selector) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + s.name = v.GetName() + s.attribute = v.GetAttribute() + s.filter = v.GetFilter() + s.count = v.GetCount() + s.clause = ClauseFromGRPCMessage(v.GetClause()) + + return nil +} + +func SelectorsToGRPC(ss []Selector) (res []netmap.Selector) { + if ss != nil { + res = make([]netmap.Selector, 0, len(ss)) + + for i := range ss { + res = append(res, *ss[i].ToGRPCMessage().(*netmap.Selector)) + } + } + + return +} + +func SelectorsFromGRPC(ss []netmap.Selector) (res []Selector, err error) { + if ss != nil { + res = make([]Selector, len(ss)) + + for i := range ss { + err = res[i].FromGRPCMessage(&ss[i]) + if err != nil { + return + } + } + } + + return +} + +func (r *Replica) ToGRPCMessage() grpc.Message { + var m *netmap.Replica + + if r != nil { + m = new(netmap.Replica) + + m.SetSelector(r.selector) + m.SetCount(r.count) + m.EcDataCount = r.ecDataCount + m.EcParityCount = r.ecParityCount + } + + return m +} + +func (r *Replica) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*netmap.Replica) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + r.selector = v.GetSelector() + r.count = v.GetCount() + r.ecDataCount = v.GetEcDataCount() + r.ecParityCount = v.GetEcParityCount() + + return nil +} + +func ReplicasToGRPC(rs []Replica) (res []netmap.Replica) { + if rs != nil { + res = make([]netmap.Replica, 0, len(rs)) + + for i := range rs { + res = append(res, *rs[i].ToGRPCMessage().(*netmap.Replica)) + } + } + + return +} + +func ReplicasFromGRPC(rs []netmap.Replica) (res []Replica, err error) { + if rs != nil { + res = make([]Replica, len(rs)) + + for i := range rs { + err = res[i].FromGRPCMessage(&rs[i]) + if err != nil { + return + } + } + } + + return +} + +func (p *PlacementPolicy) ToGRPCMessage() grpc.Message { + var m *netmap.PlacementPolicy + + if p != nil { + m = new(netmap.PlacementPolicy) + + m.SetFilters(FiltersToGRPC(p.filters)) + m.SetSelectors(SelectorsToGRPC(p.selectors)) + m.SetReplicas(ReplicasToGRPC(p.replicas)) + m.SetContainerBackupFactor(p.backupFactor) + m.SetUnique(p.unique) + } + + return m +} + +func (p *PlacementPolicy) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*netmap.PlacementPolicy) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + p.filters, err = FiltersFromGRPC(v.GetFilters()) + if err != nil { + return err + } + + p.selectors, err = SelectorsFromGRPC(v.GetSelectors()) + if err != nil { + return err + } + + p.replicas, err = ReplicasFromGRPC(v.GetReplicas()) + if err != nil { + return err + } + + p.backupFactor = v.GetContainerBackupFactor() + + p.unique = v.GetUnique() + + return nil +} + +func ClauseToGRPCMessage(n Clause) netmap.Clause { + return netmap.Clause(n) +} + +func ClauseFromGRPCMessage(n netmap.Clause) Clause { + return Clause(n) +} + +func OperationToGRPCMessage(n Operation) netmap.Operation { + return netmap.Operation(n) +} + +func OperationFromGRPCMessage(n netmap.Operation) Operation { + return Operation(n) +} + +func NodeStateToGRPCMessage(n NodeState) netmap.NodeInfo_State { + return netmap.NodeInfo_State(n) +} + +func NodeStateFromRPCMessage(n netmap.NodeInfo_State) NodeState { + return NodeState(n) +} + +func (a *Attribute) ToGRPCMessage() grpc.Message { + var m *netmap.NodeInfo_Attribute + + if a != nil { + m = new(netmap.NodeInfo_Attribute) + + m.SetKey(a.key) + m.SetValue(a.value) + m.SetParents(a.parents) + } + + return m +} + +func (a *Attribute) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*netmap.NodeInfo_Attribute) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + a.key = v.GetKey() + a.value = v.GetValue() + a.parents = v.GetParents() + + return nil +} + +func AttributesToGRPC(as []Attribute) (res []netmap.NodeInfo_Attribute) { + if as != nil { + res = make([]netmap.NodeInfo_Attribute, 0, len(as)) + + for i := range as { + res = append(res, *as[i].ToGRPCMessage().(*netmap.NodeInfo_Attribute)) + } + } + + return +} + +func AttributesFromGRPC(as []netmap.NodeInfo_Attribute) (res []Attribute, err error) { + if as != nil { + res = make([]Attribute, len(as)) + + for i := range as { + err = res[i].FromGRPCMessage(&as[i]) + if err != nil { + return + } + } + } + + return +} + +func (ni *NodeInfo) ToGRPCMessage() grpc.Message { + var m *netmap.NodeInfo + + if ni != nil { + m = new(netmap.NodeInfo) + + m.SetPublicKey(ni.publicKey) + m.SetAddresses(ni.addresses) + m.SetState(NodeStateToGRPCMessage(ni.state)) + m.SetAttributes(AttributesToGRPC(ni.attributes)) + } + + return m +} + +func (ni *NodeInfo) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*netmap.NodeInfo) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + ni.attributes, err = AttributesFromGRPC(v.GetAttributes()) + if err != nil { + return err + } + + ni.publicKey = v.GetPublicKey() + ni.addresses = v.GetAddresses() + ni.state = NodeStateFromRPCMessage(v.GetState()) + + return nil +} + +func (l *LocalNodeInfoRequestBody) ToGRPCMessage() grpc.Message { + var m *netmap.LocalNodeInfoRequest_Body + + if l != nil { + m = new(netmap.LocalNodeInfoRequest_Body) + } + + return m +} + +func (l *LocalNodeInfoRequestBody) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*netmap.LocalNodeInfoRequest_Body) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + return nil +} + +func (l *LocalNodeInfoRequest) ToGRPCMessage() grpc.Message { + var m *netmap.LocalNodeInfoRequest + + if l != nil { + m = new(netmap.LocalNodeInfoRequest) + + m.SetBody(l.body.ToGRPCMessage().(*netmap.LocalNodeInfoRequest_Body)) + l.RequestHeaders.ToMessage(m) + } + + return m +} + +func (l *LocalNodeInfoRequest) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*netmap.LocalNodeInfoRequest) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + body := v.GetBody() + if body == nil { + l.body = nil + } else { + if l.body == nil { + l.body = new(LocalNodeInfoRequestBody) + } + + err = l.body.FromGRPCMessage(body) + if err != nil { + return err + } + } + + return l.RequestHeaders.FromMessage(v) +} + +func (l *LocalNodeInfoResponseBody) ToGRPCMessage() grpc.Message { + var m *netmap.LocalNodeInfoResponse_Body + + if l != nil { + m = new(netmap.LocalNodeInfoResponse_Body) + + m.SetVersion(l.version.ToGRPCMessage().(*refsGRPC.Version)) + m.SetNodeInfo(l.nodeInfo.ToGRPCMessage().(*netmap.NodeInfo)) + } + + return m +} + +func (l *LocalNodeInfoResponseBody) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*netmap.LocalNodeInfoResponse_Body) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + version := v.GetVersion() + if version == nil { + l.version = nil + } else { + if l.version == nil { + l.version = new(refs.Version) + } + + err = l.version.FromGRPCMessage(version) + if err != nil { + return err + } + } + + nodeInfo := v.GetNodeInfo() + if nodeInfo == nil { + l.nodeInfo = nil + } else { + if l.nodeInfo == nil { + l.nodeInfo = new(NodeInfo) + } + + err = l.nodeInfo.FromGRPCMessage(nodeInfo) + } + + return err +} + +func (l *LocalNodeInfoResponse) ToGRPCMessage() grpc.Message { + var m *netmap.LocalNodeInfoResponse + + if l != nil { + m = new(netmap.LocalNodeInfoResponse) + + m.SetBody(l.body.ToGRPCMessage().(*netmap.LocalNodeInfoResponse_Body)) + l.ResponseHeaders.ToMessage(m) + } + + return m +} + +func (l *LocalNodeInfoResponse) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*netmap.LocalNodeInfoResponse) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + body := v.GetBody() + if body == nil { + l.body = nil + } else { + if l.body == nil { + l.body = new(LocalNodeInfoResponseBody) + } + + err = l.body.FromGRPCMessage(body) + if err != nil { + return err + } + } + + return l.ResponseHeaders.FromMessage(v) +} + +func (x *NetworkParameter) ToGRPCMessage() grpc.Message { + var m *netmap.NetworkConfig_Parameter + + if x != nil { + m = new(netmap.NetworkConfig_Parameter) + + m.SetKey(x.k) + m.SetValue(x.v) + } + + return m +} + +func (x *NetworkParameter) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*netmap.NetworkConfig_Parameter) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + x.k = v.GetKey() + x.v = v.GetValue() + + return nil +} + +func (x *NetworkConfig) ToGRPCMessage() grpc.Message { + var m *netmap.NetworkConfig + + if x != nil { + m = new(netmap.NetworkConfig) + + var ps []netmap.NetworkConfig_Parameter + + if ln := len(x.ps); ln > 0 { + ps = make([]netmap.NetworkConfig_Parameter, 0, ln) + + for i := range ln { + ps = append(ps, *x.ps[i].ToGRPCMessage().(*netmap.NetworkConfig_Parameter)) + } + } + + m.SetParameters(ps) + } + + return m +} + +func (x *NetworkConfig) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*netmap.NetworkConfig) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var ( + ps []NetworkParameter + psV2 = v.GetParameters() + ) + + if psV2 != nil { + ln := len(psV2) + + ps = make([]NetworkParameter, ln) + + for i := range ln { + if err := ps[i].FromGRPCMessage(&psV2[i]); err != nil { + return err + } + } + } + + x.ps = ps + + return nil +} + +func (i *NetworkInfo) ToGRPCMessage() grpc.Message { + var m *netmap.NetworkInfo + + if i != nil { + m = new(netmap.NetworkInfo) + + m.SetMagicNumber(i.magicNum) + m.SetCurrentEpoch(i.curEpoch) + m.SetMsPerBlock(i.msPerBlock) + m.SetNetworkConfig(i.netCfg.ToGRPCMessage().(*netmap.NetworkConfig)) + } + + return m +} + +func (i *NetworkInfo) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*netmap.NetworkInfo) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + netCfg := v.GetNetworkConfig() + if netCfg == nil { + i.netCfg = nil + } else { + if i.netCfg == nil { + i.netCfg = new(NetworkConfig) + } + + err = i.netCfg.FromGRPCMessage(netCfg) + if err != nil { + return err + } + } + + i.magicNum = v.GetMagicNumber() + i.curEpoch = v.GetCurrentEpoch() + i.msPerBlock = v.GetMsPerBlock() + + return nil +} + +func (l *NetworkInfoRequestBody) ToGRPCMessage() grpc.Message { + var m *netmap.NetworkInfoRequest_Body + + if l != nil { + m = new(netmap.NetworkInfoRequest_Body) + } + + return m +} + +func (l *NetworkInfoRequestBody) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*netmap.NetworkInfoRequest_Body) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + return nil +} + +func (l *NetworkInfoRequest) ToGRPCMessage() grpc.Message { + var m *netmap.NetworkInfoRequest + + if l != nil { + m = new(netmap.NetworkInfoRequest) + + m.SetBody(l.body.ToGRPCMessage().(*netmap.NetworkInfoRequest_Body)) + l.RequestHeaders.ToMessage(m) + } + + return m +} + +func (l *NetworkInfoRequest) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*netmap.NetworkInfoRequest) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + body := v.GetBody() + if body == nil { + l.body = nil + } else { + if l.body == nil { + l.body = new(NetworkInfoRequestBody) + } + + err = l.body.FromGRPCMessage(body) + if err != nil { + return err + } + } + + return l.RequestHeaders.FromMessage(v) +} + +func (i *NetworkInfoResponseBody) ToGRPCMessage() grpc.Message { + var m *netmap.NetworkInfoResponse_Body + + if i != nil { + m = new(netmap.NetworkInfoResponse_Body) + + m.SetNetworkInfo(i.netInfo.ToGRPCMessage().(*netmap.NetworkInfo)) + } + + return m +} + +func (i *NetworkInfoResponseBody) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*netmap.NetworkInfoResponse_Body) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + netInfo := v.GetNetworkInfo() + if netInfo == nil { + i.netInfo = nil + } else { + if i.netInfo == nil { + i.netInfo = new(NetworkInfo) + } + + err = i.netInfo.FromGRPCMessage(netInfo) + } + + return err +} + +func (l *NetworkInfoResponse) ToGRPCMessage() grpc.Message { + var m *netmap.NetworkInfoResponse + + if l != nil { + m = new(netmap.NetworkInfoResponse) + + m.SetBody(l.body.ToGRPCMessage().(*netmap.NetworkInfoResponse_Body)) + l.ResponseHeaders.ToMessage(m) + } + + return m +} + +func (l *NetworkInfoResponse) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*netmap.NetworkInfoResponse) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + body := v.GetBody() + if body == nil { + l.body = nil + } else { + if l.body == nil { + l.body = new(NetworkInfoResponseBody) + } + + err = l.body.FromGRPCMessage(body) + if err != nil { + return err + } + } + + return l.ResponseHeaders.FromMessage(v) +} + +func (x *NetMap) ToGRPCMessage() grpc.Message { + var m *netmap.Netmap + + if x != nil { + m = new(netmap.Netmap) + + m.SetEpoch(x.epoch) + + if x.nodes != nil { + nodes := make([]netmap.NodeInfo, len(x.nodes)) + + for i := range x.nodes { + nodes[i] = *x.nodes[i].ToGRPCMessage().(*netmap.NodeInfo) + } + + m.SetNodes(nodes) + } + } + + return m +} + +func (x *NetMap) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*netmap.Netmap) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + nodes := v.GetNodes() + if nodes == nil { + x.nodes = nil + } else { + x.nodes = make([]NodeInfo, len(nodes)) + + for i := range nodes { + err = x.nodes[i].FromGRPCMessage(&nodes[i]) + if err != nil { + return err + } + } + } + + x.epoch = v.GetEpoch() + + return nil +} + +func (x *SnapshotRequestBody) ToGRPCMessage() grpc.Message { + var m *netmap.NetmapSnapshotRequest_Body + + if x != nil { + m = new(netmap.NetmapSnapshotRequest_Body) + } + + return m +} + +func (x *SnapshotRequestBody) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*netmap.NetmapSnapshotRequest_Body) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + return nil +} + +func (x *SnapshotRequest) ToGRPCMessage() grpc.Message { + var m *netmap.NetmapSnapshotRequest + + if x != nil { + m = new(netmap.NetmapSnapshotRequest) + + m.SetBody(x.body.ToGRPCMessage().(*netmap.NetmapSnapshotRequest_Body)) + x.RequestHeaders.ToMessage(m) + } + + return m +} + +func (x *SnapshotRequest) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*netmap.NetmapSnapshotRequest) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + body := v.GetBody() + if body == nil { + x.body = nil + } else { + if x.body == nil { + x.body = new(SnapshotRequestBody) + } + + err = x.body.FromGRPCMessage(body) + if err != nil { + return err + } + } + + return x.RequestHeaders.FromMessage(v) +} + +func (x *SnapshotResponseBody) ToGRPCMessage() grpc.Message { + var m *netmap.NetmapSnapshotResponse_Body + + if x != nil { + m = new(netmap.NetmapSnapshotResponse_Body) + + m.SetNetmap(x.netMap.ToGRPCMessage().(*netmap.Netmap)) + } + + return m +} + +func (x *SnapshotResponseBody) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*netmap.NetmapSnapshotResponse_Body) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + netMap := v.GetNetmap() + if netMap == nil { + x.netMap = nil + } else { + if x.netMap == nil { + x.netMap = new(NetMap) + } + + err = x.netMap.FromGRPCMessage(netMap) + } + + return err +} + +func (x *SnapshotResponse) ToGRPCMessage() grpc.Message { + var m *netmap.NetmapSnapshotResponse + + if x != nil { + m = new(netmap.NetmapSnapshotResponse) + + m.SetBody(x.body.ToGRPCMessage().(*netmap.NetmapSnapshotResponse_Body)) + x.ResponseHeaders.ToMessage(m) + } + + return m +} + +func (x *SnapshotResponse) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*netmap.NetmapSnapshotResponse) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + body := v.GetBody() + if body == nil { + x.body = nil + } else { + if x.body == nil { + x.body = new(SnapshotResponseBody) + } + + err = x.body.FromGRPCMessage(body) + if err != nil { + return err + } + } + + return x.ResponseHeaders.FromMessage(v) +} diff --git a/api/netmap/grpc/service_frostfs.pb.go b/api/netmap/grpc/service_frostfs.pb.go new file mode 100644 index 0000000000000000000000000000000000000000..7e2d7a367dce459c5086ab87413ab1afd9f69c85 GIT binary patch literal 55007 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 NZYnE8lZSeF`Tr<=2;~3( literal 0 HcmV?d00001 diff --git a/api/netmap/grpc/service_frostfs_fuzz.go b/api/netmap/grpc/service_frostfs_fuzz.go new file mode 100644 index 0000000..ebb59bc --- /dev/null +++ b/api/netmap/grpc/service_frostfs_fuzz.go @@ -0,0 +1,121 @@ +//go:build gofuzz +// +build gofuzz + +// Code generated by protoc-gen-go-frostfs. DO NOT EDIT. + +package netmap + +func DoFuzzProtoLocalNodeInfoRequest(data []byte) int { + msg := new(LocalNodeInfoRequest) + if err := msg.UnmarshalProtobuf(data); err != nil { + return 0 + } + _ = msg.MarshalProtobuf(nil) + return 1 +} +func DoFuzzJSONLocalNodeInfoRequest(data []byte) int { + msg := new(LocalNodeInfoRequest) + if err := msg.UnmarshalJSON(data); err != nil { + return 0 + } + _, err := msg.MarshalJSON() + if err != nil { + panic(err) + } + return 1 +} +func DoFuzzProtoLocalNodeInfoResponse(data []byte) int { + msg := new(LocalNodeInfoResponse) + if err := msg.UnmarshalProtobuf(data); err != nil { + return 0 + } + _ = msg.MarshalProtobuf(nil) + return 1 +} +func DoFuzzJSONLocalNodeInfoResponse(data []byte) int { + msg := new(LocalNodeInfoResponse) + if err := msg.UnmarshalJSON(data); err != nil { + return 0 + } + _, err := msg.MarshalJSON() + if err != nil { + panic(err) + } + return 1 +} +func DoFuzzProtoNetworkInfoRequest(data []byte) int { + msg := new(NetworkInfoRequest) + if err := msg.UnmarshalProtobuf(data); err != nil { + return 0 + } + _ = msg.MarshalProtobuf(nil) + return 1 +} +func DoFuzzJSONNetworkInfoRequest(data []byte) int { + msg := new(NetworkInfoRequest) + if err := msg.UnmarshalJSON(data); err != nil { + return 0 + } + _, err := msg.MarshalJSON() + if err != nil { + panic(err) + } + return 1 +} +func DoFuzzProtoNetworkInfoResponse(data []byte) int { + msg := new(NetworkInfoResponse) + if err := msg.UnmarshalProtobuf(data); err != nil { + return 0 + } + _ = msg.MarshalProtobuf(nil) + return 1 +} +func DoFuzzJSONNetworkInfoResponse(data []byte) int { + msg := new(NetworkInfoResponse) + if err := msg.UnmarshalJSON(data); err != nil { + return 0 + } + _, err := msg.MarshalJSON() + if err != nil { + panic(err) + } + return 1 +} +func DoFuzzProtoNetmapSnapshotRequest(data []byte) int { + msg := new(NetmapSnapshotRequest) + if err := msg.UnmarshalProtobuf(data); err != nil { + return 0 + } + _ = msg.MarshalProtobuf(nil) + return 1 +} +func DoFuzzJSONNetmapSnapshotRequest(data []byte) int { + msg := new(NetmapSnapshotRequest) + if err := msg.UnmarshalJSON(data); err != nil { + return 0 + } + _, err := msg.MarshalJSON() + if err != nil { + panic(err) + } + return 1 +} +func DoFuzzProtoNetmapSnapshotResponse(data []byte) int { + msg := new(NetmapSnapshotResponse) + if err := msg.UnmarshalProtobuf(data); err != nil { + return 0 + } + _ = msg.MarshalProtobuf(nil) + return 1 +} +func DoFuzzJSONNetmapSnapshotResponse(data []byte) int { + msg := new(NetmapSnapshotResponse) + if err := msg.UnmarshalJSON(data); err != nil { + return 0 + } + _, err := msg.MarshalJSON() + if err != nil { + panic(err) + } + return 1 +} diff --git a/api/netmap/grpc/service_frostfs_test.go b/api/netmap/grpc/service_frostfs_test.go new file mode 100644 index 0000000..5c9035f --- /dev/null +++ b/api/netmap/grpc/service_frostfs_test.go @@ -0,0 +1,71 @@ +//go:build gofuzz +// +build gofuzz + +// Code generated by protoc-gen-go-frostfs. DO NOT EDIT. + +package netmap + +import ( + testing "testing" +) + +func FuzzProtoLocalNodeInfoRequest(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzProtoLocalNodeInfoRequest(data) + }) +} +func FuzzJSONLocalNodeInfoRequest(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzJSONLocalNodeInfoRequest(data) + }) +} +func FuzzProtoLocalNodeInfoResponse(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzProtoLocalNodeInfoResponse(data) + }) +} +func FuzzJSONLocalNodeInfoResponse(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzJSONLocalNodeInfoResponse(data) + }) +} +func FuzzProtoNetworkInfoRequest(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzProtoNetworkInfoRequest(data) + }) +} +func FuzzJSONNetworkInfoRequest(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzJSONNetworkInfoRequest(data) + }) +} +func FuzzProtoNetworkInfoResponse(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzProtoNetworkInfoResponse(data) + }) +} +func FuzzJSONNetworkInfoResponse(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzJSONNetworkInfoResponse(data) + }) +} +func FuzzProtoNetmapSnapshotRequest(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzProtoNetmapSnapshotRequest(data) + }) +} +func FuzzJSONNetmapSnapshotRequest(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzJSONNetmapSnapshotRequest(data) + }) +} +func FuzzProtoNetmapSnapshotResponse(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzProtoNetmapSnapshotResponse(data) + }) +} +func FuzzJSONNetmapSnapshotResponse(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzJSONNetmapSnapshotResponse(data) + }) +} diff --git a/api/netmap/grpc/service_grpc.pb.go b/api/netmap/grpc/service_grpc.pb.go new file mode 100644 index 0000000000000000000000000000000000000000..7deee56c6921a5cea59edf31d3c08ae2ec59b27e GIT binary patch literal 9148 zcmeHNZEqX75&rD`6|4%Rk|D3s6vY7!f+A4ttI&%bSWdqbg+p_>(!#6d9?6wX2>jps z47n?DrM0bVoF+gMH$+chh-vPzubyOWtZndwr* z?A;~1xV&a(?mzj{UvnPs5F7EhDGA|NE*`ie1vVL?VRAJ?Bmi6i%deIRnV7-}A zvs}hAmGfd2D?M|HF)ZM;d1!p(Mj>S^x7EX9ez+G6BJ$#To*9PUoC&okvs|9oY#|vp zaKi#BW)+i#skCHv&Mp3e@D}$JGe`}-r1{)tx4C4i%+4W+0Fgfp0+}VTTbUKJX0e3v z8P5u1U39MGuT`eu;q2nEH`N3m6G5_@O z{VA#if%1h5&D00w<`*S+egPOKMXGMjt2}=%?OY`n98N=P51~|XYU1Uq*hegGDHydB z0PNQ24L+@uzUx$ekorJDmvWG7TJX}$mEAS|0NZO@YXuDhS{{t^OcpLq6h7fUz5Os@ zDPqu)WDU;|eqz8m1dLqp!e#<=(yA&FChTvlGN2RvoGXLSk7SV$1B}&@FX$%(+YDKm zOAbjbQ>lq`b8Aa;IvSOCGwg&ok;_r{z8L+@^4m9w5`Xl@k5y41XsfAPAdc+1lx@=+ zC$ar>%7tW~qa%3mv$U+C2ANk0OSDh5S~xP796Lf(IoGV9?2~}2!shGP&8C?w1FQ4` zy8s(U@B(CKmfy+3EBWLB{KU)xs;~zNtGTc-n-s_y@)J!;Gek>O zmaS;RQ}FAwNiI2ca0^jQ94XRDgDRSK^r9*<;hc|sUa2AAxlw)sw2QeEcPvYhamXsC z4{4z)9Z7Um6ySt|)D2BtGLy*I6rvM$e0=$j<73u;Ib_qb@%7~L;%54BJU*LF2VNu$ z0ly_Th{;4&7&+&ZfDjK;2_cP1kpR}flP9lh{bRU+;H5mv5q!h?%_`?_C%=5WI=dNP zzJGstF@S}wRM01?*NHp^1u3%+!3TES5~CC+4MtRH4U6O0ol|3;=a(h1X2ANp6HJMm zCx=XGt@OZ|c?E;JSg`f?Tq|SGr*!I2Y@Z!ZQE5#as`X>LAU{7ZyfrN;mp%+`Aan?{ zE%8oZvE>W1aSQpDnL1xGl{zXlt~U_NQi=Ij2be5*R`vpl;52y@;Xv*{kXti$aK4Xx zN-n~KxlYMG>ry@z!k_TloIYvNbp#D*RR|>YRqcg8-Mwu8k*R~ug8<8ENr7iCI*j@( z#QkQ;zF@~4G6UAyeNj_xkdM@qO6PXHi*FqaV2+fM3IPm`c%$sGBj?qE=ecI)3~J0`4SiZoji=j z)+T}b{9ZQ~o?gT?6Of;q%C-O0l)Zv-50{-{@33u2M?_ufx+2Z@0^>8fTBe{c+KX|^ zv?1#)T!XA#;Nt3zCQ)WqRa+te!f zKpa9V3k?^v1Z6Tr)0y#vcA%#m>Mzw3R5^HvUYqM(`@Wm&lbFrce8|78 zDcBQ>%Gfh1(pu#2fTd4F_e{T%v&^7_*d>J)HoZU81*MnNTo0Mi%PyA&6loJTD(iXu z7cJd4_1EvD5l++A7HT|GxIOGUSGm8V`dAHtXIwD5X2K54mLGDjJ&h zX75T0-{XD@ByaQ}Zsk#bFUG3w>PoFdGWW&4tEqxBM_$LNdmzFJ=-eJ{pA=5pf!+zq zR*s$?FcVkhxepXA=_1hCQq=O-Fp3XD-6ZDka8!Q3 zoD7U?Aow=43=H|o%nVlgUdS1kw8PI}q>0aeL($!KRCw$+O{uWDpmM-fUf3dJg0BI> z=UFzfe=>MU#8VgLZ7R0h1pjF09%$W*z0p`@{Q)$bpmM_g4zBicMz?oW`Plw_u>plJ$-@~z4pCH$G zn#TL5#PsEX8=+E(r-@Lzy9q!^`Gl?kLWzFMe4;{l>x1F)U4)C{6lIknsiTp z?Q0Jb+LO8i*(N$4RZbqha8OqNS<)Z5wJ)9GYm|*kNyJ& CJ5~n( literal 0 HcmV?d00001 diff --git a/api/netmap/grpc/types_frostfs.pb.go b/api/netmap/grpc/types_frostfs.pb.go new file mode 100644 index 0000000000000000000000000000000000000000..9dc0de0e7b1cf4cfb60d5cbd33965cc37d36fe2b GIT binary patch literal 57425 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 AM*si- literal 0 HcmV?d00001 diff --git a/api/netmap/grpc/types_frostfs_fuzz.go b/api/netmap/grpc/types_frostfs_fuzz.go new file mode 100644 index 0000000..89ccd74 --- /dev/null +++ b/api/netmap/grpc/types_frostfs_fuzz.go @@ -0,0 +1,159 @@ +//go:build gofuzz +// +build gofuzz + +// Code generated by protoc-gen-go-frostfs. DO NOT EDIT. + +package netmap + +func DoFuzzProtoFilter(data []byte) int { + msg := new(Filter) + if err := msg.UnmarshalProtobuf(data); err != nil { + return 0 + } + _ = msg.MarshalProtobuf(nil) + return 1 +} +func DoFuzzJSONFilter(data []byte) int { + msg := new(Filter) + if err := msg.UnmarshalJSON(data); err != nil { + return 0 + } + _, err := msg.MarshalJSON() + if err != nil { + panic(err) + } + return 1 +} +func DoFuzzProtoSelector(data []byte) int { + msg := new(Selector) + if err := msg.UnmarshalProtobuf(data); err != nil { + return 0 + } + _ = msg.MarshalProtobuf(nil) + return 1 +} +func DoFuzzJSONSelector(data []byte) int { + msg := new(Selector) + if err := msg.UnmarshalJSON(data); err != nil { + return 0 + } + _, err := msg.MarshalJSON() + if err != nil { + panic(err) + } + return 1 +} +func DoFuzzProtoReplica(data []byte) int { + msg := new(Replica) + if err := msg.UnmarshalProtobuf(data); err != nil { + return 0 + } + _ = msg.MarshalProtobuf(nil) + return 1 +} +func DoFuzzJSONReplica(data []byte) int { + msg := new(Replica) + if err := msg.UnmarshalJSON(data); err != nil { + return 0 + } + _, err := msg.MarshalJSON() + if err != nil { + panic(err) + } + return 1 +} +func DoFuzzProtoPlacementPolicy(data []byte) int { + msg := new(PlacementPolicy) + if err := msg.UnmarshalProtobuf(data); err != nil { + return 0 + } + _ = msg.MarshalProtobuf(nil) + return 1 +} +func DoFuzzJSONPlacementPolicy(data []byte) int { + msg := new(PlacementPolicy) + if err := msg.UnmarshalJSON(data); err != nil { + return 0 + } + _, err := msg.MarshalJSON() + if err != nil { + panic(err) + } + return 1 +} +func DoFuzzProtoNodeInfo(data []byte) int { + msg := new(NodeInfo) + if err := msg.UnmarshalProtobuf(data); err != nil { + return 0 + } + _ = msg.MarshalProtobuf(nil) + return 1 +} +func DoFuzzJSONNodeInfo(data []byte) int { + msg := new(NodeInfo) + if err := msg.UnmarshalJSON(data); err != nil { + return 0 + } + _, err := msg.MarshalJSON() + if err != nil { + panic(err) + } + return 1 +} +func DoFuzzProtoNetmap(data []byte) int { + msg := new(Netmap) + if err := msg.UnmarshalProtobuf(data); err != nil { + return 0 + } + _ = msg.MarshalProtobuf(nil) + return 1 +} +func DoFuzzJSONNetmap(data []byte) int { + msg := new(Netmap) + if err := msg.UnmarshalJSON(data); err != nil { + return 0 + } + _, err := msg.MarshalJSON() + if err != nil { + panic(err) + } + return 1 +} +func DoFuzzProtoNetworkConfig(data []byte) int { + msg := new(NetworkConfig) + if err := msg.UnmarshalProtobuf(data); err != nil { + return 0 + } + _ = msg.MarshalProtobuf(nil) + return 1 +} +func DoFuzzJSONNetworkConfig(data []byte) int { + msg := new(NetworkConfig) + if err := msg.UnmarshalJSON(data); err != nil { + return 0 + } + _, err := msg.MarshalJSON() + if err != nil { + panic(err) + } + return 1 +} +func DoFuzzProtoNetworkInfo(data []byte) int { + msg := new(NetworkInfo) + if err := msg.UnmarshalProtobuf(data); err != nil { + return 0 + } + _ = msg.MarshalProtobuf(nil) + return 1 +} +func DoFuzzJSONNetworkInfo(data []byte) int { + msg := new(NetworkInfo) + if err := msg.UnmarshalJSON(data); err != nil { + return 0 + } + _, err := msg.MarshalJSON() + if err != nil { + panic(err) + } + return 1 +} diff --git a/api/netmap/grpc/types_frostfs_test.go b/api/netmap/grpc/types_frostfs_test.go new file mode 100644 index 0000000..9996dc9 --- /dev/null +++ b/api/netmap/grpc/types_frostfs_test.go @@ -0,0 +1,91 @@ +//go:build gofuzz +// +build gofuzz + +// Code generated by protoc-gen-go-frostfs. DO NOT EDIT. + +package netmap + +import ( + testing "testing" +) + +func FuzzProtoFilter(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzProtoFilter(data) + }) +} +func FuzzJSONFilter(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzJSONFilter(data) + }) +} +func FuzzProtoSelector(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzProtoSelector(data) + }) +} +func FuzzJSONSelector(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzJSONSelector(data) + }) +} +func FuzzProtoReplica(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzProtoReplica(data) + }) +} +func FuzzJSONReplica(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzJSONReplica(data) + }) +} +func FuzzProtoPlacementPolicy(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzProtoPlacementPolicy(data) + }) +} +func FuzzJSONPlacementPolicy(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzJSONPlacementPolicy(data) + }) +} +func FuzzProtoNodeInfo(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzProtoNodeInfo(data) + }) +} +func FuzzJSONNodeInfo(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzJSONNodeInfo(data) + }) +} +func FuzzProtoNetmap(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzProtoNetmap(data) + }) +} +func FuzzJSONNetmap(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzJSONNetmap(data) + }) +} +func FuzzProtoNetworkConfig(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzProtoNetworkConfig(data) + }) +} +func FuzzJSONNetworkConfig(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzJSONNetworkConfig(data) + }) +} +func FuzzProtoNetworkInfo(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzProtoNetworkInfo(data) + }) +} +func FuzzJSONNetworkInfo(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzJSONNetworkInfo(data) + }) +} diff --git a/api/netmap/json.go b/api/netmap/json.go new file mode 100644 index 0000000..6a1c257 --- /dev/null +++ b/api/netmap/json.go @@ -0,0 +1,62 @@ +package netmap + +import ( + netmap "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/netmap/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/message" +) + +func (p *PlacementPolicy) MarshalJSON() ([]byte, error) { + return message.MarshalJSON(p) +} + +func (p *PlacementPolicy) UnmarshalJSON(data []byte) error { + return message.UnmarshalJSON(p, data, new(netmap.PlacementPolicy)) +} + +func (f *Filter) MarshalJSON() ([]byte, error) { + return message.MarshalJSON(f) +} + +func (f *Filter) UnmarshalJSON(data []byte) error { + return message.UnmarshalJSON(f, data, new(netmap.Filter)) +} + +func (s *Selector) MarshalJSON() ([]byte, error) { + return message.MarshalJSON(s) +} + +func (s *Selector) UnmarshalJSON(data []byte) error { + return message.UnmarshalJSON(s, data, new(netmap.Selector)) +} + +func (r *Replica) MarshalJSON() ([]byte, error) { + return message.MarshalJSON(r) +} + +func (r *Replica) UnmarshalJSON(data []byte) error { + return message.UnmarshalJSON(r, data, new(netmap.Replica)) +} + +func (a *Attribute) MarshalJSON() ([]byte, error) { + return message.MarshalJSON(a) +} + +func (a *Attribute) UnmarshalJSON(data []byte) error { + return message.UnmarshalJSON(a, data, new(netmap.NodeInfo_Attribute)) +} + +func (ni *NodeInfo) MarshalJSON() ([]byte, error) { + return message.MarshalJSON(ni) +} + +func (ni *NodeInfo) UnmarshalJSON(data []byte) error { + return message.UnmarshalJSON(ni, data, new(netmap.NodeInfo)) +} + +func (i *NetworkInfo) MarshalJSON() ([]byte, error) { + return message.MarshalJSON(i) +} + +func (i *NetworkInfo) UnmarshalJSON(data []byte) error { + return message.UnmarshalJSON(i, data, new(netmap.NetworkInfo)) +} diff --git a/api/netmap/marshal.go b/api/netmap/marshal.go new file mode 100644 index 0000000..4d5e4f1 --- /dev/null +++ b/api/netmap/marshal.go @@ -0,0 +1,576 @@ +package netmap + +import ( + netmap "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/netmap/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/message" + protoutil "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/util/proto" +) + +const ( + nameFilterField = 1 + keyFilterField = 2 + opFilterField = 3 + valueFilterField = 4 + filtersFilterField = 5 + + nameSelectorField = 1 + countSelectorField = 2 + clauseSelectorField = 3 + attributeSelectorField = 4 + filterSelectorField = 5 + + countReplicaField = 1 + selectorReplicaField = 2 + ecDataCountReplicaField = 3 + ecParityCountReplicaField = 4 + + replicasPolicyField = 1 + backupPolicyField = 2 + selectorsPolicyField = 3 + filtersPolicyField = 4 + uniquePolicyField = 5 + + keyAttributeField = 1 + valueAttributeField = 2 + parentsAttributeField = 3 + + keyNodeInfoField = 1 + addressNodeInfoField = 2 + attributesNodeInfoField = 3 + stateNodeInfoField = 4 + + versionInfoResponseBodyField = 1 + nodeInfoResponseBodyField = 2 +) + +func (f *Filter) StableMarshal(buf []byte) []byte { + if f == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, f.StableSize()) + } + + var offset int + + offset += protoutil.StringMarshal(nameFilterField, buf[offset:], f.name) + offset += protoutil.StringMarshal(keyFilterField, buf[offset:], f.key) + offset += protoutil.EnumMarshal(opFilterField, buf[offset:], int32(f.op)) + offset += protoutil.StringMarshal(valueFilterField, buf[offset:], f.value) + + for i := range f.filters { + offset += protoutil.NestedStructureMarshal(filtersFilterField, buf[offset:], &f.filters[i]) + } + + return buf +} + +func (f *Filter) StableSize() (size int) { + if f == nil { + return 0 + } + + size += protoutil.StringSize(nameFilterField, f.name) + size += protoutil.StringSize(keyFilterField, f.key) + size += protoutil.EnumSize(opFilterField, int32(f.op)) + size += protoutil.StringSize(valueFilterField, f.value) + for i := range f.filters { + size += protoutil.NestedStructureSize(filtersFilterField, &f.filters[i]) + } + + return size +} + +func (f *Filter) Unmarshal(data []byte) error { + return message.Unmarshal(f, data, new(netmap.Filter)) +} + +func (s *Selector) StableMarshal(buf []byte) []byte { + if s == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, s.StableSize()) + } + + var offset int + + offset += protoutil.StringMarshal(nameSelectorField, buf[offset:], s.name) + offset += protoutil.UInt32Marshal(countSelectorField, buf[offset:], s.count) + offset += protoutil.EnumMarshal(clauseSelectorField, buf[offset:], int32(s.clause)) + offset += protoutil.StringMarshal(attributeSelectorField, buf[offset:], s.attribute) + protoutil.StringMarshal(filterSelectorField, buf[offset:], s.filter) + + return buf +} + +func (s *Selector) StableSize() (size int) { + if s == nil { + return 0 + } + + size += protoutil.StringSize(nameSelectorField, s.name) + size += protoutil.UInt32Size(countSelectorField, s.count) + size += protoutil.EnumSize(countSelectorField, int32(s.clause)) + size += protoutil.StringSize(attributeSelectorField, s.attribute) + size += protoutil.StringSize(filterSelectorField, s.filter) + + return size +} + +func (s *Selector) Unmarshal(data []byte) error { + return message.Unmarshal(s, data, new(netmap.Selector)) +} + +func (r *Replica) StableMarshal(buf []byte) []byte { + if r == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, r.StableSize()) + } + + var offset int + + offset += protoutil.UInt32Marshal(countReplicaField, buf[offset:], r.count) + offset += protoutil.StringMarshal(selectorReplicaField, buf[offset:], r.selector) + offset += protoutil.UInt32Marshal(ecDataCountReplicaField, buf[offset:], r.ecDataCount) + protoutil.UInt32Marshal(ecParityCountReplicaField, buf[offset:], r.ecParityCount) + + return buf +} + +func (r *Replica) StableSize() (size int) { + if r == nil { + return 0 + } + + size += protoutil.UInt32Size(countReplicaField, r.count) + size += protoutil.StringSize(selectorReplicaField, r.selector) + size += protoutil.UInt32Size(ecDataCountReplicaField, r.ecDataCount) + size += protoutil.UInt32Size(ecParityCountReplicaField, r.ecParityCount) + + return size +} + +func (r *Replica) Unmarshal(data []byte) error { + return message.Unmarshal(r, data, new(netmap.Replica)) +} + +func (p *PlacementPolicy) StableMarshal(buf []byte) []byte { + if p == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, p.StableSize()) + } + + var offset int + + for i := range p.replicas { + offset += protoutil.NestedStructureMarshal(replicasPolicyField, buf[offset:], &p.replicas[i]) + } + + offset += protoutil.UInt32Marshal(backupPolicyField, buf[offset:], p.backupFactor) + + for i := range p.selectors { + offset += protoutil.NestedStructureMarshal(selectorsPolicyField, buf[offset:], &p.selectors[i]) + } + + for i := range p.filters { + offset += protoutil.NestedStructureMarshal(filtersPolicyField, buf[offset:], &p.filters[i]) + } + + protoutil.BoolMarshal(uniquePolicyField, buf[offset:], p.unique) + + return buf +} + +func (p *PlacementPolicy) StableSize() (size int) { + if p == nil { + return 0 + } + + for i := range p.replicas { + size += protoutil.NestedStructureSize(replicasPolicyField, &p.replicas[i]) + } + + size += protoutil.UInt32Size(backupPolicyField, p.backupFactor) + + for i := range p.selectors { + size += protoutil.NestedStructureSize(selectorsPolicyField, &p.selectors[i]) + } + + for i := range p.filters { + size += protoutil.NestedStructureSize(filtersPolicyField, &p.filters[i]) + } + + size += protoutil.BoolSize(uniquePolicyField, p.unique) + + return size +} + +func (p *PlacementPolicy) Unmarshal(data []byte) error { + return message.Unmarshal(p, data, new(netmap.PlacementPolicy)) +} + +func (a *Attribute) StableMarshal(buf []byte) []byte { + if a == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, a.StableSize()) + } + + var offset int + + offset += protoutil.StringMarshal(keyAttributeField, buf[offset:], a.key) + offset += protoutil.StringMarshal(valueAttributeField, buf[offset:], a.value) + + for i := range a.parents { + offset += protoutil.StringMarshal(parentsAttributeField, buf[offset:], a.parents[i]) + } + + return buf +} + +func (a *Attribute) StableSize() (size int) { + if a == nil { + return 0 + } + + size += protoutil.StringSize(keyAttributeField, a.key) + size += protoutil.StringSize(valueAttributeField, a.value) + + for i := range a.parents { + size += protoutil.StringSize(parentsAttributeField, a.parents[i]) + } + + return size +} + +func (a *Attribute) Unmarshal(data []byte) error { + return message.Unmarshal(a, data, new(netmap.NodeInfo_Attribute)) +} + +func (ni *NodeInfo) StableMarshal(buf []byte) []byte { + if ni == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, ni.StableSize()) + } + + var offset int + + offset += protoutil.BytesMarshal(keyNodeInfoField, buf[offset:], ni.publicKey) + offset += protoutil.RepeatedStringMarshal(addressNodeInfoField, buf[offset:], ni.addresses) + + for i := range ni.attributes { + offset += protoutil.NestedStructureMarshal(attributesNodeInfoField, buf[offset:], &ni.attributes[i]) + } + + protoutil.EnumMarshal(stateNodeInfoField, buf[offset:], int32(ni.state)) + + return buf +} + +func (ni *NodeInfo) StableSize() (size int) { + if ni == nil { + return 0 + } + + size += protoutil.BytesSize(keyNodeInfoField, ni.publicKey) + size += protoutil.RepeatedStringSize(addressNodeInfoField, ni.addresses) + + for i := range ni.attributes { + size += protoutil.NestedStructureSize(attributesNodeInfoField, &ni.attributes[i]) + } + + size += protoutil.EnumSize(stateNodeInfoField, int32(ni.state)) + + return size +} + +func (ni *NodeInfo) Unmarshal(data []byte) error { + return message.Unmarshal(ni, data, new(netmap.NodeInfo)) +} + +func (l *LocalNodeInfoRequestBody) StableMarshal(_ []byte) []byte { + return nil +} + +func (l *LocalNodeInfoRequestBody) StableSize() (size int) { + return 0 +} + +func (l *LocalNodeInfoRequestBody) Unmarshal([]byte) error { + return nil +} + +func (l *LocalNodeInfoResponseBody) StableMarshal(buf []byte) []byte { + if l == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, l.StableSize()) + } + + var offset int + + offset += protoutil.NestedStructureMarshal(versionInfoResponseBodyField, buf[offset:], l.version) + protoutil.NestedStructureMarshal(nodeInfoResponseBodyField, buf[offset:], l.nodeInfo) + + return buf +} + +func (l *LocalNodeInfoResponseBody) StableSize() (size int) { + if l == nil { + return 0 + } + + size += protoutil.NestedStructureSize(versionInfoResponseBodyField, l.version) + size += protoutil.NestedStructureSize(nodeInfoResponseBodyField, l.nodeInfo) + + return size +} + +func (l *LocalNodeInfoResponseBody) Unmarshal(data []byte) error { + return message.Unmarshal(l, data, new(netmap.LocalNodeInfoResponse_Body)) +} + +const ( + _ = iota + netPrmKeyFNum + netPrmValFNum +) + +func (x *NetworkParameter) StableMarshal(buf []byte) []byte { + if x == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, x.StableSize()) + } + + var offset int + + offset += protoutil.BytesMarshal(netPrmKeyFNum, buf[offset:], x.k) + protoutil.BytesMarshal(netPrmValFNum, buf[offset:], x.v) + + return buf +} + +func (x *NetworkParameter) StableSize() (size int) { + if x == nil { + return 0 + } + + size += protoutil.BytesSize(netPrmKeyFNum, x.k) + size += protoutil.BytesSize(netPrmValFNum, x.v) + + return size +} + +const ( + _ = iota + netCfgPrmsFNum +) + +func (x *NetworkConfig) StableMarshal(buf []byte) []byte { + if x == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, x.StableSize()) + } + + var offset int + + for i := range x.ps { + offset += protoutil.NestedStructureMarshal(netCfgPrmsFNum, buf[offset:], &x.ps[i]) + } + + return buf +} + +func (x *NetworkConfig) StableSize() (size int) { + if x == nil { + return 0 + } + + for i := range x.ps { + size += protoutil.NestedStructureSize(netCfgPrmsFNum, &x.ps[i]) + } + + return size +} + +const ( + _ = iota + netInfoCurEpochFNum + netInfoMagicNumFNum + netInfoMSPerBlockFNum + netInfoCfgFNum +) + +func (i *NetworkInfo) StableMarshal(buf []byte) []byte { + if i == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, i.StableSize()) + } + + var offset int + + offset += protoutil.UInt64Marshal(netInfoCurEpochFNum, buf[offset:], i.curEpoch) + offset += protoutil.UInt64Marshal(netInfoMagicNumFNum, buf[offset:], i.magicNum) + offset += protoutil.Int64Marshal(netInfoMSPerBlockFNum, buf[offset:], i.msPerBlock) + protoutil.NestedStructureMarshal(netInfoCfgFNum, buf[offset:], i.netCfg) + + return buf +} + +func (i *NetworkInfo) StableSize() (size int) { + if i == nil { + return 0 + } + + size += protoutil.UInt64Size(netInfoCurEpochFNum, i.curEpoch) + size += protoutil.UInt64Size(netInfoMagicNumFNum, i.magicNum) + size += protoutil.Int64Size(netInfoMSPerBlockFNum, i.msPerBlock) + size += protoutil.NestedStructureSize(netInfoCfgFNum, i.netCfg) + + return size +} + +func (i *NetworkInfo) Unmarshal(data []byte) error { + return message.Unmarshal(i, data, new(netmap.NetworkInfo)) +} + +func (l *NetworkInfoRequestBody) StableMarshal(_ []byte) []byte { + return nil +} + +func (l *NetworkInfoRequestBody) StableSize() (size int) { + return 0 +} + +func (l *NetworkInfoRequestBody) Unmarshal(data []byte) error { + return message.Unmarshal(l, data, new(netmap.NetworkInfoRequest_Body)) +} + +const ( + _ = iota + netInfoRespBodyNetInfoFNum +) + +func (i *NetworkInfoResponseBody) StableMarshal(buf []byte) []byte { + if i == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, i.StableSize()) + } + + protoutil.NestedStructureMarshal(netInfoRespBodyNetInfoFNum, buf, i.netInfo) + + return buf +} + +func (i *NetworkInfoResponseBody) StableSize() (size int) { + if i == nil { + return 0 + } + + size += protoutil.NestedStructureSize(netInfoRespBodyNetInfoFNum, i.netInfo) + + return size +} + +func (i *NetworkInfoResponseBody) Unmarshal(data []byte) error { + return message.Unmarshal(i, data, new(netmap.NetworkInfoResponse_Body)) +} + +const ( + _ = iota + fNumNetMapEpoch + fNumNetMapNodes +) + +func (x *NetMap) StableMarshal(buf []byte) []byte { + if x == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, x.StableSize()) + } + + offset := protoutil.UInt64Marshal(fNumNetMapEpoch, buf, x.epoch) + + for i := range x.nodes { + offset += protoutil.NestedStructureMarshal(fNumNetMapNodes, buf[offset:], &x.nodes[i]) + } + + return buf +} + +func (x *NetMap) StableSize() (size int) { + if x != nil { + size = protoutil.UInt64Size(fNumNetMapEpoch, x.epoch) + + for i := range x.nodes { + size += protoutil.NestedStructureSize(fNumNetMapNodes, &x.nodes[i]) + } + } + + return +} + +func (x *SnapshotRequestBody) StableMarshal([]byte) []byte { + return nil +} + +func (x *SnapshotRequestBody) StableSize() int { + return 0 +} + +const ( + _ = iota + fNumSnapshotResponseBodyNetMap +) + +func (x *SnapshotResponseBody) StableMarshal(buf []byte) []byte { + if x == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, x.StableSize()) + } + + protoutil.NestedStructureMarshal(fNumSnapshotResponseBodyNetMap, buf, x.netMap) + + return buf +} + +func (x *SnapshotResponseBody) StableSize() (size int) { + if x != nil { + size = protoutil.NestedStructureSize(fNumSnapshotResponseBodyNetMap, x.netMap) + } + + return +} diff --git a/api/netmap/message_test.go b/api/netmap/message_test.go new file mode 100644 index 0000000..2406ece --- /dev/null +++ b/api/netmap/message_test.go @@ -0,0 +1,32 @@ +package netmap_test + +import ( + "testing" + + netmaptest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/netmap/test" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/message" + messagetest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/message/test" +) + +func TestMessageConvert(t *testing.T) { + messagetest.TestRPCMessage(t, + func(empty bool) message.Message { return netmaptest.GenerateFilter(empty) }, + func(empty bool) message.Message { return netmaptest.GenerateSelector(empty) }, + func(empty bool) message.Message { return netmaptest.GenerateReplica(empty) }, + func(empty bool) message.Message { return netmaptest.GeneratePlacementPolicy(empty) }, + func(empty bool) message.Message { return netmaptest.GenerateAttribute(empty) }, + func(empty bool) message.Message { return netmaptest.GenerateNodeInfo(empty) }, + func(empty bool) message.Message { return netmaptest.GenerateLocalNodeInfoRequest(empty) }, + func(empty bool) message.Message { return netmaptest.GenerateLocalNodeInfoResponseBody(empty) }, + func(empty bool) message.Message { return netmaptest.GenerateNetworkParameter(empty) }, + func(empty bool) message.Message { return netmaptest.GenerateNetworkConfig(empty) }, + func(empty bool) message.Message { return netmaptest.GenerateNetworkInfo(empty) }, + func(empty bool) message.Message { return netmaptest.GenerateNetworkInfoRequest(empty) }, + func(empty bool) message.Message { return netmaptest.GenerateNetworkInfoResponseBody(empty) }, + func(empty bool) message.Message { return netmaptest.GenerateNetMap(empty) }, + func(empty bool) message.Message { return netmaptest.GenerateSnapshotRequestBody(empty) }, + func(empty bool) message.Message { return netmaptest.GenerateSnapshotRequest(empty) }, + func(empty bool) message.Message { return netmaptest.GenerateSnapshotResponseBody(empty) }, + func(empty bool) message.Message { return netmaptest.GenerateSnapshotResponse(empty) }, + ) +} diff --git a/api/netmap/string.go b/api/netmap/string.go new file mode 100644 index 0000000..a6805ae --- /dev/null +++ b/api/netmap/string.go @@ -0,0 +1,68 @@ +package netmap + +import ( + netmap "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/netmap/grpc" +) + +// String returns string representation of Clause. +func (x Clause) String() string { + return ClauseToGRPCMessage(x).String() +} + +// FromString parses Clause from a string representation. +// It is a reverse action to String(). +// +// Returns true if s was parsed successfully. +func (x *Clause) FromString(s string) bool { + var g netmap.Clause + + ok := g.FromString(s) + + if ok { + *x = ClauseFromGRPCMessage(g) + } + + return ok +} + +// String returns string representation of Operation. +func (x Operation) String() string { + return OperationToGRPCMessage(x).String() +} + +// FromString parses Operation from a string representation. +// It is a reverse action to String(). +// +// Returns true if s was parsed successfully. +func (x *Operation) FromString(s string) bool { + var g netmap.Operation + + ok := g.FromString(s) + + if ok { + *x = OperationFromGRPCMessage(g) + } + + return ok +} + +// String returns string representation of NodeState. +func (x NodeState) String() string { + return NodeStateToGRPCMessage(x).String() +} + +// FromString parses NodeState from a string representation. +// It is a reverse action to String(). +// +// Returns true if s was parsed successfully. +func (x *NodeState) FromString(s string) bool { + var g netmap.NodeInfo_State + + ok := g.FromString(s) + + if ok { + *x = NodeStateFromRPCMessage(g) + } + + return ok +} diff --git a/api/netmap/test/generate.go b/api/netmap/test/generate.go new file mode 100644 index 0000000..4ac9254 --- /dev/null +++ b/api/netmap/test/generate.go @@ -0,0 +1,335 @@ +package netmaptest + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/netmap" + refstest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs/test" + sessiontest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session/test" +) + +func GenerateFilter(empty bool) *netmap.Filter { + return generateFilter(empty, true) +} + +func generateFilter(empty, withSub bool) *netmap.Filter { + m := new(netmap.Filter) + + if !empty { + m.SetKey("filter key") + m.SetValue("filter value") + m.SetName("filter name") + m.SetOp(1) + + if withSub { + m.SetFilters([]netmap.Filter{ + *generateFilter(empty, false), + *generateFilter(empty, false), + }) + } + } + + return m +} + +func GenerateFilters(empty bool) []netmap.Filter { + var res []netmap.Filter + + if !empty { + res = append(res, + *GenerateFilter(false), + *GenerateFilter(false), + ) + } + + return res +} + +func GenerateSelector(empty bool) *netmap.Selector { + m := new(netmap.Selector) + + if !empty { + m.SetCount(66) + m.SetAttribute("selector attribute") + m.SetFilter("select filter") + m.SetName("select name") + m.SetClause(1) + } + + return m +} + +func GenerateSelectors(empty bool) []netmap.Selector { + var res []netmap.Selector + + if !empty { + res = append(res, + *GenerateSelector(false), + *GenerateSelector(false), + ) + } + + return res +} + +func GenerateReplica(empty bool) *netmap.Replica { + m := new(netmap.Replica) + + if !empty { + m.SetCount(42) + m.SetSelector("replica selector") + } + + return m +} + +func GenerateEC(empty bool) *netmap.Replica { + m := new(netmap.Replica) + + if !empty { + m.SetECDataCount(4) + m.SetECParityCount(2) + } + + return m +} + +func GenerateReplicas(empty bool) []netmap.Replica { + var res []netmap.Replica + + if !empty { + res = append(res, + *GenerateReplica(false), + *GenerateReplica(false), + *GenerateEC(false), + ) + } + + return res +} + +func GeneratePlacementPolicy(empty bool) *netmap.PlacementPolicy { + m := new(netmap.PlacementPolicy) + + if !empty { + m.SetContainerBackupFactor(322) + m.SetFilters(GenerateFilters(false)) + m.SetSelectors(GenerateSelectors(false)) + m.SetReplicas(GenerateReplicas(false)) + m.SetUnique(true) + } + + return m +} + +func GenerateAttribute(empty bool) *netmap.Attribute { + m := new(netmap.Attribute) + + if !empty { + m.SetKey("attribute key") + m.SetValue("attribute val") + } + + return m +} + +func GenerateAttributes(empty bool) []netmap.Attribute { + var res []netmap.Attribute + + if !empty { + res = append(res, + *GenerateAttribute(false), + *GenerateAttribute(false), + ) + } + + return res +} + +func GenerateNodeInfo(empty bool) *netmap.NodeInfo { + m := new(netmap.NodeInfo) + + if !empty { + m.SetAddresses("node address", "node address 2") + m.SetPublicKey([]byte{1, 2, 3}) + m.SetState(33) + m.SetAttributes(GenerateAttributes(empty)) + } + + return m +} + +func GenerateLocalNodeInfoRequestBody(_ bool) *netmap.LocalNodeInfoRequestBody { + m := new(netmap.LocalNodeInfoRequestBody) + + return m +} + +func GenerateLocalNodeInfoRequest(empty bool) *netmap.LocalNodeInfoRequest { + m := new(netmap.LocalNodeInfoRequest) + + if !empty { + m.SetBody(GenerateLocalNodeInfoRequestBody(false)) + } + + m.SetMetaHeader(sessiontest.GenerateRequestMetaHeader(empty)) + m.SetVerificationHeader(sessiontest.GenerateRequestVerificationHeader(empty)) + + return m +} + +func GenerateLocalNodeInfoResponseBody(empty bool) *netmap.LocalNodeInfoResponseBody { + m := new(netmap.LocalNodeInfoResponseBody) + + if !empty { + m.SetNodeInfo(GenerateNodeInfo(false)) + } + + m.SetVersion(refstest.GenerateVersion(empty)) + + return m +} + +func GenerateLocalNodeInfoResponse(empty bool) *netmap.LocalNodeInfoResponse { + m := new(netmap.LocalNodeInfoResponse) + + if !empty { + m.SetBody(GenerateLocalNodeInfoResponseBody(false)) + } + + m.SetMetaHeader(sessiontest.GenerateResponseMetaHeader(empty)) + m.SetVerificationHeader(sessiontest.GenerateResponseVerificationHeader(empty)) + + return m +} + +func GenerateNetworkParameter(empty bool) *netmap.NetworkParameter { + m := new(netmap.NetworkParameter) + + if !empty { + m.SetKey([]byte("key")) + m.SetValue([]byte("value")) + } + + return m +} + +func GenerateNetworkConfig(empty bool) *netmap.NetworkConfig { + m := new(netmap.NetworkConfig) + + if !empty { + m.SetParameters( + *GenerateNetworkParameter(empty), + *GenerateNetworkParameter(empty), + ) + } + + return m +} + +func GenerateNetworkInfo(empty bool) *netmap.NetworkInfo { + m := new(netmap.NetworkInfo) + + if !empty { + m.SetMagicNumber(228) + m.SetCurrentEpoch(666) + m.SetMsPerBlock(5678) + m.SetNetworkConfig(GenerateNetworkConfig(empty)) + } + + return m +} + +func GenerateNetworkInfoRequestBody(_ bool) *netmap.NetworkInfoRequestBody { + m := new(netmap.NetworkInfoRequestBody) + + return m +} + +func GenerateNetworkInfoRequest(empty bool) *netmap.NetworkInfoRequest { + m := new(netmap.NetworkInfoRequest) + + if !empty { + m.SetBody(GenerateNetworkInfoRequestBody(false)) + } + + m.SetMetaHeader(sessiontest.GenerateRequestMetaHeader(empty)) + m.SetVerificationHeader(sessiontest.GenerateRequestVerificationHeader(empty)) + + return m +} + +func GenerateNetworkInfoResponseBody(empty bool) *netmap.NetworkInfoResponseBody { + m := new(netmap.NetworkInfoResponseBody) + + if !empty { + m.SetNetworkInfo(GenerateNetworkInfo(false)) + } + + return m +} + +func GenerateNetworkInfoResponse(empty bool) *netmap.NetworkInfoResponse { + m := new(netmap.NetworkInfoResponse) + + if !empty { + m.SetBody(GenerateNetworkInfoResponseBody(false)) + } + + m.SetMetaHeader(sessiontest.GenerateResponseMetaHeader(empty)) + m.SetVerificationHeader(sessiontest.GenerateResponseVerificationHeader(empty)) + + return m +} + +func GenerateNetMap(empty bool) *netmap.NetMap { + m := new(netmap.NetMap) + + if !empty { + m.SetEpoch(987) + m.SetNodes([]netmap.NodeInfo{ + *GenerateNodeInfo(false), + *GenerateNodeInfo(false), + }) + } + + return m +} + +func GenerateSnapshotRequestBody(_ bool) *netmap.SnapshotRequestBody { + return new(netmap.SnapshotRequestBody) +} + +func GenerateSnapshotRequest(empty bool) *netmap.SnapshotRequest { + m := new(netmap.SnapshotRequest) + + if !empty { + m.SetBody(GenerateSnapshotRequestBody(false)) + } + + m.SetMetaHeader(sessiontest.GenerateRequestMetaHeader(empty)) + m.SetVerificationHeader(sessiontest.GenerateRequestVerificationHeader(empty)) + + return m +} + +func GenerateSnapshotResponseBody(empty bool) *netmap.SnapshotResponseBody { + m := new(netmap.SnapshotResponseBody) + + if !empty { + m.SetNetMap(GenerateNetMap(false)) + } + + return m +} + +func GenerateSnapshotResponse(empty bool) *netmap.SnapshotResponse { + m := new(netmap.SnapshotResponse) + + if !empty { + m.SetBody(GenerateSnapshotResponseBody(false)) + } + + m.SetMetaHeader(sessiontest.GenerateResponseMetaHeader(empty)) + m.SetVerificationHeader(sessiontest.GenerateResponseVerificationHeader(empty)) + + return m +} diff --git a/api/netmap/types.go b/api/netmap/types.go new file mode 100644 index 0000000..877357d --- /dev/null +++ b/api/netmap/types.go @@ -0,0 +1,783 @@ +package netmap + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" +) + +type LocalNodeInfoRequest struct { + body *LocalNodeInfoRequestBody + + session.RequestHeaders +} + +type LocalNodeInfoResponse struct { + body *LocalNodeInfoResponseBody + + session.ResponseHeaders +} + +// NetworkInfoRequest is a structure of NetworkInfo request. +type NetworkInfoRequest struct { + body *NetworkInfoRequestBody + + session.RequestHeaders +} + +// NetworkInfoResponse is a structure of NetworkInfo response. +type NetworkInfoResponse struct { + body *NetworkInfoResponseBody + + session.ResponseHeaders +} + +type Filter struct { + name string + key string + op Operation + value string + filters []Filter +} + +type Selector struct { + name string + count uint32 + clause Clause + attribute string + filter string +} + +type Replica struct { + count uint32 + selector string + + ecDataCount uint32 + ecParityCount uint32 +} + +type Operation uint32 + +type PlacementPolicy struct { + replicas []Replica + backupFactor uint32 + selectors []Selector + filters []Filter + unique bool +} + +// Attribute of storage node. +type Attribute struct { + key string + value string + parents []string +} + +// NodeInfo of storage node. +type NodeInfo struct { + publicKey []byte + addresses []string + attributes []Attribute + state NodeState +} + +// NodeState of storage node. +type NodeState uint32 + +// Clause of placement selector. +type Clause uint32 + +type LocalNodeInfoRequestBody struct{} + +type LocalNodeInfoResponseBody struct { + version *refs.Version + nodeInfo *NodeInfo +} + +const ( + UnspecifiedState NodeState = iota + Online + Offline + Maintenance +) + +const ( + UnspecifiedOperation Operation = iota + EQ + NE + GT + GE + LT + LE + OR + AND + NOT + LIKE +) + +const ( + UnspecifiedClause Clause = iota + Same + Distinct +) + +func (f *Filter) GetFilters() []Filter { + if f != nil { + return f.filters + } + + return nil +} + +func (f *Filter) SetFilters(filters []Filter) { + f.filters = filters +} + +func (f *Filter) GetValue() string { + if f != nil { + return f.value + } + + return "" +} + +func (f *Filter) SetValue(value string) { + f.value = value +} + +func (f *Filter) GetOp() Operation { + if f != nil { + return f.op + } + return UnspecifiedOperation +} + +func (f *Filter) SetOp(op Operation) { + f.op = op +} + +func (f *Filter) GetKey() string { + if f != nil { + return f.key + } + + return "" +} + +func (f *Filter) SetKey(key string) { + f.key = key +} + +func (f *Filter) GetName() string { + if f != nil { + return f.name + } + + return "" +} + +func (f *Filter) SetName(name string) { + f.name = name +} + +func (s *Selector) GetFilter() string { + if s != nil { + return s.filter + } + + return "" +} + +func (s *Selector) SetFilter(filter string) { + s.filter = filter +} + +func (s *Selector) GetAttribute() string { + if s != nil { + return s.attribute + } + + return "" +} + +func (s *Selector) SetAttribute(attribute string) { + s.attribute = attribute +} + +func (s *Selector) GetClause() Clause { + if s != nil { + return s.clause + } + + return UnspecifiedClause +} + +func (s *Selector) SetClause(clause Clause) { + s.clause = clause +} + +func (s *Selector) GetCount() uint32 { + if s != nil { + return s.count + } + + return 0 +} + +func (s *Selector) SetCount(count uint32) { + s.count = count +} + +func (s *Selector) GetName() string { + if s != nil { + return s.name + } + + return "" +} + +func (s *Selector) SetName(name string) { + s.name = name +} + +func (r *Replica) GetSelector() string { + if r != nil { + return r.selector + } + + return "" +} + +func (r *Replica) SetSelector(selector string) { + r.selector = selector +} + +func (r *Replica) GetCount() uint32 { + if r != nil { + return r.count + } + + return 0 +} + +func (r *Replica) SetCount(count uint32) { + r.count = count +} + +func (r *Replica) GetECDataCount() uint32 { + if r != nil { + return r.ecDataCount + } + + return 0 +} + +func (r *Replica) SetECDataCount(count uint32) { + r.ecDataCount = count +} + +func (r *Replica) GetECParityCount() uint32 { + if r != nil { + return r.ecParityCount + } + + return 0 +} + +func (r *Replica) SetECParityCount(count uint32) { + r.ecParityCount = count +} + +func (p *PlacementPolicy) GetUnique() bool { + if p != nil { + return p.unique + } + return false +} + +func (p *PlacementPolicy) SetUnique(unique bool) { + p.unique = unique +} + +func (p *PlacementPolicy) GetFilters() []Filter { + if p != nil { + return p.filters + } + + return nil +} + +func (p *PlacementPolicy) SetFilters(filters []Filter) { + p.filters = filters +} + +func (p *PlacementPolicy) GetSelectors() []Selector { + if p != nil { + return p.selectors + } + + return nil +} + +func (p *PlacementPolicy) SetSelectors(selectors []Selector) { + p.selectors = selectors +} + +func (p *PlacementPolicy) GetContainerBackupFactor() uint32 { + if p != nil { + return p.backupFactor + } + + return 0 +} + +func (p *PlacementPolicy) SetContainerBackupFactor(backupFactor uint32) { + p.backupFactor = backupFactor +} + +func (p *PlacementPolicy) GetReplicas() []Replica { + if p == nil { + return nil + } + + return p.replicas +} + +func (p *PlacementPolicy) SetReplicas(replicas []Replica) { + p.replicas = replicas +} + +func (a *Attribute) GetKey() string { + if a != nil { + return a.key + } + + return "" +} + +func (a *Attribute) SetKey(v string) { + a.key = v +} + +func (a *Attribute) GetValue() string { + if a != nil { + return a.value + } + + return "" +} + +func (a *Attribute) SetValue(v string) { + a.value = v +} + +func (a *Attribute) GetParents() []string { + if a != nil { + return a.parents + } + + return nil +} + +func (a *Attribute) SetParents(parent []string) { + a.parents = parent +} + +func (ni *NodeInfo) GetPublicKey() []byte { + if ni != nil { + return ni.publicKey + } + + return nil +} + +func (ni *NodeInfo) SetPublicKey(v []byte) { + ni.publicKey = v +} + +// GetAddress returns node's network address. +// +// Deprecated: use IterateAddresses. +func (ni *NodeInfo) GetAddress() (addr string) { + ni.IterateAddresses(func(s string) bool { + addr = s + return true + }) + + return +} + +// SetAddress sets node's network address. +// +// Deprecated: use SetAddresses. +func (ni *NodeInfo) SetAddress(v string) { + ni.SetAddresses(v) +} + +// SetAddresses sets list of network addresses of the node. +func (ni *NodeInfo) SetAddresses(v ...string) { + ni.addresses = v +} + +// NumberOfAddresses returns number of network addresses of the node. +func (ni *NodeInfo) NumberOfAddresses() int { + if ni != nil { + return len(ni.addresses) + } + + return 0 +} + +// IterateAddresses iterates over network addresses of the node. +// Breaks iteration on f's true return. +// +// Handler should not be nil. +func (ni *NodeInfo) IterateAddresses(f func(string) bool) { + if ni != nil { + for i := range ni.addresses { + if f(ni.addresses[i]) { + break + } + } + } +} + +func (ni *NodeInfo) GetAttributes() []Attribute { + if ni != nil { + return ni.attributes + } + + return nil +} + +func (ni *NodeInfo) SetAttributes(v []Attribute) { + ni.attributes = v +} + +func (ni *NodeInfo) GetState() NodeState { + if ni != nil { + return ni.state + } + + return UnspecifiedState +} + +func (ni *NodeInfo) SetState(state NodeState) { + ni.state = state +} + +func (l *LocalNodeInfoResponseBody) GetVersion() *refs.Version { + if l != nil { + return l.version + } + + return nil +} + +func (l *LocalNodeInfoResponseBody) SetVersion(version *refs.Version) { + l.version = version +} + +func (l *LocalNodeInfoResponseBody) GetNodeInfo() *NodeInfo { + if l != nil { + return l.nodeInfo + } + + return nil +} + +func (l *LocalNodeInfoResponseBody) SetNodeInfo(nodeInfo *NodeInfo) { + l.nodeInfo = nodeInfo +} + +func (l *LocalNodeInfoRequest) GetBody() *LocalNodeInfoRequestBody { + if l != nil { + return l.body + } + return nil +} + +func (l *LocalNodeInfoRequest) SetBody(body *LocalNodeInfoRequestBody) { + l.body = body +} + +func (l *LocalNodeInfoResponse) GetBody() *LocalNodeInfoResponseBody { + if l != nil { + return l.body + } + return nil +} + +func (l *LocalNodeInfoResponse) SetBody(body *LocalNodeInfoResponseBody) { + l.body = body +} + +// NetworkParameter represents NeoFS network parameter. +type NetworkParameter struct { + k, v []byte +} + +// GetKey returns parameter key. +func (x *NetworkParameter) GetKey() []byte { + if x != nil { + return x.k + } + + return nil +} + +// SetKey sets parameter key. +func (x *NetworkParameter) SetKey(k []byte) { + x.k = k +} + +// GetValue returns parameter value. +func (x *NetworkParameter) GetValue() []byte { + if x != nil { + return x.v + } + + return nil +} + +// SetValue sets parameter value. +func (x *NetworkParameter) SetValue(v []byte) { + x.v = v +} + +// NetworkConfig represents NeoFS network configuration. +type NetworkConfig struct { + ps []NetworkParameter +} + +// NumberOfParameters returns number of network parameters. +func (x *NetworkConfig) NumberOfParameters() int { + if x != nil { + return len(x.ps) + } + + return 0 +} + +// IterateParameters iterates over network parameters. +// Breaks iteration on f's true return. +// +// Handler must not be nil. +func (x *NetworkConfig) IterateParameters(f func(*NetworkParameter) bool) { + if x != nil { + for i := range x.ps { + if f(&x.ps[i]) { + break + } + } + } +} + +// SetParameters sets list of network parameters. +func (x *NetworkConfig) SetParameters(v ...NetworkParameter) { + x.ps = v +} + +// NetworkInfo groups information about +// NeoFS network. +type NetworkInfo struct { + curEpoch, magicNum uint64 + + msPerBlock int64 + + netCfg *NetworkConfig +} + +// GetCurrentEpoch returns number of the current epoch. +func (i *NetworkInfo) GetCurrentEpoch() uint64 { + if i != nil { + return i.curEpoch + } + + return 0 +} + +// SetCurrentEpoch sets number of the current epoch. +func (i *NetworkInfo) SetCurrentEpoch(epoch uint64) { + i.curEpoch = epoch +} + +// GetMagicNumber returns magic number of the sidechain. +func (i *NetworkInfo) GetMagicNumber() uint64 { + if i != nil { + return i.magicNum + } + + return 0 +} + +// SetMagicNumber sets magic number of the sidechain. +func (i *NetworkInfo) SetMagicNumber(magic uint64) { + i.magicNum = magic +} + +// GetMsPerBlock returns MillisecondsPerBlock network parameter. +func (i *NetworkInfo) GetMsPerBlock() int64 { + if i != nil { + return i.msPerBlock + } + + return 0 +} + +// SetMsPerBlock sets MillisecondsPerBlock network parameter. +func (i *NetworkInfo) SetMsPerBlock(v int64) { + i.msPerBlock = v +} + +// GetNetworkConfig returns NeoFS network configuration. +func (i *NetworkInfo) GetNetworkConfig() *NetworkConfig { + if i != nil { + return i.netCfg + } + + return nil +} + +// SetNetworkConfig sets NeoFS network configuration. +func (i *NetworkInfo) SetNetworkConfig(v *NetworkConfig) { + i.netCfg = v +} + +// NetworkInfoRequestBody is a structure of NetworkInfo request body. +type NetworkInfoRequestBody struct{} + +// NetworkInfoResponseBody is a structure of NetworkInfo response body. +type NetworkInfoResponseBody struct { + netInfo *NetworkInfo +} + +// GetNetworkInfo returns information about the NeoFS network. +func (i *NetworkInfoResponseBody) GetNetworkInfo() *NetworkInfo { + if i != nil { + return i.netInfo + } + + return nil +} + +// SetNetworkInfo sets information about the NeoFS network. +func (i *NetworkInfoResponseBody) SetNetworkInfo(netInfo *NetworkInfo) { + i.netInfo = netInfo +} + +func (l *NetworkInfoRequest) GetBody() *NetworkInfoRequestBody { + if l != nil { + return l.body + } + return nil +} + +func (l *NetworkInfoRequest) SetBody(body *NetworkInfoRequestBody) { + l.body = body +} + +func (l *NetworkInfoResponse) GetBody() *NetworkInfoResponseBody { + if l != nil { + return l.body + } + return nil +} + +func (l *NetworkInfoResponse) SetBody(body *NetworkInfoResponseBody) { + l.body = body +} + +// NetMap represents structure of NeoFS network map. +type NetMap struct { + epoch uint64 + + nodes []NodeInfo +} + +// Epoch returns revision number of the NetMap. +func (x *NetMap) Epoch() uint64 { + if x != nil { + return x.epoch + } + + return 0 +} + +// SetEpoch sets revision number of the NetMap. +func (x *NetMap) SetEpoch(v uint64) { + x.epoch = v +} + +// Nodes returns nodes presented in the NetMap. +func (x *NetMap) Nodes() []NodeInfo { + if x != nil { + return x.nodes + } + + return nil +} + +// SetNodes sets nodes presented in the NetMap. +func (x *NetMap) SetNodes(v []NodeInfo) { + x.nodes = v +} + +// SnapshotRequestBody represents structure of Snapshot request body. +type SnapshotRequestBody struct{} + +// SnapshotRequest represents structure of Snapshot request. +type SnapshotRequest struct { + body *SnapshotRequestBody + + session.RequestHeaders +} + +func (x *SnapshotRequest) GetBody() *SnapshotRequestBody { + if x != nil { + return x.body + } + + return nil +} + +func (x *SnapshotRequest) SetBody(body *SnapshotRequestBody) { + x.body = body +} + +// SnapshotResponseBody represents structure of Snapshot response body. +type SnapshotResponseBody struct { + netMap *NetMap +} + +// NetMap returns current NetMap. +func (x *SnapshotResponseBody) NetMap() *NetMap { + if x != nil { + return x.netMap + } + + return nil +} + +// SetNetMap sets current NetMap. +func (x *SnapshotResponseBody) SetNetMap(netMap *NetMap) { + x.netMap = netMap +} + +// SnapshotResponse represents structure of Snapshot response. +type SnapshotResponse struct { + body *SnapshotResponseBody + + session.ResponseHeaders +} + +func (x *SnapshotResponse) GetBody() *SnapshotResponseBody { + if x != nil { + return x.body + } + + return nil +} + +func (x *SnapshotResponse) SetBody(body *SnapshotResponseBody) { + x.body = body +} diff --git a/api/object/attributes.go b/api/object/attributes.go new file mode 100644 index 0000000..7f4fca0 --- /dev/null +++ b/api/object/attributes.go @@ -0,0 +1,187 @@ +package object + +import ( + "errors" + "fmt" + "strconv" +) + +// SysAttributePrefix is a prefix of key to system attribute. +const SysAttributePrefix = "__SYSTEM__" + +const ( + // SysAttributeUploadID marks smaller parts of a split bigger object. + SysAttributeUploadID = SysAttributePrefix + "UPLOAD_ID" + + // SysAttributeExpEpoch tells GC to delete object after that epoch. + SysAttributeExpEpoch = SysAttributePrefix + "EXPIRATION_EPOCH" + + // SysAttributeTickEpoch defines what epoch must produce object + // notification. + SysAttributeTickEpoch = SysAttributePrefix + "TICK_EPOCH" + + // SysAttributeTickTopic defines what topic object notification + // must be sent to. + SysAttributeTickTopic = SysAttributePrefix + "TICK_TOPIC" +) + +// SysAttributePrefixNeoFS is a prefix of key to system attribute. +// Deprecated: use SysAttributePrefix. +const SysAttributePrefixNeoFS = "__NEOFS__" + +const ( + // SysAttributeUploadIDNeoFS marks smaller parts of a split bigger object. + // Deprecated: use SysAttributeUploadID. + SysAttributeUploadIDNeoFS = SysAttributePrefixNeoFS + "UPLOAD_ID" + + // SysAttributeExpEpochNeoFS tells GC to delete object after that epoch. + // Deprecated: use SysAttributeExpEpoch. + SysAttributeExpEpochNeoFS = SysAttributePrefixNeoFS + "EXPIRATION_EPOCH" + + // SysAttributeTickEpochNeoFS defines what epoch must produce object + // notification. + // Deprecated: use SysAttributeTickEpoch. + SysAttributeTickEpochNeoFS = SysAttributePrefixNeoFS + "TICK_EPOCH" + + // SysAttributeTickTopicNeoFS defines what topic object notification + // must be sent to. + // Deprecated: use SysAttributeTickTopic. + SysAttributeTickTopicNeoFS = SysAttributePrefixNeoFS + "TICK_TOPIC" +) + +// NotificationInfo groups information about object notification +// that can be written to object. +// +// Topic is an optional field. +type NotificationInfo struct { + epoch uint64 + topic string +} + +// Epoch returns object notification tick +// epoch. +func (n NotificationInfo) Epoch() uint64 { + return n.epoch +} + +// SetEpoch sets object notification tick +// epoch. +func (n *NotificationInfo) SetEpoch(epoch uint64) { + n.epoch = epoch +} + +// Topic return optional object notification +// topic. +func (n NotificationInfo) Topic() string { + return n.topic +} + +// SetTopic sets optional object notification +// topic. +func (n *NotificationInfo) SetTopic(topic string) { + n.topic = topic +} + +// WriteNotificationInfo writes NotificationInfo to the Object via attributes. Object must not be nil. +// +// Existing notification attributes are expected to be key-unique, otherwise undefined behavior. +func WriteNotificationInfo(o *Object, ni NotificationInfo) { + h := o.GetHeader() + if h == nil { + h = new(Header) + o.SetHeader(h) + } + + var ( + attrs = h.GetAttributes() + + epoch = strconv.FormatUint(ni.Epoch(), 10) + topic = ni.Topic() + + changedEpoch bool + changedTopic bool + deleteIndex = -1 + ) + + for i := range attrs { + switch attrs[i].GetKey() { + case SysAttributeTickEpoch, SysAttributeTickEpochNeoFS: + attrs[i].SetValue(epoch) + changedEpoch = true + case SysAttributeTickTopic, SysAttributeTickTopicNeoFS: + changedTopic = true + + if topic == "" { + deleteIndex = i + break + } + + attrs[i].SetValue(topic) + } + + if changedEpoch && changedTopic { + break + } + } + + if deleteIndex != -1 { + // approach without allocation/waste + // coping works since the attributes + // order is not important + attrs[deleteIndex] = attrs[len(attrs)-1] + attrs = attrs[:len(attrs)-1] + } + + if !changedEpoch { + index := len(attrs) + attrs = append(attrs, Attribute{}) + attrs[index].SetKey(SysAttributeTickEpoch) + attrs[index].SetValue(epoch) + } + + if !changedTopic && topic != "" { + index := len(attrs) + attrs = append(attrs, Attribute{}) + attrs[index].SetKey(SysAttributeTickTopic) + attrs[index].SetValue(topic) + } + + h.SetAttributes(attrs) +} + +// ErrNotificationNotSet means that object does not have notification. +var ErrNotificationNotSet = errors.New("notification for object is not set") + +// GetNotificationInfo looks for object notification attributes. Object must not be nil. +// Returns ErrNotificationNotSet if no corresponding attributes +// were found. +// +// Existing notification attributes are expected to be key-unique, otherwise undefined behavior. +func GetNotificationInfo(o *Object) (*NotificationInfo, error) { + var ( + foundEpoch bool + ni = new(NotificationInfo) + ) + + for _, attr := range o.GetHeader().GetAttributes() { + switch key := attr.GetKey(); key { + case SysAttributeTickEpoch, SysAttributeTickEpochNeoFS: + epoch, err := strconv.ParseUint(attr.GetValue(), 10, 64) + if err != nil { + return nil, fmt.Errorf("could not parse epoch: %w", err) + } + + ni.SetEpoch(epoch) + + foundEpoch = true + case SysAttributeTickTopic, SysAttributeTickTopicNeoFS: + ni.SetTopic(attr.GetValue()) + } + } + + if !foundEpoch { + return nil, ErrNotificationNotSet + } + + return ni, nil +} diff --git a/api/object/attributes_test.go b/api/object/attributes_test.go new file mode 100644 index 0000000..85635da --- /dev/null +++ b/api/object/attributes_test.go @@ -0,0 +1,89 @@ +package object + +import ( + "strconv" + "testing" + + "github.com/stretchr/testify/require" +) + +func TestSetNotification(t *testing.T) { + o := new(Object) + + ni := NotificationInfo{ + epoch: 10, + topic: "test", + } + + WriteNotificationInfo(o, ni) + + var foundEpoch, foundTopic bool + + for _, attr := range o.GetHeader().GetAttributes() { + switch key := attr.GetKey(); key { + case SysAttributeTickEpoch: + require.Equal(t, false, foundEpoch) + + uEpoch, err := strconv.ParseUint(attr.GetValue(), 10, 64) + require.NoError(t, err) + + require.Equal(t, ni.Epoch(), uEpoch) + foundEpoch = true + case SysAttributeTickTopic: + require.Equal(t, false, foundTopic) + require.Equal(t, ni.Topic(), attr.GetValue()) + foundTopic = true + } + } + + require.Equal(t, true, foundEpoch && foundTopic) +} + +func TestGetNotification(t *testing.T) { + o := new(Object) + + attr := []Attribute{ + {SysAttributeTickEpoch, "10"}, + {SysAttributeTickTopic, "test"}, + } + + h := new(Header) + h.SetAttributes(attr) + + o.SetHeader(h) + + t.Run("No error", func(t *testing.T) { + ni, err := GetNotificationInfo(o) + require.NoError(t, err) + + require.Equal(t, uint64(10), ni.Epoch()) + require.Equal(t, "test", ni.Topic()) + }) +} + +func TestIntegration(t *testing.T) { + o := new(Object) + + var ( + ni1 = NotificationInfo{ + epoch: 10, + topic: "", + } + ni2 = NotificationInfo{ + epoch: 11, + topic: "test", + } + ) + + WriteNotificationInfo(o, ni1) + WriteNotificationInfo(o, ni2) + + t.Run("double set", func(t *testing.T) { + ni, err := GetNotificationInfo(o) + require.NoError(t, err) + + require.Equal(t, ni2.epoch, ni.Epoch()) + require.Equal(t, ni2.topic, ni.Topic()) + require.Equal(t, 2, len(o.GetHeader().GetAttributes())) + }) +} diff --git a/api/object/bench_test.go b/api/object/bench_test.go new file mode 100644 index 0000000..b29b1d1 --- /dev/null +++ b/api/object/bench_test.go @@ -0,0 +1,45 @@ +package object + +import ( + "math/rand" + "testing" + + "github.com/stretchr/testify/require" +) + +func randString(n int) string { + x := make([]byte, n) + for i := range x { + x[i] = byte('a' + rand.Intn('z'-'a')) + } + return string(x) +} + +func BenchmarkAttributesMarshal(b *testing.B) { + attrs := make([]Attribute, 50) + for i := range attrs { + attrs[i].key = SysAttributePrefix + randString(10) + attrs[i].val = randString(10) + } + raw := AttributesToGRPC(attrs) + require.Equal(b, len(raw), len(attrs)) + + b.Run("marshal", func(b *testing.B) { + b.ReportAllocs() + for range b.N { + res := AttributesToGRPC(attrs) + if len(res) != len(raw) { + b.FailNow() + } + } + }) + b.Run("unmarshal", func(b *testing.B) { + b.ReportAllocs() + for range b.N { + res, err := AttributesFromGRPC(raw) + if err != nil || len(res) != len(raw) { + b.FailNow() + } + } + }) +} diff --git a/api/object/convert.go b/api/object/convert.go new file mode 100644 index 0000000..7fb1d74 --- /dev/null +++ b/api/object/convert.go @@ -0,0 +1,2555 @@ +package object + +import ( + "fmt" + + object "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" + refsGRPC "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/message" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" + sessionGRPC "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session/grpc" +) + +func TypeToGRPCField(t Type) object.ObjectType { + return object.ObjectType(t) +} + +func TypeFromGRPCField(t object.ObjectType) Type { + return Type(t) +} + +func MatchTypeToGRPCField(t MatchType) object.MatchType { + return object.MatchType(t) +} + +func MatchTypeFromGRPCField(t object.MatchType) MatchType { + return MatchType(t) +} + +func (h *ShortHeader) ToGRPCMessage() grpc.Message { + var m *object.ShortHeader + + if h != nil { + m = new(object.ShortHeader) + + m.SetVersion(h.version.ToGRPCMessage().(*refsGRPC.Version)) + m.SetOwnerId(h.ownerID.ToGRPCMessage().(*refsGRPC.OwnerID)) + m.SetHomomorphicHash(h.homoHash.ToGRPCMessage().(*refsGRPC.Checksum)) + m.SetPayloadHash(h.payloadHash.ToGRPCMessage().(*refsGRPC.Checksum)) + m.SetObjectType(TypeToGRPCField(h.typ)) + m.SetCreationEpoch(h.creatEpoch) + m.SetPayloadLength(h.payloadLen) + } + + return m +} + +func (h *ShortHeader) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.ShortHeader) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + version := v.GetVersion() + if version == nil { + h.version = nil + } else { + if h.version == nil { + h.version = new(refs.Version) + } + + err = h.version.FromGRPCMessage(version) + if err != nil { + return err + } + } + + ownerID := v.GetOwnerId() + if ownerID == nil { + h.ownerID = nil + } else { + if h.ownerID == nil { + h.ownerID = new(refs.OwnerID) + } + + err = h.ownerID.FromGRPCMessage(ownerID) + if err != nil { + return err + } + } + + homoHash := v.GetHomomorphicHash() + if homoHash == nil { + h.homoHash = nil + } else { + if h.homoHash == nil { + h.homoHash = new(refs.Checksum) + } + + err = h.homoHash.FromGRPCMessage(homoHash) + if err != nil { + return err + } + } + + payloadHash := v.GetPayloadHash() + if payloadHash == nil { + h.payloadHash = nil + } else { + if h.payloadHash == nil { + h.payloadHash = new(refs.Checksum) + } + + err = h.payloadHash.FromGRPCMessage(payloadHash) + if err != nil { + return err + } + } + + h.typ = TypeFromGRPCField(v.GetObjectType()) + h.creatEpoch = v.GetCreationEpoch() + h.payloadLen = v.GetPayloadLength() + + return nil +} + +func (a *Attribute) ToGRPCMessage() grpc.Message { + var m *object.Header_Attribute + + if a != nil { + m = new(object.Header_Attribute) + + m.SetKey(a.key) + m.SetValue(a.val) + } + + return m +} + +func (a *Attribute) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.Header_Attribute) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + a.key = v.GetKey() + a.val = v.GetValue() + + return nil +} + +func AttributesToGRPC(xs []Attribute) (res []object.Header_Attribute) { + if xs != nil { + res = make([]object.Header_Attribute, 0, len(xs)) + + for i := range xs { + res = append(res, *xs[i].ToGRPCMessage().(*object.Header_Attribute)) + } + } + + return +} + +func AttributesFromGRPC(xs []object.Header_Attribute) (res []Attribute, err error) { + if xs != nil { + res = make([]Attribute, len(xs)) + + for i := range xs { + err = res[i].FromGRPCMessage(&xs[i]) + if err != nil { + return + } + } + } + + return +} + +func (h *SplitHeader) ToGRPCMessage() grpc.Message { + var m *object.Header_Split + + if h != nil { + m = new(object.Header_Split) + + m.SetParent(h.par.ToGRPCMessage().(*refsGRPC.ObjectID)) + m.SetPrevious(h.prev.ToGRPCMessage().(*refsGRPC.ObjectID)) + m.SetParentHeader(h.parHdr.ToGRPCMessage().(*object.Header)) + m.SetParentSignature(h.parSig.ToGRPCMessage().(*refsGRPC.Signature)) + m.SetChildren(refs.ObjectIDListToGRPCMessage(h.children)) + m.SetSplitId(h.splitID) + } + + return m +} + +func (h *SplitHeader) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.Header_Split) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + par := v.GetParent() + if par == nil { + h.par = nil + } else { + if h.par == nil { + h.par = new(refs.ObjectID) + } + + err = h.par.FromGRPCMessage(par) + if err != nil { + return err + } + } + + prev := v.GetPrevious() + if prev == nil { + h.prev = nil + } else { + if h.prev == nil { + h.prev = new(refs.ObjectID) + } + + err = h.prev.FromGRPCMessage(prev) + if err != nil { + return err + } + } + + parHdr := v.GetParentHeader() + if parHdr == nil { + h.parHdr = nil + } else { + if h.parHdr == nil { + h.parHdr = new(Header) + } + + err = h.parHdr.FromGRPCMessage(parHdr) + if err != nil { + return err + } + } + + parSig := v.GetParentSignature() + if parSig == nil { + h.parSig = nil + } else { + if h.parSig == nil { + h.parSig = new(refs.Signature) + } + + err = h.parSig.FromGRPCMessage(parSig) + if err != nil { + return err + } + } + + h.children, err = refs.ObjectIDListFromGRPCMessage(v.GetChildren()) + if err != nil { + return err + } + + h.splitID = v.GetSplitId() + + return nil +} + +func (h *ECHeader) ToGRPCMessage() grpc.Message { + var m *object.Header_EC + + if h != nil { + m = new(object.Header_EC) + + m.Parent = h.Parent.ToGRPCMessage().(*refsGRPC.ObjectID) + m.ParentSplitId = h.ParentSplitID + m.ParentSplitParentId = h.ParentSplitParentID.ToGRPCMessage().(*refsGRPC.ObjectID) + m.ParentAttributes = AttributesToGRPC(h.ParentAttributes) + m.Index = h.Index + m.Total = h.Total + m.Header = h.Header + m.HeaderLength = h.HeaderLength + } + + return m +} + +func (h *ECHeader) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.Header_EC) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + par := v.GetParent() + if par == nil { + h.Parent = nil + } else { + if h.Parent == nil { + h.Parent = new(refs.ObjectID) + } + + err = h.Parent.FromGRPCMessage(par) + if err != nil { + return err + } + } + + h.ParentSplitID = v.GetParentSplitId() + + parSplitParentID := v.GetParentSplitParentId() + if parSplitParentID == nil { + h.ParentSplitParentID = nil + } else { + if h.ParentSplitParentID == nil { + h.ParentSplitParentID = new(refs.ObjectID) + } + + err = h.ParentSplitParentID.FromGRPCMessage(parSplitParentID) + if err != nil { + return err + } + } + + if h.ParentAttributes, err = AttributesFromGRPC(v.GetParentAttributes()); err != nil { + return err + } + + h.Index = v.GetIndex() + h.Total = v.GetTotal() + h.Header = v.GetHeader() + h.HeaderLength = v.GetHeaderLength() + return nil +} + +func (h *Header) ToGRPCMessage() grpc.Message { + var m *object.Header + + if h != nil { + m = new(object.Header) + + m.SetVersion(h.version.ToGRPCMessage().(*refsGRPC.Version)) + m.SetPayloadHash(h.payloadHash.ToGRPCMessage().(*refsGRPC.Checksum)) + m.SetOwnerId(h.ownerID.ToGRPCMessage().(*refsGRPC.OwnerID)) + m.SetHomomorphicHash(h.homoHash.ToGRPCMessage().(*refsGRPC.Checksum)) + m.SetContainerId(h.cid.ToGRPCMessage().(*refsGRPC.ContainerID)) + m.SetSessionToken(h.sessionToken.ToGRPCMessage().(*sessionGRPC.SessionToken)) + m.SetSplit(h.split.ToGRPCMessage().(*object.Header_Split)) + m.Ec = h.ec.ToGRPCMessage().(*object.Header_EC) + m.SetAttributes(AttributesToGRPC(h.attr)) + m.SetPayloadLength(h.payloadLen) + m.SetCreationEpoch(h.creatEpoch) + m.SetObjectType(TypeToGRPCField(h.typ)) + } + + return m +} + +func (h *Header) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.Header) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + if err := h.fillVersion(v); err != nil { + return err + } + if err := h.fillPayloadHash(v); err != nil { + return err + } + if err := h.fillOwnerID(v); err != nil { + return err + } + if err := h.fillHomomorphicHash(v); err != nil { + return err + } + if err := h.fillContainerID(v); err != nil { + return err + } + if err := h.fillSessionToken(v); err != nil { + return err + } + if err := h.fillSplitHeader(v); err != nil { + return err + } + if err := h.fillECHeader(v); err != nil { + return err + } + + h.attr, err = AttributesFromGRPC(v.GetAttributes()) + if err != nil { + return err + } + + h.payloadLen = v.GetPayloadLength() + h.creatEpoch = v.GetCreationEpoch() + h.typ = TypeFromGRPCField(v.GetObjectType()) + + return nil +} + +func (h *Header) fillVersion(v *object.Header) error { + version := v.GetVersion() + if version == nil { + h.version = nil + return nil + } + + if h.version == nil { + h.version = new(refs.Version) + } + return h.version.FromGRPCMessage(version) +} + +func (h *Header) fillPayloadHash(v *object.Header) error { + payloadHash := v.GetPayloadHash() + if payloadHash == nil { + h.payloadHash = nil + return nil + } + + if h.payloadHash == nil { + h.payloadHash = new(refs.Checksum) + } + return h.payloadHash.FromGRPCMessage(payloadHash) +} + +func (h *Header) fillOwnerID(v *object.Header) error { + ownerID := v.GetOwnerId() + if ownerID == nil { + h.ownerID = nil + return nil + } + + if h.ownerID == nil { + h.ownerID = new(refs.OwnerID) + } + return h.ownerID.FromGRPCMessage(ownerID) +} + +func (h *Header) fillHomomorphicHash(v *object.Header) error { + homoHash := v.GetHomomorphicHash() + if homoHash == nil { + h.homoHash = nil + return nil + } + + if h.homoHash == nil { + h.homoHash = new(refs.Checksum) + } + return h.homoHash.FromGRPCMessage(homoHash) +} + +func (h *Header) fillContainerID(v *object.Header) error { + cid := v.GetContainerId() + if cid == nil { + h.cid = nil + return nil + } + + if h.cid == nil { + h.cid = new(refs.ContainerID) + } + return h.cid.FromGRPCMessage(cid) +} + +func (h *Header) fillSessionToken(v *object.Header) error { + sessionToken := v.GetSessionToken() + if sessionToken == nil { + h.sessionToken = nil + return nil + } + + if h.sessionToken == nil { + h.sessionToken = new(session.Token) + } + return h.sessionToken.FromGRPCMessage(sessionToken) +} + +func (h *Header) fillSplitHeader(v *object.Header) error { + split := v.GetSplit() + if split == nil { + h.split = nil + return nil + } + + if h.split == nil { + h.split = new(SplitHeader) + } + return h.split.FromGRPCMessage(split) +} + +func (h *Header) fillECHeader(v *object.Header) error { + ec := v.GetEc() + if ec == nil { + h.ec = nil + return nil + } + + if h.ec == nil { + h.ec = new(ECHeader) + } + return h.ec.FromGRPCMessage(ec) +} + +func (h *HeaderWithSignature) ToGRPCMessage() grpc.Message { + var m *object.HeaderWithSignature + + if h != nil { + m = new(object.HeaderWithSignature) + + m.SetSignature(h.signature.ToGRPCMessage().(*refsGRPC.Signature)) + m.SetHeader(h.header.ToGRPCMessage().(*object.Header)) + } + + return m +} + +func (h *HeaderWithSignature) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.HeaderWithSignature) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + signature := v.GetSignature() + if signature == nil { + h.signature = nil + } else { + if h.signature == nil { + h.signature = new(refs.Signature) + } + + err = h.signature.FromGRPCMessage(signature) + if err != nil { + return err + } + } + + header := v.GetHeader() + if header == nil { + h.header = nil + } else { + if h.header == nil { + h.header = new(Header) + } + + err = h.header.FromGRPCMessage(header) + } + + return err +} + +func (o *Object) ToGRPCMessage() grpc.Message { + var m *object.Object + + if o != nil { + m = new(object.Object) + + m.SetObjectId(o.objectID.ToGRPCMessage().(*refsGRPC.ObjectID)) + m.SetSignature(o.idSig.ToGRPCMessage().(*refsGRPC.Signature)) + m.SetHeader(o.header.ToGRPCMessage().(*object.Header)) + m.SetPayload(o.payload) + } + + return m +} + +func (o *Object) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.Object) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + objectID := v.GetObjectId() + if objectID == nil { + o.objectID = nil + } else { + if o.objectID == nil { + o.objectID = new(refs.ObjectID) + } + + err = o.objectID.FromGRPCMessage(objectID) + if err != nil { + return err + } + } + + idSig := v.GetSignature() + if idSig == nil { + o.idSig = nil + } else { + if o.idSig == nil { + o.idSig = new(refs.Signature) + } + + err = o.idSig.FromGRPCMessage(idSig) + if err != nil { + return err + } + } + + header := v.GetHeader() + if header == nil { + o.header = nil + } else { + if o.header == nil { + o.header = new(Header) + } + + err = o.header.FromGRPCMessage(header) + if err != nil { + return err + } + } + + o.payload = v.GetPayload() + + return nil +} + +func (s *SplitInfo) ToGRPCMessage() grpc.Message { + var m *object.SplitInfo + + if s != nil { + m = new(object.SplitInfo) + + m.SetLastPart(s.lastPart.ToGRPCMessage().(*refsGRPC.ObjectID)) + m.SetLink(s.link.ToGRPCMessage().(*refsGRPC.ObjectID)) + m.SetSplitId(s.splitID) + } + + return m +} + +func (s *SplitInfo) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.SplitInfo) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + lastPart := v.GetLastPart() + if lastPart == nil { + s.lastPart = nil + } else { + if s.lastPart == nil { + s.lastPart = new(refs.ObjectID) + } + + err = s.lastPart.FromGRPCMessage(lastPart) + if err != nil { + return err + } + } + + link := v.GetLink() + if link == nil { + s.link = nil + } else { + if s.link == nil { + s.link = new(refs.ObjectID) + } + + err = s.link.FromGRPCMessage(link) + if err != nil { + return err + } + } + + s.splitID = v.GetSplitId() + + return nil +} + +func (s *ECInfo) ToGRPCMessage() grpc.Message { + var m *object.ECInfo + + if s != nil { + m = new(object.ECInfo) + + if s.Chunks != nil { + chunks := make([]object.ECInfo_Chunk, len(s.Chunks)) + for i := range chunks { + chunks[i] = *s.Chunks[i].ToGRPCMessage().(*object.ECInfo_Chunk) + } + m.Chunks = chunks + } + } + + return m +} + +func (s *ECInfo) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.ECInfo) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + chunks := v.GetChunks() + if chunks == nil { + s.Chunks = nil + } else { + s.Chunks = make([]ECChunk, len(chunks)) + for i := range chunks { + if err := s.Chunks[i].FromGRPCMessage(&chunks[i]); err != nil { + return err + } + } + } + return nil +} + +func (c *ECChunk) ToGRPCMessage() grpc.Message { + var m *object.ECInfo_Chunk + + if c != nil { + m = new(object.ECInfo_Chunk) + + m.Total = c.Total + m.Index = c.Index + m.Id = c.ID.ToGRPCMessage().(*refsGRPC.ObjectID) + } + + return m +} + +func (c *ECChunk) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.ECInfo_Chunk) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + if err := c.ID.FromGRPCMessage(v.GetId()); err != nil { + return err + } + c.Index = v.Index + c.Total = v.Total + + return nil +} + +func (r *GetRequestBody) ToGRPCMessage() grpc.Message { + var m *object.GetRequest_Body + + if r != nil { + m = new(object.GetRequest_Body) + + m.SetAddress(r.addr.ToGRPCMessage().(*refsGRPC.Address)) + m.SetRaw(r.raw) + } + + return m +} + +func (r *GetRequestBody) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.GetRequest_Body) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + addr := v.GetAddress() + if addr == nil { + r.addr = nil + } else { + if r.addr == nil { + r.addr = new(refs.Address) + } + + err = r.addr.FromGRPCMessage(addr) + if err != nil { + return err + } + } + + r.raw = v.GetRaw() + + return nil +} + +func (r *GetRequest) ToGRPCMessage() grpc.Message { + var m *object.GetRequest + + if r != nil { + m = new(object.GetRequest) + + m.SetBody(r.body.ToGRPCMessage().(*object.GetRequest_Body)) + r.RequestHeaders.ToMessage(m) + } + + return m +} + +func (r *GetRequest) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.GetRequest) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + body := v.GetBody() + if body == nil { + r.body = nil + } else { + if r.body == nil { + r.body = new(GetRequestBody) + } + + err = r.body.FromGRPCMessage(body) + if err != nil { + return err + } + } + + return r.RequestHeaders.FromMessage(v) +} + +func (r *GetObjectPartInit) ToGRPCMessage() grpc.Message { + var m *object.GetResponse_Body_Init + + if r != nil { + m = new(object.GetResponse_Body_Init) + + m.SetObjectId(r.id.ToGRPCMessage().(*refsGRPC.ObjectID)) + m.SetSignature(r.sig.ToGRPCMessage().(*refsGRPC.Signature)) + m.SetHeader(r.hdr.ToGRPCMessage().(*object.Header)) + } + + return m +} + +func (r *GetObjectPartInit) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.GetResponse_Body_Init) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + id := v.GetObjectId() + if id == nil { + r.id = nil + } else { + if r.id == nil { + r.id = new(refs.ObjectID) + } + + err = r.id.FromGRPCMessage(id) + if err != nil { + return err + } + } + + sig := v.GetSignature() + if sig == nil { + r.sig = nil + } else { + if r.sig == nil { + r.sig = new(refs.Signature) + } + + err = r.sig.FromGRPCMessage(sig) + if err != nil { + return err + } + } + + hdr := v.GetHeader() + if hdr == nil { + r.hdr = nil + } else { + if r.hdr == nil { + r.hdr = new(Header) + } + + err = r.hdr.FromGRPCMessage(hdr) + } + + return err +} + +func (r *GetObjectPartChunk) ToGRPCMessage() grpc.Message { + var m *object.GetResponse_Body_Chunk + + if r != nil { + m = new(object.GetResponse_Body_Chunk) + + m.SetChunk(r.chunk) + } + + return m +} + +func (r *GetObjectPartChunk) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.GetResponse_Body_Chunk) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + r.chunk = v.GetChunk() + + return nil +} + +func (r *GetResponseBody) ToGRPCMessage() grpc.Message { + var m *object.GetResponse_Body + + if r != nil { + m = new(object.GetResponse_Body) + + switch v := r.GetObjectPart(); t := v.(type) { + case nil: + m.ObjectPart = nil + case *GetObjectPartInit: + m.SetInit(t.ToGRPCMessage().(*object.GetResponse_Body_Init)) + case *GetObjectPartChunk: + m.SetChunk(t.ToGRPCMessage().(*object.GetResponse_Body_Chunk)) + case *SplitInfo: + m.SetSplitInfo(t.ToGRPCMessage().(*object.SplitInfo)) + case *ECInfo: + m.SetEcInfo(t.ToGRPCMessage().(*object.ECInfo)) + default: + panic(fmt.Sprintf("unknown get object part %T", t)) + } + } + + return m +} + +func (r *GetResponseBody) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.GetResponse_Body) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + r.objPart = nil + + switch pt := v.GetObjectPart().(type) { + case nil: + case *object.GetResponse_Body_Init_: + if pt != nil { + partInit := new(GetObjectPartInit) + r.objPart = partInit + err = partInit.FromGRPCMessage(pt.Init) + } + case *object.GetResponse_Body_Chunk: + if pt != nil { + partChunk := new(GetObjectPartChunk) + r.objPart = partChunk + err = partChunk.FromGRPCMessage(pt) + } + case *object.GetResponse_Body_SplitInfo: + if pt != nil { + partSplit := new(SplitInfo) + r.objPart = partSplit + err = partSplit.FromGRPCMessage(pt.SplitInfo) + } + case *object.GetResponse_Body_EcInfo: + if pt != nil { + partEC := new(ECInfo) + r.objPart = partEC + err = partEC.FromGRPCMessage(pt.EcInfo) + } + default: + err = fmt.Errorf("unknown get object part %T", pt) + } + + return err +} + +func (r *GetResponse) ToGRPCMessage() grpc.Message { + var m *object.GetResponse + + if r != nil { + m = new(object.GetResponse) + + m.SetBody(r.body.ToGRPCMessage().(*object.GetResponse_Body)) + r.ResponseHeaders.ToMessage(m) + } + + return m +} + +func (r *GetResponse) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.GetResponse) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + body := v.GetBody() + if body == nil { + r.body = nil + } else { + if r.body == nil { + r.body = new(GetResponseBody) + } + + err = r.body.FromGRPCMessage(body) + if err != nil { + return err + } + } + + return r.ResponseHeaders.FromMessage(v) +} + +func (r *PutObjectPartInit) ToGRPCMessage() grpc.Message { + var m *object.PutRequest_Body_Init + + if r != nil { + m = new(object.PutRequest_Body_Init) + + m.SetObjectId(r.id.ToGRPCMessage().(*refsGRPC.ObjectID)) + m.SetSignature(r.sig.ToGRPCMessage().(*refsGRPC.Signature)) + m.SetHeader(r.hdr.ToGRPCMessage().(*object.Header)) + m.SetCopiesNumber(r.copyNum) + } + + return m +} + +func (r *PutObjectPartInit) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.PutRequest_Body_Init) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + id := v.GetObjectId() + if id == nil { + r.id = nil + } else { + if r.id == nil { + r.id = new(refs.ObjectID) + } + + err = r.id.FromGRPCMessage(id) + if err != nil { + return err + } + } + + sig := v.GetSignature() + if sig == nil { + r.sig = nil + } else { + if r.sig == nil { + r.sig = new(refs.Signature) + } + + err = r.sig.FromGRPCMessage(sig) + if err != nil { + return err + } + } + + hdr := v.GetHeader() + if hdr == nil { + r.hdr = nil + } else { + if r.hdr == nil { + r.hdr = new(Header) + } + + err = r.hdr.FromGRPCMessage(hdr) + if err != nil { + return err + } + } + + r.copyNum = v.GetCopiesNumber() + + return nil +} + +func (r *PutObjectPartChunk) ToGRPCMessage() grpc.Message { + var m *object.PutRequest_Body_Chunk + + if r != nil { + m = new(object.PutRequest_Body_Chunk) + + m.SetChunk(r.chunk) + } + + return m +} + +func (r *PutObjectPartChunk) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.PutRequest_Body_Chunk) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + r.chunk = v.GetChunk() + + return nil +} + +func (r *PutRequestBody) ToGRPCMessage() grpc.Message { + var m *object.PutRequest_Body + + if r != nil { + m = new(object.PutRequest_Body) + + switch v := r.GetObjectPart(); t := v.(type) { + case nil: + m.ObjectPart = nil + case *PutObjectPartInit: + m.SetInit(t.ToGRPCMessage().(*object.PutRequest_Body_Init)) + case *PutObjectPartChunk: + m.SetChunk(t.ToGRPCMessage().(*object.PutRequest_Body_Chunk)) + default: + panic(fmt.Sprintf("unknown put object part %T", t)) + } + } + + return m +} + +func (r *PutRequestBody) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.PutRequest_Body) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + r.objPart = nil + + switch pt := v.GetObjectPart().(type) { + case nil: + case *object.PutRequest_Body_Init_: + if pt != nil { + partInit := new(PutObjectPartInit) + r.objPart = partInit + err = partInit.FromGRPCMessage(pt.Init) + } + case *object.PutRequest_Body_Chunk: + if pt != nil { + partChunk := new(PutObjectPartChunk) + r.objPart = partChunk + err = partChunk.FromGRPCMessage(pt) + } + default: + err = fmt.Errorf("unknown put object part %T", pt) + } + + return err +} + +func (r *PutRequest) ToGRPCMessage() grpc.Message { + var m *object.PutRequest + + if r != nil { + m = new(object.PutRequest) + + m.SetBody(r.body.ToGRPCMessage().(*object.PutRequest_Body)) + r.RequestHeaders.ToMessage(m) + } + + return m +} + +func (r *PutRequest) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.PutRequest) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + body := v.GetBody() + if body == nil { + r.body = nil + } else { + if r.body == nil { + r.body = new(PutRequestBody) + } + + err = r.body.FromGRPCMessage(body) + if err != nil { + return err + } + } + + return r.RequestHeaders.FromMessage(v) +} + +func (r *PutResponseBody) ToGRPCMessage() grpc.Message { + var m *object.PutResponse_Body + + if r != nil { + m = new(object.PutResponse_Body) + + m.SetObjectId(r.id.ToGRPCMessage().(*refsGRPC.ObjectID)) + } + + return m +} + +func (r *PutResponseBody) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.PutResponse_Body) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + id := v.GetObjectId() + if id == nil { + r.id = nil + } else { + if r.id == nil { + r.id = new(refs.ObjectID) + } + + err = r.id.FromGRPCMessage(id) + } + + return err +} + +func (r *PutResponse) ToGRPCMessage() grpc.Message { + var m *object.PutResponse + + if r != nil { + m = new(object.PutResponse) + + m.SetBody(r.body.ToGRPCMessage().(*object.PutResponse_Body)) + r.ResponseHeaders.ToMessage(m) + } + + return m +} + +func (r *PutResponse) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.PutResponse) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + body := v.GetBody() + if body == nil { + r.body = nil + } else { + if r.body == nil { + r.body = new(PutResponseBody) + } + + err = r.body.FromGRPCMessage(body) + if err != nil { + return err + } + } + + return r.ResponseHeaders.FromMessage(v) +} + +func (r *DeleteRequestBody) ToGRPCMessage() grpc.Message { + var m *object.DeleteRequest_Body + + if r != nil { + m = new(object.DeleteRequest_Body) + + m.SetAddress(r.addr.ToGRPCMessage().(*refsGRPC.Address)) + } + + return m +} + +func (r *DeleteRequestBody) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.DeleteRequest_Body) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + addr := v.GetAddress() + if addr == nil { + r.addr = nil + } else { + if r.addr == nil { + r.addr = new(refs.Address) + } + + err = r.addr.FromGRPCMessage(addr) + } + + return err +} + +func (r *DeleteRequest) ToGRPCMessage() grpc.Message { + var m *object.DeleteRequest + + if r != nil { + m = new(object.DeleteRequest) + + m.SetBody(r.body.ToGRPCMessage().(*object.DeleteRequest_Body)) + r.RequestHeaders.ToMessage(m) + } + + return m +} + +func (r *DeleteRequest) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.DeleteRequest) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + body := v.GetBody() + if body == nil { + r.body = nil + } else { + if r.body == nil { + r.body = new(DeleteRequestBody) + } + + err = r.body.FromGRPCMessage(body) + if err != nil { + return err + } + } + + return r.RequestHeaders.FromMessage(v) +} + +func (r *DeleteResponseBody) ToGRPCMessage() grpc.Message { + var m *object.DeleteResponse_Body + + if r != nil { + m = new(object.DeleteResponse_Body) + + m.SetTombstone(r.tombstone.ToGRPCMessage().(*refsGRPC.Address)) + } + + return m +} + +func (r *DeleteResponseBody) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.DeleteResponse_Body) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + tombstone := v.GetTombstone() + if tombstone == nil { + r.tombstone = nil + } else { + if r.tombstone == nil { + r.tombstone = new(refs.Address) + } + + err = r.tombstone.FromGRPCMessage(tombstone) + } + + return err +} + +func (r *DeleteResponse) ToGRPCMessage() grpc.Message { + var m *object.DeleteResponse + + if r != nil { + m = new(object.DeleteResponse) + + m.SetBody(r.body.ToGRPCMessage().(*object.DeleteResponse_Body)) + r.ResponseHeaders.ToMessage(m) + } + + return m +} + +func (r *DeleteResponse) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.DeleteResponse) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + body := v.GetBody() + if body == nil { + r.body = nil + } else { + if r.body == nil { + r.body = new(DeleteResponseBody) + } + + err = r.body.FromGRPCMessage(body) + if err != nil { + return err + } + } + + return r.ResponseHeaders.FromMessage(v) +} + +func (r *HeadRequestBody) ToGRPCMessage() grpc.Message { + var m *object.HeadRequest_Body + + if r != nil { + m = new(object.HeadRequest_Body) + + m.SetAddress(r.addr.ToGRPCMessage().(*refsGRPC.Address)) + m.SetRaw(r.raw) + m.SetMainOnly(r.mainOnly) + } + + return m +} + +func (r *HeadRequestBody) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.HeadRequest_Body) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + addr := v.GetAddress() + if addr == nil { + r.addr = nil + } else { + if r.addr == nil { + r.addr = new(refs.Address) + } + + err = r.addr.FromGRPCMessage(addr) + if err != nil { + return err + } + } + + r.raw = v.GetRaw() + r.mainOnly = v.GetMainOnly() + + return nil +} + +func (r *HeadRequest) ToGRPCMessage() grpc.Message { + var m *object.HeadRequest + + if r != nil { + m = new(object.HeadRequest) + + m.SetBody(r.body.ToGRPCMessage().(*object.HeadRequest_Body)) + r.RequestHeaders.ToMessage(m) + } + + return m +} + +func (r *HeadRequest) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.HeadRequest) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + body := v.GetBody() + if body == nil { + r.body = nil + } else { + if r.body == nil { + r.body = new(HeadRequestBody) + } + + err = r.body.FromGRPCMessage(body) + if err != nil { + return err + } + } + + return r.RequestHeaders.FromMessage(v) +} + +func (r *HeadResponseBody) ToGRPCMessage() grpc.Message { + var m *object.HeadResponse_Body + + if r != nil { + m = new(object.HeadResponse_Body) + + switch v := r.hdrPart.(type) { + case nil: + m.Head = nil + case *HeaderWithSignature: + m.SetHeader(v.ToGRPCMessage().(*object.HeaderWithSignature)) + case *ShortHeader: + m.SetShortHeader(v.ToGRPCMessage().(*object.ShortHeader)) + case *SplitInfo: + m.SetSplitInfo(v.ToGRPCMessage().(*object.SplitInfo)) + case *ECInfo: + m.SetEcInfo(v.ToGRPCMessage().(*object.ECInfo)) + default: + panic(fmt.Sprintf("unknown head part %T", v)) + } + } + + return m +} + +func (r *HeadResponseBody) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.HeadResponse_Body) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + r.hdrPart = nil + + switch pt := v.GetHead().(type) { + case nil: + case *object.HeadResponse_Body_Header: + if pt != nil { + partHdr := new(HeaderWithSignature) + r.hdrPart = partHdr + err = partHdr.FromGRPCMessage(pt.Header) + } + case *object.HeadResponse_Body_ShortHeader: + if pt != nil { + partShort := new(ShortHeader) + r.hdrPart = partShort + err = partShort.FromGRPCMessage(pt.ShortHeader) + } + case *object.HeadResponse_Body_SplitInfo: + if pt != nil { + partSplit := new(SplitInfo) + r.hdrPart = partSplit + err = partSplit.FromGRPCMessage(pt.SplitInfo) + } + case *object.HeadResponse_Body_EcInfo: + if pt != nil { + partEC := new(ECInfo) + r.hdrPart = partEC + err = partEC.FromGRPCMessage(pt.EcInfo) + } + default: + err = fmt.Errorf("unknown head part %T", pt) + } + + return err +} + +func (r *HeadResponse) ToGRPCMessage() grpc.Message { + var m *object.HeadResponse + + if r != nil { + m = new(object.HeadResponse) + + m.SetBody(r.body.ToGRPCMessage().(*object.HeadResponse_Body)) + r.ResponseHeaders.ToMessage(m) + } + + return m +} + +func (r *HeadResponse) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.HeadResponse) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + body := v.GetBody() + if body == nil { + r.body = nil + } else { + if r.body == nil { + r.body = new(HeadResponseBody) + } + + err = r.body.FromGRPCMessage(body) + if err != nil { + return err + } + } + + return r.ResponseHeaders.FromMessage(v) +} + +func (f *SearchFilter) ToGRPCMessage() grpc.Message { + var m *object.SearchRequest_Body_Filter + + if f != nil { + m = new(object.SearchRequest_Body_Filter) + + m.SetKey(f.key) + m.SetValue(f.val) + m.SetMatchType(MatchTypeToGRPCField(f.matchType)) + } + + return m +} + +func (f *SearchFilter) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.SearchRequest_Body_Filter) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + f.key = v.GetKey() + f.val = v.GetValue() + f.matchType = MatchTypeFromGRPCField(v.GetMatchType()) + + return nil +} + +func SearchFiltersToGRPC(fs []SearchFilter) (res []object.SearchRequest_Body_Filter) { + if fs != nil { + res = make([]object.SearchRequest_Body_Filter, 0, len(fs)) + + for i := range fs { + res = append(res, *fs[i].ToGRPCMessage().(*object.SearchRequest_Body_Filter)) + } + } + + return +} + +func SearchFiltersFromGRPC(fs []object.SearchRequest_Body_Filter) (res []SearchFilter, err error) { + if fs != nil { + res = make([]SearchFilter, len(fs)) + + for i := range fs { + err = res[i].FromGRPCMessage(&fs[i]) + if err != nil { + return + } + } + } + + return +} + +func (r *SearchRequestBody) ToGRPCMessage() grpc.Message { + var m *object.SearchRequest_Body + + if r != nil { + m = new(object.SearchRequest_Body) + + m.SetContainerId(r.cid.ToGRPCMessage().(*refsGRPC.ContainerID)) + m.SetFilters(SearchFiltersToGRPC(r.filters)) + m.SetVersion(r.version) + } + + return m +} + +func (r *SearchRequestBody) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.SearchRequest_Body) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + cid := v.GetContainerId() + if cid == nil { + r.cid = nil + } else { + if r.cid == nil { + r.cid = new(refs.ContainerID) + } + + err = r.cid.FromGRPCMessage(cid) + if err != nil { + return err + } + } + + r.filters, err = SearchFiltersFromGRPC(v.GetFilters()) + if err != nil { + return err + } + + r.version = v.GetVersion() + + return nil +} + +func (r *SearchRequest) ToGRPCMessage() grpc.Message { + var m *object.SearchRequest + + if r != nil { + m = new(object.SearchRequest) + + m.SetBody(r.body.ToGRPCMessage().(*object.SearchRequest_Body)) + r.RequestHeaders.ToMessage(m) + } + + return m +} + +func (r *SearchRequest) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.SearchRequest) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + body := v.GetBody() + if body == nil { + r.body = nil + } else { + if r.body == nil { + r.body = new(SearchRequestBody) + } + + err = r.body.FromGRPCMessage(body) + if err != nil { + return err + } + } + + return r.RequestHeaders.FromMessage(v) +} + +func (r *SearchResponseBody) ToGRPCMessage() grpc.Message { + var m *object.SearchResponse_Body + + if r != nil { + m = new(object.SearchResponse_Body) + + m.SetIdList(refs.ObjectIDListToGRPCMessage(r.idList)) + } + + return m +} + +func (r *SearchResponseBody) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.SearchResponse_Body) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + r.idList, err = refs.ObjectIDListFromGRPCMessage(v.GetIdList()) + + return err +} + +func (r *SearchResponse) ToGRPCMessage() grpc.Message { + var m *object.SearchResponse + + if r != nil { + m = new(object.SearchResponse) + + m.SetBody(r.body.ToGRPCMessage().(*object.SearchResponse_Body)) + r.ResponseHeaders.ToMessage(m) + } + + return m +} + +func (r *SearchResponse) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.SearchResponse) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + body := v.GetBody() + if body == nil { + r.body = nil + } else { + if r.body == nil { + r.body = new(SearchResponseBody) + } + + err = r.body.FromGRPCMessage(body) + if err != nil { + return err + } + } + + return r.ResponseHeaders.FromMessage(v) +} + +func (r *Range) ToGRPCMessage() grpc.Message { + var m *object.Range + + if r != nil { + m = new(object.Range) + + m.SetLength(r.len) + m.SetOffset(r.off) + } + + return m +} + +func (r *Range) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.Range) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + r.len = v.GetLength() + r.off = v.GetOffset() + + return nil +} + +func RangesToGRPC(rs []Range) (res []object.Range) { + if rs != nil { + res = make([]object.Range, 0, len(rs)) + + for i := range rs { + res = append(res, *rs[i].ToGRPCMessage().(*object.Range)) + } + } + + return +} + +func RangesFromGRPC(rs []object.Range) (res []Range, err error) { + if rs != nil { + res = make([]Range, len(rs)) + + for i := range rs { + err = res[i].FromGRPCMessage(&rs[i]) + if err != nil { + return + } + } + } + + return +} + +func (r *GetRangeRequestBody) ToGRPCMessage() grpc.Message { + var m *object.GetRangeRequest_Body + + if r != nil { + m = new(object.GetRangeRequest_Body) + + m.SetAddress(r.addr.ToGRPCMessage().(*refsGRPC.Address)) + m.SetRange(r.rng.ToGRPCMessage().(*object.Range)) + m.SetRaw(r.raw) + } + + return m +} + +func (r *GetRangeRequestBody) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.GetRangeRequest_Body) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + addr := v.GetAddress() + if addr == nil { + r.addr = nil + } else { + if r.addr == nil { + r.addr = new(refs.Address) + } + + err = r.addr.FromGRPCMessage(addr) + if err != nil { + return err + } + } + + rng := v.GetRange() + if rng == nil { + r.rng = nil + } else { + if r.rng == nil { + r.rng = new(Range) + } + + err = r.rng.FromGRPCMessage(rng) + if err != nil { + return err + } + } + + r.raw = v.GetRaw() + + return nil +} + +func (r *GetRangeRequest) ToGRPCMessage() grpc.Message { + var m *object.GetRangeRequest + + if r != nil { + m = new(object.GetRangeRequest) + + m.SetBody(r.body.ToGRPCMessage().(*object.GetRangeRequest_Body)) + r.RequestHeaders.ToMessage(m) + } + + return m +} + +func (r *GetRangeRequest) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.GetRangeRequest) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + body := v.GetBody() + if body == nil { + r.body = nil + } else { + if r.body == nil { + r.body = new(GetRangeRequestBody) + } + + err = r.body.FromGRPCMessage(body) + if err != nil { + return err + } + } + + return r.RequestHeaders.FromMessage(v) +} + +func (r *GetRangePartChunk) ToGRPCMessage() grpc.Message { + var m *object.GetRangeResponse_Body_Chunk + + if r != nil { + m = new(object.GetRangeResponse_Body_Chunk) + + m.SetChunk(r.chunk) + } + + return m +} + +func (r *GetRangePartChunk) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.GetRangeResponse_Body_Chunk) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + r.chunk = v.GetChunk() + + return nil +} + +func (r *GetRangeResponseBody) ToGRPCMessage() grpc.Message { + var m *object.GetRangeResponse_Body + + if r != nil { + m = new(object.GetRangeResponse_Body) + + switch v := r.rngPart.(type) { + case nil: + m.RangePart = nil + case *GetRangePartChunk: + m.SetChunk(v.ToGRPCMessage().(*object.GetRangeResponse_Body_Chunk)) + case *SplitInfo: + m.SetSplitInfo(v.ToGRPCMessage().(*object.SplitInfo)) + case *ECInfo: + m.SetEcInfo(v.ToGRPCMessage().(*object.ECInfo)) + default: + panic(fmt.Sprintf("unknown get range part %T", v)) + } + } + + return m +} + +func (r *GetRangeResponseBody) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.GetRangeResponse_Body) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + r.rngPart = nil + + switch pt := v.GetRangePart().(type) { + case nil: + case *object.GetRangeResponse_Body_Chunk: + if pt != nil { + partChunk := new(GetRangePartChunk) + r.rngPart = partChunk + err = partChunk.FromGRPCMessage(pt) + } + case *object.GetRangeResponse_Body_SplitInfo: + if pt != nil { + partSplit := new(SplitInfo) + r.rngPart = partSplit + err = partSplit.FromGRPCMessage(pt.SplitInfo) + } + case *object.GetRangeResponse_Body_EcInfo: + if pt != nil { + partEC := new(ECInfo) + r.rngPart = partEC + err = partEC.FromGRPCMessage(pt.EcInfo) + } + default: + err = fmt.Errorf("unknown get range part %T", pt) + } + + return err +} + +func (r *GetRangeResponse) ToGRPCMessage() grpc.Message { + var m *object.GetRangeResponse + + if r != nil { + m = new(object.GetRangeResponse) + + m.SetBody(r.body.ToGRPCMessage().(*object.GetRangeResponse_Body)) + r.ResponseHeaders.ToMessage(m) + } + + return m +} + +func (r *GetRangeResponse) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.GetRangeResponse) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + body := v.GetBody() + if body == nil { + r.body = nil + } else { + if r.body == nil { + r.body = new(GetRangeResponseBody) + } + + err = r.body.FromGRPCMessage(body) + if err != nil { + return err + } + } + + return r.ResponseHeaders.FromMessage(v) +} + +func (r *GetRangeHashRequestBody) ToGRPCMessage() grpc.Message { + var m *object.GetRangeHashRequest_Body + + if r != nil { + m = new(object.GetRangeHashRequest_Body) + + m.SetAddress(r.addr.ToGRPCMessage().(*refsGRPC.Address)) + m.SetRanges(RangesToGRPC(r.rngs)) + m.SetType(refs.ChecksumTypeToGRPC(r.typ)) + m.SetSalt(r.salt) + } + + return m +} + +func (r *GetRangeHashRequestBody) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.GetRangeHashRequest_Body) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + addr := v.GetAddress() + if addr == nil { + r.addr = nil + } else { + if r.addr == nil { + r.addr = new(refs.Address) + } + + err = r.addr.FromGRPCMessage(addr) + if err != nil { + return err + } + } + + r.rngs, err = RangesFromGRPC(v.GetRanges()) + if err != nil { + return err + } + + r.typ = refs.ChecksumTypeFromGRPC(v.GetType()) + r.salt = v.GetSalt() + + return nil +} + +func (r *GetRangeHashRequest) ToGRPCMessage() grpc.Message { + var m *object.GetRangeHashRequest + + if r != nil { + m = new(object.GetRangeHashRequest) + + m.SetBody(r.body.ToGRPCMessage().(*object.GetRangeHashRequest_Body)) + r.RequestHeaders.ToMessage(m) + } + + return m +} + +func (r *GetRangeHashRequest) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.GetRangeHashRequest) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + body := v.GetBody() + if body == nil { + r.body = nil + } else { + if r.body == nil { + r.body = new(GetRangeHashRequestBody) + } + + err = r.body.FromGRPCMessage(body) + if err != nil { + return err + } + } + + return r.RequestHeaders.FromMessage(v) +} + +func (r *GetRangeHashResponseBody) ToGRPCMessage() grpc.Message { + var m *object.GetRangeHashResponse_Body + + if r != nil { + m = new(object.GetRangeHashResponse_Body) + + m.SetType(refs.ChecksumTypeToGRPC(r.typ)) + m.SetHashList(r.hashList) + } + + return m +} + +func (r *GetRangeHashResponseBody) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.GetRangeHashResponse_Body) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + r.typ = refs.ChecksumTypeFromGRPC(v.GetType()) + r.hashList = v.GetHashList() + + return nil +} + +func (r *GetRangeHashResponse) ToGRPCMessage() grpc.Message { + var m *object.GetRangeHashResponse + + if r != nil { + m = new(object.GetRangeHashResponse) + + m.SetBody(r.body.ToGRPCMessage().(*object.GetRangeHashResponse_Body)) + r.ResponseHeaders.ToMessage(m) + } + + return m +} + +func (r *GetRangeHashResponse) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.GetRangeHashResponse) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + body := v.GetBody() + if body == nil { + r.body = nil + } else { + if r.body == nil { + r.body = new(GetRangeHashResponseBody) + } + + err = r.body.FromGRPCMessage(body) + if err != nil { + return err + } + } + + return r.ResponseHeaders.FromMessage(v) +} + +func (r *PutSingleRequestBody) ToGRPCMessage() grpc.Message { + var m *object.PutSingleRequest_Body + + if r != nil { + m = new(object.PutSingleRequest_Body) + m.SetObject(r.GetObject().ToGRPCMessage().(*object.Object)) + m.SetCopiesNumber(r.GetCopiesNumber()) + } + + return m +} + +func (r *PutSingleRequestBody) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.PutSingleRequest_Body) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + if v.GetObject() == nil { + r.object = nil + } else { + if r.object == nil { + r.object = new(Object) + } + + err := r.object.FromGRPCMessage(v.GetObject()) + if err != nil { + return err + } + } + + r.copyNum = v.GetCopiesNumber() + + return nil +} + +func (r *PutSingleRequest) ToGRPCMessage() grpc.Message { + var m *object.PutSingleRequest + + if r != nil { + m = new(object.PutSingleRequest) + + m.SetBody(r.body.ToGRPCMessage().(*object.PutSingleRequest_Body)) + r.RequestHeaders.ToMessage(m) + } + + return m +} + +func (r *PutSingleRequest) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.PutSingleRequest) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + body := v.GetBody() + if body == nil { + r.body = nil + } else { + if r.body == nil { + r.body = new(PutSingleRequestBody) + } + + err := r.body.FromGRPCMessage(body) + if err != nil { + return err + } + } + + return r.RequestHeaders.FromMessage(v) +} + +func (r *PutSingleResponseBody) ToGRPCMessage() grpc.Message { + var b *object.PutSingleResponse_Body + if r != nil { + b = new(object.PutSingleResponse_Body) + } + return b +} + +func (r *PutSingleResponseBody) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.PutSingleResponse_Body) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + return nil +} + +func (r *PutSingleResponse) ToGRPCMessage() grpc.Message { + var m *object.PutSingleResponse + + if r != nil { + m = new(object.PutSingleResponse) + + m.SetBody(r.body.ToGRPCMessage().(*object.PutSingleResponse_Body)) + r.ResponseHeaders.ToMessage(m) + } + + return m +} + +func (r *PutSingleResponse) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.PutSingleResponse) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + body := v.GetBody() + if body == nil { + r.body = nil + } else { + if r.body == nil { + r.body = new(PutSingleResponseBody) + } + + err = r.body.FromGRPCMessage(body) + if err != nil { + return err + } + } + + return r.ResponseHeaders.FromMessage(v) +} + +func (r *PatchRequestBodyPatch) ToGRPCMessage() grpc.Message { + var m *object.PatchRequest_Body_Patch + + if r != nil { + m = new(object.PatchRequest_Body_Patch) + + m.SetSourceRange(r.GetRange().ToGRPCMessage().(*object.Range)) + m.SetChunk(r.GetChunk()) + } + + return m +} + +func (r *PatchRequestBodyPatch) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.PatchRequest_Body_Patch) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + srcRange := v.GetSourceRange() + if srcRange == nil { + r.Range = nil + } else { + if r.Range == nil { + r.Range = new(Range) + } + + err = r.Range.FromGRPCMessage(srcRange) + if err != nil { + return err + } + } + + r.Chunk = v.GetChunk() + + return nil +} + +func (r *PatchRequestBody) ToGRPCMessage() grpc.Message { + var m *object.PatchRequest_Body + + if r != nil { + m = new(object.PatchRequest_Body) + + m.SetAddress(r.address.ToGRPCMessage().(*refsGRPC.Address)) + m.SetNewAttributes(AttributesToGRPC(r.newAttributes)) + m.SetReplaceAttributes(r.replaceAttributes) + m.SetPatch(r.patch.ToGRPCMessage().(*object.PatchRequest_Body_Patch)) + } + + return m +} + +func (r *PatchRequestBody) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.PatchRequest_Body) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + addr := v.GetAddress() + if addr == nil { + r.address = nil + } else { + if r.address == nil { + r.address = new(refs.Address) + } + + err = r.address.FromGRPCMessage(addr) + if err != nil { + return err + } + } + + r.newAttributes, err = AttributesFromGRPC(v.GetNewAttributes()) + if err != nil { + return err + } + + r.replaceAttributes = v.GetReplaceAttributes() + + patch := v.GetPatch() + if patch == nil { + r.patch = nil + } else { + if r.patch == nil { + r.patch = new(PatchRequestBodyPatch) + } + + err = r.patch.FromGRPCMessage(patch) + if err != nil { + return err + } + } + + return nil +} + +func (r *PatchRequest) ToGRPCMessage() grpc.Message { + var m *object.PatchRequest + + if r != nil { + m = new(object.PatchRequest) + + m.SetBody(r.body.ToGRPCMessage().(*object.PatchRequest_Body)) + r.RequestHeaders.ToMessage(m) + } + + return m +} + +func (r *PatchRequest) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.PatchRequest) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + body := v.GetBody() + if body == nil { + r.body = nil + } else { + if r.body == nil { + r.body = new(PatchRequestBody) + } + + err = r.body.FromGRPCMessage(body) + if err != nil { + return err + } + } + + return r.RequestHeaders.FromMessage(v) +} + +func (r *PatchResponseBody) ToGRPCMessage() grpc.Message { + var m *object.PatchResponse_Body + + if r != nil { + m = new(object.PatchResponse_Body) + + m.SetObjectId(r.ObjectID.ToGRPCMessage().(*refsGRPC.ObjectID)) + } + + return m +} + +func (r *PatchResponseBody) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.PatchResponse_Body) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + objID := v.GetObjectId() + if objID == nil { + r.ObjectID = nil + } else { + if r.ObjectID == nil { + r.ObjectID = new(refs.ObjectID) + } + + err = r.ObjectID.FromGRPCMessage(objID) + if err != nil { + return err + } + } + + return nil +} + +func (r *PatchResponse) ToGRPCMessage() grpc.Message { + var m *object.PatchResponse + + if r != nil { + m = new(object.PatchResponse) + + m.SetBody(r.Body.ToGRPCMessage().(*object.PatchResponse_Body)) + r.ResponseHeaders.ToMessage(m) + } + + return m +} + +func (r *PatchResponse) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.PatchResponse) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + body := v.GetBody() + if body == nil { + r.Body = nil + } else { + if r.Body == nil { + r.Body = new(PatchResponseBody) + } + + err = r.Body.FromGRPCMessage(body) + if err != nil { + return err + } + } + + return r.ResponseHeaders.FromMessage(v) +} diff --git a/api/object/filters.go b/api/object/filters.go new file mode 100644 index 0000000..9fe024d --- /dev/null +++ b/api/object/filters.go @@ -0,0 +1,58 @@ +package object + +// ReservedFilterPrefix is a prefix of key to object header value or property. +const ReservedFilterPrefix = "$Object:" + +const ( + // FilterHeaderVersion is a filter key to "version" field of the object header. + FilterHeaderVersion = ReservedFilterPrefix + "version" + + // FilterHeaderObjectID is a filter key to "object_id" field of the object. + FilterHeaderObjectID = ReservedFilterPrefix + "objectID" + + // FilterHeaderContainerID is a filter key to "container_id" field of the object header. + FilterHeaderContainerID = ReservedFilterPrefix + "containerID" + + // FilterHeaderOwnerID is a filter key to "owner_id" field of the object header. + FilterHeaderOwnerID = ReservedFilterPrefix + "ownerID" + + // FilterHeaderCreationEpoch is a filter key to "creation_epoch" field of the object header. + FilterHeaderCreationEpoch = ReservedFilterPrefix + "creationEpoch" + + // FilterHeaderPayloadLength is a filter key to "payload_length" field of the object header. + FilterHeaderPayloadLength = ReservedFilterPrefix + "payloadLength" + + // FilterHeaderPayloadHash is a filter key to "payload_hash" field of the object header. + FilterHeaderPayloadHash = ReservedFilterPrefix + "payloadHash" + + // FilterHeaderObjectType is a filter key to "object_type" field of the object header. + FilterHeaderObjectType = ReservedFilterPrefix + "objectType" + + // FilterHeaderHomomorphicHash is a filter key to "homomorphic_hash" field of the object header. + FilterHeaderHomomorphicHash = ReservedFilterPrefix + "homomorphicHash" + + // FilterHeaderParent is a filter key to "split.parent" field of the object header. + FilterHeaderParent = ReservedFilterPrefix + "split.parent" + + // FilterHeaderSplitID is a filter key to "split.splitID" field of the object header. + FilterHeaderSplitID = ReservedFilterPrefix + "split.splitID" + + // FilterHeaderECParent is a filter key to "ec.parent" field of the object header. + FilterHeaderECParent = ReservedFilterPrefix + "ec.parent" +) + +const ( + // FilterPropertyRoot is a filter key to check if regular object is on top of split hierarchy. + FilterPropertyRoot = ReservedFilterPrefix + "ROOT" + + // FilterPropertyPhy is a filter key to check if an object physically stored on a node. + FilterPropertyPhy = ReservedFilterPrefix + "PHY" +) + +const ( + // BooleanPropertyValueTrue is a true value for boolean property filters. + BooleanPropertyValueTrue = "true" + + // BooleanPropertyValueFalse is a false value for boolean property filters. + BooleanPropertyValueFalse = "" +) diff --git a/api/object/grpc/service_frostfs.pb.go b/api/object/grpc/service_frostfs.pb.go new file mode 100644 index 0000000000000000000000000000000000000000..5324981c5f4c0d2c3f80925b8d04fffebd236613 GIT binary patch literal 223725 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 k?IJC~z^k_73K|P`O)l+?KXY`!i_@% literal 0 HcmV?d00001 diff --git a/api/object/grpc/service_frostfs_fuzz.go b/api/object/grpc/service_frostfs_fuzz.go new file mode 100644 index 0000000..f58ee01 --- /dev/null +++ b/api/object/grpc/service_frostfs_fuzz.go @@ -0,0 +1,387 @@ +//go:build gofuzz +// +build gofuzz + +// Code generated by protoc-gen-go-frostfs. DO NOT EDIT. + +package object + +func DoFuzzProtoGetRequest(data []byte) int { + msg := new(GetRequest) + if err := msg.UnmarshalProtobuf(data); err != nil { + return 0 + } + _ = msg.MarshalProtobuf(nil) + return 1 +} +func DoFuzzJSONGetRequest(data []byte) int { + msg := new(GetRequest) + if err := msg.UnmarshalJSON(data); err != nil { + return 0 + } + _, err := msg.MarshalJSON() + if err != nil { + panic(err) + } + return 1 +} +func DoFuzzProtoGetResponse(data []byte) int { + msg := new(GetResponse) + if err := msg.UnmarshalProtobuf(data); err != nil { + return 0 + } + _ = msg.MarshalProtobuf(nil) + return 1 +} +func DoFuzzJSONGetResponse(data []byte) int { + msg := new(GetResponse) + if err := msg.UnmarshalJSON(data); err != nil { + return 0 + } + _, err := msg.MarshalJSON() + if err != nil { + panic(err) + } + return 1 +} +func DoFuzzProtoPutRequest(data []byte) int { + msg := new(PutRequest) + if err := msg.UnmarshalProtobuf(data); err != nil { + return 0 + } + _ = msg.MarshalProtobuf(nil) + return 1 +} +func DoFuzzJSONPutRequest(data []byte) int { + msg := new(PutRequest) + if err := msg.UnmarshalJSON(data); err != nil { + return 0 + } + _, err := msg.MarshalJSON() + if err != nil { + panic(err) + } + return 1 +} +func DoFuzzProtoPutResponse(data []byte) int { + msg := new(PutResponse) + if err := msg.UnmarshalProtobuf(data); err != nil { + return 0 + } + _ = msg.MarshalProtobuf(nil) + return 1 +} +func DoFuzzJSONPutResponse(data []byte) int { + msg := new(PutResponse) + if err := msg.UnmarshalJSON(data); err != nil { + return 0 + } + _, err := msg.MarshalJSON() + if err != nil { + panic(err) + } + return 1 +} +func DoFuzzProtoDeleteRequest(data []byte) int { + msg := new(DeleteRequest) + if err := msg.UnmarshalProtobuf(data); err != nil { + return 0 + } + _ = msg.MarshalProtobuf(nil) + return 1 +} +func DoFuzzJSONDeleteRequest(data []byte) int { + msg := new(DeleteRequest) + if err := msg.UnmarshalJSON(data); err != nil { + return 0 + } + _, err := msg.MarshalJSON() + if err != nil { + panic(err) + } + return 1 +} +func DoFuzzProtoDeleteResponse(data []byte) int { + msg := new(DeleteResponse) + if err := msg.UnmarshalProtobuf(data); err != nil { + return 0 + } + _ = msg.MarshalProtobuf(nil) + return 1 +} +func DoFuzzJSONDeleteResponse(data []byte) int { + msg := new(DeleteResponse) + if err := msg.UnmarshalJSON(data); err != nil { + return 0 + } + _, err := msg.MarshalJSON() + if err != nil { + panic(err) + } + return 1 +} +func DoFuzzProtoHeadRequest(data []byte) int { + msg := new(HeadRequest) + if err := msg.UnmarshalProtobuf(data); err != nil { + return 0 + } + _ = msg.MarshalProtobuf(nil) + return 1 +} +func DoFuzzJSONHeadRequest(data []byte) int { + msg := new(HeadRequest) + if err := msg.UnmarshalJSON(data); err != nil { + return 0 + } + _, err := msg.MarshalJSON() + if err != nil { + panic(err) + } + return 1 +} +func DoFuzzProtoHeaderWithSignature(data []byte) int { + msg := new(HeaderWithSignature) + if err := msg.UnmarshalProtobuf(data); err != nil { + return 0 + } + _ = msg.MarshalProtobuf(nil) + return 1 +} +func DoFuzzJSONHeaderWithSignature(data []byte) int { + msg := new(HeaderWithSignature) + if err := msg.UnmarshalJSON(data); err != nil { + return 0 + } + _, err := msg.MarshalJSON() + if err != nil { + panic(err) + } + return 1 +} +func DoFuzzProtoHeadResponse(data []byte) int { + msg := new(HeadResponse) + if err := msg.UnmarshalProtobuf(data); err != nil { + return 0 + } + _ = msg.MarshalProtobuf(nil) + return 1 +} +func DoFuzzJSONHeadResponse(data []byte) int { + msg := new(HeadResponse) + if err := msg.UnmarshalJSON(data); err != nil { + return 0 + } + _, err := msg.MarshalJSON() + if err != nil { + panic(err) + } + return 1 +} +func DoFuzzProtoSearchRequest(data []byte) int { + msg := new(SearchRequest) + if err := msg.UnmarshalProtobuf(data); err != nil { + return 0 + } + _ = msg.MarshalProtobuf(nil) + return 1 +} +func DoFuzzJSONSearchRequest(data []byte) int { + msg := new(SearchRequest) + if err := msg.UnmarshalJSON(data); err != nil { + return 0 + } + _, err := msg.MarshalJSON() + if err != nil { + panic(err) + } + return 1 +} +func DoFuzzProtoSearchResponse(data []byte) int { + msg := new(SearchResponse) + if err := msg.UnmarshalProtobuf(data); err != nil { + return 0 + } + _ = msg.MarshalProtobuf(nil) + return 1 +} +func DoFuzzJSONSearchResponse(data []byte) int { + msg := new(SearchResponse) + if err := msg.UnmarshalJSON(data); err != nil { + return 0 + } + _, err := msg.MarshalJSON() + if err != nil { + panic(err) + } + return 1 +} +func DoFuzzProtoRange(data []byte) int { + msg := new(Range) + if err := msg.UnmarshalProtobuf(data); err != nil { + return 0 + } + _ = msg.MarshalProtobuf(nil) + return 1 +} +func DoFuzzJSONRange(data []byte) int { + msg := new(Range) + if err := msg.UnmarshalJSON(data); err != nil { + return 0 + } + _, err := msg.MarshalJSON() + if err != nil { + panic(err) + } + return 1 +} +func DoFuzzProtoGetRangeRequest(data []byte) int { + msg := new(GetRangeRequest) + if err := msg.UnmarshalProtobuf(data); err != nil { + return 0 + } + _ = msg.MarshalProtobuf(nil) + return 1 +} +func DoFuzzJSONGetRangeRequest(data []byte) int { + msg := new(GetRangeRequest) + if err := msg.UnmarshalJSON(data); err != nil { + return 0 + } + _, err := msg.MarshalJSON() + if err != nil { + panic(err) + } + return 1 +} +func DoFuzzProtoGetRangeResponse(data []byte) int { + msg := new(GetRangeResponse) + if err := msg.UnmarshalProtobuf(data); err != nil { + return 0 + } + _ = msg.MarshalProtobuf(nil) + return 1 +} +func DoFuzzJSONGetRangeResponse(data []byte) int { + msg := new(GetRangeResponse) + if err := msg.UnmarshalJSON(data); err != nil { + return 0 + } + _, err := msg.MarshalJSON() + if err != nil { + panic(err) + } + return 1 +} +func DoFuzzProtoGetRangeHashRequest(data []byte) int { + msg := new(GetRangeHashRequest) + if err := msg.UnmarshalProtobuf(data); err != nil { + return 0 + } + _ = msg.MarshalProtobuf(nil) + return 1 +} +func DoFuzzJSONGetRangeHashRequest(data []byte) int { + msg := new(GetRangeHashRequest) + if err := msg.UnmarshalJSON(data); err != nil { + return 0 + } + _, err := msg.MarshalJSON() + if err != nil { + panic(err) + } + return 1 +} +func DoFuzzProtoGetRangeHashResponse(data []byte) int { + msg := new(GetRangeHashResponse) + if err := msg.UnmarshalProtobuf(data); err != nil { + return 0 + } + _ = msg.MarshalProtobuf(nil) + return 1 +} +func DoFuzzJSONGetRangeHashResponse(data []byte) int { + msg := new(GetRangeHashResponse) + if err := msg.UnmarshalJSON(data); err != nil { + return 0 + } + _, err := msg.MarshalJSON() + if err != nil { + panic(err) + } + return 1 +} +func DoFuzzProtoPutSingleRequest(data []byte) int { + msg := new(PutSingleRequest) + if err := msg.UnmarshalProtobuf(data); err != nil { + return 0 + } + _ = msg.MarshalProtobuf(nil) + return 1 +} +func DoFuzzJSONPutSingleRequest(data []byte) int { + msg := new(PutSingleRequest) + if err := msg.UnmarshalJSON(data); err != nil { + return 0 + } + _, err := msg.MarshalJSON() + if err != nil { + panic(err) + } + return 1 +} +func DoFuzzProtoPutSingleResponse(data []byte) int { + msg := new(PutSingleResponse) + if err := msg.UnmarshalProtobuf(data); err != nil { + return 0 + } + _ = msg.MarshalProtobuf(nil) + return 1 +} +func DoFuzzJSONPutSingleResponse(data []byte) int { + msg := new(PutSingleResponse) + if err := msg.UnmarshalJSON(data); err != nil { + return 0 + } + _, err := msg.MarshalJSON() + if err != nil { + panic(err) + } + return 1 +} +func DoFuzzProtoPatchRequest(data []byte) int { + msg := new(PatchRequest) + if err := msg.UnmarshalProtobuf(data); err != nil { + return 0 + } + _ = msg.MarshalProtobuf(nil) + return 1 +} +func DoFuzzJSONPatchRequest(data []byte) int { + msg := new(PatchRequest) + if err := msg.UnmarshalJSON(data); err != nil { + return 0 + } + _, err := msg.MarshalJSON() + if err != nil { + panic(err) + } + return 1 +} +func DoFuzzProtoPatchResponse(data []byte) int { + msg := new(PatchResponse) + if err := msg.UnmarshalProtobuf(data); err != nil { + return 0 + } + _ = msg.MarshalProtobuf(nil) + return 1 +} +func DoFuzzJSONPatchResponse(data []byte) int { + msg := new(PatchResponse) + if err := msg.UnmarshalJSON(data); err != nil { + return 0 + } + _, err := msg.MarshalJSON() + if err != nil { + panic(err) + } + return 1 +} diff --git a/api/object/grpc/service_frostfs_test.go b/api/object/grpc/service_frostfs_test.go new file mode 100644 index 0000000..cb4baeb --- /dev/null +++ b/api/object/grpc/service_frostfs_test.go @@ -0,0 +1,211 @@ +//go:build gofuzz +// +build gofuzz + +// Code generated by protoc-gen-go-frostfs. DO NOT EDIT. + +package object + +import ( + testing "testing" +) + +func FuzzProtoGetRequest(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzProtoGetRequest(data) + }) +} +func FuzzJSONGetRequest(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzJSONGetRequest(data) + }) +} +func FuzzProtoGetResponse(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzProtoGetResponse(data) + }) +} +func FuzzJSONGetResponse(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzJSONGetResponse(data) + }) +} +func FuzzProtoPutRequest(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzProtoPutRequest(data) + }) +} +func FuzzJSONPutRequest(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzJSONPutRequest(data) + }) +} +func FuzzProtoPutResponse(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzProtoPutResponse(data) + }) +} +func FuzzJSONPutResponse(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzJSONPutResponse(data) + }) +} +func FuzzProtoDeleteRequest(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzProtoDeleteRequest(data) + }) +} +func FuzzJSONDeleteRequest(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzJSONDeleteRequest(data) + }) +} +func FuzzProtoDeleteResponse(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzProtoDeleteResponse(data) + }) +} +func FuzzJSONDeleteResponse(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzJSONDeleteResponse(data) + }) +} +func FuzzProtoHeadRequest(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzProtoHeadRequest(data) + }) +} +func FuzzJSONHeadRequest(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzJSONHeadRequest(data) + }) +} +func FuzzProtoHeaderWithSignature(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzProtoHeaderWithSignature(data) + }) +} +func FuzzJSONHeaderWithSignature(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzJSONHeaderWithSignature(data) + }) +} +func FuzzProtoHeadResponse(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzProtoHeadResponse(data) + }) +} +func FuzzJSONHeadResponse(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzJSONHeadResponse(data) + }) +} +func FuzzProtoSearchRequest(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzProtoSearchRequest(data) + }) +} +func FuzzJSONSearchRequest(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzJSONSearchRequest(data) + }) +} +func FuzzProtoSearchResponse(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzProtoSearchResponse(data) + }) +} +func FuzzJSONSearchResponse(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzJSONSearchResponse(data) + }) +} +func FuzzProtoRange(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzProtoRange(data) + }) +} +func FuzzJSONRange(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzJSONRange(data) + }) +} +func FuzzProtoGetRangeRequest(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzProtoGetRangeRequest(data) + }) +} +func FuzzJSONGetRangeRequest(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzJSONGetRangeRequest(data) + }) +} +func FuzzProtoGetRangeResponse(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzProtoGetRangeResponse(data) + }) +} +func FuzzJSONGetRangeResponse(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzJSONGetRangeResponse(data) + }) +} +func FuzzProtoGetRangeHashRequest(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzProtoGetRangeHashRequest(data) + }) +} +func FuzzJSONGetRangeHashRequest(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzJSONGetRangeHashRequest(data) + }) +} +func FuzzProtoGetRangeHashResponse(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzProtoGetRangeHashResponse(data) + }) +} +func FuzzJSONGetRangeHashResponse(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzJSONGetRangeHashResponse(data) + }) +} +func FuzzProtoPutSingleRequest(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzProtoPutSingleRequest(data) + }) +} +func FuzzJSONPutSingleRequest(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzJSONPutSingleRequest(data) + }) +} +func FuzzProtoPutSingleResponse(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzProtoPutSingleResponse(data) + }) +} +func FuzzJSONPutSingleResponse(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzJSONPutSingleResponse(data) + }) +} +func FuzzProtoPatchRequest(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzProtoPatchRequest(data) + }) +} +func FuzzJSONPatchRequest(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzJSONPatchRequest(data) + }) +} +func FuzzProtoPatchResponse(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzProtoPatchResponse(data) + }) +} +func FuzzJSONPatchResponse(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzJSONPatchResponse(data) + }) +} diff --git a/api/object/grpc/service_grpc.pb.go b/api/object/grpc/service_grpc.pb.go new file mode 100644 index 0000000000000000000000000000000000000000..eb53afe94b898709fcb9ea22b0fcbe53853d7f5c GIT binary patch literal 45844 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 PA`ZQI9HkKk|Gf79;3$I^ literal 0 HcmV?d00001 diff --git a/api/object/grpc/types_frostfs.pb.go b/api/object/grpc/types_frostfs.pb.go new file mode 100644 index 0000000000000000000000000000000000000000..9dfd4e45e61d7dcdd84c61832254ac0bd2ec4b0f GIT binary patch literal 65153 zcmeHQ`*Rz|k^UL{E7q(^0_tQ?6cr_rOIKx+bj(DrGo|FN6cqyk3lSj*pzxrmxb(m0 z>&HCz2^vd?Iys6h>`u>o)6>)4)6+A%yPF(L`f2h$9jCMIBJC$K={K-Qj4q z!?}zGZapfFA<=%T}xP;7PKru(t2x_a1&*1pH(lPpCQi@hPbGsykYm zdZos9Ts_rmD}4ft52$9Z+9$~#KjCVr0RGwM>H&YS9QTs;wb%Qd6;fPuZ|9me>^@qOl$$P4Vkk)PfuR| zeEj0ir$_(u=KE(d8vJit0OcWm_NOTi9U9Qs0x18`FHZ$u{d{zC^y0NweSl}*FMsgz z`SX`Ah~&rP|8*38{f|6Jx6gU>(Rh)d=kvwNz0U@I_zuL^Q8dW6P-K(Hk~re8JS5Ll%~i-o@hQ+^MoRhX>LsQb$ zzru{PG^hC!(!O6|KAxPzS@4CqcGqTQBcJGn3@7SmRBrEh}`$|e} z|8uK#FiX1&P#jGsy>pN)Sr=J)CFuF3i0tJDcss{^TTa@Mr-wKFQbhBr`*Aes_MfHW_lsg|Q@@l)_EUFGL`fpp4$jlw#e8{buqhdpBBGxrm-ydo zdOqwiVLs7$SPFztk81Z$6XQK}UXfGsygQqpcSjhW1gfEZ&l|9v_INmg=8Z|-j4v%w zAqfp($FH0_N&hM*@hh(&fi>LSh4Jg2jnb3hztco4*F0IAr^%ciOa{p{JPvVm&z6H^ zz{actIw2*2T+Y&Y@?nUvV>)sM2E%mJPk0v0lk@IX>Rz1<$KBaSuD;_epwBfA5lnKM zfk0e$)BwV?Jx#z^-|)iRKoxSy|9UEDJ1^2X+;o^yfk+)}@7+(X%{0NlgamJ3qaQ!w zau2CoFlREQ^Qzw`GMzISf}`>Bk}H37U!1r$%G!yrlPT}P`90MeOp{FMJUEX%GLrUM zM1LTnXqte~I5prRO$Nw~$|g?&5)G_tM(JfbUWoh@%@T}cIvaF*Y0>CM^|t%)bKkx@ z`?yGV^uILnm*kky%EHZ&SM=-8>7os|{d9mCne+bDa?!p-f$PrE<#1uZw=X--vEacn z&Ca+sjR>_3dvDqxERGlWL98$iWia!Tu=dO3o?Sv@S}GB27HhboR%nxNob20&QCBWI z-%qFMxUW5G?@>=MJ-D7gsHwIGJdZ97(Hk}l?c51q>M&Lzz@iT;u zpL(`9CPd}rvxQCF?fI-{r(Zjr%@X{7GGmz~i#X^dPO^U_wSO?d48L9=kTIDhqjXF) z>?HrKf`%XWsR~T1K@U3mdcj0o2)-g@lwNx5H<||#k}+hJr34a&&4ZkXNahqmv{nf8b+PYC z!}9hA=22wL8s}5gUcjs99mdqE)IxqmG|ll0`W1iFnZ_ap4rIRn2tQVB0@gs`@?PSA z*S?X|3axRd+scV+zagTjV@HlS)> zX+sJ&cv%Hm)v@KSs_jzDO5>v~8$;kVtr+fVD+*ZORzkHJ6=Z{T)%8| z@2tCVoxk&@+%FieYqPRH!ZsjN|MmlnsjAZtogbD1#1ZhH;i&%uA`tU7Hg7)2I;2od zDHvPjWVuN0g>Ca7vugBWSt!@}x%)vkf40ZV(TEM3py81j3}=W)pewS8qZEX!{kva& z2jsM*LA~EdLHgAS3f-qdtxrjcJs%S6R!d4^HOAXOvR0DK#VPiYhu3CL>}j(74---T z$MzF!SDKm?uoS22t=Y(M7g$gLjBglc&ktl*pbhx5&HSN9cIXEXSw!A>FHZt1 zG88lm%#ZBxSsuv{aqZ3bej@SsihkQj<;F&7Vogc~)GHEsFg=bJLDnGbSA`q3S8hj? zg;gc>inl}kNkD^n%=OEw+mO+zzoAjVfVIh}nibh=*`$nW@5yjh^xa0jsqDsN^*r1X zs>B?by<*(K(0+pYiGqBE=F!G~R*LJfk)x%!4eDXhh(H|_GRK!Bb*1x+a$J5nM7bv% zaba6&TePO_w-hx}YdI6MhyYp9nkGw+h}}KEMX`(X*OTe9^eP?6wC^0xu}3xIxIU)) zaEu2pU>srT)r<@s1=}Un6Fgx<+G=qmHeA5b%NE%#yZY7jBtgX+x5l-jIULJ7YrjD~pwh%Y zX*)2iSp>4~;|5roz>>dU9}~gWvvkHhX|=}0$5}^pv9t&cuCWVaXB_GMsta8pv(SAvkncZ)S{o1|e%{OkXXQ>dcX8VOgUN_I~+7+Xnq@U1N|+d~ip0>%6i!_VNRT`*)8F+3q#o+k+a*~Tjp zg#Cv)yt$H4APT-Ln6@ebvd9mRn}Aq`a-f(-K#82u;Cm%ixZE&gM>lW=vIBhA=T+c# z6!xABe75i5@;E!W%sRc!>{1-mP!>gG;+sVh`3F84wN_$F)H2{1beywE99WCY9t!wY z?-O|voINV(L#N*_FqhAk3*>g#M54dKvLt4Sr`b8MHk2wOxFFb*J{0Ru&*j#g@3 zB7zPjn>vi(&G&9meXwbU-!MVc8d~)d09ZPj1i}pjQ22=h19st$Dw-%H9rJf5!L}K? zf|cQ%wHmFOz^D8jC}y#%dwbhoxMr(H+@7kw(yG}@<~awf!RA<&ls5Bdn$^RlJYNZ! zR3Bk8oFsI=KH#41)~2KGg^28m7QvM-CG>ugeyj*OQ6xzfgxG@Hh+5yHZiP9%?)uJUh7DT?mM0^Jd9M7Ye z7K`u=Dl_WURtJ&Jg!J(2S1;U7rlaA)TeQ9E&X8v97Cst%;sDXHJC=b61d7p8?$s>4 z8cvpTLsCSb#h8SNPloTuT}trR*rNNbYei|pK6aEM_|%{-txVfyDJhgvjK~hovBwI) zrrg_ioCPUC6ZA?O>}fF~VZL~$Q)JuMRA7&%%!z%+bUX!Su;wWaowwY=ic8jrrq*&b zkH)I3f~BfY^Z6}P1>KsKsCkDQ_$Y_W1Xz=Bxtdp=*D+=y)S}?i9MXan@LGh(R;NuX zntdWiprVb1AxFNuV;lxYsM*Ln1@&t zc}!S%Fpm2uc^eCM9s0YzSl4c>ccE_N!r#9z&nnIU1jjgxAV>A60mBYeeNr>v?bd{EDr$VBNXutWFdZst{JrbD1WnA`$O)WC#!obZnhk-d&{^I8 zC4@h?Pb-8zL?Uy74(rafX7>n6Q8qZ?9!ksb5bd6+aX+{eA_=-TWs15@R69@TI{6~!J|fN4JbOZA7zC{%EWQZ&zC(+mQIQPU_YDh^ zoD315qLy!oW71d-yVN*{V9Aeyc_uF#W{{joF@9O&%rOlGj4=-(KwUn>iLkzTc0UPL zM8AAuW(@}9Rr)TW*fm47^X=X{>WdS+ftP{Mh}x2KGiq3K_$YSO4E4=}*xEwCKz#=O zX)qhUG5(askC}#J$1*z*rj1s}WnpBYsoe^vf0O003DefbP_)`u7IYvlsO&*iRl6cs zrCJHDY00Fj$AI;HHRMo%TI5y(mWJyi6}wUoqJ~XJY{MGNkD932AyH1$8&zo4(jo;{ z?}9c3{PMQ|x3*p-I7Tr5a2#VP18&Gx0c~g?>QPe)+!Uzfv`%Zre1>%QQc2Oms~|P? z6HuyO@#$lQx3)bLu6D=Vpui#NO`KW~fjJG)*s$~$w0AP)`CqY1VKi@XsxGDnnbD>W zS4>rpR^!xyn?oAv(`vwB`3>V1v9AeQ3U3T?PosntXoH=!w|s`BJY+(0Jai$C=$wk2 z5+c8elVTMEVvPlS;F1A`cZ31-4NsZ5g!U`AgTC4rs2|_r4agsG0mS1+;*#1@B5MMVgZ?JJGwkW&Z7_K;I=C#5ca^2qJ zWm84^zWA~5TI|-OWbYdb({Sr``21}B|55^;tEeDLe2tdfA z`i)EZY|BQkXIl-{_}n&aS&oK$3s&}}+guj452=Zdus|1+yKE#XsDlo{@(UMR@us)* zv&D_ufCT-zpA7UJ+K(oIm<>8iVRpElGJI~x!DS2KA1zT`p5=&m!+`d$D5?XZ5r zHn1n|)TeT&wV8?rW2hg);=M<2GVmULh%ztNf$wni$jlrL0%3^76GfOCc$t60T|JaAsE@6 z_Z3@{nEZAEX#NWk=juBlg*ZbhoL>)}37Qm!hxrP$=Qc$0-aiIpqck;L46%Jc~ zdT`V})q*3{MsSR^$xA0uIMOMJ`qV?^Q~1MJ!YiKy2>~(^$}<05Ip?G#Kx#CpY$Tk_Cx6@FH(zyqsmL03T$~6eKPQA6%8ZLqXcIZUR$W!A%mG0-z0~`jDBl5z@`% z`2-NGt^S(i6XiG5xt(CjS}U8%5bj}95TmvBBp#sZSpoe zD3H7A)tuPm;Y*l>HTG&wv#O3#ir9Vl@_K6)?NM)ikL1hiwC^`zMU>n3Y_F@*gVg28 z)F*RP9EHQxs}-YS{EV{Nr6ew(D7diKM9kKq4gx12%R}k2Go@Kb!Y#K}W>8)RTJC$7 zS5-F&Ev}}?JT&3I>onLxIc(fBhuq6YgO}7q_L!GCWB{?vFYd+Z z4&4`dg$fC4`t;CcVv&)OqMQn4ZWRvO(`$+Kp|&@1AM*`9Xn;~=Lhx0e;2)(5?}g?B zu+oqEave7F$}1|#WBh<`X{CbNPxEEp99q6P7Ol!u;?I|JsrWZNH2rk6 z>OVJa(&~w5j(Q#e{%UBD)@c7xnzRRkRTJP=%YJjE>!iL#rLC`=pZBJvKf9#2#xvgB zCGV9vT>6n$t10Mym};WZZybByEaqgmK!aqe_e$q}n6(;=CgWIjk!iwybQvjelCM<$ z(dE2sI%K$IKIWQfD39<@eD{tw;X#$jzw;CTEzK+Y>@x4@GIX5#b`{v9yUI%1dwhKo z>xx=k+2cIPqaF(1LPnnrUb`LTyYdleactI~%V&H8Z*gTm(@>G$6cm0Oh^!20PkV_U(nq!=rDaoUOS&&b(HU)WQ>%2 zeEqv@cwU|P!R11}-Zp4&FUOboa?^Qt^d$Mshi(2GQz&hc)#^ekIV=*7#$dd;q`5`{ z-nhpYKKCR1#JnVqMt)Ha*7Xi&)LsBPdKakHqG63_8rH3U;$&Oj?Q5K2eq#Z*{1+ap z!myeVF*^->s)m`h_kg+O9Nflv<(djOV}ddm@Gu zwrrfI90Lj1DG^lvRzkfZiLm%?As1{~$iyo=>NU=Yqh7!Ttdjy3AUh!LKbB67SsM5@ z_*0gD&dKNMncL)5s7Z|mkl}3_FjvOuZ_VR0&E+P0GeFNTwjkZJ z!_rh#R}Ke8D!Bo$9)ZoMbV18W*EoYe*tq`oZy z78UBOj3XD09-*Iln(3086C}!^gRe6U3#;7S9j`(eb? z?jn|ejC{D&cpDM>kc;^n5f$+`Dpt}3->owELr<)ftT20fjrxm0(YfKV6%%s4A+DS@lDFWa*294rE+_jsJRG|r=K)bY#xq! z9xCh~mq8-urH=VRoem6TBQg?pL`b);>vV+OUE1))n-+)7wM3HXm-4x?D@j|aNdL9Y z*v9gedp6u!ooDSiP8-8Jk@TEOzN-JUF`PZ$IjTS#1yJ9H5=3oQ^DyUJCZ7dZlQTfJA0NgDkOdQX02Mc)HA zZ)37Lu})kC+$*|jKW9%@go(agKe?bH&P_ZWcQ4boSMR=~Hzaf{j(U~o73Vp}_l!#H zR9>;&Y*<#$!_>D57GyGEHa2Q=FR`W)wC^Qu3~|>c@KxXqR93;M7|(rVxq>#UdmhG- z-sB`q!{Runs9yzt%)Y-KarONtX#D2Yd)li6h}c*mx?p(Mf0oG0CfLY9BCmZrGG9*- z-QX0F`q0@V{UBYOj7lpwMPy=>^2Wtzz0u%UE}|?hfEk^(@ciPU_MJO?n8o0|l(xK& z&g9^5#e;iXc{^ZRecmD*;_BvL&=+;uS9ckXX3PiQkIf>GfFO5&-KVM^KN8?j?6kY( zB`smRS3XsR+_}6{RY8C=+xw~S$9{Re4?O0=-jg4j?R$7AA!h=ZaAu8J7{)py33T3R z7KC#&xfMF6gCjokv@hQ#j$Ug%mU^+cr)H7P2HhS$OW$cPK2GJMClD^4by#o>$M5;b z62xtgEyt@1-XyF_l4Wy@1jKO472KjA(OSHf2exh#5GGjoZFeF0NKVX%5^r! z49y-~I3o(Cgl-`PZB+tf1`I}%E>cdF1I08lOQjp6hP{&9s-JM4m9fbC&JOW9YcT=D4wj`muqq*(=17x+$i=1%RcdXKwk zMDHY?JfM$=%S6-PI7%0s6XVZ^x7?=$q_F#KPFk7orPFCE;RYS7($R>|Se^6zB2-ij z01CvHq-(`$h*vt3C0%jnrqXe5(uYp(aE`IvxyJ#jr%C%>T)O;BR&Hs(O54{=-Jj8! zEbT?pw~$LSHSg}`gEm&MFhi>k^YD=@k+w{EcjGu8olrqTu||*a7{=-n*e132@5(VA z(}C#b5R9l;3(nhKP1i!M;z`GE^|zRUUiHp`0l)WT6Gd3 zI1FJ_O<0wcoQk@FLp-XfJcr8Mv0YJ%cZ6q@j`6KhBVPn6I>93s#70us(ATuh@L7#y zCGalZIW4{6>?|^f)yFD~l#v;3^jw8$D99W$4`Ehp+Oj^&o*OWQU6jHO)jDsHl`J|t zIT~k-Z7JZ4ed@EuK7>+knY9fz5fJ1wQ@mm3$cYM30*!Mc>wv%5OIHu6EpDOOCnjIWOsW#FB5W?fr4*qQt_M#mwplKU zNgkH~QsDri8rR-x;d+Qn&C#v5P8!#fd1E9&y`_z1-b6TTBpO>XUrOf9L=-}GI*ah) zxL>?c)$~@MnTnOWX?7BC4C^_s)hmI@Ox_sEsl@9mVDd`D%y7@?&$$XzOOZK_^At3R z;a0wfYNoCA=WlsqGt<6R9A7s!gWw!C50Fqd94}Ln82n!sD;McUUJvVro~o#v5MuCk zN^-$kestM69`efhgWiC!?})ukqu*dxZ9q|jrbh7;0kHZei@?5;W-4OarlBkbQ7Ab8 zM1=$m%cD9CO37?%su;4(Ro$Lv)P%=F8rHQ2WjWXQcs!VRaannWuxu0%HGx)&O5;l` zh@C#`&gmNzu-}2~nE35TUvtsn_<{qI1x4|Cr3kA9UN^{^Lr@-PEh4arFuwjOCisk^ ztq$6n025PxCCX|f2NSDiko6fP1f?5|oqBA#v*A;(59^JfN|aHmFZoDcBoEM7 z?DLob4@0KrX+^9vh?tTfM77{aMGYD)ZR8>ukKx$f{o<{_X}M`BH3=Tlkv zS!X0xf{iqPn&$}`3Hd>@wiYjFGH2(}n)m==#-IGio)voz?x|?ii~DHddX*!pXDW|E zKl&Ja3SxQk7)}}kGs0q{dFpJJpAR-vwILb;8_hG#XyDAeuKVu@}?I~tm z+8BU%r{I45@ilJ?W zMP%luGsW6_ULY^{B} zU0JYA$>&&QI4ZV>yxD3LnJ)Al=IaXHP!O&>&d)x Z_q^2ouDoAGli!rrc~^Bu&l*=g{{iEYE9C$H literal 0 HcmV?d00001 diff --git a/api/object/grpc/types_frostfs_fuzz.go b/api/object/grpc/types_frostfs_fuzz.go new file mode 100644 index 0000000..8491638 --- /dev/null +++ b/api/object/grpc/types_frostfs_fuzz.go @@ -0,0 +1,102 @@ +//go:build gofuzz +// +build gofuzz + +// Code generated by protoc-gen-go-frostfs. DO NOT EDIT. + +package object + +func DoFuzzProtoShortHeader(data []byte) int { + msg := new(ShortHeader) + if err := msg.UnmarshalProtobuf(data); err != nil { + return 0 + } + _ = msg.MarshalProtobuf(nil) + return 1 +} +func DoFuzzJSONShortHeader(data []byte) int { + msg := new(ShortHeader) + if err := msg.UnmarshalJSON(data); err != nil { + return 0 + } + _, err := msg.MarshalJSON() + if err != nil { + panic(err) + } + return 1 +} +func DoFuzzProtoHeader(data []byte) int { + msg := new(Header) + if err := msg.UnmarshalProtobuf(data); err != nil { + return 0 + } + _ = msg.MarshalProtobuf(nil) + return 1 +} +func DoFuzzJSONHeader(data []byte) int { + msg := new(Header) + if err := msg.UnmarshalJSON(data); err != nil { + return 0 + } + _, err := msg.MarshalJSON() + if err != nil { + panic(err) + } + return 1 +} +func DoFuzzProtoObject(data []byte) int { + msg := new(Object) + if err := msg.UnmarshalProtobuf(data); err != nil { + return 0 + } + _ = msg.MarshalProtobuf(nil) + return 1 +} +func DoFuzzJSONObject(data []byte) int { + msg := new(Object) + if err := msg.UnmarshalJSON(data); err != nil { + return 0 + } + _, err := msg.MarshalJSON() + if err != nil { + panic(err) + } + return 1 +} +func DoFuzzProtoSplitInfo(data []byte) int { + msg := new(SplitInfo) + if err := msg.UnmarshalProtobuf(data); err != nil { + return 0 + } + _ = msg.MarshalProtobuf(nil) + return 1 +} +func DoFuzzJSONSplitInfo(data []byte) int { + msg := new(SplitInfo) + if err := msg.UnmarshalJSON(data); err != nil { + return 0 + } + _, err := msg.MarshalJSON() + if err != nil { + panic(err) + } + return 1 +} +func DoFuzzProtoECInfo(data []byte) int { + msg := new(ECInfo) + if err := msg.UnmarshalProtobuf(data); err != nil { + return 0 + } + _ = msg.MarshalProtobuf(nil) + return 1 +} +func DoFuzzJSONECInfo(data []byte) int { + msg := new(ECInfo) + if err := msg.UnmarshalJSON(data); err != nil { + return 0 + } + _, err := msg.MarshalJSON() + if err != nil { + panic(err) + } + return 1 +} diff --git a/api/object/grpc/types_frostfs_test.go b/api/object/grpc/types_frostfs_test.go new file mode 100644 index 0000000..11825be --- /dev/null +++ b/api/object/grpc/types_frostfs_test.go @@ -0,0 +1,61 @@ +//go:build gofuzz +// +build gofuzz + +// Code generated by protoc-gen-go-frostfs. DO NOT EDIT. + +package object + +import ( + testing "testing" +) + +func FuzzProtoShortHeader(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzProtoShortHeader(data) + }) +} +func FuzzJSONShortHeader(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzJSONShortHeader(data) + }) +} +func FuzzProtoHeader(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzProtoHeader(data) + }) +} +func FuzzJSONHeader(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzJSONHeader(data) + }) +} +func FuzzProtoObject(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzProtoObject(data) + }) +} +func FuzzJSONObject(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzJSONObject(data) + }) +} +func FuzzProtoSplitInfo(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzProtoSplitInfo(data) + }) +} +func FuzzJSONSplitInfo(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzJSONSplitInfo(data) + }) +} +func FuzzProtoECInfo(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzProtoECInfo(data) + }) +} +func FuzzJSONECInfo(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzJSONECInfo(data) + }) +} diff --git a/api/object/json.go b/api/object/json.go new file mode 100644 index 0000000..faef249 --- /dev/null +++ b/api/object/json.go @@ -0,0 +1,94 @@ +package object + +import ( + object "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/message" +) + +func (h *ShortHeader) MarshalJSON() ([]byte, error) { + return message.MarshalJSON(h) +} + +func (h *ShortHeader) UnmarshalJSON(data []byte) error { + return message.UnmarshalJSON(h, data, new(object.ShortHeader)) +} + +func (a *Attribute) MarshalJSON() ([]byte, error) { + return message.MarshalJSON(a) +} + +func (a *Attribute) UnmarshalJSON(data []byte) error { + return message.UnmarshalJSON(a, data, new(object.Header_Attribute)) +} + +func (h *SplitHeader) MarshalJSON() ([]byte, error) { + return message.MarshalJSON(h) +} + +func (h *SplitHeader) UnmarshalJSON(data []byte) error { + return message.UnmarshalJSON(h, data, new(object.Header_Split)) +} + +func (h *Header) MarshalJSON() ([]byte, error) { + return message.MarshalJSON(h) +} + +func (h *Header) UnmarshalJSON(data []byte) error { + return message.UnmarshalJSON(h, data, new(object.Header)) +} + +func (h *HeaderWithSignature) MarshalJSON() ([]byte, error) { + return message.MarshalJSON(h) +} + +func (h *HeaderWithSignature) UnmarshalJSON(data []byte) error { + return message.UnmarshalJSON(h, data, new(object.HeaderWithSignature)) +} + +func (o *Object) MarshalJSON() ([]byte, error) { + return message.MarshalJSON(o) +} + +func (o *Object) UnmarshalJSON(data []byte) error { + return message.UnmarshalJSON(o, data, new(object.Object)) +} + +func (s *SplitInfo) MarshalJSON() ([]byte, error) { + return message.MarshalJSON(s) +} + +func (s *SplitInfo) UnmarshalJSON(data []byte) error { + return message.UnmarshalJSON(s, data, new(object.SplitInfo)) +} + +func (e *ECInfo) MarshalJSON() ([]byte, error) { + return message.MarshalJSON(e) +} + +func (e *ECInfo) UnmarshalJSON(data []byte) error { + return message.UnmarshalJSON(e, data, new(object.ECInfo)) +} + +func (e *ECChunk) MarshalJSON() ([]byte, error) { + return message.MarshalJSON(e) +} + +func (e *ECChunk) UnmarshalJSON(data []byte) error { + return message.UnmarshalJSON(e, data, new(object.ECInfo_Chunk)) +} + +func (f *SearchFilter) MarshalJSON() ([]byte, error) { + return message.MarshalJSON(f) +} + +func (f *SearchFilter) UnmarshalJSON(data []byte) error { + return message.UnmarshalJSON(f, data, new(object.SearchRequest_Body_Filter)) +} + +func (r *Range) MarshalJSON() ([]byte, error) { + return message.MarshalJSON(r) +} + +func (r *Range) UnmarshalJSON(data []byte) error { + return message.UnmarshalJSON(r, data, new(object.Range)) +} diff --git a/api/object/lock.go b/api/object/lock.go new file mode 100644 index 0000000..3af06c6 --- /dev/null +++ b/api/object/lock.go @@ -0,0 +1,160 @@ +package object + +import ( + "errors" + "fmt" + + lock "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/lock/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" + refsGRPC "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/message" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/util/proto" +) + +// Lock represents object Lock message from NeoFS API V2 protocol. +type Lock struct { + members []refs.ObjectID +} + +// NumberOfMembers returns length of lock list. +func (x *Lock) NumberOfMembers() int { + if x != nil { + return len(x.members) + } + + return 0 +} + +// IterateMembers passes members of the lock list to f. +func (x *Lock) IterateMembers(f func(refs.ObjectID)) { + if x != nil { + for i := range x.members { + f(x.members[i]) + } + } +} + +// SetMembers sets list of locked members. +// Arg must not be mutated for the duration of the Lock. +func (x *Lock) SetMembers(ids []refs.ObjectID) { + x.members = ids +} + +const ( + _ = iota + fNumLockMembers +) + +// StableMarshal encodes the Lock into Protocol Buffers binary format +// with direct field order. +func (x *Lock) StableMarshal(buf []byte) []byte { + if x == nil || len(x.members) == 0 { + return []byte{} + } + + if buf == nil { + buf = make([]byte, x.StableSize()) + } + + var offset int + + for i := range x.members { + offset += proto.NestedStructureMarshal(fNumLockMembers, buf[offset:], &x.members[i]) + } + + return buf +} + +// StableSize size of the buffer required to write the Lock in Protocol Buffers +// binary format. +func (x *Lock) StableSize() (sz int) { + if x != nil { + for i := range x.members { + sz += proto.NestedStructureSize(fNumLockMembers, &x.members[i]) + } + } + + return +} + +// Unmarshal decodes the Lock from its Protocol Buffers binary format. +func (x *Lock) Unmarshal(data []byte) error { + return message.Unmarshal(x, data, new(lock.Lock)) +} + +func (x *Lock) ToGRPCMessage() grpc.Message { + var m *lock.Lock + + if x != nil { + m = new(lock.Lock) + + var members []refsGRPC.ObjectID + + if x.members != nil { + members = make([]refsGRPC.ObjectID, len(x.members)) + + for i := range x.members { + members[i] = *x.members[i].ToGRPCMessage().(*refsGRPC.ObjectID) + } + } + + m.SetMembers(members) + } + + return m +} + +func (x *Lock) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*lock.Lock) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + members := v.GetMembers() + if members == nil { + x.members = nil + } else { + x.members = make([]refs.ObjectID, len(members)) + var err error + + for i := range x.members { + err = x.members[i].FromGRPCMessage(&members[i]) + if err != nil { + return err + } + } + } + + return nil +} + +// WriteLock writes Lock to the Object as a payload content. +// The object must not be nil. +func WriteLock(obj *Object, lock Lock) { + hdr := obj.GetHeader() + if hdr == nil { + hdr = new(Header) + obj.SetHeader(hdr) + } + + hdr.SetObjectType(TypeLock) + + payload := lock.StableMarshal(nil) + obj.SetPayload(payload) +} + +// ReadLock reads Lock from the Object payload content. +func ReadLock(lock *Lock, obj Object) error { + payload := obj.GetPayload() + if len(payload) == 0 { + return errors.New("empty payload") + } + + err := lock.Unmarshal(payload) + if err != nil { + return fmt.Errorf("decode lock content from payload: %w", err) + } + + return nil +} diff --git a/api/object/lock_test.go b/api/object/lock_test.go new file mode 100644 index 0000000..2515723 --- /dev/null +++ b/api/object/lock_test.go @@ -0,0 +1,26 @@ +package object_test + +import ( + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" + objecttest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object/test" + "github.com/stretchr/testify/require" +) + +func TestLockRW(t *testing.T) { + var l object.Lock + var obj object.Object + + require.Error(t, object.ReadLock(&l, obj)) + + l = *objecttest.GenerateLock(false) + + object.WriteLock(&obj, l) + + var l2 object.Lock + + require.NoError(t, object.ReadLock(&l2, obj)) + + require.Equal(t, l, l2) +} diff --git a/api/object/marshal.go b/api/object/marshal.go new file mode 100644 index 0000000..82e265b --- /dev/null +++ b/api/object/marshal.go @@ -0,0 +1,1428 @@ +package object + +import ( + object "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/message" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/util/proto" +) + +const ( + shortHdrVersionField = 1 + shortHdrEpochField = 2 + shortHdrOwnerField = 3 + shortHdrObjectTypeField = 4 + shortHdrPayloadLength = 5 + shortHdrHashField = 6 + shortHdrHomoHashField = 7 + + attributeKeyField = 1 + attributeValueField = 2 + + splitHdrParentField = 1 + splitHdrPreviousField = 2 + splitHdrParentSignatureField = 3 + splitHdrParentHeaderField = 4 + splitHdrChildrenField = 5 + splitHdrSplitIDField = 6 + + ecHdrParentField = 1 + ecHdrIndexField = 2 + ecHdrTotalField = 3 + ecHdrHeaderLengthField = 4 + ecHdrHeaderField = 5 + ecHdrParentSplitID = 6 + ecHdrParentSplitParentID = 7 + ecHdrParentAttributes = 8 + + hdrVersionField = 1 + hdrContainerIDField = 2 + hdrOwnerIDField = 3 + hdrEpochField = 4 + hdrPayloadLengthField = 5 + hdrPayloadHashField = 6 + hdrObjectTypeField = 7 + hdrHomomorphicHashField = 8 + hdrSessionTokenField = 9 + hdrAttributesField = 10 + hdrSplitField = 11 + hdrECField = 12 + + hdrWithSigHeaderField = 1 + hdrWithSigSignatureField = 2 + + objIDField = 1 + objSignatureField = 2 + objHeaderField = 3 + objPayloadField = 4 + + splitInfoSplitIDField = 1 + splitInfoLastPartField = 2 + splitInfoLinkField = 3 + + ecInfoChunksField = 1 + + ecChunkIDField = 1 + ecChunkIndexField = 2 + ecChunkTotalField = 3 + + getReqBodyAddressField = 1 + getReqBodyRawFlagField = 2 + + getRespInitObjectIDField = 1 + getRespInitSignatureField = 2 + getRespInitHeaderField = 3 + + getRespBodyInitField = 1 + getRespBodyChunkField = 2 + getRespBodySplitInfoField = 3 + getRespBodyECInfoField = 4 + + putReqInitObjectIDField = 1 + putReqInitSignatureField = 2 + putReqInitHeaderField = 3 + putReqInitCopiesNumField = 4 + + putReqBodyInitField = 1 + putReqBodyChunkField = 2 + + putRespBodyObjectIDField = 1 + + deleteReqBodyAddressField = 1 + + deleteRespBodyTombstoneFNum = 1 + + headReqBodyAddressField = 1 + headReqBodyMainFlagField = 2 + headReqBodyRawFlagField = 3 + + headRespBodyHeaderField = 1 + headRespBodyShortHeaderField = 2 + headRespBodySplitInfoField = 3 + headRespBodyECInfoField = 4 + + searchFilterMatchField = 1 + searchFilterNameField = 2 + searchFilterValueField = 3 + + searchReqBodyContainerIDField = 1 + searchReqBodyVersionField = 2 + searchReqBodyFiltersField = 3 + + searchRespBodyObjectIDsField = 1 + + rangeOffsetField = 1 + rangeLengthField = 2 + + getRangeReqBodyAddressField = 1 + getRangeReqBodyRangeField = 2 + getRangeReqBodyRawField = 3 + + getRangeRespChunkField = 1 + getRangeRespSplitInfoField = 2 + getRangeRespECInfoField = 3 + + getRangeHashReqBodyAddressField = 1 + getRangeHashReqBodyRangesField = 2 + getRangeHashReqBodySaltField = 3 + getRangeHashReqBodyTypeField = 4 + + getRangeHashRespBodyTypeField = 1 + getRangeHashRespBodyHashListField = 2 + + putSingleReqObjectField = 1 + putSingleReqCopiesNumberField = 2 + + patchRequestBodyPatchRangeField = 1 + patchRequestBodyPatchChunkField = 2 + + patchRequestBodyAddrField = 1 + patchRequestBodyNewAttrsField = 2 + patchRequestBodyReplaceAttrField = 3 + patchRequestBodyPatchField = 4 + + patchResponseBodyObjectIDField = 1 +) + +func (h *ShortHeader) StableMarshal(buf []byte) []byte { + if h == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, h.StableSize()) + } + + var offset int + + offset += proto.NestedStructureMarshal(shortHdrVersionField, buf[offset:], h.version) + offset += proto.UInt64Marshal(shortHdrEpochField, buf[offset:], h.creatEpoch) + offset += proto.NestedStructureMarshal(shortHdrOwnerField, buf[offset:], h.ownerID) + offset += proto.EnumMarshal(shortHdrObjectTypeField, buf[offset:], int32(h.typ)) + offset += proto.UInt64Marshal(shortHdrPayloadLength, buf[offset:], h.payloadLen) + offset += proto.NestedStructureMarshal(shortHdrHashField, buf[offset:], h.payloadHash) + proto.NestedStructureMarshal(shortHdrHomoHashField, buf[offset:], h.homoHash) + + return buf +} + +func (h *ShortHeader) StableSize() (size int) { + if h == nil { + return 0 + } + + size += proto.NestedStructureSize(shortHdrVersionField, h.version) + size += proto.UInt64Size(shortHdrEpochField, h.creatEpoch) + size += proto.NestedStructureSize(shortHdrOwnerField, h.ownerID) + size += proto.EnumSize(shortHdrObjectTypeField, int32(h.typ)) + size += proto.UInt64Size(shortHdrPayloadLength, h.payloadLen) + size += proto.NestedStructureSize(shortHdrHashField, h.payloadHash) + size += proto.NestedStructureSize(shortHdrHomoHashField, h.homoHash) + + return size +} + +func (h *ShortHeader) Unmarshal(data []byte) error { + return message.Unmarshal(h, data, new(object.ShortHeader)) +} + +func (a *Attribute) StableMarshal(buf []byte) []byte { + if a == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, a.StableSize()) + } + + var offset int + + offset += proto.StringMarshal(attributeKeyField, buf[offset:], a.key) + proto.StringMarshal(attributeValueField, buf[offset:], a.val) + + return buf +} + +func (a *Attribute) StableSize() (size int) { + if a == nil { + return 0 + } + + size += proto.StringSize(shortHdrVersionField, a.key) + size += proto.StringSize(shortHdrEpochField, a.val) + + return size +} + +func (a *Attribute) Unmarshal(data []byte) error { + return message.Unmarshal(a, data, new(object.Header_Attribute)) +} + +func (h *SplitHeader) StableMarshal(buf []byte) []byte { + if h == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, h.StableSize()) + } + + var offset int + + offset += proto.NestedStructureMarshal(splitHdrParentField, buf[offset:], h.par) + offset += proto.NestedStructureMarshal(splitHdrPreviousField, buf[offset:], h.prev) + offset += proto.NestedStructureMarshal(splitHdrParentSignatureField, buf[offset:], h.parSig) + offset += proto.NestedStructureMarshal(splitHdrParentHeaderField, buf[offset:], h.parHdr) + offset += refs.ObjectIDNestedListMarshal(splitHdrChildrenField, buf[offset:], h.children) + proto.BytesMarshal(splitHdrSplitIDField, buf[offset:], h.splitID) + + return buf +} + +func (h *SplitHeader) StableSize() (size int) { + if h == nil { + return 0 + } + + size += proto.NestedStructureSize(splitHdrParentField, h.par) + size += proto.NestedStructureSize(splitHdrPreviousField, h.prev) + size += proto.NestedStructureSize(splitHdrParentSignatureField, h.parSig) + size += proto.NestedStructureSize(splitHdrParentHeaderField, h.parHdr) + size += refs.ObjectIDNestedListSize(splitHdrChildrenField, h.children) + size += proto.BytesSize(splitHdrSplitIDField, h.splitID) + + return size +} + +func (h *SplitHeader) Unmarshal(data []byte) error { + return message.Unmarshal(h, data, new(object.Header_Split)) +} + +func (h *ECHeader) StableMarshal(buf []byte) []byte { + if h == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, h.StableSize()) + } + + var offset int + + offset += proto.NestedStructureMarshal(ecHdrParentField, buf[offset:], h.Parent) + offset += proto.UInt32Marshal(ecHdrIndexField, buf[offset:], h.Index) + offset += proto.UInt32Marshal(ecHdrTotalField, buf[offset:], h.Total) + offset += proto.UInt32Marshal(ecHdrHeaderLengthField, buf[offset:], h.HeaderLength) + offset += proto.BytesMarshal(ecHdrHeaderField, buf[offset:], h.Header) + offset += proto.BytesMarshal(ecHdrParentSplitID, buf[offset:], h.ParentSplitID) + offset += proto.NestedStructureMarshal(ecHdrParentSplitParentID, buf[offset:], h.ParentSplitParentID) + for i := range h.ParentAttributes { + offset += proto.NestedStructureMarshal(ecHdrParentAttributes, buf[offset:], &h.ParentAttributes[i]) + } + return buf +} + +func (h *ECHeader) StableSize() (size int) { + if h == nil { + return 0 + } + + size += proto.NestedStructureSize(ecHdrParentField, h.Parent) + size += proto.UInt32Size(ecHdrIndexField, h.Index) + size += proto.UInt32Size(ecHdrTotalField, h.Total) + size += proto.UInt32Size(ecHdrHeaderLengthField, h.HeaderLength) + size += proto.BytesSize(ecHdrHeaderField, h.Header) + size += proto.BytesSize(ecHdrParentSplitID, h.ParentSplitID) + size += proto.NestedStructureSize(ecHdrParentSplitParentID, h.ParentSplitParentID) + for i := range h.ParentAttributes { + size += proto.NestedStructureSize(ecHdrParentAttributes, &h.ParentAttributes[i]) + } + + return size +} + +func (h *ECHeader) Unmarshal(data []byte) error { + return message.Unmarshal(h, data, new(object.Header_EC)) +} + +func (h *Header) StableMarshal(buf []byte) []byte { + if h == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, h.StableSize()) + } + + var offset int + + offset += proto.NestedStructureMarshal(hdrVersionField, buf[offset:], h.version) + offset += proto.NestedStructureMarshal(hdrContainerIDField, buf[offset:], h.cid) + offset += proto.NestedStructureMarshal(hdrOwnerIDField, buf[offset:], h.ownerID) + offset += proto.UInt64Marshal(hdrEpochField, buf[offset:], h.creatEpoch) + offset += proto.UInt64Marshal(hdrPayloadLengthField, buf[offset:], h.payloadLen) + offset += proto.NestedStructureMarshal(hdrPayloadHashField, buf[offset:], h.payloadHash) + offset += proto.EnumMarshal(hdrObjectTypeField, buf[offset:], int32(h.typ)) + offset += proto.NestedStructureMarshal(hdrHomomorphicHashField, buf[offset:], h.homoHash) + offset += proto.NestedStructureMarshal(hdrSessionTokenField, buf[offset:], h.sessionToken) + + for i := range h.attr { + offset += proto.NestedStructureMarshal(hdrAttributesField, buf[offset:], &h.attr[i]) + } + + proto.NestedStructureMarshal(hdrSplitField, buf[offset:], h.split) + proto.NestedStructureMarshal(hdrECField, buf[offset:], h.ec) + + return buf +} + +func (h *Header) StableSize() (size int) { + if h == nil { + return 0 + } + + size += proto.NestedStructureSize(hdrVersionField, h.version) + size += proto.NestedStructureSize(hdrContainerIDField, h.cid) + size += proto.NestedStructureSize(hdrOwnerIDField, h.ownerID) + size += proto.UInt64Size(hdrEpochField, h.creatEpoch) + size += proto.UInt64Size(hdrPayloadLengthField, h.payloadLen) + size += proto.NestedStructureSize(hdrPayloadHashField, h.payloadHash) + size += proto.EnumSize(hdrObjectTypeField, int32(h.typ)) + size += proto.NestedStructureSize(hdrHomomorphicHashField, h.homoHash) + size += proto.NestedStructureSize(hdrSessionTokenField, h.sessionToken) + for i := range h.attr { + size += proto.NestedStructureSize(hdrAttributesField, &h.attr[i]) + } + size += proto.NestedStructureSize(hdrSplitField, h.split) + size += proto.NestedStructureSize(hdrECField, h.ec) + + return size +} + +func (h *Header) Unmarshal(data []byte) error { + return message.Unmarshal(h, data, new(object.Header)) +} + +func (h *HeaderWithSignature) StableMarshal(buf []byte) []byte { + if h == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, h.StableSize()) + } + + var offset int + + offset += proto.NestedStructureMarshal(hdrWithSigHeaderField, buf[offset:], h.header) + proto.NestedStructureMarshal(hdrWithSigSignatureField, buf[offset:], h.signature) + + return buf +} + +func (h *HeaderWithSignature) StableSize() (size int) { + if h == nil { + return 0 + } + + size += proto.NestedStructureSize(hdrVersionField, h.header) + size += proto.NestedStructureSize(hdrContainerIDField, h.signature) + + return size +} + +func (h *HeaderWithSignature) Unmarshal(data []byte) error { + return message.Unmarshal(h, data, new(object.HeaderWithSignature)) +} + +func (o *Object) StableMarshal(buf []byte) []byte { + if o == nil { + return []byte{} + } + + if o.marshalData != nil { + if buf == nil { + return o.marshalData + } + copy(buf, o.marshalData) + return buf + } + + if buf == nil { + buf = make([]byte, o.StableSize()) + } + + var offset int + + offset += proto.NestedStructureMarshal(objIDField, buf[offset:], o.objectID) + offset += proto.NestedStructureMarshal(objSignatureField, buf[offset:], o.idSig) + offset += proto.NestedStructureMarshal(objHeaderField, buf[offset:], o.header) + proto.BytesMarshal(objPayloadField, buf[offset:], o.payload) + + return buf +} + +// SetMarshalData sets marshal data to reduce memory allocations. +// +// It is unsafe to modify/copy object data after setting marshal data. +func (o *Object) SetMarshalData(data []byte) { + if o == nil { + return + } + o.marshalData = data +} + +func (o *Object) StableSize() (size int) { + if o == nil { + return 0 + } + + size += proto.NestedStructureSize(objIDField, o.objectID) + size += proto.NestedStructureSize(objSignatureField, o.idSig) + size += proto.NestedStructureSize(objHeaderField, o.header) + size += proto.BytesSize(objPayloadField, o.payload) + + return size +} + +func (o *Object) Unmarshal(data []byte) error { + return message.Unmarshal(o, data, new(object.Object)) +} + +func (s *SplitInfo) StableMarshal(buf []byte) []byte { + if s == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, s.StableSize()) + } + + var offset int + + offset += proto.BytesMarshal(splitInfoSplitIDField, buf[offset:], s.splitID) + offset += proto.NestedStructureMarshal(splitInfoLastPartField, buf[offset:], s.lastPart) + proto.NestedStructureMarshal(splitInfoLinkField, buf[offset:], s.link) + + return buf +} + +func (s *SplitInfo) StableSize() (size int) { + if s == nil { + return 0 + } + + size += proto.BytesSize(splitInfoSplitIDField, s.splitID) + size += proto.NestedStructureSize(splitInfoLastPartField, s.lastPart) + size += proto.NestedStructureSize(splitInfoLinkField, s.link) + + return size +} + +func (s *SplitInfo) Unmarshal(data []byte) error { + return message.Unmarshal(s, data, new(object.SplitInfo)) +} + +func (e *ECInfo) StableMarshal(buf []byte) []byte { + if e == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, e.StableSize()) + } + + var offset int + + for i := range e.Chunks { + offset += proto.NestedStructureMarshal(ecInfoChunksField, buf[offset:], &e.Chunks[i]) + } + + return buf +} + +func (e *ECInfo) StableSize() (size int) { + if e == nil { + return 0 + } + + for i := range e.Chunks { + size += proto.NestedStructureSize(ecInfoChunksField, &e.Chunks[i]) + } + + return size +} + +func (e *ECInfo) Unmarshal(data []byte) error { + return message.Unmarshal(e, data, new(object.ECInfo)) +} + +func (c *ECChunk) StableMarshal(buf []byte) []byte { + if c == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, c.StableSize()) + } + + var offset int + + offset += proto.NestedStructureMarshal(ecChunkIDField, buf[offset:], &c.ID) + offset += proto.UInt32Marshal(ecChunkIndexField, buf[offset:], c.Index) + proto.UInt32Marshal(ecChunkTotalField, buf[offset:], c.Total) + + return buf +} + +func (c *ECChunk) StableSize() (size int) { + if c == nil { + return 0 + } + + size += proto.NestedStructureSize(ecChunkIDField, &c.ID) + size += proto.UInt32Size(ecChunkIndexField, c.Index) + size += proto.UInt32Size(ecChunkTotalField, c.Total) + + return size +} + +func (c *ECChunk) Unmarshal(data []byte) error { + return message.Unmarshal(c, data, new(object.ECInfo_Chunk)) +} + +func (r *GetRequestBody) StableMarshal(buf []byte) []byte { + if r == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, r.StableSize()) + } + + var offset int + + offset += proto.NestedStructureMarshal(getReqBodyAddressField, buf[offset:], r.addr) + proto.BoolMarshal(getReqBodyRawFlagField, buf[offset:], r.raw) + + return buf +} + +func (r *GetRequestBody) StableSize() (size int) { + if r == nil { + return 0 + } + + size += proto.NestedStructureSize(getReqBodyAddressField, r.addr) + size += proto.BoolSize(getReqBodyRawFlagField, r.raw) + + return size +} + +func (r *GetRequestBody) Unmarshal(data []byte) error { + return message.Unmarshal(r, data, new(object.GetRequest_Body)) +} + +func (r *GetObjectPartInit) StableMarshal(buf []byte) []byte { + if r == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, r.StableSize()) + } + + var offset int + + offset += proto.NestedStructureMarshal(getRespInitObjectIDField, buf[offset:], r.id) + offset += proto.NestedStructureMarshal(getRespInitSignatureField, buf[offset:], r.sig) + proto.NestedStructureMarshal(getRespInitHeaderField, buf[offset:], r.hdr) + + return buf +} + +func (r *GetObjectPartInit) StableSize() (size int) { + if r == nil { + return 0 + } + + size += proto.NestedStructureSize(getRespInitObjectIDField, r.id) + size += proto.NestedStructureSize(getRespInitSignatureField, r.sig) + size += proto.NestedStructureSize(getRespInitHeaderField, r.hdr) + + return size +} + +func (r *GetObjectPartInit) Unmarshal(data []byte) error { + return message.Unmarshal(r, data, new(object.GetResponse_Body_Init)) +} + +func (r *GetResponseBody) StableMarshal(buf []byte) []byte { + if r == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, r.StableSize()) + } + + switch v := r.objPart.(type) { + case nil: + case *GetObjectPartInit: + proto.NestedStructureMarshal(getRespBodyInitField, buf, v) + case *GetObjectPartChunk: + if v != nil { + proto.BytesMarshal(getRespBodyChunkField, buf, v.chunk) + } + case *SplitInfo: + proto.NestedStructureMarshal(getRespBodySplitInfoField, buf, v) + case *ECInfo: + proto.NestedStructureMarshal(getRespBodyECInfoField, buf, v) + default: + panic("unknown one of object get response body type") + } + + return buf +} + +func (r *GetResponseBody) StableSize() (size int) { + if r == nil { + return 0 + } + + switch v := r.objPart.(type) { + case nil: + case *GetObjectPartInit: + size += proto.NestedStructureSize(getRespBodyInitField, v) + case *GetObjectPartChunk: + if v != nil { + size += proto.BytesSize(getRespBodyChunkField, v.chunk) + } + case *SplitInfo: + size += proto.NestedStructureSize(getRespBodySplitInfoField, v) + case *ECInfo: + size += proto.NestedStructureSize(getRespBodyECInfoField, v) + default: + panic("unknown one of object get response body type") + } + + return +} + +func (r *GetResponseBody) Unmarshal(data []byte) error { + return message.Unmarshal(r, data, new(object.GetResponse_Body)) +} + +func (r *PutObjectPartInit) StableMarshal(buf []byte) []byte { + if r == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, r.StableSize()) + } + + var offset int + + offset += proto.NestedStructureMarshal(putReqInitObjectIDField, buf[offset:], r.id) + offset += proto.NestedStructureMarshal(putReqInitSignatureField, buf[offset:], r.sig) + offset += proto.NestedStructureMarshal(putReqInitHeaderField, buf[offset:], r.hdr) + proto.RepeatedUInt32Marshal(putReqInitCopiesNumField, buf[offset:], r.copyNum) + + return buf +} + +func (r *PutObjectPartInit) StableSize() (size int) { + if r == nil { + return 0 + } + + size += proto.NestedStructureSize(putReqInitObjectIDField, r.id) + size += proto.NestedStructureSize(putReqInitSignatureField, r.sig) + size += proto.NestedStructureSize(putReqInitHeaderField, r.hdr) + + arrSize, _ := proto.RepeatedUInt32Size(putReqInitCopiesNumField, r.copyNum) + size += arrSize + + return size +} + +func (r *PutObjectPartInit) Unmarshal(data []byte) error { + return message.Unmarshal(r, data, new(object.PutRequest_Body_Init)) +} + +func (r *PutRequestBody) StableMarshal(buf []byte) []byte { + if r == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, r.StableSize()) + } + + switch v := r.objPart.(type) { + case nil: + case *PutObjectPartInit: + proto.NestedStructureMarshal(putReqBodyInitField, buf, v) + case *PutObjectPartChunk: + if v != nil { + proto.BytesMarshal(putReqBodyChunkField, buf, v.chunk) + } + default: + panic("unknown one of object put request body type") + } + + return buf +} + +func (r *PutRequestBody) StableSize() (size int) { + if r == nil { + return 0 + } + + switch v := r.objPart.(type) { + case nil: + case *PutObjectPartInit: + size += proto.NestedStructureSize(putReqBodyInitField, v) + case *PutObjectPartChunk: + if v != nil { + size += proto.BytesSize(putReqBodyChunkField, v.chunk) + } + default: + panic("unknown one of object get response body type") + } + + return size +} + +func (r *PutRequestBody) Unmarshal(data []byte) error { + return message.Unmarshal(r, data, new(object.PutRequest_Body)) +} + +func (r *PutResponseBody) StableMarshal(buf []byte) []byte { + if r == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, r.StableSize()) + } + + proto.NestedStructureMarshal(putRespBodyObjectIDField, buf, r.id) + + return buf +} + +func (r *PutResponseBody) StableSize() (size int) { + if r == nil { + return 0 + } + + size += proto.NestedStructureSize(putRespBodyObjectIDField, r.id) + + return size +} + +func (r *PutResponseBody) Unmarshal(data []byte) error { + return message.Unmarshal(r, data, new(object.PutResponse_Body)) +} + +func (r *DeleteRequestBody) StableMarshal(buf []byte) []byte { + if r == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, r.StableSize()) + } + + proto.NestedStructureMarshal(deleteReqBodyAddressField, buf, r.addr) + + return buf +} + +func (r *DeleteRequestBody) StableSize() (size int) { + if r == nil { + return 0 + } + + size += proto.NestedStructureSize(deleteReqBodyAddressField, r.addr) + + return size +} + +func (r *DeleteRequestBody) Unmarshal(data []byte) error { + return message.Unmarshal(r, data, new(object.DeleteRequest_Body)) +} + +func (r *DeleteResponseBody) StableMarshal(buf []byte) []byte { + if r == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, r.StableSize()) + } + + proto.NestedStructureMarshal(deleteRespBodyTombstoneFNum, buf, r.tombstone) + + return buf +} + +func (r *DeleteResponseBody) StableSize() (size int) { + if r == nil { + return 0 + } + + size += proto.NestedStructureSize(deleteRespBodyTombstoneFNum, r.tombstone) + + return size +} + +func (r *DeleteResponseBody) Unmarshal(data []byte) error { + return message.Unmarshal(r, data, new(object.DeleteResponse_Body)) +} + +func (r *HeadRequestBody) StableMarshal(buf []byte) []byte { + if r == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, r.StableSize()) + } + + var offset int + + offset += proto.NestedStructureMarshal(headReqBodyAddressField, buf[offset:], r.addr) + offset += proto.BoolMarshal(headReqBodyMainFlagField, buf[offset:], r.mainOnly) + proto.BoolMarshal(headReqBodyRawFlagField, buf[offset:], r.raw) + + return buf +} + +func (r *HeadRequestBody) StableSize() (size int) { + if r == nil { + return 0 + } + + size += proto.NestedStructureSize(headReqBodyAddressField, r.addr) + size += proto.BoolSize(headReqBodyMainFlagField, r.mainOnly) + size += proto.BoolSize(headReqBodyRawFlagField, r.raw) + + return size +} + +func (r *HeadRequestBody) Unmarshal(data []byte) error { + return message.Unmarshal(r, data, new(object.HeadRequest_Body)) +} + +func (r *HeadResponseBody) StableMarshal(buf []byte) []byte { + if r == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, r.StableSize()) + } + + switch v := r.hdrPart.(type) { + case nil: + case *HeaderWithSignature: + if v != nil { + proto.NestedStructureMarshal(headRespBodyHeaderField, buf, v) + } + case *ShortHeader: + if v != nil { + proto.NestedStructureMarshal(headRespBodyShortHeaderField, buf, v) + } + case *SplitInfo: + if v != nil { + proto.NestedStructureMarshal(headRespBodySplitInfoField, buf, v) + } + case *ECInfo: + if v != nil { + proto.NestedStructureMarshal(headRespBodyECInfoField, buf, v) + } + default: + panic("unknown one of object put request body type") + } + + return buf +} + +func (r *HeadResponseBody) StableSize() (size int) { + if r == nil { + return 0 + } + + switch v := r.hdrPart.(type) { + case nil: + case *HeaderWithSignature: + if v != nil { + size += proto.NestedStructureSize(headRespBodyHeaderField, v) + } + case *ShortHeader: + if v != nil { + size += proto.NestedStructureSize(headRespBodyShortHeaderField, v) + } + case *SplitInfo: + if v != nil { + size += proto.NestedStructureSize(headRespBodySplitInfoField, v) + } + case *ECInfo: + if v != nil { + size += proto.NestedStructureSize(headRespBodyECInfoField, v) + } + default: + panic("unknown one of object put request body type") + } + + return +} + +func (r *HeadResponseBody) Unmarshal(data []byte) error { + return message.Unmarshal(r, data, new(object.HeadResponse_Body)) +} + +func (f *SearchFilter) StableMarshal(buf []byte) []byte { + if f == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, f.StableSize()) + } + + var offset int + + offset += proto.EnumMarshal(searchFilterMatchField, buf[offset:], int32(f.matchType)) + offset += proto.StringMarshal(searchFilterNameField, buf[offset:], f.key) + proto.StringMarshal(searchFilterValueField, buf[offset:], f.val) + + return buf +} + +func (f *SearchFilter) StableSize() (size int) { + if f == nil { + return 0 + } + + size += proto.EnumSize(searchFilterMatchField, int32(f.matchType)) + size += proto.StringSize(searchFilterNameField, f.key) + size += proto.StringSize(searchFilterValueField, f.val) + + return size +} + +func (f *SearchFilter) Unmarshal(data []byte) error { + return message.Unmarshal(f, data, new(object.SearchRequest_Body_Filter)) +} + +func (r *SearchRequestBody) StableMarshal(buf []byte) []byte { + if r == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, r.StableSize()) + } + + var offset int + + offset += proto.NestedStructureMarshal(searchReqBodyContainerIDField, buf[offset:], r.cid) + offset += proto.UInt32Marshal(searchReqBodyVersionField, buf[offset:], r.version) + + for i := range r.filters { + offset += proto.NestedStructureMarshal(searchReqBodyFiltersField, buf[offset:], &r.filters[i]) + } + + return buf +} + +func (r *SearchRequestBody) StableSize() (size int) { + if r == nil { + return 0 + } + + size += proto.NestedStructureSize(searchReqBodyContainerIDField, r.cid) + size += proto.UInt32Size(searchReqBodyVersionField, r.version) + + for i := range r.filters { + size += proto.NestedStructureSize(searchReqBodyFiltersField, &r.filters[i]) + } + + return size +} + +func (r *SearchRequestBody) Unmarshal(data []byte) error { + return message.Unmarshal(r, data, new(object.SearchRequest_Body)) +} + +func (r *SearchResponseBody) StableMarshal(buf []byte) []byte { + if r == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, r.StableSize()) + } + + var offset int + + refs.ObjectIDNestedListMarshal(searchRespBodyObjectIDsField, buf[offset:], r.idList) + + return buf +} + +func (r *SearchResponseBody) StableSize() (size int) { + if r == nil { + return 0 + } + + size += refs.ObjectIDNestedListSize(searchRespBodyObjectIDsField, r.idList) + + return size +} + +func (r *SearchResponseBody) Unmarshal(data []byte) error { + return message.Unmarshal(r, data, new(object.SearchResponse_Body)) +} + +func (r *Range) StableMarshal(buf []byte) []byte { + if r == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, r.StableSize()) + } + + var offset int + + offset += proto.UInt64Marshal(rangeOffsetField, buf[offset:], r.off) + proto.UInt64Marshal(rangeLengthField, buf[offset:], r.len) + + return buf +} + +func (r *Range) StableSize() (size int) { + if r == nil { + return 0 + } + + size += proto.UInt64Size(rangeOffsetField, r.off) + size += proto.UInt64Size(rangeLengthField, r.len) + + return size +} + +func (r *Range) Unmarshal(data []byte) error { + return message.Unmarshal(r, data, new(object.Range)) +} + +func (r *GetRangeRequestBody) StableMarshal(buf []byte) []byte { + if r == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, r.StableSize()) + } + + var offset int + + offset += proto.NestedStructureMarshal(getRangeReqBodyAddressField, buf[offset:], r.addr) + offset += proto.NestedStructureMarshal(getRangeReqBodyRangeField, buf[offset:], r.rng) + proto.BoolMarshal(getRangeReqBodyRawField, buf[offset:], r.raw) + + return buf +} + +func (r *GetRangeRequestBody) StableSize() (size int) { + if r == nil { + return 0 + } + + size += proto.NestedStructureSize(getRangeReqBodyAddressField, r.addr) + size += proto.NestedStructureSize(getRangeReqBodyRangeField, r.rng) + size += proto.BoolSize(getRangeReqBodyRawField, r.raw) + + return size +} + +func (r *GetRangeRequestBody) Unmarshal(data []byte) error { + return message.Unmarshal(r, data, new(object.GetRangeRequest_Body)) +} + +func (r *GetRangeResponseBody) StableMarshal(buf []byte) []byte { + if r == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, r.StableSize()) + } + + switch v := r.rngPart.(type) { + case nil: + case *GetRangePartChunk: + if v != nil { + proto.BytesMarshal(getRangeRespChunkField, buf, v.chunk) + } + case *SplitInfo: + if v != nil { + proto.NestedStructureMarshal(getRangeRespSplitInfoField, buf, v) + } + case *ECInfo: + if v != nil { + proto.NestedStructureMarshal(getRangeRespECInfoField, buf, v) + } + default: + panic("unknown one of object get range request body type") + } + + return buf +} + +func (r *GetRangeResponseBody) StableSize() (size int) { + if r == nil { + return 0 + } + + switch v := r.rngPart.(type) { + case nil: + case *GetRangePartChunk: + if v != nil { + size += proto.BytesSize(getRangeRespChunkField, v.chunk) + } + case *SplitInfo: + if v != nil { + size = proto.NestedStructureSize(getRangeRespSplitInfoField, v) + } + case *ECInfo: + if v != nil { + size = proto.NestedStructureSize(getRangeRespECInfoField, v) + } + default: + panic("unknown one of object get range request body type") + } + + return +} + +func (r *GetRangeResponseBody) Unmarshal(data []byte) error { + return message.Unmarshal(r, data, new(object.GetRangeResponse_Body)) +} + +func (r *GetRangeHashRequestBody) StableMarshal(buf []byte) []byte { + if r == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, r.StableSize()) + } + + var offset int + + offset += proto.NestedStructureMarshal(getRangeHashReqBodyAddressField, buf[offset:], r.addr) + + for i := range r.rngs { + offset += proto.NestedStructureMarshal(getRangeHashReqBodyRangesField, buf[offset:], &r.rngs[i]) + } + + offset += proto.BytesMarshal(getRangeHashReqBodySaltField, buf[offset:], r.salt) + proto.EnumMarshal(getRangeHashReqBodyTypeField, buf[offset:], int32(r.typ)) + + return buf +} + +func (r *GetRangeHashRequestBody) StableSize() (size int) { + if r == nil { + return 0 + } + + size += proto.NestedStructureSize(getRangeHashReqBodyAddressField, r.addr) + + for i := range r.rngs { + size += proto.NestedStructureSize(getRangeHashReqBodyRangesField, &r.rngs[i]) + } + + size += proto.BytesSize(getRangeHashReqBodySaltField, r.salt) + size += proto.EnumSize(getRangeHashReqBodyTypeField, int32(r.typ)) + + return size +} + +func (r *GetRangeHashRequestBody) Unmarshal(data []byte) error { + return message.Unmarshal(r, data, new(object.GetRangeHashRequest_Body)) +} + +func (r *GetRangeHashResponseBody) StableMarshal(buf []byte) []byte { + if r == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, r.StableSize()) + } + + var offset int + + offset += proto.EnumMarshal(getRangeHashRespBodyTypeField, buf, int32(r.typ)) + proto.RepeatedBytesMarshal(getRangeHashRespBodyHashListField, buf[offset:], r.hashList) + + return buf +} + +func (r *GetRangeHashResponseBody) StableSize() (size int) { + if r == nil { + return 0 + } + + size += proto.EnumSize(getRangeHashRespBodyTypeField, int32(r.typ)) + size += proto.RepeatedBytesSize(getRangeHashRespBodyHashListField, r.hashList) + + return size +} + +func (r *GetRangeHashResponseBody) Unmarshal(data []byte) error { + return message.Unmarshal(r, data, new(object.GetRangeHashResponse_Body)) +} + +func (r *PutSingleRequestBody) StableMarshal(buf []byte) []byte { + if r == nil { + return []byte{} + } + + if r.marshalData != nil { + if buf == nil { + return r.marshalData + } + copy(buf, r.marshalData) + return buf + } + + if buf == nil { + buf = make([]byte, r.StableSize()) + } + + var offset int + offset += proto.NestedStructureMarshal(putSingleReqObjectField, buf[offset:], r.object) + proto.RepeatedUInt32Marshal(putSingleReqCopiesNumberField, buf[offset:], r.copyNum) + + return buf +} + +// SetMarshalData sets marshal data to reduce memory allocations. +// +// It is unsafe to modify/copy request data after setting marshal data. +func (r *PutSingleRequestBody) SetMarshalData(data []byte) { + if r == nil { + return + } + + r.marshalData = data + + proto.NestedStructureSetMarshalData(putSingleReqObjectField, r.marshalData, r.object) +} + +func (r *PutSingleRequestBody) StableSize() int { + if r == nil { + return 0 + } + + var size int + size += proto.NestedStructureSize(putSingleReqObjectField, r.object) + arrSize, _ := proto.RepeatedUInt32Size(putSingleReqCopiesNumberField, r.copyNum) + size += arrSize + + return size +} + +func (r *PutSingleRequestBody) Unmarshal(data []byte) error { + return message.Unmarshal(r, data, new(object.PutSingleRequest_Body)) +} + +func (r *PutSingleResponseBody) StableMarshal(buf []byte) []byte { + if r == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, r.StableSize()) + } + + return buf +} + +func (r *PutSingleResponseBody) StableSize() int { + return 0 +} + +func (r *PutSingleResponseBody) Unmarshal(data []byte) error { + return message.Unmarshal(r, data, new(object.PutSingleResponse_Body)) +} + +func (r *PatchRequestBodyPatch) StableMarshal(buf []byte) []byte { + if r == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, r.StableSize()) + } + + var offset int + offset += proto.NestedStructureMarshal(patchRequestBodyPatchRangeField, buf[offset:], r.GetRange()) + proto.BytesMarshal(patchRequestBodyPatchChunkField, buf[offset:], r.GetChunk()) + + return buf +} + +func (r *PatchRequestBodyPatch) StableSize() int { + if r == nil { + return 0 + } + + var size int + size += proto.NestedStructureSize(patchRequestBodyPatchRangeField, r.GetRange()) + size += proto.BytesSize(patchRequestBodyPatchChunkField, r.GetChunk()) + + return size +} + +func (r *PatchRequestBodyPatch) Unmarshal(data []byte) error { + return message.Unmarshal(r, data, new(object.PatchRequest_Body_Patch)) +} + +func (r *PatchRequestBody) StableMarshal(buf []byte) []byte { + if r == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, r.StableSize()) + } + + var offset int + offset += proto.NestedStructureMarshal(patchRequestBodyAddrField, buf[offset:], r.address) + for i := range r.newAttributes { + offset += proto.NestedStructureMarshal(patchRequestBodyNewAttrsField, buf[offset:], &r.newAttributes[i]) + } + offset += proto.BoolMarshal(patchRequestBodyReplaceAttrField, buf[offset:], r.replaceAttributes) + proto.NestedStructureMarshal(patchRequestBodyPatchField, buf[offset:], r.patch) + + return buf +} + +func (r *PatchRequestBody) StableSize() int { + if r == nil { + return 0 + } + + var size int + size += proto.NestedStructureSize(patchRequestBodyAddrField, r.address) + for i := range r.newAttributes { + size += proto.NestedStructureSize(patchRequestBodyNewAttrsField, &r.newAttributes[i]) + } + size += proto.BoolSize(patchRequestBodyReplaceAttrField, r.replaceAttributes) + size += proto.NestedStructureSize(patchRequestBodyPatchField, r.patch) + + return size +} + +func (r *PatchRequestBody) Unmarshal(data []byte) error { + return message.Unmarshal(r, data, new(object.PatchRequest_Body)) +} + +func (r *PatchResponseBody) StableSize() int { + if r == nil { + return 0 + } + + var size int + size += proto.NestedStructureSize(patchResponseBodyObjectIDField, r.ObjectID) + + return size +} + +func (r *PatchResponseBody) StableMarshal(buf []byte) []byte { + if r == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, r.StableSize()) + } + + var offset int + proto.NestedStructureMarshal(patchResponseBodyObjectIDField, buf[offset:], r.ObjectID) + + return buf +} + +func (r *PatchResponseBody) Unmarshal(data []byte) error { + return message.Unmarshal(r, data, new(object.PatchResponse_Body)) +} diff --git a/api/object/message_test.go b/api/object/message_test.go new file mode 100644 index 0000000..21568f8 --- /dev/null +++ b/api/object/message_test.go @@ -0,0 +1,65 @@ +package object_test + +import ( + "testing" + + objecttest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object/test" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/message" + messagetest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/message/test" +) + +func TestMessageConvert(t *testing.T) { + messagetest.TestRPCMessage(t, + func(empty bool) message.Message { return objecttest.GenerateShortHeader(empty) }, + func(empty bool) message.Message { return objecttest.GenerateAttribute(empty) }, + func(empty bool) message.Message { return objecttest.GenerateSplitHeader(empty) }, + func(empty bool) message.Message { return objecttest.GenerateHeaderWithSplitHeader(empty) }, + func(empty bool) message.Message { return objecttest.GenerateHeaderWithECHeader(empty) }, + func(empty bool) message.Message { return objecttest.GenerateECHeader(empty) }, + func(empty bool) message.Message { return objecttest.GenerateObject(empty) }, + func(empty bool) message.Message { return objecttest.GenerateSplitInfo(empty) }, + func(empty bool) message.Message { return objecttest.GenerateECInfo(empty) }, + func(empty bool) message.Message { return objecttest.GenerateGetRequestBody(empty) }, + func(empty bool) message.Message { return objecttest.GenerateGetRequest(empty) }, + func(empty bool) message.Message { return objecttest.GenerateGetObjectPartInit(empty) }, + func(empty bool) message.Message { return objecttest.GenerateGetObjectPartChunk(empty) }, + func(empty bool) message.Message { return objecttest.GenerateGetResponseBody(empty) }, + func(empty bool) message.Message { return objecttest.GenerateGetResponse(empty) }, + func(empty bool) message.Message { return objecttest.GeneratePutObjectPartInit(empty) }, + func(empty bool) message.Message { return objecttest.GeneratePutObjectPartChunk(empty) }, + func(empty bool) message.Message { return objecttest.GeneratePutRequestBody(empty) }, + func(empty bool) message.Message { return objecttest.GeneratePutRequest(empty) }, + func(empty bool) message.Message { return objecttest.GeneratePutResponseBody(empty) }, + func(empty bool) message.Message { return objecttest.GeneratePutResponse(empty) }, + func(empty bool) message.Message { return objecttest.GenerateDeleteRequestBody(empty) }, + func(empty bool) message.Message { return objecttest.GenerateDeleteRequest(empty) }, + func(empty bool) message.Message { return objecttest.GenerateDeleteResponseBody(empty) }, + func(empty bool) message.Message { return objecttest.GenerateDeleteResponse(empty) }, + func(empty bool) message.Message { return objecttest.GenerateHeadRequestBody(empty) }, + func(empty bool) message.Message { return objecttest.GenerateHeadRequest(empty) }, + func(empty bool) message.Message { return objecttest.GenerateHeadResponseBody(empty) }, + func(empty bool) message.Message { return objecttest.GenerateHeadResponse(empty) }, + func(empty bool) message.Message { return objecttest.GenerateSearchFilter(empty) }, + func(empty bool) message.Message { return objecttest.GenerateSearchRequestBody(empty) }, + func(empty bool) message.Message { return objecttest.GenerateSearchRequest(empty) }, + func(empty bool) message.Message { return objecttest.GenerateSearchResponseBody(empty) }, + func(empty bool) message.Message { return objecttest.GenerateSearchResponse(empty) }, + func(empty bool) message.Message { return objecttest.GenerateRange(empty) }, + func(empty bool) message.Message { return objecttest.GenerateGetRangeRequestBody(empty) }, + func(empty bool) message.Message { return objecttest.GenerateGetRangeRequest(empty) }, + func(empty bool) message.Message { return objecttest.GenerateGetRangeResponseBody(empty) }, + func(empty bool) message.Message { return objecttest.GenerateGetRangeResponse(empty) }, + func(empty bool) message.Message { return objecttest.GenerateGetRangeHashRequestBody(empty) }, + func(empty bool) message.Message { return objecttest.GenerateGetRangeHashRequest(empty) }, + func(empty bool) message.Message { return objecttest.GenerateGetRangeHashResponseBody(empty) }, + func(empty bool) message.Message { return objecttest.GenerateGetRangeHashResponse(empty) }, + func(empty bool) message.Message { return objecttest.GenerateLock(empty) }, + func(empty bool) message.Message { return objecttest.GeneratePutSingleRequest(empty) }, + func(empty bool) message.Message { return objecttest.GeneratePutSingleResponse(empty) }, + func(empty bool) message.Message { return objecttest.GeneratePatchRequestBodyPatch(empty) }, + func(empty bool) message.Message { return objecttest.GeneratePatchRequestBody(empty) }, + func(empty bool) message.Message { return objecttest.GeneratePatchRequest(empty) }, + func(empty bool) message.Message { return objecttest.GeneratePatchResponseBody(empty) }, + func(empty bool) message.Message { return objecttest.GeneratePatchResponse(empty) }, + ) +} diff --git a/api/object/status.go b/api/object/status.go new file mode 100644 index 0000000..32fda2b --- /dev/null +++ b/api/object/status.go @@ -0,0 +1,91 @@ +package object + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/status" + statusgrpc "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/status/grpc" +) + +// LocalizeFailStatus checks if passed global status.Code is related to object failure and: +// +// then localizes the code and returns true, +// else leaves the code unchanged and returns false. +// +// Arg must not be nil. +func LocalizeFailStatus(c *status.Code) bool { + return status.LocalizeIfInSection(c, uint32(statusgrpc.Section_SECTION_OBJECT)) +} + +// GlobalizeFail globalizes local code of object failure. +// +// Arg must not be nil. +func GlobalizeFail(c *status.Code) { + c.GlobalizeSection(uint32(statusgrpc.Section_SECTION_OBJECT)) +} + +const ( + // StatusAccessDenied is a local status.Code value for + // ACCESS_DENIED object failure. + StatusAccessDenied status.Code = iota + // StatusNotFound is a local status.Code value for + // OBJECT_NOT_FOUND object failure. + StatusNotFound + // StatusLocked is a local status.Code value for + // LOCKED object failure. + StatusLocked + // StatusLockNonRegularObject is a local status.Code value for + // LOCK_NON_REGULAR_OBJECT object failure. + StatusLockNonRegularObject + // StatusAlreadyRemoved is a local status.Code value for + // OBJECT_ALREADY_REMOVED object failure. + StatusAlreadyRemoved + // StatusOutOfRange is a local status.Code value for + // OUT_OF_RANGE object failure. + StatusOutOfRange +) + +const ( + // detailAccessDeniedDesc is a StatusAccessDenied detail ID for + // human-readable description. + detailAccessDeniedDesc = iota +) + +// WriteAccessDeniedDesc writes human-readable description of StatusAccessDenied +// into status.Status as a detail. The status must not be nil. +// +// Existing details are expected to be ID-unique, otherwise undefined behavior. +func WriteAccessDeniedDesc(st *status.Status, desc string) { + var found bool + + st.IterateDetails(func(d *status.Detail) bool { + if d.ID() == detailAccessDeniedDesc { + found = true + d.SetValue([]byte(desc)) + } + + return found + }) + + if !found { + var d status.Detail + + d.SetID(detailAccessDeniedDesc) + d.SetValue([]byte(desc)) + + st.AppendDetails(d) + } +} + +// ReadAccessDeniedDesc looks up for status detail with human-readable description +// of StatusAccessDenied. Returns empty string if detail is missing. +func ReadAccessDeniedDesc(st status.Status) (desc string) { + st.IterateDetails(func(d *status.Detail) bool { + if d.ID() == detailAccessDeniedDesc { + desc = string(d.Value()) + return true + } + + return false + }) + + return +} diff --git a/api/object/status_test.go b/api/object/status_test.go new file mode 100644 index 0000000..465f5c8 --- /dev/null +++ b/api/object/status_test.go @@ -0,0 +1,35 @@ +package object_test + +import ( + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/status" + statustest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/status/test" + "github.com/stretchr/testify/require" +) + +func TestStatusCodes(t *testing.T) { + statustest.TestCodes(t, object.LocalizeFailStatus, object.GlobalizeFail, + object.StatusAccessDenied, 2048, + object.StatusNotFound, 2049, + object.StatusLocked, 2050, + object.StatusLockNonRegularObject, 2051, + object.StatusAlreadyRemoved, 2052, + object.StatusOutOfRange, 2053, + ) +} + +func TestAccessDeniedDesc(t *testing.T) { + var st status.Status + + require.Empty(t, object.ReadAccessDeniedDesc(st)) + + const desc = "some description" + + object.WriteAccessDeniedDesc(&st, desc) + require.Equal(t, desc, object.ReadAccessDeniedDesc(st)) + + object.WriteAccessDeniedDesc(&st, desc+"1") + require.Equal(t, desc+"1", object.ReadAccessDeniedDesc(st)) +} diff --git a/api/object/string.go b/api/object/string.go new file mode 100644 index 0000000..9910df7 --- /dev/null +++ b/api/object/string.go @@ -0,0 +1,55 @@ +package object + +import ( + object "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object/grpc" +) + +// String returns string representation of Type. +func (t Type) String() string { + return TypeToGRPCField(t).String() +} + +// FromString parses Type from a string representation. +// It is a reverse action to String(). +// +// Returns true if s was parsed successfully. +func (t *Type) FromString(s string) bool { + var g object.ObjectType + + ok := g.FromString(s) + + if ok { + *t = TypeFromGRPCField(g) + } + + return ok +} + +// TypeFromString converts string to Type. +// +// Deprecated: use FromString method. +func TypeFromString(s string) (t Type) { + t.FromString(s) + return +} + +// String returns string representation of MatchType. +func (t MatchType) String() string { + return MatchTypeToGRPCField(t).String() +} + +// FromString parses MatchType from a string representation. +// It is a reverse action to String(). +// +// Returns true if s was parsed successfully. +func (t *MatchType) FromString(s string) bool { + var g object.MatchType + + ok := g.FromString(s) + + if ok { + *t = MatchTypeFromGRPCField(g) + } + + return ok +} diff --git a/api/object/test/generate.go b/api/object/test/generate.go new file mode 100644 index 0000000..37345f9 --- /dev/null +++ b/api/object/test/generate.go @@ -0,0 +1,766 @@ +package objecttest + +import ( + crand "crypto/rand" + "math/rand" + "time" + + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" + refstest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs/test" + sessiontest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session/test" +) + +func GenerateShortHeader(empty bool) *object.ShortHeader { + m := new(object.ShortHeader) + + if !empty { + m.SetObjectType(13) + m.SetCreationEpoch(100) + m.SetPayloadLength(12321) + m.SetOwnerID(refstest.GenerateOwnerID(false)) + } + + m.SetVersion(refstest.GenerateVersion(empty)) + m.SetHomomorphicHash(refstest.GenerateChecksum(empty)) + m.SetPayloadHash(refstest.GenerateChecksum(empty)) + + return m +} + +func GenerateAttribute(empty bool) *object.Attribute { + m := new(object.Attribute) + + if !empty { + m.SetKey("object key") + m.SetValue("object value") + } + + return m +} + +func GenerateAttributes(empty bool) []object.Attribute { + var res []object.Attribute + + if !empty { + res = append(res, + *GenerateAttribute(false), + *GenerateAttribute(false), + ) + } + + return res +} + +func GenerateSplitHeader(empty bool) *object.SplitHeader { + return generateSplitHeader(empty, true) +} + +func generateSplitHeader(empty, withPar bool) *object.SplitHeader { + m := new(object.SplitHeader) + + if !empty { + id := make([]byte, 16) + _, _ = crand.Read(id) + + m.SetSplitID(id) + m.SetParent(refstest.GenerateObjectID(false)) + m.SetPrevious(refstest.GenerateObjectID(false)) + m.SetChildren(refstest.GenerateObjectIDs(false)) + } + + m.SetParentSignature(refstest.GenerateSignature(empty)) + + if withPar { + m.SetParentHeader(GenerateHeaderWithSplitHeader(empty)) + } + + return m +} + +func GenerateHeaderWithSplitHeader(empty bool) *object.Header { + m := generateHeader(empty) + m.SetSplit(generateSplitHeader(empty, false)) + return m +} + +func GenerateHeaderWithECHeader(empty bool) *object.Header { + m := generateHeader(empty) + m.SetEC(GenerateECHeader(empty)) + return m +} + +func GenerateECHeader(empty bool) *object.ECHeader { + ech := new(object.ECHeader) + + if !empty { + ech.Parent = refstest.GenerateObjectID(empty) + + ech.ParentSplitID = make([]byte, 16) + _, _ = crand.Read(ech.ParentSplitID) + + ech.ParentSplitParentID = refstest.GenerateObjectID(empty) + ech.ParentAttributes = GenerateAttributes(empty) + ech.Index = 0 + ech.Total = 2 + ech.Header = []byte("chunk of ec-encoded parent header") + ech.HeaderLength = uint32(2 * len(ech.Header)) + } + + return ech +} + +func generateHeader(empty bool) *object.Header { + m := new(object.Header) + + if !empty { + m.SetPayloadLength(777) + m.SetCreationEpoch(432) + m.SetObjectType(111) + m.SetOwnerID(refstest.GenerateOwnerID(false)) + m.SetContainerID(refstest.GenerateContainerID(false)) + m.SetAttributes(GenerateAttributes(false)) + } + + m.SetVersion(refstest.GenerateVersion(empty)) + m.SetPayloadHash(refstest.GenerateChecksum(empty)) + m.SetHomomorphicHash(refstest.GenerateChecksum(empty)) + m.SetSessionToken(sessiontest.GenerateSessionToken(empty)) + + return m +} + +func GenerateHeaderWithSignature(empty bool) *object.HeaderWithSignature { + m := new(object.HeaderWithSignature) + + m.SetSignature(refstest.GenerateSignature(empty)) + m.SetHeader(GenerateHeaderWithSplitHeader(empty)) + + return m +} + +func GenerateObject(empty bool) *object.Object { + m := new(object.Object) + + if !empty { + m.SetPayload([]byte{7, 8, 9}) + m.SetObjectID(refstest.GenerateObjectID(false)) + } + + m.SetSignature(refstest.GenerateSignature(empty)) + m.SetHeader(GenerateHeaderWithSplitHeader(empty)) + + return m +} + +func GenerateSplitInfo(empty bool) *object.SplitInfo { + m := new(object.SplitInfo) + + if !empty { + id := make([]byte, 16) + _, _ = crand.Read(id) + + m.SetSplitID(id) + m.SetLastPart(refstest.GenerateObjectID(false)) + m.SetLink(refstest.GenerateObjectID(false)) + } + + return m +} + +func GenerateECInfo(empty bool) *object.ECInfo { + m := new(object.ECInfo) + + if !empty { + m.Chunks = make([]object.ECChunk, 2) + for i := range m.Chunks { + m.Chunks[i] = *GenerateECChunk(false) + } + } + + return m +} + +func GenerateECChunk(empty bool) *object.ECChunk { + m := new(object.ECChunk) + + if !empty { + m.ID = *refstest.GenerateObjectID(false) + m.Index = 4 + m.Total = 7 + } + + return m +} + +func GenerateGetRequestBody(empty bool) *object.GetRequestBody { + m := new(object.GetRequestBody) + + if !empty { + m.SetRaw(true) + m.SetAddress(refstest.GenerateAddress(false)) + } + + return m +} + +func GenerateGetRequest(empty bool) *object.GetRequest { + m := new(object.GetRequest) + + if !empty { + m.SetBody(GenerateGetRequestBody(false)) + } + + m.SetMetaHeader(sessiontest.GenerateRequestMetaHeader(empty)) + m.SetVerificationHeader(sessiontest.GenerateRequestVerificationHeader(empty)) + + return m +} + +func GenerateGetObjectPartInit(empty bool) *object.GetObjectPartInit { + m := new(object.GetObjectPartInit) + + if !empty { + m.SetObjectID(refstest.GenerateObjectID(false)) + } + + m.SetSignature(refstest.GenerateSignature(empty)) + m.SetHeader(GenerateHeaderWithSplitHeader(empty)) + + return m +} + +func GenerateGetObjectPartChunk(empty bool) *object.GetObjectPartChunk { + m := new(object.GetObjectPartChunk) + + if !empty { + m.SetChunk([]byte("get chunk")) + } + + return m +} + +func GenerateGetResponseBody(empty bool) *object.GetResponseBody { + m := new(object.GetResponseBody) + + if !empty { + switch randomInt(3) { + case 0: + m.SetObjectPart(GenerateGetObjectPartInit(false)) + case 1: + m.SetObjectPart(GenerateGetObjectPartChunk(false)) + case 2: + m.SetObjectPart(GenerateSplitInfo(false)) + } + } + + return m +} + +func GenerateGetResponse(empty bool) *object.GetResponse { + m := new(object.GetResponse) + + if !empty { + m.SetBody(GenerateGetResponseBody(false)) + } + + m.SetMetaHeader(sessiontest.GenerateResponseMetaHeader(empty)) + m.SetVerificationHeader(sessiontest.GenerateResponseVerificationHeader(empty)) + + return m +} + +func GeneratePutObjectPartInit(empty bool) *object.PutObjectPartInit { + m := new(object.PutObjectPartInit) + + if !empty { + m.SetCopiesNumber([]uint32{234}) + m.SetObjectID(refstest.GenerateObjectID(false)) + } + + m.SetSignature(refstest.GenerateSignature(empty)) + m.SetHeader(GenerateHeaderWithSplitHeader(empty)) + + return m +} + +func GeneratePutObjectPartChunk(empty bool) *object.PutObjectPartChunk { + m := new(object.PutObjectPartChunk) + + if !empty { + m.SetChunk([]byte("put chunk")) + } + + return m +} + +func GeneratePutRequestBody(empty bool) *object.PutRequestBody { + m := new(object.PutRequestBody) + + if !empty { + switch randomInt(2) { + case 0: + m.SetObjectPart(GeneratePutObjectPartInit(false)) + case 1: + m.SetObjectPart(GeneratePutObjectPartChunk(false)) + } + } + + return m +} + +func GeneratePutRequest(empty bool) *object.PutRequest { + m := new(object.PutRequest) + + if !empty { + m.SetBody(GeneratePutRequestBody(false)) + } + + m.SetMetaHeader(sessiontest.GenerateRequestMetaHeader(empty)) + m.SetVerificationHeader(sessiontest.GenerateRequestVerificationHeader(empty)) + + return m +} + +func GeneratePutResponseBody(empty bool) *object.PutResponseBody { + m := new(object.PutResponseBody) + + if !empty { + m.SetObjectID(refstest.GenerateObjectID(false)) + } + + return m +} + +func GeneratePutResponse(empty bool) *object.PutResponse { + m := new(object.PutResponse) + + if !empty { + m.SetBody(GeneratePutResponseBody(false)) + } + + m.SetMetaHeader(sessiontest.GenerateResponseMetaHeader(empty)) + m.SetVerificationHeader(sessiontest.GenerateResponseVerificationHeader(empty)) + + return m +} + +func GenerateDeleteRequestBody(empty bool) *object.DeleteRequestBody { + m := new(object.DeleteRequestBody) + + if !empty { + m.SetAddress(refstest.GenerateAddress(false)) + } + + return m +} + +func GenerateDeleteRequest(empty bool) *object.DeleteRequest { + m := new(object.DeleteRequest) + + if !empty { + m.SetBody(GenerateDeleteRequestBody(false)) + } + + m.SetMetaHeader(sessiontest.GenerateRequestMetaHeader(empty)) + m.SetVerificationHeader(sessiontest.GenerateRequestVerificationHeader(empty)) + + return m +} + +func GenerateDeleteResponseBody(empty bool) *object.DeleteResponseBody { + m := new(object.DeleteResponseBody) + + if !empty { + m.SetTombstone(refstest.GenerateAddress(false)) + } + + return m +} + +func GenerateDeleteResponse(empty bool) *object.DeleteResponse { + m := new(object.DeleteResponse) + + if !empty { + m.SetBody(GenerateDeleteResponseBody(false)) + } + + m.SetMetaHeader(sessiontest.GenerateResponseMetaHeader(empty)) + m.SetVerificationHeader(sessiontest.GenerateResponseVerificationHeader(empty)) + + return m +} + +func GenerateHeadRequestBody(empty bool) *object.HeadRequestBody { + m := new(object.HeadRequestBody) + + if !empty { + m.SetRaw(true) + m.SetMainOnly(true) + m.SetAddress(refstest.GenerateAddress(false)) + } + + return m +} + +func GenerateHeadRequest(empty bool) *object.HeadRequest { + m := new(object.HeadRequest) + + if !empty { + m.SetBody(GenerateHeadRequestBody(false)) + } + + m.SetMetaHeader(sessiontest.GenerateRequestMetaHeader(empty)) + m.SetVerificationHeader(sessiontest.GenerateRequestVerificationHeader(empty)) + + return m +} + +func GenerateHeadResponseBody(empty bool) *object.HeadResponseBody { + m := new(object.HeadResponseBody) + + if !empty { + switch randomInt(3) { + case 0: + m.SetHeaderPart(GenerateHeaderWithSignature(false)) + case 1: + m.SetHeaderPart(GenerateShortHeader(false)) + case 2: + m.SetHeaderPart(GenerateSplitInfo(false)) + } + } + + return m +} + +func GenerateHeadResponse(empty bool) *object.HeadResponse { + m := new(object.HeadResponse) + + if !empty { + m.SetBody(GenerateHeadResponseBody(false)) + } + + m.SetMetaHeader(sessiontest.GenerateResponseMetaHeader(empty)) + m.SetVerificationHeader(sessiontest.GenerateResponseVerificationHeader(empty)) + + return m +} + +func GenerateSearchFilter(empty bool) *object.SearchFilter { + m := new(object.SearchFilter) + + if !empty { + m.SetKey("search filter key") + m.SetValue("search filter val") + m.SetMatchType(987) + } + + return m +} + +func GenerateSearchFilters(empty bool) []object.SearchFilter { + var res []object.SearchFilter + + if !empty { + res = append(res, + *GenerateSearchFilter(false), + *GenerateSearchFilter(false), + ) + } + + return res +} + +func GenerateSearchRequestBody(empty bool) *object.SearchRequestBody { + m := new(object.SearchRequestBody) + + if !empty { + m.SetVersion(555) + m.SetContainerID(refstest.GenerateContainerID(false)) + m.SetFilters(GenerateSearchFilters(false)) + } + + return m +} + +func GenerateSearchRequest(empty bool) *object.SearchRequest { + m := new(object.SearchRequest) + + if !empty { + m.SetBody(GenerateSearchRequestBody(false)) + } + + m.SetMetaHeader(sessiontest.GenerateRequestMetaHeader(empty)) + m.SetVerificationHeader(sessiontest.GenerateRequestVerificationHeader(empty)) + + return m +} + +func GenerateSearchResponseBody(empty bool) *object.SearchResponseBody { + m := new(object.SearchResponseBody) + + if !empty { + m.SetIDList(refstest.GenerateObjectIDs(false)) + } + + return m +} + +func GenerateSearchResponse(empty bool) *object.SearchResponse { + m := new(object.SearchResponse) + + if !empty { + m.SetBody(GenerateSearchResponseBody(false)) + } + + m.SetMetaHeader(sessiontest.GenerateResponseMetaHeader(empty)) + m.SetVerificationHeader(sessiontest.GenerateResponseVerificationHeader(empty)) + + return m +} + +func GenerateRange(empty bool) *object.Range { + m := new(object.Range) + + if !empty { + m.SetLength(11) + m.SetOffset(22) + } + + return m +} + +func GenerateRanges(empty bool) []object.Range { + var res []object.Range + + if !empty { + res = append(res, + *GenerateRange(false), + *GenerateRange(false), + ) + } + + return res +} + +func GenerateGetRangeRequestBody(empty bool) *object.GetRangeRequestBody { + m := new(object.GetRangeRequestBody) + + if !empty { + m.SetRaw(true) + m.SetAddress(refstest.GenerateAddress(empty)) + m.SetRange(GenerateRange(empty)) + } + + return m +} + +func GenerateGetRangeRequest(empty bool) *object.GetRangeRequest { + m := new(object.GetRangeRequest) + + if !empty { + m.SetBody(GenerateGetRangeRequestBody(false)) + } + + m.SetMetaHeader(sessiontest.GenerateRequestMetaHeader(empty)) + m.SetVerificationHeader(sessiontest.GenerateRequestVerificationHeader(empty)) + + return m +} + +func GenerateGetRangePartChunk(empty bool) *object.GetRangePartChunk { + m := new(object.GetRangePartChunk) + + if !empty { + m.SetChunk([]byte("get range chunk")) + } + + return m +} + +func GenerateGetRangeResponseBody(empty bool) *object.GetRangeResponseBody { + m := new(object.GetRangeResponseBody) + + if !empty { + switch randomInt(2) { + case 0: + m.SetRangePart(GenerateGetRangePartChunk(false)) + case 1: + m.SetRangePart(GenerateSplitInfo(false)) + } + } + + return m +} + +func GenerateGetRangeResponse(empty bool) *object.GetRangeResponse { + m := new(object.GetRangeResponse) + + if !empty { + m.SetBody(GenerateGetRangeResponseBody(false)) + } + + m.SetMetaHeader(sessiontest.GenerateResponseMetaHeader(empty)) + m.SetVerificationHeader(sessiontest.GenerateResponseVerificationHeader(empty)) + + return m +} + +func GenerateGetRangeHashRequestBody(empty bool) *object.GetRangeHashRequestBody { + m := new(object.GetRangeHashRequestBody) + + if !empty { + m.SetSalt([]byte("range hash salt")) + m.SetType(455) + m.SetAddress(refstest.GenerateAddress(false)) + m.SetRanges(GenerateRanges(false)) + } + + return m +} + +func GenerateGetRangeHashRequest(empty bool) *object.GetRangeHashRequest { + m := new(object.GetRangeHashRequest) + + if !empty { + m.SetBody(GenerateGetRangeHashRequestBody(false)) + } + + m.SetMetaHeader(sessiontest.GenerateRequestMetaHeader(empty)) + m.SetVerificationHeader(sessiontest.GenerateRequestVerificationHeader(empty)) + + return m +} + +func GenerateGetRangeHashResponseBody(empty bool) *object.GetRangeHashResponseBody { + m := new(object.GetRangeHashResponseBody) + + if !empty { + m.SetType(678) + m.SetHashList([][]byte{ + refstest.GenerateChecksum(false).GetSum(), + refstest.GenerateChecksum(false).GetSum(), + }) + } + + return m +} + +func GenerateGetRangeHashResponse(empty bool) *object.GetRangeHashResponse { + m := new(object.GetRangeHashResponse) + + if !empty { + m.SetBody(GenerateGetRangeHashResponseBody(false)) + } + + m.SetMetaHeader(sessiontest.GenerateResponseMetaHeader(empty)) + m.SetVerificationHeader(sessiontest.GenerateResponseVerificationHeader(empty)) + + return m +} + +func GenerateLock(empty bool) *object.Lock { + m := new(object.Lock) + + if !empty { + m.SetMembers([]refs.ObjectID{ + *refstest.GenerateObjectID(false), + *refstest.GenerateObjectID(false), + }) + } + + return m +} + +func GeneratePutSingleRequest(empty bool) *object.PutSingleRequest { + m := new(object.PutSingleRequest) + + if !empty { + m.SetBody(GeneratePutSingleRequestBody(false)) + } + + m.SetMetaHeader(sessiontest.GenerateRequestMetaHeader(empty)) + m.SetVerificationHeader(sessiontest.GenerateRequestVerificationHeader(empty)) + + return m +} + +func GeneratePutSingleRequestBody(empty bool) *object.PutSingleRequestBody { + b := new(object.PutSingleRequestBody) + if !empty { + b.SetObject(GenerateObject(empty)) + b.SetCopiesNumber([]uint32{12345}) + } + return b +} + +func GeneratePutSingleResponse(empty bool) *object.PutSingleResponse { + m := new(object.PutSingleResponse) + if !empty { + m.SetBody(new(object.PutSingleResponseBody)) + } + m.SetMetaHeader(sessiontest.GenerateResponseMetaHeader(empty)) + m.SetVerificationHeader(sessiontest.GenerateResponseVerificationHeader(empty)) + return m +} + +func GeneratePatchRequestBodyPatch(empty bool) *object.PatchRequestBodyPatch { + m := new(object.PatchRequestBodyPatch) + + if !empty { + m.Range = GenerateRange(false) + m.Chunk = []byte("GeneratePatchRequestBodyPatch") + } + + return m +} + +func GeneratePatchRequestBody(empty bool) *object.PatchRequestBody { + m := new(object.PatchRequestBody) + + if !empty { + m.SetAddress(refstest.GenerateAddress(empty)) + m.SetNewAttributes(GenerateAttributes(empty)) + m.SetReplaceAttributes(false) + m.SetPatch(GeneratePatchRequestBodyPatch(empty)) + } + + return m +} + +func GeneratePatchRequest(empty bool) *object.PatchRequest { + m := new(object.PatchRequest) + + if !empty { + m.SetBody(GeneratePatchRequestBody(empty)) + } + + m.SetMetaHeader(sessiontest.GenerateRequestMetaHeader(empty)) + m.SetVerificationHeader(sessiontest.GenerateRequestVerificationHeader(empty)) + + return m +} + +func GeneratePatchResponseBody(empty bool) *object.PatchResponseBody { + m := new(object.PatchResponseBody) + + if !empty { + m.ObjectID = refstest.GenerateObjectID(empty) + } + + return m +} + +func GeneratePatchResponse(empty bool) *object.PatchResponse { + m := new(object.PatchResponse) + + if !empty { + m.Body = GeneratePatchResponseBody(empty) + } + + return m +} + +func randomInt(n int) int { + return rand.New(rand.NewSource(time.Now().UnixNano())).Intn(n) +} diff --git a/api/object/types.go b/api/object/types.go new file mode 100644 index 0000000..537fb02 --- /dev/null +++ b/api/object/types.go @@ -0,0 +1,1650 @@ +package object + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" +) + +type Type uint32 + +type MatchType uint32 + +type ShortHeader struct { + version *refs.Version + + creatEpoch uint64 + + ownerID *refs.OwnerID + + typ Type + + payloadLen uint64 + + payloadHash, homoHash *refs.Checksum +} + +type Attribute struct { + key, val string +} + +type SplitHeader struct { + par, prev *refs.ObjectID + + parSig *refs.Signature + + parHdr *Header + + children []refs.ObjectID + + splitID []byte +} + +type ECHeader struct { + Parent *refs.ObjectID + ParentSplitID []byte + ParentSplitParentID *refs.ObjectID + ParentAttributes []Attribute + Index uint32 + Total uint32 + Header []byte + HeaderLength uint32 +} + +type Header struct { + version *refs.Version + + cid *refs.ContainerID + + ownerID *refs.OwnerID + + creatEpoch uint64 + + payloadLen uint64 + + payloadHash, homoHash *refs.Checksum + + typ Type + + sessionToken *session.Token + + attr []Attribute + + split *SplitHeader + + ec *ECHeader +} + +type HeaderWithSignature struct { + header *Header + + signature *refs.Signature +} + +type Object struct { + objectID *refs.ObjectID + + idSig *refs.Signature + + header *Header + + payload []byte + + // marshalData holds marshaled data, must not be marshaled by StableMarshal + marshalData []byte +} + +type SplitInfo struct { + splitID []byte + + lastPart *refs.ObjectID + + link *refs.ObjectID +} + +type ECChunk struct { + ID refs.ObjectID + Index uint32 + Total uint32 +} + +type ECInfo struct { + Chunks []ECChunk +} + +type GetRequestBody struct { + addr *refs.Address + + raw bool +} + +type GetObjectPart interface { + getObjectPart() +} + +type GetObjectPartInit struct { + id *refs.ObjectID + + sig *refs.Signature + + hdr *Header +} + +type GetObjectPartChunk struct { + chunk []byte +} + +type GetRequest struct { + body *GetRequestBody + + session.RequestHeaders +} + +type GetResponseBody struct { + objPart GetObjectPart +} + +type PutObjectPart interface { + putObjectPart() +} + +type PutObjectPartInit struct { + id *refs.ObjectID + + sig *refs.Signature + + hdr *Header + + copyNum []uint32 +} + +type PutObjectPartChunk struct { + chunk []byte +} + +type GetResponse struct { + body *GetResponseBody + + session.ResponseHeaders +} + +type PutRequestBody struct { + objPart PutObjectPart +} + +type PutRequest struct { + body *PutRequestBody + + session.RequestHeaders +} + +type PutResponseBody struct { + id *refs.ObjectID +} + +type PutResponse struct { + body *PutResponseBody + + session.ResponseHeaders +} + +type DeleteRequestBody struct { + addr *refs.Address +} + +type DeleteRequest struct { + body *DeleteRequestBody + + session.RequestHeaders +} + +type DeleteResponseBody struct { + tombstone *refs.Address +} + +type DeleteResponse struct { + body *DeleteResponseBody + + session.ResponseHeaders +} + +type HeadRequestBody struct { + addr *refs.Address + + mainOnly, raw bool +} + +type GetHeaderPart interface { + getHeaderPart() +} + +type HeadRequest struct { + body *HeadRequestBody + + session.RequestHeaders +} + +type HeadResponseBody struct { + hdrPart GetHeaderPart +} + +type HeadResponse struct { + body *HeadResponseBody + + session.ResponseHeaders +} + +type SearchFilter struct { + matchType MatchType + + key, val string +} + +type SearchRequestBody struct { + cid *refs.ContainerID + + version uint32 + + filters []SearchFilter +} + +type SearchRequest struct { + body *SearchRequestBody + + session.RequestHeaders +} + +type SearchResponseBody struct { + idList []refs.ObjectID +} + +type SearchResponse struct { + body *SearchResponseBody + + session.ResponseHeaders +} + +type Range struct { + off, len uint64 +} + +type GetRangeRequestBody struct { + addr *refs.Address + + rng *Range + + raw bool +} + +type GetRangeRequest struct { + body *GetRangeRequestBody + + session.RequestHeaders +} + +type GetRangePart interface { + getRangePart() +} + +type GetRangePartChunk struct { + chunk []byte +} + +type GetRangeResponseBody struct { + rngPart GetRangePart +} + +type GetRangeResponse struct { + body *GetRangeResponseBody + + session.ResponseHeaders +} + +type GetRangeHashRequestBody struct { + addr *refs.Address + + rngs []Range + + salt []byte + + typ refs.ChecksumType +} + +type GetRangeHashRequest struct { + body *GetRangeHashRequestBody + + session.RequestHeaders +} + +type GetRangeHashResponseBody struct { + typ refs.ChecksumType + + hashList [][]byte +} + +type GetRangeHashResponse struct { + body *GetRangeHashResponseBody + + session.ResponseHeaders +} + +type PutSingleRequestBody struct { + object *Object + copyNum []uint32 + + // marshalData holds marshaled data, must not be marshaled by StableMarshal + marshalData []byte +} + +type PutSingleRequest struct { + body *PutSingleRequestBody + + session.RequestHeaders +} + +type PutSingleResponseBody struct{} + +type PutSingleResponse struct { + body *PutSingleResponseBody + + session.ResponseHeaders +} + +type PatchRequestBodyPatch struct { + Range *Range + + Chunk []byte +} + +type PatchRequestBody struct { + address *refs.Address + + newAttributes []Attribute + + replaceAttributes bool + + patch *PatchRequestBodyPatch +} + +type PatchRequest struct { + body *PatchRequestBody + + session.RequestHeaders +} + +type PatchResponseBody struct { + ObjectID *refs.ObjectID +} + +type PatchResponse struct { + Body *PatchResponseBody + + session.ResponseHeaders +} + +const ( + TypeRegular Type = iota + TypeTombstone + _ + TypeLock +) + +const ( + MatchUnknown MatchType = iota + MatchStringEqual + MatchStringNotEqual + MatchNotPresent + MatchCommonPrefix +) + +func (h *ShortHeader) GetVersion() *refs.Version { + if h != nil { + return h.version + } + + return nil +} + +func (h *ShortHeader) SetVersion(v *refs.Version) { + h.version = v +} + +func (h *ShortHeader) GetCreationEpoch() uint64 { + if h != nil { + return h.creatEpoch + } + + return 0 +} + +func (h *ShortHeader) SetCreationEpoch(v uint64) { + h.creatEpoch = v +} + +func (h *ShortHeader) GetOwnerID() *refs.OwnerID { + if h != nil { + return h.ownerID + } + + return nil +} + +func (h *ShortHeader) SetOwnerID(v *refs.OwnerID) { + h.ownerID = v +} + +func (h *ShortHeader) GetObjectType() Type { + if h != nil { + return h.typ + } + + return TypeRegular +} + +func (h *ShortHeader) SetObjectType(v Type) { + h.typ = v +} + +func (h *ShortHeader) GetPayloadLength() uint64 { + if h != nil { + return h.payloadLen + } + + return 0 +} + +func (h *ShortHeader) SetPayloadLength(v uint64) { + h.payloadLen = v +} + +func (h *ShortHeader) GetPayloadHash() *refs.Checksum { + if h != nil { + return h.payloadHash + } + + return nil +} + +func (h *ShortHeader) SetPayloadHash(v *refs.Checksum) { + h.payloadHash = v +} + +func (h *ShortHeader) GetHomomorphicHash() *refs.Checksum { + if h != nil { + return h.homoHash + } + + return nil +} + +func (h *ShortHeader) SetHomomorphicHash(v *refs.Checksum) { + h.homoHash = v +} + +func (h *ShortHeader) getHeaderPart() {} + +func (a *Attribute) GetKey() string { + if a != nil { + return a.key + } + + return "" +} + +func (a *Attribute) SetKey(v string) { + a.key = v +} + +func (a *Attribute) GetValue() string { + if a != nil { + return a.val + } + + return "" +} + +func (a *Attribute) SetValue(v string) { + a.val = v +} + +func (h *SplitHeader) GetParent() *refs.ObjectID { + if h != nil { + return h.par + } + + return nil +} + +func (h *SplitHeader) SetParent(v *refs.ObjectID) { + h.par = v +} + +func (h *SplitHeader) GetPrevious() *refs.ObjectID { + if h != nil { + return h.prev + } + + return nil +} + +func (h *SplitHeader) SetPrevious(v *refs.ObjectID) { + h.prev = v +} + +func (h *SplitHeader) GetParentSignature() *refs.Signature { + if h != nil { + return h.parSig + } + + return nil +} + +func (h *SplitHeader) SetParentSignature(v *refs.Signature) { + h.parSig = v +} + +func (h *SplitHeader) GetParentHeader() *Header { + if h != nil { + return h.parHdr + } + + return nil +} + +func (h *SplitHeader) SetParentHeader(v *Header) { + h.parHdr = v +} + +func (h *SplitHeader) GetChildren() []refs.ObjectID { + if h != nil { + return h.children + } + + return nil +} + +func (h *SplitHeader) SetChildren(v []refs.ObjectID) { + h.children = v +} + +func (h *SplitHeader) GetSplitID() []byte { + if h != nil { + return h.splitID + } + + return nil +} + +func (h *SplitHeader) SetSplitID(v []byte) { + h.splitID = v +} + +func (h *Header) GetVersion() *refs.Version { + if h != nil { + return h.version + } + + return nil +} + +func (h *Header) SetVersion(v *refs.Version) { + h.version = v +} + +func (h *Header) GetContainerID() *refs.ContainerID { + if h != nil { + return h.cid + } + + return nil +} + +func (h *Header) SetContainerID(v *refs.ContainerID) { + h.cid = v +} + +func (h *Header) GetOwnerID() *refs.OwnerID { + if h != nil { + return h.ownerID + } + + return nil +} + +func (h *Header) SetOwnerID(v *refs.OwnerID) { + h.ownerID = v +} + +func (h *Header) GetCreationEpoch() uint64 { + if h != nil { + return h.creatEpoch + } + + return 0 +} + +func (h *Header) SetCreationEpoch(v uint64) { + h.creatEpoch = v +} + +func (h *Header) GetPayloadLength() uint64 { + if h != nil { + return h.payloadLen + } + + return 0 +} + +func (h *Header) SetPayloadLength(v uint64) { + h.payloadLen = v +} + +func (h *Header) GetPayloadHash() *refs.Checksum { + if h != nil { + return h.payloadHash + } + + return nil +} + +func (h *Header) SetPayloadHash(v *refs.Checksum) { + h.payloadHash = v +} + +func (h *Header) GetObjectType() Type { + if h != nil { + return h.typ + } + + return TypeRegular +} + +func (h *Header) SetObjectType(v Type) { + h.typ = v +} + +func (h *Header) GetHomomorphicHash() *refs.Checksum { + if h != nil { + return h.homoHash + } + + return nil +} + +func (h *Header) SetHomomorphicHash(v *refs.Checksum) { + h.homoHash = v +} + +func (h *Header) GetSessionToken() *session.Token { + if h != nil { + return h.sessionToken + } + + return nil +} + +func (h *Header) SetSessionToken(v *session.Token) { + h.sessionToken = v +} + +func (h *Header) GetAttributes() []Attribute { + if h != nil { + return h.attr + } + + return nil +} + +func (h *Header) SetAttributes(v []Attribute) { + h.attr = v +} + +func (h *Header) GetSplit() *SplitHeader { + if h != nil { + return h.split + } + + return nil +} + +func (h *Header) SetSplit(v *SplitHeader) { + h.split = v +} + +func (h *Header) GetEC() *ECHeader { + if h != nil { + return h.ec + } + return nil +} + +func (h *Header) SetEC(v *ECHeader) { + h.ec = v +} + +func (h *HeaderWithSignature) GetHeader() *Header { + if h != nil { + return h.header + } + + return nil +} + +func (h *HeaderWithSignature) SetHeader(v *Header) { + h.header = v +} + +func (h *HeaderWithSignature) GetSignature() *refs.Signature { + if h != nil { + return h.signature + } + + return nil +} + +func (h *HeaderWithSignature) SetSignature(v *refs.Signature) { + h.signature = v +} + +func (h *HeaderWithSignature) getHeaderPart() {} + +func (o *Object) GetObjectID() *refs.ObjectID { + if o != nil { + return o.objectID + } + + return nil +} + +func (o *Object) SetObjectID(v *refs.ObjectID) { + o.objectID = v +} + +func (o *Object) GetSignature() *refs.Signature { + if o != nil { + return o.idSig + } + + return nil +} + +func (o *Object) SetSignature(v *refs.Signature) { + o.idSig = v +} + +func (o *Object) GetHeader() *Header { + if o != nil { + return o.header + } + + return nil +} + +func (o *Object) SetHeader(v *Header) { + o.header = v +} + +func (o *Object) GetPayload() []byte { + if o != nil { + return o.payload + } + + return nil +} + +func (o *Object) SetPayload(v []byte) { + o.payload = v +} + +func (s *SplitInfo) GetSplitID() []byte { + if s != nil { + return s.splitID + } + + return nil +} + +func (s *SplitInfo) SetSplitID(v []byte) { + s.splitID = v +} + +func (s *SplitInfo) GetLastPart() *refs.ObjectID { + if s != nil { + return s.lastPart + } + + return nil +} + +func (s *SplitInfo) SetLastPart(v *refs.ObjectID) { + s.lastPart = v +} + +func (s *SplitInfo) GetLink() *refs.ObjectID { + if s != nil { + return s.link + } + + return nil +} + +func (s *SplitInfo) SetLink(v *refs.ObjectID) { + s.link = v +} + +func (s *SplitInfo) getObjectPart() {} + +func (s *SplitInfo) getHeaderPart() {} + +func (s *SplitInfo) getRangePart() {} + +func (r *GetRequestBody) GetAddress() *refs.Address { + if r != nil { + return r.addr + } + + return nil +} + +func (r *GetRequestBody) SetAddress(v *refs.Address) { + r.addr = v +} + +func (r *GetRequestBody) GetRaw() bool { + if r != nil { + return r.raw + } + + return false +} + +func (r *GetRequestBody) SetRaw(v bool) { + r.raw = v +} + +func (r *GetRequest) GetBody() *GetRequestBody { + if r != nil { + return r.body + } + + return nil +} + +func (r *GetRequest) SetBody(v *GetRequestBody) { + r.body = v +} + +func (r *GetObjectPartInit) GetObjectID() *refs.ObjectID { + if r != nil { + return r.id + } + + return nil +} + +func (r *GetObjectPartInit) SetObjectID(v *refs.ObjectID) { + r.id = v +} + +func (r *GetObjectPartInit) GetSignature() *refs.Signature { + if r != nil { + return r.sig + } + + return nil +} + +func (r *GetObjectPartInit) SetSignature(v *refs.Signature) { + r.sig = v +} + +func (r *GetObjectPartInit) GetHeader() *Header { + if r != nil { + return r.hdr + } + + return nil +} + +func (r *GetObjectPartInit) SetHeader(v *Header) { + r.hdr = v +} + +func (r *GetObjectPartInit) getObjectPart() {} + +func (r *GetObjectPartChunk) GetChunk() []byte { + if r != nil { + return r.chunk + } + + return nil +} + +func (r *GetObjectPartChunk) SetChunk(v []byte) { + r.chunk = v +} + +func (r *GetObjectPartChunk) getObjectPart() {} + +func (r *GetResponseBody) GetObjectPart() GetObjectPart { + if r != nil { + return r.objPart + } + + return nil +} + +func (r *GetResponseBody) SetObjectPart(v GetObjectPart) { + r.objPart = v +} + +func (r *GetResponse) GetBody() *GetResponseBody { + if r != nil { + return r.body + } + + return nil +} + +func (r *GetResponse) SetBody(v *GetResponseBody) { + r.body = v +} + +func (r *PutObjectPartInit) GetObjectID() *refs.ObjectID { + if r != nil { + return r.id + } + + return nil +} + +func (r *PutObjectPartInit) SetObjectID(v *refs.ObjectID) { + r.id = v +} + +func (r *PutObjectPartInit) GetSignature() *refs.Signature { + if r != nil { + return r.sig + } + + return nil +} + +func (r *PutObjectPartInit) SetSignature(v *refs.Signature) { + r.sig = v +} + +func (r *PutObjectPartInit) GetHeader() *Header { + if r != nil { + return r.hdr + } + + return nil +} + +func (r *PutObjectPartInit) SetHeader(v *Header) { + r.hdr = v +} + +func (r *PutObjectPartInit) GetCopiesNumber() []uint32 { + if r != nil { + return r.copyNum + } + + return nil +} + +func (r *PutObjectPartInit) SetCopiesNumber(v []uint32) { + r.copyNum = v +} + +func (r *PutObjectPartInit) putObjectPart() {} + +func (r *PutObjectPartChunk) GetChunk() []byte { + if r != nil { + return r.chunk + } + + return nil +} + +func (r *PutObjectPartChunk) SetChunk(v []byte) { + r.chunk = v +} + +func (r *PutObjectPartChunk) putObjectPart() {} + +func (r *PutRequestBody) GetObjectPart() PutObjectPart { + if r != nil { + return r.objPart + } + + return nil +} + +func (r *PutRequestBody) SetObjectPart(v PutObjectPart) { + r.objPart = v +} + +func (r *PutRequest) GetBody() *PutRequestBody { + if r != nil { + return r.body + } + + return nil +} + +func (r *PutRequest) SetBody(v *PutRequestBody) { + r.body = v +} + +func (r *PutResponseBody) GetObjectID() *refs.ObjectID { + if r != nil { + return r.id + } + + return nil +} + +func (r *PutResponseBody) SetObjectID(v *refs.ObjectID) { + r.id = v +} + +func (r *PutResponse) GetBody() *PutResponseBody { + if r != nil { + return r.body + } + + return nil +} + +func (r *PutResponse) SetBody(v *PutResponseBody) { + r.body = v +} + +func (r *DeleteRequestBody) GetAddress() *refs.Address { + if r != nil { + return r.addr + } + + return nil +} + +func (r *DeleteRequestBody) SetAddress(v *refs.Address) { + r.addr = v +} + +func (r *DeleteRequest) GetBody() *DeleteRequestBody { + if r != nil { + return r.body + } + + return nil +} + +func (r *DeleteRequest) SetBody(v *DeleteRequestBody) { + r.body = v +} + +// GetTombstone returns tombstone address. +func (r *DeleteResponseBody) GetTombstone() *refs.Address { + if r != nil { + return r.tombstone + } + + return nil +} + +// SetTombstone sets tombstone address. +func (r *DeleteResponseBody) SetTombstone(v *refs.Address) { + r.tombstone = v +} + +func (r *DeleteResponse) GetBody() *DeleteResponseBody { + if r != nil { + return r.body + } + + return nil +} + +func (r *DeleteResponse) SetBody(v *DeleteResponseBody) { + r.body = v +} + +func (r *HeadRequestBody) GetAddress() *refs.Address { + if r != nil { + return r.addr + } + + return nil +} + +func (r *HeadRequestBody) SetAddress(v *refs.Address) { + r.addr = v +} + +func (r *HeadRequestBody) GetMainOnly() bool { + if r != nil { + return r.mainOnly + } + + return false +} + +func (r *HeadRequestBody) SetMainOnly(v bool) { + r.mainOnly = v +} + +func (r *HeadRequestBody) GetRaw() bool { + if r != nil { + return r.raw + } + + return false +} + +func (r *HeadRequestBody) SetRaw(v bool) { + r.raw = v +} + +func (r *HeadRequest) GetBody() *HeadRequestBody { + if r != nil { + return r.body + } + + return nil +} + +func (r *HeadRequest) SetBody(v *HeadRequestBody) { + r.body = v +} + +func (r *HeadResponseBody) GetHeaderPart() GetHeaderPart { + if r != nil { + return r.hdrPart + } + + return nil +} + +func (r *HeadResponseBody) SetHeaderPart(v GetHeaderPart) { + r.hdrPart = v +} + +func (r *HeadResponse) GetBody() *HeadResponseBody { + if r != nil { + return r.body + } + + return nil +} + +func (r *HeadResponse) SetBody(v *HeadResponseBody) { + r.body = v +} + +func (f *SearchFilter) GetMatchType() MatchType { + if f != nil { + return f.matchType + } + + return MatchUnknown +} + +func (f *SearchFilter) SetMatchType(v MatchType) { + f.matchType = v +} + +func (f *SearchFilter) GetKey() string { + if f != nil { + return f.key + } + + return "" +} + +func (f *SearchFilter) SetKey(v string) { + f.key = v +} + +func (f *SearchFilter) GetValue() string { + if f != nil { + return f.val + } + + return "" +} + +func (f *SearchFilter) SetValue(v string) { + f.val = v +} + +func (r *SearchRequestBody) GetContainerID() *refs.ContainerID { + if r != nil { + return r.cid + } + + return nil +} + +func (r *SearchRequestBody) SetContainerID(v *refs.ContainerID) { + r.cid = v +} + +func (r *SearchRequestBody) GetVersion() uint32 { + if r != nil { + return r.version + } + + return 0 +} + +func (r *SearchRequestBody) SetVersion(v uint32) { + r.version = v +} + +func (r *SearchRequestBody) GetFilters() []SearchFilter { + if r != nil { + return r.filters + } + + return nil +} + +func (r *SearchRequestBody) SetFilters(v []SearchFilter) { + r.filters = v +} + +func (r *SearchRequest) GetBody() *SearchRequestBody { + if r != nil { + return r.body + } + + return nil +} + +func (r *SearchRequest) SetBody(v *SearchRequestBody) { + r.body = v +} + +func (r *SearchResponseBody) GetIDList() []refs.ObjectID { + if r != nil { + return r.idList + } + + return nil +} + +func (r *SearchResponseBody) SetIDList(v []refs.ObjectID) { + r.idList = v +} + +func (r *SearchResponse) GetBody() *SearchResponseBody { + if r != nil { + return r.body + } + + return nil +} + +func (r *SearchResponse) SetBody(v *SearchResponseBody) { + r.body = v +} + +func (r *Range) GetOffset() uint64 { + if r != nil { + return r.off + } + + return 0 +} + +func (r *Range) SetOffset(v uint64) { + r.off = v +} + +func (r *Range) GetLength() uint64 { + if r != nil { + return r.len + } + + return 0 +} + +func (r *Range) SetLength(v uint64) { + r.len = v +} + +func (r *GetRangeRequestBody) GetAddress() *refs.Address { + if r != nil { + return r.addr + } + + return nil +} + +func (r *GetRangeRequestBody) SetAddress(v *refs.Address) { + r.addr = v +} + +func (r *GetRangeRequestBody) GetRange() *Range { + if r != nil { + return r.rng + } + + return nil +} + +func (r *GetRangeRequestBody) SetRange(v *Range) { + r.rng = v +} + +func (r *GetRangeRequestBody) GetRaw() bool { + if r != nil { + return r.raw + } + + return false +} + +func (r *GetRangeRequestBody) SetRaw(v bool) { + r.raw = v +} + +func (r *GetRangeRequest) GetBody() *GetRangeRequestBody { + if r != nil { + return r.body + } + + return nil +} + +func (r *GetRangeRequest) SetBody(v *GetRangeRequestBody) { + r.body = v +} + +func (r *GetRangePartChunk) GetChunk() []byte { + if r != nil { + return r.chunk + } + + return nil +} + +func (r *GetRangePartChunk) SetChunk(v []byte) { + r.chunk = v +} + +func (r *GetRangePartChunk) getRangePart() {} + +func (r *GetRangeResponseBody) GetRangePart() GetRangePart { + if r != nil { + return r.rngPart + } + + return nil +} + +func (r *GetRangeResponseBody) SetRangePart(v GetRangePart) { + r.rngPart = v +} + +func (r *GetRangeResponse) GetBody() *GetRangeResponseBody { + if r != nil { + return r.body + } + + return nil +} + +func (r *GetRangeResponse) SetBody(v *GetRangeResponseBody) { + r.body = v +} + +func (r *GetRangeHashRequestBody) GetAddress() *refs.Address { + if r != nil { + return r.addr + } + + return nil +} + +func (r *GetRangeHashRequestBody) SetAddress(v *refs.Address) { + r.addr = v +} + +func (r *GetRangeHashRequestBody) GetRanges() []Range { + if r != nil { + return r.rngs + } + + return nil +} + +func (r *GetRangeHashRequestBody) SetRanges(v []Range) { + r.rngs = v +} + +func (r *GetRangeHashRequestBody) GetSalt() []byte { + if r != nil { + return r.salt + } + + return nil +} + +func (r *GetRangeHashRequestBody) SetSalt(v []byte) { + r.salt = v +} + +func (r *GetRangeHashRequestBody) GetType() refs.ChecksumType { + if r != nil { + return r.typ + } + + return refs.UnknownChecksum +} + +func (r *GetRangeHashRequestBody) SetType(v refs.ChecksumType) { + r.typ = v +} + +func (r *GetRangeHashRequest) GetBody() *GetRangeHashRequestBody { + if r != nil { + return r.body + } + + return nil +} + +func (r *GetRangeHashRequest) SetBody(v *GetRangeHashRequestBody) { + r.body = v +} + +func (r *GetRangeHashResponseBody) GetType() refs.ChecksumType { + if r != nil { + return r.typ + } + + return refs.UnknownChecksum +} + +func (r *GetRangeHashResponseBody) SetType(v refs.ChecksumType) { + r.typ = v +} + +func (r *GetRangeHashResponseBody) GetHashList() [][]byte { + if r != nil { + return r.hashList + } + + return nil +} + +func (r *GetRangeHashResponseBody) SetHashList(v [][]byte) { + r.hashList = v +} + +func (r *GetRangeHashResponse) GetBody() *GetRangeHashResponseBody { + if r != nil { + return r.body + } + + return nil +} + +func (r *GetRangeHashResponse) SetBody(v *GetRangeHashResponseBody) { + r.body = v +} + +func (r *PutSingleRequest) GetBody() *PutSingleRequestBody { + if r != nil { + return r.body + } + + return nil +} + +func (r *PutSingleRequest) SetBody(v *PutSingleRequestBody) { + r.body = v +} + +func (b *PutSingleRequestBody) GetObject() *Object { + if b == nil { + return nil + } + return b.object +} + +func (b *PutSingleRequestBody) SetObject(o *Object) { + b.object = o +} + +func (b *PutSingleRequestBody) GetCopiesNumber() []uint32 { + if b == nil { + return nil + } + return b.copyNum +} + +func (b *PutSingleRequestBody) SetCopiesNumber(v []uint32) { + b.copyNum = v +} + +func (r *PutSingleResponse) GetBody() *PutSingleResponseBody { + if r != nil { + return r.body + } + + return nil +} + +func (r *PutSingleResponse) SetBody(v *PutSingleResponseBody) { + r.body = v +} + +func (r *PatchRequest) GetBody() *PatchRequestBody { + if r != nil { + return r.body + } + + return nil +} + +func (r *PatchRequest) SetBody(v *PatchRequestBody) { + r.body = v +} + +func (r *PatchRequestBody) GetAddress() *refs.Address { + if r != nil { + return r.address + } + + return nil +} + +func (r *PatchRequestBody) SetAddress(addr *refs.Address) { + r.address = addr +} + +func (r *PatchRequestBody) GetNewAttributes() []Attribute { + if r != nil { + return r.newAttributes + } + + return nil +} + +func (r *PatchRequestBody) SetNewAttributes(attrs []Attribute) { + r.newAttributes = attrs +} + +func (r *PatchRequestBody) GetReplaceAttributes() bool { + if r != nil { + return r.replaceAttributes + } + + return false +} + +func (r *PatchRequestBody) SetReplaceAttributes(replace bool) { + r.replaceAttributes = replace +} + +func (r *PatchRequestBody) GetPatch() *PatchRequestBodyPatch { + if r != nil { + return r.patch + } + + return nil +} + +func (r *PatchRequestBody) SetPatch(patch *PatchRequestBodyPatch) { + r.patch = patch +} + +func (r *PatchResponse) GetBody() *PatchResponseBody { + if r != nil { + return r.Body + } + + return nil +} + +func (r *PatchResponse) SetBody(v *PatchResponseBody) { + r.Body = v +} + +func (r *PatchResponseBody) GetObjectID() *refs.ObjectID { + if r != nil { + return r.ObjectID + } + + return nil +} + +func (r *PatchResponseBody) SetObjectID(objectID *refs.ObjectID) { + r.ObjectID = objectID +} + +func (r *PatchRequestBodyPatch) GetChunk() []byte { + if r != nil { + return r.Chunk + } + + return nil +} + +func (r *PatchRequestBodyPatch) GetRange() *Range { + if r != nil { + return r.Range + } + + return nil +} + +func (s *ECInfo) getObjectPart() {} + +func (s *ECInfo) getHeaderPart() {} + +func (s *ECInfo) getRangePart() {} diff --git a/api/refs/bench_test.go b/api/refs/bench_test.go new file mode 100644 index 0000000..40784c6 --- /dev/null +++ b/api/refs/bench_test.go @@ -0,0 +1,53 @@ +package refs + +import ( + "math/rand" + "strconv" + "testing" +) + +func BenchmarkObjectIDSlice(b *testing.B) { + for _, size := range []int{0, 1, 50} { + b.Run(strconv.Itoa(size)+" elements", func(b *testing.B) { + benchmarkObjectIDSlice(b, size) + }) + } +} + +func benchmarkObjectIDSlice(b *testing.B, size int) { + ids := make([]ObjectID, size) + for i := range ids { + ids[i].val = make([]byte, 32) + rand.Read(ids[i].val) + } + raw := ObjectIDListToGRPCMessage(ids) + + b.Run("to grpc message", func(b *testing.B) { + b.ReportAllocs() + for range b.N { + raw := ObjectIDListToGRPCMessage(ids) + if len(raw) != len(ids) { + b.FailNow() + } + } + }) + b.Run("from grpc message", func(b *testing.B) { + b.ReportAllocs() + for range b.N { + ids, err := ObjectIDListFromGRPCMessage(raw) + if err != nil || len(raw) != len(ids) { + b.FailNow() + } + } + }) + b.Run("marshal", func(b *testing.B) { + b.ReportAllocs() + for range b.N { + buf := make([]byte, ObjectIDNestedListSize(1, ids)) + n := ObjectIDNestedListMarshal(1, buf, ids) + if n != len(buf) { + b.FailNow() + } + } + }) +} diff --git a/api/refs/convert.go b/api/refs/convert.go new file mode 100644 index 0000000..8e72c37 --- /dev/null +++ b/api/refs/convert.go @@ -0,0 +1,264 @@ +package refs + +import ( + refs "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/message" +) + +func (o *OwnerID) ToGRPCMessage() grpc.Message { + var m *refs.OwnerID + + if o != nil { + m = new(refs.OwnerID) + + m.SetValue(o.val) + } + + return m +} + +func (o *OwnerID) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*refs.OwnerID) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + o.val = v.GetValue() + + return nil +} + +func (c *ContainerID) ToGRPCMessage() grpc.Message { + var m *refs.ContainerID + + if c != nil { + m = new(refs.ContainerID) + + m.SetValue(c.val) + } + + return m +} + +func (c *ContainerID) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*refs.ContainerID) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + c.val = v.GetValue() + + return nil +} + +func ContainerIDsToGRPCMessage(ids []ContainerID) (res []refs.ContainerID) { + if ids != nil { + res = make([]refs.ContainerID, 0, len(ids)) + + for i := range ids { + res = append(res, *ids[i].ToGRPCMessage().(*refs.ContainerID)) + } + } + + return +} + +func ContainerIDsFromGRPCMessage(idsV2 []refs.ContainerID) (res []ContainerID, err error) { + if idsV2 != nil { + res = make([]ContainerID, len(idsV2)) + + for i := range idsV2 { + err = res[i].FromGRPCMessage(&idsV2[i]) + if err != nil { + return + } + } + } + + return +} + +func (o *ObjectID) ToGRPCMessage() grpc.Message { + var m *refs.ObjectID + + if o != nil { + m = new(refs.ObjectID) + + m.SetValue(o.val) + } + + return m +} + +func (o *ObjectID) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*refs.ObjectID) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + o.val = v.GetValue() + + return nil +} + +func ObjectIDListToGRPCMessage(ids []ObjectID) (res []refs.ObjectID) { + if ids != nil { + res = make([]refs.ObjectID, 0, len(ids)) + + for i := range ids { + res = append(res, *ids[i].ToGRPCMessage().(*refs.ObjectID)) + } + } + + return +} + +func ObjectIDListFromGRPCMessage(idsV2 []refs.ObjectID) (res []ObjectID, err error) { + if idsV2 != nil { + res = make([]ObjectID, len(idsV2)) + + for i := range idsV2 { + err = res[i].FromGRPCMessage(&idsV2[i]) + if err != nil { + return + } + } + } + + return +} + +func (a *Address) ToGRPCMessage() grpc.Message { + var m *refs.Address + + if a != nil { + m = new(refs.Address) + + m.SetContainerId(a.cid.ToGRPCMessage().(*refs.ContainerID)) + m.SetObjectId(a.oid.ToGRPCMessage().(*refs.ObjectID)) + } + + return m +} + +func (a *Address) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*refs.Address) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + cid := v.GetContainerId() + if cid == nil { + a.cid = nil + } else { + if a.cid == nil { + a.cid = new(ContainerID) + } + + err = a.cid.FromGRPCMessage(cid) + if err != nil { + return err + } + } + + oid := v.GetObjectId() + if oid == nil { + a.oid = nil + } else { + if a.oid == nil { + a.oid = new(ObjectID) + } + + err = a.oid.FromGRPCMessage(oid) + } + + return err +} + +func ChecksumTypeToGRPC(t ChecksumType) refs.ChecksumType { + return refs.ChecksumType(t) +} + +func ChecksumTypeFromGRPC(t refs.ChecksumType) ChecksumType { + return ChecksumType(t) +} + +func (c *Checksum) ToGRPCMessage() grpc.Message { + var m *refs.Checksum + + if c != nil { + m = new(refs.Checksum) + + m.SetType(ChecksumTypeToGRPC(c.typ)) + m.SetSum(c.sum) + } + + return m +} + +func (c *Checksum) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*refs.Checksum) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + c.typ = ChecksumTypeFromGRPC(v.GetType()) + c.sum = v.GetSum() + + return nil +} + +func (v *Version) ToGRPCMessage() grpc.Message { + var m *refs.Version + + if v != nil { + m = new(refs.Version) + + m.SetMajor(v.major) + m.SetMinor(v.minor) + } + + return m +} + +func (v *Version) FromGRPCMessage(m grpc.Message) error { + ver, ok := m.(*refs.Version) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + v.major = ver.GetMajor() + v.minor = ver.GetMinor() + + return nil +} + +func (s *Signature) ToGRPCMessage() grpc.Message { + var m *refs.Signature + + if s != nil { + m = new(refs.Signature) + + m.SetKey(s.key) + m.SetSign(s.sign) + m.SetScheme(refs.SignatureScheme(s.scheme)) + } + + return m +} + +func (s *Signature) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*refs.Signature) + if !ok { + return message.NewUnexpectedMessageType(m, s) + } + + s.key = v.GetKey() + s.sign = v.GetSign() + s.scheme = SignatureScheme(v.GetScheme()) + + return nil +} diff --git a/api/refs/grpc/types_frostfs.pb.go b/api/refs/grpc/types_frostfs.pb.go new file mode 100644 index 0000000000000000000000000000000000000000..d3a80a56e718cdb31b583604ba59548bb18a66d1 GIT binary patch literal 30571 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 NvQMta!nDL>`~O5L;Y0uc literal 0 HcmV?d00001 diff --git a/api/refs/grpc/types_frostfs_fuzz.go b/api/refs/grpc/types_frostfs_fuzz.go new file mode 100644 index 0000000..a64a9bf --- /dev/null +++ b/api/refs/grpc/types_frostfs_fuzz.go @@ -0,0 +1,159 @@ +//go:build gofuzz +// +build gofuzz + +// Code generated by protoc-gen-go-frostfs. DO NOT EDIT. + +package refs + +func DoFuzzProtoAddress(data []byte) int { + msg := new(Address) + if err := msg.UnmarshalProtobuf(data); err != nil { + return 0 + } + _ = msg.MarshalProtobuf(nil) + return 1 +} +func DoFuzzJSONAddress(data []byte) int { + msg := new(Address) + if err := msg.UnmarshalJSON(data); err != nil { + return 0 + } + _, err := msg.MarshalJSON() + if err != nil { + panic(err) + } + return 1 +} +func DoFuzzProtoObjectID(data []byte) int { + msg := new(ObjectID) + if err := msg.UnmarshalProtobuf(data); err != nil { + return 0 + } + _ = msg.MarshalProtobuf(nil) + return 1 +} +func DoFuzzJSONObjectID(data []byte) int { + msg := new(ObjectID) + if err := msg.UnmarshalJSON(data); err != nil { + return 0 + } + _, err := msg.MarshalJSON() + if err != nil { + panic(err) + } + return 1 +} +func DoFuzzProtoContainerID(data []byte) int { + msg := new(ContainerID) + if err := msg.UnmarshalProtobuf(data); err != nil { + return 0 + } + _ = msg.MarshalProtobuf(nil) + return 1 +} +func DoFuzzJSONContainerID(data []byte) int { + msg := new(ContainerID) + if err := msg.UnmarshalJSON(data); err != nil { + return 0 + } + _, err := msg.MarshalJSON() + if err != nil { + panic(err) + } + return 1 +} +func DoFuzzProtoOwnerID(data []byte) int { + msg := new(OwnerID) + if err := msg.UnmarshalProtobuf(data); err != nil { + return 0 + } + _ = msg.MarshalProtobuf(nil) + return 1 +} +func DoFuzzJSONOwnerID(data []byte) int { + msg := new(OwnerID) + if err := msg.UnmarshalJSON(data); err != nil { + return 0 + } + _, err := msg.MarshalJSON() + if err != nil { + panic(err) + } + return 1 +} +func DoFuzzProtoVersion(data []byte) int { + msg := new(Version) + if err := msg.UnmarshalProtobuf(data); err != nil { + return 0 + } + _ = msg.MarshalProtobuf(nil) + return 1 +} +func DoFuzzJSONVersion(data []byte) int { + msg := new(Version) + if err := msg.UnmarshalJSON(data); err != nil { + return 0 + } + _, err := msg.MarshalJSON() + if err != nil { + panic(err) + } + return 1 +} +func DoFuzzProtoSignature(data []byte) int { + msg := new(Signature) + if err := msg.UnmarshalProtobuf(data); err != nil { + return 0 + } + _ = msg.MarshalProtobuf(nil) + return 1 +} +func DoFuzzJSONSignature(data []byte) int { + msg := new(Signature) + if err := msg.UnmarshalJSON(data); err != nil { + return 0 + } + _, err := msg.MarshalJSON() + if err != nil { + panic(err) + } + return 1 +} +func DoFuzzProtoSignatureRFC6979(data []byte) int { + msg := new(SignatureRFC6979) + if err := msg.UnmarshalProtobuf(data); err != nil { + return 0 + } + _ = msg.MarshalProtobuf(nil) + return 1 +} +func DoFuzzJSONSignatureRFC6979(data []byte) int { + msg := new(SignatureRFC6979) + if err := msg.UnmarshalJSON(data); err != nil { + return 0 + } + _, err := msg.MarshalJSON() + if err != nil { + panic(err) + } + return 1 +} +func DoFuzzProtoChecksum(data []byte) int { + msg := new(Checksum) + if err := msg.UnmarshalProtobuf(data); err != nil { + return 0 + } + _ = msg.MarshalProtobuf(nil) + return 1 +} +func DoFuzzJSONChecksum(data []byte) int { + msg := new(Checksum) + if err := msg.UnmarshalJSON(data); err != nil { + return 0 + } + _, err := msg.MarshalJSON() + if err != nil { + panic(err) + } + return 1 +} diff --git a/api/refs/grpc/types_frostfs_test.go b/api/refs/grpc/types_frostfs_test.go new file mode 100644 index 0000000..9b19892 --- /dev/null +++ b/api/refs/grpc/types_frostfs_test.go @@ -0,0 +1,91 @@ +//go:build gofuzz +// +build gofuzz + +// Code generated by protoc-gen-go-frostfs. DO NOT EDIT. + +package refs + +import ( + testing "testing" +) + +func FuzzProtoAddress(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzProtoAddress(data) + }) +} +func FuzzJSONAddress(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzJSONAddress(data) + }) +} +func FuzzProtoObjectID(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzProtoObjectID(data) + }) +} +func FuzzJSONObjectID(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzJSONObjectID(data) + }) +} +func FuzzProtoContainerID(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzProtoContainerID(data) + }) +} +func FuzzJSONContainerID(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzJSONContainerID(data) + }) +} +func FuzzProtoOwnerID(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzProtoOwnerID(data) + }) +} +func FuzzJSONOwnerID(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzJSONOwnerID(data) + }) +} +func FuzzProtoVersion(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzProtoVersion(data) + }) +} +func FuzzJSONVersion(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzJSONVersion(data) + }) +} +func FuzzProtoSignature(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzProtoSignature(data) + }) +} +func FuzzJSONSignature(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzJSONSignature(data) + }) +} +func FuzzProtoSignatureRFC6979(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzProtoSignatureRFC6979(data) + }) +} +func FuzzJSONSignatureRFC6979(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzJSONSignatureRFC6979(data) + }) +} +func FuzzProtoChecksum(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzProtoChecksum(data) + }) +} +func FuzzJSONChecksum(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzJSONChecksum(data) + }) +} diff --git a/api/refs/json.go b/api/refs/json.go new file mode 100644 index 0000000..652211f --- /dev/null +++ b/api/refs/json.go @@ -0,0 +1,62 @@ +package refs + +import ( + refs "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/message" +) + +func (a *Address) MarshalJSON() ([]byte, error) { + return message.MarshalJSON(a) +} + +func (a *Address) UnmarshalJSON(data []byte) error { + return message.UnmarshalJSON(a, data, new(refs.Address)) +} + +func (o *ObjectID) MarshalJSON() ([]byte, error) { + return message.MarshalJSON(o) +} + +func (o *ObjectID) UnmarshalJSON(data []byte) error { + return message.UnmarshalJSON(o, data, new(refs.ObjectID)) +} + +func (c *ContainerID) MarshalJSON() ([]byte, error) { + return message.MarshalJSON(c) +} + +func (c *ContainerID) UnmarshalJSON(data []byte) error { + return message.UnmarshalJSON(c, data, new(refs.ContainerID)) +} + +func (o *OwnerID) MarshalJSON() ([]byte, error) { + return message.MarshalJSON(o) +} + +func (o *OwnerID) UnmarshalJSON(data []byte) error { + return message.UnmarshalJSON(o, data, new(refs.OwnerID)) +} + +func (v *Version) MarshalJSON() ([]byte, error) { + return message.MarshalJSON(v) +} + +func (v *Version) UnmarshalJSON(data []byte) error { + return message.UnmarshalJSON(v, data, new(refs.Version)) +} + +func (s *Signature) MarshalJSON() ([]byte, error) { + return message.MarshalJSON(s) +} + +func (s *Signature) UnmarshalJSON(data []byte) error { + return message.UnmarshalJSON(s, data, new(refs.Signature)) +} + +func (c *Checksum) MarshalJSON() ([]byte, error) { + return message.MarshalJSON(c) +} + +func (c *Checksum) UnmarshalJSON(data []byte) error { + return message.UnmarshalJSON(c, data, new(refs.Checksum)) +} diff --git a/api/refs/marshal.go b/api/refs/marshal.go new file mode 100644 index 0000000..18f84b9 --- /dev/null +++ b/api/refs/marshal.go @@ -0,0 +1,264 @@ +package refs + +import ( + "encoding/binary" + + refs "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/message" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/util/proto" + "google.golang.org/protobuf/encoding/protowire" +) + +const ( + ownerIDValField = 1 + + containerIDValField = 1 + + objectIDValField = 1 + + addressContainerField = 1 + addressObjectField = 2 + + checksumTypeField = 1 + checksumValueField = 2 + + signatureKeyField = 1 + signatureValueField = 2 + signatureSchemeField = 3 + + versionMajorField = 1 + versionMinorField = 2 +) + +func (o *OwnerID) StableMarshal(buf []byte) []byte { + if o == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, o.StableSize()) + } + + proto.BytesMarshal(ownerIDValField, buf, o.val) + + return buf +} + +func (o *OwnerID) StableSize() int { + if o == nil { + return 0 + } + + return proto.BytesSize(ownerIDValField, o.val) +} + +func (o *OwnerID) Unmarshal(data []byte) error { + return message.Unmarshal(o, data, new(refs.OwnerID)) +} + +func (c *ContainerID) StableMarshal(buf []byte) []byte { + if c == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, c.StableSize()) + } + + proto.BytesMarshal(containerIDValField, buf, c.val) + + return buf +} + +func (c *ContainerID) StableSize() int { + if c == nil { + return 0 + } + + return proto.BytesSize(containerIDValField, c.val) +} + +func (c *ContainerID) Unmarshal(data []byte) error { + return message.Unmarshal(c, data, new(refs.ContainerID)) +} + +func (o *ObjectID) StableMarshal(buf []byte) []byte { + if o == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, o.StableSize()) + } + + proto.BytesMarshal(objectIDValField, buf, o.val) + + return buf +} + +// ObjectIDNestedListSize returns byte length of nested +// repeated ObjectID field with fNum number. +func ObjectIDNestedListSize(fNum int64, ids []ObjectID) (sz int) { + for i := range ids { + sz += proto.NestedStructureSize(fNum, &ids[i]) + } + + return +} + +func (o *ObjectID) StableSize() int { + if o == nil { + return 0 + } + + return proto.BytesSize(objectIDValField, o.val) +} + +// ObjectIDNestedListMarshal writes protobuf repeated ObjectID field +// with fNum number to buf. +func ObjectIDNestedListMarshal(fNum int64, buf []byte, ids []ObjectID) (off int) { + prefix := protowire.EncodeTag(protowire.Number(fNum), protowire.BytesType) + for i := range ids { + off += binary.PutUvarint(buf[off:], prefix) + + n := ids[i].StableSize() + off += binary.PutUvarint(buf[off:], uint64(n)) + off += proto.BytesMarshal(objectIDValField, buf[off:], ids[i].val) + } + + return +} + +func (o *ObjectID) Unmarshal(data []byte) error { + return message.Unmarshal(o, data, new(refs.ObjectID)) +} + +func (a *Address) StableMarshal(buf []byte) []byte { + if a == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, a.StableSize()) + } + + var offset int + + offset += proto.NestedStructureMarshal(addressContainerField, buf[offset:], a.cid) + proto.NestedStructureMarshal(addressObjectField, buf[offset:], a.oid) + + return buf +} + +func (a *Address) StableSize() (size int) { + if a == nil { + return 0 + } + + size += proto.NestedStructureSize(addressContainerField, a.cid) + size += proto.NestedStructureSize(addressObjectField, a.oid) + + return size +} + +func (a *Address) Unmarshal(data []byte) error { + return message.Unmarshal(a, data, new(refs.Address)) +} + +func (c *Checksum) StableMarshal(buf []byte) []byte { + if c == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, c.StableSize()) + } + + var offset int + + offset += proto.EnumMarshal(checksumTypeField, buf[offset:], int32(c.typ)) + proto.BytesMarshal(checksumValueField, buf[offset:], c.sum) + + return buf +} + +func (c *Checksum) StableSize() (size int) { + if c == nil { + return 0 + } + + size += proto.EnumSize(checksumTypeField, int32(c.typ)) + size += proto.BytesSize(checksumValueField, c.sum) + + return size +} + +func (c *Checksum) Unmarshal(data []byte) error { + return message.Unmarshal(c, data, new(refs.Checksum)) +} + +func (s *Signature) StableMarshal(buf []byte) []byte { + if s == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, s.StableSize()) + } + + var offset int + + offset += proto.BytesMarshal(signatureKeyField, buf[offset:], s.key) + offset += proto.BytesMarshal(signatureValueField, buf[offset:], s.sign) + proto.EnumMarshal(signatureSchemeField, buf[offset:], int32(s.scheme)) + + return buf +} + +func (s *Signature) StableSize() (size int) { + if s == nil { + return 0 + } + + size += proto.BytesSize(signatureKeyField, s.key) + size += proto.BytesSize(signatureValueField, s.sign) + size += proto.EnumSize(signatureSchemeField, int32(s.scheme)) + + return size +} + +func (s *Signature) Unmarshal(data []byte) error { + return message.Unmarshal(s, data, new(refs.Signature)) +} + +func (v *Version) StableMarshal(buf []byte) []byte { + if v == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, v.StableSize()) + } + + var offset int + + offset += proto.UInt32Marshal(versionMajorField, buf[offset:], v.major) + proto.UInt32Marshal(versionMinorField, buf[offset:], v.minor) + + return buf +} + +func (v *Version) StableSize() (size int) { + if v == nil { + return 0 + } + + size += proto.UInt32Size(versionMajorField, v.major) + size += proto.UInt32Size(versionMinorField, v.minor) + + return size +} + +func (v *Version) Unmarshal(data []byte) error { + return message.Unmarshal(v, data, new(refs.Version)) +} diff --git a/api/refs/message_test.go b/api/refs/message_test.go new file mode 100644 index 0000000..d844f93 --- /dev/null +++ b/api/refs/message_test.go @@ -0,0 +1,21 @@ +package refs_test + +import ( + "testing" + + refstest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs/test" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/message" + messagetest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/message/test" +) + +func TestMessageConvert(t *testing.T) { + messagetest.TestRPCMessage(t, + func(empty bool) message.Message { return refstest.GenerateOwnerID(empty) }, + func(empty bool) message.Message { return refstest.GenerateObjectID(empty) }, + func(empty bool) message.Message { return refstest.GenerateContainerID(empty) }, + func(empty bool) message.Message { return refstest.GenerateAddress(empty) }, + func(empty bool) message.Message { return refstest.GenerateChecksum(empty) }, + func(empty bool) message.Message { return refstest.GenerateSignature(empty) }, + func(empty bool) message.Message { return refstest.GenerateVersion(empty) }, + ) +} diff --git a/api/refs/string.go b/api/refs/string.go new file mode 100644 index 0000000..c33a241 --- /dev/null +++ b/api/refs/string.go @@ -0,0 +1,47 @@ +package refs + +import ( + refs "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs/grpc" +) + +// String returns string representation of ChecksumType. +func (t ChecksumType) String() string { + return ChecksumTypeToGRPC(t).String() +} + +// FromString parses ChecksumType from a string representation. +// It is a reverse action to String(). +// +// Returns true if s was parsed successfully. +func (t *ChecksumType) FromString(s string) bool { + var g refs.ChecksumType + + ok := g.FromString(s) + + if ok { + *t = ChecksumTypeFromGRPC(g) + } + + return ok +} + +// String returns string representation of SignatureScheme. +func (t SignatureScheme) String() string { + return refs.SignatureScheme(t).String() +} + +// FromString parses SignatureScheme from a string representation. +// It is a reverse action to String(). +// +// Returns true if s was parsed successfully. +func (t *SignatureScheme) FromString(s string) bool { + var g refs.SignatureScheme + + ok := g.FromString(s) + + if ok { + *t = SignatureScheme(g) + } + + return ok +} diff --git a/api/refs/test/generate.go b/api/refs/test/generate.go new file mode 100644 index 0000000..ec9151a --- /dev/null +++ b/api/refs/test/generate.go @@ -0,0 +1,127 @@ +package refstest + +import ( + crand "crypto/rand" + "crypto/sha256" + + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" +) + +func GenerateVersion(empty bool) *refs.Version { + m := new(refs.Version) + + if !empty { + m.SetMajor(2) + m.SetMinor(1) + } + + return m +} + +func GenerateOwnerID(empty bool) *refs.OwnerID { + m := new(refs.OwnerID) + + if !empty { + id := make([]byte, 25) + _, _ = crand.Read(id) + + m.SetValue(id) + } + + return m +} + +func GenerateAddress(empty bool) *refs.Address { + m := new(refs.Address) + + if !empty { + m.SetObjectID(GenerateObjectID(false)) + m.SetContainerID(GenerateContainerID(false)) + } + + return m +} + +func GenerateObjectID(empty bool) *refs.ObjectID { + m := new(refs.ObjectID) + + if !empty { + id := make([]byte, sha256.Size) + _, _ = crand.Read(id) + + m.SetValue(id) + } + + return m +} + +func GenerateObjectIDs(empty bool) []refs.ObjectID { + var ids []refs.ObjectID + + if !empty { + ids = append(ids, + *GenerateObjectID(false), + *GenerateObjectID(false), + ) + } + + return ids +} + +func GenerateContainerID(empty bool) *refs.ContainerID { + m := new(refs.ContainerID) + + if !empty { + id := make([]byte, sha256.Size) + _, _ = crand.Read(id) + + m.SetValue(id) + } + + return m +} + +func GenerateContainerIDs(empty bool) []refs.ContainerID { + var res []refs.ContainerID + + if !empty { + res = append(res, + *GenerateContainerID(false), + *GenerateContainerID(false), + ) + } + + return res +} + +func GenerateSignature(empty bool) *refs.Signature { + m := new(refs.Signature) + + if !empty { + key := make([]byte, 33) + _, _ = crand.Read(key) + + sign := make([]byte, 65) + _, _ = crand.Read(sign) + + m.SetScheme(refs.ECDSA_SHA512) + m.SetKey(key) + m.SetSign(sign) + } + + return m +} + +func GenerateChecksum(empty bool) *refs.Checksum { + m := new(refs.Checksum) + + if !empty { + cs := make([]byte, sha256.Size) + _, _ = crand.Read(cs) + + m.SetType(refs.SHA256) + m.SetSum(cs) + } + + return m +} diff --git a/api/refs/types.go b/api/refs/types.go new file mode 100644 index 0000000..d8f0d9b --- /dev/null +++ b/api/refs/types.go @@ -0,0 +1,194 @@ +package refs + +type OwnerID struct { + val []byte +} + +type ContainerID struct { + val []byte +} + +type ObjectID struct { + val []byte +} + +type Address struct { + cid *ContainerID + + oid *ObjectID +} + +type Checksum struct { + typ ChecksumType + + sum []byte +} + +type ChecksumType uint32 + +type SignatureScheme uint32 + +//nolint:revive +const ( + ECDSA_SHA512 SignatureScheme = iota + ECDSA_RFC6979_SHA256 + ECDSA_RFC6979_SHA256_WALLET_CONNECT +) + +type Signature struct { + key, sign []byte + scheme SignatureScheme +} + +type Version struct { + major, minor uint32 +} + +const ( + UnknownChecksum ChecksumType = iota + TillichZemor + SHA256 +) + +func (o *OwnerID) GetValue() []byte { + if o != nil { + return o.val + } + + return nil +} + +func (o *OwnerID) SetValue(v []byte) { + o.val = v +} + +func (c *ContainerID) GetValue() []byte { + if c != nil { + return c.val + } + + return nil +} + +func (c *ContainerID) SetValue(v []byte) { + c.val = v +} + +func (o *ObjectID) GetValue() []byte { + if o != nil { + return o.val + } + + return nil +} + +func (o *ObjectID) SetValue(v []byte) { + o.val = v +} + +func (a *Address) GetContainerID() *ContainerID { + if a != nil { + return a.cid + } + + return nil +} + +func (a *Address) SetContainerID(v *ContainerID) { + a.cid = v +} + +func (a *Address) GetObjectID() *ObjectID { + if a != nil { + return a.oid + } + + return nil +} + +func (a *Address) SetObjectID(v *ObjectID) { + a.oid = v +} + +func (c *Checksum) GetType() ChecksumType { + if c != nil { + return c.typ + } + + return UnknownChecksum +} + +func (c *Checksum) SetType(v ChecksumType) { + c.typ = v +} + +func (c *Checksum) GetSum() []byte { + if c != nil { + return c.sum + } + + return nil +} + +func (c *Checksum) SetSum(v []byte) { + c.sum = v +} + +func (s *Signature) GetKey() []byte { + if s != nil { + return s.key + } + + return nil +} + +func (s *Signature) SetKey(v []byte) { + s.key = v +} + +func (s *Signature) GetSign() []byte { + if s != nil { + return s.sign + } + + return nil +} + +func (s *Signature) SetSign(v []byte) { + s.sign = v +} + +func (s *Signature) GetScheme() SignatureScheme { + if s != nil { + return s.scheme + } + return 0 +} + +func (s *Signature) SetScheme(scheme SignatureScheme) { + s.scheme = scheme +} + +func (v *Version) GetMajor() uint32 { + if v != nil { + return v.major + } + + return 0 +} + +func (v *Version) SetMajor(val uint32) { + v.major = val +} + +func (v *Version) GetMinor() uint32 { + if v != nil { + return v.minor + } + + return 0 +} + +func (v *Version) SetMinor(val uint32) { + v.minor = val +} diff --git a/api/rpc/accounting.go b/api/rpc/accounting.go new file mode 100644 index 0000000..31259bd --- /dev/null +++ b/api/rpc/accounting.go @@ -0,0 +1,29 @@ +package rpc + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/accounting" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/common" +) + +const serviceAccounting = serviceNamePrefix + "accounting.AccountingService" + +const ( + rpcAccountingBalance = "Balance" +) + +// Balance executes AccountingService.Balance RPC. +func Balance( + cli *client.Client, + req *accounting.BalanceRequest, + opts ...client.CallOption, +) (*accounting.BalanceResponse, error) { + resp := new(accounting.BalanceResponse) + + err := client.SendUnary(cli, common.CallMethodInfoUnary(serviceAccounting, rpcAccountingBalance), req, resp, opts...) + if err != nil { + return nil, err + } + + return resp, nil +} diff --git a/api/rpc/apemanager.go b/api/rpc/apemanager.go new file mode 100644 index 0000000..6494d16 --- /dev/null +++ b/api/rpc/apemanager.go @@ -0,0 +1,60 @@ +package rpc + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/apemanager" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/common" +) + +const serviceAPEManager = frostfsServiceNamePrefix + "apemanager.APEManagerService" + +const ( + rpcAPEManagerAddChain = "AddChain" + rpcAPEManagerRemoveChain = "RemoveChain" + rpcAPEManagerListChains = "ListChains" +) + +func AddChain( + cli *client.Client, + req *apemanager.AddChainRequest, + opts ...client.CallOption, +) (*apemanager.AddChainResponse, error) { + resp := new(apemanager.AddChainResponse) + + err := client.SendUnary(cli, common.CallMethodInfoUnary(serviceAPEManager, rpcAPEManagerAddChain), req, resp, opts...) + if err != nil { + return nil, err + } + + return resp, nil +} + +func RemoveChain( + cli *client.Client, + req *apemanager.RemoveChainRequest, + opts ...client.CallOption, +) (*apemanager.RemoveChainResponse, error) { + resp := new(apemanager.RemoveChainResponse) + + err := client.SendUnary(cli, common.CallMethodInfoUnary(serviceAPEManager, rpcAPEManagerRemoveChain), req, resp, opts...) + if err != nil { + return nil, err + } + + return resp, nil +} + +func ListChains( + cli *client.Client, + req *apemanager.ListChainsRequest, + opts ...client.CallOption, +) (*apemanager.ListChainsResponse, error) { + resp := new(apemanager.ListChainsResponse) + + err := client.SendUnary(cli, common.CallMethodInfoUnary(serviceAPEManager, rpcAPEManagerListChains), req, resp, opts...) + if err != nil { + return nil, err + } + + return resp, nil +} diff --git a/api/rpc/client/call_options.go b/api/rpc/client/call_options.go new file mode 100644 index 0000000..4fe8791 --- /dev/null +++ b/api/rpc/client/call_options.go @@ -0,0 +1,40 @@ +package client + +import ( + "context" + + "google.golang.org/grpc" +) + +// CallOption is a messaging session option within Protobuf RPC. +type CallOption func(*callParameters) + +type callParameters struct { + ctx context.Context // nolint:containedctx + dialer func(context.Context, grpc.ClientConnInterface) error +} + +func defaultCallParameters() *callParameters { + return &callParameters{ + ctx: context.Background(), + } +} + +// WithContext returns option to specify call context. If provided, all network +// communications will be based on this context. Otherwise, context.Background() +// is used. +// +// Context SHOULD NOT be nil. +func WithContext(ctx context.Context) CallOption { + return func(prm *callParameters) { + prm.ctx = ctx + } +} + +// WithDialer returns option to specify grpc dialer. If passed, it will be +// called after the connection is successfully created. +func WithDialer(dialer func(context.Context, grpc.ClientConnInterface) error) CallOption { + return func(prm *callParameters) { + prm.dialer = dialer + } +} diff --git a/api/rpc/client/client.go b/api/rpc/client/client.go new file mode 100644 index 0000000..eeac896 --- /dev/null +++ b/api/rpc/client/client.go @@ -0,0 +1,30 @@ +package client + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/util/proto/encoding" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials" +) + +// Client represents client for exchanging messages +// with a remote server using Protobuf RPC. +type Client struct { + cfg +} + +// New creates, configures via options and returns new Client instance. +func New(opts ...Option) *Client { + var c Client + c.initDefault() + + for _, opt := range opts { + opt(&c.cfg) + } + + c.grpcDialOpts = append(c.grpcDialOpts, grpc.WithDefaultCallOptions(grpc.ForceCodec(encoding.ProtoCodec{}))) + if c.tlsCfg != nil { + c.grpcDialOpts = append(c.grpcDialOpts, grpc.WithTransportCredentials(credentials.NewTLS(c.tlsCfg))) + } + + return &c +} diff --git a/api/rpc/client/conn.go b/api/rpc/client/conn.go new file mode 100644 index 0000000..f208413 --- /dev/null +++ b/api/rpc/client/conn.go @@ -0,0 +1,24 @@ +package client + +import ( + "io" + + "google.golang.org/grpc" +) + +// Conn is an interface for grpc client connection. +type Conn interface { + grpc.ClientConnInterface + io.Closer +} + +// Conn returns underlying connection. +// +// Returns non-nil result after the first Init() call +// completed without a connection error. +// +// Client should not be used after Close() call +// on the connection: behavior is undefined. +func (c *Client) Conn() io.Closer { + return c.conn +} diff --git a/api/rpc/client/connect.go b/api/rpc/client/connect.go new file mode 100644 index 0000000..e22e0a6 --- /dev/null +++ b/api/rpc/client/connect.go @@ -0,0 +1,72 @@ +package client + +import ( + "context" + "errors" + "fmt" + "net" + "net/url" + + grpcstd "google.golang.org/grpc" +) + +var errInvalidEndpoint = errors.New("invalid endpoint options") + +func (c *Client) openGRPCConn(ctx context.Context, dialer func(ctx context.Context, cc grpcstd.ClientConnInterface) error) error { + if c.conn != nil { + return nil + } + + if c.addr == "" { + return errInvalidEndpoint + } + + var err error + + c.conn, err = grpcstd.NewClient(c.addr, c.grpcDialOpts...) + if err != nil { + return fmt.Errorf("gRPC new client: %w", err) + } + + if dialer != nil { + ctx, cancel := context.WithTimeout(ctx, c.dialTimeout) + defer cancel() + + if err := dialer(ctx, c.conn); err != nil { + _ = c.conn.Close() + return fmt.Errorf("gRPC dial: %w", err) + } + } + + return nil +} + +// ParseURI parses s as address and returns a host and a flag +// indicating that TLS is enabled. If multi-address is provided +// the argument is returned unchanged. +func ParseURI(s string) (string, bool, error) { + uri, err := url.ParseRequestURI(s) + if err != nil { + return s, false, nil + } + + // check if passed string was parsed correctly + // URIs that do not start with a slash after the scheme are interpreted as: + // `scheme:opaque` => if `opaque` is not empty, then it is supposed that URI + // is in `host:port` format + if uri.Host == "" { + uri.Host = uri.Scheme + uri.Scheme = grpcScheme // assume GRPC by default + if uri.Opaque != "" { + uri.Host = net.JoinHostPort(uri.Host, uri.Opaque) + } + } + + switch uri.Scheme { + case grpcTLSScheme, grpcScheme: + default: + return "", false, fmt.Errorf("unsupported scheme: %s", uri.Scheme) + } + + return uri.Host, uri.Scheme == grpcTLSScheme, nil +} diff --git a/api/rpc/client/flows.go b/api/rpc/client/flows.go new file mode 100644 index 0000000..671c679 --- /dev/null +++ b/api/rpc/client/flows.go @@ -0,0 +1,124 @@ +package client + +import ( + "errors" + "io" + "sync" + + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/common" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/message" +) + +// SendUnary initializes communication session by RPC info, performs unary RPC +// and closes the session. +func SendUnary(cli *Client, info common.CallMethodInfo, req, resp message.Message, opts ...CallOption) error { + rw, err := cli.Init(info, opts...) + if err != nil { + return err + } + + err = rw.WriteMessage(req) + if err != nil { + return err + } + + err = rw.ReadMessage(resp) + if err != nil { + return err + } + + return rw.Close() +} + +// MessageWriterCloser wraps MessageWriter +// and io.Closer interfaces. +type MessageWriterCloser interface { + MessageWriter + io.Closer +} + +type clientStreamWriterCloser struct { + MessageReadWriter + + resp message.Message +} + +func (c *clientStreamWriterCloser) Close() error { + err := c.MessageReadWriter.Close() + if err != nil { + return err + } + + return c.ReadMessage(c.resp) +} + +// OpenClientStream initializes communication session by RPC info, opens client-side stream +// and returns its interface. +// +// All stream writes must be performed before the closing. Close must be called once. +func OpenClientStream(cli *Client, info common.CallMethodInfo, resp message.Message, opts ...CallOption) (MessageWriterCloser, error) { + rw, err := cli.Init(info, opts...) + if err != nil { + return nil, err + } + + return &clientStreamWriterCloser{ + MessageReadWriter: rw, + resp: resp, + }, nil +} + +// MessageReaderCloser wraps MessageReader +// and io.Closer interface. +type MessageReaderCloser interface { + MessageReader + io.Closer +} + +type serverStreamReaderCloser struct { + rw MessageReadWriter + + once sync.Once + + req message.Message +} + +func (s *serverStreamReaderCloser) ReadMessage(msg message.Message) error { + var err error + + s.once.Do(func() { + err = s.rw.WriteMessage(s.req) + }) + + if err != nil { + return err + } + + err = s.rw.ReadMessage(msg) + if !errors.Is(err, io.EOF) { + return err + } + + err = s.rw.Close() + if err != nil { + return err + } + + return io.EOF +} + +// OpenServerStream initializes communication session by RPC info, opens server-side stream +// and returns its interface. +// +// All stream reads must be performed before the closing. Close must be called once. +func OpenServerStream(cli *Client, info common.CallMethodInfo, req message.Message, opts ...CallOption) (MessageReader, error) { + rw, err := cli.Init(info, opts...) + if err != nil { + return nil, err + } + + return &serverStreamReaderCloser{ + rw: rw, + req: req, + }, nil +} diff --git a/api/rpc/client/init.go b/api/rpc/client/init.go new file mode 100644 index 0000000..706e6a9 --- /dev/null +++ b/api/rpc/client/init.go @@ -0,0 +1,69 @@ +package client + +import ( + "context" + "io" + + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/common" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/message" + "google.golang.org/grpc" +) + +// MessageReader is an interface of the Message reader. +type MessageReader interface { + // ReadMessage reads the next Message. + // + // Returns io.EOF if there are no more messages to read. + // ReadMessage should not be called after io.EOF occasion. + ReadMessage(message.Message) error +} + +// MessageWriter is an interface of the Message writer. +type MessageWriter interface { + // WriteMessage writers the next Message. + // + // WriteMessage should not be called after any error. + WriteMessage(message.Message) error +} + +// MessageReadWriter is a component interface +// for transmitting raw Protobuf messages. +type MessageReadWriter interface { + MessageReader + MessageWriter + + // Closes the communication session. + // + // All calls to send/receive messages must be done before closing. + io.Closer +} + +// Init initiates a messaging session and returns the interface for message transmitting. +func (c *Client) Init(info common.CallMethodInfo, opts ...CallOption) (MessageReadWriter, error) { + prm := defaultCallParameters() + + for _, opt := range opts { + opt(prm) + } + + if err := c.openGRPCConn(prm.ctx, prm.dialer); err != nil { + return nil, err + } + + ctx, cancel := context.WithCancel(prm.ctx) + stream, err := c.conn.NewStream(ctx, &grpc.StreamDesc{ + StreamName: info.Name, + ServerStreams: info.ServerStream(), + ClientStreams: info.ClientStream(), + }, toMethodName(info)) + if err != nil { + cancel() + return nil, err + } + + return &streamWrapper{ + ClientStream: stream, + cancel: cancel, + timeout: c.rwTimeout, + }, nil +} diff --git a/api/rpc/client/options.go b/api/rpc/client/options.go new file mode 100644 index 0000000..5711cd4 --- /dev/null +++ b/api/rpc/client/options.go @@ -0,0 +1,129 @@ +package client + +import ( + "crypto/tls" + "time" + + "google.golang.org/grpc" + "google.golang.org/grpc/credentials/insecure" +) + +const ( + grpcScheme = "grpc" + grpcTLSScheme = "grpcs" +) + +// Option is a Client's option. +type Option func(*cfg) + +type cfg struct { + addr string + + dialTimeout time.Duration + rwTimeout time.Duration + + tlsCfg *tls.Config + grpcDialOpts []grpc.DialOption + + conn Conn +} + +const ( + defaultDialTimeout = 5 * time.Second + defaultRWTimeout = 1 * time.Minute +) + +func (c *cfg) initDefault() { + c.dialTimeout = defaultDialTimeout + c.rwTimeout = defaultRWTimeout + c.grpcDialOpts = []grpc.DialOption{ + grpc.WithTransportCredentials(insecure.NewCredentials()), + } +} + +// WithNetworkAddress returns option to specify +// network address of the remote server. +// +// Ignored if WithGRPCConn is provided. +func WithNetworkAddress(v string) Option { + return func(c *cfg) { + if v != "" { + c.addr = v + } + } +} + +// WithNetworkURIAddress combines WithNetworkAddress and WithTLSCfg options +// based on arguments. +// +// Do not use along with WithNetworkAddress and WithTLSCfg. +// +// Ignored if WithGRPCConn is provided. +func WithNetworkURIAddress(addr string, tlsCfg *tls.Config) []Option { + host, isTLS, err := ParseURI(addr) + if err != nil { + return nil + } + + opts := make([]Option, 2) + opts[0] = WithNetworkAddress(host) + if isTLS { + if tlsCfg == nil { + tlsCfg = &tls.Config{} + } + opts[1] = WithTLSCfg(tlsCfg) + } else { + opts[1] = WithTLSCfg(nil) + } + + return opts +} + +// WithDialTimeout returns option to specify +// dial timeout of the remote server connection. +// +// Ignored if WithGRPCConn is provided. +func WithDialTimeout(v time.Duration) Option { + return func(c *cfg) { + if v > 0 { + c.dialTimeout = v + } + } +} + +// WithRWTimeout returns option to specify timeout +// for reading and writing single gRPC message. +func WithRWTimeout(v time.Duration) Option { + return func(c *cfg) { + if v > 0 { + c.rwTimeout = v + } + } +} + +// WithTLSCfg returns option to specify +// TLS configuration. +// +// Ignored if WithGRPCConn is provided. +func WithTLSCfg(v *tls.Config) Option { + return func(c *cfg) { + c.tlsCfg = v + } +} + +// WithGRPCConn returns option to specify +// gRPC virtual connection. +func WithGRPCConn(v Conn) Option { + return func(c *cfg) { + if v != nil { + c.conn = v + } + } +} + +// WithGRPCDialOptions returns an option to specify grpc.DialOption. +func WithGRPCDialOptions(opts []grpc.DialOption) Option { + return func(c *cfg) { + c.grpcDialOpts = append(c.grpcDialOpts, opts...) + } +} diff --git a/api/rpc/client/options_test.go b/api/rpc/client/options_test.go new file mode 100644 index 0000000..56704b6 --- /dev/null +++ b/api/rpc/client/options_test.go @@ -0,0 +1,197 @@ +package client + +import ( + "crypto/tls" + "testing" + + "github.com/stretchr/testify/require" +) + +func TestWithNetworkURIAddress(t *testing.T) { + hostPort := "frostfs.example.com:8080" + apiPort := "127.0.0.1:8080" + serverName := "testServer" + + testCases := []struct { + uri string + tlsConfig *tls.Config + + wantHost string + wantTLS bool + }{ + { + uri: grpcScheme + "://" + hostPort, + tlsConfig: nil, + wantHost: "frostfs.example.com:8080", + wantTLS: false, + }, + { + uri: grpcScheme + "://" + hostPort, + tlsConfig: &tls.Config{}, + wantHost: "frostfs.example.com:8080", + wantTLS: false, + }, + { + uri: grpcTLSScheme + "://" + hostPort, + tlsConfig: nil, + wantHost: "frostfs.example.com:8080", + wantTLS: true, + }, + { + uri: grpcTLSScheme + "://" + hostPort, + tlsConfig: &tls.Config{ServerName: serverName}, + wantHost: "frostfs.example.com:8080", + wantTLS: true, + }, + { + uri: "wrongScheme://" + hostPort, + tlsConfig: nil, + wantHost: "", + wantTLS: false, + }, + { + uri: "impossibleToParseIt", + tlsConfig: nil, + wantHost: "impossibleToParseIt", + wantTLS: false, + }, + { + uri: hostPort, + tlsConfig: nil, + wantHost: hostPort, + wantTLS: false, + }, + { + uri: apiPort, + tlsConfig: nil, + wantHost: apiPort, + wantTLS: false, + }, + } + + for _, test := range testCases { + cfg := &cfg{} + opts := WithNetworkURIAddress(test.uri, test.tlsConfig) + + for _, opt := range opts { + opt(cfg) + } + + require.Equal(t, test.wantHost, cfg.addr, test.uri) + require.Equal(t, test.wantTLS, cfg.tlsCfg != nil, test.uri) + // check if custom tlsConfig was applied + if test.tlsConfig != nil && test.wantTLS { + require.Equal(t, test.tlsConfig.ServerName, cfg.tlsCfg.ServerName, test.uri) + } + } +} + +func Test_WithNetworkAddress_WithTLS_WithNetworkURIAddress(t *testing.T) { + addr1, addr2 := "example1.com:8080", "example2.com:8080" + + testCases := []struct { + addr string + withTLS bool + + uri string + + wantHost string + wantTLS bool + }{ + { + addr: addr1, + withTLS: true, + + uri: grpcScheme + "://" + addr2, + + wantHost: addr2, + wantTLS: false, + }, + { + addr: addr1, + withTLS: false, + + uri: grpcTLSScheme + "://" + addr2, + + wantHost: addr2, + wantTLS: true, + }, + } + + for _, test := range testCases { + // order: + // 1. WithNetworkAddress + // 2. WithTLSCfg(if test.withTLS == true) + // 3. WithNetworkURIAddress + config := &cfg{} + opts := []Option{WithNetworkAddress(test.addr)} + + if test.withTLS { + opts = append(opts, WithTLSCfg(&tls.Config{})) + } + + opts = append(opts, WithNetworkURIAddress(test.uri, nil)...) + + for _, opt := range opts { + opt(config) + } + + require.Equal(t, test.wantHost, config.addr, test.addr) + require.Equal(t, test.wantTLS, config.tlsCfg != nil, test.addr) + } +} + +func Test_WithNetworkURIAddress_WithTLS_WithNetworkAddress(t *testing.T) { + addr1, addr2 := "example1.com:8080", "example2.com:8080" + + testCases := []struct { + addr string + withTLS bool + + uri string + + wantHost string + wantTLS bool + }{ + { + uri: grpcScheme + "://" + addr1, + + addr: addr2, + withTLS: true, + + wantHost: addr2, + wantTLS: true, + }, + { + uri: grpcTLSScheme + "://" + addr1, + + addr: addr2, + withTLS: false, + + wantHost: addr2, + wantTLS: true, + }, + } + + for _, test := range testCases { + // order: + // 1. WithNetworkURIAddress + // 2. WithNetworkAddress + // 3. WithTLSCfg(if test.withTLS == true) + config := &cfg{} + opts := WithNetworkURIAddress(test.uri, nil) + + opts = append(opts, WithNetworkAddress(test.addr)) + + if test.withTLS { + opts = append(opts, WithTLSCfg(&tls.Config{})) + } + + for _, opt := range opts { + opt(config) + } + + require.Equal(t, test.wantHost, config.addr, test.uri) + require.Equal(t, test.wantTLS, config.tlsCfg != nil, test.uri) + } +} diff --git a/api/rpc/client/stream_wrapper.go b/api/rpc/client/stream_wrapper.go new file mode 100644 index 0000000..4c7bb1f --- /dev/null +++ b/api/rpc/client/stream_wrapper.go @@ -0,0 +1,58 @@ +package client + +import ( + "context" + "time" + + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/message" + "google.golang.org/grpc" +) + +type streamWrapper struct { + grpc.ClientStream + timeout time.Duration + cancel context.CancelFunc +} + +func (w streamWrapper) ReadMessage(m message.Message) error { + // Can be optimized: we can create blank message here. + gm := m.ToGRPCMessage() + + err := w.withTimeout(func() error { + return w.ClientStream.RecvMsg(gm) + }) + if err != nil { + return err + } + + return m.FromGRPCMessage(gm) +} + +func (w streamWrapper) WriteMessage(m message.Message) error { + return w.withTimeout(func() error { + return w.ClientStream.SendMsg(m.ToGRPCMessage()) + }) +} + +func (w *streamWrapper) Close() error { + return w.withTimeout(w.ClientStream.CloseSend) +} + +func (w *streamWrapper) withTimeout(closure func() error) error { + ch := make(chan error, 1) + go func() { + ch <- closure() + close(ch) + }() + + tt := time.NewTimer(w.timeout) + + select { + case err := <-ch: + tt.Stop() + return err + case <-tt.C: + w.cancel() + return context.DeadlineExceeded + } +} diff --git a/api/rpc/client/util.go b/api/rpc/client/util.go new file mode 100644 index 0000000..3d68b95 --- /dev/null +++ b/api/rpc/client/util.go @@ -0,0 +1,13 @@ +package client + +import ( + "fmt" + + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/common" +) + +const methodNameFmt = "/%s/%s" + +func toMethodName(p common.CallMethodInfo) string { + return fmt.Sprintf(methodNameFmt, p.Service, p.Name) +} diff --git a/api/rpc/common.go b/api/rpc/common.go new file mode 100644 index 0000000..8177694 --- /dev/null +++ b/api/rpc/common.go @@ -0,0 +1,10 @@ +package rpc + +const ( + // serviceNamePrefix is still used in "old" services but should be + // considered as deprecated. Since new services use "frostfs" root, + // `frostfsServiceNamePrefix` must be used for their rpc interface. + serviceNamePrefix = "neo.fs.v2." + + frostfsServiceNamePrefix = "frostfs.v2." +) diff --git a/api/rpc/common/call.go b/api/rpc/common/call.go new file mode 100644 index 0000000..bc3410a --- /dev/null +++ b/api/rpc/common/call.go @@ -0,0 +1,75 @@ +package common + +type callType uint8 + +const ( + _ callType = iota + callUnary + callClientStream + callServerStream + callBidirStream +) + +// CallMethodInfo is an information about the RPC. +type CallMethodInfo struct { + // Name of the service. + Service string + + // Name of the RPC. + Name string + + t callType +} + +// ServerStream checks if CallMethodInfo contains +// information about the server-side streaming RPC. +func (c CallMethodInfo) ServerStream() bool { + return c.t == callServerStream || c.t == callBidirStream +} + +// ClientStream checks if CallMethodInfo contains +// information about the client-side streaming RPC. +func (c CallMethodInfo) ClientStream() bool { + return c.t == callClientStream || c.t == callBidirStream +} + +func (c *CallMethodInfo) setCommon(service, name string) { + c.Service = service + c.Name = name +} + +// CallMethodInfoUnary returns CallMethodInfo structure +// initialized for the unary RPC. +func CallMethodInfoUnary(service, name string) (info CallMethodInfo) { + info.setCommon(service, name) + info.t = callUnary + + return +} + +// CallMethodInfoClientStream returns CallMethodInfo structure +// initialized for the client-side streaming RPC. +func CallMethodInfoClientStream(service, name string) (info CallMethodInfo) { + info.setCommon(service, name) + info.t = callClientStream + + return +} + +// CallMethodInfoServerStream returns CallMethodInfo structure +// initialized for the server-side streaming RPC. +func CallMethodInfoServerStream(service, name string) (info CallMethodInfo) { + info.setCommon(service, name) + info.t = callServerStream + + return +} + +// CallMethodInfoBidirectionalStream returns CallMethodInfo structure +// initialized for the bidirectional streaming RPC. +func CallMethodInfoBidirectionalStream(service, name string) (info CallMethodInfo) { + info.setCommon(service, name) + info.t = callBidirStream + + return +} diff --git a/api/rpc/common/call_test.go b/api/rpc/common/call_test.go new file mode 100644 index 0000000..eb88b69 --- /dev/null +++ b/api/rpc/common/call_test.go @@ -0,0 +1,49 @@ +package common_test + +import ( + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/common" + "github.com/stretchr/testify/require" +) + +const ( + testServiceName = "test service" + testRPCName = "test RPC" +) + +func TestCallMethodInfoUnary(t *testing.T) { + i := common.CallMethodInfoUnary(testServiceName, testRPCName) + + require.Equal(t, testServiceName, i.Service) + require.Equal(t, testRPCName, i.Name) + require.False(t, i.ClientStream()) + require.False(t, i.ServerStream()) +} + +func TestCallMethodInfoServerStream(t *testing.T) { + i := common.CallMethodInfoServerStream(testServiceName, testRPCName) + + require.Equal(t, testServiceName, i.Service) + require.Equal(t, testRPCName, i.Name) + require.False(t, i.ClientStream()) + require.True(t, i.ServerStream()) +} + +func TestCallMethodInfoClientStream(t *testing.T) { + i := common.CallMethodInfoClientStream(testServiceName, testRPCName) + + require.Equal(t, testServiceName, i.Service) + require.Equal(t, testRPCName, i.Name) + require.True(t, i.ClientStream()) + require.False(t, i.ServerStream()) +} + +func TestCallMethodInfoBidirectionalStream(t *testing.T) { + i := common.CallMethodInfoBidirectionalStream(testServiceName, testRPCName) + + require.Equal(t, testServiceName, i.Service) + require.Equal(t, testRPCName, i.Name) + require.True(t, i.ClientStream()) + require.True(t, i.ServerStream()) +} diff --git a/api/rpc/container.go b/api/rpc/container.go new file mode 100644 index 0000000..9ba5c99 --- /dev/null +++ b/api/rpc/container.go @@ -0,0 +1,82 @@ +package rpc + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/container" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/common" +) + +const serviceContainer = serviceNamePrefix + "container.ContainerService" + +const ( + rpcContainerPut = "Put" + rpcContainerGet = "Get" + rpcContainerDel = "Delete" + rpcContainerList = "List" + rpcContainerGetEACL = "GetExtendedACL" + rpcContainerUsedSpace = "AnnounceUsedSpace" +) + +// PutContainer executes ContainerService.Put RPC. +func PutContainer( + cli *client.Client, + req *container.PutRequest, + opts ...client.CallOption, +) (*container.PutResponse, error) { + resp := new(container.PutResponse) + + err := client.SendUnary(cli, common.CallMethodInfoUnary(serviceContainer, rpcContainerPut), req, resp, opts...) + if err != nil { + return nil, err + } + + return resp, nil +} + +// GetContainer executes ContainerService.Get RPC. +func GetContainer( + cli *client.Client, + req *container.GetRequest, + opts ...client.CallOption, +) (*container.GetResponse, error) { + resp := new(container.GetResponse) + + err := client.SendUnary(cli, common.CallMethodInfoUnary(serviceContainer, rpcContainerGet), req, resp, opts...) + if err != nil { + return nil, err + } + + return resp, nil +} + +// DeleteContainer executes ContainerService.Delete RPC. +func DeleteContainer( + cli *client.Client, + req *container.DeleteRequest, + opts ...client.CallOption, +) (*container.PutResponse, error) { + resp := new(container.PutResponse) + + err := client.SendUnary(cli, common.CallMethodInfoUnary(serviceContainer, rpcContainerDel), req, resp, opts...) + if err != nil { + return nil, err + } + + return resp, nil +} + +// ListContainers executes ContainerService.List RPC. +func ListContainers( + cli *client.Client, + req *container.ListRequest, + opts ...client.CallOption, +) (*container.ListResponse, error) { + resp := new(container.ListResponse) + + err := client.SendUnary(cli, common.CallMethodInfoUnary(serviceContainer, rpcContainerList), req, resp, opts...) + if err != nil { + return nil, err + } + + return resp, nil +} diff --git a/api/rpc/grpc/init.go b/api/rpc/grpc/init.go new file mode 100644 index 0000000..0092d39 --- /dev/null +++ b/api/rpc/grpc/init.go @@ -0,0 +1,4 @@ +package grpc + +// Message represents raw gRPC message. +type Message any diff --git a/api/rpc/message/encoding.go b/api/rpc/message/encoding.go new file mode 100644 index 0000000..d656acd --- /dev/null +++ b/api/rpc/message/encoding.go @@ -0,0 +1,40 @@ +package message + +import ( + "encoding/json" +) + +// GRPCConvertedMessage is an interface +// of the gRPC message that is used +// for Message encoding/decoding. +type GRPCConvertedMessage interface { + UnmarshalProtobuf([]byte) error +} + +// Unmarshal decodes m from its Protobuf binary representation +// via related gRPC message. +// +// gm should be tof the same type as the m.ToGRPCMessage() return. +func Unmarshal(m Message, data []byte, gm GRPCConvertedMessage) error { + if err := gm.UnmarshalProtobuf(data); err != nil { + return err + } + + return m.FromGRPCMessage(gm) +} + +// MarshalJSON encodes m to Protobuf JSON representation. +func MarshalJSON(m Message) ([]byte, error) { + return json.Marshal(m.ToGRPCMessage()) +} + +// UnmarshalJSON decodes m from its Protobuf JSON representation +// via related gRPC message. +// +// gm should be tof the same type as the m.ToGRPCMessage() return. +func UnmarshalJSON(m Message, data []byte, gm any) error { + if err := json.Unmarshal(data, gm); err != nil { + return err + } + return m.FromGRPCMessage(gm) +} diff --git a/api/rpc/message/message.go b/api/rpc/message/message.go new file mode 100644 index 0000000..793351f --- /dev/null +++ b/api/rpc/message/message.go @@ -0,0 +1,43 @@ +package message + +import ( + "fmt" + + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/grpc" +) + +// Message represents raw Protobuf message +// that can be transmitted via several +// transport protocols. +type Message interface { + // Must return gRPC message that can + // be used for gRPC protocol transmission. + ToGRPCMessage() grpc.Message + + // Must restore the message from related + // gRPC message. + // + // If gRPC message is not a related one, + // ErrUnexpectedMessageType can be returned + // to indicate this. + FromGRPCMessage(grpc.Message) error +} + +// ErrUnexpectedMessageType is an error that +// is used to indicate message mismatch. +type ErrUnexpectedMessageType struct { + exp, act any +} + +// NewUnexpectedMessageType initializes an error about message mismatch +// between act and exp. +func NewUnexpectedMessageType(act, exp any) ErrUnexpectedMessageType { + return ErrUnexpectedMessageType{ + exp: exp, + act: act, + } +} + +func (e ErrUnexpectedMessageType) Error() string { + return fmt.Sprintf("unexpected message type %T: expected %T", e.act, e.exp) +} diff --git a/api/rpc/message/test/message.go b/api/rpc/message/test/message.go new file mode 100644 index 0000000..a402756 --- /dev/null +++ b/api/rpc/message/test/message.go @@ -0,0 +1,126 @@ +package messagetest + +import ( + "encoding/json" + "errors" + "fmt" + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/message" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/util/proto/encoding" + "github.com/stretchr/testify/require" +) + +type jsonMessage interface { + json.Marshaler + json.Unmarshaler +} + +type binaryMessage interface { + StableMarshal([]byte) []byte + StableSize() int + Unmarshal([]byte) error +} + +func TestRPCMessage(t *testing.T, msgGens ...func(empty bool) message.Message) { + for _, msgGen := range msgGens { + msg := msgGen(false) + + t.Run(fmt.Sprintf("convert_%T", msg), func(t *testing.T) { + msg := msgGen(false) + + err := msg.FromGRPCMessage(100) + + require.True(t, errors.As(err, new(message.ErrUnexpectedMessageType))) + + msg2 := msgGen(true) + + err = msg2.FromGRPCMessage(msg.ToGRPCMessage()) + require.NoError(t, err) + + require.Equal(t, msg, msg2) + }) + + t.Run("encoding", func(t *testing.T) { + if jm, ok := msg.(jsonMessage); ok { + t.Run(fmt.Sprintf("JSON_%T", msg), func(t *testing.T) { + data, err := jm.MarshalJSON() + require.NoError(t, err) + + jm2 := msgGen(true).(jsonMessage) + require.NoError(t, jm2.UnmarshalJSON(data)) + + require.Equal(t, jm, jm2) + }) + } + + if bm, ok := msg.(binaryMessage); ok { + t.Run(fmt.Sprintf("%T.StableSize() does no allocations", bm), func(t *testing.T) { + require.Zero(t, testing.AllocsPerRun(1000, func() { + _ = bm.StableSize() + })) + }) + t.Run(fmt.Sprintf("Binary_%T", msg), func(t *testing.T) { + data := bm.StableMarshal(nil) + + bm2 := msgGen(true).(binaryMessage) + require.NoError(t, bm2.Unmarshal(data)) + + require.Equal(t, bm, bm2) + }) + } + t.Run("compatibility", func(t *testing.T) { + testCompatibility(t, msgGen) + }) + }) + } +} + +func testCompatibility(t *testing.T, msgGen func(empty bool) message.Message) { + compareBinary := func(t *testing.T, msg message.Message) { + am, ok := msg.(binaryMessage) + if !ok { + t.Skip() + } + + a := am.StableMarshal(nil) + b := msg.ToGRPCMessage().(encoding.ProtoMarshaler).MarshalProtobuf(nil) + if len(a) == 0 { + require.Empty(t, b) + } else { + require.Equal(t, a, b) + } + } + compareJSON := func(t *testing.T, msg message.Message) { + am, ok := msg.(jsonMessage) + if !ok { + t.Skip() + } + + a, err := am.MarshalJSON() + require.NoError(t, err) + + b, err := json.Marshal(msg.ToGRPCMessage()) + require.NoError(t, err) + + require.JSONEq(t, string(a), string(b)) + } + t.Run("empty", func(t *testing.T) { + msg := msgGen(true) + t.Run(fmt.Sprintf("Binary_%T", msg), func(t *testing.T) { + compareBinary(t, msg) + }) + t.Run(fmt.Sprintf("JSON_%T", msg), func(t *testing.T) { + compareJSON(t, msg) + }) + }) + t.Run("not empty", func(t *testing.T) { + msg := msgGen(false) + t.Run(fmt.Sprintf("Binary_%T", msg), func(t *testing.T) { + compareBinary(t, msg) + }) + t.Run(fmt.Sprintf("JSON_%T", msg), func(t *testing.T) { + compareJSON(t, msg) + }) + }) +} diff --git a/api/rpc/netmap.go b/api/rpc/netmap.go new file mode 100644 index 0000000..fe52b2e --- /dev/null +++ b/api/rpc/netmap.go @@ -0,0 +1,62 @@ +package rpc + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/common" +) + +const serviceNetmap = serviceNamePrefix + "netmap.NetmapService" + +const ( + rpcNetmapNodeInfo = "LocalNodeInfo" + rpcNetmapNetInfo = "NetworkInfo" + rpcNetmapSnapshot = "NetmapSnapshot" +) + +// LocalNodeInfo executes NetmapService.LocalNodeInfo RPC. +func LocalNodeInfo( + cli *client.Client, + req *netmap.LocalNodeInfoRequest, + opts ...client.CallOption, +) (*netmap.LocalNodeInfoResponse, error) { + resp := new(netmap.LocalNodeInfoResponse) + + err := client.SendUnary(cli, common.CallMethodInfoUnary(serviceNetmap, rpcNetmapNodeInfo), req, resp, opts...) + if err != nil { + return nil, err + } + + return resp, nil +} + +// NetworkInfo executes NetmapService.NetworkInfo RPC. +func NetworkInfo( + cli *client.Client, + req *netmap.NetworkInfoRequest, + opts ...client.CallOption, +) (*netmap.NetworkInfoResponse, error) { + resp := new(netmap.NetworkInfoResponse) + err := client.SendUnary(cli, common.CallMethodInfoUnary(serviceNetmap, rpcNetmapNetInfo), req, resp, opts...) + if err != nil { + return nil, err + } + + return resp, nil +} + +// NetMapSnapshot executes NetmapService.NetmapSnapshot RPC. +func NetMapSnapshot( + cli *client.Client, + req *netmap.SnapshotRequest, + opts ...client.CallOption, +) (*netmap.SnapshotResponse, error) { + resp := new(netmap.SnapshotResponse) + + err := client.SendUnary(cli, common.CallMethodInfoUnary(serviceNetmap, rpcNetmapSnapshot), req, resp, opts...) + if err != nil { + return nil, err + } + + return resp, nil +} diff --git a/api/rpc/object.go b/api/rpc/object.go new file mode 100644 index 0000000..b6792f0 --- /dev/null +++ b/api/rpc/object.go @@ -0,0 +1,243 @@ +package rpc + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/common" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/message" +) + +const serviceObject = serviceNamePrefix + "object.ObjectService" + +const ( + rpcObjectPut = "Put" + rpcObjectGet = "Get" + rpcObjectSearch = "Search" + rpcObjectRange = "GetRange" + rpcObjectHash = "GetRangeHash" + rpcObjectHead = "Head" + rpcObjectDelete = "Delete" + rpcObjectPutSingle = "PutSingle" + rpcObjectPatch = "Patch" +) + +// PutRequestWriter is an object.PutRequest +// message streaming component. +type PutRequestWriter struct { + wc client.MessageWriterCloser + + resp message.Message +} + +// Write writes req to the stream. +func (w *PutRequestWriter) Write(req *object.PutRequest) error { + return w.wc.WriteMessage(req) +} + +// Close closes the stream. +func (w *PutRequestWriter) Close() error { + return w.wc.Close() +} + +// PutObject executes ObjectService.Put RPC. +func PutObject( + cli *client.Client, + resp *object.PutResponse, + opts ...client.CallOption, +) (*PutRequestWriter, error) { + wc, err := client.OpenClientStream(cli, common.CallMethodInfoClientStream(serviceObject, rpcObjectPut), resp, opts...) + if err != nil { + return nil, err + } + + return &PutRequestWriter{ + wc: wc, + resp: resp, + }, nil +} + +// GetResponseReader is an object.GetResponse +// stream reader. +type GetResponseReader struct { + r client.MessageReader +} + +// Read reads response from the stream. +// +// Returns io.EOF of streaming is finished. +func (r *GetResponseReader) Read(resp *object.GetResponse) error { + return r.r.ReadMessage(resp) +} + +// GetObject executes ObjectService.Get RPC. +func GetObject( + cli *client.Client, + req *object.GetRequest, + opts ...client.CallOption, +) (*GetResponseReader, error) { + wc, err := client.OpenServerStream(cli, common.CallMethodInfoServerStream(serviceObject, rpcObjectGet), req, opts...) + if err != nil { + return nil, err + } + + return &GetResponseReader{ + r: wc, + }, nil +} + +// GetResponseReader is an object.SearchResponse +// stream reader. +type SearchResponseReader struct { + r client.MessageReader +} + +// Read reads response from the stream. +// +// Returns io.EOF of streaming is finished. +func (r *SearchResponseReader) Read(resp *object.SearchResponse) error { + return r.r.ReadMessage(resp) +} + +// SearchObjects executes ObjectService.Search RPC. +func SearchObjects( + cli *client.Client, + req *object.SearchRequest, + opts ...client.CallOption, +) (*SearchResponseReader, error) { + wc, err := client.OpenServerStream(cli, common.CallMethodInfoServerStream(serviceObject, rpcObjectSearch), req, opts...) + if err != nil { + return nil, err + } + + return &SearchResponseReader{ + r: wc, + }, nil +} + +// GetResponseReader is an object.GetRangeResponse +// stream reader. +type ObjectRangeResponseReader struct { + r client.MessageReader +} + +// Read reads response from the stream. +// +// Returns io.EOF of streaming is finished. +func (r *ObjectRangeResponseReader) Read(resp *object.GetRangeResponse) error { + return r.r.ReadMessage(resp) +} + +// GetObjectRange executes ObjectService.GetRange RPC. +func GetObjectRange( + cli *client.Client, + req *object.GetRangeRequest, + opts ...client.CallOption, +) (*ObjectRangeResponseReader, error) { + wc, err := client.OpenServerStream(cli, common.CallMethodInfoServerStream(serviceObject, rpcObjectRange), req, opts...) + if err != nil { + return nil, err + } + + return &ObjectRangeResponseReader{ + r: wc, + }, nil +} + +// HeadObject executes ObjectService.Head RPC. +func HeadObject( + cli *client.Client, + req *object.HeadRequest, + opts ...client.CallOption, +) (*object.HeadResponse, error) { + resp := new(object.HeadResponse) + + err := client.SendUnary(cli, common.CallMethodInfoUnary(serviceObject, rpcObjectHead), req, resp, opts...) + if err != nil { + return nil, err + } + + return resp, nil +} + +// DeleteObject executes ObjectService.Delete RPC. +func DeleteObject( + cli *client.Client, + req *object.DeleteRequest, + opts ...client.CallOption, +) (*object.DeleteResponse, error) { + resp := new(object.DeleteResponse) + + err := client.SendUnary(cli, common.CallMethodInfoUnary(serviceObject, rpcObjectDelete), req, resp, opts...) + if err != nil { + return nil, err + } + + return resp, nil +} + +// HashObjectRange executes ObjectService.GetRangeHash RPC. +func HashObjectRange( + cli *client.Client, + req *object.GetRangeHashRequest, + opts ...client.CallOption, +) (*object.GetRangeHashResponse, error) { + resp := new(object.GetRangeHashResponse) + + err := client.SendUnary(cli, common.CallMethodInfoUnary(serviceObject, rpcObjectHash), req, resp, opts...) + if err != nil { + return nil, err + } + + return resp, nil +} + +// PutSingleObject executes ObjectService.PutSingle RPC. +func PutSingleObject( + cli *client.Client, + req *object.PutSingleRequest, + opts ...client.CallOption, +) (*object.PutSingleResponse, error) { + resp := new(object.PutSingleResponse) + + err := client.SendUnary(cli, common.CallMethodInfoUnary(serviceObject, rpcObjectPutSingle), req, resp, opts...) + if err != nil { + return nil, err + } + + return resp, nil +} + +// PatchRequestWriter is an object.PatchRequest +// message streaming component. +type PatchRequestWriter struct { + wc client.MessageWriterCloser + + resp message.Message +} + +// Write writes req to the stream. +func (w *PatchRequestWriter) Write(req *object.PatchRequest) error { + return w.wc.WriteMessage(req) +} + +// Close closes the stream. +func (w *PatchRequestWriter) Close() error { + return w.wc.Close() +} + +// Patch executes ObjectService.Patch RPC. +func Patch( + cli *client.Client, + resp *object.PatchResponse, + opts ...client.CallOption, +) (*PatchRequestWriter, error) { + wc, err := client.OpenClientStream(cli, common.CallMethodInfoClientStream(serviceObject, rpcObjectPatch), resp, opts...) + if err != nil { + return nil, err + } + + return &PatchRequestWriter{ + wc: wc, + resp: resp, + }, nil +} diff --git a/api/rpc/session.go b/api/rpc/session.go new file mode 100644 index 0000000..2477029 --- /dev/null +++ b/api/rpc/session.go @@ -0,0 +1,28 @@ +package rpc + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/common" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" +) + +const serviceSession = serviceNamePrefix + "session.SessionService" + +const ( + rpcSessionCreate = "Create" +) + +func CreateSession( + cli *client.Client, + req *session.CreateRequest, + opts ...client.CallOption, +) (*session.CreateResponse, error) { + resp := new(session.CreateResponse) + + err := client.SendUnary(cli, common.CallMethodInfoUnary(serviceSession, rpcSessionCreate), req, resp, opts...) + if err != nil { + return nil, err + } + + return resp, nil +} diff --git a/api/session/convert.go b/api/session/convert.go new file mode 100644 index 0000000..342be4e --- /dev/null +++ b/api/session/convert.go @@ -0,0 +1,898 @@ +package session + +import ( + "fmt" + + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/acl" + aclGRPC "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/acl/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" + refsGRPC "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/message" + session "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/status" + statusGRPC "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/status/grpc" +) + +func (c *CreateRequestBody) ToGRPCMessage() grpc.Message { + var m *session.CreateRequest_Body + + if c != nil { + m = new(session.CreateRequest_Body) + + m.SetOwnerId(c.ownerID.ToGRPCMessage().(*refsGRPC.OwnerID)) + m.SetExpiration(c.expiration) + } + + return m +} + +func (c *CreateRequestBody) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*session.CreateRequest_Body) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + ownerID := v.GetOwnerId() + if ownerID == nil { + c.ownerID = nil + } else { + if c.ownerID == nil { + c.ownerID = new(refs.OwnerID) + } + + err = c.ownerID.FromGRPCMessage(ownerID) + if err != nil { + return err + } + } + + c.expiration = v.GetExpiration() + + return nil +} + +func (c *CreateRequest) ToGRPCMessage() grpc.Message { + var m *session.CreateRequest + + if c != nil { + m = new(session.CreateRequest) + + m.SetBody(c.body.ToGRPCMessage().(*session.CreateRequest_Body)) + c.RequestHeaders.ToMessage(m) + } + + return m +} + +func (c *CreateRequest) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*session.CreateRequest) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + body := v.GetBody() + if body == nil { + c.body = nil + } else { + if c.body == nil { + c.body = new(CreateRequestBody) + } + + err = c.body.FromGRPCMessage(body) + if err != nil { + return err + } + } + + return c.RequestHeaders.FromMessage(v) +} + +func (c *CreateResponseBody) ToGRPCMessage() grpc.Message { + var m *session.CreateResponse_Body + + if c != nil { + m = new(session.CreateResponse_Body) + + m.SetSessionKey(c.sessionKey) + m.SetId(c.id) + } + + return m +} + +func (c *CreateResponseBody) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*session.CreateResponse_Body) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + c.sessionKey = v.GetSessionKey() + c.id = v.GetId() + + return nil +} + +func (c *CreateResponse) ToGRPCMessage() grpc.Message { + var m *session.CreateResponse + + if c != nil { + m = new(session.CreateResponse) + + m.SetBody(c.body.ToGRPCMessage().(*session.CreateResponse_Body)) + c.ResponseHeaders.ToMessage(m) + } + + return m +} + +func (c *CreateResponse) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*session.CreateResponse) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + body := v.GetBody() + if body == nil { + c.body = nil + } else { + if c.body == nil { + c.body = new(CreateResponseBody) + } + + err = c.body.FromGRPCMessage(body) + if err != nil { + return err + } + } + + return c.ResponseHeaders.FromMessage(v) +} + +func (l *TokenLifetime) ToGRPCMessage() grpc.Message { + var m *session.SessionToken_Body_TokenLifetime + + if l != nil { + m = new(session.SessionToken_Body_TokenLifetime) + + m.SetExp(l.exp) + m.SetIat(l.iat) + m.SetNbf(l.nbf) + } + + return m +} + +func (l *TokenLifetime) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*session.SessionToken_Body_TokenLifetime) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + l.exp = v.GetExp() + l.iat = v.GetIat() + l.nbf = v.GetNbf() + + return nil +} + +func (x *XHeader) ToGRPCMessage() grpc.Message { + var m *session.XHeader + + if x != nil { + m = new(session.XHeader) + + m.SetKey(x.key) + m.SetValue(x.val) + } + + return m +} + +func (x *XHeader) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*session.XHeader) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + x.key = v.GetKey() + x.val = v.GetValue() + + return nil +} + +func XHeadersToGRPC(xs []XHeader) (res []session.XHeader) { + if xs != nil { + res = make([]session.XHeader, 0, len(xs)) + + for i := range xs { + res = append(res, *xs[i].ToGRPCMessage().(*session.XHeader)) + } + } + + return +} + +func XHeadersFromGRPC(xs []session.XHeader) (res []XHeader, err error) { + if xs != nil { + res = make([]XHeader, len(xs)) + + for i := range xs { + err = res[i].FromGRPCMessage(&xs[i]) + if err != nil { + return + } + } + } + + return +} + +func (t *Token) ToGRPCMessage() grpc.Message { + var m *session.SessionToken + + if t != nil { + m = new(session.SessionToken) + + m.SetBody(t.body.ToGRPCMessage().(*session.SessionToken_Body)) + m.SetSignature(t.sig.ToGRPCMessage().(*refsGRPC.Signature)) + } + + return m +} + +func (t *Token) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*session.SessionToken) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + body := v.GetBody() + if body == nil { + t.body = nil + } else { + if t.body == nil { + t.body = new(TokenBody) + } + + err = t.body.FromGRPCMessage(body) + if err != nil { + return err + } + } + + sig := v.GetSignature() + if sig == nil { + t.sig = nil + } else { + if t.sig == nil { + t.sig = new(refs.Signature) + } + + err = t.sig.FromGRPCMessage(sig) + if err != nil { + return err + } + } + + return nil +} + +func (r *RequestVerificationHeader) ToGRPCMessage() grpc.Message { + var m *session.RequestVerificationHeader + + if r != nil { + m = new(session.RequestVerificationHeader) + + m.SetBodySignature(r.bodySig.ToGRPCMessage().(*refsGRPC.Signature)) + m.SetMetaSignature(r.metaSig.ToGRPCMessage().(*refsGRPC.Signature)) + m.SetOriginSignature(r.originSig.ToGRPCMessage().(*refsGRPC.Signature)) + m.SetOrigin(r.origin.ToGRPCMessage().(*session.RequestVerificationHeader)) + } + + return m +} + +func (r *RequestVerificationHeader) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*session.RequestVerificationHeader) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + originSig := v.GetOriginSignature() + if originSig == nil { + r.originSig = nil + } else { + if r.originSig == nil { + r.originSig = new(refs.Signature) + } + + err = r.originSig.FromGRPCMessage(originSig) + if err != nil { + return err + } + } + + metaSig := v.GetMetaSignature() + if metaSig == nil { + r.metaSig = nil + } else { + if r.metaSig == nil { + r.metaSig = new(refs.Signature) + } + + err = r.metaSig.FromGRPCMessage(metaSig) + if err != nil { + return err + } + } + + bodySig := v.GetBodySignature() + if bodySig == nil { + r.bodySig = nil + } else { + if r.bodySig == nil { + r.bodySig = new(refs.Signature) + } + + err = r.bodySig.FromGRPCMessage(bodySig) + if err != nil { + return err + } + } + + origin := v.GetOrigin() + if origin == nil { + r.origin = nil + } else { + if r.origin == nil { + r.origin = new(RequestVerificationHeader) + } + + err = r.origin.FromGRPCMessage(origin) + if err != nil { + return err + } + } + + return nil +} + +func (r *RequestMetaHeader) ToGRPCMessage() grpc.Message { + var m *session.RequestMetaHeader + + if r != nil { + m = new(session.RequestMetaHeader) + + m.SetVersion(r.version.ToGRPCMessage().(*refsGRPC.Version)) + m.SetSessionToken(r.sessionToken.ToGRPCMessage().(*session.SessionToken)) + m.SetBearerToken(r.bearerToken.ToGRPCMessage().(*aclGRPC.BearerToken)) + m.SetXHeaders(XHeadersToGRPC(r.xHeaders)) + m.SetEpoch(r.epoch) + m.SetTtl(r.ttl) + m.SetOrigin(r.origin.ToGRPCMessage().(*session.RequestMetaHeader)) + m.SetMagicNumber(r.netMagic) + } + + return m +} + +func (r *RequestMetaHeader) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*session.RequestMetaHeader) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + version := v.GetVersion() + if version == nil { + r.version = nil + } else { + if r.version == nil { + r.version = new(refs.Version) + } + + err = r.version.FromGRPCMessage(version) + if err != nil { + return err + } + } + + sessionToken := v.GetSessionToken() + if sessionToken == nil { + r.sessionToken = nil + } else { + if r.sessionToken == nil { + r.sessionToken = new(Token) + } + + err = r.sessionToken.FromGRPCMessage(sessionToken) + if err != nil { + return err + } + } + + bearerToken := v.GetBearerToken() + if bearerToken == nil { + r.bearerToken = nil + } else { + if r.bearerToken == nil { + r.bearerToken = new(acl.BearerToken) + } + + err = r.bearerToken.FromGRPCMessage(bearerToken) + if err != nil { + return err + } + } + + origin := v.GetOrigin() + if origin == nil { + r.origin = nil + } else { + if r.origin == nil { + r.origin = new(RequestMetaHeader) + } + + err = r.origin.FromGRPCMessage(origin) + if err != nil { + return err + } + } + + r.xHeaders, err = XHeadersFromGRPC(v.GetXHeaders()) + if err != nil { + return err + } + + r.epoch = v.GetEpoch() + r.ttl = v.GetTtl() + r.netMagic = v.GetMagicNumber() + + return nil +} + +func (r *ResponseVerificationHeader) ToGRPCMessage() grpc.Message { + var m *session.ResponseVerificationHeader + + if r != nil { + m = new(session.ResponseVerificationHeader) + + m.SetBodySignature(r.bodySig.ToGRPCMessage().(*refsGRPC.Signature)) + m.SetMetaSignature(r.metaSig.ToGRPCMessage().(*refsGRPC.Signature)) + m.SetOriginSignature(r.originSig.ToGRPCMessage().(*refsGRPC.Signature)) + m.SetOrigin(r.origin.ToGRPCMessage().(*session.ResponseVerificationHeader)) + } + + return m +} + +func (r *ResponseVerificationHeader) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*session.ResponseVerificationHeader) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + originSig := v.GetOriginSignature() + if originSig == nil { + r.originSig = nil + } else { + if r.originSig == nil { + r.originSig = new(refs.Signature) + } + + err = r.originSig.FromGRPCMessage(originSig) + if err != nil { + return err + } + } + + metaSig := v.GetMetaSignature() + if metaSig == nil { + r.metaSig = nil + } else { + if r.metaSig == nil { + r.metaSig = new(refs.Signature) + } + + err = r.metaSig.FromGRPCMessage(metaSig) + if err != nil { + return err + } + } + + bodySig := v.GetBodySignature() + if bodySig == nil { + r.bodySig = nil + } else { + if r.bodySig == nil { + r.bodySig = new(refs.Signature) + } + + err = r.bodySig.FromGRPCMessage(bodySig) + if err != nil { + return err + } + } + + origin := v.GetOrigin() + if origin == nil { + r.origin = nil + } else { + if r.origin == nil { + r.origin = new(ResponseVerificationHeader) + } + + err = r.origin.FromGRPCMessage(origin) + if err != nil { + return err + } + } + + return nil +} + +func (r *ResponseMetaHeader) ToGRPCMessage() grpc.Message { + var m *session.ResponseMetaHeader + + if r != nil { + m = new(session.ResponseMetaHeader) + + m.SetVersion(r.version.ToGRPCMessage().(*refsGRPC.Version)) + m.SetXHeaders(XHeadersToGRPC(r.xHeaders)) + m.SetEpoch(r.epoch) + m.SetTtl(r.ttl) + m.SetOrigin(r.origin.ToGRPCMessage().(*session.ResponseMetaHeader)) + m.SetStatus(r.status.ToGRPCMessage().(*statusGRPC.Status)) + } + + return m +} + +func (r *ResponseMetaHeader) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*session.ResponseMetaHeader) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + version := v.GetVersion() + if version == nil { + r.version = nil + } else { + if r.version == nil { + r.version = new(refs.Version) + } + + err = r.version.FromGRPCMessage(version) + if err != nil { + return err + } + } + + origin := v.GetOrigin() + if origin == nil { + r.origin = nil + } else { + if r.origin == nil { + r.origin = new(ResponseMetaHeader) + } + + err = r.origin.FromGRPCMessage(origin) + if err != nil { + return err + } + } + + st := v.GetStatus() + if st == nil { + r.status = nil + } else { + if r.status == nil { + r.status = new(status.Status) + } + + err = r.status.FromGRPCMessage(st) + if err != nil { + return err + } + } + + r.xHeaders, err = XHeadersFromGRPC(v.GetXHeaders()) + if err != nil { + return err + } + + r.epoch = v.GetEpoch() + r.ttl = v.GetTtl() + + return nil +} + +func ObjectSessionVerbToGRPCField(v ObjectSessionVerb) session.ObjectSessionContext_Verb { + switch v { + case ObjectVerbPut: + return session.ObjectSessionContext_PUT + case ObjectVerbGet: + return session.ObjectSessionContext_GET + case ObjectVerbHead: + return session.ObjectSessionContext_HEAD + case ObjectVerbSearch: + return session.ObjectSessionContext_SEARCH + case ObjectVerbDelete: + return session.ObjectSessionContext_DELETE + case ObjectVerbRange: + return session.ObjectSessionContext_RANGE + case ObjectVerbRangeHash: + return session.ObjectSessionContext_RANGEHASH + case ObjectVerbPatch: + return session.ObjectSessionContext_PATCH + default: + return session.ObjectSessionContext_VERB_UNSPECIFIED + } +} + +func ObjectSessionVerbFromGRPCField(v session.ObjectSessionContext_Verb) ObjectSessionVerb { + switch v { + case session.ObjectSessionContext_PUT: + return ObjectVerbPut + case session.ObjectSessionContext_GET: + return ObjectVerbGet + case session.ObjectSessionContext_HEAD: + return ObjectVerbHead + case session.ObjectSessionContext_SEARCH: + return ObjectVerbSearch + case session.ObjectSessionContext_DELETE: + return ObjectVerbDelete + case session.ObjectSessionContext_RANGE: + return ObjectVerbRange + case session.ObjectSessionContext_RANGEHASH: + return ObjectVerbRangeHash + case session.ObjectSessionContext_PATCH: + return ObjectVerbPatch + default: + return ObjectVerbUnknown + } +} + +func (c *ObjectSessionContext) ToGRPCMessage() grpc.Message { + var m *session.ObjectSessionContext + + if c != nil { + m = new(session.ObjectSessionContext) + + m.SetVerb(ObjectSessionVerbToGRPCField(c.verb)) + m.SetTarget(&session.ObjectSessionContext_Target{ + Container: c.cnr.ToGRPCMessage().(*refsGRPC.ContainerID), + Objects: refs.ObjectIDListToGRPCMessage(c.objs), + }) + } + + return m +} + +func (c *ObjectSessionContext) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*session.ObjectSessionContext) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + cnr := v.GetTarget().GetContainer() + if cnr == nil { + c.cnr = nil + } else { + if c.cnr == nil { + c.cnr = new(refs.ContainerID) + } + + err = c.cnr.FromGRPCMessage(cnr) + if err != nil { + return err + } + } + + c.objs, err = refs.ObjectIDListFromGRPCMessage(v.GetTarget().GetObjects()) + if err != nil { + return err + } + + c.verb = ObjectSessionVerbFromGRPCField(v.GetVerb()) + + return nil +} + +func (t *TokenBody) ToGRPCMessage() grpc.Message { + var m *session.SessionToken_Body + + if t != nil { + m = new(session.SessionToken_Body) + + switch typ := t.ctx.(type) { + default: + panic(fmt.Sprintf("unknown session context %T", typ)) + case nil: + m.Context = nil + case *ObjectSessionContext: + m.SetObject(typ.ToGRPCMessage().(*session.ObjectSessionContext)) + case *ContainerSessionContext: + m.SetContainer(typ.ToGRPCMessage().(*session.ContainerSessionContext)) + } + + m.SetOwnerId(t.ownerID.ToGRPCMessage().(*refsGRPC.OwnerID)) + m.SetId(t.id) + m.SetSessionKey(t.sessionKey) + m.SetLifetime(t.lifetime.ToGRPCMessage().(*session.SessionToken_Body_TokenLifetime)) + } + + return m +} + +func (t *TokenBody) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*session.SessionToken_Body) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + t.ctx = nil + + switch val := v.GetContext().(type) { + default: + err = fmt.Errorf("unknown session context %T", val) + case nil: + case *session.SessionToken_Body_Object: + ctx, ok := t.ctx.(*ObjectSessionContext) + if !ok { + ctx = new(ObjectSessionContext) + t.ctx = ctx + } + + err = ctx.FromGRPCMessage(val.Object) + case *session.SessionToken_Body_Container: + ctx, ok := t.ctx.(*ContainerSessionContext) + if !ok { + ctx = new(ContainerSessionContext) + t.ctx = ctx + } + + err = ctx.FromGRPCMessage(val.Container) + } + + if err != nil { + return err + } + + ownerID := v.GetOwnerId() + if ownerID == nil { + t.ownerID = nil + } else { + if t.ownerID == nil { + t.ownerID = new(refs.OwnerID) + } + + err = t.ownerID.FromGRPCMessage(ownerID) + if err != nil { + return err + } + } + + lifetime := v.GetLifetime() + if lifetime == nil { + t.lifetime = nil + } else { + if t.lifetime == nil { + t.lifetime = new(TokenLifetime) + } + + err = t.lifetime.FromGRPCMessage(lifetime) + if err != nil { + return err + } + } + + t.id = v.GetId() + t.sessionKey = v.GetSessionKey() + + return nil +} + +// ContainerSessionVerbToGRPCField converts ContainerSessionVerb +// to gRPC-generated session.ContainerSessionContext_Verb. +// +// If v is outside of the ContainerSessionVerb enum, +// session.ContainerSessionContext_VERB_UNSPECIFIED is returned. +func ContainerSessionVerbToGRPCField(v ContainerSessionVerb) session.ContainerSessionContext_Verb { + switch v { + default: + return session.ContainerSessionContext_VERB_UNSPECIFIED + case ContainerVerbPut: + return session.ContainerSessionContext_PUT + case ContainerVerbDelete: + return session.ContainerSessionContext_DELETE + case ContainerVerbSetEACL: + return session.ContainerSessionContext_SETEACL + } +} + +// ContainerSessionVerbFromGRPCField converts gRPC-generated +// session.ContainerSessionContext_Verb to ContainerSessionVerb. +// +// If v is outside of the session.ContainerSessionContext_Verb enum, +// ContainerVerbUnknown is returned. +func ContainerSessionVerbFromGRPCField(v session.ContainerSessionContext_Verb) ContainerSessionVerb { + switch v { + default: + return ContainerVerbUnknown + case session.ContainerSessionContext_PUT: + return ContainerVerbPut + case session.ContainerSessionContext_DELETE: + return ContainerVerbDelete + case session.ContainerSessionContext_SETEACL: + return ContainerVerbSetEACL + } +} + +// ToGRPCMessage converts ContainerSessionContext to gRPC-generated +// session.ContainerSessionContext message. +func (x *ContainerSessionContext) ToGRPCMessage() grpc.Message { + var m *session.ContainerSessionContext + + if x != nil { + m = new(session.ContainerSessionContext) + + m.SetVerb(ContainerSessionVerbToGRPCField(x.verb)) + m.SetWildcard(x.wildcard) + m.SetContainerId(x.cid.ToGRPCMessage().(*refsGRPC.ContainerID)) + } + + return m +} + +// FromGRPCMessage tries to restore ContainerSessionContext from grpc.Message. +// +// Returns message.ErrUnexpectedMessageType if m is not +// a gRPC-generated session.ContainerSessionContext message. +func (x *ContainerSessionContext) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*session.ContainerSessionContext) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + cid := v.GetContainerId() + if cid == nil { + x.cid = nil + } else { + if x.cid == nil { + x.cid = new(refs.ContainerID) + } + + err = x.cid.FromGRPCMessage(cid) + if err != nil { + return err + } + } + + x.verb = ContainerSessionVerbFromGRPCField(v.GetVerb()) + x.wildcard = v.GetWildcard() + + return nil +} diff --git a/api/session/grpc/service_frostfs.pb.go b/api/session/grpc/service_frostfs.pb.go new file mode 100644 index 0000000000000000000000000000000000000000..aad809c9185b2d03f643f48111379da312f2d373 GIT binary patch literal 20200 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 A?*IS* literal 0 HcmV?d00001 diff --git a/api/session/grpc/service_frostfs_fuzz.go b/api/session/grpc/service_frostfs_fuzz.go new file mode 100644 index 0000000..759361c --- /dev/null +++ b/api/session/grpc/service_frostfs_fuzz.go @@ -0,0 +1,45 @@ +//go:build gofuzz +// +build gofuzz + +// Code generated by protoc-gen-go-frostfs. DO NOT EDIT. + +package session + +func DoFuzzProtoCreateRequest(data []byte) int { + msg := new(CreateRequest) + if err := msg.UnmarshalProtobuf(data); err != nil { + return 0 + } + _ = msg.MarshalProtobuf(nil) + return 1 +} +func DoFuzzJSONCreateRequest(data []byte) int { + msg := new(CreateRequest) + if err := msg.UnmarshalJSON(data); err != nil { + return 0 + } + _, err := msg.MarshalJSON() + if err != nil { + panic(err) + } + return 1 +} +func DoFuzzProtoCreateResponse(data []byte) int { + msg := new(CreateResponse) + if err := msg.UnmarshalProtobuf(data); err != nil { + return 0 + } + _ = msg.MarshalProtobuf(nil) + return 1 +} +func DoFuzzJSONCreateResponse(data []byte) int { + msg := new(CreateResponse) + if err := msg.UnmarshalJSON(data); err != nil { + return 0 + } + _, err := msg.MarshalJSON() + if err != nil { + panic(err) + } + return 1 +} diff --git a/api/session/grpc/service_frostfs_test.go b/api/session/grpc/service_frostfs_test.go new file mode 100644 index 0000000..fc8664e --- /dev/null +++ b/api/session/grpc/service_frostfs_test.go @@ -0,0 +1,31 @@ +//go:build gofuzz +// +build gofuzz + +// Code generated by protoc-gen-go-frostfs. DO NOT EDIT. + +package session + +import ( + testing "testing" +) + +func FuzzProtoCreateRequest(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzProtoCreateRequest(data) + }) +} +func FuzzJSONCreateRequest(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzJSONCreateRequest(data) + }) +} +func FuzzProtoCreateResponse(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzProtoCreateResponse(data) + }) +} +func FuzzJSONCreateResponse(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzJSONCreateResponse(data) + }) +} diff --git a/api/session/grpc/service_grpc.pb.go b/api/session/grpc/service_grpc.pb.go new file mode 100644 index 0000000000000000000000000000000000000000..6073111a36083bca0fdbec0a4541e419db3ab6aa GIT binary patch literal 4116 zcmds4U2oeq6n&0<#hnLqa^TQehM|CqU?|*lGq%P>oa|*70!E^2p|YrwlwG69f8V*J zWLt@o6a)6MAPH>o@_w9izcd`uSf`5Ss#HcgmD1gYDx;lFPVnqxu21HsN(8-|(&hA; zF5XS9MKm1JN*SB$(vJAc$$=}h`ceEOPWO*#|7Z2HID0M5_}uE+Bx*#m%7<22);naY z_+nOhqJ(!SiYl3Wl5<6kOcdqIN*hOUbd>1QsV|Ot&4*re#2TnK*Lq$kG1rAG=R%vg z*No!?VcVz9hyD~&)=5`CEf$V@Q9t51t{1r_{7OpnvdRl};_{^;X%UA*P~P{i@H5af=_JbDbMR zIKTQhKKWI9I?lu?X+s5wHX;I4*3m7Ud(~oASB&Pz0P@8C85n*YHG)8S7RZ?eT5iWi zLDTK~x+p#lX}7pg6I;LnA&z-*|>l%cZ@AuRb5P_hH63MC(R~y!Z2WIhu)z>C)`?>PlO!bbj)h5!FRRGvG9jj=lgL3he&%lf zFn2I$l&eiiuMYY3HA(KbR^x<@4+-_@zs8Pn(Y2$|IcHVeQV{^|M@K-I&k~U&Vp6X3 zC&fG>fjS@^u6AY@bk+^0pcD%8j9H`aU@tG&dW#aidP1Y4`z><*E)Ezdq;S_L(~L?) ztK(L{#g1<;w*q=w6olbWs3kfH8YxnV>_XQ?N@{tBDR)zDk5zieCi}wu27ha5&^Vfo zoEN#<94hD5)i&M!7v&sEcvs5X>hyK|e7OR^7g26Wxl@6c6x49rl`HiKdCbBsXMxhD zt$u@*wm-BjAb#=At}Op82Alv*ckp>1b_H?4{Va?9f+0F?45+vCW3=fARBBAYHj7o- z^Ig!xYGtMlWi2h`25r3qCVDLwDCz7Gq&}H_n)_9R>xct8hVDTzEKI!bay0{rAZnx;kTt7=VfC43D|Sl##rRcM`)#A} zowAA7wQ~nYe&uZ>+CKXm)|En;nC)(3{(3*~>&&AWo2rC3xOh*rA28(>jc5~9IrK9h z-AyUYhV3ac*`1-B_ine7m%{^94~9pm|81+sDLlaS{+n-U{TLAYKAk@r6bM?xU0i~@ zeX*OC92lkzMoC^~nmv5=IJ!*3e=M#X>&U-$0Q`V{{oB9Ec(o6TWx!p5w{z|-=pJZb&|$Q# za20xxwo9GnS&q-KTJe4yUb3o9KU&F$F9n@w+LxP9&m0Kyp(!<{bws_FURHXbzNyA* ztnni(sa+hJ)Qr*Q`;ZOqLUu%d{q3U--y73MoQ{o1V?SgxTRCd&_)LAiF|hbO{_$UU c%Yen!WO(3B@;N+^sdN&-KL3slC+?$v0Q;Mfv;Y7A literal 0 HcmV?d00001 diff --git a/api/session/grpc/types_frostfs.pb.go b/api/session/grpc/types_frostfs.pb.go new file mode 100644 index 0000000000000000000000000000000000000000..c530ed904cb8dd8b2452a79a08aa871724ae1e3e GIT binary patch literal 70740 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 aAzu>}C25y?CXPS}AszF@Lbb(&&Hn>EK;t3+ literal 0 HcmV?d00001 diff --git a/api/session/grpc/types_frostfs_fuzz.go b/api/session/grpc/types_frostfs_fuzz.go new file mode 100644 index 0000000..fae4a05 --- /dev/null +++ b/api/session/grpc/types_frostfs_fuzz.go @@ -0,0 +1,159 @@ +//go:build gofuzz +// +build gofuzz + +// Code generated by protoc-gen-go-frostfs. DO NOT EDIT. + +package session + +func DoFuzzProtoObjectSessionContext(data []byte) int { + msg := new(ObjectSessionContext) + if err := msg.UnmarshalProtobuf(data); err != nil { + return 0 + } + _ = msg.MarshalProtobuf(nil) + return 1 +} +func DoFuzzJSONObjectSessionContext(data []byte) int { + msg := new(ObjectSessionContext) + if err := msg.UnmarshalJSON(data); err != nil { + return 0 + } + _, err := msg.MarshalJSON() + if err != nil { + panic(err) + } + return 1 +} +func DoFuzzProtoContainerSessionContext(data []byte) int { + msg := new(ContainerSessionContext) + if err := msg.UnmarshalProtobuf(data); err != nil { + return 0 + } + _ = msg.MarshalProtobuf(nil) + return 1 +} +func DoFuzzJSONContainerSessionContext(data []byte) int { + msg := new(ContainerSessionContext) + if err := msg.UnmarshalJSON(data); err != nil { + return 0 + } + _, err := msg.MarshalJSON() + if err != nil { + panic(err) + } + return 1 +} +func DoFuzzProtoSessionToken(data []byte) int { + msg := new(SessionToken) + if err := msg.UnmarshalProtobuf(data); err != nil { + return 0 + } + _ = msg.MarshalProtobuf(nil) + return 1 +} +func DoFuzzJSONSessionToken(data []byte) int { + msg := new(SessionToken) + if err := msg.UnmarshalJSON(data); err != nil { + return 0 + } + _, err := msg.MarshalJSON() + if err != nil { + panic(err) + } + return 1 +} +func DoFuzzProtoXHeader(data []byte) int { + msg := new(XHeader) + if err := msg.UnmarshalProtobuf(data); err != nil { + return 0 + } + _ = msg.MarshalProtobuf(nil) + return 1 +} +func DoFuzzJSONXHeader(data []byte) int { + msg := new(XHeader) + if err := msg.UnmarshalJSON(data); err != nil { + return 0 + } + _, err := msg.MarshalJSON() + if err != nil { + panic(err) + } + return 1 +} +func DoFuzzProtoRequestMetaHeader(data []byte) int { + msg := new(RequestMetaHeader) + if err := msg.UnmarshalProtobuf(data); err != nil { + return 0 + } + _ = msg.MarshalProtobuf(nil) + return 1 +} +func DoFuzzJSONRequestMetaHeader(data []byte) int { + msg := new(RequestMetaHeader) + if err := msg.UnmarshalJSON(data); err != nil { + return 0 + } + _, err := msg.MarshalJSON() + if err != nil { + panic(err) + } + return 1 +} +func DoFuzzProtoResponseMetaHeader(data []byte) int { + msg := new(ResponseMetaHeader) + if err := msg.UnmarshalProtobuf(data); err != nil { + return 0 + } + _ = msg.MarshalProtobuf(nil) + return 1 +} +func DoFuzzJSONResponseMetaHeader(data []byte) int { + msg := new(ResponseMetaHeader) + if err := msg.UnmarshalJSON(data); err != nil { + return 0 + } + _, err := msg.MarshalJSON() + if err != nil { + panic(err) + } + return 1 +} +func DoFuzzProtoRequestVerificationHeader(data []byte) int { + msg := new(RequestVerificationHeader) + if err := msg.UnmarshalProtobuf(data); err != nil { + return 0 + } + _ = msg.MarshalProtobuf(nil) + return 1 +} +func DoFuzzJSONRequestVerificationHeader(data []byte) int { + msg := new(RequestVerificationHeader) + if err := msg.UnmarshalJSON(data); err != nil { + return 0 + } + _, err := msg.MarshalJSON() + if err != nil { + panic(err) + } + return 1 +} +func DoFuzzProtoResponseVerificationHeader(data []byte) int { + msg := new(ResponseVerificationHeader) + if err := msg.UnmarshalProtobuf(data); err != nil { + return 0 + } + _ = msg.MarshalProtobuf(nil) + return 1 +} +func DoFuzzJSONResponseVerificationHeader(data []byte) int { + msg := new(ResponseVerificationHeader) + if err := msg.UnmarshalJSON(data); err != nil { + return 0 + } + _, err := msg.MarshalJSON() + if err != nil { + panic(err) + } + return 1 +} diff --git a/api/session/grpc/types_frostfs_test.go b/api/session/grpc/types_frostfs_test.go new file mode 100644 index 0000000..5c9b6c2 --- /dev/null +++ b/api/session/grpc/types_frostfs_test.go @@ -0,0 +1,91 @@ +//go:build gofuzz +// +build gofuzz + +// Code generated by protoc-gen-go-frostfs. DO NOT EDIT. + +package session + +import ( + testing "testing" +) + +func FuzzProtoObjectSessionContext(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzProtoObjectSessionContext(data) + }) +} +func FuzzJSONObjectSessionContext(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzJSONObjectSessionContext(data) + }) +} +func FuzzProtoContainerSessionContext(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzProtoContainerSessionContext(data) + }) +} +func FuzzJSONContainerSessionContext(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzJSONContainerSessionContext(data) + }) +} +func FuzzProtoSessionToken(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzProtoSessionToken(data) + }) +} +func FuzzJSONSessionToken(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzJSONSessionToken(data) + }) +} +func FuzzProtoXHeader(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzProtoXHeader(data) + }) +} +func FuzzJSONXHeader(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzJSONXHeader(data) + }) +} +func FuzzProtoRequestMetaHeader(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzProtoRequestMetaHeader(data) + }) +} +func FuzzJSONRequestMetaHeader(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzJSONRequestMetaHeader(data) + }) +} +func FuzzProtoResponseMetaHeader(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzProtoResponseMetaHeader(data) + }) +} +func FuzzJSONResponseMetaHeader(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzJSONResponseMetaHeader(data) + }) +} +func FuzzProtoRequestVerificationHeader(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzProtoRequestVerificationHeader(data) + }) +} +func FuzzJSONRequestVerificationHeader(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzJSONRequestVerificationHeader(data) + }) +} +func FuzzProtoResponseVerificationHeader(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzProtoResponseVerificationHeader(data) + }) +} +func FuzzJSONResponseVerificationHeader(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzJSONResponseVerificationHeader(data) + }) +} diff --git a/api/session/json.go b/api/session/json.go new file mode 100644 index 0000000..92602ea --- /dev/null +++ b/api/session/json.go @@ -0,0 +1,86 @@ +package session + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/message" + session "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session/grpc" +) + +func (c *ObjectSessionContext) MarshalJSON() ([]byte, error) { + return message.MarshalJSON(c) +} + +func (c *ObjectSessionContext) UnmarshalJSON(data []byte) error { + return message.UnmarshalJSON(c, data, new(session.ObjectSessionContext)) +} + +func (l *TokenLifetime) MarshalJSON() ([]byte, error) { + return message.MarshalJSON(l) +} + +func (l *TokenLifetime) UnmarshalJSON(data []byte) error { + return message.UnmarshalJSON(l, data, new(session.SessionToken_Body_TokenLifetime)) +} + +func (t *TokenBody) MarshalJSON() ([]byte, error) { + return message.MarshalJSON(t) +} + +func (t *TokenBody) UnmarshalJSON(data []byte) error { + return message.UnmarshalJSON(t, data, new(session.SessionToken_Body)) +} + +func (t *Token) MarshalJSON() ([]byte, error) { + return message.MarshalJSON(t) +} + +func (t *Token) UnmarshalJSON(data []byte) error { + return message.UnmarshalJSON(t, data, new(session.SessionToken)) +} + +func (x *XHeader) MarshalJSON() ([]byte, error) { + return message.MarshalJSON(x) +} + +func (x *XHeader) UnmarshalJSON(data []byte) error { + return message.UnmarshalJSON(x, data, new(session.XHeader)) +} + +func (r *RequestMetaHeader) MarshalJSON() ([]byte, error) { + return message.MarshalJSON(r) +} + +func (r *RequestMetaHeader) UnmarshalJSON(data []byte) error { + return message.UnmarshalJSON(r, data, new(session.RequestMetaHeader)) +} + +func (r *RequestVerificationHeader) MarshalJSON() ([]byte, error) { + return message.MarshalJSON(r) +} + +func (r *RequestVerificationHeader) UnmarshalJSON(data []byte) error { + return message.UnmarshalJSON(r, data, new(session.RequestVerificationHeader)) +} + +func (r *ResponseMetaHeader) MarshalJSON() ([]byte, error) { + return message.MarshalJSON(r) +} + +func (r *ResponseMetaHeader) UnmarshalJSON(data []byte) error { + return message.UnmarshalJSON(r, data, new(session.ResponseMetaHeader)) +} + +func (r *ResponseVerificationHeader) MarshalJSON() ([]byte, error) { + return message.MarshalJSON(r) +} + +func (r *ResponseVerificationHeader) UnmarshalJSON(data []byte) error { + return message.UnmarshalJSON(r, data, new(session.ResponseVerificationHeader)) +} + +func (x *ContainerSessionContext) MarshalJSON() ([]byte, error) { + return message.MarshalJSON(x) +} + +func (x *ContainerSessionContext) UnmarshalJSON(data []byte) error { + return message.UnmarshalJSON(x, data, new(session.ContainerSessionContext)) +} diff --git a/api/session/marshal.go b/api/session/marshal.go new file mode 100644 index 0000000..d4838b2 --- /dev/null +++ b/api/session/marshal.go @@ -0,0 +1,536 @@ +package session + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/message" + session "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/util/proto" +) + +const ( + createReqBodyOwnerField = 1 + createReqBodyExpirationField = 2 + + createRespBodyIDField = 1 + createRespBodyKeyField = 2 + + xheaderKeyField = 1 + xheaderValueField = 2 + + lifetimeExpirationField = 1 + lifetimeNotValidBeforeField = 2 + lifetimeIssuedAtField = 3 + + objectCtxVerbField = 1 + objectCtxTargetField = 2 + + sessionTokenBodyIDField = 1 + sessionTokenBodyOwnerField = 2 + sessionTokenBodyLifetimeField = 3 + sessionTokenBodyKeyField = 4 + sessionTokenBodyObjectCtxField = 5 + sessionTokenBodyCnrCtxField = 6 + + sessionTokenBodyField = 1 + sessionTokenSignatureField = 2 + + reqMetaHeaderVersionField = 1 + reqMetaHeaderEpochField = 2 + reqMetaHeaderTTLField = 3 + reqMetaHeaderXHeadersField = 4 + reqMetaHeaderSessionTokenField = 5 + reqMetaHeaderBearerTokenField = 6 + reqMetaHeaderOriginField = 7 + reqMetaHeaderNetMagicField = 8 + + reqVerifHeaderBodySignatureField = 1 + reqVerifHeaderMetaSignatureField = 2 + reqVerifHeaderOriginSignatureField = 3 + reqVerifHeaderOriginField = 4 + + respMetaHeaderVersionField = 1 + respMetaHeaderEpochField = 2 + respMetaHeaderTTLField = 3 + respMetaHeaderXHeadersField = 4 + respMetaHeaderOriginField = 5 + respMetaHeaderStatusField = 6 + + respVerifHeaderBodySignatureField = 1 + respVerifHeaderMetaSignatureField = 2 + respVerifHeaderOriginSignatureField = 3 + respVerifHeaderOriginField = 4 +) + +func (c *CreateRequestBody) StableMarshal(buf []byte) []byte { + if c == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, c.StableSize()) + } + + var offset int + + offset += proto.NestedStructureMarshal(createReqBodyOwnerField, buf[offset:], c.ownerID) + proto.UInt64Marshal(createReqBodyExpirationField, buf[offset:], c.expiration) + + return buf +} + +func (c *CreateRequestBody) StableSize() (size int) { + if c == nil { + return 0 + } + + size += proto.NestedStructureSize(createReqBodyOwnerField, c.ownerID) + size += proto.UInt64Size(createReqBodyExpirationField, c.expiration) + + return size +} + +func (c *CreateRequestBody) Unmarshal(data []byte) error { + return message.Unmarshal(c, data, new(session.CreateRequest_Body)) +} + +func (c *CreateResponseBody) StableMarshal(buf []byte) []byte { + if c == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, c.StableSize()) + } + + var offset int + + offset += proto.BytesMarshal(createRespBodyIDField, buf[offset:], c.id) + proto.BytesMarshal(createRespBodyKeyField, buf[offset:], c.sessionKey) + + return buf +} + +func (c *CreateResponseBody) StableSize() (size int) { + if c == nil { + return 0 + } + + size += proto.BytesSize(createRespBodyIDField, c.id) + size += proto.BytesSize(createRespBodyKeyField, c.sessionKey) + + return size +} + +func (c *CreateResponseBody) Unmarshal(data []byte) error { + return message.Unmarshal(c, data, new(session.CreateResponse_Body)) +} + +func (x *XHeader) StableMarshal(buf []byte) []byte { + if x == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, x.StableSize()) + } + + var offset int + + offset += proto.StringMarshal(xheaderKeyField, buf[offset:], x.key) + proto.StringMarshal(xheaderValueField, buf[offset:], x.val) + + return buf +} + +func (x *XHeader) StableSize() (size int) { + if x == nil { + return 0 + } + + size += proto.StringSize(xheaderKeyField, x.key) + size += proto.StringSize(xheaderValueField, x.val) + + return size +} + +func (x *XHeader) Unmarshal(data []byte) error { + return message.Unmarshal(x, data, new(session.XHeader)) +} + +func (l *TokenLifetime) StableMarshal(buf []byte) []byte { + if l == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, l.StableSize()) + } + + var offset int + + offset += proto.UInt64Marshal(lifetimeExpirationField, buf[offset:], l.exp) + offset += proto.UInt64Marshal(lifetimeNotValidBeforeField, buf[offset:], l.nbf) + proto.UInt64Marshal(lifetimeIssuedAtField, buf[offset:], l.iat) + + return buf +} + +func (l *TokenLifetime) StableSize() (size int) { + if l == nil { + return 0 + } + + size += proto.UInt64Size(lifetimeExpirationField, l.exp) + size += proto.UInt64Size(lifetimeNotValidBeforeField, l.nbf) + size += proto.UInt64Size(lifetimeIssuedAtField, l.iat) + + return size +} + +func (l *TokenLifetime) Unmarshal(data []byte) error { + return message.Unmarshal(l, data, new(session.SessionToken_Body_TokenLifetime)) +} + +func (c *ObjectSessionContext) StableMarshal(buf []byte) []byte { + if c == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, c.StableSize()) + } + + offset := proto.EnumMarshal(objectCtxVerbField, buf, int32(c.verb)) + proto.NestedStructureMarshalUnchecked(objectCtxTargetField, buf[offset:], objectSessionContextTarget{ + cnr: c.cnr, + objs: c.objs, + }) + + return buf +} + +func (c *ObjectSessionContext) StableSize() (size int) { + if c == nil { + return 0 + } + + size += proto.EnumSize(objectCtxVerbField, int32(c.verb)) + size += proto.NestedStructureSizeUnchecked(objectCtxTargetField, objectSessionContextTarget{ + cnr: c.cnr, + objs: c.objs, + }) + + return size +} + +func (c *ObjectSessionContext) Unmarshal(data []byte) error { + return message.Unmarshal(c, data, new(session.ObjectSessionContext)) +} + +const ( + _ = iota + cnrCtxVerbFNum + cnrCtxWildcardFNum + cnrCtxCidFNum +) + +func (x *ContainerSessionContext) StableMarshal(buf []byte) []byte { + if x == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, x.StableSize()) + } + + var offset int + + offset += proto.EnumMarshal(cnrCtxVerbFNum, buf[offset:], int32(ContainerSessionVerbToGRPCField(x.verb))) + offset += proto.BoolMarshal(cnrCtxWildcardFNum, buf[offset:], x.wildcard) + proto.NestedStructureMarshal(cnrCtxCidFNum, buf[offset:], x.cid) + + return buf +} + +func (x *ContainerSessionContext) StableSize() (size int) { + if x == nil { + return 0 + } + + size += proto.EnumSize(cnrCtxVerbFNum, int32(ContainerSessionVerbToGRPCField(x.verb))) + size += proto.BoolSize(cnrCtxWildcardFNum, x.wildcard) + size += proto.NestedStructureSize(cnrCtxCidFNum, x.cid) + + return size +} + +func (x *ContainerSessionContext) Unmarshal(data []byte) error { + return message.Unmarshal(x, data, new(session.ContainerSessionContext)) +} + +func (t *TokenBody) StableMarshal(buf []byte) []byte { + if t == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, t.StableSize()) + } + + var offset int + + offset += proto.BytesMarshal(sessionTokenBodyIDField, buf[offset:], t.id) + offset += proto.NestedStructureMarshal(sessionTokenBodyOwnerField, buf[offset:], t.ownerID) + offset += proto.NestedStructureMarshal(sessionTokenBodyLifetimeField, buf[offset:], t.lifetime) + offset += proto.BytesMarshal(sessionTokenBodyKeyField, buf[offset:], t.sessionKey) + + if t.ctx != nil { + switch v := t.ctx.(type) { + case *ObjectSessionContext: + proto.NestedStructureMarshal(sessionTokenBodyObjectCtxField, buf[offset:], v) + case *ContainerSessionContext: + proto.NestedStructureMarshal(sessionTokenBodyCnrCtxField, buf[offset:], v) + default: + panic("cannot marshal unknown session token context") + } + } + + return buf +} + +func (t *TokenBody) StableSize() (size int) { + if t == nil { + return 0 + } + + size += proto.BytesSize(sessionTokenBodyIDField, t.id) + size += proto.NestedStructureSize(sessionTokenBodyOwnerField, t.ownerID) + size += proto.NestedStructureSize(sessionTokenBodyLifetimeField, t.lifetime) + size += proto.BytesSize(sessionTokenBodyKeyField, t.sessionKey) + + if t.ctx != nil { + switch v := t.ctx.(type) { + case *ObjectSessionContext: + size += proto.NestedStructureSize(sessionTokenBodyObjectCtxField, v) + case *ContainerSessionContext: + size += proto.NestedStructureSize(sessionTokenBodyCnrCtxField, v) + default: + panic("cannot marshal unknown session token context") + } + } + + return size +} + +func (t *TokenBody) Unmarshal(data []byte) error { + return message.Unmarshal(t, data, new(session.SessionToken_Body)) +} + +func (t *Token) StableMarshal(buf []byte) []byte { + if t == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, t.StableSize()) + } + + var offset int + + offset += proto.NestedStructureMarshal(sessionTokenBodyField, buf[offset:], t.body) + proto.NestedStructureMarshal(sessionTokenSignatureField, buf[offset:], t.sig) + + return buf +} + +func (t *Token) StableSize() (size int) { + if t == nil { + return 0 + } + + size += proto.NestedStructureSize(sessionTokenBodyField, t.body) + size += proto.NestedStructureSize(sessionTokenSignatureField, t.sig) + + return size +} + +func (t *Token) Unmarshal(data []byte) error { + return message.Unmarshal(t, data, new(session.SessionToken)) +} + +func (r *RequestMetaHeader) StableMarshal(buf []byte) []byte { + if r == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, r.StableSize()) + } + + var offset int + + offset += proto.NestedStructureMarshal(reqMetaHeaderVersionField, buf[offset:], r.version) + offset += proto.UInt64Marshal(reqMetaHeaderEpochField, buf[offset:], r.epoch) + offset += proto.UInt32Marshal(reqMetaHeaderTTLField, buf[offset:], r.ttl) + + for i := range r.xHeaders { + offset += proto.NestedStructureMarshal(reqMetaHeaderXHeadersField, buf[offset:], &r.xHeaders[i]) + } + + offset += proto.NestedStructureMarshal(reqMetaHeaderSessionTokenField, buf[offset:], r.sessionToken) + offset += proto.NestedStructureMarshal(reqMetaHeaderBearerTokenField, buf[offset:], r.bearerToken) + offset += proto.NestedStructureMarshal(reqMetaHeaderOriginField, buf[offset:], r.origin) + proto.UInt64Marshal(reqMetaHeaderNetMagicField, buf[offset:], r.netMagic) + + return buf +} + +func (r *RequestMetaHeader) StableSize() (size int) { + if r == nil { + return 0 + } + + if r.version != nil { + size += proto.NestedStructureSize(reqMetaHeaderVersionField, r.version) + } + + size += proto.UInt64Size(reqMetaHeaderEpochField, r.epoch) + size += proto.UInt32Size(reqMetaHeaderTTLField, r.ttl) + + for i := range r.xHeaders { + size += proto.NestedStructureSize(reqMetaHeaderXHeadersField, &r.xHeaders[i]) + } + + size += proto.NestedStructureSize(reqMetaHeaderSessionTokenField, r.sessionToken) + size += proto.NestedStructureSize(reqMetaHeaderBearerTokenField, r.bearerToken) + size += proto.NestedStructureSize(reqMetaHeaderOriginField, r.origin) + size += proto.UInt64Size(reqMetaHeaderNetMagicField, r.netMagic) + + return size +} + +func (r *RequestMetaHeader) Unmarshal(data []byte) error { + return message.Unmarshal(r, data, new(session.RequestMetaHeader)) +} + +func (r *RequestVerificationHeader) StableMarshal(buf []byte) []byte { + if r == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, r.StableSize()) + } + + var offset int + + offset += proto.NestedStructureMarshal(reqVerifHeaderBodySignatureField, buf[offset:], r.bodySig) + offset += proto.NestedStructureMarshal(reqVerifHeaderMetaSignatureField, buf[offset:], r.metaSig) + offset += proto.NestedStructureMarshal(reqVerifHeaderOriginSignatureField, buf[offset:], r.originSig) + proto.NestedStructureMarshal(reqVerifHeaderOriginField, buf[offset:], r.origin) + + return buf +} + +func (r *RequestVerificationHeader) StableSize() (size int) { + if r == nil { + return 0 + } + + size += proto.NestedStructureSize(reqVerifHeaderBodySignatureField, r.bodySig) + size += proto.NestedStructureSize(reqVerifHeaderMetaSignatureField, r.metaSig) + size += proto.NestedStructureSize(reqVerifHeaderOriginSignatureField, r.originSig) + size += proto.NestedStructureSize(reqVerifHeaderOriginField, r.origin) + + return size +} + +func (r *RequestVerificationHeader) Unmarshal(data []byte) error { + return message.Unmarshal(r, data, new(session.RequestVerificationHeader)) +} + +func (r *ResponseMetaHeader) StableMarshal(buf []byte) []byte { + if r == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, r.StableSize()) + } + + var offset int + + offset += proto.NestedStructureMarshal(respMetaHeaderVersionField, buf[offset:], r.version) + offset += proto.UInt64Marshal(respMetaHeaderEpochField, buf[offset:], r.epoch) + offset += proto.UInt32Marshal(respMetaHeaderTTLField, buf[offset:], r.ttl) + + for i := range r.xHeaders { + offset += proto.NestedStructureMarshal(respMetaHeaderXHeadersField, buf[offset:], &r.xHeaders[i]) + } + + offset += proto.NestedStructureMarshal(respMetaHeaderOriginField, buf[offset:], r.origin) + proto.NestedStructureMarshal(respMetaHeaderStatusField, buf[offset:], r.status) + + return buf +} + +func (r *ResponseMetaHeader) StableSize() (size int) { + if r == nil { + return 0 + } + + if r.version != nil { + size += proto.NestedStructureSize(respMetaHeaderVersionField, r.version) + } + + size += proto.UInt64Size(respMetaHeaderEpochField, r.epoch) + size += proto.UInt32Size(respMetaHeaderTTLField, r.ttl) + + for i := range r.xHeaders { + size += proto.NestedStructureSize(respMetaHeaderXHeadersField, &r.xHeaders[i]) + } + + size += proto.NestedStructureSize(respMetaHeaderOriginField, r.origin) + size += proto.NestedStructureSize(respMetaHeaderStatusField, r.status) + + return size +} + +func (r *ResponseMetaHeader) Unmarshal(data []byte) error { + return message.Unmarshal(r, data, new(session.ResponseMetaHeader)) +} + +func (r *ResponseVerificationHeader) StableMarshal(buf []byte) []byte { + if r == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, r.StableSize()) + } + + var offset int + + offset += proto.NestedStructureMarshal(respVerifHeaderBodySignatureField, buf[offset:], r.bodySig) + offset += proto.NestedStructureMarshal(respVerifHeaderMetaSignatureField, buf[offset:], r.metaSig) + offset += proto.NestedStructureMarshal(respVerifHeaderOriginSignatureField, buf[offset:], r.originSig) + proto.NestedStructureMarshal(respVerifHeaderOriginField, buf[offset:], r.origin) + + return buf +} + +func (r *ResponseVerificationHeader) StableSize() (size int) { + if r == nil { + return 0 + } + + size += proto.NestedStructureSize(respVerifHeaderBodySignatureField, r.bodySig) + size += proto.NestedStructureSize(respVerifHeaderMetaSignatureField, r.metaSig) + size += proto.NestedStructureSize(respVerifHeaderOriginSignatureField, r.originSig) + size += proto.NestedStructureSize(respVerifHeaderOriginField, r.origin) + + return size +} + +func (r *ResponseVerificationHeader) Unmarshal(data []byte) error { + return message.Unmarshal(r, data, new(session.ResponseVerificationHeader)) +} diff --git a/api/session/message_test.go b/api/session/message_test.go new file mode 100644 index 0000000..7e5844a --- /dev/null +++ b/api/session/message_test.go @@ -0,0 +1,27 @@ +package session_test + +import ( + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/message" + rpctest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/message/test" + sessiontest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session/test" +) + +func TestMessageConvert(t *testing.T) { + rpctest.TestRPCMessage(t, + func(empty bool) message.Message { return sessiontest.GenerateCreateRequestBody(empty) }, + func(empty bool) message.Message { return sessiontest.GenerateCreateRequest(empty) }, + func(empty bool) message.Message { return sessiontest.GenerateCreateResponseBody(empty) }, + func(empty bool) message.Message { return sessiontest.GenerateCreateResponse(empty) }, + func(empty bool) message.Message { return sessiontest.GenerateTokenLifetime(empty) }, + func(empty bool) message.Message { return sessiontest.GenerateXHeader(empty) }, + func(empty bool) message.Message { return sessiontest.GenerateSessionTokenBody(empty) }, + func(empty bool) message.Message { return sessiontest.GenerateSessionToken(empty) }, + func(empty bool) message.Message { return sessiontest.GenerateRequestMetaHeader(empty) }, + func(empty bool) message.Message { return sessiontest.GenerateRequestVerificationHeader(empty) }, + func(empty bool) message.Message { return sessiontest.GenerateResponseMetaHeader(empty) }, + func(empty bool) message.Message { return sessiontest.GenerateResponseVerificationHeader(empty) }, + func(empty bool) message.Message { return sessiontest.GenerateContainerSessionContext(empty) }, + ) +} diff --git a/api/session/status.go b/api/session/status.go new file mode 100644 index 0000000..229a459 --- /dev/null +++ b/api/session/status.go @@ -0,0 +1,32 @@ +package session + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/status" + statusgrpc "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/status/grpc" +) + +// LocalizeFailStatus checks if passed global status.Code is related to session failure and: +// +// then localizes the code and returns true, +// else leaves the code unchanged and returns false. +// +// Arg must not be nil. +func LocalizeFailStatus(c *status.Code) bool { + return status.LocalizeIfInSection(c, uint32(statusgrpc.Section_SECTION_SESSION)) +} + +// GlobalizeFail globalizes local code of session failure. +// +// Arg must not be nil. +func GlobalizeFail(c *status.Code) { + c.GlobalizeSection(uint32(statusgrpc.Section_SECTION_SESSION)) +} + +const ( + // StatusTokenNotFound is a local status.Code value for + // TOKEN_NOT_FOUND session failure. + StatusTokenNotFound status.Code = iota + // StatusTokenExpired is a local status.Code value for + // TOKEN_EXPIRED session failure. + StatusTokenExpired +) diff --git a/api/session/status_test.go b/api/session/status_test.go new file mode 100644 index 0000000..c984e6f --- /dev/null +++ b/api/session/status_test.go @@ -0,0 +1,15 @@ +package session_test + +import ( + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" + statustest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/status/test" +) + +func TestStatusCodes(t *testing.T) { + statustest.TestCodes(t, session.LocalizeFailStatus, session.GlobalizeFail, + session.StatusTokenNotFound, 4096, + session.StatusTokenExpired, 4097, + ) +} diff --git a/api/session/string.go b/api/session/string.go new file mode 100644 index 0000000..fd2d425 --- /dev/null +++ b/api/session/string.go @@ -0,0 +1,47 @@ +package session + +import ( + session "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session/grpc" +) + +// String returns string representation of ObjectSessionVerb. +func (x ObjectSessionVerb) String() string { + return ObjectSessionVerbToGRPCField(x).String() +} + +// FromString parses ObjectSessionVerb from a string representation. +// It is a reverse action to String(). +// +// Returns true if s was parsed successfully. +func (x *ObjectSessionVerb) FromString(s string) bool { + var g session.ObjectSessionContext_Verb + + ok := g.FromString(s) + + if ok { + *x = ObjectSessionVerbFromGRPCField(g) + } + + return ok +} + +// String returns string representation of ContainerSessionVerb. +func (x ContainerSessionVerb) String() string { + return ContainerSessionVerbToGRPCField(x).String() +} + +// FromString parses ContainerSessionVerb from a string representation. +// It is a reverse action to String(). +// +// Returns true if s was parsed successfully. +func (x *ContainerSessionVerb) FromString(s string) bool { + var g session.ContainerSessionContext_Verb + + ok := g.FromString(s) + + if ok { + *x = ContainerSessionVerbFromGRPCField(g) + } + + return ok +} diff --git a/api/session/test/generate.go b/api/session/test/generate.go new file mode 100644 index 0000000..b35fe07 --- /dev/null +++ b/api/session/test/generate.go @@ -0,0 +1,251 @@ +package sessiontest + +import ( + crand "crypto/rand" + "math/rand" + "time" + + acltest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/acl/test" + refstest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs/test" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" + statustest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/status/test" +) + +func GenerateCreateRequestBody(empty bool) *session.CreateRequestBody { + m := new(session.CreateRequestBody) + + if !empty { + m.SetExpiration(555) + m.SetOwnerID(refstest.GenerateOwnerID(false)) + } + + return m +} + +func GenerateCreateRequest(empty bool) *session.CreateRequest { + m := new(session.CreateRequest) + + if !empty { + m.SetBody(GenerateCreateRequestBody(false)) + } + + m.SetMetaHeader(GenerateRequestMetaHeader(empty)) + m.SetVerificationHeader(GenerateRequestVerificationHeader(empty)) + + return m +} + +func GenerateCreateResponseBody(empty bool) *session.CreateResponseBody { + m := new(session.CreateResponseBody) + + if !empty { + id := make([]byte, 16) + _, _ = crand.Read(id) + + m.SetID(id) + m.SetSessionKey([]byte{4, 5, 6}) + } + + return m +} + +func GenerateCreateResponse(empty bool) *session.CreateResponse { + m := new(session.CreateResponse) + + if !empty { + m.SetBody(GenerateCreateResponseBody(false)) + } + + m.SetMetaHeader(GenerateResponseMetaHeader(empty)) + m.SetVerificationHeader(GenerateResponseVerificationHeader(empty)) + + return m +} + +func GenerateResponseVerificationHeader(empty bool) *session.ResponseVerificationHeader { + return generateResponseVerificationHeader(empty, true) +} + +func generateResponseVerificationHeader(empty, withOrigin bool) *session.ResponseVerificationHeader { + m := new(session.ResponseVerificationHeader) + + if !empty { + m.SetBodySignature(refstest.GenerateSignature(false)) + } + + m.SetMetaSignature(refstest.GenerateSignature(empty)) + m.SetOriginSignature(refstest.GenerateSignature(empty)) + + if withOrigin { + m.SetOrigin(generateResponseVerificationHeader(empty, false)) + } + + return m +} + +func GenerateResponseMetaHeader(empty bool) *session.ResponseMetaHeader { + return generateResponseMetaHeader(empty, true) +} + +func generateResponseMetaHeader(empty, withOrigin bool) *session.ResponseMetaHeader { + m := new(session.ResponseMetaHeader) + + if !empty { + m.SetEpoch(13) + m.SetTTL(100) + } + + m.SetXHeaders(GenerateXHeaders(empty)) + m.SetVersion(refstest.GenerateVersion(empty)) + m.SetStatus(statustest.Status(empty)) + + if withOrigin { + m.SetOrigin(generateResponseMetaHeader(empty, false)) + } + + return m +} + +func GenerateRequestVerificationHeader(empty bool) *session.RequestVerificationHeader { + return generateRequestVerificationHeader(empty, true) +} + +func generateRequestVerificationHeader(empty, withOrigin bool) *session.RequestVerificationHeader { + m := new(session.RequestVerificationHeader) + + if !empty { + m.SetBodySignature(refstest.GenerateSignature(false)) + } + + m.SetMetaSignature(refstest.GenerateSignature(empty)) + m.SetOriginSignature(refstest.GenerateSignature(empty)) + + if withOrigin { + m.SetOrigin(generateRequestVerificationHeader(empty, false)) + } + + return m +} + +func GenerateRequestMetaHeader(empty bool) *session.RequestMetaHeader { + return generateRequestMetaHeader(empty, true) +} + +func generateRequestMetaHeader(empty, withOrigin bool) *session.RequestMetaHeader { + m := new(session.RequestMetaHeader) + + if !empty { + m.SetEpoch(13) + m.SetTTL(100) + m.SetNetworkMagic(1337) + } + + m.SetXHeaders(GenerateXHeaders(empty)) + m.SetVersion(refstest.GenerateVersion(empty)) + m.SetSessionToken(GenerateSessionToken(empty)) + m.SetBearerToken(acltest.GenerateBearerToken(empty)) + + if withOrigin { + m.SetOrigin(generateRequestMetaHeader(empty, false)) + } + + return m +} + +func GenerateSessionToken(empty bool) *session.Token { + m := new(session.Token) + + if !empty { + m.SetBody(GenerateSessionTokenBody(false)) + } + + m.SetSignature(refstest.GenerateSignature(empty)) + + return m +} + +func GenerateSessionTokenBody(empty bool) *session.TokenBody { + m := new(session.TokenBody) + + if !empty { + id := make([]byte, 16) + _, _ = crand.Read(id) + + m.SetID(id) + m.SetSessionKey([]byte{2}) + m.SetOwnerID(refstest.GenerateOwnerID(false)) + m.SetLifetime(GenerateTokenLifetime(false)) + + switch randomInt(2) { + case 0: + m.SetContext(GenerateObjectSessionContext(false)) + case 1: + m.SetContext(GenerateContainerSessionContext(false)) + } + } + + return m +} + +func GenerateTokenLifetime(empty bool) *session.TokenLifetime { + m := new(session.TokenLifetime) + + if !empty { + m.SetExp(1) + m.SetIat(2) + m.SetExp(3) + } + + return m +} + +func GenerateObjectSessionContext(empty bool) *session.ObjectSessionContext { + m := new(session.ObjectSessionContext) + + if !empty { + m.SetVerb(session.ObjectVerbHead) + m.SetTarget(refstest.GenerateContainerID(false), refstest.GenerateObjectIDs(false)...) + } + + return m +} + +func GenerateContainerSessionContext(empty bool) *session.ContainerSessionContext { + m := new(session.ContainerSessionContext) + + if !empty { + m.SetVerb(session.ContainerVerbDelete) + m.SetWildcard(true) + m.SetContainerID(refstest.GenerateContainerID(false)) + } + + return m +} + +func GenerateXHeader(empty bool) *session.XHeader { + m := new(session.XHeader) + + if !empty { + m.SetKey("key") + m.SetValue("val") + } + + return m +} + +func GenerateXHeaders(empty bool) []session.XHeader { + var xs []session.XHeader + + if !empty { + xs = append(xs, + *GenerateXHeader(false), + *GenerateXHeader(false), + ) + } + + return xs +} + +func randomInt(n int) int { + return rand.New(rand.NewSource(time.Now().UnixNano())).Intn(n) +} diff --git a/api/session/types.go b/api/session/types.go new file mode 100644 index 0000000..838024f --- /dev/null +++ b/api/session/types.go @@ -0,0 +1,836 @@ +package session + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/acl" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/status" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/util/proto" +) + +type CreateRequestBody struct { + ownerID *refs.OwnerID + + expiration uint64 +} + +type CreateRequest struct { + body *CreateRequestBody + + RequestHeaders +} + +type CreateResponseBody struct { + id []byte + + sessionKey []byte +} + +type CreateResponse struct { + body *CreateResponseBody + + ResponseHeaders +} + +type XHeader struct { + key, val string +} + +type TokenLifetime struct { + exp, nbf, iat uint64 +} + +type ObjectSessionVerb uint32 + +type objectSessionContextTarget struct { + cnr *refs.ContainerID + + objs []refs.ObjectID +} + +const ( + _ = iota + fNumObjectTargetContainer + fNumObjectTargetObjects +) + +func (x objectSessionContextTarget) StableMarshal(buf []byte) []byte { + if buf == nil { + buf = make([]byte, x.StableSize()) + } + + offset := proto.NestedStructureMarshal(fNumObjectTargetContainer, buf, x.cnr) + + for i := range x.objs { + offset += proto.NestedStructureMarshal(fNumObjectTargetObjects, buf[offset:], &x.objs[i]) + } + + return buf +} + +func (x objectSessionContextTarget) StableSize() (size int) { + size += proto.NestedStructureSize(fNumObjectTargetContainer, x.cnr) + + for i := range x.objs { + size += proto.NestedStructureSize(fNumObjectTargetObjects, &x.objs[i]) + } + + return size +} + +type ObjectSessionContext struct { + verb ObjectSessionVerb + + cnr *refs.ContainerID + + objs []refs.ObjectID +} + +type TokenContext interface { + sessionTokenContext() +} + +// Deprecated: use TokenContext instead. +// +//nolint:revive +type SessionTokenContext = TokenContext + +type TokenBody struct { + id []byte + + ownerID *refs.OwnerID + + lifetime *TokenLifetime + + sessionKey []byte + + ctx TokenContext +} + +// Deprecated: use TokenBody instead. +// +//nolint:revive +type SessionTokenBody = TokenBody + +type Token struct { + body *TokenBody + + sig *refs.Signature +} + +// Deprecated: use Token instead. +// +//nolint:revive +type SessionToken = Token + +type RequestVerificationHeader struct { + bodySig, metaSig, originSig *refs.Signature + + origin *RequestVerificationHeader +} + +type RequestMetaHeader struct { + version *refs.Version + + ttl uint32 + + epoch uint64 + + xHeaders []XHeader + + sessionToken *Token + + bearerToken *acl.BearerToken + + origin *RequestMetaHeader + + netMagic uint64 +} + +type ResponseVerificationHeader struct { + bodySig, metaSig, originSig *refs.Signature + + origin *ResponseVerificationHeader +} + +type ResponseMetaHeader struct { + version *refs.Version + + ttl uint32 + + epoch uint64 + + xHeaders []XHeader + + origin *ResponseMetaHeader + + status *status.Status +} + +const ( + ObjectVerbUnknown ObjectSessionVerb = iota + ObjectVerbPut + ObjectVerbGet + ObjectVerbHead + ObjectVerbSearch + ObjectVerbDelete + ObjectVerbRange + ObjectVerbRangeHash + ObjectVerbPatch +) + +func (c *CreateRequestBody) GetOwnerID() *refs.OwnerID { + if c != nil { + return c.ownerID + } + + return nil +} + +func (c *CreateRequestBody) SetOwnerID(v *refs.OwnerID) { + c.ownerID = v +} + +func (c *CreateRequestBody) GetExpiration() uint64 { + if c != nil { + return c.expiration + } + + return 0 +} + +func (c *CreateRequestBody) SetExpiration(v uint64) { + c.expiration = v +} + +func (c *CreateRequest) GetBody() *CreateRequestBody { + if c != nil { + return c.body + } + + return nil +} + +func (c *CreateRequest) SetBody(v *CreateRequestBody) { + c.body = v +} + +func (c *CreateRequest) GetMetaHeader() *RequestMetaHeader { + if c != nil { + return c.metaHeader + } + + return nil +} + +func (c *CreateRequest) SetMetaHeader(v *RequestMetaHeader) { + c.metaHeader = v +} + +func (c *CreateRequest) GetVerificationHeader() *RequestVerificationHeader { + if c != nil { + return c.verifyHeader + } + + return nil +} + +func (c *CreateRequest) SetVerificationHeader(v *RequestVerificationHeader) { + c.verifyHeader = v +} + +func (c *CreateResponseBody) GetID() []byte { + if c != nil { + return c.id + } + + return nil +} + +func (c *CreateResponseBody) SetID(v []byte) { + c.id = v +} + +func (c *CreateResponseBody) GetSessionKey() []byte { + if c != nil { + return c.sessionKey + } + + return nil +} + +func (c *CreateResponseBody) SetSessionKey(v []byte) { + c.sessionKey = v +} + +func (c *CreateResponse) GetBody() *CreateResponseBody { + if c != nil { + return c.body + } + + return nil +} + +func (c *CreateResponse) SetBody(v *CreateResponseBody) { + c.body = v +} + +func (c *CreateResponse) GetMetaHeader() *ResponseMetaHeader { + if c != nil { + return c.metaHeader + } + + return nil +} + +func (c *CreateResponse) SetMetaHeader(v *ResponseMetaHeader) { + c.metaHeader = v +} + +func (c *CreateResponse) GetVerificationHeader() *ResponseVerificationHeader { + if c != nil { + return c.verifyHeader + } + + return nil +} + +func (c *CreateResponse) SetVerificationHeader(v *ResponseVerificationHeader) { + c.verifyHeader = v +} + +func (x *XHeader) GetKey() string { + if x != nil { + return x.key + } + + return "" +} + +func (x *XHeader) SetKey(v string) { + x.key = v +} + +func (x *XHeader) GetValue() string { + if x != nil { + return x.val + } + + return "" +} + +func (x *XHeader) SetValue(v string) { + x.val = v +} + +func (r *RequestVerificationHeader) GetBodySignature() *refs.Signature { + if r != nil { + return r.bodySig + } + + return nil +} + +func (r *RequestVerificationHeader) SetBodySignature(v *refs.Signature) { + r.bodySig = v +} + +func (r *RequestVerificationHeader) GetMetaSignature() *refs.Signature { + if r != nil { + return r.metaSig + } + + return nil +} + +func (r *RequestVerificationHeader) SetMetaSignature(v *refs.Signature) { + r.metaSig = v +} + +func (r *RequestVerificationHeader) GetOriginSignature() *refs.Signature { + if r != nil { + return r.originSig + } + + return nil +} + +func (r *RequestVerificationHeader) SetOriginSignature(v *refs.Signature) { + r.originSig = v +} + +func (r *RequestVerificationHeader) GetOrigin() *RequestVerificationHeader { + if r != nil { + return r.origin + } + + return nil +} + +func (r *RequestVerificationHeader) SetOrigin(v *RequestVerificationHeader) { + r.origin = v +} + +func (r *RequestMetaHeader) GetVersion() *refs.Version { + if r != nil { + return r.version + } + + return nil +} + +func (r *RequestMetaHeader) SetVersion(v *refs.Version) { + r.version = v +} + +func (r *RequestMetaHeader) GetTTL() uint32 { + if r != nil { + return r.ttl + } + + return 0 +} + +func (r *RequestMetaHeader) SetTTL(v uint32) { + r.ttl = v +} + +func (r *RequestMetaHeader) GetEpoch() uint64 { + if r != nil { + return r.epoch + } + + return 0 +} + +func (r *RequestMetaHeader) SetEpoch(v uint64) { + r.epoch = v +} + +func (r *RequestMetaHeader) GetXHeaders() []XHeader { + if r != nil { + return r.xHeaders + } + + return nil +} + +func (r *RequestMetaHeader) SetXHeaders(v []XHeader) { + r.xHeaders = v +} + +func (r *RequestMetaHeader) GetSessionToken() *Token { + if r != nil { + return r.sessionToken + } + + return nil +} + +func (r *RequestMetaHeader) SetSessionToken(v *Token) { + r.sessionToken = v +} + +func (r *RequestMetaHeader) GetBearerToken() *acl.BearerToken { + if r != nil { + return r.bearerToken + } + + return nil +} + +func (r *RequestMetaHeader) SetBearerToken(v *acl.BearerToken) { + r.bearerToken = v +} + +func (r *RequestMetaHeader) GetOrigin() *RequestMetaHeader { + if r != nil { + return r.origin + } + + return nil +} + +func (r *RequestMetaHeader) SetOrigin(v *RequestMetaHeader) { + r.origin = v +} + +// GetNetworkMagic returns NeoFS network magic. +func (r *RequestMetaHeader) GetNetworkMagic() uint64 { + if r != nil { + return r.netMagic + } + + return 0 +} + +// SetNetworkMagic sets NeoFS network magic. +func (r *RequestMetaHeader) SetNetworkMagic(v uint64) { + r.netMagic = v +} + +func (l *TokenLifetime) GetExp() uint64 { + if l != nil { + return l.exp + } + + return 0 +} + +func (l *TokenLifetime) SetExp(v uint64) { + l.exp = v +} + +func (l *TokenLifetime) GetNbf() uint64 { + if l != nil { + return l.nbf + } + + return 0 +} + +func (l *TokenLifetime) SetNbf(v uint64) { + l.nbf = v +} + +func (l *TokenLifetime) GetIat() uint64 { + if l != nil { + return l.iat + } + + return 0 +} + +func (l *TokenLifetime) SetIat(v uint64) { + l.iat = v +} + +func (r *ResponseVerificationHeader) GetBodySignature() *refs.Signature { + if r != nil { + return r.bodySig + } + + return nil +} + +func (r *ResponseVerificationHeader) SetBodySignature(v *refs.Signature) { + r.bodySig = v +} + +func (r *ResponseVerificationHeader) GetMetaSignature() *refs.Signature { + if r != nil { + return r.metaSig + } + + return nil +} + +func (r *ResponseVerificationHeader) SetMetaSignature(v *refs.Signature) { + r.metaSig = v +} + +func (r *ResponseVerificationHeader) GetOriginSignature() *refs.Signature { + if r != nil { + return r.originSig + } + + return nil +} + +func (r *ResponseVerificationHeader) SetOriginSignature(v *refs.Signature) { + r.originSig = v +} + +func (r *ResponseVerificationHeader) GetOrigin() *ResponseVerificationHeader { + if r != nil { + return r.origin + } + + return nil +} + +func (r *ResponseVerificationHeader) SetOrigin(v *ResponseVerificationHeader) { + r.origin = v +} + +func (r *ResponseMetaHeader) GetVersion() *refs.Version { + if r != nil { + return r.version + } + + return nil +} + +func (r *ResponseMetaHeader) SetVersion(v *refs.Version) { + r.version = v +} + +func (r *ResponseMetaHeader) GetTTL() uint32 { + if r != nil { + return r.ttl + } + + return 0 +} + +func (r *ResponseMetaHeader) SetTTL(v uint32) { + r.ttl = v +} + +func (r *ResponseMetaHeader) GetEpoch() uint64 { + if r != nil { + return r.epoch + } + + return 0 +} + +func (r *ResponseMetaHeader) SetEpoch(v uint64) { + r.epoch = v +} + +func (r *ResponseMetaHeader) GetXHeaders() []XHeader { + if r != nil { + return r.xHeaders + } + + return nil +} + +func (r *ResponseMetaHeader) SetXHeaders(v []XHeader) { + r.xHeaders = v +} + +func (r *ResponseMetaHeader) GetOrigin() *ResponseMetaHeader { + if r != nil { + return r.origin + } + + return nil +} + +func (r *ResponseMetaHeader) SetOrigin(v *ResponseMetaHeader) { + r.origin = v +} + +// GetStatus returns response status. +func (r *ResponseMetaHeader) GetStatus() *status.Status { + if r != nil { + return r.status + } + + return nil +} + +// SetStatus sets response status. +func (r *ResponseMetaHeader) SetStatus(v *status.Status) { + r.status = v +} + +// SetStatus sets status of the message which can carry ResponseMetaHeader. +// +// Sets status field on the "highest" level of meta headers. +// If meta header is missing in message, it is allocated. +func SetStatus(msg interface { + GetMetaHeader() *ResponseMetaHeader + SetMetaHeader(*ResponseMetaHeader) +}, st *status.Status, +) { + meta := msg.GetMetaHeader() + if meta == nil { + meta = new(ResponseMetaHeader) + msg.SetMetaHeader(meta) + } + + meta.SetStatus(st) +} + +func (c *ObjectSessionContext) sessionTokenContext() {} + +func (c *ObjectSessionContext) GetVerb() ObjectSessionVerb { + if c != nil { + return c.verb + } + + return ObjectVerbUnknown +} + +func (c *ObjectSessionContext) SetVerb(v ObjectSessionVerb) { + c.verb = v +} + +func (c *ObjectSessionContext) GetContainer() *refs.ContainerID { + if c != nil { + return c.cnr + } + + return nil +} + +func (c *ObjectSessionContext) GetObjects() []refs.ObjectID { + if c != nil { + return c.objs + } + + return nil +} + +func (c *ObjectSessionContext) SetTarget(cnr *refs.ContainerID, objs ...refs.ObjectID) { + c.cnr = cnr + c.objs = objs +} + +func (t *TokenBody) GetID() []byte { + if t != nil { + return t.id + } + + return nil +} + +func (t *TokenBody) SetID(v []byte) { + t.id = v +} + +func (t *TokenBody) GetOwnerID() *refs.OwnerID { + if t != nil { + return t.ownerID + } + + return nil +} + +func (t *TokenBody) SetOwnerID(v *refs.OwnerID) { + t.ownerID = v +} + +func (t *TokenBody) GetLifetime() *TokenLifetime { + if t != nil { + return t.lifetime + } + + return nil +} + +func (t *TokenBody) SetLifetime(v *TokenLifetime) { + t.lifetime = v +} + +func (t *TokenBody) GetSessionKey() []byte { + if t != nil { + return t.sessionKey + } + + return nil +} + +func (t *TokenBody) SetSessionKey(v []byte) { + t.sessionKey = v +} + +func (t *TokenBody) GetContext() TokenContext { + if t != nil { + return t.ctx + } + + return nil +} + +func (t *TokenBody) SetContext(v TokenContext) { + t.ctx = v +} + +func (t *Token) GetBody() *TokenBody { + if t != nil { + return t.body + } + + return nil +} + +func (t *Token) SetBody(v *TokenBody) { + t.body = v +} + +func (t *Token) GetSignature() *refs.Signature { + if t != nil { + return t.sig + } + + return nil +} + +func (t *Token) SetSignature(v *refs.Signature) { + t.sig = v +} + +// ContainerSessionVerb represents NeoFS API v2 +// session.ContainerSessionContext.Verb enumeration. +type ContainerSessionVerb uint32 + +const ( + // ContainerVerbUnknown corresponds to VERB_UNSPECIFIED enum value. + ContainerVerbUnknown ContainerSessionVerb = iota + + // ContainerVerbPut corresponds to PUT enum value. + ContainerVerbPut + + // ContainerVerbDelete corresponds to DELETE enum value. + ContainerVerbDelete + + // ContainerVerbSetEACL corresponds to SETEACL enum value. + ContainerVerbSetEACL +) + +// ContainerSessionContext represents structure of the +// NeoFS API v2 session.ContainerSessionContext message. +type ContainerSessionContext struct { + verb ContainerSessionVerb + + wildcard bool + + cid *refs.ContainerID +} + +func (x *ContainerSessionContext) sessionTokenContext() {} + +// Verb returns type of request for which the token is issued. +func (x *ContainerSessionContext) Verb() ContainerSessionVerb { + if x != nil { + return x.verb + } + + return ContainerVerbUnknown +} + +// SetVerb sets type of request for which the token is issued. +func (x *ContainerSessionContext) SetVerb(v ContainerSessionVerb) { + x.verb = v +} + +// Wildcard returns wildcard flag of the container session. +func (x *ContainerSessionContext) Wildcard() bool { + if x != nil { + return x.wildcard + } + + return false +} + +// SetWildcard sets wildcard flag of the container session. +func (x *ContainerSessionContext) SetWildcard(v bool) { + x.wildcard = v +} + +// ContainerID returns identifier of the container related to the session. +func (x *ContainerSessionContext) ContainerID() *refs.ContainerID { + if x != nil { + return x.cid + } + + return nil +} + +// SetContainerID sets identifier of the container related to the session. +func (x *ContainerSessionContext) SetContainerID(v *refs.ContainerID) { + x.cid = v +} diff --git a/api/session/util.go b/api/session/util.go new file mode 100644 index 0000000..ea5aff0 --- /dev/null +++ b/api/session/util.go @@ -0,0 +1,167 @@ +package session + +import ( + session "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session/grpc" +) + +// RequestHeaders represents common part of +// all NeoFS requests including headers. +type RequestHeaders struct { + metaHeader *RequestMetaHeader + + verifyHeader *RequestVerificationHeader +} + +// GetMetaHeader returns meta header of the request. +func (c *RequestHeaders) GetMetaHeader() *RequestMetaHeader { + if c != nil { + return c.metaHeader + } + + return nil +} + +// SetMetaHeader sets meta header of the request. +func (c *RequestHeaders) SetMetaHeader(v *RequestMetaHeader) { + c.metaHeader = v +} + +// GetVerificationHeader returns verification header of the request. +func (c *RequestHeaders) GetVerificationHeader() *RequestVerificationHeader { + if c != nil { + return c.verifyHeader + } + + return nil +} + +// SetVerificationHeader sets verification header of the request. +func (c *RequestHeaders) SetVerificationHeader(v *RequestVerificationHeader) { + c.verifyHeader = v +} + +func (c *RequestHeaders) ToMessage(m interface { + SetMetaHeader(*session.RequestMetaHeader) + SetVerifyHeader(*session.RequestVerificationHeader) +}, +) { + m.SetMetaHeader(c.metaHeader.ToGRPCMessage().(*session.RequestMetaHeader)) + m.SetVerifyHeader(c.verifyHeader.ToGRPCMessage().(*session.RequestVerificationHeader)) +} + +func (c *RequestHeaders) FromMessage(m interface { + GetMetaHeader() *session.RequestMetaHeader + GetVerifyHeader() *session.RequestVerificationHeader +}, +) error { + metaHdr := m.GetMetaHeader() + if metaHdr == nil { + c.metaHeader = nil + } else { + if c.metaHeader == nil { + c.metaHeader = new(RequestMetaHeader) + } + + err := c.metaHeader.FromGRPCMessage(metaHdr) + if err != nil { + return err + } + } + + verifyHdr := m.GetVerifyHeader() + if verifyHdr == nil { + c.verifyHeader = nil + } else { + if c.verifyHeader == nil { + c.verifyHeader = new(RequestVerificationHeader) + } + + err := c.verifyHeader.FromGRPCMessage(verifyHdr) + if err != nil { + return err + } + } + + return nil +} + +// ResponseHeaders represents common part of +// all NeoFS responses including headers. +type ResponseHeaders struct { + metaHeader *ResponseMetaHeader + + verifyHeader *ResponseVerificationHeader +} + +// GetMetaHeader returns meta header of the response. +func (c *ResponseHeaders) GetMetaHeader() *ResponseMetaHeader { + if c != nil { + return c.metaHeader + } + + return nil +} + +// SetMetaHeader sets meta header of the response. +func (c *ResponseHeaders) SetMetaHeader(v *ResponseMetaHeader) { + c.metaHeader = v +} + +// GetVerificationHeader returns verification header of the response. +func (c *ResponseHeaders) GetVerificationHeader() *ResponseVerificationHeader { + if c != nil { + return c.verifyHeader + } + + return nil +} + +// SetVerificationHeader sets verification header of the response. +func (c *ResponseHeaders) SetVerificationHeader(v *ResponseVerificationHeader) { + c.verifyHeader = v +} + +func (c *ResponseHeaders) ToMessage(m interface { + SetMetaHeader(*session.ResponseMetaHeader) + SetVerifyHeader(*session.ResponseVerificationHeader) +}, +) { + m.SetMetaHeader(c.metaHeader.ToGRPCMessage().(*session.ResponseMetaHeader)) + m.SetVerifyHeader(c.verifyHeader.ToGRPCMessage().(*session.ResponseVerificationHeader)) +} + +func (c *ResponseHeaders) FromMessage(m interface { + GetMetaHeader() *session.ResponseMetaHeader + GetVerifyHeader() *session.ResponseVerificationHeader +}, +) error { + metaHdr := m.GetMetaHeader() + if metaHdr == nil { + c.metaHeader = nil + } else { + if c.metaHeader == nil { + c.metaHeader = new(ResponseMetaHeader) + } + + err := c.metaHeader.FromGRPCMessage(metaHdr) + if err != nil { + return err + } + } + + verifyHdr := m.GetVerifyHeader() + if verifyHdr == nil { + c.verifyHeader = nil + } else { + if c.verifyHeader == nil { + c.verifyHeader = new(ResponseVerificationHeader) + } + + err := c.verifyHeader.FromGRPCMessage(verifyHdr) + if err != nil { + return err + } + } + + return nil +} diff --git a/api/session/xheaders.go b/api/session/xheaders.go new file mode 100644 index 0000000..c575d5f --- /dev/null +++ b/api/session/xheaders.go @@ -0,0 +1,34 @@ +package session + +// ReservedXHeaderPrefix is a prefix of keys to "well-known" X-headers. +const ReservedXHeaderPrefix = "__SYSTEM__" + +const ( + // XHeaderNetmapEpoch is a key to the reserved X-header that specifies netmap epoch + // to use for object placement calculation. If set to '0' or not set, the current + // epoch only will be used. + XHeaderNetmapEpoch = ReservedXHeaderPrefix + "NETMAP_EPOCH" + + // XHeaderNetmapLookupDepth is a key to the reserved X-header that limits + // how many past epochs back the node will can lookup. If set to '0' or not + // set, the current epoch only will be used. + XHeaderNetmapLookupDepth = ReservedXHeaderPrefix + "NETMAP_LOOKUP_DEPTH" +) + +// ReservedXHeaderPrefixNeoFS is a prefix of keys to "well-known" X-headers. +// Deprecated: use ReservedXHeaderPrefix. +const ReservedXHeaderPrefixNeoFS = "__NEOFS__" + +const ( + // XHeaderNetmapEpochNeoFS is a key to the reserved X-header that specifies netmap epoch + // to use for object placement calculation. If set to '0' or not set, the current + // epoch only will be used. + // Deprecated: use XHeaderNetmapEpoch. + XHeaderNetmapEpochNeoFS = ReservedXHeaderPrefixNeoFS + "NETMAP_EPOCH" + + // XHeaderNetmapLookupDepthNeoFS is a key to the reserved X-header that limits + // how many past epochs back the node will can lookup. If set to '0' or not + // set, the current epoch only will be used. + // Deprecated: use XHeaderNetmapLookupDepth. + XHeaderNetmapLookupDepthNeoFS = ReservedXHeaderPrefixNeoFS + "NETMAP_LOOKUP_DEPTH" +) diff --git a/api/signature/body.go b/api/signature/body.go new file mode 100644 index 0000000..50a09e9 --- /dev/null +++ b/api/signature/body.go @@ -0,0 +1,116 @@ +package signature + +import ( + "fmt" + + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/accounting" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/apemanager" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/container" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" +) + +// nolint:funlen +func serviceMessageBody(req any) stableMarshaler { + switch v := req.(type) { + default: + panic(fmt.Sprintf("unsupported session message %T", req)) + + /* Accounting */ + case *accounting.BalanceRequest: + return v.GetBody() + case *accounting.BalanceResponse: + return v.GetBody() + + /* Session */ + case *session.CreateRequest: + return v.GetBody() + case *session.CreateResponse: + return v.GetBody() + + /* Container */ + case *container.PutRequest: + return v.GetBody() + case *container.PutResponse: + return v.GetBody() + case *container.DeleteRequest: + return v.GetBody() + case *container.DeleteResponse: + return v.GetBody() + case *container.GetRequest: + return v.GetBody() + case *container.GetResponse: + return v.GetBody() + case *container.ListRequest: + return v.GetBody() + case *container.ListResponse: + return v.GetBody() + + /* Object */ + case *object.PutRequest: + return v.GetBody() + case *object.PutResponse: + return v.GetBody() + case *object.GetRequest: + return v.GetBody() + case *object.GetResponse: + return v.GetBody() + case *object.HeadRequest: + return v.GetBody() + case *object.HeadResponse: + return v.GetBody() + case *object.SearchRequest: + return v.GetBody() + case *object.SearchResponse: + return v.GetBody() + case *object.DeleteRequest: + return v.GetBody() + case *object.DeleteResponse: + return v.GetBody() + case *object.GetRangeRequest: + return v.GetBody() + case *object.GetRangeResponse: + return v.GetBody() + case *object.GetRangeHashRequest: + return v.GetBody() + case *object.GetRangeHashResponse: + return v.GetBody() + case *object.PutSingleRequest: + return v.GetBody() + case *object.PutSingleResponse: + return v.GetBody() + case *object.PatchRequest: + return v.GetBody() + case *object.PatchResponse: + return v.GetBody() + + /* Netmap */ + case *netmap.LocalNodeInfoRequest: + return v.GetBody() + case *netmap.LocalNodeInfoResponse: + return v.GetBody() + case *netmap.NetworkInfoRequest: + return v.GetBody() + case *netmap.NetworkInfoResponse: + return v.GetBody() + case *netmap.SnapshotRequest: + return v.GetBody() + case *netmap.SnapshotResponse: + return v.GetBody() + + /* APEManager */ + case *apemanager.AddChainRequest: + return v.GetBody() + case *apemanager.AddChainResponse: + return v.GetBody() + case *apemanager.RemoveChainRequest: + return v.GetBody() + case *apemanager.RemoveChainResponse: + return v.GetBody() + case *apemanager.ListChainsRequest: + return v.GetBody() + case *apemanager.ListChainsResponse: + return v.GetBody() + } +} diff --git a/api/signature/marshaller.go b/api/signature/marshaller.go new file mode 100644 index 0000000..ff9beb3 --- /dev/null +++ b/api/signature/marshaller.go @@ -0,0 +1,26 @@ +package signature + +type stableMarshaler interface { + StableMarshal([]byte) []byte + StableSize() int +} + +type StableMarshalerWrapper struct { + SM stableMarshaler +} + +func (s StableMarshalerWrapper) ReadSignedData(buf []byte) ([]byte, error) { + if s.SM != nil { + return s.SM.StableMarshal(buf), nil + } + + return nil, nil +} + +func (s StableMarshalerWrapper) SignedDataSize() int { + if s.SM != nil { + return s.SM.StableSize() + } + + return 0 +} diff --git a/api/signature/sign.go b/api/signature/sign.go new file mode 100644 index 0000000..04b8d36 --- /dev/null +++ b/api/signature/sign.go @@ -0,0 +1,122 @@ +package signature + +import ( + "crypto/ecdsa" + "fmt" + + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/util/signature" + "golang.org/x/sync/errgroup" +) + +type serviceRequest interface { + GetMetaHeader() *session.RequestMetaHeader + GetVerificationHeader() *session.RequestVerificationHeader + SetVerificationHeader(*session.RequestVerificationHeader) +} + +type serviceResponse interface { + GetMetaHeader() *session.ResponseMetaHeader + GetVerificationHeader() *session.ResponseVerificationHeader + SetVerificationHeader(*session.ResponseVerificationHeader) +} + +type signatureReceiver interface { + SetBodySignature(*refs.Signature) + SetMetaSignature(*refs.Signature) + SetOriginSignature(*refs.Signature) +} + +// SignServiceMessage signes service message with key. +func SignServiceMessage(key *ecdsa.PrivateKey, msg any) error { + switch v := msg.(type) { + case nil: + return nil + case serviceRequest: + return signServiceRequest(key, v) + case serviceResponse: + return signServiceResponse(key, v) + default: + panic(fmt.Sprintf("unsupported session message %T", v)) + } +} + +func signServiceRequest(key *ecdsa.PrivateKey, v serviceRequest) error { + result := &session.RequestVerificationHeader{} + body := serviceMessageBody(v) + meta := v.GetMetaHeader() + header := v.GetVerificationHeader() + if err := signMessageParts(key, body, meta, header, header != nil, result); err != nil { + return err + } + result.SetOrigin(header) + v.SetVerificationHeader(result) + return nil +} + +func signServiceResponse(key *ecdsa.PrivateKey, v serviceResponse) error { + result := &session.ResponseVerificationHeader{} + body := serviceMessageBody(v) + meta := v.GetMetaHeader() + header := v.GetVerificationHeader() + if err := signMessageParts(key, body, meta, header, header != nil, result); err != nil { + return err + } + result.SetOrigin(header) + v.SetVerificationHeader(result) + return nil +} + +func signMessageParts(key *ecdsa.PrivateKey, body, meta, header stableMarshaler, hasHeader bool, result signatureReceiver) error { + eg := &errgroup.Group{} + if !hasHeader { + // sign session message body + eg.Go(func() error { + if err := signServiceMessagePart(key, body, result.SetBodySignature); err != nil { + return fmt.Errorf("could not sign body: %w", err) + } + return nil + }) + } + + // sign meta header + eg.Go(func() error { + if err := signServiceMessagePart(key, meta, result.SetMetaSignature); err != nil { + return fmt.Errorf("could not sign meta header: %w", err) + } + return nil + }) + + // sign verification header origin + eg.Go(func() error { + if err := signServiceMessagePart(key, header, result.SetOriginSignature); err != nil { + return fmt.Errorf("could not sign origin of verification header: %w", err) + } + return nil + }) + return eg.Wait() +} + +func signServiceMessagePart(key *ecdsa.PrivateKey, part stableMarshaler, sigWrite func(*refs.Signature)) error { + var sig *refs.Signature + + wrapper := StableMarshalerWrapper{ + SM: part, + } + // sign part + if err := signature.SignDataWithHandler( + key, + wrapper, + func(s *refs.Signature) { + sig = s + }, + ); err != nil { + return err + } + + // write part signature + sigWrite(sig) + + return nil +} diff --git a/api/signature/sign_test.go b/api/signature/sign_test.go new file mode 100644 index 0000000..23779c4 --- /dev/null +++ b/api/signature/sign_test.go @@ -0,0 +1,125 @@ +package signature + +import ( + "testing" + + crypto "git.frostfs.info/TrueCloudLab/frostfs-crypto" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/accounting" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" + "github.com/stretchr/testify/require" +) + +func TestBalanceResponse(t *testing.T) { + dec := new(accounting.Decimal) + dec.SetValue(100) + + body := new(accounting.BalanceResponseBody) + body.SetBalance(dec) + + meta := new(session.ResponseMetaHeader) + meta.SetTTL(1) + + req := new(accounting.BalanceResponse) + req.SetBody(body) + req.SetMetaHeader(meta) + + // verify unsigned request + require.Error(t, VerifyServiceMessage(req)) + + key, err := crypto.LoadPrivateKey("Kwk6k2eC3L3QuPvD8aiaNyoSXgQ2YL1bwS5CP1oKoA9waeAze97s") + require.NoError(t, err) + + // sign request + require.NoError(t, SignServiceMessage(key, req)) + + // verification must pass + require.NoError(t, VerifyServiceMessage(req)) + + // add level to meta header matryoshka + meta = new(session.ResponseMetaHeader) + meta.SetOrigin(req.GetMetaHeader()) + req.SetMetaHeader(meta) + + // sign request + require.NoError(t, SignServiceMessage(key, req)) + + // verification must pass + require.NoError(t, VerifyServiceMessage(req)) + + // corrupt body + dec.SetValue(dec.GetValue() + 1) + + // verification must fail + require.Error(t, VerifyServiceMessage(req)) + + // restore body + dec.SetValue(dec.GetValue() - 1) + + // corrupt meta header + meta.SetTTL(meta.GetTTL() + 1) + + // verification must fail + require.Error(t, VerifyServiceMessage(req)) + + // restore meta header + meta.SetTTL(meta.GetTTL() - 1) + + // corrupt origin verification header + req.GetVerificationHeader().SetOrigin(nil) + + // verification must fail + require.Error(t, VerifyServiceMessage(req)) +} + +func BenchmarkSignRequest(b *testing.B) { + key, _ := crypto.LoadPrivateKey("Kwk6k2eC3L3QuPvD8aiaNyoSXgQ2YL1bwS5CP1oKoA9waeAze97s") + + b.ResetTimer() + b.ReportAllocs() + + for range b.N { + b.StopTimer() + dec := new(accounting.Decimal) + dec.SetValue(100) + + body := new(accounting.BalanceResponseBody) + body.SetBalance(dec) + + meta := new(session.ResponseMetaHeader) + meta.SetTTL(1) + + resp := new(accounting.BalanceResponse) + resp.SetBody(body) + resp.SetMetaHeader(meta) + + b.StartTimer() + SignServiceMessage(key, resp) + } +} + +func BenchmarkVerifyRequest(b *testing.B) { + key, _ := crypto.LoadPrivateKey("Kwk6k2eC3L3QuPvD8aiaNyoSXgQ2YL1bwS5CP1oKoA9waeAze97s") + + b.ResetTimer() + b.ReportAllocs() + + for range b.N { + b.StopTimer() + dec := new(accounting.Decimal) + dec.SetValue(100) + + body := new(accounting.BalanceResponseBody) + body.SetBalance(dec) + + meta := new(session.ResponseMetaHeader) + meta.SetTTL(1) + + resp := new(accounting.BalanceResponse) + resp.SetBody(body) + resp.SetMetaHeader(meta) + SignServiceMessage(key, resp) + b.StartTimer() + + VerifyServiceMessage(resp) + } +} diff --git a/api/signature/verify.go b/api/signature/verify.go new file mode 100644 index 0000000..26dda83 --- /dev/null +++ b/api/signature/verify.go @@ -0,0 +1,127 @@ +package signature + +import ( + "errors" + "fmt" + + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/util/signature" + "golang.org/x/sync/errgroup" +) + +type signatureProvider interface { + GetBodySignature() *refs.Signature + GetMetaSignature() *refs.Signature + GetOriginSignature() *refs.Signature +} + +// VerifyServiceMessage verifies service message. +func VerifyServiceMessage(msg any) error { + switch v := msg.(type) { + case nil: + return nil + case serviceRequest: + return verifyServiceRequest(v) + case serviceResponse: + return verifyServiceResponse(v) + default: + panic(fmt.Sprintf("unsupported session message %T", v)) + } +} + +func verifyServiceRequest(v serviceRequest) error { + meta := v.GetMetaHeader() + verificationHeader := v.GetVerificationHeader() + body := serviceMessageBody(v) + return verifyServiceRequestRecursive(body, meta, verificationHeader) +} + +func verifyServiceRequestRecursive(body stableMarshaler, meta *session.RequestMetaHeader, verify *session.RequestVerificationHeader) error { + verificationHeaderOrigin := verify.GetOrigin() + metaOrigin := meta.GetOrigin() + + stop, err := verifyMessageParts(body, meta, verificationHeaderOrigin, verificationHeaderOrigin != nil, verify) + if err != nil { + return err + } + if stop { + return nil + } + + return verifyServiceRequestRecursive(body, metaOrigin, verificationHeaderOrigin) +} + +func verifyMessageParts(body, meta, originHeader stableMarshaler, hasOriginHeader bool, sigProvider signatureProvider) (stop bool, err error) { + eg := &errgroup.Group{} + + eg.Go(func() error { + if err := verifyServiceMessagePart(meta, sigProvider.GetMetaSignature); err != nil { + return fmt.Errorf("could not verify meta header: %w", err) + } + return nil + }) + + eg.Go(func() error { + if err := verifyServiceMessagePart(originHeader, sigProvider.GetOriginSignature); err != nil { + return fmt.Errorf("could not verify origin of verification header: %w", err) + } + return nil + }) + + if !hasOriginHeader { + eg.Go(func() error { + if err := verifyServiceMessagePart(body, sigProvider.GetBodySignature); err != nil { + return fmt.Errorf("could not verify body: %w", err) + } + return nil + }) + } + + if err := eg.Wait(); err != nil { + return false, err + } + + if !hasOriginHeader { + return true, nil + } + + if sigProvider.GetBodySignature() != nil { + return false, errors.New("body signature misses at the matryoshka upper level") + } + + return false, nil +} + +func verifyServiceResponse(v serviceResponse) error { + meta := v.GetMetaHeader() + verificationHeader := v.GetVerificationHeader() + body := serviceMessageBody(v) + return verifyServiceResponseRecursive(body, meta, verificationHeader) +} + +func verifyServiceResponseRecursive(body stableMarshaler, meta *session.ResponseMetaHeader, verify *session.ResponseVerificationHeader) error { + verificationHeaderOrigin := verify.GetOrigin() + metaOrigin := meta.GetOrigin() + + stop, err := verifyMessageParts(body, meta, verificationHeaderOrigin, verificationHeaderOrigin != nil, verify) + if err != nil { + return err + } + if stop { + return nil + } + + return verifyServiceResponseRecursive(body, metaOrigin, verificationHeaderOrigin) +} + +func verifyServiceMessagePart(part stableMarshaler, sigRdr func() *refs.Signature) error { + wrapper := StableMarshalerWrapper{ + SM: part, + } + + return signature.VerifyDataWithSource( + wrapper, + sigRdr, + ) +} diff --git a/api/status/convert.go b/api/status/convert.go new file mode 100644 index 0000000..2612c52 --- /dev/null +++ b/api/status/convert.go @@ -0,0 +1,95 @@ +package status + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/message" + status "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/status/grpc" +) + +func (x *Detail) ToGRPCMessage() grpc.Message { + var m *status.Status_Detail + + if x != nil { + m = new(status.Status_Detail) + + m.SetId(x.id) + m.SetValue(x.val) + } + + return m +} + +func (x *Detail) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*status.Status_Detail) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + x.id = v.GetId() + x.val = v.GetValue() + + return nil +} + +func CodeFromGRPC(v uint32) Code { + return Code(v) +} + +func CodeToGRPC(v Code) uint32 { + return uint32(v) +} + +func (x *Status) ToGRPCMessage() grpc.Message { + var m *status.Status + + if x != nil { + m = new(status.Status) + + m.SetCode(CodeToGRPC(x.code)) + m.SetMessage(x.msg) + + var ds []status.Status_Detail + + if ln := len(x.details); ln > 0 { + ds = make([]status.Status_Detail, 0, ln) + + for i := range ln { + ds = append(ds, *x.details[i].ToGRPCMessage().(*status.Status_Detail)) + } + } + + m.SetDetails(ds) + } + + return m +} + +func (x *Status) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*status.Status) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var ( + ds []Detail + dsV2 = v.GetDetails() + ) + + if dsV2 != nil { + ln := len(dsV2) + + ds = make([]Detail, ln) + + for i := range ln { + if err := ds[i].FromGRPCMessage(&dsV2[i]); err != nil { + return err + } + } + } + + x.details = ds + x.msg = v.GetMessage() + x.code = CodeFromGRPC(v.GetCode()) + + return nil +} diff --git a/api/status/details.go b/api/status/details.go new file mode 100644 index 0000000..5b8f460 --- /dev/null +++ b/api/status/details.go @@ -0,0 +1,8 @@ +package status + +// details for WrongMagicNumber code. +const ( + // DetailIDCorrectMagic is an identifier of details with correct network magic + // which can be attached to WrongMagicNumber code. + DetailIDCorrectMagic = iota +) diff --git a/api/status/grpc/types_frostfs.pb.go b/api/status/grpc/types_frostfs.pb.go new file mode 100644 index 0000000000000000000000000000000000000000..6958eec9fb801ed8dac0f84a54bd849a8d57d5d0 GIT binary patch literal 14147 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 literal 0 HcmV?d00001 diff --git a/api/status/grpc/types_frostfs_fuzz.go b/api/status/grpc/types_frostfs_fuzz.go new file mode 100644 index 0000000..ce9d84e --- /dev/null +++ b/api/status/grpc/types_frostfs_fuzz.go @@ -0,0 +1,26 @@ +//go:build gofuzz +// +build gofuzz + +// Code generated by protoc-gen-go-frostfs. DO NOT EDIT. + +package status + +func DoFuzzProtoStatus(data []byte) int { + msg := new(Status) + if err := msg.UnmarshalProtobuf(data); err != nil { + return 0 + } + _ = msg.MarshalProtobuf(nil) + return 1 +} +func DoFuzzJSONStatus(data []byte) int { + msg := new(Status) + if err := msg.UnmarshalJSON(data); err != nil { + return 0 + } + _, err := msg.MarshalJSON() + if err != nil { + panic(err) + } + return 1 +} diff --git a/api/status/grpc/types_frostfs_test.go b/api/status/grpc/types_frostfs_test.go new file mode 100644 index 0000000..dfc5631 --- /dev/null +++ b/api/status/grpc/types_frostfs_test.go @@ -0,0 +1,21 @@ +//go:build gofuzz +// +build gofuzz + +// Code generated by protoc-gen-go-frostfs. DO NOT EDIT. + +package status + +import ( + testing "testing" +) + +func FuzzProtoStatus(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzProtoStatus(data) + }) +} +func FuzzJSONStatus(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzJSONStatus(data) + }) +} diff --git a/api/status/marshal.go b/api/status/marshal.go new file mode 100644 index 0000000..663ead7 --- /dev/null +++ b/api/status/marshal.go @@ -0,0 +1,92 @@ +package status + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/message" + status "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/status/grpc" + protoutil "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/util/proto" +) + +const ( + _ = iota + detailIDFNum + detailValueFNum +) + +func (x *Detail) StableMarshal(buf []byte) []byte { + if x == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, x.StableSize()) + } + + var offset int + + offset += protoutil.UInt32Marshal(detailIDFNum, buf[offset:], x.id) + protoutil.BytesMarshal(detailValueFNum, buf[offset:], x.val) + + return buf +} + +func (x *Detail) StableSize() (size int) { + if x == nil { + return 0 + } + + size += protoutil.UInt32Size(detailIDFNum, x.id) + size += protoutil.BytesSize(detailValueFNum, x.val) + + return size +} + +func (x *Detail) Unmarshal(data []byte) error { + return message.Unmarshal(x, data, new(status.Status_Detail)) +} + +const ( + _ = iota + statusCodeFNum + statusMsgFNum + statusDetailsFNum +) + +func (x *Status) StableMarshal(buf []byte) []byte { + if x == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, x.StableSize()) + } + + var offset int + + offset += protoutil.UInt32Marshal(statusCodeFNum, buf[offset:], CodeToGRPC(x.code)) + offset += protoutil.StringMarshal(statusMsgFNum, buf[offset:], x.msg) + + for i := range x.details { + offset += protoutil.NestedStructureMarshal(statusDetailsFNum, buf[offset:], &x.details[i]) + } + + return buf +} + +func (x *Status) StableSize() (size int) { + if x == nil { + return 0 + } + + size += protoutil.UInt32Size(statusCodeFNum, CodeToGRPC(x.code)) + size += protoutil.StringSize(statusMsgFNum, x.msg) + + for i := range x.details { + size += protoutil.NestedStructureSize(statusDetailsFNum, &x.details[i]) + } + + return size +} + +func (x *Status) Unmarshal(data []byte) error { + return message.Unmarshal(x, data, new(status.Status)) +} diff --git a/api/status/message_test.go b/api/status/message_test.go new file mode 100644 index 0000000..0185032 --- /dev/null +++ b/api/status/message_test.go @@ -0,0 +1,16 @@ +package status_test + +import ( + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/message" + messagetest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/message/test" + statustest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/status/test" +) + +func TestMessageConvert(t *testing.T) { + messagetest.TestRPCMessage(t, + func(empty bool) message.Message { return statustest.Detail(empty) }, + func(empty bool) message.Message { return statustest.Status(empty) }, + ) +} diff --git a/api/status/status.go b/api/status/status.go new file mode 100644 index 0000000..53d361e --- /dev/null +++ b/api/status/status.go @@ -0,0 +1,103 @@ +package status + +const sectionBitSize = 10 + +// InSections checks if the Code is in [i,j] section list. +func (x Code) InSections(i, j uint32) bool { + return uint32(x) >= i<HA&yPX{Wx>y%$Yly&FEdeRCJ{>Rfa|_X>mtInVUR1z`KL1{2(s#%EVPb zM<40*<2fB4oty{baS=v0;guqjr;EzunHrCETI8i6e?0n9t9MCWFW-lYnHxE%mN&pL3ky9fRb0*37a@u~PyR-T z+UR7)z8r!l`nO}SGlDd;{Hi#!CJF}(tGf-d>v|DHc{=+|Mx#-#hp>@BRS7X%#PUO zgGv{wtXh-Lm&}XcDBJq|q6pc}Xa`j|sE@S_e`h1rbGOt?tYnf{NWQklBUDl*rKDt?j2 zv?iU|&Ag~%it{oJO#naZ%8OQ)s-jzMuB~5~DvGsAmb40!8bjCN3Ok%b^3XzOVRpO7ywz<>!;Lo=NDoKR4H99g{dVmx{P%NX$YbBi^&IAPZCto)Z# zS_cDGVLkfxZ^4vG%zt2WMnb$x;V;v`1c zYA7`iVv(BN-%tk4Kyb{dW8aIyEXxgqEL>8C5Kf68Vc%5Vl)P4zJrs>M;HZLf;gms2 zNq1VO!htBP6umqo?8t$1z-P1!O*p0ehW86R9ZxtU<9vnzR)+v@yg@1f zDJXes^$$FhiBTYpK>b0WI@#I*(X#OC5xNXLWbWMn(JMjZ)N%(R$KNANg2m-4E9dg` za5YLjr%<*t_NjX{rQSJz{~!S3nAfwT(spkLih!Z?VWC#JWVEfr+3UQ{$2IU|jxp_um0GR#U{<8uC-$Xv#*T2T}=6 z0vWcJ*!Lk`**!YK#Rh2#+$r^%FEPM_HS_)$-cSDU4sjD|GC1JYjnnktd6Jo5wIz)a z6w&z_)#*+AzRiw4cS&l9If|Dg5TOB~xoPTox`u z!vtXgruNUzF12^UCuY}M*Uz%9kM@1cNWEzy2gI1+UVy*Xbu zn!{(L)11r(=t@^+qH3yqnLeOLd+X@6}2rtQR^9PAXiAOS$v#dhm-=NDS1{ zZ5h4s5M_V~n%k;QanWlEk9TJ`x{&9NF5&f&N_6T}h}rN=GPt)`4ast&?i`wntO{dg zyHnhteUTr|0=M78%)HB!Jd-p#z_L*bW8;yguIYlJ7@e^~3awl>%*lCT(pnCs%sa%0 zh{tFojlSyw_^n-0+)n!$OV^a% zytby88h2gY_FoF{^KyC2Y~l-uwRGf=1mF-p#fo#=uE<|mD;CsZCBwTKmzYP`+g89y z+4jus;VEG_A|~Exw0j-LAfl6x?TEc*Kmv1(6D=3^?LlO8#Ifo!l6z&3QP}jdn3xe` z?8V@7oj;vUwzF4UK_z+HMDx>>VmF5TmV+&$tUPhI;J#d&3wp`3K`TmROUw|4VeoEa S%K|0B*xz+9=x#c`0{<6TLJFh+ literal 0 HcmV?d00001 diff --git a/api/tombstone/grpc/types_frostfs_fuzz.go b/api/tombstone/grpc/types_frostfs_fuzz.go new file mode 100644 index 0000000..57cfb58 --- /dev/null +++ b/api/tombstone/grpc/types_frostfs_fuzz.go @@ -0,0 +1,26 @@ +//go:build gofuzz +// +build gofuzz + +// Code generated by protoc-gen-go-frostfs. DO NOT EDIT. + +package tombstone + +func DoFuzzProtoTombstone(data []byte) int { + msg := new(Tombstone) + if err := msg.UnmarshalProtobuf(data); err != nil { + return 0 + } + _ = msg.MarshalProtobuf(nil) + return 1 +} +func DoFuzzJSONTombstone(data []byte) int { + msg := new(Tombstone) + if err := msg.UnmarshalJSON(data); err != nil { + return 0 + } + _, err := msg.MarshalJSON() + if err != nil { + panic(err) + } + return 1 +} diff --git a/api/tombstone/grpc/types_frostfs_test.go b/api/tombstone/grpc/types_frostfs_test.go new file mode 100644 index 0000000..8264824 --- /dev/null +++ b/api/tombstone/grpc/types_frostfs_test.go @@ -0,0 +1,21 @@ +//go:build gofuzz +// +build gofuzz + +// Code generated by protoc-gen-go-frostfs. DO NOT EDIT. + +package tombstone + +import ( + testing "testing" +) + +func FuzzProtoTombstone(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzProtoTombstone(data) + }) +} +func FuzzJSONTombstone(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzJSONTombstone(data) + }) +} diff --git a/api/tombstone/json.go b/api/tombstone/json.go new file mode 100644 index 0000000..9b816fe --- /dev/null +++ b/api/tombstone/json.go @@ -0,0 +1,14 @@ +package tombstone + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/message" + tombstone "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/tombstone/grpc" +) + +func (s *Tombstone) MarshalJSON() ([]byte, error) { + return message.MarshalJSON(s) +} + +func (s *Tombstone) UnmarshalJSON(data []byte) error { + return message.UnmarshalJSON(s, data, new(tombstone.Tombstone)) +} diff --git a/api/tombstone/marshal.go b/api/tombstone/marshal.go new file mode 100644 index 0000000..dda9469 --- /dev/null +++ b/api/tombstone/marshal.go @@ -0,0 +1,56 @@ +package tombstone + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/message" + tombstone "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/tombstone/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/util/proto" +) + +const ( + expFNum = 1 + splitIDFNum = 2 + membersFNum = 3 +) + +// StableMarshal marshals unified tombstone message in a protobuf +// compatible way without field order shuffle. +func (s *Tombstone) StableMarshal(buf []byte) []byte { + if s == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, s.StableSize()) + } + + var offset int + + offset += proto.UInt64Marshal(expFNum, buf[offset:], s.exp) + offset += proto.BytesMarshal(splitIDFNum, buf[offset:], s.splitID) + + for i := range s.members { + offset += proto.NestedStructureMarshal(membersFNum, buf[offset:], &s.members[i]) + } + + return buf +} + +// StableSize returns size of tombstone message marshalled by StableMarshal function. +func (s *Tombstone) StableSize() (size int) { + if s == nil { + return 0 + } + + size += proto.UInt64Size(expFNum, s.exp) + size += proto.BytesSize(splitIDFNum, s.splitID) + for i := range s.members { + size += proto.NestedStructureSize(membersFNum, &s.members[i]) + } + + return size +} + +// Unmarshal unmarshal tombstone message from its binary representation. +func (s *Tombstone) Unmarshal(data []byte) error { + return message.Unmarshal(s, data, new(tombstone.Tombstone)) +} diff --git a/api/tombstone/message_test.go b/api/tombstone/message_test.go new file mode 100644 index 0000000..dec17cc --- /dev/null +++ b/api/tombstone/message_test.go @@ -0,0 +1,15 @@ +package tombstone_test + +import ( + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/message" + messagetest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/message/test" + tombstonetest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/tombstone/test" +) + +func TestMessageConvert(t *testing.T) { + messagetest.TestRPCMessage(t, + func(empty bool) message.Message { return tombstonetest.GenerateTombstone(empty) }, + ) +} diff --git a/api/tombstone/test/generate.go b/api/tombstone/test/generate.go new file mode 100644 index 0000000..c71bd81 --- /dev/null +++ b/api/tombstone/test/generate.go @@ -0,0 +1,23 @@ +package tombstonetest + +import ( + "crypto/rand" + + refstest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs/test" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/tombstone" +) + +func GenerateTombstone(empty bool) *tombstone.Tombstone { + m := new(tombstone.Tombstone) + + if !empty { + id := make([]byte, 16) + _, _ = rand.Read(id) + + m.SetExpirationEpoch(89) + m.SetSplitID(id) + m.SetMembers(refstest.GenerateObjectIDs(false)) + } + + return m +} diff --git a/api/tombstone/types.go b/api/tombstone/types.go new file mode 100644 index 0000000..f28c69d --- /dev/null +++ b/api/tombstone/types.go @@ -0,0 +1,57 @@ +package tombstone + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" +) + +// Tombstone is a unified structure of Tombstone +// message from proto definition. +type Tombstone struct { + exp uint64 + + splitID []byte + + members []refs.ObjectID +} + +// GetExpirationEpoch returns number of tombstone expiration epoch. +func (s *Tombstone) GetExpirationEpoch() uint64 { + if s != nil { + return s.exp + } + + return 0 +} + +// SetExpirationEpoch sets number of tombstone expiration epoch. +func (s *Tombstone) SetExpirationEpoch(v uint64) { + s.exp = v +} + +// GetSplitID returns identifier of split object hierarchy. +func (s *Tombstone) GetSplitID() []byte { + if s != nil { + return s.splitID + } + + return nil +} + +// SetSplitID sets identifier of split object hierarchy. +func (s *Tombstone) SetSplitID(v []byte) { + s.splitID = v +} + +// GetMembers returns list of objects to be deleted. +func (s *Tombstone) GetMembers() []refs.ObjectID { + if s != nil { + return s.members + } + + return nil +} + +// SetMembers sets list of objects to be deleted. +func (s *Tombstone) SetMembers(v []refs.ObjectID) { + s.members = v +} diff --git a/api/util/pool/buffer.go b/api/util/pool/buffer.go new file mode 100644 index 0000000..e0a7185 --- /dev/null +++ b/api/util/pool/buffer.go @@ -0,0 +1,54 @@ +package pool + +import ( + "sync" +) + +// Buffer contains a byte slice. +type Buffer struct { + Data []byte +} + +// BufferPool manages a pool of Buffers. +type BufferPool struct { + poolSliceSize uint32 // Size for the buffer slices in the pool. + buffersPool *sync.Pool +} + +// NewBufferPool creates a BufferPool with a specified size. +func NewBufferPool(poolSliceSize uint32) BufferPool { + pool := sync.Pool{ + New: func() any { + return new(Buffer) + }, + } + return BufferPool{poolSliceSize: poolSliceSize, buffersPool: &pool} +} + +// Get retrieves a Buffer from the pool or creates a new one if necessary. +// It ensures the buffer's capacity is at least the specified size. +func (pool BufferPool) Get(size uint32) *Buffer { + result := pool.buffersPool.Get().(*Buffer) + + if cap(result.Data) < int(size) { + result.Data = make([]byte, size) + } else { + result.Data = result.Data[:size] + } + return result +} + +// Put returns a Buffer to the pool if its capacity does not exceed poolSliceSize. +func (pool BufferPool) Put(buf *Buffer) { + if cap(buf.Data) > int(pool.poolSliceSize) { + return + } + + buf.Data = buf.Data[:0] + pool.buffersPool.Put(buf) +} + +// PoolSliceSize returns the size for buffer slices in the pool. +func (pool BufferPool) PoolSliceSize() uint32 { + return uint32(pool.poolSliceSize) +} diff --git a/api/util/pool/marshal.go b/api/util/pool/marshal.go new file mode 100644 index 0000000..107df28 --- /dev/null +++ b/api/util/pool/marshal.go @@ -0,0 +1,7 @@ +package pool + +import ( + "github.com/VictoriaMetrics/easyproto" +) + +var MarshalerPool easyproto.MarshalerPool diff --git a/api/util/proto/encoding/compat.go b/api/util/proto/encoding/compat.go new file mode 100644 index 0000000..09d45e6 --- /dev/null +++ b/api/util/proto/encoding/compat.go @@ -0,0 +1,22 @@ +package encoding + +import ( + _ "google.golang.org/grpc/encoding/proto" // Ensure default codec is registered before our one. + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/protoadapt" +) + +// messageV2Of converts v to a proto.Message. +// This is needed for this library to continue working in presence of external gRPC packages, +// such as opentelemetry gRPC exporter. +// Copied from https://github.com/grpc/grpc-go/blob/e524655becd8d4c7ba9e8687faef456e495e341e/encoding/proto/proto.go#L59. +func messageV2Of(v any) proto.Message { + switch v := v.(type) { + case protoadapt.MessageV1: + return protoadapt.MessageV2Of(v) + case protoadapt.MessageV2: + return v + } + + return nil +} diff --git a/api/util/proto/encoding/json.go b/api/util/proto/encoding/json.go new file mode 100644 index 0000000..3456a40 --- /dev/null +++ b/api/util/proto/encoding/json.go @@ -0,0 +1,48 @@ +package encoding + +import ( + "encoding/json" + "fmt" + + "google.golang.org/grpc/encoding" + "google.golang.org/protobuf/encoding/protojson" +) + +// JSONCodec is easyjson codec used for code generated by protogen. +// It is binary-level compatible with the standard protojson format, thus uses the same name. +type JSONCodec struct{} + +var _ encoding.Codec = JSONCodec{} + +func init() { + encoding.RegisterCodec(JSONCodec{}) +} + +// Name implements the encoding.Codec interface. +func (JSONCodec) Name() string { return "json" } + +// Marshal implements the encoding.Codec interface. +func (JSONCodec) Marshal(v any) ([]byte, error) { + switch v := v.(type) { + case json.Marshaler: + return json.Marshal(v) + default: + if v := messageV2Of(v); v != nil { + return protojson.Marshal(v) + } + return nil, fmt.Errorf("failed to marshal, message is %T, want proto.Message", v) + } +} + +// Unmarshal implements the encoding.Codec interface. +func (JSONCodec) Unmarshal(data []byte, v any) error { + switch v := v.(type) { + case json.Unmarshaler: + return json.Unmarshal(data, v) + default: + if v := messageV2Of(v); v != nil { + return protojson.Unmarshal(data, v) + } + return fmt.Errorf("failed to unmarshal, message is %T, want proto.Message", v) + } +} diff --git a/api/util/proto/encoding/proto.go b/api/util/proto/encoding/proto.go new file mode 100644 index 0000000..5f3c556 --- /dev/null +++ b/api/util/proto/encoding/proto.go @@ -0,0 +1,57 @@ +package encoding + +import ( + "fmt" + + "google.golang.org/grpc/encoding" + "google.golang.org/protobuf/proto" +) + +// ProtoCodec is easyproto codec used for code generated by protogen. +// It is binary-level compatible with the standard proto codec, thus uses the same name. +type ProtoCodec struct{} + +// ProtoMarshaler is an interface accepted by ProtoCodec.Marshal. +type ProtoMarshaler interface { + MarshalProtobuf([]byte) []byte +} + +// ProtoUnmarshaler is an interface accepted by ProtoCodec.Unmarshal. +type ProtoUnmarshaler interface { + UnmarshalProtobuf([]byte) error +} + +var _ encoding.Codec = ProtoCodec{} + +func init() { + encoding.RegisterCodec(ProtoCodec{}) +} + +// Name implements the encoding.Codec interface. +func (ProtoCodec) Name() string { return "proto" } + +// Marshal implements the encoding.Codec interface. +func (ProtoCodec) Marshal(v any) ([]byte, error) { + switch v := v.(type) { + case ProtoMarshaler: + return v.MarshalProtobuf(nil), nil + default: + if v := messageV2Of(v); v != nil { + return proto.Marshal(v) + } + return nil, fmt.Errorf("failed to marshal, message is %T, want proto.Message", v) + } +} + +// Unmarshal implements the encoding.Codec interface. +func (ProtoCodec) Unmarshal(data []byte, v any) error { + switch v := v.(type) { + case ProtoUnmarshaler: + return v.UnmarshalProtobuf(data) + default: + if v := messageV2Of(v); v != nil { + return proto.Unmarshal(data, v) + } + return fmt.Errorf("failed to unmarshal, message is %T, want proto.Message", v) + } +} diff --git a/api/util/proto/marshal.go b/api/util/proto/marshal.go new file mode 100644 index 0000000..5016255 --- /dev/null +++ b/api/util/proto/marshal.go @@ -0,0 +1,413 @@ +/* +This package contains help functions for stable marshaller. Their usage is +totally optional. One can implement fast stable marshaller without these +runtime function calls. +*/ + +package proto + +import ( + "encoding/binary" + "math" + "math/bits" + + "google.golang.org/protobuf/encoding/protowire" +) + +type ( + stableMarshaler interface { + StableMarshal([]byte) []byte + stableSizer + } + + stableSizer interface { + StableSize() int + } + + setMarshalData[T any] interface { + SetMarshalData([]byte) + StableSize() int + ~*T + } +) + +func BytesMarshal(field int, buf, v []byte) int { + return bytesMarshal(field, buf, v) +} + +func BytesSize(field int, v []byte) int { + return bytesSize(field, v) +} + +func bytesMarshal[T ~[]byte | ~string](field int, buf []byte, v T) int { + if len(v) == 0 { + return 0 + } + return bytesMarshalNoCheck(field, buf, v) +} + +func bytesMarshalNoCheck[T ~[]byte | ~string](field int, buf []byte, v T) int { + prefix := protowire.EncodeTag(protowire.Number(field), protowire.BytesType) + + // buf length check can prevent panic at PutUvarint, but it will make + // marshaller a bit slower. + i := binary.PutUvarint(buf, uint64(prefix)) + i += binary.PutUvarint(buf[i:], uint64(len(v))) + i += copy(buf[i:], v) + + return i +} + +func bytesSize[T ~[]byte | ~string](field int, v T) int { + if len(v) == 0 { + return 0 + } + return bytesSizeNoCheck(field, v) +} + +func bytesSizeNoCheck[T ~[]byte | ~string](field int, v T) int { + return protowire.SizeGroup(protowire.Number(field), protowire.SizeBytes(len(v))) +} + +func StringMarshal(field int, buf []byte, v string) int { + return bytesMarshal(field, buf, v) +} + +func StringSize(field int, v string) int { + return bytesSize(field, v) +} + +func BoolMarshal(field int, buf []byte, v bool) int { + if !v { + return 0 + } + + prefix := protowire.EncodeTag(protowire.Number(field), protowire.VarintType) + + // buf length check can prevent panic at PutUvarint, but it will make + // marshaller a bit slower. + i := binary.PutUvarint(buf, uint64(prefix)) + const boolTrueValue = 0x1 + buf[i] = boolTrueValue + + return i + 1 +} + +func BoolSize(field int, v bool) int { + if !v { + return 0 + } + const boolLength = 1 + return protowire.SizeGroup(protowire.Number(field), boolLength) +} + +func UInt64Marshal(field int, buf []byte, v uint64) int { + if v == 0 { + return 0 + } + + prefix := protowire.EncodeTag(protowire.Number(field), protowire.VarintType) + + // buf length check can prevent panic at PutUvarint, but it will make + // marshaller a bit slower. + i := binary.PutUvarint(buf, uint64(prefix)) + i += binary.PutUvarint(buf[i:], v) + + return i +} + +func UInt64Size(field int, v uint64) int { + if v == 0 { + return 0 + } + return protowire.SizeGroup(protowire.Number(field), protowire.SizeVarint(v)) +} + +func Int64Marshal(field int, buf []byte, v int64) int { + return UInt64Marshal(field, buf, uint64(v)) +} + +func Int64Size(field int, v int64) int { + return UInt64Size(field, uint64(v)) +} + +func UInt32Marshal(field int, buf []byte, v uint32) int { + return UInt64Marshal(field, buf, uint64(v)) +} + +func UInt32Size(field int, v uint32) int { + return UInt64Size(field, uint64(v)) +} + +func Int32Marshal(field int, buf []byte, v int32) int { + return UInt64Marshal(field, buf, uint64(uint32(v))) +} + +func Int32Size(field int, v int32) int { + return UInt64Size(field, uint64(uint32(v))) +} + +func EnumMarshal(field int, buf []byte, v int32) int { + return UInt64Marshal(field, buf, uint64(uint32(v))) +} + +func EnumSize(field int, v int32) int { + return UInt64Size(field, uint64(uint32(v))) +} + +func RepeatedBytesMarshal(field int, buf []byte, v [][]byte) int { + var offset int + + for i := range v { + offset += bytesMarshalNoCheck(field, buf[offset:], v[i]) + } + + return offset +} + +func RepeatedBytesSize(field int, v [][]byte) (size int) { + for i := range v { + size += bytesSizeNoCheck(field, v[i]) + } + + return size +} + +func RepeatedStringMarshal(field int, buf []byte, v []string) int { + var offset int + + for i := range v { + offset += bytesMarshalNoCheck(field, buf[offset:], v[i]) + } + + return offset +} + +func RepeatedStringSize(field int, v []string) (size int) { + for i := range v { + size += bytesSizeNoCheck(field, v[i]) + } + + return size +} + +func repeatedUIntSize[T ~uint64 | ~int64 | ~uint32 | ~int32](field int, v []T) (size, arraySize int) { + if len(v) == 0 { + return 0, 0 + } + + for i := range v { + arraySize += protowire.SizeVarint(uint64(v[i])) + } + + size = protowire.SizeGroup(protowire.Number(field), protowire.SizeBytes(arraySize)) + + return +} + +func repeatedUIntMarshal[T ~uint64 | ~int64 | ~uint32 | ~int32](field int, buf []byte, v []T) int { + if len(v) == 0 { + return 0 + } + + prefix := protowire.EncodeTag(protowire.Number(field), protowire.BytesType) + offset := binary.PutUvarint(buf, uint64(prefix)) + + _, arrSize := repeatedUIntSize(field, v) + offset += binary.PutUvarint(buf[offset:], uint64(arrSize)) + for i := range v { + offset += binary.PutUvarint(buf[offset:], uint64(v[i])) + } + + return offset +} + +func RepeatedUInt64Marshal(field int, buf []byte, v []uint64) int { + return repeatedUIntMarshal(field, buf, v) +} + +func RepeatedUInt64Size(field int, v []uint64) (size, arraySize int) { + return repeatedUIntSize(field, v) +} + +func RepeatedInt64Marshal(field int, buf []byte, v []int64) int { + return repeatedUIntMarshal(field, buf, v) +} + +func RepeatedInt64Size(field int, v []int64) (size, arraySize int) { + return repeatedUIntSize(field, v) +} + +func RepeatedUInt32Marshal(field int, buf []byte, v []uint32) int { + return repeatedUIntMarshal(field, buf, v) +} + +func RepeatedUInt32Size(field int, v []uint32) (size, arraySize int) { + return repeatedUIntSize(field, v) +} + +func RepeatedInt32Marshal(field int, buf []byte, v []int32) int { + if len(v) == 0 { + return 0 + } + + prefix := protowire.EncodeTag(protowire.Number(field), protowire.BytesType) + offset := binary.PutUvarint(buf, uint64(prefix)) + _, arrSize := RepeatedInt32Size(field, v) + offset += binary.PutUvarint(buf[offset:], uint64(arrSize)) + for i := range v { + offset += binary.PutUvarint(buf[offset:], uint64(uint32(v[i]))) + } + return offset +} + +func RepeatedInt32Size(field int, v []int32) (size, arraySize int) { + if len(v) == 0 { + return 0, 0 + } + for i := range v { + arraySize += protowire.SizeVarint(uint64(uint32(v[i]))) + } + return protowire.SizeGroup(protowire.Number(field), protowire.SizeBytes(arraySize)), arraySize +} + +// VarUIntSize returns length of varint byte sequence for uint64 value 'x'. +func VarUIntSize(x uint64) int { + return (bits.Len64(x|1) + 6) / 7 +} + +type ptrStableMarshaler[T any] interface { + stableMarshaler + ~*T +} + +type ptrStableSizer[T any] interface { + stableSizer + ~*T +} + +func NestedStructureMarshal[T any, M ptrStableMarshaler[T]](field int64, buf []byte, v M) int { + if v == nil { + return 0 + } + + return NestedStructureMarshalUnchecked(field, buf, v) +} + +func NestedStructureMarshalUnchecked[T stableMarshaler](field int64, buf []byte, v T) int { + n := v.StableSize() + prefix := protowire.EncodeTag(protowire.Number(field), protowire.BytesType) + offset := binary.PutUvarint(buf, prefix) + offset += binary.PutUvarint(buf[offset:], uint64(n)) + v.StableMarshal(buf[offset:]) + + return offset + n +} + +// NestedStructureSetMarshalData calculates offset for field in parentData +// and calls SetMarshalData for nested structure. +// +// Returns marshalled data length of nested structure. +func NestedStructureSetMarshalData[T any, M setMarshalData[T]](field int64, parentData []byte, v M) int { + if v == nil { + return 0 + } + + if parentData == nil { + v.SetMarshalData(nil) + return 0 + } + + n := v.StableSize() + buf := make([]byte, binary.MaxVarintLen64) + prefix := protowire.EncodeTag(protowire.Number(field), protowire.BytesType) + offset := binary.PutUvarint(buf, prefix) + offset += binary.PutUvarint(buf, uint64(n)) + + v.SetMarshalData(parentData[offset : offset+n]) + + return offset + n +} + +func NestedStructureSize[T any, M ptrStableSizer[T]](field int64, v M) (size int) { + if v == nil { + return 0 + } + + return NestedStructureSizeUnchecked(field, v) +} + +func NestedStructureSizeUnchecked[T stableSizer](field int64, v T) int { + n := v.StableSize() + return protowire.SizeGroup(protowire.Number(field), protowire.SizeBytes(n)) +} + +func Fixed64Marshal(field int, buf []byte, v uint64) int { + if v == 0 { + return 0 + } + + prefix := protowire.EncodeTag(protowire.Number(field), protowire.Fixed64Type) + + // buf length check can prevent panic at PutUvarint, but it will make + // marshaller a bit slower. + i := binary.PutUvarint(buf, uint64(prefix)) + binary.LittleEndian.PutUint64(buf[i:], v) + + return i + 8 +} + +func Fixed64Size(fNum int, v uint64) int { + if v == 0 { + return 0 + } + return protowire.SizeGroup(protowire.Number(fNum), protowire.SizeFixed64()) +} + +func Float64Marshal(field int, buf []byte, v float64) int { + if v == 0 { + return 0 + } + + prefix := protowire.EncodeTag(protowire.Number(field), protowire.Fixed64Type) + + i := binary.PutUvarint(buf, uint64(prefix)) + binary.LittleEndian.PutUint64(buf[i:], math.Float64bits(v)) + + return i + 8 +} + +func Float64Size(fNum int, v float64) int { + if v == 0 { + return 0 + } + return protowire.SizeGroup(protowire.Number(fNum), protowire.SizeFixed64()) +} + +// Fixed32Marshal encodes uint32 value to Protocol Buffers fixed32 field with specified number, +// and writes it to specified buffer. Returns number of bytes written. +// +// Panics if the buffer is undersized. +func Fixed32Marshal(field int, buf []byte, v uint32) int { + if v == 0 { + return 0 + } + + prefix := protowire.EncodeTag(protowire.Number(field), protowire.Fixed32Type) + + // buf length check can prevent panic at PutUvarint, but it will make + // marshaller a bit slower. + i := binary.PutUvarint(buf, uint64(prefix)) + binary.LittleEndian.PutUint32(buf[i:], v) + + return i + 4 +} + +// Fixed32Size returns number of bytes required to encode uint32 value to Protocol Buffers fixed32 field +// with specified number. +func Fixed32Size(fNum int, v uint32) int { + if v == 0 { + return 0 + } + return protowire.SizeGroup(protowire.Number(fNum), protowire.SizeFixed32()) +} diff --git a/api/util/proto/marshal_test.go b/api/util/proto/marshal_test.go new file mode 100644 index 0000000..d40ec94 --- /dev/null +++ b/api/util/proto/marshal_test.go @@ -0,0 +1,255 @@ +package proto_test + +import ( + "math" + "math/rand" + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/util/proto/test" + generated "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/util/proto/test/custom" + "github.com/stretchr/testify/require" + "google.golang.org/protobuf/encoding/protojson" + goproto "google.golang.org/protobuf/proto" +) + +type protoInt interface { + ~int32 | ~uint32 | ~int64 | ~uint64 +} + +func nonZero[T protoInt]() T { + var r T + for r == 0 { + r = T(rand.Uint64()) + } + return r +} + +func TestStableMarshalSingle(t *testing.T) { + t.Run("empty", func(t *testing.T) { + t.Run("proto", func(t *testing.T) { + input := &generated.Primitives{} + require.Zero(t, input.StableSize()) + + r := input.MarshalProtobuf(nil) + require.Empty(t, r) + }) + t.Run("json", func(t *testing.T) { + input := &generated.Primitives{} + r, err := input.MarshalJSON() + require.NoError(t, err) + require.NotEmpty(t, r) + + var actual test.Primitives + require.NoError(t, protojson.Unmarshal(r, &actual)) + + t.Run("protojson compatibility", func(t *testing.T) { + data, err := protojson.MarshalOptions{EmitUnpopulated: true}.Marshal(&actual) + require.NoError(t, err) + require.JSONEq(t, string(data), string(r)) + }) + + var actualFrostfs generated.Primitives + require.NoError(t, actualFrostfs.UnmarshalJSON(r)) + if len(actualFrostfs.FieldA) == 0 { + actualFrostfs.FieldA = nil + } + require.Equal(t, input, &actualFrostfs) + + primitivesEqual(t, input, &actual) + }) + }) + + marshalCases := []struct { + name string + input *generated.Primitives + }{ + {name: "bytes", input: &generated.Primitives{FieldA: []byte{1, 2, 3}}}, + {name: "string", input: &generated.Primitives{FieldB: "123"}}, + {name: "bool", input: &generated.Primitives{FieldC: true}}, + {name: "int32", input: &generated.Primitives{FieldD: -10}}, + {name: "uint32", input: &generated.Primitives{FieldE: nonZero[uint32]()}}, + {name: "int64", input: &generated.Primitives{FieldF: nonZero[int64]()}}, + {name: "uint64", input: &generated.Primitives{FieldG: nonZero[uint64]()}}, + {name: "uint64", input: &generated.Primitives{FieldI: nonZero[uint64]()}}, + {name: "float64", input: &generated.Primitives{FieldJ: math.Float64frombits(12345677890)}}, + {name: "fixed32", input: &generated.Primitives{FieldK: nonZero[uint32]()}}, + {name: "enum, positive", input: &generated.Primitives{FieldH: generated.Primitives_POSITIVE}}, + {name: "enum, negative", input: &generated.Primitives{FieldH: generated.Primitives_NEGATIVE}}, + {name: "oneof, first", input: &generated.Primitives{FieldM: &generated.Primitives_FieldMa{FieldMa: []byte{4, 2}}}}, + {name: "oneof, second", input: &generated.Primitives{FieldM: &generated.Primitives_FieldMe{FieldMe: nonZero[uint32]()}}}, + } + for _, tc := range marshalCases { + t.Run(tc.name, func(t *testing.T) { + t.Run("proto", func(t *testing.T) { + r := tc.input.MarshalProtobuf(nil) + require.Equal(t, len(r), tc.input.StableSize()) + require.NotEmpty(t, r) + + var actual test.Primitives + require.NoError(t, goproto.Unmarshal(r, &actual)) + + var actualFrostfs generated.Primitives + require.NoError(t, actualFrostfs.UnmarshalProtobuf(r)) + require.Equal(t, tc.input, &actualFrostfs) + + primitivesEqual(t, tc.input, &actual) + }) + t.Run("json", func(t *testing.T) { + r, err := tc.input.MarshalJSON() + require.NoError(t, err) + require.NotEmpty(t, r) + + var actual test.Primitives + require.NoError(t, protojson.Unmarshal(r, &actual)) + + t.Run("protojson compatibility", func(t *testing.T) { + data, err := protojson.MarshalOptions{EmitUnpopulated: true}.Marshal(&actual) + require.NoError(t, err) + require.JSONEq(t, string(data), string(r)) + }) + + var actualFrostfs generated.Primitives + require.NoError(t, actualFrostfs.UnmarshalJSON(r)) + if len(actualFrostfs.FieldA) == 0 { + actualFrostfs.FieldA = nil + } + require.Equal(t, tc.input, &actualFrostfs) + + primitivesEqual(t, tc.input, &actual) + }) + }) + } +} + +func primitivesEqual(t *testing.T, a *generated.Primitives, b *test.Primitives) { + // Compare each field directly, because proto-generated code has private fields. + require.Equal(t, len(a.FieldA), len(b.FieldA)) + if len(a.FieldA) != 0 { + require.Equal(t, a.FieldA, b.FieldA) + } + require.Equal(t, a.FieldB, b.FieldB) + require.Equal(t, a.FieldC, b.FieldC) + require.Equal(t, a.FieldD, b.FieldD) + require.Equal(t, a.FieldE, b.FieldE) + require.Equal(t, a.FieldF, b.FieldF) + require.Equal(t, a.FieldG, b.FieldG) + require.Equal(t, a.FieldI, b.FieldI) + require.Equal(t, a.FieldJ, b.FieldJ) + require.Equal(t, a.FieldK, b.FieldK) + require.EqualValues(t, a.FieldH, b.FieldH) + require.Equal(t, a.GetFieldMa(), b.GetFieldMa()) + require.Equal(t, a.GetFieldMe(), b.GetFieldMe()) + require.Equal(t, a.GetFieldAux().GetInnerField(), b.GetFieldAux().GetInnerField()) +} + +func repPrimitivesEqual(t *testing.T, a *generated.RepPrimitives, b *test.RepPrimitives) { + // Compare each field directly, because proto-generated code has private fields. + require.Equal(t, a.FieldA, b.FieldA) + require.Equal(t, a.FieldB, b.FieldB) + require.Equal(t, a.FieldC, b.FieldC) + require.Equal(t, a.FieldD, b.FieldD) + require.Equal(t, a.FieldE, b.FieldE) + require.Equal(t, a.FieldF, b.FieldF) + require.Equal(t, a.FieldFu, b.FieldFu) + require.Equal(t, len(a.GetFieldAux()), len(b.GetFieldAux())) + for i := range a.FieldAux { + require.Equal(t, a.GetFieldAux()[i].GetInnerField(), b.GetFieldAux()[i].GetInnerField()) + } +} + +func randIntSlice[T protoInt](n int, includeZero bool) []T { + r := make([]T, n) + if n == 0 { + return r + } + for i := range r { + r[i] = T(rand.Uint64()) + } + if includeZero { + r[0] = 0 + } + return r +} + +func uint32SliceToAux(s []uint32) []generated.RepPrimitives_Aux { + r := make([]generated.RepPrimitives_Aux, len(s)) + for i := range s { + r[i] = generated.RepPrimitives_Aux{InnerField: s[i]} + } + return r +} + +func TestStableMarshalRep(t *testing.T) { + t.Run("empty", func(t *testing.T) { + marshalCases := []struct { + name string + input *generated.RepPrimitives + }{ + {name: "default", input: &generated.RepPrimitives{}}, + {name: "bytes", input: &generated.RepPrimitives{FieldA: [][]byte{}}}, + {name: "string", input: &generated.RepPrimitives{FieldB: []string{}}}, + {name: "int32", input: &generated.RepPrimitives{FieldC: []int32{}}}, + {name: "uint32", input: &generated.RepPrimitives{FieldD: []uint32{}}}, + {name: "int64", input: &generated.RepPrimitives{FieldE: []int64{}}}, + {name: "uint64", input: &generated.RepPrimitives{FieldF: []uint64{}}}, + {name: "uint64", input: &generated.RepPrimitives{FieldFu: []uint64{}}}, + } + + for _, tc := range marshalCases { + t.Run(tc.name, func(t *testing.T) { + require.Zero(t, tc.input.StableSize()) + + r := tc.input.MarshalProtobuf(nil) + require.Empty(t, r) + }) + } + }) + + marshalCases := []struct { + name string + input *generated.RepPrimitives + }{ + {name: "bytes", input: &generated.RepPrimitives{FieldA: [][]byte{{1, 2, 3}}}}, + {name: "string", input: &generated.RepPrimitives{FieldB: []string{"123"}}}, + {name: "int32", input: &generated.RepPrimitives{FieldC: randIntSlice[int32](1, true)}}, + {name: "int32", input: &generated.RepPrimitives{FieldC: randIntSlice[int32](2, true)}}, + {name: "int32", input: &generated.RepPrimitives{FieldC: randIntSlice[int32](2, false)}}, + {name: "uint32", input: &generated.RepPrimitives{FieldD: randIntSlice[uint32](1, true)}}, + {name: "uint32", input: &generated.RepPrimitives{FieldD: randIntSlice[uint32](2, true)}}, + {name: "uint32", input: &generated.RepPrimitives{FieldD: randIntSlice[uint32](2, false)}}, + {name: "int64", input: &generated.RepPrimitives{FieldE: randIntSlice[int64](1, true)}}, + {name: "int64", input: &generated.RepPrimitives{FieldE: randIntSlice[int64](2, true)}}, + {name: "int64", input: &generated.RepPrimitives{FieldE: randIntSlice[int64](2, false)}}, + {name: "uint64", input: &generated.RepPrimitives{FieldF: randIntSlice[uint64](1, true)}}, + {name: "uint64", input: &generated.RepPrimitives{FieldF: randIntSlice[uint64](2, true)}}, + {name: "uint64", input: &generated.RepPrimitives{FieldF: randIntSlice[uint64](2, false)}}, + {name: "uint64", input: &generated.RepPrimitives{FieldFu: randIntSlice[uint64](1, true)}}, + {name: "uint64", input: &generated.RepPrimitives{FieldFu: randIntSlice[uint64](2, true)}}, + {name: "uint64", input: &generated.RepPrimitives{FieldFu: randIntSlice[uint64](2, false)}}, + {name: "message", input: &generated.RepPrimitives{FieldAux: uint32SliceToAux(randIntSlice[uint32](1, true))}}, + {name: "message", input: &generated.RepPrimitives{FieldAux: uint32SliceToAux(randIntSlice[uint32](2, true))}}, + {name: "message", input: &generated.RepPrimitives{FieldAux: uint32SliceToAux(randIntSlice[uint32](2, false))}}, + } + for _, tc := range marshalCases { + t.Run(tc.name, func(t *testing.T) { + t.Run("proto", func(t *testing.T) { + r := tc.input.MarshalProtobuf(nil) + require.Equal(t, len(r), tc.input.StableSize()) + require.NotEmpty(t, r) + + var actual test.RepPrimitives + require.NoError(t, goproto.Unmarshal(r, &actual)) + repPrimitivesEqual(t, tc.input, &actual) + }) + t.Run("json", func(t *testing.T) { + r, err := tc.input.MarshalJSON() + require.NoError(t, err) + require.NotEmpty(t, r) + + var actual test.RepPrimitives + require.NoError(t, protojson.Unmarshal(r, &actual)) + repPrimitivesEqual(t, tc.input, &actual) + }) + }) + } +} diff --git a/api/util/proto/test/custom/test_frostfs.pb.go b/api/util/proto/test/custom/test_frostfs.pb.go new file mode 100644 index 0000000000000000000000000000000000000000..c1530e092d7a2db667ffafb14a5f96d06b178f54 GIT binary patch literal 34806 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 f1y`YCIOYCsj0R&U 0 {") + { + g.P("src, err = fc.NextField(src)") + g.P("if err != nil { return ", fmtPackage.Ident("Errorf"), `("cannot read next field in %s", "`, msg.GoIdent.GoName, `")}`) + g.P("switch fc.FieldNum {") + { + for _, f := range msg.Fields { + g.P("case ", f.Desc.Number(), ":", " // ", f.GoName) + emitFieldUnmarshal(g, f) + } + } + g.P("}") + } + g.P("}") + + g.P("return nil") + g.P("}") +} + +func emitFieldUnmarshal(g *protogen.GeneratedFile, f *protogen.Field) { + name := castFieldName(f) + if f.Desc.Kind() == protoreflect.MessageKind { + g.P("data, ok := fc.MessageData()") + g.P(`if !ok { return fmt.Errorf("cannot unmarshal field %s", "`, f.GoName, `") }`) + if f.Desc.IsList() { + g.P(name, " = append(", name, ", ", fieldType(g, f)[2:], "{})") + g.P("ff := &", name, "[len(", name, ")-1]") + name = "ff" + } else if f.Oneof != nil { + const tmp = "oneofField" + g.P(tmp, " := &", f.GoIdent, "{", f.GoName, ": ", "new(", fieldType(g, f)[1:], ")}") + defer g.P(name, " = ", tmp) + + name = tmp + "." + f.GoName + } else { + g.P(name, " = new(", fieldType(g, f)[1:], ")") + } + + g.P(`if err := `, name, `.UnmarshalProtobuf(data); err != nil { return fmt.Errorf("unmarshal: %w", err)}`) + return + } + + getter, _ := easyprotoKindInfo(f.Desc.Kind()) + + if f.Desc.IsList() && (f.Desc.Kind() == protoreflect.BytesKind || f.Desc.Kind() == protoreflect.StringKind || f.Desc.Kind() == protoreflect.Uint64Kind && !f.Desc.IsPacked()) { + g.P("data, ok := fc.", getter, "()") + g.P(`if !ok { return fmt.Errorf("cannot unmarshal field %s", "`, f.GoName, `") }`) + g.P(name, " = append(", name, ", data)") + return + } + + if f.Desc.IsList() { + g.P("data, ok := fc.Unpack", getter, "s(nil)") + } else { + g.P("data, ok := fc.", getter, "()") + } + + g.P(`if !ok { return fmt.Errorf("cannot unmarshal field %s", "`, f.GoName, `") }`) + value := "data" + if f.Desc.Kind() == protoreflect.EnumKind { + value = fieldType(g, f).String() + "(data)" + } + + if f.Oneof == nil { + g.P("x.", f.GoName, " = ", value) + } else { + g.P("x.", f.Oneof.GoName, " = &", f.GoIdent, "{", f.GoName, ": data}") + } +} + +func emitMarshalProtobuf(g *protogen.GeneratedFile, msg *protogen.Message) { + g.P("// MarshalProtobuf implements the encoding.ProtoMarshaler interface.") + g.P("func (x *", msg.GoIdent.GoName, ") MarshalProtobuf(dst []byte) []byte {") + g.P("m := ", mp, ".Get()") + g.P("defer ", mp, ".Put(m)") + g.P("x.EmitProtobuf(m.MessageMarshaler())") + g.P("dst = m.Marshal(dst)") + g.P("return dst") + g.P("}\n") + + g.P("func (x *", msg.GoIdent.GoName, ") EmitProtobuf(mm *", easyprotoPackage.Ident("MessageMarshaler"), ") {") + if len(msg.Fields) != 0 { + fs := sortFields(msg.Fields) + + g.P("if x == nil { return }") + for _, f := range fs { + emitFieldMarshal(g, f) + } + } + g.P("}") +} + +func emitMarshalOneof(g *protogen.GeneratedFile, f *protogen.Field) { + name := "x." + f.Oneof.GoName + g.P("if inner, ok := ", name, ".(*", f.GoIdent.GoName, "); ok {") + defer g.P("}") + emitMarshalRaw(g, f, "inner."+f.GoName) +} + +// easyprotoKindInfo returns string name for kind, used in easyproto methods. +// The second return value is a condition to test for the default value of kind. +func easyprotoKindInfo(kind protoreflect.Kind) (string, func(string) string) { + switch kind { + case protoreflect.BoolKind: + return "Bool", identity + case protoreflect.EnumKind: + return "Int32", notZero + case protoreflect.Int32Kind: + return "Int32", notZero + case protoreflect.Sint32Kind: + return "Sint32", notZero + case protoreflect.Uint32Kind: + return "Uint32", notZero + case protoreflect.Int64Kind: + return "Int64", notZero + case protoreflect.Sint64Kind: + return "Sint64", notZero + case protoreflect.Uint64Kind: + return "Uint64", notZero + case protoreflect.Sfixed32Kind: + return "Sfixed32", notZero + case protoreflect.Fixed32Kind: + return "Fixed32", notZero + case protoreflect.FloatKind: + return "Float", notZero + case protoreflect.Sfixed64Kind: + return "Sfixed64", notZero + case protoreflect.Fixed64Kind: + return "Fixed64", notZero + case protoreflect.DoubleKind: + return "Double", notZero + case protoreflect.StringKind: + return "String", notEmpty + case protoreflect.BytesKind: + return "Bytes", notEmpty + case protoreflect.GroupKind: + panic("unimplemented") + default: + panic("unreachable") + } +} + +func emitFieldMarshal(g *protogen.GeneratedFile, f *protogen.Field) { + if f.Oneof != nil { + emitMarshalOneof(g, f) + return + } + + emitMarshalRaw(g, f, castFieldName(f)) +} + +func emitMarshalRaw(g *protogen.GeneratedFile, f *protogen.Field, name string) { + if f.Desc.Kind() == protoreflect.MessageKind { + if f.Desc.IsList() { + g.P("for i := range ", name, " {") + defer g.P("}") + + name += "[i]" + } else { + g.P("if ", notNil(name), " {") + defer g.P("}") + } + + g.P(name, ".EmitProtobuf(mm.AppendMessage(", f.Desc.Number(), "))") + return + } + + method, cond := easyprotoKindInfo(f.Desc.Kind()) + method = "Append" + method + if f.Desc.IsList() && !f.Desc.IsPacked() { + g.P("for j := range ", name, " {") + g.P("mm.", method, "(", f.Desc.Number(), ", ", name, "[j])") + g.P("}") + return + } + + if f.Desc.IsList() { + method += "s" + g.P("if ", notEmpty(name), "{") + } else { + g.P("if ", cond(name), " {") + } + + g.P("mm.", method, "(", f.Desc.Number(), ", ", name, ")") + g.P("}") +} diff --git a/api/util/protogen/internalgengo/proto_field_type.go b/api/util/protogen/internalgengo/proto_field_type.go new file mode 100644 index 0000000..0096751 --- /dev/null +++ b/api/util/protogen/internalgengo/proto_field_type.go @@ -0,0 +1,59 @@ +package internalgengo + +import ( + "google.golang.org/protobuf/compiler/protogen" + "google.golang.org/protobuf/reflect/protoreflect" +) + +type structField string + +func (f structField) String() string { + return string(f) +} + +func (f structField) PointerTo() structField { + return "*" + f +} + +func (f structField) SliceOf() structField { + return "[]" + f +} + +func fieldType(g *protogen.GeneratedFile, field *protogen.Field) structField { + var typ structField + switch field.Desc.Kind() { + case protoreflect.BoolKind: + typ = "bool" + case protoreflect.EnumKind: + typ = structField(g.QualifiedGoIdent(field.Enum.GoIdent)) + case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind: + typ = "int32" + case protoreflect.Uint32Kind, protoreflect.Fixed32Kind: + typ = "uint32" + case protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind: + typ = "int64" + case protoreflect.Uint64Kind, protoreflect.Fixed64Kind: + typ = "uint64" + case protoreflect.FloatKind: + typ = "float32" + case protoreflect.DoubleKind: + typ = "float64" + case protoreflect.StringKind: + typ = "string" + case protoreflect.BytesKind: + typ = "[]byte" + case protoreflect.MessageKind: + typ = structField(g.QualifiedGoIdent(field.Message.GoIdent)) + if !field.Desc.IsList() { + typ = typ.PointerTo() + } + case protoreflect.GroupKind: + panic("unimplemented") + } + + if field.Desc.IsList() { + typ = "[]" + typ + } + + return typ +} diff --git a/api/util/protogen/internalgengo/proto_stable_compat.go b/api/util/protogen/internalgengo/proto_stable_compat.go new file mode 100644 index 0000000..3c4670c --- /dev/null +++ b/api/util/protogen/internalgengo/proto_stable_compat.go @@ -0,0 +1,124 @@ +package internalgengo + +import ( + "google.golang.org/protobuf/compiler/protogen" + "google.golang.org/protobuf/reflect/protoreflect" +) + +var protowirePackage = protogen.GoImportPath("google.golang.org/protobuf/encoding/protowire") + +func emitStableSize(g *protogen.GeneratedFile, msg *protogen.Message) { + fs := sortFields(msg.Fields) + + g.P("// StableSize returns the size of x in protobuf format.") + g.P("//") + g.P("// Structures with the same field values have the same binary size.") + g.P("func (x *", msg.GoIdent.GoName, ") StableSize() (size int) {") + g.P("if x == nil { return 0 }") + if len(fs) != 0 { + for _, f := range fs { + if f.Desc.IsList() && marshalers[f.Desc.Kind()].RepeatedDouble && !(f.Desc.Kind() == protoreflect.Uint64Kind && !f.Desc.IsPacked()) { + g.P("var n int") + break + } + } + for _, f := range fs { + emitFieldSize(g, f) + } + } + g.P("return size") + g.P("}\n") +} + +func emitSignatureMethods(g *protogen.GeneratedFile, msg *protogen.Message) { + // SignedDataSize implementation (only for requests and responses). + g.P("// ReadSignedData fills buf with signed data of x.") + g.P("// If buffer length is less than x.SignedDataSize(), new buffer is allocated.") + g.P("//") + g.P("// Returns any error encountered which did not allow writing the data completely.") + g.P("// Otherwise, returns the buffer in which the data is written.") + g.P("//") + g.P("// Structures with the same field values have the same signed data.") + g.P("func (x *", msg.GoIdent.GoName, ") SignedDataSize() int {") + g.P("return x.GetBody().StableSize()") + g.P("}\n") + + // ReadSignedData implementation (only for requests and responses). + g.P("// SignedDataSize returns size of the request signed data in bytes.") + g.P("//") + g.P("// Structures with the same field values have the same signed data size.") + g.P("func (x *", msg.GoIdent.GoName, ") ReadSignedData(buf []byte) ([]byte, error) {") + g.P("return x.GetBody().MarshalProtobuf(buf), nil") + g.P("}\n") +} + +func emitFieldSize(g *protogen.GeneratedFile, f *protogen.Field) { + m := marshalers[f.Desc.Kind()] + if m.Prefix == "" { + g.P("// FIXME missing field marshaler: ", f.GoName, " of type ", f.Desc.Kind().String()) + g.P(`panic("unimplemented")`) + return + } + + name := castFieldName(f) + if f.Oneof != nil { + name = "x." + f.Oneof.GoName + g.P("if inner, ok := ", name, ".(*", f.GoIdent.GoName, "); ok {") + defer g.P("}") + name = "inner." + f.GoName + } + + switch { + case f.Desc.IsList() && (f.Desc.Kind() == protoreflect.MessageKind || f.Desc.Kind() == protoreflect.Uint64Kind && !f.Desc.IsPacked()): + g.P("for i := range ", name, "{") + if f.Desc.Kind() == protoreflect.MessageKind { + g.P("size += ", protoPackage.Ident("NestedStructureSizeUnchecked"), "(", f.Desc.Number(), ", &", name, "[i])") + } else { + if f.Desc.Kind() != protoreflect.Uint64Kind { + panic("only uint64 unpacked primitive is supported") + } + + g.P("size += ", protowirePackage.Ident("SizeGroup"), "(", + protowirePackage.Ident("Number"), "(", f.Desc.Number(), "), ", + protowirePackage.Ident("SizeVarint"), "(", name, "[i]))") + } + g.P("}") + + case f.Desc.IsList(): + if m.RepeatedDouble { + g.P("n, _ = ", protoPackage.Ident("Repeated"+m.Prefix+"Size"), "(", f.Desc.Number(), ", ", name, ")") + g.P("size += n") + } else { + g.P("size += ", protoPackage.Ident("Repeated"+m.Prefix+"Size"), "(", f.Desc.Number(), ", ", name, ")") + } + default: + g.P("size += ", protoPackage.Ident(m.Prefix+"Size"), "(", f.Desc.Number(), ", ", name, ")") + } +} + +type marshalerDesc struct { + Prefix string + RepeatedDouble bool +} + +// Unused kinds are commented. +var marshalers = map[protoreflect.Kind]marshalerDesc{ + protoreflect.BoolKind: {Prefix: "Bool"}, + protoreflect.EnumKind: {Prefix: "Enum"}, + protoreflect.Int32Kind: {Prefix: "Int32", RepeatedDouble: true}, + // protoreflect.Sint32Kind: "", + protoreflect.Uint32Kind: {Prefix: "UInt32", RepeatedDouble: true}, + protoreflect.Int64Kind: {Prefix: "Int64", RepeatedDouble: true}, + // protoreflect.Sint64Kind: "", + protoreflect.Uint64Kind: {Prefix: "UInt64", RepeatedDouble: true}, + // protoreflect.Sfixed32Kind: "", + protoreflect.Fixed32Kind: {Prefix: "Fixed32", RepeatedDouble: true}, + // protoreflect.FloatKind: "", + // protoreflect.Sfixed64Kind: "", + protoreflect.Fixed64Kind: {Prefix: "Fixed64", RepeatedDouble: true}, + protoreflect.DoubleKind: {Prefix: "Float64"}, + protoreflect.StringKind: {Prefix: "String"}, + protoreflect.BytesKind: {Prefix: "Bytes"}, + protoreflect.MessageKind: {Prefix: "NestedStructure"}, + // protoreflect.GroupKind: "", +} diff --git a/api/util/protogen/internalgengo/writer.go b/api/util/protogen/internalgengo/writer.go new file mode 100644 index 0000000..7b0d4f1 --- /dev/null +++ b/api/util/protogen/internalgengo/writer.go @@ -0,0 +1,30 @@ +package internalgengo + +import ( + "fmt" +) + +type condition = func(string) string + +var ( + _ condition = notZero + _ condition = notEmpty + _ condition = identity + _ condition = notNil +) + +func notZero(name string) string { + return fmt.Sprintf("%s != 0", name) +} + +func notEmpty(name string) string { + return fmt.Sprintf("len(%s) != 0", name) +} + +func identity(name string) string { + return name +} + +func notNil(name string) string { + return fmt.Sprintf("%s != nil", name) +} diff --git a/api/util/protogen/main.go b/api/util/protogen/main.go new file mode 100644 index 0000000..3ebc1dd --- /dev/null +++ b/api/util/protogen/main.go @@ -0,0 +1,27 @@ +package main + +import ( + "flag" + + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/util/protogen/internalgengo" + "google.golang.org/protobuf/compiler/protogen" +) + +func main() { + var flags flag.FlagSet + genFuzz := flags.Bool("fuzz", false, "generate fuzz tests") + + protogen.Options{ + ParamFunc: flags.Set, + }.Run(func(gen *protogen.Plugin) error { + for _, f := range gen.Files { + if f.Generate { + internalgengo.GenerateFile(gen, f) + if *genFuzz { + internalgengo.GenerateFuzzTests(gen, f) + } + } + } + return nil + }) +} diff --git a/api/util/signature/data.go b/api/util/signature/data.go new file mode 100644 index 0000000..e444a73 --- /dev/null +++ b/api/util/signature/data.go @@ -0,0 +1,93 @@ +package signature + +import ( + "crypto/ecdsa" + + crypto "git.frostfs.info/TrueCloudLab/frostfs-crypto" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/util/pool" +) + +const poolSliceMaxSize = 128 * 1024 + +var buffersPool = pool.NewBufferPool(poolSliceMaxSize) + +type DataSource interface { + ReadSignedData([]byte) ([]byte, error) + SignedDataSize() int +} + +type DataWithSignature interface { + DataSource + GetSignature() *refs.Signature + SetSignature(*refs.Signature) +} + +type SignOption func(*cfg) + +type KeySignatureHandler func(*refs.Signature) + +type KeySignatureSource func() *refs.Signature + +func SignDataWithHandler(key *ecdsa.PrivateKey, src DataSource, handler KeySignatureHandler, opts ...SignOption) error { + if key == nil { + return crypto.ErrEmptyPrivateKey + } + + cfg := defaultCfg() + + for i := range opts { + opts[i](cfg) + } + + buffer := buffersPool.Get(uint32(src.SignedDataSize())) + defer buffersPool.Put(buffer) + + data, err := src.ReadSignedData(buffer.Data) + if err != nil { + return err + } + + sigData, err := sign(cfg, key, data) + if err != nil { + return err + } + + sig := new(refs.Signature) + sig.SetScheme(cfg.scheme) + sig.SetKey(crypto.MarshalPublicKey(&key.PublicKey)) + sig.SetSign(sigData) + handler(sig) + + return nil +} + +func VerifyDataWithSource(dataSrc DataSource, sigSrc KeySignatureSource, opts ...SignOption) error { + buffer := buffersPool.Get(uint32(dataSrc.SignedDataSize())) + defer buffersPool.Put(buffer) + + data, err := dataSrc.ReadSignedData(buffer.Data) + if err != nil { + return err + } + + return VerifyDataSlice(data, sigSrc, opts...) +} + +func SignData(key *ecdsa.PrivateKey, v DataWithSignature, opts ...SignOption) error { + return SignDataWithHandler(key, v, v.SetSignature, opts...) +} + +func VerifyData(src DataWithSignature, opts ...SignOption) error { + return VerifyDataWithSource(src, src.GetSignature, opts...) +} + +func VerifyDataSlice(data []byte, sigSrc KeySignatureSource, opts ...SignOption) error { + cfg := defaultCfg() + + for i := range opts { + opts[i](cfg) + } + + return verify(cfg, data, sigSrc()) +} diff --git a/api/util/signature/options.go b/api/util/signature/options.go new file mode 100644 index 0000000..d27eff2 --- /dev/null +++ b/api/util/signature/options.go @@ -0,0 +1,77 @@ +package signature + +import ( + "crypto/ecdsa" + "encoding/base64" + "fmt" + + crypto "git.frostfs.info/TrueCloudLab/frostfs-crypto" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/util/signature/walletconnect" +) + +type cfg struct { + schemeFixed bool + scheme refs.SignatureScheme +} + +func defaultCfg() *cfg { + return new(cfg) +} + +func verify(cfg *cfg, data []byte, sig *refs.Signature) error { + if !cfg.schemeFixed { + cfg.scheme = sig.GetScheme() + } + + pub := crypto.UnmarshalPublicKey(sig.GetKey()) + if pub == nil { + return crypto.ErrEmptyPublicKey + } + + switch cfg.scheme { + case refs.ECDSA_SHA512: + return crypto.Verify(pub, data, sig.GetSign()) + case refs.ECDSA_RFC6979_SHA256: + return crypto.VerifyRFC6979(pub, data, sig.GetSign()) + case refs.ECDSA_RFC6979_SHA256_WALLET_CONNECT: + buffer := buffersPool.Get(uint32(base64.StdEncoding.EncodedLen(len(data)))) + defer buffersPool.Put(buffer) + base64.StdEncoding.Encode(buffer.Data, data) + if !walletconnect.Verify(pub, buffer.Data, sig.GetSign()) { + return crypto.ErrInvalidSignature + } + return nil + default: + return fmt.Errorf("unsupported signature scheme %s", cfg.scheme) + } +} + +func sign(cfg *cfg, key *ecdsa.PrivateKey, data []byte) ([]byte, error) { + switch cfg.scheme { + case refs.ECDSA_SHA512: + return crypto.Sign(key, data) + case refs.ECDSA_RFC6979_SHA256: + return crypto.SignRFC6979(key, data) + case refs.ECDSA_RFC6979_SHA256_WALLET_CONNECT: + buffer := buffersPool.Get(uint32(base64.StdEncoding.EncodedLen(len(data)))) + defer buffersPool.Put(buffer) + base64.StdEncoding.Encode(buffer.Data, data) + return walletconnect.Sign(key, buffer.Data) + default: + panic(fmt.Sprintf("unsupported scheme %s", cfg.scheme)) + } +} + +func SignWithRFC6979() SignOption { + return func(c *cfg) { + c.schemeFixed = true + c.scheme = refs.ECDSA_RFC6979_SHA256 + } +} + +func SignWithWalletConnect() SignOption { + return func(c *cfg) { + c.scheme = refs.ECDSA_RFC6979_SHA256_WALLET_CONNECT + } +} diff --git a/api/util/signature/sign_test.go b/api/util/signature/sign_test.go new file mode 100644 index 0000000..222f9be --- /dev/null +++ b/api/util/signature/sign_test.go @@ -0,0 +1,44 @@ +package signature + +import ( + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rand" + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" + "github.com/stretchr/testify/require" +) + +type testData struct { + data []byte + sig *refs.Signature +} + +func (t testData) SignedDataSize() int { return len(t.data) } +func (t testData) ReadSignedData(data []byte) ([]byte, error) { + n := copy(data, t.data) + return data[:n], nil +} +func (t testData) GetSignature() *refs.Signature { return t.sig } +func (t *testData) SetSignature(s *refs.Signature) { t.sig = s } + +func TestWalletConnect(t *testing.T) { + testCases := [...][]byte{ + {}, + {0}, + {1, 2}, + {3, 4, 5}, + {6, 7, 8, 9, 10, 11, 12}, + } + + pk, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + require.NoError(t, err) + + for _, tc := range testCases { + td := &testData{data: tc} + require.NoError(t, SignData(pk, td, SignWithWalletConnect())) + require.Equal(t, refs.ECDSA_RFC6979_SHA256_WALLET_CONNECT, td.sig.GetScheme()) + require.NoError(t, VerifyData(td)) + } +} diff --git a/api/util/signature/walletconnect/sign.go b/api/util/signature/walletconnect/sign.go new file mode 100644 index 0000000..b96a842 --- /dev/null +++ b/api/util/signature/walletconnect/sign.go @@ -0,0 +1,142 @@ +package walletconnect + +import ( + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rand" + "encoding/binary" + "encoding/hex" + + crypto "git.frostfs.info/TrueCloudLab/frostfs-crypto" +) + +const ( + // saltSize is the salt size added to signed message. + saltSize = 16 + // signatureLen is the length of RFC6979 signature. + signatureLen = 64 +) + +// SignedMessage contains mirrors `SignedMessage` struct from the WalletConnect API. +// https://neon.coz.io/wksdk/core/modules.html#SignedMessage +type SignedMessage struct { + Data []byte + Message []byte + PublicKey []byte + Salt []byte +} + +// Sign signs message using WalletConnect API. The returned signature +// contains RFC6979 signature and 16-byte salt. +func Sign(p *ecdsa.PrivateKey, msg []byte) ([]byte, error) { + sm, err := SignMessage(p, msg) + if err != nil { + return nil, err + } + return append(sm.Data, sm.Salt...), nil +} + +// Verify verifies message using WalletConnect API. +func Verify(p *ecdsa.PublicKey, data, sign []byte) bool { + if len(sign) != signatureLen+saltSize { + return false + } + + salt := sign[signatureLen:] + return VerifyMessage(p, SignedMessage{ + Data: sign[:signatureLen], + Message: createMessageWithSalt(data, salt), + Salt: salt, + }) +} + +// SignMessage signs message with a private key and returns structure similar to +// `signMessage` of the WalletConnect API. +// https://github.com/CityOfZion/wallet-connect-sdk/blob/89c236b/packages/wallet-connect-sdk-core/src/index.ts#L496 +// https://github.com/CityOfZion/neon-wallet/blob/1174a9388480e6bbc4f79eb13183c2a573f67ca8/app/context/WalletConnect/helpers.js#L133 +func SignMessage(p *ecdsa.PrivateKey, msg []byte) (SignedMessage, error) { + var salt [saltSize]byte + _, _ = rand.Read(salt[:]) + + msg = createMessageWithSalt(msg, salt[:]) + sign, err := crypto.SignRFC6979(p, msg) + if err != nil { + return SignedMessage{}, err + } + + return SignedMessage{ + Data: sign, + Message: msg, + PublicKey: elliptic.MarshalCompressed(p.Curve, p.X, p.Y), + Salt: salt[:], + }, nil +} + +// VerifyMessage verifies message with a private key and returns structure similar to +// `verifyMessage` of WalletConnect API. +// https://github.com/CityOfZion/wallet-connect-sdk/blob/89c236b/packages/wallet-connect-sdk-core/src/index.ts#L515 +// https://github.com/CityOfZion/neon-wallet/blob/1174a9388480e6bbc4f79eb13183c2a573f67ca8/app/context/WalletConnect/helpers.js#L147 +func VerifyMessage(p *ecdsa.PublicKey, m SignedMessage) bool { + if p == nil { + x, y := elliptic.UnmarshalCompressed(elliptic.P256(), m.PublicKey) + if x == nil || y == nil { + return false + } + p = &ecdsa.PublicKey{ + Curve: elliptic.P256(), + X: x, + Y: y, + } + } + return crypto.VerifyRFC6979(p, m.Message, m.Data) == nil +} + +func createMessageWithSalt(msg, salt []byte) []byte { + // 4 byte prefix + length of the message with salt in bytes + + // + salt + message + 2 byte postfix. + saltedLen := hex.EncodedLen(len(salt)) + len(msg) + data := make([]byte, 4+getVarIntSize(saltedLen)+saltedLen+2) + + n := copy(data, []byte{0x01, 0x00, 0x01, 0xf0}) // fixed prefix + n += putVarUint(data[n:], uint64(saltedLen)) // salt is hex encoded, double its size + n += hex.Encode(data[n:], salt[:]) // for some reason we encode salt in hex + n += copy(data[n:], msg) + copy(data[n:], []byte{0x00, 0x00}) + + return data +} + +// Following functions are copied from github.com/nspcc-dev/neo-go/pkg/io package +// to avoid having another dependency. + +// getVarIntSize returns the size in number of bytes of a variable integer. +// Reference: https://github.com/neo-project/neo/blob/26d04a642ac5a1dd1827dabf5602767e0acba25c/src/neo/IO/Helper.cs#L131 +func getVarIntSize(value int) int { + var size uintptr + + if value < 0xFD { + size = 1 // unit8 + } else if value <= 0xFFFF { + size = 3 // byte + uint16 + } else { + size = 5 // byte + uint32 + } + return int(size) +} + +// putVarUint puts val in varint form to the pre-allocated buffer. +func putVarUint(data []byte, val uint64) int { + if val < 0xfd { + data[0] = byte(val) + return 1 + } + if val <= 0xFFFF { + data[0] = byte(0xfd) + binary.LittleEndian.PutUint16(data[1:], uint16(val)) + return 3 + } + + data[0] = byte(0xfe) + binary.LittleEndian.PutUint32(data[1:], uint32(val)) + return 5 +} diff --git a/api/util/signature/walletconnect/sign_test.go b/api/util/signature/walletconnect/sign_test.go new file mode 100644 index 0000000..1b4fe18 --- /dev/null +++ b/api/util/signature/walletconnect/sign_test.go @@ -0,0 +1,112 @@ +package walletconnect + +import ( + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rand" + "encoding/hex" + "testing" + + "github.com/stretchr/testify/require" +) + +func TestSignMessage(t *testing.T) { + p1, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + require.NoError(t, err) + + msg := []byte("NEO") + result, err := SignMessage(p1, msg) + require.NoError(t, err) + require.Equal(t, elliptic.MarshalCompressed(elliptic.P256(), p1.PublicKey.X, p1.PublicKey.Y), result.PublicKey) + require.Equal(t, saltSize, len(result.Salt)) + require.Equal(t, 64, len(result.Data)) + require.Equal(t, 4+1+16*2+3+2, len(result.Message)) + + require.True(t, VerifyMessage(&p1.PublicKey, result)) + + t.Run("invalid public key", func(t *testing.T) { + p2, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + require.NoError(t, err) + require.False(t, VerifyMessage(&p2.PublicKey, result)) + }) + t.Run("invalid signature", func(t *testing.T) { + result := result + result.Data[0] ^= 0xFF + require.False(t, VerifyMessage(&p1.PublicKey, result)) + }) +} + +func TestSign(t *testing.T) { + p1, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + require.NoError(t, err) + + msg := []byte("NEO") + sign, err := Sign(p1, msg) + require.NoError(t, err) + require.True(t, Verify(&p1.PublicKey, msg, sign)) + + t.Run("invalid public key", func(t *testing.T) { + p2, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + require.NoError(t, err) + require.False(t, Verify(&p2.PublicKey, msg, sign)) + }) + t.Run("invalid signature", func(t *testing.T) { + sign[0] ^= 0xFF + require.False(t, Verify(&p1.PublicKey, msg, sign)) + }) +} + +func TestVerifyNeonWallet(t *testing.T) { + testCases := [...]struct { + publicKey string + data string + salt string + messageHex string + messageOriginal string + }{ + { // Test values from this GIF https://github.com/CityOfZion/neon-wallet/pull/2390 . + publicKey: "02ce6228ba2cb2fc235be93aff9cd5fc0851702eb9791552f60db062f01e3d83f6", + data: "90ab1886ca0bece59b982d9ade8f5598065d651362fb9ce45ad66d0474b89c0b80913c8f0118a282acbdf200a429ba2d81bc52534a53ab41a2c6dfe2f0b4fb1b", + salt: "d41e348afccc2f3ee45cd9f5128b16dc", + messageHex: "010001f05c6434316533343861666363633266336565343563643966353132386231366463436172616c686f2c206d756c65712c206f2062616775697520656820697373756d65726d6f2074616978206c696761646f206e61206d697373e36f3f0000", + messageOriginal: "436172616c686f2c206d756c65712c206f2062616775697520656820697373756d65726d6f2074616978206c696761646f206e61206d697373e36f3f", + }, + { // Test value from wallet connect integration test + publicKey: "03bd9108c0b49f657e9eee50d1399022bd1e436118e5b7529a1b7cd606652f578f", + data: "510caa8cb6db5dedf04d215a064208d64be7496916d890df59aee132db8f2b07532e06f7ea664c4a99e3bcb74b43a35eb9653891b5f8701d2aef9e7526703eaa", + salt: "2c5b189569e92cce12e1c640f23e83ba", + messageHex: "010001f02632633562313839353639653932636365313265316336343066323365383362613132333435360000", + messageOriginal: "313233343536", // ascii string "123456" + }, + { // Test value from wallet connect integration test + publicKey: "03bd9108c0b49f657e9eee50d1399022bd1e436118e5b7529a1b7cd606652f578f", + data: "1e13f248962d8b3b60708b55ddf448d6d6a28c6b43887212a38b00bf6bab695e61261e54451c6e3d5f1f000e5534d166c7ca30f662a296d3a9aafa6d8c173c01", + salt: "58c86b2e74215b4f36b47d731236be3b", + messageHex: "010001f02035386338366232653734323135623466333662343764373331323336626533620000", + messageOriginal: "", // empty string + }, + } + + for _, testCase := range testCases { + rawPub, err := hex.DecodeString(testCase.publicKey) + require.NoError(t, err) + data, err := hex.DecodeString(testCase.data) + require.NoError(t, err) + salt, err := hex.DecodeString(testCase.salt) + require.NoError(t, err) + msg, err := hex.DecodeString(testCase.messageHex) + require.NoError(t, err) + orig, err := hex.DecodeString(testCase.messageOriginal) + require.NoError(t, err) + + require.Equal(t, msg, createMessageWithSalt(orig, salt)) + + sm := SignedMessage{ + Data: data, + Message: msg, + PublicKey: rawPub, + Salt: salt, + } + require.True(t, VerifyMessage(nil, sm)) + } +} diff --git a/bearer/bearer.go b/bearer/bearer.go index e419d54..d1b77ed 100644 --- a/bearer/bearer.go +++ b/bearer/bearer.go @@ -5,10 +5,10 @@ import ( "errors" "fmt" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl" - apeV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/ape" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" apeSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/ape" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/acl" + apeV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/ape" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" frostfscrypto "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto" frostfsecdsa "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto/ecdsa" @@ -18,7 +18,7 @@ import ( // Token represents bearer token for object service operations. // -// Token is mutually compatible with git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl.BearerToken +// Token is mutually compatible with git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/acl.BearerToken // message. See ReadFromV2 / WriteToV2 methods. // // Instances can be created using built-in var declaration. diff --git a/bearer/bearer_test.go b/bearer/bearer_test.go index 341c4f2..650dc82 100644 --- a/bearer/bearer_test.go +++ b/bearer/bearer_test.go @@ -6,8 +6,8 @@ import ( "reflect" "testing" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/acl" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer" bearertest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer/test" cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" diff --git a/checksum/checksum.go b/checksum/checksum.go index 9d227ad..76887f6 100644 --- a/checksum/checksum.go +++ b/checksum/checksum.go @@ -6,13 +6,13 @@ import ( "errors" "fmt" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" "git.frostfs.info/TrueCloudLab/tzhash/tz" ) // Checksum represents checksum of some digital data. // -// Checksum is mutually compatible with git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs.Checksum +// Checksum is mutually compatible with git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs.Checksum // message. See ReadFromV2 / WriteToV2 methods. // // Instances can be created using built-in var declaration. diff --git a/checksum/checksum_test.go b/checksum/checksum_test.go index 9da857d..1e1c07c 100644 --- a/checksum/checksum_test.go +++ b/checksum/checksum_test.go @@ -5,7 +5,7 @@ import ( "crypto/sha256" "testing" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" "git.frostfs.info/TrueCloudLab/tzhash/tz" "github.com/stretchr/testify/require" ) diff --git a/checksum/example_test.go b/checksum/example_test.go index 337767a..72d4a05 100644 --- a/checksum/example_test.go +++ b/checksum/example_test.go @@ -6,7 +6,7 @@ import ( "crypto/sha256" "fmt" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" ) func ExampleCalculate() { diff --git a/client/accounting.go b/client/accounting.go index faf7ddc..707ec3d 100644 --- a/client/accounting.go +++ b/client/accounting.go @@ -4,13 +4,13 @@ import ( "context" "fmt" - v2accounting "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/accounting" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" - rpcapi "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" - v2session "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/signature" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/accounting" + v2accounting "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/accounting" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" + rpcapi "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client" + v2session "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/signature" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" ) diff --git a/client/apemanager_add_chain.go b/client/apemanager_add_chain.go index 2581e2a..a8d53a7 100644 --- a/client/apemanager_add_chain.go +++ b/client/apemanager_add_chain.go @@ -4,12 +4,12 @@ import ( "context" "fmt" - apemanagerV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/apemanager" - rpcapi "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" - sessionV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/signature" apeSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/ape" + apemanagerV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/apemanager" + rpcapi "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client" + sessionV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/signature" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" ) diff --git a/client/apemanager_list_chains.go b/client/apemanager_list_chains.go index a8a3e8a..56cc4ef 100644 --- a/client/apemanager_list_chains.go +++ b/client/apemanager_list_chains.go @@ -4,12 +4,12 @@ import ( "context" "fmt" - apemanagerV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/apemanager" - rpcapi "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" - sessionV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/signature" apeSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/ape" + apemanagerV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/apemanager" + rpcapi "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client" + sessionV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/signature" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" ) diff --git a/client/apemanager_remove_chain.go b/client/apemanager_remove_chain.go index a297716..39ccdeb 100644 --- a/client/apemanager_remove_chain.go +++ b/client/apemanager_remove_chain.go @@ -4,12 +4,12 @@ import ( "context" "fmt" - apemanagerV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/apemanager" - rpcapi "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" - sessionV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/signature" apeSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/ape" + apemanagerV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/apemanager" + rpcapi "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client" + sessionV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/signature" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" ) diff --git a/client/api.go b/client/api.go index dd18c42..c86dde2 100644 --- a/client/api.go +++ b/client/api.go @@ -4,9 +4,9 @@ import ( "context" "fmt" - v2netmap "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap" - rpcapi "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" + v2netmap "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/netmap" + rpcapi "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client" ) // interface of FrostFS API server. Exists for test purposes only. diff --git a/client/client.go b/client/client.go index 4dd5059..a93c457 100644 --- a/client/client.go +++ b/client/client.go @@ -7,9 +7,9 @@ import ( "errors" "time" - v2accounting "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/accounting" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" + v2accounting "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/accounting" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client" "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" @@ -124,7 +124,7 @@ func (c *Client) Dial(ctx context.Context, prm PrmDial) error { // sets underlying provider of frostFSAPIServer. The method is used for testing as an approach // to skip Dial stage and override FrostFS API server. MUST NOT be used outside test code. -// In real applications wrapper over git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client +// In real applications wrapper over git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client // is statically used. func (c *Client) setFrostFSAPIServer(server frostFSAPIServer) { c.server = server diff --git a/client/common.go b/client/common.go index 65abae5..ba8281d 100644 --- a/client/common.go +++ b/client/common.go @@ -4,10 +4,10 @@ import ( "errors" "fmt" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" - v2session "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/signature" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client" + v2session "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/signature" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/version" ) @@ -104,7 +104,7 @@ func (c *Client) processResponse(resp responseV2) (apistatus.Status, error) { return st, nil } -// ExecRaw executes f with underlying git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client.Client +// ExecRaw executes f with underlying sdk-go/api/rpc/client.Client // instance. Communicate over the Protocol Buffers protocol in a more flexible way: // most often used to transmit data over a fixed version of the FrostFS protocol, as well // as to support custom services. @@ -115,7 +115,7 @@ func (c *Client) processResponse(resp responseV2) (apistatus.Status, error) { // before closing the connection. // // See also Dial and Close. -// See also git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client package docs. +// See also git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client package docs. func (c *Client) ExecRaw(f func(client *client.Client) error) error { return f(&c.c) } diff --git a/client/container_delete.go b/client/container_delete.go index 6d4b345..cf5adf4 100644 --- a/client/container_delete.go +++ b/client/container_delete.go @@ -4,12 +4,12 @@ import ( "context" "fmt" - v2container "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" - rpcapi "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" - v2session "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/signature" + v2container "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/container" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" + rpcapi "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client" + v2session "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/signature" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" frostfscrypto "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto" frostfsecdsa "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto/ecdsa" diff --git a/client/container_get.go b/client/container_get.go index da8166f..fd34090 100644 --- a/client/container_get.go +++ b/client/container_get.go @@ -5,12 +5,12 @@ import ( "errors" "fmt" - v2container "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" - rpcapi "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" - v2session "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/signature" + v2container "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/container" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" + rpcapi "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client" + v2session "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/signature" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" diff --git a/client/container_list.go b/client/container_list.go index 6d2efb6..d094cdb 100644 --- a/client/container_list.go +++ b/client/container_list.go @@ -4,12 +4,12 @@ import ( "context" "fmt" - v2container "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" - rpcapi "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" - v2session "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/signature" + v2container "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/container" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" + rpcapi "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client" + v2session "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/signature" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session" diff --git a/client/container_put.go b/client/container_put.go index e5b8f18..30ebf7a 100644 --- a/client/container_put.go +++ b/client/container_put.go @@ -4,12 +4,12 @@ import ( "context" "fmt" - v2container "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" - rpcapi "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" - v2session "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/signature" + v2container "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/container" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" + rpcapi "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client" + v2session "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/signature" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" diff --git a/client/doc.go b/client/doc.go index 7f6ec42..2a1d607 100644 --- a/client/doc.go +++ b/client/doc.go @@ -47,8 +47,8 @@ Consume custom service of the server: rpc CustomRPC(CustomRPCRequest) returns (CustomRPCResponse); } - import "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" - import "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/common" + import "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client" + import "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/common" req := new(CustomRPCRequest) // ... diff --git a/client/netmap.go b/client/netmap.go index a870ab2..f87d3b0 100644 --- a/client/netmap.go +++ b/client/netmap.go @@ -4,11 +4,11 @@ import ( "context" "fmt" - v2netmap "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap" - rpcapi "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" - v2session "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/signature" + v2netmap "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/netmap" + rpcapi "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client" + v2session "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/signature" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/version" diff --git a/client/netmap_test.go b/client/netmap_test.go index bce6b3a..d6ff0fb 100644 --- a/client/netmap_test.go +++ b/client/netmap_test.go @@ -6,9 +6,9 @@ import ( "fmt" "testing" - v2netmap "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/signature" + v2netmap "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/signature" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" "github.com/stretchr/testify/require" diff --git a/client/object_delete.go b/client/object_delete.go index 3214cff..048398c 100644 --- a/client/object_delete.go +++ b/client/object_delete.go @@ -5,13 +5,13 @@ import ( "crypto/ecdsa" "fmt" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl" - v2object "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" - v2refs "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" - rpcapi "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" - v2session "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/signature" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/acl" + v2object "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" + v2refs "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" + rpcapi "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client" + v2session "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/signature" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" diff --git a/client/object_get.go b/client/object_get.go index ba4f72d..b84844e 100644 --- a/client/object_get.go +++ b/client/object_get.go @@ -7,13 +7,13 @@ import ( "fmt" "io" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl" - v2object "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" - v2refs "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" - rpcapi "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" - v2session "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/signature" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/acl" + v2object "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" + v2refs "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" + rpcapi "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client" + v2session "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/signature" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" diff --git a/client/object_hash.go b/client/object_hash.go index b1b9ffc..83f2360 100644 --- a/client/object_hash.go +++ b/client/object_hash.go @@ -5,13 +5,13 @@ import ( "crypto/ecdsa" "fmt" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl" - v2object "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" - v2refs "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" - rpcapi "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" - v2session "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/signature" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/acl" + v2object "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" + v2refs "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" + rpcapi "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client" + v2session "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/signature" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/checksum" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" diff --git a/client/object_patch.go b/client/object_patch.go index 7b054db..6930644 100644 --- a/client/object_patch.go +++ b/client/object_patch.go @@ -7,12 +7,12 @@ import ( "fmt" "io" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl" - v2object "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" - rpcapi "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" - v2session "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/signature" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/acl" + v2object "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" + rpcapi "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client" + v2session "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/signature" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" diff --git a/client/object_patch_test.go b/client/object_patch_test.go index 839c453..63996b6 100644 --- a/client/object_patch_test.go +++ b/client/object_patch_test.go @@ -8,7 +8,7 @@ import ( "crypto/rand" "testing" - v2object "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" + v2object "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" "github.com/stretchr/testify/require" diff --git a/client/object_put.go b/client/object_put.go index 07ca840..9a01f34 100644 --- a/client/object_put.go +++ b/client/object_put.go @@ -4,7 +4,7 @@ import ( "context" "crypto/ecdsa" - buffPool "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/util/pool" + buffPool "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/util/pool" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" diff --git a/client/object_put_raw.go b/client/object_put_raw.go index e47c6a2..b682102 100644 --- a/client/object_put_raw.go +++ b/client/object_put_raw.go @@ -7,12 +7,12 @@ import ( "fmt" "io" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl" - v2object "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" - rpcapi "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" - v2session "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/signature" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/acl" + v2object "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" + rpcapi "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client" + v2session "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/signature" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" ) diff --git a/client/object_put_single.go b/client/object_put_single.go index a2ff8a0..ffce126 100644 --- a/client/object_put_single.go +++ b/client/object_put_single.go @@ -5,12 +5,12 @@ import ( "crypto/ecdsa" "fmt" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl" - v2object "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" - rpcapi "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" - v2session "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/signature" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/acl" + v2object "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" + rpcapi "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client" + v2session "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/signature" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session" diff --git a/client/object_put_transformer.go b/client/object_put_transformer.go index 5314a12..7e30be1 100644 --- a/client/object_put_transformer.go +++ b/client/object_put_transformer.go @@ -3,7 +3,7 @@ package client import ( "context" - buffPool "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/util/pool" + buffPool "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/util/pool" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/transformer" diff --git a/client/object_search.go b/client/object_search.go index aa02542..859c8c6 100644 --- a/client/object_search.go +++ b/client/object_search.go @@ -7,13 +7,13 @@ import ( "fmt" "io" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl" - v2object "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" - v2refs "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" - rpcapi "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" - v2session "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/signature" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/acl" + v2object "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" + v2refs "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" + rpcapi "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client" + v2session "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/signature" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" diff --git a/client/object_search_test.go b/client/object_search_test.go index f449d61..f385f48 100644 --- a/client/object_search_test.go +++ b/client/object_search_test.go @@ -7,9 +7,9 @@ import ( "io" "testing" - v2object "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" - signatureV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/signature" + v2object "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" + signatureV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/signature" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" diff --git a/client/response.go b/client/response.go index e1a702e..69972b9 100644 --- a/client/response.go +++ b/client/response.go @@ -1,6 +1,6 @@ package client -import "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" +import "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" // ResponseMetaInfo groups meta information about any FrostFS API response. type ResponseMetaInfo struct { diff --git a/client/session.go b/client/session.go index b49c67b..9f806f0 100644 --- a/client/session.go +++ b/client/session.go @@ -5,11 +5,11 @@ import ( "crypto/ecdsa" "fmt" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" - rpcapi "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" - v2session "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/signature" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" + rpcapi "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client" + v2session "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/signature" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" ) diff --git a/client/status/apemanager.go b/client/status/apemanager.go index f68fd48..b4d49cb 100644 --- a/client/status/apemanager.go +++ b/client/status/apemanager.go @@ -1,8 +1,8 @@ package apistatus import ( - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/apemanager" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/status" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/apemanager" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/status" ) // APEManagerAccessDenied describes status of the failure because of the access control violation. diff --git a/client/status/common.go b/client/status/common.go index 598631b..486bc72 100644 --- a/client/status/common.go +++ b/client/status/common.go @@ -3,7 +3,7 @@ package apistatus import ( "encoding/binary" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/status" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/status" ) // ServerInternal describes failure statuses related to internal server errors. @@ -53,7 +53,7 @@ func (x ServerInternal) Message() string { // WriteInternalServerErr writes err message to ServerInternal instance. func WriteInternalServerErr(x *ServerInternal, err error) { - x.SetMessage(err.Error()) + x.v2.SetMessage(err.Error()) } // WrongMagicNumber describes failure status related to incorrect network magic. @@ -192,7 +192,7 @@ const defaultNodeUnderMaintenanceMsg = "node is under maintenance" // Error implements the error interface. func (x *NodeUnderMaintenance) Error() string { - msg := x.Message() + msg := x.v2.Message() if msg == "" { msg = defaultNodeUnderMaintenanceMsg } diff --git a/client/status/common_test.go b/client/status/common_test.go index 5a7a2b7..e55883e 100644 --- a/client/status/common_test.go +++ b/client/status/common_test.go @@ -3,7 +3,7 @@ package apistatus_test import ( "testing" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/status" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/status" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" "github.com/stretchr/testify/require" ) diff --git a/client/status/container.go b/client/status/container.go index 9f06b27..594d984 100644 --- a/client/status/container.go +++ b/client/status/container.go @@ -1,8 +1,8 @@ package apistatus import ( - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/status" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/container" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/status" ) // ContainerNotFound describes status of the failure because of the missing container. diff --git a/client/status/object.go b/client/status/object.go index 27ea86c..ae2e8e0 100644 --- a/client/status/object.go +++ b/client/status/object.go @@ -1,8 +1,8 @@ package apistatus import ( - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/status" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/status" ) // ObjectLocked describes status of the failure because of the locked object. diff --git a/client/status/session.go b/client/status/session.go index 6f60758..f87ce61 100644 --- a/client/status/session.go +++ b/client/status/session.go @@ -1,8 +1,8 @@ package apistatus import ( - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/status" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/status" ) // SessionTokenNotFound describes status of the failure because of the missing session token. diff --git a/client/status/success.go b/client/status/success.go index a68983d..3975b92 100644 --- a/client/status/success.go +++ b/client/status/success.go @@ -1,7 +1,7 @@ package apistatus import ( - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/status" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/status" ) // SuccessDefaultV2 represents Status instance of default success. Implements StatusV2. diff --git a/client/status/unrecognized.go b/client/status/unrecognized.go index 19e481e..e4b4a81 100644 --- a/client/status/unrecognized.go +++ b/client/status/unrecognized.go @@ -1,7 +1,7 @@ package apistatus import ( - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/status" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/status" ) type unrecognizedStatusV2 struct { diff --git a/client/status/v2.go b/client/status/v2.go index 5cee3be..95dfb8a 100644 --- a/client/status/v2.go +++ b/client/status/v2.go @@ -3,11 +3,11 @@ package apistatus import ( "fmt" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/apemanager" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/status" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/apemanager" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/container" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/status" ) // StatusV2 defines a variety of Status instances compatible with FrostFS API V2 protocol. @@ -16,7 +16,7 @@ import ( type StatusV2 interface { Status - // ToStatusV2 returns the status as git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/status.Status message structure. + // ToStatusV2 returns the status as git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/status.Status message structure. ToStatusV2() *status.Status } diff --git a/container/container.go b/container/container.go index 39c6259..ff63adb 100644 --- a/container/container.go +++ b/container/container.go @@ -9,9 +9,9 @@ import ( "strings" "time" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container" - v2netmap "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/container" + v2netmap "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/acl" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" frostfscrypto "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto" @@ -37,7 +37,7 @@ import ( // Instances for existing containers can be initialized using decoding methods // (e.g Unmarshal). // -// Container is mutually compatible with git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container.Container +// Container is mutually compatible with git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/container.Container // message. See ReadFromV2 / WriteToV2 methods. type Container struct { v2 container.Container diff --git a/container/container_test.go b/container/container_test.go index c5f1b7e..a66a866 100644 --- a/container/container_test.go +++ b/container/container_test.go @@ -6,9 +6,9 @@ import ( "testing" "time" - v2container "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container" - v2netmap "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" + v2container "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/container" + v2netmap "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" diff --git a/container/doc.go b/container/doc.go index 34b044d..85e2082 100644 --- a/container/doc.go +++ b/container/doc.go @@ -27,7 +27,7 @@ Instances can be also used to process FrostFS API V2 protocol messages On client side: - import "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container" + import "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/container" var msg container.Container cnr.WriteToV2(&msg) diff --git a/container/id/id.go b/container/id/id.go index bde739c..569968a 100644 --- a/container/id/id.go +++ b/container/id/id.go @@ -4,13 +4,13 @@ import ( "crypto/sha256" "fmt" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" "github.com/mr-tron/base58" ) // ID represents FrostFS container identifier. // -// ID is mutually compatible with git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs.ContainerID +// ID is mutually compatible with git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs.ContainerID // message. See ReadFromV2 / WriteToV2 methods. // // Instances can be created using built-in var declaration. diff --git a/container/id/id_test.go b/container/id/id_test.go index ded7457..6f60d92 100644 --- a/container/id/id_test.go +++ b/container/id/id_test.go @@ -5,7 +5,7 @@ import ( "crypto/sha256" "testing" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" "github.com/mr-tron/base58" diff --git a/crypto/crypto_test.go b/crypto/crypto_test.go index 7d1ad52..da33d88 100644 --- a/crypto/crypto_test.go +++ b/crypto/crypto_test.go @@ -4,7 +4,7 @@ import ( "crypto/rand" "testing" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" frostfscrypto "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto" frostfsecdsa "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto/ecdsa" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" diff --git a/crypto/doc.go b/crypto/doc.go index 8b568f5..7fc66c1 100644 --- a/crypto/doc.go +++ b/crypto/doc.go @@ -29,7 +29,7 @@ Signature can be also used to process FrostFS API V2 protocol messages On client side: - import "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" + import "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" var msg refs.Signature sig.WriteToV2(&msg) diff --git a/crypto/ecdsa/wallet_connect.go b/crypto/ecdsa/wallet_connect.go index 34cbcae..0fe8651 100644 --- a/crypto/ecdsa/wallet_connect.go +++ b/crypto/ecdsa/wallet_connect.go @@ -6,7 +6,7 @@ import ( "encoding/base64" "fmt" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/util/signature/walletconnect" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/util/signature/walletconnect" frostfscrypto "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" ) diff --git a/crypto/signature.go b/crypto/signature.go index 33c6132..f8a668e 100644 --- a/crypto/signature.go +++ b/crypto/signature.go @@ -4,13 +4,13 @@ import ( "errors" "fmt" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" ) // Signature represents a confirmation of data integrity received by the // digital signature mechanism. // -// Signature is mutually compatible with git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs.Signature +// Signature is mutually compatible with git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs.Signature // message. See ReadFromV2 / WriteToV2 methods. // // Note that direct typecast is not safe and may result in loss of compatibility: diff --git a/crypto/signer.go b/crypto/signer.go index 9f99e3d..be96973 100644 --- a/crypto/signer.go +++ b/crypto/signer.go @@ -3,7 +3,7 @@ package frostfscrypto import ( "fmt" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" ) // Scheme represents digital signature algorithm with fixed cryptographic hash function. diff --git a/eacl/enums.go b/eacl/enums.go index b2b5353..8f693ec 100644 --- a/eacl/enums.go +++ b/eacl/enums.go @@ -1,7 +1,7 @@ package eacl import ( - v2acl "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl" + v2acl "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/acl" ) // Action taken if ContainerEACL record matched request. diff --git a/eacl/enums_test.go b/eacl/enums_test.go index 29f2518..e283b09 100644 --- a/eacl/enums_test.go +++ b/eacl/enums_test.go @@ -3,7 +3,7 @@ package eacl_test import ( "testing" - v2acl "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl" + v2acl "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/acl" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl" "github.com/stretchr/testify/require" ) diff --git a/eacl/filter.go b/eacl/filter.go index 4403e5a..af32eae 100644 --- a/eacl/filter.go +++ b/eacl/filter.go @@ -3,7 +3,7 @@ package eacl import ( "strconv" - v2acl "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl" + v2acl "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/acl" ) // Filter defines check conditions if request header is matched or not. Matched diff --git a/eacl/filter_test.go b/eacl/filter_test.go index 74b9a10..3a01a32 100644 --- a/eacl/filter_test.go +++ b/eacl/filter_test.go @@ -4,7 +4,7 @@ import ( "strconv" "testing" - v2acl "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl" + v2acl "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/acl" "github.com/stretchr/testify/require" ) diff --git a/eacl/record.go b/eacl/record.go index 3c0d44a..c808387 100644 --- a/eacl/record.go +++ b/eacl/record.go @@ -3,7 +3,7 @@ package eacl import ( "crypto/ecdsa" - v2acl "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl" + v2acl "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/acl" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/checksum" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" diff --git a/eacl/record_test.go b/eacl/record_test.go index a1738fc..02301da 100644 --- a/eacl/record_test.go +++ b/eacl/record_test.go @@ -5,7 +5,7 @@ import ( "fmt" "testing" - v2acl "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl" + v2acl "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/acl" checksumtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/checksum/test" cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" diff --git a/eacl/table.go b/eacl/table.go index 6982b85..3fc9e60 100644 --- a/eacl/table.go +++ b/eacl/table.go @@ -4,8 +4,8 @@ import ( "crypto/sha256" "fmt" - v2acl "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" + v2acl "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/acl" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/version" ) diff --git a/eacl/table_test.go b/eacl/table_test.go index 4ec110f..630d3ed 100644 --- a/eacl/table_test.go +++ b/eacl/table_test.go @@ -4,7 +4,7 @@ import ( "crypto/sha256" "testing" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl" eacltest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl/test" diff --git a/eacl/target.go b/eacl/target.go index 2b8b709..a2f9c36 100644 --- a/eacl/target.go +++ b/eacl/target.go @@ -4,7 +4,7 @@ import ( "bytes" "crypto/ecdsa" - v2acl "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl" + v2acl "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/acl" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" ) diff --git a/eacl/target_test.go b/eacl/target_test.go index e226194..9da4f82 100644 --- a/eacl/target_test.go +++ b/eacl/target_test.go @@ -4,7 +4,7 @@ import ( "crypto/ecdsa" "testing" - v2acl "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl" + v2acl "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/acl" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/stretchr/testify/require" ) diff --git a/go.mod b/go.mod index 788de4a..ed14604 100644 --- a/go.mod +++ b/go.mod @@ -3,34 +3,35 @@ module git.frostfs.info/TrueCloudLab/frostfs-sdk-go go 1.22 require ( - git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20241002064811-3e705a3cbe84 git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240621131249-49e5270f673e + git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 git.frostfs.info/TrueCloudLab/hrw v1.2.1 git.frostfs.info/TrueCloudLab/tzhash v1.8.0 + github.com/VictoriaMetrics/easyproto v0.1.4 github.com/antlr4-go/antlr/v4 v4.13.1 github.com/google/uuid v1.6.0 github.com/hashicorp/golang-lru/v2 v2.0.7 github.com/klauspost/reedsolomon v1.12.1 + github.com/mailru/easyjson v0.7.7 github.com/mr-tron/base58 v1.2.0 github.com/nspcc-dev/neo-go v0.106.2 github.com/stretchr/testify v1.9.0 go.uber.org/zap v1.27.0 + golang.org/x/sync v0.7.0 google.golang.org/grpc v1.66.2 google.golang.org/protobuf v1.34.1 gopkg.in/yaml.v3 v3.0.1 ) require ( - git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 // indirect git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0 // indirect - github.com/VictoriaMetrics/easyproto v0.1.4 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect github.com/golang/snappy v0.0.1 // indirect github.com/gorilla/websocket v1.5.1 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/klauspost/cpuid/v2 v2.2.6 // indirect - github.com/mailru/easyjson v0.7.7 // indirect + github.com/kr/pretty v0.1.0 // indirect github.com/nspcc-dev/go-ordered-json v0.0.0-20240301084351-0246b013f8b2 // indirect github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20240521091047-78685785716d // indirect github.com/nspcc-dev/rfc6979 v0.2.1 // indirect @@ -42,8 +43,8 @@ require ( golang.org/x/crypto v0.24.0 // indirect golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 // indirect golang.org/x/net v0.26.0 // indirect - golang.org/x/sync v0.7.0 // indirect golang.org/x/sys v0.21.0 // indirect golang.org/x/text v0.16.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117 // indirect + gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect ) diff --git a/go.sum b/go.sum index bf04bf0a93b572ed1a51a7b90ae744f01963149f..56930c779a92b45099c8646bf7fe31a3ba0ab9b9 100644 GIT binary patch delta 153 zcmey|&Dhw@I6-alK1RLG>5MVr4h1EZ3T1|RK&YRdua}#jqL5)|Rp1sFnP+Ae?os4l z5D@8?lU45TTbOTX5Rx64VVG8FoE({%Z}7Jzu}fNTJL~&(KWIP}e}u$iT?N(7?dRz|6$L&`{Sn)!e`| z(KtCN)xty}!_X=*eOBfNXLzbq_Yr2udR&&3|~<_Xt16ALnR)ARMqj5av0P$88E0Zarfzz^ewoq6h85fZPU#1S diff --git a/prepare.sh b/prepare.sh new file mode 100755 index 0000000..a7b6100 --- /dev/null +++ b/prepare.sh @@ -0,0 +1,39 @@ +#!/bin/bash + +if [ -z "$1" ]; then + echo "usage: ./prepare.sh path/to/frostfs-api" + exit 1 +fi + +API_GO_PATH=$(pwd)/api +API_PATH=$1 + +# MOVE FILES FROM API REPO +cd "$API_PATH" || exit 1 +ARGS=$(find ./ -name '*.proto' -not -path './bin/*') +for file in $ARGS; do + dir=$(dirname "$file") + mkdir -p "$API_GO_PATH/$dir/grpc" + cp -r "$dir"/* "$API_GO_PATH/$dir/grpc" +done + +# MODIFY FILES +cd "$API_GO_PATH" || exit 1 +ARGS2=$(find ./ -name '*.proto' -not -path './bin/*') +for file in $ARGS2; do + echo "$file" + sed -i "s/import\ \"\(.*\)\/\(.*\)\.proto\";/import\ \"\1\/grpc\/\2\.proto\";/" $file + sed -i "s/api-go\\/v2/sdk-go\\/api/" $file + sed -i "s/import \"/import \"api\//" $file +done + + +cd "$API_GO_PATH/.." || exit 1 +# COMPILE +make protoc + +# REMOVE PROTO DEFINITIONS +ARGS=$(find ./$prefix -name '*.proto' -not -path './util/*' -not -path './bin/*') +for file in $ARGS; do + rm "$file" +done diff --git a/session/common.go b/session/common.go index b103b59..3d7308f 100644 --- a/session/common.go +++ b/session/common.go @@ -6,8 +6,8 @@ import ( "errors" "fmt" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" frostfscrypto "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto" frostfsecdsa "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto/ecdsa" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" diff --git a/session/container.go b/session/container.go index 45c5ff8..463523b 100644 --- a/session/container.go +++ b/session/container.go @@ -5,8 +5,8 @@ import ( "errors" "fmt" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" frostfscrypto "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" @@ -18,7 +18,7 @@ import ( // limited validity period, and applies to a strictly defined set of operations. // See methods for details. // -// Container is mutually compatible with git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session.Token +// Container is mutually compatible with git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session.Token // message. See ReadFromV2 / WriteToV2 methods. // // Instances can be created using built-in var declaration. diff --git a/session/container_test.go b/session/container_test.go index 73fd815..fcf152d 100644 --- a/session/container_test.go +++ b/session/container_test.go @@ -8,8 +8,8 @@ import ( mrand "math/rand" "testing" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" - v2session "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" + v2session "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" frostfscrypto "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto" frostfsecdsa "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto/ecdsa" diff --git a/session/doc.go b/session/doc.go index 12ec0c4..98858f7 100644 --- a/session/doc.go +++ b/session/doc.go @@ -28,7 +28,7 @@ Instances can be also used to process FrostFS API V2 protocol messages On client side: - import "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" + import "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" var msg session.Token tok.WriteToV2(&msg) diff --git a/session/object.go b/session/object.go index 3641bd1..385ca03 100644 --- a/session/object.go +++ b/session/object.go @@ -5,8 +5,8 @@ import ( "errors" "fmt" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" ) @@ -17,7 +17,7 @@ import ( // limited validity period, and applies to a strictly defined set of operations. // See methods for details. // -// Object is mutually compatible with git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session.Token +// Object is mutually compatible with git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session.Token // message. See ReadFromV2 / WriteToV2 methods. // // Instances can be created using built-in var declaration. diff --git a/session/object_test.go b/session/object_test.go index 59ff8d6..4d20773 100644 --- a/session/object_test.go +++ b/session/object_test.go @@ -8,8 +8,8 @@ import ( "math/rand" "testing" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" - v2session "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" + v2session "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" frostfscrypto "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto" frostfsecdsa "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto/ecdsa" diff --git a/user/doc.go b/user/doc.go index 4809e4a..d4e0b4b 100644 --- a/user/doc.go +++ b/user/doc.go @@ -39,7 +39,7 @@ Instances can be also used to process FrostFS API protocol messages On client side: - import "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" + import "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" var msg refs.OwnerID id.WriteToV2(&msg) diff --git a/user/id.go b/user/id.go index 31ff9b6..2d64d43 100644 --- a/user/id.go +++ b/user/id.go @@ -5,7 +5,7 @@ import ( "errors" "fmt" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" "github.com/mr-tron/base58" "github.com/nspcc-dev/neo-go/pkg/crypto/hash" "github.com/nspcc-dev/neo-go/pkg/encoding/address" @@ -18,7 +18,7 @@ var zeroSlice = bytes.Repeat([]byte{0}, idSize) // ID identifies users of the FrostFS system. // -// ID is mutually compatible with git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs.OwnerID +// ID is mutually compatible with git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs.OwnerID // message. See ReadFromV2 / WriteToV2 methods. // // Instances can be created using built-in var declaration. Zero ID is not valid, diff --git a/user/id_test.go b/user/id_test.go index 9867472..afeb746 100644 --- a/user/id_test.go +++ b/user/id_test.go @@ -5,7 +5,7 @@ import ( "crypto/rand" "testing" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" . "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" usertest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user/test" "github.com/mr-tron/base58" diff --git a/version/version.go b/version/version.go index 47e61c8..2411966 100644 --- a/version/version.go +++ b/version/version.go @@ -3,12 +3,12 @@ package version import ( "fmt" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" ) // Version represents revision number in SemVer scheme. // -// Version is mutually compatible with git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs.Version +// Version is mutually compatible with git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs.Version // message. See ReadFromV2 / WriteToV2 methods. // // Instances can be created using built-in var declaration. diff --git a/version/version_test.go b/version/version_test.go index fdf2b6a..97cec9a 100644 --- a/version/version_test.go +++ b/version/version_test.go @@ -3,7 +3,7 @@ package version import ( "testing" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" "github.com/stretchr/testify/require" )