azure-sdk-for-cpp/sdk/tables/azure-data-tables/src/serializers.cpp
George Arama 84e4a81947
Api view comments (#5408)
* mroe quotes

* dssf

* listTables -> queryTables

* move create/delete to the tableservice

* one more batch

* small refactor, added default data types

* oops

* clangs

* table sas builder

* sas test

* cspell

* add more test

* cspell

* hjhjh

* clang

* rename table-> tables

* clang

* partition and row key

* clang why?

* constructors, update tests

* IT WORKSSSSS

* PR comments

* wqe

* ewr

* enum operator

* clang

* dsaada

* sada

* assets.json

* clang

* Update sdk/tables/azure-data-tables/inc/azure/data/tables/enum_operators.hpp

Co-authored-by: Anton Kolesnyk <41349689+antkmsft@users.noreply.github.com>

* Update sdk/core/azure-core/test/ut/string_test.cpp

Co-authored-by: Anton Kolesnyk <41349689+antkmsft@users.noreply.github.com>

* the = enums

* assert and remove empty

* compact string tests

* clangs

* complement

* azureSasCredentials

* PR cpmments

* some extra

* clang 11

---------

Co-authored-by: Anton Kolesnyk <41349689+antkmsft@users.noreply.github.com>
2024-03-15 14:30:45 -07:00

546 lines
22 KiB
C++

// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
#include "azure/data/tables/internal/serializers.hpp"
#include <azure/core/internal/json/json.hpp>
using namespace Azure::Data::Tables::_detail::Xml;
using namespace Azure::Data::Tables;
namespace Azure { namespace Data { namespace Tables { namespace _detail {
std::string const Serializers::CreateEntity(Models::TableEntity const& tableEntity)
{
std::string jsonBody;
{
auto jsonRoot = Core::Json::_internal::json::object();
jsonRoot["PartitionKey"] = tableEntity.PartitionKey;
jsonRoot["RowKey"] = tableEntity.RowKey;
for (auto entry : tableEntity.Properties)
{
jsonRoot[entry.first] = entry.second;
}
jsonBody = jsonRoot.dump();
}
return jsonBody;
}
std::string const Serializers::MergeEntity(Models::TableEntity const& tableEntity)
{
return CreateEntity(tableEntity);
}
std::string const Serializers::UpdateEntity(Models::TableEntity const& tableEntity)
{
return CreateEntity(tableEntity);
}
std::string const Serializers::SetAccessPolicy(Models::TableAccessPolicy const& tableAccessPolicy)
{
std::string xmlBody;
{
XmlWriter writer;
writer.Write(XmlNode{XmlNodeType::StartTag, "SignedIdentifiers"});
for (const auto& i1 : tableAccessPolicy.SignedIdentifiers)
{
writer.Write(XmlNode{XmlNodeType::StartTag, "SignedIdentifier"});
writer.Write(XmlNode{XmlNodeType::StartTag, "Id", i1.Id});
writer.Write(XmlNode{XmlNodeType::StartTag, "AccessPolicy"});
if (i1.StartsOn.HasValue())
{
writer.Write(XmlNode{
XmlNodeType::StartTag,
"Start",
i1.StartsOn.Value().ToString(
Azure::DateTime::DateFormat::Rfc3339,
Azure::DateTime::TimeFractionFormat::AllDigits)});
}
if (i1.ExpiresOn.HasValue())
{
writer.Write(XmlNode{
XmlNodeType::StartTag,
"Expiry",
i1.ExpiresOn.Value().ToString(
Azure::DateTime::DateFormat::Rfc3339,
Azure::DateTime::TimeFractionFormat::AllDigits)});
}
writer.Write(XmlNode{XmlNodeType::StartTag, "Permission", i1.Permissions});
writer.Write(XmlNode{XmlNodeType::EndTag});
writer.Write(XmlNode{XmlNodeType::EndTag});
}
writer.Write(XmlNode{XmlNodeType::EndTag});
writer.Write(XmlNode{XmlNodeType::End});
xmlBody = writer.GetDocument();
}
return xmlBody;
}
std::string const Serializers::Create(std::string const& tableName)
{
std::string jsonBody;
{
auto jsonRoot = Azure::Core::Json::_internal::json::object();
jsonRoot["TableName"] = tableName;
jsonBody = jsonRoot.dump();
}
return jsonBody;
}
std::string const Serializers::SetServiceProperties(
Models::SetServicePropertiesOptions const& options)
{
std::string xmlBody;
{
XmlWriter writer;
writer.Write(XmlNode{XmlNodeType::StartTag, "StorageServiceProperties"});
writer.Write(XmlNode{XmlNodeType::StartTag, "Logging"});
writer.Write(
XmlNode{XmlNodeType::StartTag, "Version", options.ServiceProperties.Logging.Version});
writer.Write(XmlNode{
XmlNodeType::StartTag,
"Delete",
options.ServiceProperties.Logging.Delete ? "true" : "false"});
writer.Write(XmlNode{
XmlNodeType::StartTag,
"Read",
options.ServiceProperties.Logging.Read ? "true" : "false"});
writer.Write(XmlNode{
XmlNodeType::StartTag,
"Write",
options.ServiceProperties.Logging.Write ? "true" : "false"});
writer.Write(XmlNode{XmlNodeType::StartTag, "RetentionPolicy"});
writer.Write(XmlNode{
XmlNodeType::StartTag,
"Enabled",
options.ServiceProperties.Logging.RetentionPolicyDefinition.IsEnabled ? "true"
: "false"});
if (options.ServiceProperties.Logging.RetentionPolicyDefinition.Days.HasValue())
{
writer.Write(XmlNode{
XmlNodeType::StartTag,
"Days",
std::to_string(
options.ServiceProperties.Logging.RetentionPolicyDefinition.Days.Value())});
}
writer.Write(XmlNode{XmlNodeType::EndTag});
writer.Write(XmlNode{XmlNodeType::EndTag});
writer.Write(XmlNode{XmlNodeType::StartTag, "HourMetrics"});
writer.Write(
XmlNode{XmlNodeType::StartTag, "Version", options.ServiceProperties.HourMetrics.Version});
writer.Write(XmlNode{
XmlNodeType::StartTag,
"Enabled",
options.ServiceProperties.HourMetrics.IsEnabled ? "true" : "false"});
if (options.ServiceProperties.HourMetrics.IncludeApis.HasValue())
{
writer.Write(XmlNode{
XmlNodeType::StartTag,
"IncludeAPIs",
options.ServiceProperties.HourMetrics.IncludeApis.Value() ? "true" : "false"});
}
writer.Write(XmlNode{XmlNodeType::StartTag, "RetentionPolicy"});
writer.Write(XmlNode{
XmlNodeType::StartTag,
"Enabled",
options.ServiceProperties.HourMetrics.RetentionPolicyDefinition.IsEnabled ? "true"
: "false"});
if (options.ServiceProperties.HourMetrics.RetentionPolicyDefinition.Days.HasValue())
{
writer.Write(XmlNode{
XmlNodeType::StartTag,
"Days",
std::to_string(
options.ServiceProperties.HourMetrics.RetentionPolicyDefinition.Days.Value())});
}
writer.Write(XmlNode{XmlNodeType::EndTag});
writer.Write(XmlNode{XmlNodeType::EndTag});
writer.Write(XmlNode{XmlNodeType::StartTag, "MinuteMetrics"});
writer.Write(XmlNode{
XmlNodeType::StartTag, "Version", options.ServiceProperties.MinuteMetrics.Version});
writer.Write(XmlNode{
XmlNodeType::StartTag,
"Enabled",
options.ServiceProperties.MinuteMetrics.IsEnabled ? "true" : "false"});
if (options.ServiceProperties.MinuteMetrics.IncludeApis.HasValue())
{
writer.Write(XmlNode{
XmlNodeType::StartTag,
"IncludeAPIs",
options.ServiceProperties.MinuteMetrics.IncludeApis.Value() ? "true" : "false"});
}
writer.Write(XmlNode{XmlNodeType::StartTag, "RetentionPolicy"});
writer.Write(XmlNode{
XmlNodeType::StartTag,
"Enabled",
options.ServiceProperties.MinuteMetrics.RetentionPolicyDefinition.IsEnabled ? "true"
: "false"});
if (options.ServiceProperties.MinuteMetrics.RetentionPolicyDefinition.Days.HasValue())
{
writer.Write(XmlNode{
XmlNodeType::StartTag,
"Days",
std::to_string(
options.ServiceProperties.MinuteMetrics.RetentionPolicyDefinition.Days.Value())});
}
writer.Write(XmlNode{XmlNodeType::EndTag});
writer.Write(XmlNode{XmlNodeType::EndTag});
writer.Write(XmlNode{XmlNodeType::StartTag, "Cors"});
for (const auto& i1 : options.ServiceProperties.Cors)
{
writer.Write(XmlNode{XmlNodeType::StartTag, "CorsRule"});
writer.Write(XmlNode{XmlNodeType::StartTag, "AllowedOrigins", i1.AllowedOrigins});
writer.Write(XmlNode{XmlNodeType::StartTag, "AllowedMethods", i1.AllowedMethods});
writer.Write(XmlNode{XmlNodeType::StartTag, "AllowedHeaders", i1.AllowedHeaders});
writer.Write(XmlNode{XmlNodeType::StartTag, "ExposedHeaders", i1.ExposedHeaders});
writer.Write(
XmlNode{XmlNodeType::StartTag, "MaxAgeInSeconds", std::to_string(i1.MaxAgeInSeconds)});
writer.Write(XmlNode{XmlNodeType::EndTag});
}
writer.Write(XmlNode{XmlNodeType::EndTag});
writer.Write(XmlNode{XmlNodeType::EndTag});
writer.Write(XmlNode{XmlNodeType::End});
xmlBody = writer.GetDocument();
}
return xmlBody;
}
Models::TableAccessPolicy Serializers::TableAccessPolicyFromXml(std::vector<uint8_t> responseData)
{
Models::TableAccessPolicy response;
XmlReader reader(reinterpret_cast<const char*>(responseData.data()), responseData.size());
enum class XmlTagEnum
{
kUnknown,
kSignedIdentifiers,
kSignedIdentifier,
kId,
kAccessPolicy,
kStart,
kExpiry,
kPermission,
};
const std::unordered_map<std::string, XmlTagEnum> XmlTagEnumMap{
{"SignedIdentifiers", XmlTagEnum::kSignedIdentifiers},
{"SignedIdentifier", XmlTagEnum::kSignedIdentifier},
{"Id", XmlTagEnum::kId},
{"AccessPolicy", XmlTagEnum::kAccessPolicy},
{"Start", XmlTagEnum::kStart},
{"Expiry", XmlTagEnum::kExpiry},
{"Permission", XmlTagEnum::kPermission},
};
std::vector<XmlTagEnum> xmlPath;
Models::SignedIdentifier vectorElement1;
while (true)
{
auto node = reader.Read();
if (node.Type == XmlNodeType::End)
{
break;
}
else if (node.Type == XmlNodeType::StartTag)
{
auto ite = XmlTagEnumMap.find(node.Name);
xmlPath.push_back(ite == XmlTagEnumMap.end() ? XmlTagEnum::kUnknown : ite->second);
}
else if (node.Type == XmlNodeType::Text)
{
if (xmlPath.size() == 3 && xmlPath[0] == XmlTagEnum::kSignedIdentifiers
&& xmlPath[1] == XmlTagEnum::kSignedIdentifier && xmlPath[2] == XmlTagEnum::kId)
{
vectorElement1.Id = node.Value;
}
else if (
xmlPath.size() == 4 && xmlPath[0] == XmlTagEnum::kSignedIdentifiers
&& xmlPath[1] == XmlTagEnum::kSignedIdentifier
&& xmlPath[2] == XmlTagEnum::kAccessPolicy && xmlPath[3] == XmlTagEnum::kStart)
{
vectorElement1.StartsOn
= DateTime::Parse(node.Value, Azure::DateTime::DateFormat::Rfc3339);
}
else if (
xmlPath.size() == 4 && xmlPath[0] == XmlTagEnum::kSignedIdentifiers
&& xmlPath[1] == XmlTagEnum::kSignedIdentifier
&& xmlPath[2] == XmlTagEnum::kAccessPolicy && xmlPath[3] == XmlTagEnum::kExpiry)
{
vectorElement1.ExpiresOn
= DateTime::Parse(node.Value, Azure::DateTime::DateFormat::Rfc3339);
}
else if (
xmlPath.size() == 4 && xmlPath[0] == XmlTagEnum::kSignedIdentifiers
&& xmlPath[1] == XmlTagEnum::kSignedIdentifier
&& xmlPath[2] == XmlTagEnum::kAccessPolicy && xmlPath[3] == XmlTagEnum::kPermission)
{
vectorElement1.Permissions = node.Value;
}
}
else if (node.Type == XmlNodeType::Attribute)
{
}
else if (node.Type == XmlNodeType::EndTag)
{
if (xmlPath.size() == 2 && xmlPath[0] == XmlTagEnum::kSignedIdentifiers
&& xmlPath[1] == XmlTagEnum::kSignedIdentifier)
{
response.SignedIdentifiers.push_back(std::move(vectorElement1));
vectorElement1 = Models::SignedIdentifier();
}
xmlPath.pop_back();
}
}
return response;
}
Models::TableServiceProperties Serializers::ServicePropertiesFromXml(
std::vector<uint8_t> responseData)
{
Models::TableServiceProperties response;
XmlReader reader(reinterpret_cast<const char*>(responseData.data()), responseData.size());
enum class XmlTagEnum
{
kUnknown,
kStorageServiceProperties,
kLogging,
kVersion,
kDelete,
kRead,
kWrite,
kRetentionPolicy,
kEnabled,
kDays,
kHourMetrics,
kIncludeAPIs,
kMinuteMetrics,
kCors,
kCorsRule,
kAllowedOrigins,
kAllowedMethods,
kAllowedHeaders,
kExposedHeaders,
kMaxAgeInSeconds,
};
const std::unordered_map<std::string, XmlTagEnum> XmlTagEnumMap{
{"StorageServiceProperties", XmlTagEnum::kStorageServiceProperties},
{"Logging", XmlTagEnum::kLogging},
{"Version", XmlTagEnum::kVersion},
{"Delete", XmlTagEnum::kDelete},
{"Read", XmlTagEnum::kRead},
{"Write", XmlTagEnum::kWrite},
{"RetentionPolicy", XmlTagEnum::kRetentionPolicy},
{"Enabled", XmlTagEnum::kEnabled},
{"Days", XmlTagEnum::kDays},
{"HourMetrics", XmlTagEnum::kHourMetrics},
{"IncludeAPIs", XmlTagEnum::kIncludeAPIs},
{"MinuteMetrics", XmlTagEnum::kMinuteMetrics},
{"Cors", XmlTagEnum::kCors},
{"CorsRule", XmlTagEnum::kCorsRule},
{"AllowedOrigins", XmlTagEnum::kAllowedOrigins},
{"AllowedMethods", XmlTagEnum::kAllowedMethods},
{"AllowedHeaders", XmlTagEnum::kAllowedHeaders},
{"ExposedHeaders", XmlTagEnum::kExposedHeaders},
{"MaxAgeInSeconds", XmlTagEnum::kMaxAgeInSeconds},
};
std::vector<XmlTagEnum> xmlPath;
Models::CorsRule vectorElement1;
while (true)
{
auto node = reader.Read();
if (node.Type == XmlNodeType::End)
{
break;
}
else if (node.Type == XmlNodeType::StartTag)
{
auto ite = XmlTagEnumMap.find(node.Name);
xmlPath.push_back(ite == XmlTagEnumMap.end() ? XmlTagEnum::kUnknown : ite->second);
}
else if (node.Type == XmlNodeType::Text)
{
if (xmlPath.size() == 3 && xmlPath[0] == XmlTagEnum::kStorageServiceProperties
&& xmlPath[1] == XmlTagEnum::kLogging && xmlPath[2] == XmlTagEnum::kVersion)
{
response.Logging.Version = node.Value;
}
else if (
xmlPath.size() == 3 && xmlPath[0] == XmlTagEnum::kStorageServiceProperties
&& xmlPath[1] == XmlTagEnum::kLogging && xmlPath[2] == XmlTagEnum::kDelete)
{
response.Logging.Delete = node.Value == std::string("true");
}
else if (
xmlPath.size() == 3 && xmlPath[0] == XmlTagEnum::kStorageServiceProperties
&& xmlPath[1] == XmlTagEnum::kLogging && xmlPath[2] == XmlTagEnum::kRead)
{
response.Logging.Read = node.Value == std::string("true");
}
else if (
xmlPath.size() == 3 && xmlPath[0] == XmlTagEnum::kStorageServiceProperties
&& xmlPath[1] == XmlTagEnum::kLogging && xmlPath[2] == XmlTagEnum::kWrite)
{
response.Logging.Write = node.Value == std::string("true");
}
else if (
xmlPath.size() == 4 && xmlPath[0] == XmlTagEnum::kStorageServiceProperties
&& xmlPath[1] == XmlTagEnum::kLogging && xmlPath[2] == XmlTagEnum::kRetentionPolicy
&& xmlPath[3] == XmlTagEnum::kEnabled)
{
response.Logging.RetentionPolicyDefinition.IsEnabled = node.Value == std::string("true");
}
else if (
xmlPath.size() == 4 && xmlPath[0] == XmlTagEnum::kStorageServiceProperties
&& xmlPath[1] == XmlTagEnum::kLogging && xmlPath[2] == XmlTagEnum::kRetentionPolicy
&& xmlPath[3] == XmlTagEnum::kDays)
{
response.Logging.RetentionPolicyDefinition.Days = std::stoi(node.Value);
}
else if (
xmlPath.size() == 3 && xmlPath[0] == XmlTagEnum::kStorageServiceProperties
&& xmlPath[1] == XmlTagEnum::kHourMetrics && xmlPath[2] == XmlTagEnum::kVersion)
{
response.HourMetrics.Version = node.Value;
}
else if (
xmlPath.size() == 3 && xmlPath[0] == XmlTagEnum::kStorageServiceProperties
&& xmlPath[1] == XmlTagEnum::kHourMetrics && xmlPath[2] == XmlTagEnum::kEnabled)
{
response.HourMetrics.IsEnabled = node.Value == std::string("true");
}
else if (
xmlPath.size() == 3 && xmlPath[0] == XmlTagEnum::kStorageServiceProperties
&& xmlPath[1] == XmlTagEnum::kHourMetrics && xmlPath[2] == XmlTagEnum::kIncludeAPIs)
{
response.HourMetrics.IncludeApis = node.Value == std::string("true");
}
else if (
xmlPath.size() == 4 && xmlPath[0] == XmlTagEnum::kStorageServiceProperties
&& xmlPath[1] == XmlTagEnum::kHourMetrics && xmlPath[2] == XmlTagEnum::kRetentionPolicy
&& xmlPath[3] == XmlTagEnum::kEnabled)
{
response.HourMetrics.RetentionPolicyDefinition.IsEnabled
= node.Value == std::string("true");
}
else if (
xmlPath.size() == 4 && xmlPath[0] == XmlTagEnum::kStorageServiceProperties
&& xmlPath[1] == XmlTagEnum::kHourMetrics && xmlPath[2] == XmlTagEnum::kRetentionPolicy
&& xmlPath[3] == XmlTagEnum::kDays)
{
response.HourMetrics.RetentionPolicyDefinition.Days = std::stoi(node.Value);
}
else if (
xmlPath.size() == 3 && xmlPath[0] == XmlTagEnum::kStorageServiceProperties
&& xmlPath[1] == XmlTagEnum::kMinuteMetrics && xmlPath[2] == XmlTagEnum::kVersion)
{
response.MinuteMetrics.Version = node.Value;
}
else if (
xmlPath.size() == 3 && xmlPath[0] == XmlTagEnum::kStorageServiceProperties
&& xmlPath[1] == XmlTagEnum::kMinuteMetrics && xmlPath[2] == XmlTagEnum::kEnabled)
{
response.MinuteMetrics.IsEnabled = node.Value == std::string("true");
}
else if (
xmlPath.size() == 3 && xmlPath[0] == XmlTagEnum::kStorageServiceProperties
&& xmlPath[1] == XmlTagEnum::kMinuteMetrics && xmlPath[2] == XmlTagEnum::kIncludeAPIs)
{
response.MinuteMetrics.IncludeApis = node.Value == std::string("true");
}
else if (
xmlPath.size() == 4 && xmlPath[0] == XmlTagEnum::kStorageServiceProperties
&& xmlPath[1] == XmlTagEnum::kMinuteMetrics
&& xmlPath[2] == XmlTagEnum::kRetentionPolicy && xmlPath[3] == XmlTagEnum::kEnabled)
{
response.MinuteMetrics.RetentionPolicyDefinition.IsEnabled
= node.Value == std::string("true");
}
else if (
xmlPath.size() == 4 && xmlPath[0] == XmlTagEnum::kStorageServiceProperties
&& xmlPath[1] == XmlTagEnum::kMinuteMetrics
&& xmlPath[2] == XmlTagEnum::kRetentionPolicy && xmlPath[3] == XmlTagEnum::kDays)
{
response.MinuteMetrics.RetentionPolicyDefinition.Days = std::stoi(node.Value);
}
else if (
xmlPath.size() == 4 && xmlPath[0] == XmlTagEnum::kStorageServiceProperties
&& xmlPath[1] == XmlTagEnum::kCors && xmlPath[2] == XmlTagEnum::kCorsRule
&& xmlPath[3] == XmlTagEnum::kAllowedOrigins)
{
vectorElement1.AllowedOrigins = node.Value;
}
else if (
xmlPath.size() == 4 && xmlPath[0] == XmlTagEnum::kStorageServiceProperties
&& xmlPath[1] == XmlTagEnum::kCors && xmlPath[2] == XmlTagEnum::kCorsRule
&& xmlPath[3] == XmlTagEnum::kAllowedMethods)
{
vectorElement1.AllowedMethods = node.Value;
}
else if (
xmlPath.size() == 4 && xmlPath[0] == XmlTagEnum::kStorageServiceProperties
&& xmlPath[1] == XmlTagEnum::kCors && xmlPath[2] == XmlTagEnum::kCorsRule
&& xmlPath[3] == XmlTagEnum::kAllowedHeaders)
{
vectorElement1.AllowedHeaders = node.Value;
}
else if (
xmlPath.size() == 4 && xmlPath[0] == XmlTagEnum::kStorageServiceProperties
&& xmlPath[1] == XmlTagEnum::kCors && xmlPath[2] == XmlTagEnum::kCorsRule
&& xmlPath[3] == XmlTagEnum::kExposedHeaders)
{
vectorElement1.ExposedHeaders = node.Value;
}
else if (
xmlPath.size() == 4 && xmlPath[0] == XmlTagEnum::kStorageServiceProperties
&& xmlPath[1] == XmlTagEnum::kCors && xmlPath[2] == XmlTagEnum::kCorsRule
&& xmlPath[3] == XmlTagEnum::kMaxAgeInSeconds)
{
vectorElement1.MaxAgeInSeconds = std::stoi(node.Value);
}
}
else if (node.Type == XmlNodeType::Attribute)
{
}
else if (node.Type == XmlNodeType::EndTag)
{
if (xmlPath.size() == 3 && xmlPath[0] == XmlTagEnum::kStorageServiceProperties
&& xmlPath[1] == XmlTagEnum::kCors && xmlPath[2] == XmlTagEnum::kCorsRule)
{
response.Cors.push_back(std::move(vectorElement1));
vectorElement1 = Models::CorsRule();
}
xmlPath.pop_back();
}
}
return response;
}
Models::TableEntity Serializers::DeserializeEntity(Azure::Core::Json::_internal::json json)
{
Models::TableEntity tableEntity{};
if (json.contains("PartitionKey"))
{
tableEntity.PartitionKey = json["PartitionKey"].get<std::string>();
}
if (json.contains("RowKey"))
{
tableEntity.RowKey = json["RowKey"].get<std::string>();
}
if (json.contains("odata.etag"))
{
tableEntity.ETag = json["odata.etag"].get<std::string>();
}
for (auto properties : json.get<std::map<std::string, std::string>>())
{
if (properties.first.find("odata.type") != std::string::npos)
{
tableEntity.DataType = Models::TableEntityDataType(properties.second);
}
if (properties.first != "odata.metadata" && properties.first != "PartitionKey"
&& properties.first != "RowKey" && properties.first != "odata.etag")
{
tableEntity.Properties[properties.first] = properties.second;
}
}
return tableEntity;
}
}}}} // namespace Azure::Data::Tables::_detail