From aa7232fc8376bd05196626afed08f828b89bf4fc Mon Sep 17 00:00:00 2001 From: Carlos O'Ryan Date: Wed, 21 Sep 2022 13:06:30 +0000 Subject: [PATCH] feat(storage): easier mocks with `BucketMetadata` Populating all the fields for `BucketMetadata` was somewhat difficult. The class tried to prevent applications from setting fields that only the server would set. I thought about adding a `BucketMetadataBuilder`, but that would duplicate a lot of code without preventing anything. In addition, all the other libraries use protos that allow any field to be set, and that does not seemt to create a lot of trouble or confusion. I also stopped using the "composition-by-private-inheritance" base because it does not save enough code. I expect this class will go away once I make similar changes to `ObjectMetadata`. --- google/cloud/storage/bucket_metadata.cc | 45 ++-- google/cloud/storage/bucket_metadata.h | 117 ++++++++-- .../internal/bucket_metadata_parser.cc | 201 +++++++++--------- .../internal/grpc_bucket_metadata_parser.cc | 72 ++++--- 4 files changed, 269 insertions(+), 166 deletions(-) diff --git a/google/cloud/storage/bucket_metadata.cc b/google/cloud/storage/bucket_metadata.cc index 1c76ee7f007e..506ac917dc22 100644 --- a/google/cloud/storage/bucket_metadata.cc +++ b/google/cloud/storage/bucket_metadata.cc @@ -140,22 +140,35 @@ std::ostream& operator<<(std::ostream& os, } bool operator==(BucketMetadata const& lhs, BucketMetadata const& rhs) { - return static_cast const&>(lhs) == - rhs && - lhs.acl_ == rhs.acl_ && lhs.billing_ == rhs.billing_ && - lhs.cors_ == rhs.cors_ && - lhs.default_event_based_hold_ == rhs.default_event_based_hold_ && - lhs.default_acl_ == rhs.default_acl_ && - lhs.encryption_ == rhs.encryption_ && - lhs.iam_configuration_ == rhs.iam_configuration_ && - lhs.project_number_ == rhs.project_number_ && - lhs.lifecycle_ == rhs.lifecycle_ && lhs.location_ == rhs.location_ && - lhs.location_type_ == rhs.location_type_ && - lhs.logging_ == rhs.logging_ && lhs.labels_ == rhs.labels_ && - lhs.retention_policy_ == rhs.retention_policy_ && - lhs.rpo_ == rhs.rpo_ && lhs.versioning_ == rhs.versioning_ && - lhs.website_ == rhs.website_ && - lhs.custom_placement_config_ == rhs.custom_placement_config_; + return lhs.acl_ == rhs.acl_ // + && lhs.billing_ == rhs.billing_ // + && lhs.cors_ == rhs.cors_ // + && lhs.custom_placement_config_ == rhs.custom_placement_config_ // + && lhs.default_acl_ == rhs.default_acl_ // + && lhs.default_event_based_hold_ == rhs.default_event_based_hold_ // + && lhs.encryption_ == rhs.encryption_ // + && lhs.etag_ == rhs.etag_ // + && lhs.iam_configuration_ == rhs.iam_configuration_ // + && lhs.id_ == rhs.id_ // + && lhs.kind_ == rhs.kind_ // + && lhs.labels_ == rhs.labels_ // + && lhs.lifecycle_ == rhs.lifecycle_ // + && lhs.location_ == rhs.location_ // + && lhs.location_type_ == rhs.location_type_ // + && lhs.logging_ == rhs.logging_ // + && lhs.metageneration_ == rhs.metageneration_ // + && lhs.name_ == rhs.name_ // + && lhs.owner_ == rhs.owner_ // + && lhs.project_number_ == rhs.project_number_ // + && lhs.retention_policy_ == rhs.retention_policy_ // + && lhs.rpo_ == rhs.rpo_ // + && lhs.self_link_ == rhs.self_link_ // + && lhs.storage_class_ == rhs.storage_class_ // + && lhs.time_created_ == rhs.time_created_ // + && lhs.updated_ == rhs.updated_ // + && lhs.versioning_ == rhs.versioning_ // + && lhs.website_ == rhs.website_ // + ; } std::ostream& operator<<(std::ostream& os, BucketMetadata const& rhs) { diff --git a/google/cloud/storage/bucket_metadata.h b/google/cloud/storage/bucket_metadata.h index e95d4d87ac18..8b35f77e573d 100644 --- a/google/cloud/storage/bucket_metadata.h +++ b/google/cloud/storage/bucket_metadata.h @@ -35,8 +35,6 @@ namespace cloud { namespace storage { GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_BEGIN namespace internal { -struct BucketMetadataParser; -struct GrpcBucketMetadataParser; struct GrpcBucketRequestParser; } // namespace internal @@ -574,7 +572,7 @@ std::ostream& operator<<(std::ostream& os, /** * Represents a Google Cloud Storage Bucket Metadata object. */ -class BucketMetadata : private internal::CommonMetadata { +class BucketMetadata { public: BucketMetadata() = default; @@ -710,7 +708,12 @@ class BucketMetadata : private internal::CommonMetadata { } ///@} - using CommonMetadata::etag; + std::string const& etag() const { return etag_; } + /// @note This is only intended for mocking. + BucketMetadata& set_etag(std::string v) { + etag_ = std::move(v); + return *this; + } /** * @name Get and set the IAM configuration. @@ -743,8 +746,19 @@ class BucketMetadata : private internal::CommonMetadata { } ///@} - using CommonMetadata::id; - using CommonMetadata::kind; + std::string const& id() const { return id_; } + /// @note This is only intended for mocking + BucketMetadata& set_id(std::string v) { + id_ = std::move(v); + return *this; + } + + std::string const& kind() const { return kind_; } + /// @note This is only intended for mocking + BucketMetadata& set_kind(std::string v) { + kind_ = std::move(v); + return *this; + } /// @name Accessors and modifiers to the `labels`. ///@{ @@ -819,8 +833,15 @@ class BucketMetadata : private internal::CommonMetadata { return *this; } + /// Returns the location type (e.g. regional vs. dual region). std::string const& location_type() const { return location_type_; } + /// @note This is only intended for mocking. + BucketMetadata& set_location_type(std::string v) { + location_type_ = std::move(v); + return *this; + } + /// @name Accessors and modifiers for logging configuration. ///@{ bool has_logging() const { return logging_.has_value(); } @@ -839,10 +860,15 @@ class BucketMetadata : private internal::CommonMetadata { ///@} /// The bucket metageneration. - using CommonMetadata::metageneration; + std::int64_t metageneration() const { return metageneration_; } + /// @note this is only intended for mocking. + BucketMetadata& set_metageneration(std::int64_t v) { + metageneration_ = v; + return *this; + } /// The bucket name. - using CommonMetadata::name; + std::string const& name() const { return name_; } /** * Changes the name. @@ -852,17 +878,46 @@ class BucketMetadata : private internal::CommonMetadata { * some other attribute. */ BucketMetadata& set_name(std::string v) { - CommonMetadata::set_name(std::move(v)); + name_ = std::move(v); return *this; } /// Returns true if the bucket `owner` attribute is present. - using CommonMetadata::has_owner; - using CommonMetadata::owner; + bool has_owner() const { return owner_.has_value(); } + /** + * Returns the owner. + * + * It is undefined behavior to call `owner()` if `has_owner()` is false. + */ + Owner const& owner() const { return *owner_; } + + /// @note this is only intended for mocking. + BucketMetadata& set_owner(Owner v) { + owner_ = std::move(v); + return *this; + } + /// @note this is only intended for mocking. + BucketMetadata& reset_owner() { + owner_.reset(); + return *this; + } std::int64_t const& project_number() const { return project_number_; } - using CommonMetadata::self_link; + /// @note this is only intended for mocking. + BucketMetadata& set_project_number(std::int64_t v) { + project_number_ = v; + return *this; + } + + /// Returns a HTTP link to retrieve the bucket metadata. + std::string const& self_link() const { return self_link_; } + + /// @note this is only intended for mocking. + BucketMetadata& set_self_link(std::string v) { + self_link_ = std::move(v); + return *this; + } /// @name Accessors and modifiers for retention policy configuration. ///@{ @@ -908,18 +963,31 @@ class BucketMetadata : private internal::CommonMetadata { /// @name Access and modify the default storage class attribute. ///@{ - using CommonMetadata::storage_class; + std::string const& storage_class() const { return storage_class_; } BucketMetadata& set_storage_class(std::string v) { - CommonMetadata::set_storage_class(std::move(v)); + storage_class_ = std::move(v); return *this; } ///@} /// Returns the bucket creation timestamp. - using CommonMetadata::time_created; + std::chrono::system_clock::time_point time_created() const { + return time_created_; + } + /// @note This is only intended for mocking. + BucketMetadata& set_time_created(std::chrono::system_clock::time_point v) { + time_created_ = v; + return *this; + } /// Returns the timestamp for the last bucket metadata update. - using CommonMetadata::updated; + std::chrono::system_clock::time_point updated() const { return updated_; } + + /// @note This is only intended for mocking. + BucketMetadata& set_updated(std::chrono::system_clock::time_point v) { + updated_ = v; + return *this; + } /// @name Accessors and modifiers for versioning configuration. ///@{ @@ -992,29 +1060,36 @@ class BucketMetadata : private internal::CommonMetadata { } private: - friend struct internal::BucketMetadataParser; - friend struct internal::GrpcBucketMetadataParser; - friend std::ostream& operator<<(std::ostream& os, BucketMetadata const& rhs); // Keep the fields in alphabetical order. std::vector acl_; absl::optional billing_; std::vector cors_; - bool default_event_based_hold_ = false; + absl::optional custom_placement_config_; std::vector default_acl_; + bool default_event_based_hold_ = false; absl::optional encryption_; + std::string etag_; absl::optional iam_configuration_; + std::string id_; + std::string kind_; std::map labels_; absl::optional lifecycle_; std::string location_; std::string location_type_; absl::optional logging_; + std::int64_t metageneration_{0}; + std::string name_; + absl::optional owner_; std::int64_t project_number_ = 0; absl::optional retention_policy_; std::string rpo_; + std::string self_link_; + std::string storage_class_; + std::chrono::system_clock::time_point time_created_; + std::chrono::system_clock::time_point updated_; absl::optional versioning_; absl::optional website_; - absl::optional custom_placement_config_; }; std::ostream& operator<<(std::ostream& os, BucketMetadata const& rhs); diff --git a/google/cloud/storage/internal/bucket_metadata_parser.cc b/google/cloud/storage/internal/bucket_metadata_parser.cc index 93008960dbf3..d094456530b4 100644 --- a/google/cloud/storage/internal/bucket_metadata_parser.cc +++ b/google/cloud/storage/internal/bucket_metadata_parser.cc @@ -68,8 +68,7 @@ StatusOr ParseUniformBucketLevelAccess( return UniformBucketLevelAccess{*enabled, *locked_time}; } -Status ParseAcl(std::vector& acl, - nlohmann::json const& json) { +Status ParseAcl(BucketMetadata& meta, nlohmann::json const& json) { if (!json.contains("acl")) return Status{}; std::vector value; @@ -78,21 +77,20 @@ Status ParseAcl(std::vector& acl, if (!parsed.ok()) return std::move(parsed).status(); value.push_back(std::move(*parsed)); } - acl = std::move(value); + meta.set_acl(std::move(value)); return Status{}; } -Status ParseBilling(absl::optional& billing, - nlohmann::json const& json) { +Status ParseBilling(BucketMetadata& meta, nlohmann::json const& json) { if (!json.contains("billing")) return Status{}; auto const& b = json["billing"]; auto requester_pays = internal::ParseBoolField(b, "requesterPays"); if (!requester_pays) return std::move(requester_pays).status(); - billing = BucketBilling{*requester_pays}; + meta.set_billing(BucketBilling{*requester_pays}); return Status{}; } -Status ParseCorsList(std::vector& list, nlohmann::json const& json) { +Status ParseCorsList(BucketMetadata& meta, nlohmann::json const& json) { if (!json.contains("cors")) return Status{}; std::vector value; for (auto const& kv : json["cors"].items()) { @@ -100,20 +98,33 @@ Status ParseCorsList(std::vector& list, nlohmann::json const& json) { if (!cors) return std::move(cors).status(); value.push_back(*std::move(cors)); } - list = std::move(value); + meta.set_cors(std::move(value)); return Status{}; } -Status ParseDefaultEventBasedHold(bool& default_event_based_hold, +Status ParseCustomPlacementConfig(BucketMetadata& meta, nlohmann::json const& json) { - if (json.contains("defaultEventBasedHold")) { - default_event_based_hold = json.value("defaultEventBasedHold", false); + if (!json.contains("customPlacementConfig")) return Status{}; + auto const& field = json["customPlacementConfig"]; + auto error = [] { + return Status{StatusCode::kInvalidArgument, + "malformed customPlacementConfig"}; + }; + if (!field.is_object()) return error(); + if (!field.contains("dataLocations")) return Status{}; + auto const& locations = field["dataLocations"]; + if (!locations.is_array()) return error(); + + BucketCustomPlacementConfig value; + for (auto const& i : locations.items()) { + if (!i.value().is_string()) return error(); + value.data_locations.push_back(i.value().get()); } + meta.set_custom_placement_config(std::move(value)); return Status{}; } -Status ParseDefaultObjectAcl(std::vector& acl, - nlohmann::json const& json) { +Status ParseDefaultObjectAcl(BucketMetadata& meta, nlohmann::json const& json) { if (!json.contains("defaultObjectAcl")) return Status{}; std::vector value; for (auto const& kv : json["defaultObjectAcl"].items()) { @@ -121,23 +132,20 @@ Status ParseDefaultObjectAcl(std::vector& acl, if (!parsed.ok()) return std::move(parsed).status(); value.push_back(std::move(*parsed)); } - acl = std::move(value); + meta.set_default_acl(std::move(value)); return Status{}; } -Status ParseEncryption(absl::optional& encryption, - nlohmann::json const& json) { +Status ParseEncryption(BucketMetadata& meta, nlohmann::json const& json) { if (json.contains("encryption")) { BucketEncryption e; e.default_kms_key_name = json["encryption"].value("defaultKmsKeyName", ""); - encryption = std::move(e); + meta.set_encryption(std::move(e)); } return Status{}; } -Status ParseIamConfiguration( - absl::optional& iam_configuration, - nlohmann::json const& json) { +Status ParseIamConfiguration(BucketMetadata& meta, nlohmann::json const& json) { if (!json.contains("iamConfiguration")) return Status{}; BucketIamConfiguration value; auto c = json["iamConfiguration"]; @@ -149,12 +157,11 @@ Status ParseIamConfiguration( if (c.contains("publicAccessPrevention")) { value.public_access_prevention = c.value("publicAccessPrevention", ""); } - iam_configuration = std::move(value); + meta.set_iam_configuration(std::move(value)); return Status{}; } -Status ParseLifecycle(absl::optional& lifecycle, - nlohmann::json const& json) { +Status ParseLifecycle(BucketMetadata& meta, nlohmann::json const& json) { if (!json.contains("lifecycle")) return Status{}; auto const& l = json["lifecycle"]; BucketLifecycle value; @@ -165,18 +172,17 @@ Status ParseLifecycle(absl::optional& lifecycle, value.rule.emplace_back(std::move(*parsed)); } } - lifecycle = std::move(value); + meta.set_lifecycle(std::move(value)); return Status{}; } -Status ParseLogging(absl::optional& logging, - nlohmann::json const& json) { +Status ParseLogging(BucketMetadata& meta, nlohmann::json const& json) { if (!json.contains("logging")) return Status{}; auto const& l = json["logging"]; BucketLogging value; value.log_bucket = l.value("logBucket", ""); value.log_object_prefix = l.value("logObjectPrefix", ""); - logging = std::move(value); + meta.set_logging(std::move(value)); return Status{}; } @@ -189,17 +195,16 @@ std::map ParseLabels(nlohmann::json const& json) { return value; } -Status ParseProjectNumber(std::int64_t& project_number, - nlohmann::json const& json) { - auto p = internal::ParseLongField(json, "projectNumber"); - if (!p) return std::move(p).status(); - project_number = *p; +Status ParseOwner(BucketMetadata& meta, nlohmann::json const& json) { + if (!json.contains("owner")) return Status{}; + Owner o; + o.entity = json["owner"].value("entity", ""); + o.entity_id = json["owner"].value("entityId", ""); + meta.set_owner(std::move(o)); return Status{}; } -Status ParseRetentionPolicy( - absl::optional& retention_policy, - nlohmann::json const& json) { +Status ParseRetentionPolicy(BucketMetadata& meta, nlohmann::json const& json) { if (!json.contains("retentionPolicy")) return Status{}; auto const& r = json["retentionPolicy"]; auto const is_locked = internal::ParseBoolField(r, "isLocked"); @@ -208,53 +213,42 @@ Status ParseRetentionPolicy( if (!retention_period) return std::move(retention_period).status(); auto effective_time = internal::ParseTimestampField(r, "effectiveTime"); if (!effective_time) return std::move(effective_time).status(); - retention_policy = BucketRetentionPolicy{ - std::chrono::seconds(*retention_period), *effective_time, *is_locked}; + meta.set_retention_policy(BucketRetentionPolicy{ + std::chrono::seconds(*retention_period), *effective_time, *is_locked}); + return Status{}; +} + +Status ParseTimeCreated(BucketMetadata& meta, nlohmann::json const& json) { + auto v = ParseTimestampField(json, "timeCreated"); + if (!v) return std::move(v).status(); + meta.set_time_created(*std::move(v)); return Status{}; } -Status ParseVersioning(absl::optional& versioning, - nlohmann::json const& json) { +Status ParseUpdated(BucketMetadata& meta, nlohmann::json const& json) { + auto v = ParseTimestampField(json, "updated"); + if (!v) return std::move(v).status(); + meta.set_updated(*std::move(v)); + return Status{}; +} + +Status ParseVersioning(BucketMetadata& meta, nlohmann::json const& json) { if (!json.contains("versioning")) return Status{}; auto const& v = json["versioning"]; if (!v.contains("enabled")) return Status{}; auto const& enabled = internal::ParseBoolField(v, "enabled"); if (!enabled) return std::move(enabled).status(); - versioning = BucketVersioning{*enabled}; + meta.set_versioning(BucketVersioning{*enabled}); return Status{}; } -Status ParseWebsite(absl::optional& website, - nlohmann::json const& json) { +Status ParseWebsite(BucketMetadata& meta, nlohmann::json const& json) { if (!json.contains("website")) return Status{}; auto const& w = json["website"]; BucketWebsite value; value.main_page_suffix = w.value("mainPageSuffix", ""); value.not_found_page = w.value("notFoundPage", ""); - website = std::move(value); - return Status{}; -} - -Status ParseCustomPlacementConfig( - absl::optional& lhs, - nlohmann::json const& json) { - if (!json.contains("customPlacementConfig")) return Status{}; - auto const& field = json["customPlacementConfig"]; - auto error = [] { - return Status{StatusCode::kInvalidArgument, - "malformed customPlacementConfig"}; - }; - if (!field.is_object()) return error(); - if (!field.contains("dataLocations")) return Status{}; - auto const& locations = field["dataLocations"]; - if (!locations.is_array()) return error(); - - BucketCustomPlacementConfig value; - for (auto const& i : locations.items()) { - if (!i.value().is_string()) return error(); - value.data_locations.push_back(i.value().get()); - } - lhs = std::move(value); + meta.set_website(std::move(value)); return Status{}; } @@ -457,67 +451,80 @@ StatusOr BucketMetadataParser::FromJson( using Parser = std::function; Parser parsers[] = { + ParseAcl, + ParseBilling, + ParseCorsList, + ParseCustomPlacementConfig, [](BucketMetadata& meta, nlohmann::json const& json) { - return CommonMetadataParser::FromJson(meta, json); - }, - [](BucketMetadata& meta, nlohmann::json const& json) { - return ParseAcl(meta.acl_, json); - }, - [](BucketMetadata& meta, nlohmann::json const& json) { - return ParseBilling(meta.billing_, json); - }, - [](BucketMetadata& meta, nlohmann::json const& json) { - return ParseCorsList(meta.cors_, json); - }, - [](BucketMetadata& meta, nlohmann::json const& json) { - return ParseDefaultEventBasedHold(meta.default_event_based_hold_, json); - }, - [](BucketMetadata& meta, nlohmann::json const& json) { - return ParseDefaultObjectAcl(meta.default_acl_, json); - }, - [](BucketMetadata& meta, nlohmann::json const& json) { - return ParseEncryption(meta.encryption_, json); + if (json.contains("defaultEventBasedHold")) { + meta.set_default_event_based_hold( + json.value("defaultEventBasedHold", false)); + } + return Status{}; }, + ParseDefaultObjectAcl, + ParseEncryption, [](BucketMetadata& meta, nlohmann::json const& json) { - return ParseIamConfiguration(meta.iam_configuration_, json); + meta.set_etag(json.value("etag", "")); + return Status{}; }, + ParseIamConfiguration, [](BucketMetadata& meta, nlohmann::json const& json) { - return ParseLifecycle(meta.lifecycle_, json); + meta.set_id(json.value("id", "")); + return Status{}; }, [](BucketMetadata& meta, nlohmann::json const& json) { - meta.location_ = json.value("location", ""); + meta.set_kind(json.value("kind", "")); return Status{}; }, [](BucketMetadata& meta, nlohmann::json const& json) { - meta.location_type_ = json.value("locationType", ""); + meta.mutable_labels() = ParseLabels(json); return Status{}; }, + ParseLifecycle, [](BucketMetadata& meta, nlohmann::json const& json) { - return ParseLogging(meta.logging_, json); + meta.set_location(json.value("location", "")); + return Status{}; }, [](BucketMetadata& meta, nlohmann::json const& json) { - return ParseProjectNumber(meta.project_number_, json); + meta.set_location_type(json.value("locationType", "")); + return Status{}; }, + ParseLogging, [](BucketMetadata& meta, nlohmann::json const& json) { - meta.labels_ = ParseLabels(json); + auto v = internal::ParseLongField(json, "metageneration"); + if (!v) return std::move(v).status(); + meta.set_metageneration(*v); return Status{}; }, [](BucketMetadata& meta, nlohmann::json const& json) { - return ParseRetentionPolicy(meta.retention_policy_, json); + meta.set_name(json.value("name", "")); + return Status{}; }, [](BucketMetadata& meta, nlohmann::json const& json) { - meta.rpo_ = json.value("rpo", ""); + auto v = internal::ParseLongField(json, "projectNumber"); + if (!v) return std::move(v).status(); + meta.set_project_number(*v); return Status{}; }, + ParseOwner, + ParseRetentionPolicy, [](BucketMetadata& meta, nlohmann::json const& json) { - return ParseVersioning(meta.versioning_, json); + meta.set_rpo(json.value("rpo", "")); + return Status{}; }, [](BucketMetadata& meta, nlohmann::json const& json) { - return ParseWebsite(meta.website_, json); + meta.set_self_link(json.value("selfLink", "")); + return Status{}; }, [](BucketMetadata& meta, nlohmann::json const& json) { - return ParseCustomPlacementConfig(meta.custom_placement_config_, json); + meta.set_storage_class(json.value("storageClass", "")); + return Status{}; }, + ParseTimeCreated, + ParseUpdated, + ParseVersioning, + ParseWebsite, }; BucketMetadata meta{}; diff --git a/google/cloud/storage/internal/grpc_bucket_metadata_parser.cc b/google/cloud/storage/internal/grpc_bucket_metadata_parser.cc index 25ca66d43fd2..3d172fe13892 100644 --- a/google/cloud/storage/internal/grpc_bucket_metadata_parser.cc +++ b/google/cloud/storage/internal/grpc_bucket_metadata_parser.cc @@ -115,36 +115,42 @@ BucketMetadata GrpcBucketMetadataParser::FromProto( // These are sorted as the fields in the BucketMetadata class, to make them // easier to find in the future. for (auto const& v : rhs.acl()) { - metadata.acl_.push_back( + metadata.mutable_acl().push_back( GrpcBucketAccessControlParser::FromProto(v, rhs.bucket_id())); } - if (rhs.has_billing()) metadata.billing_ = FromProto(rhs.billing()); - metadata.default_event_based_hold_ = rhs.default_event_based_hold(); + if (rhs.has_billing()) metadata.set_billing(FromProto(rhs.billing())); + metadata.set_default_event_based_hold(rhs.default_event_based_hold()); for (auto const& v : rhs.cors()) { - metadata.cors_.push_back(FromProto(v)); + metadata.mutable_cors().push_back(FromProto(v)); } for (auto const& v : rhs.default_object_acl()) { - metadata.default_acl_.push_back(GrpcObjectAccessControlParser::FromProto( - v, rhs.bucket_id(), /*object_name*/ std::string{}, /*generation=*/0)); + metadata.mutable_default_acl().push_back( + GrpcObjectAccessControlParser::FromProto(v, rhs.bucket_id(), + /*object_name*/ std::string{}, + /*generation=*/0)); + } + if (rhs.has_encryption()) { + metadata.set_encryption(FromProto(rhs.encryption())); } - if (rhs.has_encryption()) metadata.encryption_ = FromProto(rhs.encryption()); if (rhs.has_iam_config()) { - metadata.iam_configuration_ = FromProto(rhs.iam_config()); + metadata.set_iam_configuration(FromProto(rhs.iam_config())); } - metadata.etag_ = rhs.etag(); - metadata.id_ = rhs.bucket_id(); - metadata.kind_ = "storage#bucket"; + metadata.set_etag(rhs.etag()); + metadata.set_id(rhs.bucket_id()); + metadata.set_kind("storage#bucket"); for (auto const& kv : rhs.labels()) { - metadata.labels_.emplace(std::make_pair(kv.first, kv.second)); - } - if (rhs.has_lifecycle()) metadata.lifecycle_ = FromProto(rhs.lifecycle()); - metadata.location_ = rhs.location(); - metadata.location_type_ = rhs.location_type(); - if (rhs.has_logging()) metadata.logging_ = FromProto(rhs.logging()); - metadata.metageneration_ = rhs.metageneration(); - metadata.name_ = GrpcBucketNameToId(rhs.name()); + metadata.mutable_labels().emplace(std::make_pair(kv.first, kv.second)); + } + if (rhs.has_lifecycle()) { + metadata.set_lifecycle(FromProto(rhs.lifecycle())); + } + metadata.set_location(rhs.location()); + metadata.set_location_type(rhs.location_type()); + if (rhs.has_logging()) metadata.set_logging(FromProto(rhs.logging())); + metadata.set_metageneration(rhs.metageneration()); + metadata.set_name(GrpcBucketNameToId(rhs.name())); if (rhs.has_owner()) { - metadata.owner_ = storage_internal::FromProto(rhs.owner()); + metadata.set_owner(storage_internal::FromProto(rhs.owner())); } // The protos use `projects/{project}` format, but the field may be absent or @@ -155,27 +161,29 @@ BucketMetadata GrpcBucketMetadataParser::FromProto( auto s = rhs.project().substr(std::strlen("projects/")); char* end; auto number = std::strtol(s.c_str(), &end, 10); - if (end != nullptr && *end == '\0') metadata.project_number_ = number; + if (end != nullptr && *end == '\0') metadata.set_project_number(number); } if (rhs.has_retention_policy()) { - metadata.retention_policy_ = FromProto(rhs.retention_policy()); + metadata.set_retention_policy(FromProto(rhs.retention_policy())); } - metadata.rpo_ = rhs.rpo(); - metadata.storage_class_ = rhs.storage_class(); + metadata.set_rpo(rhs.rpo()); + metadata.set_storage_class(rhs.storage_class()); if (rhs.has_create_time()) { - metadata.time_created_ = - google::cloud::internal::ToChronoTimePoint(rhs.create_time()); + metadata.set_time_created( + google::cloud::internal::ToChronoTimePoint(rhs.create_time())); } if (rhs.has_update_time()) { - metadata.updated_ = - google::cloud::internal::ToChronoTimePoint(rhs.update_time()); + metadata.set_updated( + google::cloud::internal::ToChronoTimePoint(rhs.update_time())); + } + if (rhs.has_versioning()) { + metadata.set_versioning(FromProto(rhs.versioning())); } - if (rhs.has_versioning()) metadata.versioning_ = FromProto(rhs.versioning()); - if (rhs.has_website()) metadata.website_ = FromProto(rhs.website()); + if (rhs.has_website()) metadata.set_website(FromProto(rhs.website())); if (rhs.has_custom_placement_config()) { - metadata.custom_placement_config_ = - FromProto(rhs.custom_placement_config()); + metadata.set_custom_placement_config( + FromProto(rhs.custom_placement_config())); } return metadata;