Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion src/aws-cpp-sdk-core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -543,7 +543,15 @@ check_cxx_source_compiles("
return 0;
}" AWS_HAS_ALIGNED_ALLOC)

add_library(${PROJECT_NAME} ${AWS_NATIVE_SDK_SRC})
add_library(${PROJECT_NAME} ${AWS_NATIVE_SDK_SRC}
include/smithy/client/schema/ShapeSerializer.h
include/smithy/client/schema/CborShapeSerializer.h
include/smithy/client/schema/Schema.h
include/smithy/client/schema/JsonShapeSerializer.h
include/smithy/client/schema/QueryShapeSerializer.h
include/smithy/client/schema/XmlShapeSerializer.h
source/smithy/client/schema/JsonShapeSerializer.cpp
)
add_library(AWS::${PROJECT_NAME} ALIAS ${PROJECT_NAME})

target_compile_definitions(${PROJECT_NAME} PUBLIC "AWS_SDK_VERSION_MAJOR=${AWSSDK_VERSION_MAJOR}")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@

#include <aws/core/Core_EXPORTS.h>
#include <smithy/client/schema/ShapeSerializer.h>

#include <memory>
#include <aws/core/utils/memory/AWSMemory.h>

namespace smithy {
namespace schema {
Expand Down Expand Up @@ -40,7 +39,7 @@ class AWS_CORE_API CborShapeSerialize final : public ShapeSerializer {

private:
struct Impl;
std::unique_ptr<Impl> m_impl;
Aws::UniquePtr<Impl> m_impl;
};

} // namespace schema
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

#include <smithy/client/schema/ShapeSerializer.h>

#include <memory>
#include <aws/core/utils/memory/AWSMemory.h>

namespace smithy {
namespace schema {
Expand Down Expand Up @@ -35,11 +35,11 @@ class JsonShapeSerializer final : public ShapeSerializer {
void BeginNestedStructure(const Schema& schema) override;
void EndNestedStructure() override;

Aws::String GetPayload() const;
Aws::String GetPayload();

private:
struct Impl;
std::unique_ptr<Impl> m_impl;
Aws::UniquePtr<Impl> m_impl;
};

} // namespace schema
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

#include <smithy/client/schema/ShapeSerializer.h>

#include <memory>
#include <aws/core/utils/memory/AWSMemory.h>

namespace smithy {
namespace schema {
Expand Down Expand Up @@ -39,7 +39,7 @@ class QueryShapeSerializer final : public ShapeSerializer {

private:
struct Impl;
std::unique_ptr<Impl> m_impl;
Aws::UniquePtr<Impl> m_impl;
};

} // namespace schema
Expand Down
2 changes: 2 additions & 0 deletions src/aws-cpp-sdk-core/include/smithy/client/schema/Schema.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ enum class ShapeType : uint8_t {
class Schema {
public:
Schema() = default;
Schema(const char* memberName, ShapeType type)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not const Aws::String& memberName? lets avoid using c

: m_type(type), m_memberName(memberName) {}

ShapeType GetType() const { return m_type; }
const char* GetId() const { return m_id; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

#include <smithy/client/schema/ShapeSerializer.h>

#include <memory>
#include <aws/core/utils/memory/AWSMemory.h>

namespace smithy {
namespace schema {
Expand Down Expand Up @@ -39,7 +39,7 @@ class XmlShapeSerializer final : public ShapeSerializer {

private:
struct Impl;
std::unique_ptr<Impl> m_impl;
Aws::UniquePtr<Impl> m_impl;
};

} // namespace schema
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
/**
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0.
*/
#include <aws/core/utils/HashingUtils.h>
#include <smithy/client/schema/JsonShapeSerializer.h>

#include <cassert>

using namespace smithy::schema;
using namespace Aws::Utils;

static const int MAX_DEPTH = 64;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cjson has this set at 1000, we should also likely set this the same. so we avoid any surprises


struct JsonShapeSerializer::Impl {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should probably be a class that has a constructor and fields that are private to ensure encapsulation of the buffer.

Aws::String m_buf;
int m_depth = 0;
bool m_needsComma[MAX_DEPTH] = {};

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

perfer c++ std::array or Aws::Array over c arrays

bool m_isMap[MAX_DEPTH] = {};
bool m_isList[MAX_DEPTH] = {};
const char* m_currentMapKey = nullptr;
bool m_finalized = false;

void WriteCommaIfNeeded() {
if (m_needsComma[m_depth]) {
m_buf += ',';
} else {
m_needsComma[m_depth] = true;
}
}

void WriteKey(const char* key) {
m_buf += '"';
m_buf += key;
m_buf += "\":";
}

void WriteFieldName(const Schema& schema) {
WriteCommaIfNeeded();
if (m_isList[m_depth]) {
return;
}
if (m_depth > 0 && m_isMap[m_depth]) {
WriteKey(m_currentMapKey);
} else {
WriteKey(schema.GetMemberName());
}
}

void BeginStructure(const Schema&) {
m_buf += '{';
m_depth++;
m_needsComma[m_depth] = false;
m_isMap[m_depth] = false;
m_isList[m_depth] = false;
}

void EndStructure() {
m_depth--;
m_buf += '}';
}

void WriteBoolean(const Schema& schema, bool value) {
WriteFieldName(schema);
m_buf += value ? "true" : "false";
}

void WriteInteger(const Schema& schema, int value) {
WriteFieldName(schema);
auto start = m_buf.size();
m_buf.resize(start + 11);
int written = snprintf(&m_buf[start],12,"%d", value);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think this goes for all of the operations but we should stop using snprintf and .resize alltogether. this is a string buffer. you should just use the until to_string https://github.com/aws/aws-sdk-cpp/blob/main/src/aws-cpp-sdk-core/include/aws/core/utils/StringUtils.h#L189-L198 and just append the the string to the buffer, allowing the string implementation to handle the underlying buffer resize not us.

m_buf.resize(start + written);
}

void WriteLong(const Schema& schema, int64_t value) {
WriteFieldName(schema);
auto start = m_buf.size();
m_buf.resize(start+20);
int writter = snprintf(&m_buf[start],21,"%lld", static_cast<long long>(value));
m_buf.resize(start + writter);
}

void WriteDouble(const Schema& schema, double value) {
WriteFieldName(schema);
auto start = m_buf.size();
m_buf.resize(start+32);
int writter = snprintf(&m_buf[start],32,"%f", value);
m_buf.resize(start + writter);
}

void WriteString(const Schema& schema, const Aws::String& value) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so in this case, we need to account for "json escaping strings", and if you dont, crafted json strings can break the string. smithy java extracts this to a utils file called JsonWriteUtils. and in the utils file the do json encoding. we idealliy should have a identical class called JsonWriteUtils that works the same way but is only internally visible to the SDK.

WriteFieldName(schema);
m_buf += '"';
m_buf += value;
m_buf += '"';
}

void WriteTimestamp(const Schema& schema, const DateTime& value) {
WriteFieldName(schema);
auto start = m_buf.size();
m_buf.resize(start+32);
int written = snprintf(&m_buf[start], 32, "%g", value.SecondsWithMSPrecision());
m_buf.resize(start + written);
}

void WriteBlob(const Schema& schema, const ByteBuffer& value) {
WriteFieldName(schema);
m_buf += '"';
m_buf += HashingUtils::Base64Encode(value);
m_buf += '"';
}

void WriteEnum(const Schema& schema, int value) { WriteInteger(schema, value); }

void WriteNull(const Schema& schema) {
WriteFieldName(schema);
m_buf += "null";
}

void BeginList(const Schema& schema, size_t) {
WriteFieldName(schema);
m_buf += '[';
m_depth++;
m_needsComma[m_depth] = false;
m_isMap[m_depth] = false;
m_isList[m_depth] = true;
}

void EndList() {
m_depth--;
m_buf += ']';
}

void BeginMap(const Schema& schema, size_t) {
WriteFieldName(schema);
m_buf += '{';
m_depth++;
m_needsComma[m_depth] = false;
m_isMap[m_depth] = true;
m_isList[m_depth] = false;
}

void WriteMapKey(const Aws::String& key) { m_currentMapKey = key.c_str(); }

void EndMap() {
m_depth--;
m_buf += '}';
}

void BeginNestedStructure(const Schema& schema) {
WriteFieldName(schema);
m_buf += '{';
m_depth++;
m_needsComma[m_depth] = false;
m_isMap[m_depth] = false;
m_isList[m_depth] = false;
}

void EndNestedStructure() {
m_depth--;
m_buf += '}';
}

Aws::String GetPayload() {
assert(!m_finalized);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

assertions are only enabled in debug mode, what happens in release mode? shouldnt we return a Aws::Outcome to represent error?

m_finalized = true;
return std::move(m_buf);
}
};

JsonShapeSerializer::JsonShapeSerializer() : m_impl(Aws::MakeUnique<Impl>("JsonShapeSerializer")) { m_impl->m_buf.reserve(8192); }
JsonShapeSerializer::~JsonShapeSerializer() = default;

void JsonShapeSerializer::BeginStructure(const Schema& schema) { m_impl->BeginStructure(schema); }
void JsonShapeSerializer::EndStructure() { m_impl->EndStructure(); }
void JsonShapeSerializer::WriteBoolean(const Schema& schema, bool value) { m_impl->WriteBoolean(schema, value); }
void JsonShapeSerializer::WriteInteger(const Schema& schema, int value) { m_impl->WriteInteger(schema, value); }
void JsonShapeSerializer::WriteLong(const Schema& schema, int64_t value) { m_impl->WriteLong(schema, value); }
void JsonShapeSerializer::WriteDouble(const Schema& schema, double value) { m_impl->WriteDouble(schema, value); }
void JsonShapeSerializer::WriteString(const Schema& schema, const Aws::String& value) { m_impl->WriteString(schema, value); }
void JsonShapeSerializer::WriteTimestamp(const Schema& schema, const DateTime& value) { m_impl->WriteTimestamp(schema, value); }
void JsonShapeSerializer::WriteBlob(const Schema& schema, const ByteBuffer& value) { m_impl->WriteBlob(schema, value); }
void JsonShapeSerializer::WriteEnum(const Schema& schema, int value) { m_impl->WriteEnum(schema, value); }
void JsonShapeSerializer::WriteNull(const Schema& schema) { m_impl->WriteNull(schema); }
void JsonShapeSerializer::BeginList(const Schema& schema, size_t count) { m_impl->BeginList(schema, count); }
void JsonShapeSerializer::EndList() { m_impl->EndList(); }
void JsonShapeSerializer::BeginMap(const Schema& schema, size_t count) { m_impl->BeginMap(schema, count); }
void JsonShapeSerializer::WriteMapKey(const Aws::String& key) { m_impl->WriteMapKey(key); }
void JsonShapeSerializer::EndMap() { m_impl->EndMap(); }
void JsonShapeSerializer::BeginNestedStructure(const Schema& schema) { m_impl->BeginNestedStructure(schema); }
void JsonShapeSerializer::EndNestedStructure() { m_impl->EndNestedStructure(); }
Aws::String JsonShapeSerializer::GetPayload() { return m_impl->GetPayload(); }
1 change: 1 addition & 0 deletions tests/aws-cpp-sdk-core-tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ file(GLOB UTILS_COMPONENT_REGISTRY_SRC "${CMAKE_CURRENT_SOURCE_DIR}/utils/compon
file(GLOB MONITORING_SRC "${CMAKE_CURRENT_SOURCE_DIR}/monitoring/*.cpp")
file(GLOB SMITHY_TRACING_SRC "${CMAKE_CURRENT_SOURCE_DIR}/smithy/tracing/*.cpp")
file(GLOB SMITHY_CLIENT_SRC "${CMAKE_CURRENT_SOURCE_DIR}/smithy/client/*.cpp")
file(GLOB SMITHY_CLIENT_SRC "${CMAKE_CURRENT_SOURCE_DIR}/smithy/client/schema/*.cpp")
file(GLOB SMITHY_CLIENT_SERIALIZER_SRC "${CMAKE_CURRENT_SOURCE_DIR}/smithy/client/serializer/*.cpp")
file(GLOB SMITHY_CLIENT_FEATURE_SRC "${CMAKE_CURRENT_SOURCE_DIR}/smithy/client/feature/*.cpp")
file(GLOB ENDPOINT_SRC "${CMAKE_CURRENT_SOURCE_DIR}/endpoint/*.cpp")
Expand Down
Loading
Loading