From 397123a81020ac80ff827c6cc592fec2163b28f9 Mon Sep 17 00:00:00 2001 From: Pavel Pogodaev Date: Mon, 7 Oct 2024 17:20:25 +0300 Subject: [PATCH] [] Merge repo with frostfs-api-go Signed-off-by: Pavel Pogodaev --- accounting/decimal.go | 4 +- accounting/decimal_test.go | 2 +- accounting/doc.go | 2 +- apiv2/accounting/accounting.go | 104 + apiv2/accounting/convert.go | 178 ++ apiv2/accounting/grpc/service_frostfs.pb.go | Bin 0 -> 18357 bytes apiv2/accounting/grpc/service_frostfs_fuzz.go | 45 + apiv2/accounting/grpc/service_frostfs_test.go | 31 + apiv2/accounting/grpc/service_grpc.pb.go | Bin 0 -> 4321 bytes apiv2/accounting/grpc/types_frostfs.pb.go | Bin 0 -> 3773 bytes apiv2/accounting/grpc/types_frostfs_fuzz.go | 26 + apiv2/accounting/grpc/types_frostfs_test.go | 21 + apiv2/accounting/json.go | 14 + apiv2/accounting/marshal.go | 104 + apiv2/accounting/message_test.go | 19 + apiv2/accounting/test/generate.go | 64 + apiv2/acl/bench_test.go | 51 + apiv2/acl/convert.go | 592 ++++ apiv2/acl/filters.go | 33 + apiv2/acl/grpc/types_frostfs.pb.go | Bin 0 -> 45158 bytes apiv2/acl/grpc/types_frostfs_fuzz.go | 64 + apiv2/acl/grpc/types_frostfs_test.go | 41 + apiv2/acl/json.go | 70 + apiv2/acl/marshal.go | 350 +++ apiv2/acl/message_test.go | 21 + apiv2/acl/string.go | 110 + apiv2/acl/test/generate.go | 144 + apiv2/acl/types.go | 426 +++ apiv2/ape/convert.go | 132 + apiv2/ape/grpc/types_frostfs.pb.go | Bin 0 -> 8237 bytes apiv2/ape/grpc/types_frostfs_fuzz.go | 45 + apiv2/ape/grpc/types_frostfs_test.go | 31 + apiv2/ape/json.go | 14 + apiv2/ape/marshal.go | 92 + apiv2/ape/message_test.go | 15 + apiv2/ape/string.go | 18 + apiv2/ape/test/generate.go | 71 + apiv2/ape/types.go | 79 + apiv2/apemanager/convert.go | 358 +++ apiv2/apemanager/grpc/service_frostfs.pb.go | Bin 0 -> 55301 bytes apiv2/apemanager/grpc/service_frostfs_fuzz.go | 121 + apiv2/apemanager/grpc/service_frostfs_test.go | 71 + apiv2/apemanager/grpc/service_grpc.pb.go | Bin 0 -> 9993 bytes apiv2/apemanager/marshal.go | 205 ++ apiv2/apemanager/message_test.go | 26 + apiv2/apemanager/status.go | 76 + apiv2/apemanager/status_test.go | 30 + apiv2/apemanager/test/generate.go | 143 + apiv2/apemanager/types.go | 226 ++ apiv2/container/attributes.go | 90 + apiv2/container/attributes_test.go | 59 + apiv2/container/convert.go | 764 +++++ apiv2/container/grpc/service_frostfs.pb.go | Bin 0 -> 74362 bytes apiv2/container/grpc/service_frostfs_fuzz.go | 159 + apiv2/container/grpc/service_frostfs_test.go | 91 + apiv2/container/grpc/service_grpc.pb.go | Bin 0 -> 11817 bytes apiv2/container/grpc/types_frostfs.pb.go | Bin 0 -> 11447 bytes apiv2/container/grpc/types_frostfs_fuzz.go | 26 + apiv2/container/grpc/types_frostfs_test.go | 21 + apiv2/container/json.go | 22 + apiv2/container/marshal.go | 345 +++ apiv2/container/message_test.go | 36 + apiv2/container/status.go | 33 + apiv2/container/status_test.go | 15 + apiv2/container/test/generate.go | 240 ++ apiv2/container/types.go | 446 +++ apiv2/lock/grpc/types_frostfs.pb.go | Bin 0 -> 3790 bytes apiv2/lock/grpc/types_frostfs_fuzz.go | 26 + apiv2/lock/grpc/types_frostfs_test.go | 21 + apiv2/netmap/convert.go | 916 ++++++ apiv2/netmap/grpc/service_frostfs.pb.go | Bin 0 -> 53488 bytes apiv2/netmap/grpc/service_frostfs_fuzz.go | 121 + apiv2/netmap/grpc/service_frostfs_test.go | 71 + apiv2/netmap/grpc/service_grpc.pb.go | Bin 0 -> 9132 bytes apiv2/netmap/grpc/types_frostfs.pb.go | Bin 0 -> 52866 bytes apiv2/netmap/grpc/types_frostfs_fuzz.go | 159 + apiv2/netmap/grpc/types_frostfs_test.go | 91 + apiv2/netmap/json.go | 62 + apiv2/netmap/marshal.go | 576 ++++ apiv2/netmap/message_test.go | 32 + apiv2/netmap/string.go | 68 + apiv2/netmap/test/generate.go | 335 +++ apiv2/netmap/types.go | 783 +++++ apiv2/object/attributes.go | 187 ++ apiv2/object/attributes_test.go | 89 + apiv2/object/bench_test.go | 45 + apiv2/object/convert.go | 2555 +++++++++++++++++ apiv2/object/filters.go | 58 + apiv2/object/grpc/client.go | 86 + apiv2/object/grpc/service_frostfs.pb.go | Bin 0 -> 214441 bytes apiv2/object/grpc/service_frostfs_fuzz.go | 387 +++ apiv2/object/grpc/service_frostfs_test.go | 211 ++ apiv2/object/grpc/service_grpc.pb.go | Bin 0 -> 46612 bytes apiv2/object/grpc/types_frostfs.pb.go | Bin 0 -> 59850 bytes apiv2/object/grpc/types_frostfs_fuzz.go | 102 + apiv2/object/grpc/types_frostfs_test.go | 61 + apiv2/object/json.go | 94 + apiv2/object/lock.go | 160 ++ apiv2/object/lock_test.go | 26 + apiv2/object/marshal.go | 1428 +++++++++ apiv2/object/message_test.go | 65 + apiv2/object/status.go | 91 + apiv2/object/status_test.go | 35 + apiv2/object/string.go | 55 + apiv2/object/test/generate.go | 766 +++++ apiv2/object/types.go | 1650 +++++++++++ apiv2/refs/bench_test.go | 53 + apiv2/refs/convert.go | 264 ++ apiv2/refs/grpc/types_frostfs.pb.go | Bin 0 -> 28648 bytes apiv2/refs/grpc/types_frostfs_fuzz.go | 159 + apiv2/refs/grpc/types_frostfs_test.go | 91 + apiv2/refs/json.go | 62 + apiv2/refs/marshal.go | 264 ++ apiv2/refs/message_test.go | 21 + apiv2/refs/string.go | 47 + apiv2/refs/test/generate.go | 127 + apiv2/refs/types.go | 194 ++ apiv2/rpc/accounting.go | 29 + apiv2/rpc/apemanager.go | 60 + apiv2/rpc/client/call_options.go | 40 + apiv2/rpc/client/client.go | 30 + apiv2/rpc/client/conn.go | 24 + apiv2/rpc/client/connect.go | 72 + apiv2/rpc/client/flows.go | 124 + apiv2/rpc/client/init.go | 69 + apiv2/rpc/client/options.go | 129 + apiv2/rpc/client/options_test.go | 197 ++ apiv2/rpc/client/stream_wrapper.go | 58 + apiv2/rpc/client/util.go | 13 + apiv2/rpc/common.go | 10 + apiv2/rpc/common/call.go | 75 + apiv2/rpc/common/call_test.go | 49 + apiv2/rpc/container.go | 82 + apiv2/rpc/grpc/init.go | 4 + apiv2/rpc/message/encoding.go | 40 + apiv2/rpc/message/message.go | 43 + apiv2/rpc/message/test/message.go | 126 + apiv2/rpc/netmap.go | 62 + apiv2/rpc/object.go | 243 ++ apiv2/rpc/session.go | 28 + apiv2/session/convert.go | 898 ++++++ apiv2/session/grpc/client.go | 62 + apiv2/session/grpc/service_frostfs.pb.go | Bin 0 -> 19139 bytes apiv2/session/grpc/service_frostfs_fuzz.go | 45 + apiv2/session/grpc/service_frostfs_test.go | 31 + apiv2/session/grpc/service_grpc.pb.go | Bin 0 -> 4108 bytes apiv2/session/grpc/types_frostfs.pb.go | Bin 0 -> 65808 bytes apiv2/session/grpc/types_frostfs_fuzz.go | 159 + apiv2/session/grpc/types_frostfs_test.go | 91 + apiv2/session/json.go | 86 + apiv2/session/marshal.go | 536 ++++ apiv2/session/message_test.go | 27 + apiv2/session/status.go | 32 + apiv2/session/status_test.go | 15 + apiv2/session/string.go | 47 + apiv2/session/test/generate.go | 251 ++ apiv2/session/types.go | 836 ++++++ apiv2/session/util.go | 167 ++ apiv2/session/xheaders.go | 34 + apiv2/signature/body.go | 116 + apiv2/signature/marshaller.go | 26 + apiv2/signature/sign.go | 122 + apiv2/signature/sign_test.go | 125 + apiv2/signature/verify.go | 127 + apiv2/status/convert.go | 95 + apiv2/status/details.go | 8 + apiv2/status/grpc/types_frostfs.pb.go | Bin 0 -> 13432 bytes apiv2/status/grpc/types_frostfs_fuzz.go | 26 + apiv2/status/grpc/types_frostfs_test.go | 21 + apiv2/status/marshal.go | 92 + apiv2/status/message_test.go | 16 + apiv2/status/status.go | 103 + apiv2/status/test/codes.go | 28 + apiv2/status/test/generate.go | 44 + apiv2/status/types.go | 124 + apiv2/tombstone/convert.go | 41 + apiv2/tombstone/grpc/types_frostfs.pb.go | Bin 0 -> 5253 bytes apiv2/tombstone/grpc/types_frostfs_fuzz.go | 26 + apiv2/tombstone/grpc/types_frostfs_test.go | 21 + apiv2/tombstone/json.go | 14 + apiv2/tombstone/marshal.go | 56 + apiv2/tombstone/message_test.go | 15 + apiv2/tombstone/test/generate.go | 23 + apiv2/tombstone/types.go | 57 + apiv2/util/pool/buffer.go | 54 + apiv2/util/pool/marshal.go | 7 + apiv2/util/proto/encoding/compat.go | 22 + apiv2/util/proto/encoding/json.go | 48 + apiv2/util/proto/encoding/proto.go | 57 + apiv2/util/proto/marshal.go | 413 +++ apiv2/util/proto/marshal_test.go | 217 ++ .../util/proto/test/custom/test_frostfs.pb.go | Bin 0 -> 30151 bytes apiv2/util/proto/test/test.pb.go | Bin 0 -> 20911 bytes apiv2/util/proto/test/test.proto | 46 + apiv2/util/protogen/internalgengo/file.go | 245 ++ apiv2/util/protogen/internalgengo/fuzz.go | 69 + apiv2/util/protogen/internalgengo/getter.go | 14 + apiv2/util/protogen/internalgengo/json.go | 228 ++ apiv2/util/protogen/internalgengo/options.go | 7 + apiv2/util/protogen/internalgengo/proto.go | 202 ++ .../internalgengo/proto_field_type.go | 59 + .../internalgengo/proto_stable_compat.go | 124 + apiv2/util/protogen/internalgengo/writer.go | 30 + apiv2/util/protogen/main.go | 27 + apiv2/util/signature/data.go | 93 + apiv2/util/signature/options.go | 77 + apiv2/util/signature/sign_test.go | 44 + apiv2/util/signature/walletconnect/sign.go | 142 + .../util/signature/walletconnect/sign_test.go | 112 + bearer/bearer_test.go | 4 +- checksum/checksum.go | 4 +- checksum/checksum_test.go | 2 +- checksum/example_test.go | 2 +- client/accounting.go | 4 + client/api.go | 6 +- client/client.go | 8 +- client/common.go | 10 +- client/container_delete.go | 12 +- client/container_eacl.go | 0 client/container_get.go | 12 +- client/container_list.go | 12 +- client/container_put.go | 12 +- client/container_set_eacl.go | 0 client/container_space.go | 0 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_search.go | 14 +- client/object_search_test.go | 6 +- client/response.go | 2 +- client/session.go | 10 +- client/status/common.go | 2 +- 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 +- container/container.go | 8 +- container/container_test.go | 6 +- container/doc.go | 2 +- container/id/id.go | 4 +- container/id/id_test.go | 2 +- container/size.go | 0 container/size_test.go | 0 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 +- 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/policy.go | 4 +- netmap/selector.go | 2 +- netmap/selector_test.go | 2 +- object/attribute.go | 2 +- object/attribute_test.go | 2 +- 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/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/type.go | 2 +- object/type_test.go | 2 +- 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 +- 307 files changed, 28086 insertions(+), 193 deletions(-) create mode 100644 apiv2/accounting/accounting.go create mode 100644 apiv2/accounting/convert.go create mode 100644 apiv2/accounting/grpc/service_frostfs.pb.go create mode 100644 apiv2/accounting/grpc/service_frostfs_fuzz.go create mode 100644 apiv2/accounting/grpc/service_frostfs_test.go create mode 100644 apiv2/accounting/grpc/service_grpc.pb.go create mode 100644 apiv2/accounting/grpc/types_frostfs.pb.go create mode 100644 apiv2/accounting/grpc/types_frostfs_fuzz.go create mode 100644 apiv2/accounting/grpc/types_frostfs_test.go create mode 100644 apiv2/accounting/json.go create mode 100644 apiv2/accounting/marshal.go create mode 100644 apiv2/accounting/message_test.go create mode 100644 apiv2/accounting/test/generate.go create mode 100644 apiv2/acl/bench_test.go create mode 100644 apiv2/acl/convert.go create mode 100644 apiv2/acl/filters.go create mode 100644 apiv2/acl/grpc/types_frostfs.pb.go create mode 100644 apiv2/acl/grpc/types_frostfs_fuzz.go create mode 100644 apiv2/acl/grpc/types_frostfs_test.go create mode 100644 apiv2/acl/json.go create mode 100644 apiv2/acl/marshal.go create mode 100644 apiv2/acl/message_test.go create mode 100644 apiv2/acl/string.go create mode 100644 apiv2/acl/test/generate.go create mode 100644 apiv2/acl/types.go create mode 100644 apiv2/ape/convert.go create mode 100644 apiv2/ape/grpc/types_frostfs.pb.go create mode 100644 apiv2/ape/grpc/types_frostfs_fuzz.go create mode 100644 apiv2/ape/grpc/types_frostfs_test.go create mode 100644 apiv2/ape/json.go create mode 100644 apiv2/ape/marshal.go create mode 100644 apiv2/ape/message_test.go create mode 100644 apiv2/ape/string.go create mode 100644 apiv2/ape/test/generate.go create mode 100644 apiv2/ape/types.go create mode 100644 apiv2/apemanager/convert.go create mode 100644 apiv2/apemanager/grpc/service_frostfs.pb.go create mode 100644 apiv2/apemanager/grpc/service_frostfs_fuzz.go create mode 100644 apiv2/apemanager/grpc/service_frostfs_test.go create mode 100644 apiv2/apemanager/grpc/service_grpc.pb.go create mode 100644 apiv2/apemanager/marshal.go create mode 100644 apiv2/apemanager/message_test.go create mode 100644 apiv2/apemanager/status.go create mode 100644 apiv2/apemanager/status_test.go create mode 100644 apiv2/apemanager/test/generate.go create mode 100644 apiv2/apemanager/types.go create mode 100644 apiv2/container/attributes.go create mode 100644 apiv2/container/attributes_test.go create mode 100644 apiv2/container/convert.go create mode 100644 apiv2/container/grpc/service_frostfs.pb.go create mode 100644 apiv2/container/grpc/service_frostfs_fuzz.go create mode 100644 apiv2/container/grpc/service_frostfs_test.go create mode 100644 apiv2/container/grpc/service_grpc.pb.go create mode 100644 apiv2/container/grpc/types_frostfs.pb.go create mode 100644 apiv2/container/grpc/types_frostfs_fuzz.go create mode 100644 apiv2/container/grpc/types_frostfs_test.go create mode 100644 apiv2/container/json.go create mode 100644 apiv2/container/marshal.go create mode 100644 apiv2/container/message_test.go create mode 100644 apiv2/container/status.go create mode 100644 apiv2/container/status_test.go create mode 100644 apiv2/container/test/generate.go create mode 100644 apiv2/container/types.go create mode 100644 apiv2/lock/grpc/types_frostfs.pb.go create mode 100644 apiv2/lock/grpc/types_frostfs_fuzz.go create mode 100644 apiv2/lock/grpc/types_frostfs_test.go create mode 100644 apiv2/netmap/convert.go create mode 100644 apiv2/netmap/grpc/service_frostfs.pb.go create mode 100644 apiv2/netmap/grpc/service_frostfs_fuzz.go create mode 100644 apiv2/netmap/grpc/service_frostfs_test.go create mode 100644 apiv2/netmap/grpc/service_grpc.pb.go create mode 100644 apiv2/netmap/grpc/types_frostfs.pb.go create mode 100644 apiv2/netmap/grpc/types_frostfs_fuzz.go create mode 100644 apiv2/netmap/grpc/types_frostfs_test.go create mode 100644 apiv2/netmap/json.go create mode 100644 apiv2/netmap/marshal.go create mode 100644 apiv2/netmap/message_test.go create mode 100644 apiv2/netmap/string.go create mode 100644 apiv2/netmap/test/generate.go create mode 100644 apiv2/netmap/types.go create mode 100644 apiv2/object/attributes.go create mode 100644 apiv2/object/attributes_test.go create mode 100644 apiv2/object/bench_test.go create mode 100644 apiv2/object/convert.go create mode 100644 apiv2/object/filters.go create mode 100644 apiv2/object/grpc/client.go create mode 100644 apiv2/object/grpc/service_frostfs.pb.go create mode 100644 apiv2/object/grpc/service_frostfs_fuzz.go create mode 100644 apiv2/object/grpc/service_frostfs_test.go create mode 100644 apiv2/object/grpc/service_grpc.pb.go create mode 100644 apiv2/object/grpc/types_frostfs.pb.go create mode 100644 apiv2/object/grpc/types_frostfs_fuzz.go create mode 100644 apiv2/object/grpc/types_frostfs_test.go create mode 100644 apiv2/object/json.go create mode 100644 apiv2/object/lock.go create mode 100644 apiv2/object/lock_test.go create mode 100644 apiv2/object/marshal.go create mode 100644 apiv2/object/message_test.go create mode 100644 apiv2/object/status.go create mode 100644 apiv2/object/status_test.go create mode 100644 apiv2/object/string.go create mode 100644 apiv2/object/test/generate.go create mode 100644 apiv2/object/types.go create mode 100644 apiv2/refs/bench_test.go create mode 100644 apiv2/refs/convert.go create mode 100644 apiv2/refs/grpc/types_frostfs.pb.go create mode 100644 apiv2/refs/grpc/types_frostfs_fuzz.go create mode 100644 apiv2/refs/grpc/types_frostfs_test.go create mode 100644 apiv2/refs/json.go create mode 100644 apiv2/refs/marshal.go create mode 100644 apiv2/refs/message_test.go create mode 100644 apiv2/refs/string.go create mode 100644 apiv2/refs/test/generate.go create mode 100644 apiv2/refs/types.go create mode 100644 apiv2/rpc/accounting.go create mode 100644 apiv2/rpc/apemanager.go create mode 100644 apiv2/rpc/client/call_options.go create mode 100644 apiv2/rpc/client/client.go create mode 100644 apiv2/rpc/client/conn.go create mode 100644 apiv2/rpc/client/connect.go create mode 100644 apiv2/rpc/client/flows.go create mode 100644 apiv2/rpc/client/init.go create mode 100644 apiv2/rpc/client/options.go create mode 100644 apiv2/rpc/client/options_test.go create mode 100644 apiv2/rpc/client/stream_wrapper.go create mode 100644 apiv2/rpc/client/util.go create mode 100644 apiv2/rpc/common.go create mode 100644 apiv2/rpc/common/call.go create mode 100644 apiv2/rpc/common/call_test.go create mode 100644 apiv2/rpc/container.go create mode 100644 apiv2/rpc/grpc/init.go create mode 100644 apiv2/rpc/message/encoding.go create mode 100644 apiv2/rpc/message/message.go create mode 100644 apiv2/rpc/message/test/message.go create mode 100644 apiv2/rpc/netmap.go create mode 100644 apiv2/rpc/object.go create mode 100644 apiv2/rpc/session.go create mode 100644 apiv2/session/convert.go create mode 100644 apiv2/session/grpc/client.go create mode 100644 apiv2/session/grpc/service_frostfs.pb.go create mode 100644 apiv2/session/grpc/service_frostfs_fuzz.go create mode 100644 apiv2/session/grpc/service_frostfs_test.go create mode 100644 apiv2/session/grpc/service_grpc.pb.go create mode 100644 apiv2/session/grpc/types_frostfs.pb.go create mode 100644 apiv2/session/grpc/types_frostfs_fuzz.go create mode 100644 apiv2/session/grpc/types_frostfs_test.go create mode 100644 apiv2/session/json.go create mode 100644 apiv2/session/marshal.go create mode 100644 apiv2/session/message_test.go create mode 100644 apiv2/session/status.go create mode 100644 apiv2/session/status_test.go create mode 100644 apiv2/session/string.go create mode 100644 apiv2/session/test/generate.go create mode 100644 apiv2/session/types.go create mode 100644 apiv2/session/util.go create mode 100644 apiv2/session/xheaders.go create mode 100644 apiv2/signature/body.go create mode 100644 apiv2/signature/marshaller.go create mode 100644 apiv2/signature/sign.go create mode 100644 apiv2/signature/sign_test.go create mode 100644 apiv2/signature/verify.go create mode 100644 apiv2/status/convert.go create mode 100644 apiv2/status/details.go create mode 100644 apiv2/status/grpc/types_frostfs.pb.go create mode 100644 apiv2/status/grpc/types_frostfs_fuzz.go create mode 100644 apiv2/status/grpc/types_frostfs_test.go create mode 100644 apiv2/status/marshal.go create mode 100644 apiv2/status/message_test.go create mode 100644 apiv2/status/status.go create mode 100644 apiv2/status/test/codes.go create mode 100644 apiv2/status/test/generate.go create mode 100644 apiv2/status/types.go create mode 100644 apiv2/tombstone/convert.go create mode 100644 apiv2/tombstone/grpc/types_frostfs.pb.go create mode 100644 apiv2/tombstone/grpc/types_frostfs_fuzz.go create mode 100644 apiv2/tombstone/grpc/types_frostfs_test.go create mode 100644 apiv2/tombstone/json.go create mode 100644 apiv2/tombstone/marshal.go create mode 100644 apiv2/tombstone/message_test.go create mode 100644 apiv2/tombstone/test/generate.go create mode 100644 apiv2/tombstone/types.go create mode 100644 apiv2/util/pool/buffer.go create mode 100644 apiv2/util/pool/marshal.go create mode 100644 apiv2/util/proto/encoding/compat.go create mode 100644 apiv2/util/proto/encoding/json.go create mode 100644 apiv2/util/proto/encoding/proto.go create mode 100644 apiv2/util/proto/marshal.go create mode 100644 apiv2/util/proto/marshal_test.go create mode 100644 apiv2/util/proto/test/custom/test_frostfs.pb.go create mode 100644 apiv2/util/proto/test/test.pb.go create mode 100644 apiv2/util/proto/test/test.proto create mode 100644 apiv2/util/protogen/internalgengo/file.go create mode 100644 apiv2/util/protogen/internalgengo/fuzz.go create mode 100644 apiv2/util/protogen/internalgengo/getter.go create mode 100644 apiv2/util/protogen/internalgengo/json.go create mode 100644 apiv2/util/protogen/internalgengo/options.go create mode 100644 apiv2/util/protogen/internalgengo/proto.go create mode 100644 apiv2/util/protogen/internalgengo/proto_field_type.go create mode 100644 apiv2/util/protogen/internalgengo/proto_stable_compat.go create mode 100644 apiv2/util/protogen/internalgengo/writer.go create mode 100644 apiv2/util/protogen/main.go create mode 100644 apiv2/util/signature/data.go create mode 100644 apiv2/util/signature/options.go create mode 100644 apiv2/util/signature/sign_test.go create mode 100644 apiv2/util/signature/walletconnect/sign.go create mode 100644 apiv2/util/signature/walletconnect/sign_test.go create mode 100644 client/container_eacl.go create mode 100644 client/container_set_eacl.go create mode 100644 client/container_space.go create mode 100644 container/size.go create mode 100644 container/size_test.go diff --git a/accounting/decimal.go b/accounting/decimal.go index bb01f28..e7acdb3 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/apiv2/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/apiv2/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..84f739f 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/apiv2/accounting" "github.com/stretchr/testify/require" ) diff --git a/accounting/doc.go b/accounting/doc.go index defcb0d..7a55f24 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/apiv2/accounting" var msg accounting.Decimal dec.WriteToV2(&msg) diff --git a/apiv2/accounting/accounting.go b/apiv2/accounting/accounting.go new file mode 100644 index 0000000..119882f --- /dev/null +++ b/apiv2/accounting/accounting.go @@ -0,0 +1,104 @@ +package accounting + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/refs" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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/apiv2/accounting/convert.go b/apiv2/accounting/convert.go new file mode 100644 index 0000000..f53eaed --- /dev/null +++ b/apiv2/accounting/convert.go @@ -0,0 +1,178 @@ +package accounting + +import ( + accounting "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/accounting/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/refs" + refsGRPC "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/refs/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/rpc/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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/apiv2/accounting/grpc/service_frostfs.pb.go b/apiv2/accounting/grpc/service_frostfs.pb.go new file mode 100644 index 0000000000000000000000000000000000000000..10e7ce4081b8b300e1e2894d98cc15c112ffec99 GIT binary patch literal 18357 zcmeHOS##S)5`HFs#h6t|K&=c$_M1}PszS)2^pq(5eB6IJXR>q zsv)^GCdHmS5imS`>?zH~_x;|-eveoF?TOObe}$-!<1>y3sCov$-qE4B(!nr><1{tV zQ6#`9+7TQ9v~T32M5Z#UlyR1Y2-K5B6ohNHw!q&TmzDVCxAW^t4)x!(tyCOi7sv^9 zV7#GE|B{slwZ}3-Sa!UBGp)Q73$Fa9;H3&y(xtWu zK9EUPJE|!q6$dr}v?Q+Z9{Y|QYdj+!)DE@}7q*o8|Cmfn z4sComBo^>d6e60hDkkDZhz!Zx9AqmRC67!B}Kqp-(7|_BZ9= zPz*Y<+5m>6)6^?*w!=#j&VpY}Q`RdCN-2(x1x|}jvRK<22UTz=^7jiK~v%HZ<=7BbLso!=PX+8X*Wymf| zTFs8dH*=T{+*uG=3V-mUvk6iY!f^G$!9mvgBf~YXD3jzI$7;rQBil+ltEJ7F(l|IR zU)XZi%!B_qd;Mzh>?~YZ8y^^*W{4%Fb(Qtlj{1S<@PFot-~-HhWfIhL)F4d# z?HrcZMw$ChrxDU2{)&_FQzX*T8yRs5JaQ z$>CVgYWA{~Y@P8foiOd^LOB%4WZl_n^Fg*da3w2`mhbY(3ptYsgYQu68fUZ(CyGHG(GyZd+feOL>x*Z# z{V0|@oPhLEWXI(m@+jAvLq=5 zHAUR>mHdX&H@Az_8;aA27EpJBa`pn9VO-*0B{fe$2AMTGZpUy@qj)nUSQ{isj<}a& z(`mldooSF=Q^ke6Ni7)AB3S@wnqS5!P{%Q9TNJrOJQoBL(4|VfEZ;-`D$v7KGP!0I zU*knFk4t&jXnVEVxGEG=OAf7wWhFDClWi%t=zbk*E$x00Q`XwbJk*Ww-N{yf{ZKbj zV0c5n?%w%I}T z+|#^wTe-p-)^cBT*^A#d>iL%4To(JY96Bld=sR^KPBj#^)aV51sVbqo?Iu@ySF6*! zu_VA#MBxFO>N0E#Xs3pfy&xjz0sebwuq-1ZQ_M|Mc&F5kV> zHrSFI8m&#WLu=*cTwdF4&!uc_u&ssOs7s}{>Xc|pK`33~Z3IEts*JIx+Xoh{J{Ir* z7I#~i;yKRMMt~yUZ5?1J5*5xdqe4r8%hci;D@0Moa|3@lbh%pC%t1ibigUwnxxmka zl{!V^9yUbp5z+?Y$T0m{gp>|f2Rzzwhf!(LGbm}tdoBmofTeUokwPs}%Jt%) zK6@RSEV+al+ALYKiAME}*VfBDrt380Q`#txmTTBvyNRZ59&mL8G+^7w#wUc&3bay$eE6!rWYvg{3 zNUyuYz2m(q1Q5--jCO$71;lId7qU%XZ&*7u_O>A44&qvk?d%-gQoeC}9W*5B;TjC- zvy7!QHg6A~ZM*L@lH}}d8$3xlhwhR6LP|ZHYU=IzIuUsYR9uEjlJrOcl$kKmsYkc zzs=53xnV_%RZpXsRH%*Ws*kuwZ0x_oYM9ZUsoUzay0x)(x$m}a(ru}L>}V!*{%AA} zCa0)}HKOYHfKxIdi#Fld-U=bR*S=u=7>W}?wt}XAY&3_Wh@JM#u-IY{Me%62TSkMK zgTs7E-*Us2r6${|TUj8piDKz6iZX*H`*M4f`*9R^qJh4>z_T8w_v0wtU&e5()isWy zqyFojM=_hclLIM6`LCsOzaL3agPv>PgwHaPVq(kQj$ad!unmX+#C`t=0{s$!OHnF1 z>tA%!ms)gX`c^8BFq+Iu8$bdW)b*`()s9evyD^ob>{A!KEhE*h_H3#SbGQqb78xHx^}YKA+-j%Z(9tKt(NS2ieLEy3DrRqD$J|WLuBVGNWSb^o0SA_fskc zl+<70Q{S+o{P%x5rD8(W)_u1NpWe@@P(g@U1p9@;7ACoyIThu1t}aPpdr-w$zy-qo zCRLQA`mSo|V@6dL7j2?b&C;F!P%|_$7s~AZx+9HpDzWWrWQC6H#hd8LROXw3&cx3S HQR%+`xH>=} literal 0 HcmV?d00001 diff --git a/apiv2/accounting/grpc/service_frostfs_fuzz.go b/apiv2/accounting/grpc/service_frostfs_fuzz.go new file mode 100644 index 0000000..69e7174 --- /dev/null +++ b/apiv2/accounting/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 accounting + +func DoFuzzProtoBalanceRequest(data []byte) int { + msg := new(BalanceRequest) + if err := msg.UnmarshalProtobuf(data); err != nil { + return 0 + } + _ = msg.MarshalProtobuf(nil) + return 1 +} +func DoFuzzJSONBalanceRequest(data []byte) int { + msg := new(BalanceRequest) + if err := msg.UnmarshalJSON(data); err != nil { + return 0 + } + _, err := msg.MarshalJSON() + if err != nil { + panic(err) + } + return 1 +} +func DoFuzzProtoBalanceResponse(data []byte) int { + msg := new(BalanceResponse) + if err := msg.UnmarshalProtobuf(data); err != nil { + return 0 + } + _ = msg.MarshalProtobuf(nil) + return 1 +} +func DoFuzzJSONBalanceResponse(data []byte) int { + msg := new(BalanceResponse) + if err := msg.UnmarshalJSON(data); err != nil { + return 0 + } + _, err := msg.MarshalJSON() + if err != nil { + panic(err) + } + return 1 +} diff --git a/apiv2/accounting/grpc/service_frostfs_test.go b/apiv2/accounting/grpc/service_frostfs_test.go new file mode 100644 index 0000000..b97a13e --- /dev/null +++ b/apiv2/accounting/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 accounting + +import ( + testing "testing" +) + +func FuzzProtoBalanceRequest(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzProtoBalanceRequest(data) + }) +} +func FuzzJSONBalanceRequest(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzJSONBalanceRequest(data) + }) +} +func FuzzProtoBalanceResponse(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzProtoBalanceResponse(data) + }) +} +func FuzzJSONBalanceResponse(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzJSONBalanceResponse(data) + }) +} diff --git a/apiv2/accounting/grpc/service_grpc.pb.go b/apiv2/accounting/grpc/service_grpc.pb.go new file mode 100644 index 0000000000000000000000000000000000000000..63207fe396288297a3e146f2b61b25065774d6a2 GIT binary patch literal 4321 zcmd^DQE%He5Pr6P#mxgcIdJGM!%)CQFl27h8C#PgPWCbk21C(~P+8PS%4tyKzwbLz zvYje!vpwu(MH5)&@p$)rci&MNjc8&rO-o&BE4|L>=AJ5Ryitev?r>=im$p)Z-dxc6 z#TA{tnO=!xG@`Y(E;pqc^TXj2TWI~g_(8nfU8dcC>mS9@D{;i@&eT@vF-fINUHZIS zj`+}#({`OJEkZm=Qc3keF7=LClH{w(SWjuvQ>OI#qo;oJp`Y~F3H6u8EDJ4`rjX@Q z7#p2qSs`(^Z+#S2VdcE^^?tLs+)oAxXL5C$JHmfS%B-rq(1$)>A!3JAJm4a4NSCg* zn*6Qw_yyxF_6zJ_H~5nGOP}8qn(lIc3rmp1`LrnHp3QDF&}t9MNG@ewIv*Ii)PL2v zMTX1E_mji7CJ=HYUXrm?fNCoeK;=Bm={UF+v$|q5-$$IM?)S*?tE4dm$|oC&W|5rv z&l0#QJwL09;+^)lCOel%`I!2nQX8>wVtpjG%!-bOQRAV-uwyVOa$SaO83YxdPTo&x zflNBq)K(3EWGv5M47eIfG#mF_5Q9iE*`f4jasolh>_y}LLcAee^xlnH4XR{$vPp3q5A5Jpa+S5PF#GwO`ot*MKQ^y&u9 zc3p0kb++eZ4vM7epF6NNd2@$%Woi?X;5jm=}+bg@|*9hY|Kv6Esr{9m?Iw zS3vHWYm8wGy>MsBH;n)zj>~Ga5xNrG4RPNhnK6qo0W`YVD+70VQLuLms=7daWpkSf z`h;E&X_k#Z?sdv<2J5&*SL}X`7gLc722j8!3Kj*55sWD>df>^E55d< zbjNfMVP@q=>PlB0>KO98E~UNasI;AK*US%SUK2UFCE%?QCVLcspP>*tIV z44&PfjynSgS&Os-P7HY{VZP|5xG+ef7k7`t+YV8H#!n-*@1yWH&uxRsE9kT!gaoy%F|BO=l0(GJ4#uD~|{MrjBQ4#m|f zO$X@Rl5HpYZijFw2Q}&Jd?YPX|D7XK;vUPfu!w|BSq@q8;Y}gDgayx^_0f>UgWn@q zg`hK#I{2{0RoDtYDCL#O@h zDcX)*uRw#uiKx4GkN575OqS8Hnn=2qjnu-(361Y)s+Cds0oD$#)j^?EYl=3dlXrCX z?vhSVUSFnBG!^-+xRxaHTy>2po9iel>#5R)l4$U?RSm_m$<+jJGJcGsK~Wou@qs_5 zN>vnJmnQA;%cfA-rS9Z$rMk%*G0yy(gLZNYBAJ+$v%{=2WtFivgD}w_Kw)>l^fZ4E zDeG|%e>8k6+FIHav`;)(3{tytaN9sIDwfnVcWSb z&HouYn>ZRqk-3{nI+1x82%fBdO&DRnP)ya=kI`3M!PYg-PM( zTsf(omMzUobL0F(EvYDFH6fePmTtsME?GNiKBDInu`RhhkuzGoDtq$2L=nhMd z%?_+J(&Qzu8gnMl^_8q;V_dqvRRka}bs=)OZL^OslSymny1%LUV6K*`c9TkmYqs(UT*3ZY8ek^!MphHWMr8x|k5%x&+y_xLqOrFAtLq zc^|x}p;7wm?3Oi{BjG!R4Te2#(&{`&n@Ft*KT6x2@E|F2T4wGK?w(_X%2^m3A4*dt z8%7w?Z$2@2*k=exR^;g!46TzjLTex~{1SQWo29R4oI~j;hc1#h7fquKx?W7E0fcW` z^!rb3yic(oT`}r_TWrvx$@3cyXoH<~wG}BBt)v$tLX+4=gXLf%jMyi2%cTo@Cm-W5 zwI^8T1`aK}g;dwiMNi5xviO#dC4|zpE64%|1f=D1Xt{*C*uuxx#g7vTLDoox)g>|H z58r;QKok_J06z z$K5(BVVC|b<`=j{HP=bpbX8@m&M~oh_a;mud3OH{G`Y`m)nK?!wJgd7UxeU}^v3(2 z+@0rBJi_g2unzC6KfV}!<|g5Hu7`c)U=gX=4Gsu*kJ=HS2loxReh4GN+J+vmAy*P% zzJ9YPg2i`_YAY>|kuaz2h~^&DwleHhHGRVu*83CKjqK2|6%wKaQJ-pT&DV%_#elCTd#}es-eA9(>HP^D<)Gm>FX9ZH*K!~n5lN*3?+fuW?6V?>A@=lnBY)p zyIM~8-e4yv)-G<#seN9lBP^fDs;qqx@e%aIM)0dp!bZ83cb?5v(~3g6a{)KNq!3jr zISSl9h{hbNN;Njj7P4#SIT38P*VEn7qNl)6JLmb>zAfG?}`aa@~+T9N9vFc_X zFAfUSJnw-AtAkxRJ_ 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/apiv2/acl/filters.go b/apiv2/acl/filters.go new file mode 100644 index 0000000..c1d8afe --- /dev/null +++ b/apiv2/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/apiv2/acl/grpc/types_frostfs.pb.go b/apiv2/acl/grpc/types_frostfs.pb.go new file mode 100644 index 0000000000000000000000000000000000000000..e34267e940e8552717c5acda5361f8a2a9cf5dfc GIT binary patch literal 45158 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 literal 0 HcmV?d00001 diff --git a/apiv2/acl/grpc/types_frostfs_fuzz.go b/apiv2/acl/grpc/types_frostfs_fuzz.go new file mode 100644 index 0000000..5d5b763 --- /dev/null +++ b/apiv2/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/apiv2/acl/grpc/types_frostfs_test.go b/apiv2/acl/grpc/types_frostfs_test.go new file mode 100644 index 0000000..c6d1c43 --- /dev/null +++ b/apiv2/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/apiv2/acl/json.go b/apiv2/acl/json.go new file mode 100644 index 0000000..64f9cbe --- /dev/null +++ b/apiv2/acl/json.go @@ -0,0 +1,70 @@ +package acl + +import ( + acl "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/acl/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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/apiv2/acl/marshal.go b/apiv2/acl/marshal.go new file mode 100644 index 0000000..e05c475 --- /dev/null +++ b/apiv2/acl/marshal.go @@ -0,0 +1,350 @@ +package acl + +import ( + acl "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/acl/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/rpc/message" + protoutil "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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/apiv2/acl/message_test.go b/apiv2/acl/message_test.go new file mode 100644 index 0000000..bc16637 --- /dev/null +++ b/apiv2/acl/message_test.go @@ -0,0 +1,21 @@ +package acl_test + +import ( + "testing" + + acltest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/acl/test" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/rpc/message" + messagetest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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/apiv2/acl/string.go b/apiv2/acl/string.go new file mode 100644 index 0000000..65801b0 --- /dev/null +++ b/apiv2/acl/string.go @@ -0,0 +1,110 @@ +package acl + +import ( + acl "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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/apiv2/acl/test/generate.go b/apiv2/acl/test/generate.go new file mode 100644 index 0000000..1e07c8f --- /dev/null +++ b/apiv2/acl/test/generate.go @@ -0,0 +1,144 @@ +package acltest + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/acl" + apetest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/ape/test" + accountingtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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/apiv2/acl/types.go b/apiv2/acl/types.go new file mode 100644 index 0000000..06eb2f0 --- /dev/null +++ b/apiv2/acl/types.go @@ -0,0 +1,426 @@ +package acl + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/ape" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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/apiv2/ape/convert.go b/apiv2/ape/convert.go new file mode 100644 index 0000000..f70acf3 --- /dev/null +++ b/apiv2/ape/convert.go @@ -0,0 +1,132 @@ +package ape + +import ( + "fmt" + + ape "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/ape/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/rpc/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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/apiv2/ape/grpc/types_frostfs.pb.go b/apiv2/ape/grpc/types_frostfs.pb.go new file mode 100644 index 0000000000000000000000000000000000000000..fe31b5a8e8935a27f887aea1623f8faf762b45fd GIT binary patch literal 8237 zcmeHMZExE~68AkqzKK4=|NWks zT`oyQvg=ENUV$^3#9YqKJUcTxGY>l)ilbyM#f^+*>g94SruSlzCV4V@i?z2m$y+~7 zvfR&HaeOK!rx#*;d~)IT`wMS&=iNx*Eo8qRM2jTNh28J{o+YucWIRjeL3}f$N2}lS zqg+_{3%@RsBox+7kh`_wAoi2tMOw(CFe&CAyy;NCd7I7efMDn?f^v6QV-i z5T*r7kpqWHgk+a#kUuA^WFVd8=`4v$Vd-D2zSHmL_X{a5y!1xq7xZfo=X<;TJ_Iuk zVDswwa&kO=e=->#x8)DScE8sWnjC%{pPwBbjk`iS9igMs$;BZwed-GBc7!g^@t%Jg z_2NM6b%cKWbb5LArO-Ydt@Kh#!Djb$>_rkPB5(1T&v^w;AT1yIz25dnSmuD%04qCK zF{j~`U91@Bys}5TfRi8g@xXZK>9J$D^unUHtZZH}0J7XNI}+Puxn*`Fc6g;RI}*FR z!e&RxL3_NSY^$YxtUQtv{34zSyJ|Vw5$Akr+Yt(i0E)mDK3l3=}ZoN`AuckrlrT47fZL+8BwH6|zv&}$| zc8*RSq{V@NW7|oKa)rCel7Bx?Xx(vKM06^9XP^q8UAdG44kFT(RH@3cy8}_VlnM~4 z?*MdA{NXAc4vsr{11&L>k&JWYvQ3Er@G|wincQ^X6}|QxW%~2g^gfr4{+A9L(LJW- z*rdf7J^d(i8*t~+M-r}ie^%sn1cAyOM?qeLwHL@YUys9bQ`-fkT-@d_=810F^0;bI}<`3b*Y6I&z#wudst zW{%{V&AK?Xqy4C3Z0=9(sHdZB#NqpA<7|X$-FBAFOr&j@rUHMGl-)!1#-EACiSOxB z9VJMnD#y5$q5M z$4QQ2;LSx075X-#4E!y#2I!Ved9_F@9Nx=t|7W*klnqXbh@&<0GAYn=ad+tIL9jRX za<6Vm5LaO&HH7Y!?nR~>t-)2))l=hAph!KVVK~TjTIe#*^Z!6#4sQO&1E?cTO z|BMUEje7x$4zxOStcRq0-JI95HtGc?)?1q40cTaW8O|d-t!n(!`RQc!j;=J%XD_BM zfuxFBj;g(Ulk{a=Qtj1~x%&$b=nptbRhP*zC;{(&y+qdNFf847g^!|)e}ZuS4&^+v zF*q&NP1|^S4aTTUid<}UZLh7LkaItIOP#z{T!bO#ocj_X;(@oXJEBNSX3o-KN2@AD$eJInL zp|^9EN1R1vg{iR{^TJ5HsAO|=>E4=p&83>kT*}G86wm!YMDO7kawERwoFvAgiRtSU zC(~(?s(e5X-*o-I+>c_sr5K~Ks1hQ(NERPtDMJDj#O_Ik;V$LrfIBJ{Cddk;I0c24 znjN&#!yYu4tcc{CMhdQ_SUbN97W~{wB`hDyFo<*>Q9F9YCiN;J!dC9&y+(5xXPz%r zf1s+tLpxc)wqLwBKT5(RW;1KRl8}MX?1&6Ma3aO|5j^M*GJW{%6bP`-m8?Sb@2V!rR9F8BLSsevv zHFgi@a~=d}8qu;kQ9HJt1;}024-*f3QF~zX9%Tr31wTGYd`ptoOfT~3k>pstMb*Rl zBBILeMj2&}CdXPCH5XVh%1EI}LY-1r!%~yXJXNmT7YMYk3y+YL1cFB-3WDaI{|e$c zE*mdj(*qT&mk`PqQOQPlr4JfD*rKW{!lu+Pq177*YAbQ2zN7{`&Or1;h}y zhRQOHR`o3eFVxdAy+O$SdtM0b9RkLc_&~f?r5JA?@W+g5D#rEwUB}2A0n$TCP-of& zoyH6RT~B?u;h;%P2con*5#A@@*QUO zANExpP^n2%A{XI$GrhFmd~@#Cs>FW=>uZ@eQT{*QQw;G%d=J^C$brh=ST1c-_9>T| zid9wg$jPf&p{gdd+9N`ONx#*RdMY2kD~0GZ7tFHi{~&O2Z}A9_UoeS=b5Koe@eX>@ TCxMu19LhRSrEZb$>Cu*o5x8e`iBR9q;VvA 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 KS!ve@bN@fzVgFhH literal 0 HcmV?d00001 diff --git a/apiv2/apemanager/grpc/service_frostfs_fuzz.go b/apiv2/apemanager/grpc/service_frostfs_fuzz.go new file mode 100644 index 0000000..08af63e --- /dev/null +++ b/apiv2/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/apiv2/apemanager/grpc/service_frostfs_test.go b/apiv2/apemanager/grpc/service_frostfs_test.go new file mode 100644 index 0000000..5c4653c --- /dev/null +++ b/apiv2/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/apiv2/apemanager/grpc/service_grpc.pb.go b/apiv2/apemanager/grpc/service_grpc.pb.go new file mode 100644 index 0000000000000000000000000000000000000000..47814272fe891c0b1e467544d451c40630017f37 GIT binary patch literal 9993 zcmeHNYj5MY75yCl3f2Xtw&BRLSu6(dA}9jKvo*T0gFO1BExe3G+rr4AmZY6A2Knzj zmy|5pvQlSfXJ=X@m`QB$lJ~)Lc^_1-#|APIY%WrvxDgS1*sx4VBg0cXJDtnZxyr(T zT~63|a>s_3qr0Hd>#?;^I+m&K)0fi&Q`q{u;QQdMKg|4}^$)?>yWot*wOpxC^cl~@ zlBawwRF9bUv{36f6oHke(a3oC0fQb{qY*DNsSIm1PC}U)@zJnm{-N18p+#78F6BHC z!CWRhod;6Q?cx{?p}4La@7YmMX~WH`p3Dt58|?;Za<_;z!#~bKxy<53oSJwEi8WL) zFc&kDiBzwYU}nJ$eu22O{R}f`89b!<+{6!wV2`m`fD)TT`V>}(4Us*FIGq>FBF5)D zPPMT+bR&LU#R?kEZ>|TYKS{eGXTe)06-%(yDrmq|+OR1*w@U}NtBkC9?d&|#|8RT! zu8|YM$`{weE4M|rZgZv=Q8ZY9>-7C9Nv?!h$Y{)=Gk(rlvo}*xo0$&QXF<8WL1md< zu?#F;8JymTrCf`HY+k~{Tjn5}pJQz-6J1f}C2Y!N3RqM$8YHnu?FQ1mhVI+N^@z=| zITdPFI0CRi@OTd*O|D|%5Li=kl}0QyAK6L+YxFsh8o20*G$MFtqXb{lCm=z0S(XS6 zN+o7O5h54HWV+w$Wgq5nlOPi7-eITd{nhY?^GJq&b_xt+ng(O>cxxF14YSEaRs2F( z_@|ojP_R#p6KH`Qho7hw5FQeMtnQrYOoZ_)4w>Om0<95}7TrT0nGae^!Va-~_+V3w$Ki}UBr-RAW)nwc*XLLG) z$@uPKG#=heaehwUPwvN;B-rhx56#Hm2OQzF%h#uF{sQt(t4kog1f zXk~jvp|%e9fQjq@&nMMQ{Ek1vvz_t5gxaDkEU=T3QGM0j3>hN5B^x8kn-;RV~8p_p%U;{TKs& zuQkI9YglEQCtkJqTEz;KYF^N4Rf^b-H=0KY!rji(-DqHQcsj&iYl8pLwniC&58$C3 z^x)t>+(QGhbwsseqF)g&AA}2;XgJxP9F=qX5fQDjZ8&w&Ht)F|$Ec_?ic+F=%rrl% z|D3a#B6MD8*nHVF&VwN}duFgWdhx-IJYCjY+II4`tgx-GtpP;TY$Ln2MbVL(c>a4} zkG)ZElXsr(?(%1-Eu8B-Bc*8X@wRq9Uql*h< zz_KdmsqZ}8B(gegZ&y4wFvMI@i$^l zogGz2iEAIax1&56S7?q}an)s7t?N{56QFfaES=A7y{Yh+=0lf4hjztMu4$FHDA1>W z!`(z8REtE|8sXDZ*WO)JVsIovM$X;xNZYPCOl2i>4@G8BH&{jQQ?527mQbT|3_;tQ zU9^@-O>AGKf8g@VZK02G$bbdfKOR%~qdnkDbzW%`K<%JaF^`kE9TZk_oeD6u-Gn%u zNfPu;Rmquz8Ygag-`=c(K^Kq8i@1Jur)xVNmfgbb5OK7oKiJ_{;#YtB>TO({_b*W# ziwFLtfZG#ij68gJRxXT1fSAcHnxGb8&%)6=dcRRbdJ-0g_E!R>CrM%IFNI5w)qV%$ zt3lI~$*J$q={+v?=l29?8A!iTe3k+h>VGA8mV$g~be5dH8E}>&`PeL<7JKtspoui6 z5~%#3Uo;E-9D|Ypn~zmymUqWkcVzyenM`rHPUkqKVRlj!BQZ1f4F>zZi(Ppy6X{a= zMejFI9*0Z~$s*Rk3nqAFfL>ifF0hmlULL^bmRRF5pYl7TY1yXTSn~sKR_y3hyanS@ zCQ=6hHqUhEm6kqh9{Dy)6Ja<{cJA;>M4zs?4|iSLEfhm-kh?c$bf5k6-&S?^Js0AH zB7IJhOH!l@#OkDAX48NpGBBF+M8B%*dS}~FOMCRiY4yzNB|48XWo1}Mdoxo&; c&D;ZPGa82pdBhFJzLl>Y9eA@0qC7SJ1D?O@ssI20 literal 0 HcmV?d00001 diff --git a/apiv2/apemanager/marshal.go b/apiv2/apemanager/marshal.go new file mode 100644 index 0000000..b742248 --- /dev/null +++ b/apiv2/apemanager/marshal.go @@ -0,0 +1,205 @@ +package apemanager + +import ( + apemanager "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/apemanager/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/rpc/message" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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/apiv2/apemanager/message_test.go b/apiv2/apemanager/message_test.go new file mode 100644 index 0000000..caac5ee --- /dev/null +++ b/apiv2/apemanager/message_test.go @@ -0,0 +1,26 @@ +package apemanager_test + +import ( + "testing" + + apemanagertest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/apemanager/test" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/rpc/message" + messagetest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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/apiv2/apemanager/status.go b/apiv2/apemanager/status.go new file mode 100644 index 0000000..bf1ffa0 --- /dev/null +++ b/apiv2/apemanager/status.go @@ -0,0 +1,76 @@ +package apemanager + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/status" + statusgrpc "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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/apiv2/apemanager/status_test.go b/apiv2/apemanager/status_test.go new file mode 100644 index 0000000..3cccf16 --- /dev/null +++ b/apiv2/apemanager/status_test.go @@ -0,0 +1,30 @@ +package apemanager_test + +import ( + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/apemanager" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/status" + statustest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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/apiv2/apemanager/test/generate.go b/apiv2/apemanager/test/generate.go new file mode 100644 index 0000000..c9bc41b --- /dev/null +++ b/apiv2/apemanager/test/generate.go @@ -0,0 +1,143 @@ +package apemanagertest + +import ( + apetest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/ape/test" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/apemanager" + sessiontest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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/apiv2/apemanager/types.go b/apiv2/apemanager/types.go new file mode 100644 index 0000000..74554aa --- /dev/null +++ b/apiv2/apemanager/types.go @@ -0,0 +1,226 @@ +package apemanager + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/ape" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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/apiv2/container/attributes.go b/apiv2/container/attributes.go new file mode 100644 index 0000000..288d048 --- /dev/null +++ b/apiv2/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/apiv2/container/attributes_test.go b/apiv2/container/attributes_test.go new file mode 100644 index 0000000..3599b0f --- /dev/null +++ b/apiv2/container/attributes_test.go @@ -0,0 +1,59 @@ +package container_test + +import ( + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/container" + containertest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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/apiv2/container/convert.go b/apiv2/container/convert.go new file mode 100644 index 0000000..6f450fb --- /dev/null +++ b/apiv2/container/convert.go @@ -0,0 +1,764 @@ +package container + +import ( + container "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/container/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/netmap" + netmapGRPC "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/netmap/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/refs" + refsGRPC "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/refs/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/rpc/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/rpc/message" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/session" + sessionGRPC "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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/apiv2/container/grpc/service_frostfs.pb.go b/apiv2/container/grpc/service_frostfs.pb.go new file mode 100644 index 0000000000000000000000000000000000000000..1fa1b115b3a3a7a042229e137a35cf06b93bdb45 GIT binary patch literal 74362 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 literal 0 HcmV?d00001 diff --git a/apiv2/container/grpc/service_frostfs_fuzz.go b/apiv2/container/grpc/service_frostfs_fuzz.go new file mode 100644 index 0000000..7e6d6e6 --- /dev/null +++ b/apiv2/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/apiv2/container/grpc/service_frostfs_test.go b/apiv2/container/grpc/service_frostfs_test.go new file mode 100644 index 0000000..804b89c --- /dev/null +++ b/apiv2/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/apiv2/container/grpc/service_grpc.pb.go b/apiv2/container/grpc/service_grpc.pb.go new file mode 100644 index 0000000000000000000000000000000000000000..abb0fef28efa7bc1a88d27d920de117d4d04fafa GIT binary patch literal 11817 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 literal 0 HcmV?d00001 diff --git a/apiv2/container/grpc/types_frostfs.pb.go b/apiv2/container/grpc/types_frostfs.pb.go new file mode 100644 index 0000000000000000000000000000000000000000..f562e15c94ed08dba9ce1d426c58a4d5bfee83d6 GIT binary patch literal 11447 zcmeHN>rWg<692sWSF~4(J7pdg_SCDZs()Qoo!LyhPv=sc$wX#eA?M=sS}d}(Nd4zndw!Na53)2b zg4`8*U&Q{Guj0er$FJ^qyzu-B?@S6mO$sjr_jnw}i!>{QGamh(r-_)z#82m8ayFx% zlkq5s3o*gJ@SkVd!ru~;v#@ZD{4fd9+1IR;@1wMwfAUUe`pfftegQ*f-XdIX&k|Y0 z-eN`qw44Wt$z+flA&WGP9wekJ!e~a^u!NoV2c(eCA;$RZ4@#ODIV94{uPf`$%Tw1+ z0AX%>5h3qHk4ZZ9*L zi_5S$SA1S9MG(qpF4(!bIQN#a`g9s5UUtpm-EmMRzHqKYuUBi9IaA@VL19u%Da;`m zw!16fc=|a~mWvnT(d~G|lz-V(R=bCs3$#CHYg1gg$PmQpPMU3^;Zy;Y7E8pGBJh@u z5T^z?1h^H+SSE$?+FiK=yJZ%5z8u)EF? zv@A4UB^zs){m;WM`|T6lx^>q+wi*&iB;8F4q4}KYqk2hMtm_;1XD)MYu(>M(rXNsP zG56C;WVjB}rTeZ70NwZ_jOOnE`nfaR6qo884tiW0WksiDAvT&e^r9^2+<$wQ`oK++ zGKx4$l~tTHnuJVpp4~iy$#fR|G{F_IKs_8@nH1a=lg(eK$jlnpJA#U(>}Wxs(wZ z7AEe;9Q9$wRRutp7xs}KNO}qrEma(}G6D&1gS?F8oJtV}U925mgbV&%ODZhy$ta9< zM$z^4gf-|@M2NK@nY1-WN$v$w-6NleWX-5J;@D#j z%H|?WN~w+3_ZBJVjHLUDTZtXoChv8`7qZTLS{(%db5g@KrxI&#oPa10RCVV}IFTp! z7iQ4SiX)MB|9UrA!&2o(E`?g50zo}eT=g_NEZUjwtG>xB57C&Lzc#3ecH66_<60_e z>bkyMqQCz*H+(`ds?|NaY8X?d-Xq5SH1TCcV5;BR3je3>@e-mYws&40`fvTn(3QaS zm)qu-{Zq4@GWGjU#A(~fTu~jLz&&a{QEN4grJiX%bK*USP}@@*aF9l!f30@8<+hi# z)?^0=shixFIVN2=->UJg z+Dd&C07lK$vX6ng4Sg^=41Ddg+?Ujf@-gTT9et#%W~x_2WwIWG1fwD0W#%QAv0b^f zye8BdH18{C>SDp4Rz~L%OzsErT+gH)K^S{lTm6E#lXguP$0l`_nGa9@J1z z+im)vu#KLI@7p|MsG%Xe)*RTy);z#8)p{)8Y|%J??i7q&T!ZKhIeKwG&UPh7HS;RF zd-`%!{5DR2(Qk6ShwF&J-f15Ra1Nb{R+CVRixo?!*R$02<*{H+w z%06Z)EUA(F=N>xTW7MF}099hGaf42ED!*0ThFpL6%t7mEHv9VgVbmfooqGL*!!@F_ zMUxl+cXcYefg-D?f9=d{46xRRBBhyz?1-N(F{OcYR)o_~AA9JN`{*vwdKxYyno|31U?0aft57b+jIy9W1}$2wtfMK|Gau#kLr<>oG^8opIH}?J+tU zCYi;SRj=8qs;20%>-!$1N>#(WY8eK4JOajWxLV!pdnmfOWoHEe9kXU>qwb@MfBJmu zLolOQ6DGJ&30~T18TPIFpw$K$#DYz_>tE$DLtS^- zi{3dJdPi9pa%ZW9Ygd`|)uvUr!Vc>jEUdD%Vy|0!cdoSLKR&}wq1RwnuG?614`&!0XQJvyiyfnHMJSs#i<@Z zuAxDfdyQewpnT7cDc8_|M5f=1 zZR3sRgk%ivanT&74s5jBllQ!vDYXq-9_78L){FnBSE8B;7D4|1Hl$vY?)5gLv9J52 z(kqez6AgxU>DJX}pnJp;d|3rds=4E9hD~F@V?=sA{^pzyMHxDD8TyzwEL>F-hGm%oNGW?Cw@=HjK0(nB6#)SgUqI=*;&~^Eny>aJhYrrZ>+2 E0xk6(s{jB1 literal 0 HcmV?d00001 diff --git a/apiv2/container/grpc/types_frostfs_fuzz.go b/apiv2/container/grpc/types_frostfs_fuzz.go new file mode 100644 index 0000000..5551978 --- /dev/null +++ b/apiv2/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/apiv2/container/grpc/types_frostfs_test.go b/apiv2/container/grpc/types_frostfs_test.go new file mode 100644 index 0000000..64d840e --- /dev/null +++ b/apiv2/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/apiv2/container/json.go b/apiv2/container/json.go new file mode 100644 index 0000000..91c4c08 --- /dev/null +++ b/apiv2/container/json.go @@ -0,0 +1,22 @@ +package container + +import ( + container "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/container/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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/apiv2/container/marshal.go b/apiv2/container/marshal.go new file mode 100644 index 0000000..ae38bc5 --- /dev/null +++ b/apiv2/container/marshal.go @@ -0,0 +1,345 @@ +package container + +import ( + container "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/container/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/rpc/message" + protoutil "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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/apiv2/container/message_test.go b/apiv2/container/message_test.go new file mode 100644 index 0000000..2df5bdb --- /dev/null +++ b/apiv2/container/message_test.go @@ -0,0 +1,36 @@ +package container_test + +import ( + "testing" + + containertest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/container/test" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/rpc/message" + messagetest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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/apiv2/container/status.go b/apiv2/container/status.go new file mode 100644 index 0000000..94046f7 --- /dev/null +++ b/apiv2/container/status.go @@ -0,0 +1,33 @@ +package container + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/status" + statusgrpc "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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/apiv2/container/status_test.go b/apiv2/container/status_test.go new file mode 100644 index 0000000..f3f2483 --- /dev/null +++ b/apiv2/container/status_test.go @@ -0,0 +1,15 @@ +package container_test + +import ( + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/container" + statustest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/status/test" +) + +func TestStatusCodes(t *testing.T) { + statustest.TestCodes(t, container.LocalizeFailStatus, container.GlobalizeFail, + container.StatusNotFound, 3072, + container.StatusEACLNotFound, 3073, + ) +} diff --git a/apiv2/container/test/generate.go b/apiv2/container/test/generate.go new file mode 100644 index 0000000..143aca3 --- /dev/null +++ b/apiv2/container/test/generate.go @@ -0,0 +1,240 @@ +package containertest + +import ( + "crypto/rand" + + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/container" + netmaptest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/netmap/test" + refstest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/refs/test" + sessiontest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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/apiv2/container/types.go b/apiv2/container/types.go new file mode 100644 index 0000000..453a1cc --- /dev/null +++ b/apiv2/container/types.go @@ -0,0 +1,446 @@ +package container + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/refs" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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/apiv2/lock/grpc/types_frostfs.pb.go b/apiv2/lock/grpc/types_frostfs.pb.go new file mode 100644 index 0000000000000000000000000000000000000000..31343dadb4d8b36a13fc41c1f702002680d90aab GIT binary patch literal 3790 zcmbtWZExE)5dLiaimQOOa^^_QK6>zgHOYn+c`253{g4JLEm1LRi8M&cb{6En?~bHo zTTa?x4cew6@8!9>=kAzgaI6XrcU*GKEH7Ys4-2iV$`A4E@J=0;S{YlK6izPT;_@0! zPu^XpQM6$BoZWG#R6dU)Q7@FXkVJ#8MoEad%vB-eT}GdAG$?BeG5&-9z0->v;yYo} z*0PYL%C2?8k1N#_XKb2!eWQYsJ@GI|!|K%|xXeCq-4r zya>szw6Nb3_A+raj3Rr#;Bba@24i)TTX={D=e(YBZQ$mXDw1AKzw+F^JAp6cY8==8 zI{p$pM$wXKV#eRlMwot})SWYJW~@RW024?K$ipy^q8jeYew1}5y)R2X(`|ET(f>Rn zyKSx&?PI{evka~*n^ycv{KG+W+h}RP&Nvu4P$jHENZ&8hri4=In%NZfyecKD(cHjF z*qPU3HHT90s(>Y{8oZjZCEr|4g=G5PnNOp#kvSx5@R`|yk_;hn2!ymls)isWlL=t* z=yTwq!kcLDh`pyY2pCU5Gl>nmPTSg%q%-r=#K(|caDy}8%2gSGQ`jG6KI8eE7s=5G zUUkYh;ugz<)`KguL$$_~g+jO*Q&w;`RJ`WW`qVu~0*r<0lI46a@See>Fcx_?y|;WA zepApjg-D&fVZsOc`h(j9p%%PEraf{0p|MGg0_*g&7Pdv5)R-n?aKd%GN`_A^X+V@YZ1VCub;z+oMy#zTaK$BA7{agc#!(zU zMq~o3QRYb8wRK8P2ziYiL6+CZ>a^l zc6|a_)6Tts%)<(P95M$D$=f#d1ehyz(jARpXGA|dIsj!!(6$}C3?RCke#;pGZ*i)I}T$}IlHKcR_mh9NO~J%mjh0>s(Z-#M5>HvqSa z9c*>+eAmI%#=)}hz;U!Qg@jw~PP+G3mlyq>>8+&a8zl@9vO#0r&o!5x&>SnuepuP* zC%3sDFk6VnkDyb0D>&^}D@M9F-;+j$q}Pzn|Z}E!9{!*me5k zY(ly8PqxC1fsef;mQ7VTR(cpN>p_GtB(EP{BSs>9t|U&<1-|LTnw}M?j){#&pWCOy z=Xi`ymBFq9FMo41rsdP#dCNCs`P;jWSR!a7_zBW8FmeWZ?SyM?FV6^xToG}1V!I^+ zc)D}=h=+bHcHQ$VT{?;XHd$TKsRO&Qiamw99@FbO*1z}CGkO?4(Bv5dNjvUzt~TtU zb`0#%o+db{_8M_t5r^f$wkyvQbFCIL08CTk%L9?QbmQ68TrAx87Q^uPgjb>t^rH993+Ex6Vhx;^Ilm8RK1#z%?#DR3 z$dZy(hLaam`^2O@R+W;@%@bfrsDrW5sOvD=k=jTAF>f#-^ zCAd4P>C&B7!aaF*=D54ugzow8J76bzq@{C=rb=wF9UC-A=x1xTcZ3j<5`sU@dAC;R sYXoJu>+;n_?;B`mA(2WCt?LzERD#eqgJ+w_sD++j2nuWygkCfM0?<3R4gdfE literal 0 HcmV?d00001 diff --git a/apiv2/lock/grpc/types_frostfs_fuzz.go b/apiv2/lock/grpc/types_frostfs_fuzz.go new file mode 100644 index 0000000..cb55151 --- /dev/null +++ b/apiv2/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/apiv2/lock/grpc/types_frostfs_test.go b/apiv2/lock/grpc/types_frostfs_test.go new file mode 100644 index 0000000..7c69064 --- /dev/null +++ b/apiv2/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/apiv2/netmap/convert.go b/apiv2/netmap/convert.go new file mode 100644 index 0000000..d301343 --- /dev/null +++ b/apiv2/netmap/convert.go @@ -0,0 +1,916 @@ +package netmap + +import ( + netmap "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/netmap/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/refs" + refsGRPC "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/refs/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/rpc/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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/apiv2/netmap/grpc/service_frostfs.pb.go b/apiv2/netmap/grpc/service_frostfs.pb.go new file mode 100644 index 0000000000000000000000000000000000000000..b137fb908f841a7a0615fdb8e6c5339f94960a2c GIT binary patch literal 53488 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 literal 0 HcmV?d00001 diff --git a/apiv2/netmap/grpc/service_frostfs_fuzz.go b/apiv2/netmap/grpc/service_frostfs_fuzz.go new file mode 100644 index 0000000..ebb59bc --- /dev/null +++ b/apiv2/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/apiv2/netmap/grpc/service_frostfs_test.go b/apiv2/netmap/grpc/service_frostfs_test.go new file mode 100644 index 0000000..5c9035f --- /dev/null +++ b/apiv2/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/apiv2/netmap/grpc/service_grpc.pb.go b/apiv2/netmap/grpc/service_grpc.pb.go new file mode 100644 index 0000000000000000000000000000000000000000..7881cd61760a4572989f516b8bd3d6d60cbfebcf GIT binary patch literal 9132 zcmeHNZExE+68;?h3Z4(>*?}YXdN?eQqBs<8x@X)rDdP0L92O}hr8b!=%qe|1>6pTne~5v0iC+%D%=NwK$Yj0FY6{jX%zKDHL~3trevfKFOfMZ$#rl~o3GqMvhR5c-iU5@LX{TJi<`gkYN?D|5*q zsbwlPk#25nX--F@@^*%u5GQgu>fRTle_4L>DpBIE-uSU93IuI6bqmCiU6-{E0E4}O%EHPj&UDq)HCsa6X|=8|Jah$`or6_j}ra8=lR9lO~ylVxC)USJns z;|N}W?9B38S$HKMJ%AsXSwI!`Kw&i(HfEConFItBK)?*0I*_uO&4)}Ck}dd}tpF^+ zGJ}y=)&(h8tg(f*3ZyL0Z{5Fh>9jd}3uW0F(@ShIKi|1URuO60J6?XINoj^?smihy zZFmZPoifQKrw(o*s)-{-T4_*4(~e$LMJAl{vCk_t1Uxs&Pk?qYm*SRXDKZXO<@6yf zRHY+{u8IPjaFDv8sY_-O*_uLh!j6wG{&RfH`p<`KdN#hAT%2D|Ka9s`)9JvAgdyNJ z_hN@9k;|N#Yuw^Ra(R1ICf{$nCJOLNvs*L{_X@*BIn5= zlUgf1aAsb@;4T(y{XLiJ?Uc?OitLl4DJrdrLA8Et7G&qA1-B+8Wzzeh4TKH>wk6&P zD>i&#Hf|x?GE-+urcy_w#&r*{ER~plad^p&CuJ^x2u_j*@eSk-gt#?h2j#oSr{f|# zlAv0jD9ezKWEwMwu+?mkEl7OP@cKQl@UG+O!^JL_3ml8C0x}FmdX*A(YTz>`4SiYog9pY)+TxT z++H^o9$&;Y5s;gksvl)Ykd50{-n@31XN$3tD_x&qDj0OK>dQl=m;+KO?@v?1#) zTw|7QK&-EyvVz*O)z`-Q`JlBF1JH7M! z!|+trd#qLZP_t=gSD;tn`a!q?@9qs(pSa4!HHN9pLcMRd1iE?d(u`s%+texeKpa8~ z3yl`E0%bBpvzhUPcA%#mYA@AUm94ToC(Y=~R5^Hv9-He~`+l42kC@HYywAU_DcBQ> z%Gfh1&|2j0fTd4F_e{T(v&^7#*d>M5HN831#iWzYg5r?od;f4UpGuI%1{l}N#8C-(!dAHtCtNVQX<3nvh*kGR)#tCxg%UzA1X>0!54m9C8XB7RYVSG< z-{XD@ByaQ}Zsk#bC&sGo+Da`%GWXfOtEqxBM_$LNdlbS7=-3`@pAt^nf!+zqR*s$= zFca70xepXA=_1hCO4Ra~FpBp>-6Z_ffWtJUxJpwGP^hIuR_Ye9`ClNWbkzplP4r(a8!P~oD7U? zAox183=H|g%nVlgR>&Ecw8PI}q>0b(q3CWaDm?a^hE!NxP&wc#FKiJq!Pfxcvn-p~ zzZtwB;)#p$HWgcLf`2S@53}y2-f7*bL55Ul(X%a8YpBOi5<-Voro@{k^q>$}s3c1> z{M?sIJgHF?hk~qJ527WWNLyC5d}-e9y}{%L&eYm`IuuV?@8L)I9*)iW1i8ZF?y0|5 zZ!xHk_&%;W1Bm(;esjwH_p|fVf3DX(qVv2KsTXfm2DH{uvzj~c52?9m(jEP^uRTa; zkLnI&oAmUs=75TaC=bMU^^^7f1s%XO$oVfEax@MgdBQDs0V57}{0A7AaTom`bGc82 literal 0 HcmV?d00001 diff --git a/apiv2/netmap/grpc/types_frostfs.pb.go b/apiv2/netmap/grpc/types_frostfs.pb.go new file mode 100644 index 0000000000000000000000000000000000000000..1ee614f1f1aaff0200850e4ab32fac55f5a532d0 GIT binary patch literal 52866 zcmeHQYjYbnvi(f`idk0eE|sfL@gq*wTfS9}EpO?rEqP;m_k-8vrKq9Jh_B0sEZt zYu|ntf7_dmXY<~yojpCyj*eev2Tu=Qw|90Xo$guZL!OQD`LHwD+361_uTJC++Tdxc|?7 zcRrr>J1_G2wBMcW8x>0YGRQCTDU0C9hn@alx?n2mzL_n`{S1fKR#Qkna{@{P^cpvi}g0KR$YzpbtCp$B>+?viu3j{}PfvKm2<_`jGt2ccdogohg~K-FQFh z408-3%>6Cv%sVI*Ed1A3^i}=qdj37y5yI;2(D&O_N$lzkUl_aNZd#ToXk2cia+c z!V>WxX5Uc@NP5&!{@mfaXixI)UA~JJChy*pyGzR6=ey{IWZCcK?vk<(_%3=XS@s9M zOMRER{UhI{&P?6?i_}ZKo49?4I_o#mp59{A%~}`Uo_DiXtS+tHOu9ZpulIY|`Cc|Y z%N{=Rl&ol?Vy%nacYme(G(yvSzL<`(a~@Rv0aoPT+Rw(*VP}3gnzt~Z5ALJfUUuiZ z-JRb|kZ(+pce7{H@ld6isWiLU2~A5&Wn$HNJM+?fa{*g0o~`p;FX0?BStw+$GnnNN zMLh45L1!_`OKw*#zkl-l@tao%k;Byj>}{3m)#DdM8#XF9S*3b<`0DlH(UZ_S7}edt z#Ff0-zMEyq#M)qNBo6<8aW`G9YJJMQ()1Fno!v3(qNa(_Sw-P(vbabArT&%L7xcmA zRnN&#Tkpb7D=D4aTtnlY^#>F(z*ZLBIjQ&&d2)Qz5b^Cl6lFYYk_t5cv(xx{{+V4} ziQp{%O!to`eB0~4V=$i3?SHbLP4H(eAPNy_mc4za!Z`*#mURXi*o#g-) z_M$VLee4X-qzpFL`bJpnwnqH{tguM^W;8VV6g9QH9kP_BE#b}7Ai}DIVnm5wwUI#>{EaKQOeQK_4@hX zG~>>kWgk1|xxaPNA9bdmnSI;)KJB4E7`WjU%K(45t8Nb-?NNqK481KPJWQcX`CpGj z(6+cvYEtXYUUtzYbwbB4CAv#QP^l8l!DumLHuv_#AGR*q$CKR>T~OhD;>G#}Ds)%Y zr@3R=86g+BXiGb1+<;h|qkM++28^Ufsn$26?#H})mY=r1-^>1Fh2Qqyfi)WKrWlZt zGGZ)MOIQhMxRCS=@?k!j%a|_HQgm@X?RC0&VnhloTc-%Z-@ZHfJkNLaUuw*d8cCUt zSJapE>u>qI1z}I~9*iMz|K(!d8iL@WeK73Lo!qTq`$ayRA$>EoZ&9aH-H7j89V82` zYB%5q^@5w%ozZ16<6-uVWj3WsD)fvy9MQlaA3+CLp|U?<#^aG34%?3>lYB(Ohk!Fu zI*gMQBNba-D$qhHgkiaNS2QkB>X7f26f>+()G$$2<&1O{1uNAx)W5=Lx#sJjwZ5mp z`b~Axe32X7YOOSKC`^@J8l7X?noYZ=nXP;}&G6rN%414?y4TJ8$Uh?o^<)gaznDwA zX<)%&H~ViLRQ%W@7SOm}w|xXcF2qC#r7);;6FT4=l2b&02<-!^y4PxUJEPHf4#(O# z1rl*FSI-ES`o~#wFKdcFXrjBwpc^x|(e6j8kLx;G3|YUr9mHeEQDEVuc_3_@cIF)y zn1Wmfl=zTjf6$23V$y_63peekOd=5RXK`2_*d<*+7f^j*&XORAf+SGpZ3+VRksSD4 z5Ch2>#5kTLq!8PgdsKc3Dv=!g7gs5u*D?=+SvGT1(8sErO-9VPa%v> zHVJXmP@kd!G-l=?K zZJ_M++GW${k@#!LAX64;YX30%<0qIP*s>gCe)tc6I-kI-;lWDN31&1hiDH&`5qbjU zAjT8&Y&KIYUn$FTOZ70Ln&q9Ria-h&L_HzcP<^|W%0LVYB8br~li+v)0W8BLPX*VL z?g+9{FT!`JCZQL=@Z2+G&rR_blzW*7to-%5K~2+3v9u$EX`w5enJtq<6&A8s%23rI zN*?yg5`{y*INs;RTl+?DXa@xm;QzcjJ}S<$g*>8aa@DYlxS&BTiTBu6bVB_^rl?SF z`(KRs{)(QxaG}`&FlH|Or%$jhwTDmbpB6m?g7~LDIQkwetYL3Mdf@?tJN@(YpdpcmVd5bU1AHX#5HtxHP`W^22+_Sp$jh3 zti$=7(&rk?ts~fY>TvE!c3p!vhF8Y!Esb4u=t_R6@55jlL1D1R45&XFP+&DFBv~b0 z#<){eL>Ot$J7R#V(Z%0zQIay7u9h05QPhoj*|ccVvw#=V7;;T01W%H(8qD`?ZX*B zhAC%)G!k^-2qp>FLK;k$dq;U zm_Kk0dKKfqwZO(ynm40arEPnEN=QXnrN)z^MKhC zI6M29x91+yrp^iL52NvOM!1RM1nJfp%gg}X-yHSAdLw=tK{Qh>kY;oECXosmlly~gfS^aK**J8 zbW|8e?zZw!N{@57w1UZ)mefLha+#sHN@hrkG3YZi6kJ88sTGQo7B?N4CwwPc20D&} zlEM^9&?gA>1COJ9&(&FaLBIC0p58;nV##KgIy&axQ5O~Adc2tI$z>!-gd!VU^R(pP z6TS-sq3dE4gcr15<%67-*vZffFt-8G1(f^AcrltYe!Jiq+F{ULx=tvyAnin<-;_a@ zmvD&U@f>z`vX}$VWrK4pI_|m$yNOLqBqP5T)a_bX7wj(67s6DMN;lNCpj= z3ZQc_lUWDH_T5}ydV7#;--H{1WnaL-kzXpq-)|(3h%}3QCdGV`V5k-)%Ccg%0yx_% zoUjmF$g5X^hiF)fVQo*yu{mT2fu#xrvuv6=ZxfQu>P(RU zWmEyEuIdaA)gT?dJgCkUMDVCsPzH|5kP=Fr2#MrNi{Vt< z3V>}hr-Wo`c2^h8DvA2au0lYP%n25P+}o5&V$w(?x#Zy|gOk+3OAav}R zt^pqVLXdiRL5pcH~mC}j&)e}u< zYs#gJ3(&V|JN4JqL1y0**9|k5B(W?LP~PtmXzo(rRs&qsnNLj@jvcno_!aNLPQl|{ zwy7GdWg08QgLP`?xQw+%B|0Nrw9TIC)X-z_c^&p*8Nz#O=&#pOixs~x{+p1%EafW# zTtJ$>I0DQ@T}J0*VyD2Up>SUq&r;OKSzHP36H6}hlc|~c6=C4u)`l=(;rPA=04$WP zn~DAwgj)&yI(m2%eBg9-@XENaP$EhwV87-i%L6EJjPV3e83yi92y>QYw&EHu!P8;~ zlapGtQDF7wd@|^FI{~gLn(bgijc^?_>abJi)PzifJSCbbR!iXML6;WL9Ltzl?(Yfd z%MRAUKMQe@G`P1Gq^j+!i>Q{!s{z$Cxy>|1JT)f2L2#-QY(r>j0F?3;VjfbMWek*x z0WqY>pqJCB5@Em&5Epj4dc~=tWhCpM8)y!ww+fe9H{M#b)LO7vu++_$OHt2AP2l7V zaWth^j#w6zM~X*kk|?b6c|xIl`9O7+b4aS$mXJ>y9&<6b8u--atbu#7C!tyRdeKJN z#Ori3Ax{__TnYVjbwmi7yNFOD#PkFM4ZLGQFjaea!p7BL*`S(8w%~d}JlW(MIppmM z7?^KC#Ndt>5_XTjG!AKow@L8Nn68EWSt*F(6rmoP<*37U#yFethD46Kh_bos=(q?1 zw6c&ZPy&div0N1f7!(Mli@-^%0Kx_IkWVU5fHJsMEn=Vqb%hLy)D$x)Q5H0~siIyT zAhce(ZhWvPh=Cs02oH8wKzQLsRP~f=z<4uFeAWTMoHfBA!}(Ohgt?DFu9P$|!xZblb}q#{C?B$iQ`szF^m2elUFoUVmtz1&cox|< zU8L~gQzhh@7FjUeS`byCN9#gW zON&)QR@KGKofe_1bg>%*VHE|uG?Z0(j@R^>X6G2fs(kJom&-$L-@*|Afce8TjMznrhw8h6eUHm0*?Q!eD1%{tTo_6r_2=o6%fSDKGp3iif|`)5%HNl*X^$DW%{l7 zWVa)DD?4!A&oBFIH^;vMdL}J7(Vv=rLb)4P0~(VRM*W(kKqr^6QF99kfj6rFR#POY zT@6*hF79RSYf%Z@^_gmc{k{e@5ExgTxp{NIp)BO^wJGJ9)V3rcHN5GPjns6 z3|F@p;U9IG&O>Gsm_zZG#<~mcmABqHw*#QmCv=$Au(pxj_Ua0(Qx9-mR}5IG)uXts zy9LvUaOae`NsmwurOFw~PsBP!@Hbgaou--T^H8{76!t6~3r92yn^D+k zooa}c*;jR{Gh%N> z?jXqJ6+k((f^)7wyV8tvGh2j9?Yi!jfMo(1VtS1$0#gN}DuC{AQDD`<3Ff3I;wOu& zdvby+Ncn}1SJ*u?DL~WWQxf=rTU@2Oy302gr&6zq=2BIJ+iL(v>mLb!2C9`c&vZRx zR-?969qZlAx;<+pH{Z3r+kD_gwbm>+HLWpl9J55JY^=$1B zSuThf?blVHORNGpZ(LphQU3_vBu9Sec?scVf4V^30~56LHcw2@Dkw^-J~Ba;nBd0C zI9a(jRxUOreKuq$tZ12sE?42)X0gYk>+5&9E56M>cXib5bamt9K9GpA*aN}U_1iCn zx7m8Bp>Es7&zGA{@h>-AAAj(vDV9hrU^R83*kq&o(vR@sl0&>Wfhv<7dx|(k?neytKluy?A_h^!niF@zIlm z%q}{@d%+3p@y!))T4)9>vLo06cAUk#_Iy&g8Fz(@tpxN z(Hh6NTS5OIiC#CB~i`FYkS|C_lw_aNE1}$ADWW4n1b-d2{%AXp;JM5uHNZgjv@Uj~#Q;7<3 zOir(m3OMrCdDSe?Z*}oD)kU{<{WjH@!W!j94qB(tPCU0DLn!C0i$Y-b22>#nOfvk- zi$ywug0yV<3msbLPU&~PhVn~W^VB*+m3jM%oWx&94&BP+)mA=JU2HzWRdFj9Kg%s+ zpq~P;)yKwQxGAVBEPd+Wz=j*72bVvp1?;0$2mD6R5iY~Y8Y1i1HU;4dB2oBCK^S>n zLiKf<;%F6-K+a5pMJ&Cv$2~@)fkDMzdX=WE2fR>&E(dx&ljG`Of=d?#SQR|?_&Ixyl}jQ3~{s|lPU~ookyUaY^on?N+%T*U7@-?oJ+x3E z_2@!?-hi5JW+fms64$*LP$83HXVFgWoyka>MH5hc{{$k^~;(UuXBLKx#O-?ZAA&V+1c3CwQ=cMhes83EnWk$cO)*LLU=HM)(F!m&SY4W_XpF zO{u1klT{K4W>+DYZMV0J z9%SJlP@o|1Y!l*cc7M39Di+!YC85-IbuSnvvJyPhgOEs4JiqU;!mvQ4#G{wTPy@ETa?uy{Tp8USOlD+P&;}A|?#Z2cEIS z?w+sDNpEshiqDD!$&HU_R+SPkMcBX5o^i*Bg%$4S1@0=L)U;_d(Bd^lL$2cub-o7@ zTV1c~=-`R7w+b9B#Q%Q6>!=>wm&x^_ZDtH#2FFqj1$JB>T2U4G#0Vr?@~Sp(gI56U zjL9n4ZbiGyqBhYmW5!``eK@ih*(P+1Iv1l9cd&ydtJ^rE)V@aZWM+$lWzmgjRJQ?r z?q(JTUlZUNNbnWrJ9A29I8necim4pf83g*+q-P!pvs(e8H2+iP z8o-e^4Wu+Dg$C8xOWQFAQf{W3fqYQF9T_xv3B~#tZJE(FcYpeDsb(*+Kda~GLa5zg*r4~J4Q{C+%F9KLc_4olh29zg9Tv)RQJ~b0KQ`}#Fq;Kcxt2&G@kjxb z$`?F}TEtHIwjQ#<-@hzkijl?N5>!&vnU2>bLj@#7kAY#fg~P=_rq5weE%01pC`x$( zH4~n4mhOZ53P8C5jd#y^LAZ+|RIgGPCa=*%h$Eb7ha7#QCxKKXzJZB-Lp$WOE!Vy) zE|$ZRW?%)^g@@&&WEDV1h=r+7(J2J31^QMEql_r(tKd%VDFRBCz+a*cRM$EH5tl-= zvG$|(kw_cGZd3tmvij1mb(l>!8w0d)4z~cK$<**y3kI^uu^ptaL@pT+s8PA$B_N^{1P2y3LX)x}rlw>65J7b!w?@+2mKAeWPJaY-kc(J$Qf; zZV3VRis$8|R5bS6+W)k~DE%_fZO?pDDzHW>jB%x@u#gDL08yYxqj~x5N8ldiocN9W zr2bQHo05a~qeqgs9qK9z)E0kBv&&Q`2hWu0yjPWMazC$M1=2l~Ebf1iZY*Y=ONHdN zaw>X4d&aB8WYWv@1q799C@-aIG$(cays?}#-O3w~q*e-MDZ@2pt!K5L--`EdK-=I6 zpu5#+>v_$GxMJq4AHsf{31oV3ESCH78RZIrOkcjHn3qT~q3Pv}aMh*&ajJ#vl9hUW zUe4u0{G3c^V;g-~X4Md5ACnm{0k(y-ukbDh zedolsmJ`FVG}HY3DH0u_QHaP1~uC#gD z^uL_kESVgr=0>=ZmUeDTc8P_xG`DT8vw6FN|E=CNy{+_(Rw#qy?a5+Fhf&H(r`y8f zc2(-CS~sAfy`wKWANt*+#qfmlAl>#-C^PglTx9kVZQosg+D7iiFIqAJVnlyhM`Q zv!SKC;%?SZA2BF#P8ksMN=~4NC0f5rmXA4nVaipaOk}DpJTH%3lc9Q{*q2x=l)k;~ z3xv{&LUwq?Q#A4Fi@*;h76x_m2Coc;q!>9kQ`(b<4MyH`E!|n0P%SHOT9l}tHLg|G zHdi=OCn^uWLm2@!nnbr&WYzjc!)<2OGJNKveh)b{HEE5EI@BKuFA9s5;Xa`&tyYHh zLyvW!R z(rp$niE4|)jP9TlNBO5#bj@{8KAqB$zC|}twolTM-M?l;AGnu>o49(zdHY~G9Z!3$ z=3+F&!($&igNNB4KQ;HL3|B{CC;r1<<;t{p2ml|Up4Qs~9hL|yDsF|g_>4{w2nzw{ zkeE|Jjqo12F||f*;s$D4PuieBZDE5lMOlMeD@8RehNKcPW3r%WEF4@NB}{EbUSCct z0x`J;?NQHbm5`CXLe4^*UL|l;G?cmUECZV1vP{i4F$1e~iIL}@jVE}c%}2oLTEUWno&yoP5s&nDBn*T10D zwLkiRA#LvcyE*jnTt!vn*l4BSstK&HRxM^HH7b$0EwslvRg6NVUQtVN9!QM6RJrZl z4WfEB4P6gPR}jK1;Oj1iOYC9@ZMTfl$*fBeQ$r7QRf{46qco;46WdkOK%wS%`5lJmm-jy^1pc{=wqx(Sv^W;hP-F%p5AM#ng7_9PPcJV2@Ud&hX z%Rj-hKYf`0X|$LxSEFS=d--Gb!;imYuU@|XrT^&B_2Ba3;6t9xFMi7}SC1Zzr`Pkv zD(gKu`E5C$WvBVAWpR^# zH<{lIzaLyYF>n5~9DW2Qo(!(X>!(i^`DpnBYnw*CYSqdzUoOY)u-z` z`#<^W=lp+e^5yFNxAWnr3<}&_uCmXMPQDoq7cgMiV;uLs{p-JxjpwHWetG)ek4}Cb z+-CUS1rDeDXUZ)Gw@~KyM~~Kn1*+)#%u1;L6N>)tgT?Y{FoBL_*^8|AIAG_jHycmR z;%dLnrcyCk4Y}=WBEn#GHBF>OHIV3&C)u0T;9`=$8UH)a7WwLCF&>@w?ZvPg=GtKM1GBWA|4)fo=+7@2zUA_GC=pC`<9_UA_@zk}W&+yCnY zbKL&{v?L$CAq@dG-@wb>SLfNrDhCXdU*TI&2`cpzOM#+53DZ6nM7;o!nc*RQK&gO1 zo8;4cwqnthDGYQVUyKHq$&LqY_lC<=_V(Syr&WGteqyJm*>mV4FzZz1C;SVvu?H*< z^ARX$!TXQ4!Iq(><@0}wGpez3P31y#ei@c5wQm-b`&N9Q2+V z@ZZfa%XG4GN)NOY2hrCWYN=q`?=2UXGT6O*vB=&mr9;i*J1JPze3WZ-s$CF zHk+@&HVlT@44N>L8?3?~m#631Xph%PS;IM1Q!M5>J4YnWsX4ISc)SOfL9s{`m# ze%sRvhNXw10dAydKOQdR`s}Zf5R0TJoITI}cne~K)`<{GibV31L;|{5AP!Pc%U63j zK;xbaa3Z|OuoFNN7=eGr)`4k-IZ!^eVa$yH!8-fPEesJEXr)!AQITX5N^cycwNHs= zg|rDBSy!l8cddG_{*gMJYv&pYTB^HvPG8Eg7JUf{P;s?LxT0b zmf}st z3oFjDcXpoLvL#4Lz%V4u&Tm%PW1oJZiHCBy$ie~*?tkxeb~BlfhO)+xo|q!YPVdXl zU&1UvBLKc3tWDS8<&QV$0YY`qfYbATSwHVzr_aHQJn;!|`L|y^e}|JvbSIJu)Pe#a zur#T~;5I=9Ng#Qeyw;b1HoXr04jp0@5$jT_BvPXB`a(mE^IR4eFh8(hK=;VTv5(&W z9-aBmXmp>GRUnNKsxr7=pye`idcn#8MmjY?;x=IQc&w?ib}WCHUw@yk^9ic&c-DWt z1m|=?9u3$Odhi3N2kX~ql%3(9mGp1EPbsZcPcP(TkU`DQ^J zs6s%B2yN&SMiutC{4^oo1%#0p7ea(P_%CpCD7K?j?W?{CHN96{-&CGTC2Zm!`C>f! zWE%0CpjYF|!3qEcQ@}K_R+U=Dp3TEfS0h+~L^@%78`O|VP2w`O{20~L*vmNctm_aH zRS`7Wk1vY?Qi?pBg4L??HHN2J*`Ss&$tq6$8I<|W_`@t8qEQE*crsaL7_d^bzN9x~ z=_%01s6Kl=!U7mQLNxIKV*2qCegjZtbv2j)P1hWS$>1M=nXy%%>|ipPgO2AzixK>6 zFonVF6FR+MW-&az!B7|=#M`Se#0bMNgccBEVCCBkF(6#e5rv>d3s5MCuUGlx6S4Rs zyja|hm-)E|SQxfpW#LApI&g(euJW1XNdSQcxP_8dA#MTsB$8&)U=T=4EJ*-l2VOHO zMenTdFc(@m2}|*6OV3Ds0EWTdEEx6z>;#9DWdq$sY+$*iu9f35XPK`}J=7x$Occ1F zMjLgnjh86VF0_F9L$QYPlI{D@Q*H;VoP}u3AtEYg*|xzHS}0YFwt>Za_^Anu;w+X% z5Fo^m1+k*Fry7*ew#;u&zo}^PYi==csO#yIUe3}%*jXlJZPN!1+%&*!P)pF|L&Mw| zV1q4)rOo4{qzqF{BeUKr74W5}Wff;MD?K--oWrSNa+ zuvI~rH-zLRGm{7i7QL%gg>YcjKqzl~e5B-WJlo*z&X8Ixz!20stbC=oKidY{tOn>< zY}2<-D*!DoZ%H)6Z%Q6lwB^BV#%Or}AU~^UrE`ca9ucuTR*Mf8Z3{cs0C=++gR6C? z;F~4nfhYDMtTnQ&Y@WRY!*k+6aJI1Xuw>-62`+KQl&F8_f)PrdWaOz9jXaEGBX2qu z4kK?or8}1llkvo23=FFa{}IW8A9p7Ra4z9r0!Ry|BLP-cdo99aZS~6}o?~k@CkY^% zt!yD3A!z^{`yNy*hS~}{A!;VQkSED*NU2u+klNA_d187Zf7kB{YYFzl=u`^agwm`lJ;4p6fbrW|%k<6KJ{>m{h6 zIpcf?iVEA3x}rd_k`Ak3IgxH*v{*C5Dcc32mS9Iz^$4!D0N3m!D*=&YT|$pS;5AB~ zH#3f%!HOh9J3C0FzbVQ~f=+P*oes6;_{>3hhEFehuO5h^%4M+Ewaw1V0reA|%bcUL#Fk7YFJ(7_u# zr3Y9TQ{wWiNWHn9j90JWyl@%0qHIh+)R?fV-HQ0D%chi{S<0rW_G0e`(v#g&7q1`G z=|iR4+s>G~%e=Bvgl3Hf?_lo(W-C3efZYfP#OZeT83)|pK|wvckS9Jds18Na`JZSS zw&cN0Cb2dm6?s=68hKYCAA%)Y@)piiVT@lCaK$ewSbB!Zh|E%V35lM@%Ni)t_h8SH zs(v-VNO4s{|EyDd6p1LPYd*{8BRUj>$ArF!oGUE;{xkmnbAnC_3!I@ds4!I5C>w`( zWVZyQLImr)Kk!Z+VPHs|OQlt~K(ywRpy9s#(Nt<*Ni|?A7AsZwO#d&3)tF&MKE-ep zFumQ=#X?E3@5ETF6jJB2{KncLe#nc zB#ccRM2m@_Z=t=kecHH42g_&Pf@NV3kmgp`vw<}tVgkz&K4jk3;ALqcvReEAeQCV8e0VO^ zU@9l*tS(2~Y=Rvav3uJcQ)%8i-WXGy$Q(ZIiM7}hL&L$lL2RBd|EbU^eUH;J^mjHJ zd`Py*Ue-}q8B3kmTRRF%Q0wV!Ew)^GlZi~kDOsG#K8R_l?gP7^!ZTj|!Pf=RBWtE& zM#S7yG9z}TrckB4FookJPiqNJO2>?|NvhwJVP4Ik8$KDl9NO$kX ziBbDntb`+|hK&y0*s}$Z$m|RGX--&52^^PoY*usRrYhgy!}>rt-WqO2L>j$x-^~LaB5bo&hZkT zJ-Wn)Cpjn-U9R&Iu8W{N1Tc&b!GpWT$1?s9P8w}HEy0{r_0I9&GFq`W?VT%f zR!hUH-f{8ZP*iZcvUjq`JN@bLrQcNWcTcB`RE+#kw#;dh3?qT+>z7eaFw*FBw;YM6 zjXOD6T@*!AYy;UBa`Q52vN$O+L|fYXrr4Md5xFVQxj-B#Pb}^+gmm_Z72cG>*3Z3; zgydeifUy%%9mr)qEU?&Hj|Au0qt3Jp<|6#7+}WiaKGb*IHwp0{yMvJ0;sd`>-)3%m^IT>7Eo~w&mB1U%)&uI}~Pf zp>Q{e*SnI<37E5KBGcpDK8a6hu)$G2-0pT<6ceJH$ITWGiN5>oK5DT-FRgU9gckbr zM#)|7_X*cIkC(E=unte&iWMA;T5E_Aw^02pC7*1(TqJmm3)kT_Sa^h6FlpP}gMbef z>92j2U-1LDF1aFdMy=wOA1UvSf~7C|!3yRSSAZd3*}HyDzMEf<^Cf)h<^mAax9@HM zJNo)*Q2J7pX@nLRiNXQ8Y1lYjH;o_Hs4L!c2qY)!?h&F~$YtxRf$#v`3}M4MxG{Z= zj1w1M4`JrjM4CluYgO@Y37VZ}@4;ET#;@5yfO(zcb?v{tMpY%q6V4$)o{7>@MPnwR z3^IxvT-*H|TJcC6Eb>>}od8X{^M}!_`snb`CQ-c}RzPhY6ew!tHzkiN+VX%vV=Fxf zke^kwV!%H<4uJ=i0$oJT_^gtAzwK8tv&&wQ;&${cx8i{nGbs4WAs)af>RSU?(P|_5 z9GyaomXL>|*@s}@EQ%%`0obtRd2F$&-vc)uNGyk!lkvo2%+yXVDk3DBPt@pjw?G`f&hTT(*5JW84LfdkIC`a4dQUQ%70?-+5x^06 z_@!85k>w!7(9TK=ugR25VrjNkV~TP-<@L~lX+qH;XSQwVn1^+ic0uNY^g*5^J0Ydo z^g=32H{^-whx}c;BdqY)3#0mgLBUd6d|5mfX~Vi91Nrv+o8i~ctSfb`gTS(cR4JZy zoi?27`XF~p({w<;H8NK|FhWq_C7VHX1-|3_84Uh4(#$qu0kOu)H8pIPcDr4uZ2d$h_E663k z;3X|^_TP@_L!DU2W8ocEhNs@cZGK9#So6h8yl0@ff*Tq5BjVfwake&ubGu1#ZKA$+ zu@x$+K+fJ9oDT5H`N?WP_??S1V8sxulymc!_Nuuu24sbgIgnR%SdhXo4_6Fe#<()C z)*fNAn%C&FEcHQ;wc&|7&6p`Qk3iaFOgGS|r!JqJEfL!y@7t|lAJ_!(h(QfwURX{i z)aZ+BK;MY(;a}(3$h-?P=wWEdNWr0qVClzt#HZtk3=>ztN?}{@%#}rZMK;p^hAk8* z{@!U|1ytTN`?7Shdb|vZy>~AWt*d#tSI|gHl-X4aTp){x!%w_HzLXkO6RTT+E$?5V za@eodh%&CEiF>^QI`?s{S4fi2BFNo7K8l^b)ypKZ+zXy8DFg!09n5w0fyB3+NO}kT zvf6n+*INa0Fo*d?^MIK<-)_ab8e(^>u7q)2`HowS5KmnM+{+U%&xTXo)l~HUjJyF*Gn1w2nmk_Bgg3i<5eki#hVZ5)5F-35 z&Wa2gPynJ_cM}v*PEHbwQ@&6G@`5JHWjE#I4M^k&fkaaHB6SXx6!EyQS$uB$lf3Ds zsG_>p)2516UUU<*LpO*JbAaLn?`WV4pg zxZcx?CW;3m&-@hhpQ#{&Ho7ai+9>Fvy?O=`e7WJRTyRrDL~(Dw(@oqGWuuo{hc3m# z+F8bEAPr$iqVi4w%lbE&1bp)1Q{#4wG0dmBcVpn(E5QfR01^Tb&1}+-8jM_S>mC!} z!gIo#)fZ^Z89*W%E5H`V!pu4$& z|8`eKn0p(-YD5_?O9)>$j}M#|b!$Udjz_Xi19VY>tFF3BXLKxv7MgGSTz=NNCgFc> z@})Xo6IONy5%A-eUh=P;|Dh)0Y~nj#lHf$(@Wk@a+s6}Kjk*YAP(wg~a`17VamVBR z2)MnH4=H&in?sgEA3fgJqwL~lG=eb&tmwn)3Z^6cwp?bbtHBJ);8saKd?|MToMSGT ztpa5Slga!Nvu3e1Z1CqCz8pJ)7qd@@3(OZ8YUmA`Iv{>~HNL#chT~y2o3E(yZFajD z!>5iv0L7e{yPQw2C;2L$d?FTqgcpn3{kR`N&AEFk`F;Q?(%Xi#k9Q-0 zZ7E+V#S!bfdxy0~$O3{&)k*nx3GeniQDX9aw7oo&IkL0Gk`|czMK_~pH z+5jL(7$-^rJZ`aJeN@F_y>z~_CIx^=i9(F=8h9Jumc#hOqSG~G)Sku+G&ISuYoR{d zu8vI)E}9n%QMqy(0xWxXOP)huj5dgfFv9Vy_TWNGs_DJfHjBX5-o_*&Py0-?msDd(_YMd8BE z`BBQuz3}HfEH}dI*1>cdb9MEF!hsocemx8?J}`*y+?2=kw2C$E{r)d5=%}TU{JfOoqgw@2t9PZF6vZTQcTiC5pGH6?ZHYx*jC1Z+# zElW0N6y}q0udP)T9(vRyBd_-P-Yw-hd0ZH)x7&cQh$C@Vb{H1Uw|g|R+x#F;h++nJ z5k?hrA_IC1rdkA3RuxOa8L?AQh#+t3gf7;Q-B&Q6;sA={Y{~}bgD5?+FXU&fgb;2( z#bdU*sjZ^K(u@#pBaW}OlM=$Mw}?+%mD-_6P(@5cA}TRe_A?+k=7k*dLh@yHJBHjB z%s^QVrg=6R=aXT!9!ww?EV~-4bN5O~E8HzM)9~RYhS&}sTxN)6{2@f=$J`J;O<(Wo zysiNQh4V|;dEi(<1DF8atYd)qrh~=uYA|`8{qgqn9P>YEKyW93M0FtfA-r6~-g=~6ROFMfN8$>LA-G@sDb5h# zeo)?25_#fj45O4tLa|F|m?NTSR3(YnCg8}Qi>53_R`mUfB-5^mdVm=n;dGUBIt4T4 z-kFZL2PTVxPeN?W`3lt?tp{<3Vns@JOgGk`Yr0z8xtNE}lSQn2_6Qt2ri<9)g$4N= zPTkA1H_{0(Yqc+3agUn6ZCp<9KG06(!|e{}R7@N(PB`#}yF9@cobUAAjL=i`AkOe5 zk?$^LBwTMiUTn@tSf~z9ZVGGcm2X$mld}Z>b!%|ETqJmm3)kV5Y8l^2bG!Alk(W6h zCeokIP=N6_!{GvtJMjlI>|X}i9q`LWStBtuhnS}GMp8A?@N8vGaZN*%wzTFRfwcuZ zcAY3vDTJgmTj%*P!%!GnsrE>ljT!9#?F;+{1? zhs?m>%F$^KiJ{|RL{?K&28nq@YmRBAd!&eoU5AJXp2Qj7VFt;7{g6aR_4cdhbU*aQ4&DwT zsv;qZ6};!bD#?os=`n|-MGlEk#*z@i>R%Kt*cWv|17~u&OD6X;LRr3NudP)V#rGCVPr_BAp&CX%Ssh~ot# zEfY!n3HcyXNrEmOQZh-v`ooCTj|n9^PbdlWO4h@NgB>)04R|-YW6S`Fcz^-?(BTD4s9Lxo z&b)HaFrD`?l_erU3hmsc@8(roV(SA+G70oT{JLGDp~plMa#UvhHy_8>9VD7~V@^w# zhlR$k>mZ^yJ9Ux-r*yb^SAxbCta=_ZHrFIvptz88KE#rZXUwgh$T44fidJz(%flG1 zkR8uw9EX*27?-UhJF0b`i6)%6!)UR)R{NLv^kTV!Z{+y9Y!<>@+1IVIO%zFot=3C7 zDXdx#%Pp@emaYuZjjQe1V04wjK78f2$%8*y}IW1F>tZ0-==w2N$9ttLTDP)jChI-W7L_BNC` z=BONVRPKJ+iNB_TP6gix!VjCFhiJmsO&<>Y(#FnN|IKP}G0ESI|DE$U&ESJUe(j7a zEi=056FyUfcd{(_3kUGbeZdG8N&GD8(tdXc4m93e!l#E?c8}<(3thrK9%7aXn`PM@ zaS_FGmD$gr@=qMCY4-d@c0Hd@te2KAe!{(=J=7Qg73?&5ozI4* zJ3Vudgs%Em+ZjGI;MUVXD$}5~rzjNgARrp_kHq@zX$-TX#jm-=P7k_R&5~tNbnB20 zxp1!b7i`UwSMX<6n~|vo3LUVy2lGqd`1&FE6kgkGAOxV+pjPSM|Dao zhlLQ`bd0qtIXJqp+Q=exP}j7$Vv3C}Z$=5_zh6kB_=?GR+VfQ7FXzKGM-I+U7m z_N6PQ^_r#px^dR4Ckl{rACm_Ty~wDZ2ppK;UGH1y9Xe zz=2QTJ7WC4u;gNJ+XyTUd3O+QIuWM4UK%j2s3!(9gp5n-?Gb1kaoBb8i#hNMQ^Ehh z&$pmK1QtF$2YAFPR(Y|nu^4C-l;|{vCKk}aCeXxP3E;2naXwgnx?apz^9a%-PZ^=B z>;(W4;|V(OM)D5TvZuK{pv^q2z_NU-&Ds?tGPOV&sz@(X4-2TFfr(2iE%_bsMgXB@ zvRWW3^qI;{NRjgt3pFCpJ4B=`>{kP<%nUfXFP&!N7&;zeW;M{AU-CA6btaD0%XqxD zl!rr^yHB5Ipmf%r7086Nnmhww?ho^iq{Vh>d3Ww!4ra6YD!Z{)@0z>o|G0$vcTX(^ zPa5_iI1<<=psr3)!HnsS9cbL+1gEDk0duw#c?tE7P#!Z>7Fe)DngkI{okpY@-jE}^ z7llk);RDy?^ni6D`>BkhY@6A#n%mJ}vdqC~C8z+uwkDt*NW~sFvIdl|@<}uSfE0{P z9Ue(v+_=?a58L)QV?{tX>F!5^VzKWUV=3iGgB981-)0^xhN1jyA&+#pP!xFgB7*l0^LFqxtod*K;y08rw1 z+WQh`7cO?=@^E#M4Sr8bfgR1uq%05MFJ{lqVh8E-mi3i7Eom@t*S z9%UCdBh2WT8tS)euI0ES671>l<||YdS~Z&^MkDdWe1bV91zcZXw$EL&LQ_| z1}|ox@UtKDMTQac%?uoxe3;!{jW4gV;dq!~tb&zqGxT=Gvk$Z*fpJK7Imc~^RX+Jd zEdB^v6^q;PGC!A`Fx&^41r`x2g-%NOnfaB59a(H7D$7^0b+Ugno7N^H8MF^kO>+(VJ%*|ktt zItY5o1kp)e;p{-VdQO0HBs-(EAnH!6MagdIwiz6pukUGs2$te{o1{_${9C!1&{qzcN@l zJ;Ejd*xMDPdT~r#8`+N{77Po4Jof^;s%){{VXle^(f1?V+5&FHX%$11kJaiE=c|P; zX_41ct4;HnV~wx3YmD7r>Qq+qH%kBQTgg=pn0byjGNR7?-UhyI|1~Ucu^b z9~{mX|Aeo$BUClOgMSJn#$ji~lGH|2I9LcPQ1=E<7LRi0cm$L2kO-r5 z4$#W^qv#rZ!5u;sSL6pL@}}G^ zUaWNybOX%8qy_&zot?F`UUY&MPJZ5cCR0+2A?&TO=l)r!=eQ{H)p-0$%MN4A^1JaJh2|9_rf6mnr zz##I5WD=BwSL8iD!5C;gSY*9NC+{ggWC#f$eez0OsFMNj90Yp}xDeQnkz{s)M_f^{ zI(9ChSRFYRRot_<*=MnJ)C^wEcs9!yc1w@ln|{HF(U8N$`73Vz;p$KwK!0`4jhmp1 z7nTMT-(1ZX#%pRq7LE^5pZdB!Eox0@Ur)xX*R#>Q31v8nWGGARrgUFjHYNJZ5;aw| zgV!BY5$NAR0~JAEwhL3VonBT~&E(Oc2w<-;Wg9>p=+MDG+hmQ&uBVR7cw1jjtOCAN z-8$Gw3+7~Y6|iRC6)|StRj@_bNX^*_r>=;LUlcIJFDkfshBtsQH=Th@!3>a9_~0QX zuVV)QFu?~U<|9hr!p-(CiXE?f@tJ+o=gOn?u~zgFalV_hA=j+68u1Ws37mqM519k+ z%@GA=$aOZDm0Q-4%T6iUmX2g&|7b25TeDCu_GNRa*qS60`$x4zY)NhV z>qvvG6pDfkT4OnI14TmMH;pA=I0BV0CKg!|N2p+ia0M~W)az~Kb9z&2AGS;a^I}*M z$h*@G6LTzLvq4YKqFZ<%mDH2GQZjKKj|S_){3}Gd66fu&z$WJlvkPLgAkBgP>qR~q zZ|s)K$;KMvlARD-k;?c{#-j#POXpzMGN%$*5lfij(KJSR?RS*u1ap%jqzADo=qLKU?Q4HFo@gD7%mIM zU;_pYsgDMiIeCR8TbKN~5_K3U)zZKe8wk!adNEX0(be>2oH?k$$SZ%!e_E>g?$r{qfckOqqd;LlElEj<=R92h-eK?6@9GZr~eNSA%siRJu3Btsl;E@9-mVt2m#n@g-#$wK&GHsu@a$D`+kkw>SS z#YjZ$ux;S7z2NQ=9*g7UCE}ApjHge-vV5E~OL3-4L(n%hxcFT3c}p1x1fufpw|191 zS07ExQzQMNP++m=9tlpj(VgfZOoxBf8?goVm#C>>_hWR%lih!#IaQkqY`NhawEK`A z_GR{$%p5JQ8vxOcU%5BAQQkg(~BD-2qa?vPdo+z9hqj`bgven0dD%qFwTVKyiVH>-H*E7{-x z3y~%=mE|Ep3N4(s9u#Z~LYYcpYjtBnB{{8n<-NO?t(*PWwNYG%dLB1yT5QhR>61cM%MrYC46Z!|%@ zi`)`C#)a$fs%?Pg7A(znw{Q{{Ghczl|rbJE0KezYpNj#$WJ$Z1N&D6cZ?4stkRA z=^vXIQ9AO~6D#Fb{W(gZ`jW6f|JmNu@Ws5^G6$HBXf~`kGfl;9^XyvL58sDy1E4 zfVYWtz~wgp-B?FpuAiVb+~spt#sYa@iBN{MS$^*kGz1jYF%nR~0_KeV-JLsV-s21Y z29A&q%Z7oN(C~H12+bLf6?)>Bfe8lxib0!FU0_(mt^oich^&)Pft1oT{|uI1(z_EB z0nL&6fEUQ`7XGl@K-WCW0UFKf3B@9c_}gsv0-47<8hc4}2UfmqnY zVMHU?$N?pC5^sc;|zJbekW(tv8<-A{hRd~Ck*~~vB(D>`FEHq z_#ZZI&hY|Wz;@UDpRgOiVh>(@_2={K>!+qV@Pb9X+vR}68GcUl6@JL42d^zDb{RZc zRs2!!N0a$r^_OR+`=wQw40i$(ja5OSsbWxg8=yvDwc_z)u~TL9IW%Lom=qbWxG5Tl z7LBo%D9*4eAWBb1;Tb$?`AxLgI4EccKBKmR@4MxT*F*D>cK76^0fQ6_1bShMn?%9o zcs`?YH?(l5D(Y7QA^}K;#jz%1R7)!J_Fc@P1+h%c5kXqZJHkutaV1wXa9mU;F^mr;S6Hem;WqE7+#5pE?8yFjrJBC^v#{iH*_5E(Ws?Ih@F{ z>V{5?-$=ooyuZ#auky=}@NGdr3ciraZ^!STX_$)lj6TWMp5O%sb3t#xblCd+yh=m# zinPHmL|R)_kzVE9)N8b;06zMaEF6D0-su`BL{i3-S%{s&n%*Q=z z06{4w!4*FMp|<X4bt(=ClK*e#4d82?MC7 zD%&(5P1pctsuawn3gC=7WONKVV?5Xtx+n9%iLC;cq>C;rjkTd+n04x1hf$*;z-Y>0 zPH}HqXfAt8dYvL|I%Ucl>30DGibJ$V_@D43Fbm*My8`|$o#&GP&n)!kuOuX5TwO4vimTa%REU^o{n{X??`uUyat`1LOGluilq$@yp?9&kR@8vGenoJ!#;a z8o-`o3YpPrhyhA6x~QOsIljXNpt|=EKWNV2xGdYH@VJzyy-}?at#*z;Dqdtx9Fx90 zSch^b;e*z+wTFsk;6Z?;Xv3Uvuv0agV|O1=fGr4U#dwLbif&# z1U3qPfXAk1P`42{9#(A^vrqjaax5t_N*#lVV^%f(lpSc#PCIRjgHqlY^8RL9H0@^N)?f zG26*xnO)qBvRnANT&9lJ9uFdC?G7S)W(ib^&UU|q#2CVR;ev+Q3hkO1noS>aG*B;K zBkj#v{P-9niDSpnf^BfA{p4K=b_QgdimhCdtQMln=i+qM?g-PERTMB zw4~Y(@TU2@H)ovyTCn@KM`tL>^R(ma*x(oqMJV>$+AHPf^lIOg12(OC=D%ZHtvRwg-j#p=rmQ*a$&btE~Q zDM(o#&xDCp(IKr9QJ3hY9~Y(uMYq+cbGoA4ix9cSOgOaPExz1Q<&~A9fNdPH{Q$*4o|+tcpE zj~Bn?m#fz=ErL6yx2>>SMb6=>KB^&JB;XnvS1qhs563O9s)-e%xpCD!O!m}FwmvBw zWyl#Nz~!_O$94IbaAXwnF}d#jrek_i2!XbP%g6M36QDiW<9x9EbiJ6b=6wT6i3>`e zECo3)03jIj&JqVXTzLA$Ib)NBBsRa-(grfCU++hzS+Rk3(ZQB zo6LaXqDmP6HFKM|+FqtMdBY}VdPh-XF*Bk?$Jnt&?8y2b$3~vLLVc!#m6Tf(7&Ch5 z(qHN(`FI4nOzbg}a%XuxthJSiJxaMHR-s>NW%h7w2l`4A4N`l!jX1Qmk>Oh5U3Z8N z+l7X%R+FeOs3iuh?C>9pz|`8?Sn!zOb4>7QnF3Q9i9PHLA2Y8HGR4R8{y;#F;}-{Z z{>1@{{9DbEW$^*QFAb0v+|uYAcR?Z^>S8uhbea#3$1%@GHgN$Ov8Qoyd!OawoLt&- z0W?%j<+@jH4@-3VKQPgU1r~esk>K>sRCl6-eXhz39BY##o!F)NsOgb}>v%rbrc{vZ zqbSwL_E9W51=P7QT)@3ca_@>YkXC8JPe|Hy#}P5;V|1~f>XcTFxLdJyCA+5^Yt}(s zQz!i}r!gC*tGZf8P^;wG>hW6ya`3f_BdT^fi>tR&2=|!z zLpubs{+o~E>$}{Fhm$MDZYA@FN1Yr>LTT->R6hW44rfKCjd59n9Gj`QYXzJj%3I{R zdF+%GA~&UiCvPPSI9qGLlJ2piof-SNY@ckrfFyW~3)kT_Sc-((t>^#zOt)^ijGrGz zqh-FLyD$Fo%)+^IdI&)7$@lr}1Du+}BgF1C?CZkAMmR5#b&zX1^Cu{rMs6 zQVK8dH$6RAz{>Ey#k?F$*)e0}_JpTXbMOpL>i^{#-p6kX!3cp-pju{f#+Ue;TK>3p zbeq1Bh)g-FB?p)gZ{sF(W{xAI7Tv)mu!#gNOJL1T07sXw&(kr_VDu z1@B`{u8eto4fe@a10YRf#TVVY~r7k?8W5w*6^=@`DjY6br8s)p3 z{_@Pkc_J|H0E=UVJ5Y}mE8$93OrrrSA}eI&?s+|?54+Cf@!8mi&~i>5OpV|Yb9c;S z^(`#=gK)hI++uRQ$VcOix%?ld-Rb$iPAB97CECZC@3qY%&(_;Z7}{n`X9hxy@jZuf zA$ie+WByHx{2SKcIC5fxiAMg!T!O7v8#uot_D;eGzO9Irwnc+twWL8Xf7?Bm04oA% zkN#SkN{oTq%i(H=rMU;&{$(;)2K*A^6>0-ATprtBbe_xtV;?ScOV2On^NFOx*x+X| zxNQ{L6mecR(n;4%2R=3GiX8~!phVq03X2N4+)|WOaJMvj*+#d(Q2X&xQ3Z0aNz|rjR&jT>9d}tn;@tyc9@aYv!I2nS8?P05RMCca0SM>_ zZjZQ6v7rj#HRqc?t4~J(T(P9ZbR2X%SJbx#;hoV0Txx^(ZoBsw8#-Q8WmVJdbK@sG za1jJca)N3nd)wxDce}GH!X&lsTp&cn69>;Q76$zuNr9erECas91Eynv1ZcWiuG$Cu z(0I`CTNmns+vNh!;6jWdU8jRBMm_BQtW~4rUaYCpm>k65mYlg;!jdzwxOr=~TV-## zlzAFeWStctg%VJSHXJhz;Fo?ej5598(u)L}x4Bv%qy?r{5hz~(ps0@wpW8#@WguXjkp4GWB15`@s~pql`t z+LO4gAb_X^89C>Wba#Pr@#u?Ja?ij<1vjFNN1USt&SB*9lxZq?BVT2v5hb42Mjrh^7usK7xfnqEwVCYf%gYsf{R zEwr0&fsw~W%5Pud&swLDg6pNEeuG0uC3llq`relQeFx)S!m0Tn?;4Iec}TYnN6bGI#PN6- zY3GNLBHfbJ@gaed4e&_x%g|ly6pTb79s*@@JJIhBM#QCuYB&|7|0 zlqVYZ7(8_wn8wkr!oM319Ymuso$G2O+_joD^ zJuCnyJ35sVjC*`6si*)g*A>98SqcLzc3S6LQm`1I06hFz78SQX)#1pM*5EFq(R!-J zU@^hrLN#7P$~lb7*5QOVMYl`kapKp%109DrGVhFuvVXQ=z1~FrVe~(ci}TWQa>^ zNf)HzXZh_pe~C`kJ?xZ9Om)qw2^}jbjuR}In9ZsZs2gK;HvftI#21+(ZY9k~C{N(d z#mr=y%9v|?<{vEGSKra1UM^ZL+#QOXk}Gfp{|vZVijyjzj1W4RF96R~I`m0=PFiZt z2jx^kx*Vzt;B%FHNZO^T19QCuUk$rUvmUz2AB?sA**H(unhav)tgbt2q`rZ#!lR$t zN&?K92PP}-jRTDwD|fqA$8A;UT5i9|akdtIN{SM>aSG5P_^!)lgU`rRn7h8%S-__!<}|&E z6i@8j2L~e9Ly+lPk0F`7guGWV<(6|{4EyRglHU4I_9AAUXLvo%d4AVpn-^P;XS4qD zGZ&_)nLtgWq?wZD7EH%>w;C$_d;q`9m&wSZsoHM&nilmz{Qgv6pnFq!*LjKv`OD(W9A~o;@;ae@~wuJpHwP$p*I(#$C z6%LdVFKrjv?UrJB*thtz*2xDpOKRKCw$R|{1Gf=x<5>>YYLCC=FU{6R&wO>3?^;nSsoF2_GUd{(dAF{3NiJS{`c0h;zs|2`u|pz@ zh~D%$2-aEmIueq5)v>4!HVIqOG6=xoU%eeZ+802j$6bNKDPlJX z^a5aaL*VQ?&gur#V8@53mF-`doe(SoTAAFfBi5ZNVh8*y;N81qA6&7fJ#jVlX@O|^ zAa%Xe)#{j5mAGrMt|hyu8*AE0T{rG#%!nC5UCnfO`#Um{ghr6@S=M8Wh7JbJ7sSae z?oj-8yBGsP)c+^_z^~K7c<@Og!L+_mxBcDrzr7iapu)E|()A=V}J_Yk>`IBk7e z!#`?KbnbyZXku>Vg3x9(Uu0wSu1NLl>5e5jqQSY1g2sNGU82I}!yeqn{Ds+CUA`T^ zgNDI9^O+$BjLv<~&AO=IP|Pp$YIZZFBF``ve)aX!-lmVbd=xPldM=M28N5rBQ$ zI2{p>L_p;54oJjZ3P8H-aXwgnx?apz^S(iHOs8}9z5!ae~1bnB3h9EAOA07y1 z#j`!04^JO<0-3va6 zrlLS(1~xD(wZB{%oA*S84?s{j`p`Iy-ZT1=6s~s#jIimkdexp0Y~Eu89{?kf|JWnN z1Wv#-!oM^U8BSn=_006Jz?YpHNsvpXa|@CHOInhEOj3u;-v-Vye?e~xG0DPCuv$VN ztkVvj5iN*n%Sw<`F5F69_E^Lc;5kFeaLtW2Vj7i;SiS&2Bq?uJ`*y-6D#$HTG0YmZ zt}kCyKVUUdza-Z@M;zDQN6E^9HpmOfS43_dlQZm_$$;!D4-CXjmmt z76YdU&<3JN2+Mi&-(h`tn#PWoU z?H2EAN7?BKj%3CiG29jyuCWybFs^n3aI&4)?``WBIK|+Nb2Qax@H_F~VI2-|+XaJm z5iUyWHZ_dbVNb^JK|`~!(?fS_3)>R5CVzm(ua__L$#~lP5+*stt%hrA5cj>Rm^~q4 z;)Ua1=h=um5@mHmW89?m$DxNQ7J!-k#l4+0UQ zDT&*Pd;$^XHEjFk!+#7WH+j62Qz>(dVU3XniqtO8Jviox)U05sFOZ=Y}G>TSTK1nL0$$S8xKsI8jtjc7$ zQ#i*|1?n#&d3yR_S>WB9?(hsA8U4paftJzbFZ1i~^L5Vn6BPIkwo7lO06ang!d`Gp zt9ucLxC9RSo=J>2d}m z>+S<8q)Js~39bR#8>;(_*dNo)kLl*yOE=dO=Rs$jdmTN*q;szW4{4X^c>n(1+`sSX zn5>)+ZOez?XmkdR(>}WF)162^+)OF_A#e060>?3>6urq#w|bC>2a)3gaBuXXXEib| z?FT}KV-7l;md2<_u1j@^MHC@u8M#+3@)qUZ=Dyg0q@b6?0+HNwB+;GZU`E2f+WS6* zN$BA;Nuv5Zxtq}}NJS568ff24;;NmAL_&HP?WJ~toN70fBJ{{r*16gNdDAUd7A#b) z&S~wjdvh{d>E-xxuo};2ybLCXOt;mdqq=(3)tD92WnIg3x|7WsNdw=feHvj(AWFc| zv&VjNJP8Uct(UfA@OE?6{psvxGNDz@;zTg!)?{)Pu#!V=3hxR&2s}t6jj?x?YxgiIY{%VZl07Lw3O;CA@+`=o0i+ClM6%{R^Vw z_+PZ2VWDc;fdP;jb?JNFstQxj4I+MJO57o*Truf@b+7@*hN}gxZ~@51!%e;cgckRifl2@%e|gfXQ2~D{(cn(} zSrQ%uXdgnnDY?z|**RtLqF_Mr;a?rdM2!p~4k+_3(;z*1jq)I)D~Yk&-c@_l0V@nj zJ2kFD3LvrN+er+1U>l%(SuY3GzUc@X@I<*^nVdzeiC@1%oB+Mc8aM$)%4}u8c8BSL zX(Zyxc%=y{I6=Kwyd;NH)CVcn&*H?U{X|OJ5Fdy`%iz<`cT5hSFzx&ChBPyrX z3dUfO%F9&QsOqW9x~rRx3N@6=b<#HJ)LKbctpH+ak&+;-lenX~@^iG#MMhnqQQd+?xe$Ybu{ zp5+c&Et3V*;;0V>-E07CqDO~5d;o0T|Mj)#^ZF1PvZYhwkX5%gD}%Ppq&NmtoiEzC zWE?3ET6K>h1gN~mObf}?>{wI>l0V3kJ&p_z`SP?&Z%%h7Itb3-Uwt$@kwM5k;{#eL zRGDXZL#m}YgoYsWF1eQh3{84lVy$wL zDz+vzeXYUe1n+gXK&9~Q!A61N=D0^-zNj7mqFYQTWV1zUF8U8A#TkXF6uB7{348>q zMpr0I>!cJiCA}glrfg1OSf~z9u1Rn}B~gzNbv=P&R9#MSGue2N@dW4d7#FU?tF{rE zTd+ji1;>B7S-pWv5hi)by|+JJ{FYzR6}13iKem4v5PVKA@p{_t=GWtV2`9NO0J(kp z?uIsYEmD1{UN%Z6EM(3>#y-p~p)YWNFn2}eG*(@wvL{{_$#FdxLiW5Vo=BCAI>E7=q9zWL`nw> z=auwlyD5csY%!bAUMFjxRb1|BuZjf#fG>>n#=Rgt@mI1nOT3$S0~dxkI|NG7(S5BY zG8BU#IL;xa78Z7{0s6+X8dtH!MNK0gSv;Kn)jZP6tp8 zLkF(-mH_KsU!vj}0>vndQ z!dRjvvZCHIDpAFb=-8xFp!qAhg%hE~d$b znMkUHIrY@#oi#|9Gn0$iZksWuCnj|3p0nn{DNvd*7Z&uc*MqpYR>E9xj#R>FQ&|B= zrTKCt2R|4dSVj86uA;U_ZVoTz|=5OC{iYmh?5E8n0;O9L8nqaHp$Z=&)K1;kN$Uj^k9gq3%{`?^ffd*s_I5#6(g@1Bmx7oOXQ{l;x>!!wQ6&Y7#&&@T%r z%7m$O$xOw4_QsBT@yEURt?tE}N&3(?<83z&bT{6z{}8t0ZC@J3G?+H)eL#gHOWL5o zSNwSd?;r~=mW<7ff%>cR9_&MuzKnBh7J7UV+R(4g;Is*y|^>SPRaxP@QR60eT|W zn@7{2Y*(K9#M#WL!$LS=>g{IR1xj5+6LHgEW8OA*k5|w{>?Zc+nLW3}HQAh3UDFz) zcjviCta8cx1Kn8TG1HZG5<(d#_q0K8Wwm!G-aP|&>BCnSFiR7MuG|?fTK|kJ1qlOi zkR7lzk*VZ(B}k!7)GlG$<78`Pjw{J&-7P10e;BCp2zL#CDpq8?kH@-N9P7dZT?>wUxp`Q?kKKZ2N^X5B+yxH{G2Ky;C)cFj{QghB zXJ)Xvgu5^)1A#{O{ZIHrA=+=|H;c>s=fUhlo;~It26tY%H+0v`)y?dqfu_wDXiULN zeADcPnPRpa(p$0dUsb&VVXjqO+~f#nPFCM1w7G=Q)|>zK@|SD6F{bo_8KqJ%as5j4 zO@lY%f9K}n5L6u~)NNWpnH&xmek<$Iwm~>Gls<;0UQ|F{@y#+c<^@;EsL$1XXY``0 zn`Fx5CzDEV$mbu_E9jbk45F+>z+6Zcz`k)oQtX?70wEUPl1#2p>>Lre!erKljKLJ_IBeaEbFWK@4XshVuSr>PTnc6=-31 zaemo=$#Qnz(S9XEqC>}+zeUWiw7($KCM$~z)QP=R)-9YBx4Eck5=YTA0b+XUGiOLI z_;4BAbcFLpw}z|QRzEcs8FCfhelr{{^5xRzRKZWm%kRg}ZLZXSYhcX#Lw@_sYPA?& z+^ir=1OI#bj?Z1cm*@0Y?puK)rt)TqO~AdHlfh-~9%dKw`NUN6f0%H35!S$FIBeJD zA4k15vAt>L8t35MqVm@9xU1MO5)Ueh{i=+?O~rkVzB|wLGAa#=4SpYdtiKQLD>ANg zepp@*%l|sNyvi>>=0l9szu5G>CiuoOn8a8EIZb(oJpUkly?Cfl1rflUxH_sutQ zjN_LtdYC3M1lljMsilFZ9-Ktr5B&C^+g}Y=-0feGVJ)VY`(hpj9h&yPxxUV4L({LG z#Q4*3pU{y>COe?QS-#(y#XsW zAaelMUV1Oiv(TCP{5y$nG(youiw@sR?KN@sr?1}m0w1YuBAFW7M1lCij>ys!NSn-! z)raR6OqJ32-!nyP@g#0=&f^KVyHp zn=WAH;a^Qih=4OQ*=-(-ozcmh7covvXaQnoX_=cSEG>gTIkS@n%!qAoq7Y;jPPb$a zyz0$l2L14A1NIjOPNqvRI!94e3Jr`Z=`M{1lVuJLRmz`&PDO1%$B?k; zO7yy3cW7Rqa+OSwBJTeLWZ=&-zIqKEbFn0 zeU5AAd_g?i;zID-?P9#j7yWf8ReHzV-D;m3F~ zG`ReEcH4i2?N&%9Y)E_waj>PgvnT1srOYuxylB}Oyn?pL`OQxc=M9vX_o1T@BsEpb2ijdRMx?v7_P zals-x-z3Nj^K47ZLFkkaDRnD&;rr(IgNM!FGD6)=bgJzg;-3A2^)r2mIOnKEMk$sQ zx*9S>h_fS{VZ~qMd;|kQb|`MP%n1-uFn~$ty<$_rdJ)16O1`rV0EPWyQn5hhaWCZ+ z|6*`+%BKXxUF8#+Jp;KF&U@umo=Pe*g7!N7m$x0H33}yUaA)Z21mo85y~EM#XVSSk z^+Effj;tFgyner-`p!{$R7#k$)j&9XS<9(ftvZBlYPEw}F^2A+n$1Sz$z+*b+>El@ z@d|Q7#~)_-kT8U7j(8|~{;x+^0C8;qVLm{q@e+Q6eYMrqUQxKR0poG$yGkHJi(oQH4}&^0G8^1DK(*+d_1~-p7n7W2hyXuG%C9YbBL#x-!Tu~b!`B-+ z*jT^#1lyKd>KwHF@4R0eAfLf#4u+1;9_kXua)m)%LBEaLD}WuefI396ED9lbpN(V@hdC>3y-7V#**tQctY3cNKdhkib4v5|6fk;muweh!7 zoJFf>&D+?~HqCEOzo}@k)6>`9aL7U^3VrCCGlc4*vj4YnJ{iKtXVH|M z?A4iTH5Tqn3uvY6$&fO~gS5?Uf~SPLJ8egA8rwh5<{uH%0s(Fpe0QWg1l~P{KmW1 zT`lZF*&IQ_-qM!Xub}Se)hX%_z4U`XXdhQky~K&Pq}yuJHC-?2T+D+REnTaVEr9(( z|AiYtwg7P5Rd(|Q%#;LP>`;H4QYGLxSO;2{=QGG7x?bd?@dlw0jG$g*r|17VoeEZw zAcgiuD|}mG>q9y=t*oR1pm&IcD=tJmkBQSQ5~p!u)d4_pl|8Z9)A4%7ubo?@289-A zm@;Ou6U>uAUN`3oxF}h4JYGu5FjbZLQoxa0;lKa{eCg>~#aX;!lyexDt-~qR`ow^} z<`u(_E^uRY`dy*N{AJVELz6IW{(NcE#OL$@M`JI5pY>` zED0*af`mXD=994>A~X(4WIxF4v5kNh z_o_Rnh4x|&Bsy2b|VhY^`vz)J#87UD8@%VM5n*tX9c!(T&wb52<^)V%)))i+e~xu`=2# zIPsW-Vh@)>Dn2+uJNPn56{qivj~XO=C;;&}62VlllM_63Ida*LOv$ZH9yc}7B3wM9^=Awc%@q1CZqg+6(=Bp literal 0 HcmV?d00001 diff --git a/apiv2/object/grpc/service_frostfs_fuzz.go b/apiv2/object/grpc/service_frostfs_fuzz.go new file mode 100644 index 0000000..f58ee01 --- /dev/null +++ b/apiv2/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/apiv2/object/grpc/service_frostfs_test.go b/apiv2/object/grpc/service_frostfs_test.go new file mode 100644 index 0000000..cb4baeb --- /dev/null +++ b/apiv2/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/apiv2/object/grpc/service_grpc.pb.go b/apiv2/object/grpc/service_grpc.pb.go new file mode 100644 index 0000000000000000000000000000000000000000..687df9973e3b6536a5bc1ef015bd8557c943f6f4 GIT binary patch literal 46612 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 literal 0 HcmV?d00001 diff --git a/apiv2/object/grpc/types_frostfs.pb.go b/apiv2/object/grpc/types_frostfs.pb.go new file mode 100644 index 0000000000000000000000000000000000000000..5d60ff7d125d5d4c73d94dda3bd7872790d1e55b GIT binary patch literal 59850 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 literal 0 HcmV?d00001 diff --git a/apiv2/object/grpc/types_frostfs_fuzz.go b/apiv2/object/grpc/types_frostfs_fuzz.go new file mode 100644 index 0000000..8491638 --- /dev/null +++ b/apiv2/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/apiv2/object/grpc/types_frostfs_test.go b/apiv2/object/grpc/types_frostfs_test.go new file mode 100644 index 0000000..11825be --- /dev/null +++ b/apiv2/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/apiv2/object/json.go b/apiv2/object/json.go new file mode 100644 index 0000000..dbd3af0 --- /dev/null +++ b/apiv2/object/json.go @@ -0,0 +1,94 @@ +package object + +import ( + object "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/object/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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/apiv2/object/lock.go b/apiv2/object/lock.go new file mode 100644 index 0000000..7e1667a --- /dev/null +++ b/apiv2/object/lock.go @@ -0,0 +1,160 @@ +package object + +import ( + "errors" + "fmt" + + lock "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/lock/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/refs" + refsGRPC "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/refs/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/rpc/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/rpc/message" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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/apiv2/object/lock_test.go b/apiv2/object/lock_test.go new file mode 100644 index 0000000..30a9c72 --- /dev/null +++ b/apiv2/object/lock_test.go @@ -0,0 +1,26 @@ +package object_test + +import ( + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/object" + objecttest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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/apiv2/object/marshal.go b/apiv2/object/marshal.go new file mode 100644 index 0000000..89ac640 --- /dev/null +++ b/apiv2/object/marshal.go @@ -0,0 +1,1428 @@ +package object + +import ( + object "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/object/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/refs" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/rpc/message" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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/apiv2/object/message_test.go b/apiv2/object/message_test.go new file mode 100644 index 0000000..24f40d8 --- /dev/null +++ b/apiv2/object/message_test.go @@ -0,0 +1,65 @@ +package object_test + +import ( + "testing" + + objecttest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/object/test" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/rpc/message" + messagetest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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/apiv2/object/status.go b/apiv2/object/status.go new file mode 100644 index 0000000..6bebace --- /dev/null +++ b/apiv2/object/status.go @@ -0,0 +1,91 @@ +package object + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/status" + statusgrpc "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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/apiv2/object/status_test.go b/apiv2/object/status_test.go new file mode 100644 index 0000000..689891e --- /dev/null +++ b/apiv2/object/status_test.go @@ -0,0 +1,35 @@ +package object_test + +import ( + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/object" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/status" + statustest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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/apiv2/object/string.go b/apiv2/object/string.go new file mode 100644 index 0000000..875cf9c --- /dev/null +++ b/apiv2/object/string.go @@ -0,0 +1,55 @@ +package object + +import ( + object "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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/apiv2/object/test/generate.go b/apiv2/object/test/generate.go new file mode 100644 index 0000000..db59c6a --- /dev/null +++ b/apiv2/object/test/generate.go @@ -0,0 +1,766 @@ +package objecttest + +import ( + crand "crypto/rand" + "math/rand" + "time" + + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/object" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/refs" + refstest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/refs/test" + sessiontest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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/apiv2/object/types.go b/apiv2/object/types.go new file mode 100644 index 0000000..4a0220b --- /dev/null +++ b/apiv2/object/types.go @@ -0,0 +1,1650 @@ +package object + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/refs" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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/apiv2/refs/bench_test.go b/apiv2/refs/bench_test.go new file mode 100644 index 0000000..40784c6 --- /dev/null +++ b/apiv2/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/apiv2/refs/convert.go b/apiv2/refs/convert.go new file mode 100644 index 0000000..0ae66a8 --- /dev/null +++ b/apiv2/refs/convert.go @@ -0,0 +1,264 @@ +package refs + +import ( + refs "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/refs/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/rpc/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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/apiv2/refs/grpc/types_frostfs.pb.go b/apiv2/refs/grpc/types_frostfs.pb.go new file mode 100644 index 0000000000000000000000000000000000000000..94349af29ad8d771e1a8c4811e448d2ac0b60665 GIT binary patch literal 28648 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 aq4H)aqH1NQ^tydq8F~#S3dnQXg8M&y6X4na literal 0 HcmV?d00001 diff --git a/apiv2/refs/grpc/types_frostfs_fuzz.go b/apiv2/refs/grpc/types_frostfs_fuzz.go new file mode 100644 index 0000000..a64a9bf --- /dev/null +++ b/apiv2/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/apiv2/refs/grpc/types_frostfs_test.go b/apiv2/refs/grpc/types_frostfs_test.go new file mode 100644 index 0000000..9b19892 --- /dev/null +++ b/apiv2/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/apiv2/refs/json.go b/apiv2/refs/json.go new file mode 100644 index 0000000..15c1f63 --- /dev/null +++ b/apiv2/refs/json.go @@ -0,0 +1,62 @@ +package refs + +import ( + refs "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/refs/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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/apiv2/refs/marshal.go b/apiv2/refs/marshal.go new file mode 100644 index 0000000..70af7fd --- /dev/null +++ b/apiv2/refs/marshal.go @@ -0,0 +1,264 @@ +package refs + +import ( + "encoding/binary" + + refs "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/refs/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/rpc/message" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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/apiv2/refs/message_test.go b/apiv2/refs/message_test.go new file mode 100644 index 0000000..4d70cd8 --- /dev/null +++ b/apiv2/refs/message_test.go @@ -0,0 +1,21 @@ +package refs_test + +import ( + "testing" + + refstest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/refs/test" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/rpc/message" + messagetest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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/apiv2/refs/string.go b/apiv2/refs/string.go new file mode 100644 index 0000000..1675f3b --- /dev/null +++ b/apiv2/refs/string.go @@ -0,0 +1,47 @@ +package refs + +import ( + refs "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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/apiv2/refs/test/generate.go b/apiv2/refs/test/generate.go new file mode 100644 index 0000000..5e22e73 --- /dev/null +++ b/apiv2/refs/test/generate.go @@ -0,0 +1,127 @@ +package refstest + +import ( + crand "crypto/rand" + "crypto/sha256" + + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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/apiv2/refs/types.go b/apiv2/refs/types.go new file mode 100644 index 0000000..d8f0d9b --- /dev/null +++ b/apiv2/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/apiv2/rpc/accounting.go b/apiv2/rpc/accounting.go new file mode 100644 index 0000000..7c7145c --- /dev/null +++ b/apiv2/rpc/accounting.go @@ -0,0 +1,29 @@ +package rpc + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/accounting" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/rpc/client" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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/apiv2/rpc/apemanager.go b/apiv2/rpc/apemanager.go new file mode 100644 index 0000000..8732cac --- /dev/null +++ b/apiv2/rpc/apemanager.go @@ -0,0 +1,60 @@ +package rpc + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/apemanager" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/rpc/client" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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/apiv2/rpc/client/call_options.go b/apiv2/rpc/client/call_options.go new file mode 100644 index 0000000..4fe8791 --- /dev/null +++ b/apiv2/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/apiv2/rpc/client/client.go b/apiv2/rpc/client/client.go new file mode 100644 index 0000000..7ec56a1 --- /dev/null +++ b/apiv2/rpc/client/client.go @@ -0,0 +1,30 @@ +package client + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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/apiv2/rpc/client/conn.go b/apiv2/rpc/client/conn.go new file mode 100644 index 0000000..f208413 --- /dev/null +++ b/apiv2/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/apiv2/rpc/client/connect.go b/apiv2/rpc/client/connect.go new file mode 100644 index 0000000..e22e0a6 --- /dev/null +++ b/apiv2/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/apiv2/rpc/client/flows.go b/apiv2/rpc/client/flows.go new file mode 100644 index 0000000..1648ee0 --- /dev/null +++ b/apiv2/rpc/client/flows.go @@ -0,0 +1,124 @@ +package client + +import ( + "errors" + "io" + "sync" + + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/rpc/common" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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/apiv2/rpc/client/init.go b/apiv2/rpc/client/init.go new file mode 100644 index 0000000..b53b118 --- /dev/null +++ b/apiv2/rpc/client/init.go @@ -0,0 +1,69 @@ +package client + +import ( + "context" + "io" + + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/rpc/common" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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/apiv2/rpc/client/options.go b/apiv2/rpc/client/options.go new file mode 100644 index 0000000..5711cd4 --- /dev/null +++ b/apiv2/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/apiv2/rpc/client/options_test.go b/apiv2/rpc/client/options_test.go new file mode 100644 index 0000000..56704b6 --- /dev/null +++ b/apiv2/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/apiv2/rpc/client/stream_wrapper.go b/apiv2/rpc/client/stream_wrapper.go new file mode 100644 index 0000000..092fbb9 --- /dev/null +++ b/apiv2/rpc/client/stream_wrapper.go @@ -0,0 +1,58 @@ +package client + +import ( + "context" + "time" + + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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/apiv2/rpc/client/util.go b/apiv2/rpc/client/util.go new file mode 100644 index 0000000..eb9e84a --- /dev/null +++ b/apiv2/rpc/client/util.go @@ -0,0 +1,13 @@ +package client + +import ( + "fmt" + + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/rpc/common" +) + +const methodNameFmt = "/%s/%s" + +func toMethodName(p common.CallMethodInfo) string { + return fmt.Sprintf(methodNameFmt, p.Service, p.Name) +} diff --git a/apiv2/rpc/common.go b/apiv2/rpc/common.go new file mode 100644 index 0000000..8177694 --- /dev/null +++ b/apiv2/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/apiv2/rpc/common/call.go b/apiv2/rpc/common/call.go new file mode 100644 index 0000000..bc3410a --- /dev/null +++ b/apiv2/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/apiv2/rpc/common/call_test.go b/apiv2/rpc/common/call_test.go new file mode 100644 index 0000000..49d4da2 --- /dev/null +++ b/apiv2/rpc/common/call_test.go @@ -0,0 +1,49 @@ +package common_test + +import ( + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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/apiv2/rpc/container.go b/apiv2/rpc/container.go new file mode 100644 index 0000000..ef584a2 --- /dev/null +++ b/apiv2/rpc/container.go @@ -0,0 +1,82 @@ +package rpc + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/container" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/rpc/client" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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/apiv2/rpc/grpc/init.go b/apiv2/rpc/grpc/init.go new file mode 100644 index 0000000..0092d39 --- /dev/null +++ b/apiv2/rpc/grpc/init.go @@ -0,0 +1,4 @@ +package grpc + +// Message represents raw gRPC message. +type Message any diff --git a/apiv2/rpc/message/encoding.go b/apiv2/rpc/message/encoding.go new file mode 100644 index 0000000..d656acd --- /dev/null +++ b/apiv2/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/apiv2/rpc/message/message.go b/apiv2/rpc/message/message.go new file mode 100644 index 0000000..6f6af1a --- /dev/null +++ b/apiv2/rpc/message/message.go @@ -0,0 +1,43 @@ +package message + +import ( + "fmt" + + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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/apiv2/rpc/message/test/message.go b/apiv2/rpc/message/test/message.go new file mode 100644 index 0000000..44df8e9 --- /dev/null +++ b/apiv2/rpc/message/test/message.go @@ -0,0 +1,126 @@ +package messagetest + +import ( + "encoding/json" + "errors" + "fmt" + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/rpc/message" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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/apiv2/rpc/netmap.go b/apiv2/rpc/netmap.go new file mode 100644 index 0000000..3b297e7 --- /dev/null +++ b/apiv2/rpc/netmap.go @@ -0,0 +1,62 @@ +package rpc + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/rpc/client" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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/apiv2/rpc/object.go b/apiv2/rpc/object.go new file mode 100644 index 0000000..6217b11 --- /dev/null +++ b/apiv2/rpc/object.go @@ -0,0 +1,243 @@ +package rpc + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/object" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/rpc/client" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/rpc/common" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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/apiv2/rpc/session.go b/apiv2/rpc/session.go new file mode 100644 index 0000000..5458afe --- /dev/null +++ b/apiv2/rpc/session.go @@ -0,0 +1,28 @@ +package rpc + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/rpc/client" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/rpc/common" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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/apiv2/session/convert.go b/apiv2/session/convert.go new file mode 100644 index 0000000..20a60da --- /dev/null +++ b/apiv2/session/convert.go @@ -0,0 +1,898 @@ +package session + +import ( + "fmt" + + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/acl" + aclGRPC "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/acl/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/refs" + refsGRPC "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/refs/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/rpc/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/rpc/message" + session "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/session/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/status" + statusGRPC "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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/apiv2/session/grpc/client.go b/apiv2/session/grpc/client.go new file mode 100644 index 0000000..2dfe77e --- /dev/null +++ b/apiv2/session/grpc/client.go @@ -0,0 +1,62 @@ +package session + +import ( + "context" + "errors" + + "google.golang.org/grpc" +) + +// Client wraps SessionServiceClient +// with pre-defined configurations. +type Client struct { + *cfg + + client SessionServiceClient +} + +// Option represents Client option. +type Option func(*cfg) + +type cfg struct { + callOpts []grpc.CallOption +} + +// ErrNilSessionServiceClient is returned by functions that expect +// a non-nil SessionServiceClient, but received nil. +var ErrNilSessionServiceClient = errors.New("session gRPC client is nil") + +func defaultCfg() *cfg { + return new(cfg) +} + +// NewClient creates, initializes and returns a new Client instance. +// +// Options are applied one by one in order. +func NewClient(c SessionServiceClient, opts ...Option) (*Client, error) { + if c == nil { + return nil, ErrNilSessionServiceClient + } + + cfg := defaultCfg() + for i := range opts { + opts[i](cfg) + } + + return &Client{ + cfg: cfg, + client: c, + }, nil +} + +func (c *Client) Create(ctx context.Context, req *CreateRequest) (*CreateResponse, error) { + return c.client.Create(ctx, req, c.callOpts...) +} + +// WithCallOptions returns Option that configures +// Client to attach call options to each rpc call. +func WithCallOptions(opts []grpc.CallOption) Option { + return func(c *cfg) { + c.callOpts = opts + } +} diff --git a/apiv2/session/grpc/service_frostfs.pb.go b/apiv2/session/grpc/service_frostfs.pb.go new file mode 100644 index 0000000000000000000000000000000000000000..387bc2950f431974716744fc0c88f28bca0ce281 GIT binary patch literal 19139 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 literal 0 HcmV?d00001 diff --git a/apiv2/session/grpc/service_frostfs_fuzz.go b/apiv2/session/grpc/service_frostfs_fuzz.go new file mode 100644 index 0000000..759361c --- /dev/null +++ b/apiv2/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/apiv2/session/grpc/service_frostfs_test.go b/apiv2/session/grpc/service_frostfs_test.go new file mode 100644 index 0000000..fc8664e --- /dev/null +++ b/apiv2/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/apiv2/session/grpc/service_grpc.pb.go b/apiv2/session/grpc/service_grpc.pb.go new file mode 100644 index 0000000000000000000000000000000000000000..adf6fc18dfc356ea7e15e4e99c164d392359cee6 GIT binary patch literal 4108 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 IH64=pe~@mmrT_o{ literal 0 HcmV?d00001 diff --git a/apiv2/session/grpc/types_frostfs_fuzz.go b/apiv2/session/grpc/types_frostfs_fuzz.go new file mode 100644 index 0000000..fae4a05 --- /dev/null +++ b/apiv2/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/apiv2/session/grpc/types_frostfs_test.go b/apiv2/session/grpc/types_frostfs_test.go new file mode 100644 index 0000000..5c9b6c2 --- /dev/null +++ b/apiv2/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/apiv2/session/json.go b/apiv2/session/json.go new file mode 100644 index 0000000..3ef09c5 --- /dev/null +++ b/apiv2/session/json.go @@ -0,0 +1,86 @@ +package session + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/rpc/message" + session "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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/apiv2/session/marshal.go b/apiv2/session/marshal.go new file mode 100644 index 0000000..9bfb8f2 --- /dev/null +++ b/apiv2/session/marshal.go @@ -0,0 +1,536 @@ +package session + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/rpc/message" + session "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/session/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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/apiv2/session/message_test.go b/apiv2/session/message_test.go new file mode 100644 index 0000000..202701d --- /dev/null +++ b/apiv2/session/message_test.go @@ -0,0 +1,27 @@ +package session_test + +import ( + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/rpc/message" + rpctest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/rpc/message/test" + sessiontest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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/apiv2/session/status.go b/apiv2/session/status.go new file mode 100644 index 0000000..0f38c3e --- /dev/null +++ b/apiv2/session/status.go @@ -0,0 +1,32 @@ +package session + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/status" + statusgrpc "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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/apiv2/session/status_test.go b/apiv2/session/status_test.go new file mode 100644 index 0000000..ba739d6 --- /dev/null +++ b/apiv2/session/status_test.go @@ -0,0 +1,15 @@ +package session_test + +import ( + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/session" + statustest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/status/test" +) + +func TestStatusCodes(t *testing.T) { + statustest.TestCodes(t, session.LocalizeFailStatus, session.GlobalizeFail, + session.StatusTokenNotFound, 4096, + session.StatusTokenExpired, 4097, + ) +} diff --git a/apiv2/session/string.go b/apiv2/session/string.go new file mode 100644 index 0000000..c01d9e4 --- /dev/null +++ b/apiv2/session/string.go @@ -0,0 +1,47 @@ +package session + +import ( + session "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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/apiv2/session/test/generate.go b/apiv2/session/test/generate.go new file mode 100644 index 0000000..59d7f3f --- /dev/null +++ b/apiv2/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/apiv2/acl/test" + refstest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/refs/test" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/session" + statustest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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/apiv2/session/types.go b/apiv2/session/types.go new file mode 100644 index 0000000..9a57947 --- /dev/null +++ b/apiv2/session/types.go @@ -0,0 +1,836 @@ +package session + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/acl" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/refs" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/status" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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/apiv2/session/util.go b/apiv2/session/util.go new file mode 100644 index 0000000..0e94066 --- /dev/null +++ b/apiv2/session/util.go @@ -0,0 +1,167 @@ +package session + +import ( + session "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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/apiv2/session/xheaders.go b/apiv2/session/xheaders.go new file mode 100644 index 0000000..c575d5f --- /dev/null +++ b/apiv2/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/apiv2/signature/body.go b/apiv2/signature/body.go new file mode 100644 index 0000000..b6c04c2 --- /dev/null +++ b/apiv2/signature/body.go @@ -0,0 +1,116 @@ +package signature + +import ( + "fmt" + + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/accounting" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/apemanager" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/container" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/object" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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/apiv2/signature/marshaller.go b/apiv2/signature/marshaller.go new file mode 100644 index 0000000..ff9beb3 --- /dev/null +++ b/apiv2/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/apiv2/signature/sign.go b/apiv2/signature/sign.go new file mode 100644 index 0000000..1dca5a2 --- /dev/null +++ b/apiv2/signature/sign.go @@ -0,0 +1,122 @@ +package signature + +import ( + "crypto/ecdsa" + "fmt" + + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/refs" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/session" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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/apiv2/signature/sign_test.go b/apiv2/signature/sign_test.go new file mode 100644 index 0000000..1e5b57b --- /dev/null +++ b/apiv2/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/apiv2/accounting" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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/apiv2/signature/verify.go b/apiv2/signature/verify.go new file mode 100644 index 0000000..941974b --- /dev/null +++ b/apiv2/signature/verify.go @@ -0,0 +1,127 @@ +package signature + +import ( + "errors" + "fmt" + + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/refs" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/session" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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/apiv2/status/convert.go b/apiv2/status/convert.go new file mode 100644 index 0000000..903a409 --- /dev/null +++ b/apiv2/status/convert.go @@ -0,0 +1,95 @@ +package status + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/rpc/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/rpc/message" + status "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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/apiv2/status/details.go b/apiv2/status/details.go new file mode 100644 index 0000000..5b8f460 --- /dev/null +++ b/apiv2/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/apiv2/status/grpc/types_frostfs.pb.go b/apiv2/status/grpc/types_frostfs.pb.go new file mode 100644 index 0000000000000000000000000000000000000000..8e581661f2187f22af67162344756069bfa769a8 GIT binary patch literal 13432 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 literal 0 HcmV?d00001 diff --git a/apiv2/status/grpc/types_frostfs_fuzz.go b/apiv2/status/grpc/types_frostfs_fuzz.go new file mode 100644 index 0000000..ce9d84e --- /dev/null +++ b/apiv2/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/apiv2/status/grpc/types_frostfs_test.go b/apiv2/status/grpc/types_frostfs_test.go new file mode 100644 index 0000000..dfc5631 --- /dev/null +++ b/apiv2/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/apiv2/status/marshal.go b/apiv2/status/marshal.go new file mode 100644 index 0000000..bfb5870 --- /dev/null +++ b/apiv2/status/marshal.go @@ -0,0 +1,92 @@ +package status + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/rpc/message" + status "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/status/grpc" + protoutil "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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/apiv2/status/message_test.go b/apiv2/status/message_test.go new file mode 100644 index 0000000..53e0168 --- /dev/null +++ b/apiv2/status/message_test.go @@ -0,0 +1,16 @@ +package status_test + +import ( + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/rpc/message" + messagetest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/rpc/message/test" + statustest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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/apiv2/status/status.go b/apiv2/status/status.go new file mode 100644 index 0000000..53d361e --- /dev/null +++ b/apiv2/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<!#>-Ih8Jpg-qReF;?PG2KCf|?CypnMhu%k0} zdUnB%k4`QE*Db>6F1+DP=IOMOdB$B=q(xpz=DW_fD$kh5vnZd5>}Eutp6kS^WFG#( ze{aenV&09AL1SKIaXz{zYkrvI_3T499hsf|YIX-4qp%S3*Q1ih)rhoVq{#E+e;KKz zNJgYhM(D6lutMrE)138*mPU;oG8tC)D|EN@G>Gza^p}WaUW)J|m!*iRk(GkRw}dZw zsUS4sX(*DiR#KFOkrpA@MJeR>gtd(44qR8>7o1%*$!3)->qxQ(*EwDm0@M+Cc3kAq zEvrQ)-@Rq_&sXw0_IOv!`|3L9MIz+M%t~HePwyqSpUh}hO6-U z76m$K&^By=?owzQ-l>2rj7IEShSP+fi+?yPxva~qV)B-=iWc&iEt$x41yAdk#d(>A zGJu{|rKHs*uh>G!TdfzSoW+7CGd2&C8e6yF9A!-=X=^I7u)J6112?X-i1|y_idGAc zKVZIs0R{|+8iL?VCJX_kPevJR#Q5sr-W>TLwK=As=1&_h3q; z#9x!Rp%TP!VkX#l!pbm1ds+q!X9z&o#woAR@y->K5frj^nMJoey5lqd&5*sY%2(nV zrUBZVfb0;rkPee>#VLw7nqb0Ho=KgSZKOkpco~Ng-yGDQRex4Vrpsesep5hGIw$q9 z73n_F*Y8~Vz&qnH=)Gb8Q!V`z0tj;|WCPt#5v!^~Q@0fM2V@4mCk&gK{)7dqCKC9d zKx`sL*LKSGY^z%Hvx6-v>_ntKCD^kGd!=ZVropd8!L!+=YCYQsg!I8q!ZUxxmkmY~ zv-}>bpu3Y;ZKm{s+JG~$_1{oT9}RnK?Ker-%^xd{yncs4R76$AW6LowH$pp9&N5Lrsm68%dsUg&~i6k}E-%th< zKyXa1W8aIyEXyStSvX@EOqfoD7WTaIhRm~F*+bB%0G$e*3%3khDtD)KsyGmZ6=w%y zhKlU94(K?uP=-U6-%-6l)9{2$63%DXpzdHB)CPog)BO!X4X@`)fmA4|w7M4_!bB+G zMnQe8pqjR|0itH%(-9gE9b{&$hvELQQ^@N40oKdG{ zX~;VF{KKOH5XY3yR+rYbZFC0v2iFEB5s@+<2kTWqNg4dS#??(^wHz3;=L@hCW)%*i zC4TVNG(|8T^}VSlqBHk+flJd&OrRk3xpv7IduwEBJA1Xo)%m)sxpAdxe$6QOFyCSe zunlPd*Nkbq;96e)NK62d`m$F&+|1 z`^5r$HJn-m@9P-z0e*>OX4=h=Ep%(%!h^oSyq0XQ>v`i<4!PjZaDh<^&q3eI>LgK> zud%2k7!d;EzkGNJph%w+ z8yG4B&8=m4jDdHJJ%}y2LY$f~YXjG00IQu0K4MW1$hPHftpqFaAEp|`XX@RyW1t&j z^hXL+uh;L~-~&B~ALz~+tLs;lh4r^83~J=2FiKqkxZ^gr@O5oWD|>B!x&*3=y!gQ9 zJfZ3oS#VO}FyzG|`ThRvNV8Km-$5Ri}830GD)U#i>5x;Eq1O1WrYrr2=#1R-^5`|W_0=L0`8;?Ri&b3j^D9C z-JSll<{3+6k?B)7%DEk-=xfMgvuBfRQ>Ma3XJ1`pq@w(+(5h0`AtnfYGgw>6QU};T MYY4PiO%I`e0n=xG7ytkO literal 0 HcmV?d00001 diff --git a/apiv2/tombstone/grpc/types_frostfs_fuzz.go b/apiv2/tombstone/grpc/types_frostfs_fuzz.go new file mode 100644 index 0000000..57cfb58 --- /dev/null +++ b/apiv2/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/apiv2/tombstone/grpc/types_frostfs_test.go b/apiv2/tombstone/grpc/types_frostfs_test.go new file mode 100644 index 0000000..8264824 --- /dev/null +++ b/apiv2/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/apiv2/tombstone/json.go b/apiv2/tombstone/json.go new file mode 100644 index 0000000..9d1f70d --- /dev/null +++ b/apiv2/tombstone/json.go @@ -0,0 +1,14 @@ +package tombstone + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/rpc/message" + tombstone "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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/apiv2/tombstone/marshal.go b/apiv2/tombstone/marshal.go new file mode 100644 index 0000000..15bf1cd --- /dev/null +++ b/apiv2/tombstone/marshal.go @@ -0,0 +1,56 @@ +package tombstone + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/rpc/message" + tombstone "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/tombstone/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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/apiv2/tombstone/message_test.go b/apiv2/tombstone/message_test.go new file mode 100644 index 0000000..e174d30 --- /dev/null +++ b/apiv2/tombstone/message_test.go @@ -0,0 +1,15 @@ +package tombstone_test + +import ( + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/rpc/message" + messagetest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/rpc/message/test" + tombstonetest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/tombstone/test" +) + +func TestMessageConvert(t *testing.T) { + messagetest.TestRPCMessage(t, + func(empty bool) message.Message { return tombstonetest.GenerateTombstone(empty) }, + ) +} diff --git a/apiv2/tombstone/test/generate.go b/apiv2/tombstone/test/generate.go new file mode 100644 index 0000000..a9a1d22 --- /dev/null +++ b/apiv2/tombstone/test/generate.go @@ -0,0 +1,23 @@ +package tombstonetest + +import ( + "crypto/rand" + + refstest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/refs/test" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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/apiv2/tombstone/types.go b/apiv2/tombstone/types.go new file mode 100644 index 0000000..b126c6d --- /dev/null +++ b/apiv2/tombstone/types.go @@ -0,0 +1,57 @@ +package tombstone + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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/apiv2/util/pool/buffer.go b/apiv2/util/pool/buffer.go new file mode 100644 index 0000000..e0a7185 --- /dev/null +++ b/apiv2/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/apiv2/util/pool/marshal.go b/apiv2/util/pool/marshal.go new file mode 100644 index 0000000..107df28 --- /dev/null +++ b/apiv2/util/pool/marshal.go @@ -0,0 +1,7 @@ +package pool + +import ( + "github.com/VictoriaMetrics/easyproto" +) + +var MarshalerPool easyproto.MarshalerPool diff --git a/apiv2/util/proto/encoding/compat.go b/apiv2/util/proto/encoding/compat.go new file mode 100644 index 0000000..09d45e6 --- /dev/null +++ b/apiv2/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/apiv2/util/proto/encoding/json.go b/apiv2/util/proto/encoding/json.go new file mode 100644 index 0000000..3456a40 --- /dev/null +++ b/apiv2/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/apiv2/util/proto/encoding/proto.go b/apiv2/util/proto/encoding/proto.go new file mode 100644 index 0000000..5f3c556 --- /dev/null +++ b/apiv2/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/apiv2/util/proto/marshal.go b/apiv2/util/proto/marshal.go new file mode 100644 index 0000000..5016255 --- /dev/null +++ b/apiv2/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/apiv2/util/proto/marshal_test.go b/apiv2/util/proto/marshal_test.go new file mode 100644 index 0000000..7d7ab91 --- /dev/null +++ b/apiv2/util/proto/marshal_test.go @@ -0,0 +1,217 @@ +package proto_test + +import ( + "math" + "math/rand" + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/util/proto/test" + generated "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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) { + input := &generated.Primitives{} + require.Zero(t, input.StableSize()) + + r := input.MarshalProtobuf(nil) + require.Empty(t, r) + }) + + 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)) + + var actualFrostfs generated.Primitives + require.NoError(t, actualFrostfs.UnmarshalJSON(r)) + 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, 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/apiv2/util/proto/test/custom/test_frostfs.pb.go b/apiv2/util/proto/test/custom/test_frostfs.pb.go new file mode 100644 index 0000000000000000000000000000000000000000..74b3cbb40edb72d2fb2189dbe0e07ce1e83d0ee1 GIT binary patch literal 30151 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 literal 0 HcmV?d00001 diff --git a/apiv2/util/proto/test/test.pb.go b/apiv2/util/proto/test/test.pb.go new file mode 100644 index 0000000000000000000000000000000000000000..e7d5699b73a81daaef96ecfadb426b4b0e543d4f GIT binary patch literal 20911 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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/apiv2/util/protogen/internalgengo/proto_field_type.go b/apiv2/util/protogen/internalgengo/proto_field_type.go new file mode 100644 index 0000000..0096751 --- /dev/null +++ b/apiv2/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/apiv2/util/protogen/internalgengo/proto_stable_compat.go b/apiv2/util/protogen/internalgengo/proto_stable_compat.go new file mode 100644 index 0000000..3c4670c --- /dev/null +++ b/apiv2/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/apiv2/util/protogen/internalgengo/writer.go b/apiv2/util/protogen/internalgengo/writer.go new file mode 100644 index 0000000..7b0d4f1 --- /dev/null +++ b/apiv2/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/apiv2/util/protogen/main.go b/apiv2/util/protogen/main.go new file mode 100644 index 0000000..6e28c69 --- /dev/null +++ b/apiv2/util/protogen/main.go @@ -0,0 +1,27 @@ +package main + +import ( + "flag" + + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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/apiv2/util/signature/data.go b/apiv2/util/signature/data.go new file mode 100644 index 0000000..fc291db --- /dev/null +++ b/apiv2/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/apiv2/refs" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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/apiv2/util/signature/options.go b/apiv2/util/signature/options.go new file mode 100644 index 0000000..a755c2d --- /dev/null +++ b/apiv2/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/apiv2/refs" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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/apiv2/util/signature/sign_test.go b/apiv2/util/signature/sign_test.go new file mode 100644 index 0000000..1c6e897 --- /dev/null +++ b/apiv2/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/apiv2/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/apiv2/util/signature/walletconnect/sign.go b/apiv2/util/signature/walletconnect/sign.go new file mode 100644 index 0000000..b96a842 --- /dev/null +++ b/apiv2/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/apiv2/util/signature/walletconnect/sign_test.go b/apiv2/util/signature/walletconnect/sign_test.go new file mode 100644 index 0000000..1b4fe18 --- /dev/null +++ b/apiv2/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_test.go b/bearer/bearer_test.go index 341c4f2..35a7749 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/apiv2/acl" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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..cbcf550 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/apiv2/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/apiv2/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..c65f8a5 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/apiv2/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..e381367 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/apiv2/refs" ) func ExampleCalculate() { diff --git a/client/accounting.go b/client/accounting.go index faf7ddc..e4dd3a2 100644 --- a/client/accounting.go +++ b/client/accounting.go @@ -11,6 +11,10 @@ import ( 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/apiv2/accounting" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/refs" + rpcapi "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/rpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/rpc/client" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" ) diff --git a/client/api.go b/client/api.go index dd18c42..05c5785 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/apiv2/netmap" + rpcapi "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/rpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/rpc/client" ) // interface of FrostFS API server. Exists for test purposes only. diff --git a/client/client.go b/client/client.go index 4dd5059..9adcb70 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/apiv2/accounting" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/rpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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/apiv2/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..936a948 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/apiv2/refs" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/rpc/client" + v2session "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/session" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/signature" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/version" ) @@ -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/apiv2/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..0a70f8a 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/apiv2/container" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/refs" + rpcapi "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/rpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/rpc/client" + v2session "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/session" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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_eacl.go b/client/container_eacl.go new file mode 100644 index 0000000..e69de29 diff --git a/client/container_get.go b/client/container_get.go index da8166f..f54dbf6 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/apiv2/container" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/refs" + rpcapi "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/rpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/rpc/client" + v2session "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/session" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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..e5273fa 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/apiv2/container" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/refs" + rpcapi "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/rpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/rpc/client" + v2session "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/session" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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..61e46e9 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/apiv2/container" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/refs" + rpcapi "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/rpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/rpc/client" + v2session "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/session" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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_set_eacl.go b/client/container_set_eacl.go new file mode 100644 index 0000000..e69de29 diff --git a/client/container_space.go b/client/container_space.go new file mode 100644 index 0000000..e69de29 diff --git a/client/doc.go b/client/doc.go index 7f6ec42..e69d923 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/apiv2/rpc/client" + import "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/rpc/common" req := new(CustomRPCRequest) // ... diff --git a/client/netmap.go b/client/netmap.go index a870ab2..bbe3326 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/apiv2/netmap" + rpcapi "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/rpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/rpc/client" + v2session "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/session" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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..43b0580 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/apiv2/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/session" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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..eb75e68 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/apiv2/acl" + v2object "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/object" + v2refs "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/refs" + rpcapi "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/rpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/rpc/client" + v2session "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/session" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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..b7d686e 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/apiv2/acl" + v2object "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/object" + v2refs "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/refs" + rpcapi "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/rpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/rpc/client" + v2session "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/session" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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..7d23806 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/apiv2/acl" + v2object "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/object" + v2refs "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/refs" + rpcapi "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/rpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/rpc/client" + v2session "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/session" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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_search.go b/client/object_search.go index aa02542..fa063a6 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/apiv2/acl" + v2object "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/object" + v2refs "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/refs" + rpcapi "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/rpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/rpc/client" + v2session "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/session" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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..e048e86 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/apiv2/object" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/refs" + signatureV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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..0de646d 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/apiv2/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..391a973 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/apiv2/refs" + rpcapi "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/rpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/rpc/client" + v2session "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/session" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/signature" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" ) diff --git a/client/status/common.go b/client/status/common.go index 598631b..e1f52f4 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/apiv2/status" ) // ServerInternal describes failure statuses related to internal server errors. diff --git a/client/status/common_test.go b/client/status/common_test.go index 5a7a2b7..76648b1 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/apiv2/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..a5d817c 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/apiv2/container" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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..78ae81e 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/apiv2/object" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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..a5a78fd 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/apiv2/session" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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..7206890 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/apiv2/status" ) // SuccessDefaultV2 represents Status instance of default success. Implements StatusV2. diff --git a/client/status/unrecognized.go b/client/status/unrecognized.go index 19e481e..feb1097 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/apiv2/status" ) type unrecognizedStatusV2 struct { diff --git a/container/container.go b/container/container.go index 39c6259..67e1708 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/apiv2/container" + v2netmap "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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/apiv2/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..a92346c 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/apiv2/container" + v2netmap "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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..d27dc75 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/apiv2/container" var msg container.Container cnr.WriteToV2(&msg) diff --git a/container/id/id.go b/container/id/id.go index bde739c..aeb44c0 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/apiv2/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/apiv2/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..7efd692 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/apiv2/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/container/size.go b/container/size.go new file mode 100644 index 0000000..e69de29 diff --git a/container/size_test.go b/container/size_test.go new file mode 100644 index 0000000..e69de29 diff --git a/crypto/crypto_test.go b/crypto/crypto_test.go index 7d1ad52..94e7c8c 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/apiv2/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..0bc980e 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/apiv2/refs" var msg refs.Signature sig.WriteToV2(&msg) diff --git a/crypto/ecdsa/wallet_connect.go b/crypto/ecdsa/wallet_connect.go index 34cbcae..f7bf31c 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/apiv2/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..09cacf4 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/apiv2/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/apiv2/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..86b3be3 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/apiv2/refs" ) // Scheme represents digital signature algorithm with fixed cryptographic hash function. diff --git a/eacl/enums.go b/eacl/enums.go index b2b5353..2fac0cd 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/apiv2/acl" ) // Action taken if ContainerEACL record matched request. diff --git a/eacl/enums_test.go b/eacl/enums_test.go index 29f2518..d8e35aa 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/apiv2/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..f4e1f30 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/apiv2/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..2e431aa 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/apiv2/acl" "github.com/stretchr/testify/require" ) diff --git a/eacl/record.go b/eacl/record.go index 3c0d44a..91d075b 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/apiv2/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..2827295 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/apiv2/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..140e57b 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/apiv2/acl" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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..4960253 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/apiv2/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..8cba6bf 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/apiv2/acl" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" ) diff --git a/eacl/target_test.go b/eacl/target_test.go index e226194..bc3a0b4 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/apiv2/acl" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/stretchr/testify/require" ) diff --git a/netmap/context.go b/netmap/context.go index ca791e8..66030a1 100644 --- a/netmap/context.go +++ b/netmap/context.go @@ -3,7 +3,7 @@ package netmap import ( "errors" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/netmap" "git.frostfs.info/TrueCloudLab/hrw" ) diff --git a/netmap/doc.go b/netmap/doc.go index cea3f48..af53177 100644 --- a/netmap/doc.go +++ b/netmap/doc.go @@ -19,7 +19,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/netmap" + import "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/netmap" var msg netmap.NodeInfo info.WriteToV2(&msg) diff --git a/netmap/filter.go b/netmap/filter.go index 76d8545..a3bfa7d 100644 --- a/netmap/filter.go +++ b/netmap/filter.go @@ -5,7 +5,7 @@ import ( "strconv" "strings" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/netmap" ) // mainFilterName is a name of the filter diff --git a/netmap/filter_test.go b/netmap/filter_test.go index 2b88b3c..660b677 100644 --- a/netmap/filter_test.go +++ b/netmap/filter_test.go @@ -4,7 +4,7 @@ import ( "errors" "testing" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/netmap" "github.com/stretchr/testify/require" ) diff --git a/netmap/helper_test.go b/netmap/helper_test.go index 3775f18..b026b47 100644 --- a/netmap/helper_test.go +++ b/netmap/helper_test.go @@ -1,7 +1,7 @@ package netmap import ( - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/netmap" ) func newFilter(name string, k, v string, op netmap.Operation, fs ...Filter) (f Filter) { diff --git a/netmap/netmap.go b/netmap/netmap.go index 85e2a84..78f141f 100644 --- a/netmap/netmap.go +++ b/netmap/netmap.go @@ -3,14 +3,14 @@ package netmap import ( "fmt" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/netmap" "git.frostfs.info/TrueCloudLab/hrw" ) // NetMap represents FrostFS network map. It includes information about all // storage nodes registered in FrostFS the network. // -// NetMap is mutually compatible with git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap.NetMap +// NetMap is mutually compatible with git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/netmap.NetMap // message. See ReadFromV2 / WriteToV2 methods. // // Instances can be created using built-in var declaration. diff --git a/netmap/netmap_test.go b/netmap/netmap_test.go index 7c286a4..ee8adbd 100644 --- a/netmap/netmap_test.go +++ b/netmap/netmap_test.go @@ -3,7 +3,7 @@ package netmap_test import ( "testing" - v2netmap "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap" + v2netmap "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/netmap" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" netmaptest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap/test" "github.com/stretchr/testify/require" diff --git a/netmap/network_info.go b/netmap/network_info.go index 1e553f4..459461f 100644 --- a/netmap/network_info.go +++ b/netmap/network_info.go @@ -6,14 +6,14 @@ import ( "errors" "fmt" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/netmap" "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" ) // NetworkInfo groups information about the FrostFS network state. Mainly used to // describe the current state of the network. // -// NetworkInfo is mutually compatible with git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap.NetworkInfo +// NetworkInfo is mutually compatible with git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/netmap.NetworkInfo // message. See ReadFromV2 / WriteToV2 methods. // // Instances can be created using built-in var declaration. diff --git a/netmap/network_info_test.go b/netmap/network_info_test.go index 161d152..dfb36c6 100644 --- a/netmap/network_info_test.go +++ b/netmap/network_info_test.go @@ -4,7 +4,7 @@ import ( "encoding/binary" "testing" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/netmap" . "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" "github.com/stretchr/testify/require" ) diff --git a/netmap/node_info.go b/netmap/node_info.go index 4be4b70..b2b42ae 100644 --- a/netmap/node_info.go +++ b/netmap/node_info.go @@ -7,7 +7,7 @@ import ( "strconv" "strings" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/netmap" frostfscrypto "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto" "git.frostfs.info/TrueCloudLab/hrw" ) @@ -18,7 +18,7 @@ import ( // about the nodes is available to all network participants to work with the network // map (mainly to comply with container storage policies). // -// NodeInfo is mutually compatible with git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap.NodeInfo +// NodeInfo is mutually compatible with git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/netmap.NodeInfo // message. See ReadFromV2 / WriteToV2 methods. // // Instances can be created using built-in var declaration. diff --git a/netmap/policy.go b/netmap/policy.go index 48ca364..c6132e0 100644 --- a/netmap/policy.go +++ b/netmap/policy.go @@ -7,7 +7,7 @@ import ( "strconv" "strings" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/netmap" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap/parser" "github.com/antlr4-go/antlr/v4" ) @@ -16,7 +16,7 @@ import ( // Within itself, PlacementPolicy represents a set of rules to select a subset // of nodes from FrostFS network map - node-candidates for object storage. // -// PlacementPolicy is mutually compatible with git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap.PlacementPolicy +// PlacementPolicy is mutually compatible with git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/netmap.PlacementPolicy // message. See ReadFromV2 / WriteToV2 methods. // // Instances can be created using built-in var declaration. diff --git a/netmap/selector.go b/netmap/selector.go index ab73cec..dbbefc4 100644 --- a/netmap/selector.go +++ b/netmap/selector.go @@ -5,7 +5,7 @@ import ( "fmt" "slices" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/netmap" "git.frostfs.info/TrueCloudLab/hrw" ) diff --git a/netmap/selector_test.go b/netmap/selector_test.go index 6ef5883..226fa0e 100644 --- a/netmap/selector_test.go +++ b/netmap/selector_test.go @@ -12,7 +12,7 @@ import ( "strings" "testing" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/netmap" "git.frostfs.info/TrueCloudLab/hrw" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/object/attribute.go b/object/attribute.go index e4c7f60..e44305f 100644 --- a/object/attribute.go +++ b/object/attribute.go @@ -1,7 +1,7 @@ package object import ( - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/object" ) // Attribute represents v2-compatible object attribute. diff --git a/object/attribute_test.go b/object/attribute_test.go index eafc312..9e82602 100644 --- a/object/attribute_test.go +++ b/object/attribute_test.go @@ -3,7 +3,7 @@ package object import ( "testing" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/object" "github.com/stretchr/testify/require" ) diff --git a/object/fmt.go b/object/fmt.go index 5e6386d..72ebf12 100644 --- a/object/fmt.go +++ b/object/fmt.go @@ -7,7 +7,7 @@ import ( "errors" "fmt" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/object" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/checksum" frostfscrypto "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" diff --git a/object/id/address.go b/object/id/address.go index 6d5f12a..d868b5f 100644 --- a/object/id/address.go +++ b/object/id/address.go @@ -5,14 +5,14 @@ import ( "fmt" "strings" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/refs" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" ) // Address represents global object identifier in FrostFS network. Each object // belongs to exactly one container and is uniquely addressed within the container. // -// Address is mutually compatible with git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs.Address +// Address is mutually compatible with git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/refs.Address // message. See ReadFromV2 / WriteToV2 methods. // // Instances can be created using built-in var declaration. diff --git a/object/id/address_test.go b/object/id/address_test.go index 5ae91ca..e33dd00 100644 --- a/object/id/address_test.go +++ b/object/id/address_test.go @@ -3,7 +3,7 @@ package oid_test import ( "testing" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/refs" cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" diff --git a/object/id/id.go b/object/id/id.go index 5ba0c6d..c305615 100644 --- a/object/id/id.go +++ b/object/id/id.go @@ -5,7 +5,7 @@ import ( "crypto/sha256" "fmt" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/refs" frostfscrypto "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto" frostfsecdsa "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto/ecdsa" "github.com/mr-tron/base58" @@ -13,7 +13,7 @@ import ( // ID represents FrostFS object identifier in a container. // -// ID is mutually compatible with git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs.ObjectID +// ID is mutually compatible with git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/refs.ObjectID // message. See ReadFromV2 / WriteToV2 methods. // // Instances can be created using built-in var declaration. diff --git a/object/id/id_test.go b/object/id/id_test.go index 3f35a3b..856a449 100644 --- a/object/id/id_test.go +++ b/object/id/id_test.go @@ -6,7 +6,7 @@ import ( "strconv" "testing" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/refs" "github.com/mr-tron/base58" "github.com/stretchr/testify/require" ) diff --git a/object/lock.go b/object/lock.go index dd08eba..a4d202b 100644 --- a/object/lock.go +++ b/object/lock.go @@ -1,8 +1,8 @@ package object import ( - v2object "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" + v2object "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/object" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/refs" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" ) diff --git a/object/range.go b/object/range.go index 87ad3b7..d2248e9 100644 --- a/object/range.go +++ b/object/range.go @@ -1,7 +1,7 @@ package object import ( - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/object" ) // Range represents v2-compatible object payload range. diff --git a/object/range_test.go b/object/range_test.go index c8208d8..2b2e1e4 100644 --- a/object/range_test.go +++ b/object/range_test.go @@ -3,7 +3,7 @@ package object import ( "testing" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/object" "github.com/stretchr/testify/require" ) diff --git a/object/raw.go b/object/raw.go index 5c91f1d..3b87a19 100644 --- a/object/raw.go +++ b/object/raw.go @@ -1,7 +1,7 @@ package object import ( - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/object" ) // RawObject represents v2-compatible FrostFS object that provides diff --git a/object/raw_test.go b/object/raw_test.go index 52ac9de..8cfe92d 100644 --- a/object/raw_test.go +++ b/object/raw_test.go @@ -5,7 +5,7 @@ import ( "crypto/sha256" "testing" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/object" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/checksum" cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" diff --git a/object/search.go b/object/search.go index 818099d..e78a29a 100644 --- a/object/search.go +++ b/object/search.go @@ -4,7 +4,7 @@ import ( "encoding/json" "strconv" - v2object "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" + v2object "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/object" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" diff --git a/object/search_test.go b/object/search_test.go index 4241f7d..e286bad 100644 --- a/object/search_test.go +++ b/object/search_test.go @@ -5,7 +5,7 @@ import ( "crypto/sha256" "testing" - v2object "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" + v2object "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/object" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "github.com/stretchr/testify/require" diff --git a/object/splitinfo.go b/object/splitinfo.go index c38b2a4..3ad36b4 100644 --- a/object/splitinfo.go +++ b/object/splitinfo.go @@ -4,8 +4,8 @@ import ( "errors" "fmt" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/object" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/refs" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" ) diff --git a/object/splitinfo_test.go b/object/splitinfo_test.go index ba3a54f..1c1fd92 100644 --- a/object/splitinfo_test.go +++ b/object/splitinfo_test.go @@ -5,7 +5,7 @@ import ( "encoding/json" "testing" - objv2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" + objv2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/object" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "github.com/stretchr/testify/require" diff --git a/object/tombstone.go b/object/tombstone.go index e332630..0d76a1b 100644 --- a/object/tombstone.go +++ b/object/tombstone.go @@ -1,8 +1,8 @@ package object import ( - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/tombstone" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/refs" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/tombstone" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" ) diff --git a/object/tombstone_test.go b/object/tombstone_test.go index e819b22..3c55a24 100644 --- a/object/tombstone_test.go +++ b/object/tombstone_test.go @@ -5,7 +5,7 @@ import ( "crypto/sha256" "testing" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/tombstone" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/tombstone" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "github.com/stretchr/testify/require" ) diff --git a/object/type.go b/object/type.go index 29328d3..51aafb4 100644 --- a/object/type.go +++ b/object/type.go @@ -1,7 +1,7 @@ package object import ( - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/object" ) type Type object.Type diff --git a/object/type_test.go b/object/type_test.go index 5faa936..0980248 100644 --- a/object/type_test.go +++ b/object/type_test.go @@ -3,7 +3,7 @@ package object_test import ( "testing" - v2object "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" + v2object "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/object" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" "github.com/stretchr/testify/require" ) diff --git a/session/common.go b/session/common.go index b103b59..9bd074c 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/apiv2/refs" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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..202fbc6 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/apiv2/refs" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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/apiv2/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..c8193dd 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/apiv2/refs" + v2session "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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..19d5f10 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/apiv2/session" var msg session.Token tok.WriteToV2(&msg) diff --git a/session/object.go b/session/object.go index 3641bd1..db98188 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/apiv2/refs" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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/apiv2/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..8b14030 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/apiv2/refs" + v2session "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apiv2/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..16f3a7c 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/apiv2/refs" var msg refs.OwnerID id.WriteToV2(&msg) diff --git a/user/id.go b/user/id.go index 31ff9b6..54846db 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/apiv2/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/apiv2/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..c770c48 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/apiv2/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..ecc27db 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/apiv2/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/apiv2/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..a1fd5ca 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/apiv2/refs" "github.com/stretchr/testify/require" )