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
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#pragma once

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

namespace smithy {
namespace schema {

class SMITHY_API CborShapeDeserializer final : public ShapeDeserializer {
public:
CborShapeDeserializer(const unsigned char* data, size_t length);
~CborShapeDeserializer();

bool ReadBoolean() override;
int ReadInteger() override;
int64_t ReadLong() override;
float ReadFloat() override;
double ReadDouble() override;
Aws::String ReadString() override;
Aws::Utils::DateTime ReadTimestamp() override;
Aws::Utils::ByteBuffer ReadBlob() override;
int ReadEnum() override;

void BeginStruct() override;
void EndStruct() override;

size_t BeginList() override;
void EndList() override;

size_t BeginMap() override;
void EndMap() override;

Aws::String ReadKey() override;
bool IsBreak() override;
bool IsNull() override;
void ReadNull() override;
void SkipValue() override;

private:
class Impl;
Aws::UniquePtr<Impl> m_impl;
};

} // namespace schema
} // namespace smithy
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#pragma once

#include <aws/core/utils/Array.h>
#include <aws/core/utils/DateTime.h>
#include <aws/core/utils/memory/stl/AWSString.h>
#include <smithy/Smithy_EXPORTS.h>

#include <cstdint>

namespace smithy {
namespace schema {

class SMITHY_API ShapeDeserializer {
public:
virtual ~ShapeDeserializer() = default;

virtual bool ReadBoolean() = 0;
virtual int ReadInteger() = 0;
virtual int64_t ReadLong() = 0;
virtual float ReadFloat() = 0;
virtual double ReadDouble() = 0;
virtual Aws::String ReadString() = 0;
virtual Aws::Utils::DateTime ReadTimestamp() = 0;
virtual Aws::Utils::ByteBuffer ReadBlob() = 0;
virtual int ReadEnum() = 0;

virtual void BeginStruct() = 0;
virtual void EndStruct() = 0;

virtual size_t BeginList() = 0;
virtual void EndList() = 0;

virtual size_t BeginMap() = 0;
virtual void EndMap() = 0;

virtual Aws::String ReadKey() = 0;
virtual bool IsBreak() = 0;
virtual bool IsNull() = 0;
virtual void ReadNull() = 0;
virtual void SkipValue() = 0;
};

} // namespace schema
} // namespace smithy
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
/**
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0.
*/
#include <aws/crt/cbor/Cbor.h>
#include <smithy/client/schema/CborShapeDeserializer.h>

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

