blob: 8114bb79a5b4e5842b23a9ff5315f650d64145d6 [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/modular/bin/sessionmgr/storage/annotation_xdr.h"
#include "src/lib/fsl/vmo/strings.h"
#include "src/modular/lib/base64url/base64url.h"
namespace modular {
// Serialization and deserialization of fuchsia::modular::Annotation
// to and from JSON.
namespace {
std::vector<uint8_t> BytesFromBase64(const std::string& base64) {
std::string decoded;
if (!base64url::Base64UrlDecode(base64, &decoded)) {
FXL_LOG(ERROR) << "Unable to decode from Base64";
return std::vector<uint8_t>{};
}
auto decoded_data = reinterpret_cast<const uint8_t*>(decoded.data());
return std::vector<uint8_t>(decoded_data, decoded_data + decoded.length());
}
std::string BytesToBase64(const std::vector<uint8_t>& bytes) {
return base64url::Base64UrlEncode({reinterpret_cast<const char*>(bytes.data()), bytes.size()});
}
void XdrAnnotationValue_v0(XdrContext* const xdr, fuchsia::modular::AnnotationValue* const data) {
static constexpr char kTag[] = "@tag";
static constexpr char kValue[] = "@value";
static constexpr char kTextTag[] = "text";
static constexpr char kBytesTag[] = "bytes";
static constexpr char kBufferTag[] = "buffer";
switch (xdr->op()) {
case XdrOp::FROM_JSON: {
std::string tag;
xdr->Field(kTag, &tag);
if (tag == kTextTag) {
std::string text;
xdr->Field(kValue, &text);
data->set_text(std::move(text));
} else if (tag == kBytesTag) {
std::string bytes_base64;
xdr->Field(kValue, &bytes_base64);
data->set_bytes(BytesFromBase64(bytes_base64));
} else if (tag == kBufferTag) {
std::string buffer_base64;
xdr->Field(kValue, &buffer_base64);
std::string decoded;
if (!base64url::Base64UrlDecode(buffer_base64, &decoded)) {
FXL_LOG(ERROR) << "Unable to decode buffer value from Base64";
}
fuchsia::mem::Buffer buffer{};
if (!fsl::VmoFromString(decoded, &buffer)) {
FXL_LOG(ERROR)
<< "Unable to convert buffer VMO to string; annotation value will be empty";
}
data->set_buffer(std::move(buffer));
} else {
FXL_LOG(ERROR) << "XdrAnnotationValue_v0 FROM_JSON unknown tag: " << tag;
}
break;
}
case XdrOp::TO_JSON: {
std::string tag;
switch (data->Which()) {
case fuchsia::modular::AnnotationValue::Tag::kText: {
tag = kTextTag;
std::string text = data->text();
xdr->Field(kValue, &text);
break;
}
case fuchsia::modular::AnnotationValue::Tag::kBytes: {
tag = kBytesTag;
std::string bytes_base64 = BytesToBase64(data->bytes());
xdr->Field(kValue, &bytes_base64);
break;
}
case fuchsia::modular::AnnotationValue::Tag::kBuffer: {
tag = kBufferTag;
std::string buffer;
if (!fsl::StringFromVmo(data->buffer(), &buffer)) {
FXL_LOG(ERROR)
<< "Unable to convert buffer VMO to string; annotation value will be empty";
}
auto buffer_base64 = base64url::Base64UrlEncode(buffer);
xdr->Field(kValue, &buffer_base64);
break;
}
default:
case fuchsia::modular::AnnotationValue::Tag::kUnknown: {
FXL_LOG(ERROR) << "XdrAnnotation_v0 TO_JSON unknown tag: "
<< static_cast<int>(data->Which());
break;
}
}
xdr->Field(kTag, &tag);
break;
}
}
}
void XdrAnnotation_v0(XdrContext* const xdr, fuchsia::modular::Annotation* const data) {
xdr->Field("key", &data->key);
xdr->Field("value", &data->value, XdrAnnotationValue_v0);
}
} // namespace
void XdrAnnotation(XdrContext* const xdr, fuchsia::modular::Annotation* const data) {
XdrAnnotation_v0(xdr, data);
}
} // namespace modular