Skip to content
Draft
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
85 changes: 63 additions & 22 deletions src/aws-cpp-sdk-core/include/smithy/client/schema/Schema.h
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
#pragma once

#include <aws/core/utils/memory/stl/AWSString.h>
#include <smithy/Smithy_EXPORTS.h>
#include <smithy/client/schema/TraitMap.h>

#include <cstdint>
#include <initializer_list>
#include <memory>

namespace smithy {
namespace schema {

class SchemaBuilder;

enum class ShapeType : uint8_t {
Boolean,
Byte,
Expand All @@ -34,21 +38,34 @@ enum class ShapeType : uint8_t {
Service
};

class Schema {
// A single trait supplied at construction time. Schemas are immutable once
// built, so traits are attached through the factories and SchemaBuilder rather
// than mutated afterwards.
struct TraitEntry {
const TraitKeyBase& key;
std::shared_ptr<const Trait> value;
};
using TraitList = std::initializer_list<TraitEntry>;

// Abstract, immutable description of a shape. Concrete variants (scalar, member,
// structure/list/map/union root) live in the translation unit and are reached
// only through the factories below and SchemaBuilder. Serializers and
// deserializers hold a Schema only by const reference.
class SMITHY_API Schema {
public:
Schema() = default;
Schema(const Aws::String& memberName, ShapeType type) : m_type(type), m_memberName(memberName) {}
virtual ~Schema() = default;

ShapeType GetType() const { return m_type; }
const char* GetId() const { return m_id; }
Aws::String GetMemberName() const { return m_memberName; }
int GetMemberIndex() const { return m_memberIndex; }
bool IsMember() const { return !m_memberName.empty(); }
virtual ShapeType GetType() const = 0;
virtual const char* GetId() const = 0;

const Schema* GetMember(const char* name) const;
const Schema* GetMember(int index) const;
virtual bool IsMember() const { return false; }
virtual Aws::String GetMemberName() const { return {}; }
virtual int GetMemberIndex() const { return 0; }
virtual const Schema* GetMemberTarget() const { return nullptr; }

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.

returning a pointer, especially when the default case is nullptr is sketchy, lets return a optoinal of a shared pointer. to represent that it is missing, and to lifetime extend the pointer being returned.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

okay


uint16_t GetMemberCount() const { return m_memberCount; }
virtual const Schema* GetMember(const char* /*name*/) const { return nullptr; }
virtual const Schema* GetMember(int /*index*/) const { return nullptr; }
virtual uint16_t GetMemberCount() const { return 0; }

template <typename T>
std::shared_ptr<const T> GetTrait(const TraitKey<T>& key) const {
Expand All @@ -57,19 +74,43 @@ class Schema {

bool HasTrait(const TraitKeyBase& key) const { return m_traits.Has(key); }

Schema& SetTrait(const TraitKeyBase& key, std::shared_ptr<const Trait> trait) {
m_traits.Set(key, std::move(trait));
return *this;
}
// Scalar factories. No members, so no builder is needed.
static std::shared_ptr<const Schema> CreateBoolean(const char* id, TraitList traits = {});
static std::shared_ptr<const Schema> CreateByte(const char* id, TraitList traits = {});
static std::shared_ptr<const Schema> CreateShort(const char* id, TraitList traits = {});
static std::shared_ptr<const Schema> CreateInteger(const char* id, TraitList traits = {});
static std::shared_ptr<const Schema> CreateLong(const char* id, TraitList traits = {});
static std::shared_ptr<const Schema> CreateFloat(const char* id, TraitList traits = {});
static std::shared_ptr<const Schema> CreateDouble(const char* id, TraitList traits = {});
static std::shared_ptr<const Schema> CreateBigInteger(const char* id, TraitList traits = {});
static std::shared_ptr<const Schema> CreateBigDecimal(const char* id, TraitList traits = {});
static std::shared_ptr<const Schema> CreateString(const char* id, TraitList traits = {});
static std::shared_ptr<const Schema> CreateEnum(const char* id, TraitList traits = {});
static std::shared_ptr<const Schema> CreateIntEnum(const char* id, TraitList traits = {});
static std::shared_ptr<const Schema> CreateBlob(const char* id, TraitList traits = {});
static std::shared_ptr<const Schema> CreateTimestamp(const char* id, TraitList traits = {});
static std::shared_ptr<const Schema> CreateDocument(const char* id, TraitList traits = {});

// Standalone member node targeting an (otherwise empty) shape of targetType.
// Convenience for the positional serializer/deserializer API, where a caller
// hands members one at a time rather than driving them off a parent shape.
static std::shared_ptr<const Schema> CreateMember(const char* name, ShapeType targetType, TraitList traits = {});

// Aggregate builders. Shapes that carry members are assembled incrementally.
static SchemaBuilder StructureBuilder(const char* id, TraitList traits = {});
static SchemaBuilder UnionBuilder(const char* id, TraitList traits = {});
static SchemaBuilder ListBuilder(const char* id, TraitList traits = {});
static SchemaBuilder MapBuilder(const char* id, TraitList traits = {});

protected:
Schema() = default;
explicit Schema(TraitList traits);

private:
const char* m_id = nullptr;
ShapeType m_type = ShapeType::Structure;
Aws::String m_memberName;
int m_memberIndex = 0;
const Schema* m_members = nullptr;
uint16_t m_memberCount = 0;
TraitMap m_traits;

private:
Schema(const Schema&) = delete;
Schema& operator=(const Schema&) = delete;
};

} // namespace schema
Expand Down
40 changes: 40 additions & 0 deletions src/aws-cpp-sdk-core/include/smithy/client/schema/SchemaBuilder.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#pragma once

#include <aws/core/utils/memory/AWSMemory.h>
#include <smithy/Smithy_EXPORTS.h>
#include <smithy/client/schema/Schema.h>

#include <memory>

namespace smithy {
namespace schema {

// Assembles a shape that carries members (structure, union, list, map). Members
// may target shapes that are already built, or other builders that are not yet
// built to describe recursive shapes. Once Build() is called the builder is
// spent. Move-only; obtained from Schema::StructureBuilder and friends.
class SMITHY_API SchemaBuilder {
public:
~SchemaBuilder();

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.

nit: needs virutal

SchemaBuilder(SchemaBuilder&&) noexcept;
SchemaBuilder& operator=(SchemaBuilder&&) noexcept;

SchemaBuilder& PutMember(const char* name, std::shared_ptr<const Schema> target, TraitList traits = {});
SchemaBuilder& PutMember(const char* name, SchemaBuilder& target, TraitList traits = {});

std::shared_ptr<const Schema> Build();

private:
friend class Schema;
class SchemaBuilderImpl;

explicit SchemaBuilder(Aws::UniquePtr<SchemaBuilderImpl> impl);

Aws::UniquePtr<SchemaBuilderImpl> m_impl;

SchemaBuilder(const SchemaBuilder&) = delete;
SchemaBuilder& operator=(const SchemaBuilder&) = delete;
};

} // namespace schema
} // namespace smithy
Loading
Loading