class CborShapeDeserializer::Impl {
public:
Impl(const unsigned char* data, size_t length)
: m_decoder(Aws::Crt::ByteCursorFromArray(data, length)) {}

bool ReadBoolean() {
auto val = m_decoder.PopNextBooleanVal();
return val.has_value() ? val.value() : false;
}

int ReadInteger() { return static_cast<int>(ReadLong()); }

int64_t ReadLong() {
auto type = m_decoder.PeekType();
if (!type.has_value()) {
return 0;
}
if (*type == CborType::UInt) {
auto val = m_decoder.PopNextUnsignedIntVal();
return val.has_value() ? static_cast<int64_t>(val.value()) : 0;
}
if (*type == CborType::NegInt) {
auto val = m_decoder.PopNextNegativeIntVal();
return val.has_value() ? static_cast<int64_t>(-(static_cast<int64_t>(val.value()) + 1)) : 0;
}
return 0;
}

float ReadFloat() { return static_cast<float>(ReadDouble()); }

double ReadDouble() {
auto type = m_decoder.PeekType();
if (!type.has_value()) {
return 0.0;
}
if (*type == CborType::Float) {
auto val = m_decoder.PopNextFloatVal();
return val.has_value() ? val.value() : 0.0;
}
// CRT "smallest possible" may encode doubles as integers
return static_cast<double>(ReadLong());
}

Aws::String ReadString() {
auto val = m_decoder.PopNextTextVal();
if (!val.has_value()) {
return {};
}
return Aws::String(reinterpret_cast<const char*>(val->ptr), val->len);
}

DateTime ReadTimestamp() {
auto tag = m_decoder.PopNextTagVal();
(void)tag;
return DateTime(static_cast<double>(ReadLong()));
}

ByteBuffer ReadBlob() {
auto val = m_decoder.PopNextBytesVal();
if (!val.has_value()) {
return {};
}
return ByteBuffer(val->ptr, val->len);
}

int ReadEnum() { return ReadInteger(); }

void BeginStruct() {
auto type = m_decoder.PeekType();
if (type.has_value() && *type == CborType::IndefMapStart) {
m_decoder.ConsumeNextSingleElement();
} else {
m_decoder.PopNextMapStart();
}
}

void EndStruct() {
// For indefinite maps, the break is consumed by the IsBreak/read loop
}

size_t BeginList() {
auto type = m_decoder.PeekType();
if (type.has_value() && *type == CborType::IndefArrayStart) {
m_decoder.ConsumeNextSingleElement();
return 0;
}
auto size = m_decoder.PopNextArrayStart();
return size.has_value() ? static_cast<size_t>(size.value()) : 0;
}

void EndList() {}

size_t BeginMap() {
auto type = m_decoder.PeekType();
if (type.has_value() && *type == CborType::IndefMapStart) {
m_decoder.ConsumeNextSingleElement();
return 0;
}
auto size = m_decoder.PopNextMapStart();
return size.has_value() ? static_cast<size_t>(size.value()) : 0;
}

void EndMap() {}

Aws::String ReadKey() { return ReadString(); }

bool IsBreak() {
auto type = m_decoder.PeekType();
return type.has_value() && *type == CborType::Break;
}

bool IsNull() {
auto type = m_decoder.PeekType();
return type.has_value() && *type == CborType::Null;
}

void ReadNull() { m_decoder.ConsumeNextSingleElement(); }

void SkipValue() { m_decoder.ConsumeNextWholeDataItem(); }

private:
CborDecoder m_decoder;
};

CborShapeDeserializer::CborShapeDeserializer(const unsigned char* data, size_t length)
: m_impl(Aws::MakeUnique<Impl>("CborShapeDeserializer", data, length)) {}
CborShapeDeserializer::~CborShapeDeserializer() = default;

bool CborShapeDeserializer::ReadBoolean() { return m_impl->ReadBoolean(); }
int CborShapeDeserializer::ReadInteger() { return m_impl->ReadInteger(); }
int64_t CborShapeDeserializer::ReadLong() { return m_impl->ReadLong(); }
float CborShapeDeserializer::ReadFloat() { return m_impl->ReadFloat(); }
double CborShapeDeserializer::ReadDouble() { return m_impl->ReadDouble(); }
Aws::String CborShapeDeserializer::ReadString() { return m_impl->ReadString(); }
DateTime CborShapeDeserializer::ReadTimestamp() { return m_impl->ReadTimestamp(); }
ByteBuffer CborShapeDeserializer::ReadBlob() { return m_impl->ReadBlob(); }
int CborShapeDeserializer::ReadEnum() { return m_impl->ReadEnum(); }
void CborShapeDeserializer::BeginStruct() { m_impl->BeginStruct(); }
void CborShapeDeserializer::EndStruct() { m_impl->EndStruct(); }
size_t CborShapeDeserializer::BeginList() { return m_impl->BeginList(); }
void CborShapeDeserializer::EndList() { m_impl->EndList(); }
size_t CborShapeDeserializer::BeginMap() { return m_impl->BeginMap(); }
void CborShapeDeserializer::EndMap() { m_impl->EndMap(); }
Aws::String CborShapeDeserializer::ReadKey() { return m_impl->ReadKey(); }
bool CborShapeDeserializer::IsBreak() { return m_impl->IsBreak(); }
bool CborShapeDeserializer::IsNull() { return m_impl->IsNull(); }
void CborShapeDeserializer::ReadNull() { m_impl->ReadNull(); }
void CborShapeDeserializer::SkipValue() { m_impl->SkipValue(); }
Loading
Loading