blob: 76c5d701c14b2f05600124da25e1f6ef4ad20605 [file] [log] [blame]
// Copyright 2018 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 "peridot/lib/commit_pack/commit_pack.h"
#include <fuchsia/ledger/cloud/c/fidl.h>
#include <lib/fidl/cpp/encoder.h>
#include <lib/fsl/vmo/vector.h>
#include "peridot/lib/convert/convert.h"
using fuchsia::ledger::cloud::SerializedCommit;
using fuchsia::ledger::cloud::SerializedCommits;
namespace cloud_provider {
bool operator==(const CommitPackEntry& lhs, const CommitPackEntry& rhs) {
return lhs.id == rhs.id && lhs.data == rhs.data;
}
bool EncodeCommitPack(std::vector<CommitPackEntry> commits,
CommitPack* commit_pack) {
FXL_DCHECK(commit_pack);
SerializedCommits serialized_commits;
for (auto& commit : commits) {
serialized_commits.commits.push_back(SerializedCommit{
convert::ToArray(commit.id), convert::ToArray(commit.data)});
}
// Serialization of the SerializedCommits in a buffer. In this particular
// case, we do not rely on FIDL encoding being stable: the buffer is simply a
// way to extend the maximum message size, and we expect the buffer to be
// immediately deserialized.
// Caveats: see https://fuchsia-review.googlesource.com/c/fuchsia/+/262309
// TODO(ambre): rewrite this using a more-supported API when available.
fidl::Encoder encoder(fidl::Encoder::NO_HEADER);
// We need to preallocate the size of the structure in the encoder, the rest
// is allocated when the vector is encoded.
encoder.Alloc(sizeof(fuchsia_ledger_cloud_SerializedCommits));
fidl::Encode(&encoder, &serialized_commits, 0);
return fsl::VmoFromVector(encoder.TakeBytes(), &commit_pack->buffer);
}
bool DecodeCommitPack(const CommitPack& commit_pack,
std::vector<CommitPackEntry>* commits) {
FXL_DCHECK(commits);
commits->clear();
std::vector<uint8_t> data;
if (!fsl::VectorFromVmo(commit_pack.buffer, &data)) {
return false;
}
// Deserialization of the SerializedCommits. See the comment in
// EncodeCommitPack for details/caveats.
// TODO(ambre): rewrite this using a supported API when available.
fidl::Message message(fidl::BytePart(data.data(), data.size(), data.size()),
fidl::HandlePart());
const char* error_msg;
zx_status_t status = message.Decode(SerializedCommits::FidlType, &error_msg);
if (status != ZX_OK) {
FXL_LOG(ERROR) << "Decoding invalid CommitPack: " << error_msg;
return false;
}
fidl::Decoder decoder(std::move(message));
SerializedCommits result;
SerializedCommits::Decode(&decoder, &result, 0);
for (auto& commit : result.commits) {
commits->emplace_back();
commits->back().id = convert::ToString(commit.id);
commits->back().data = convert::ToString(commit.data);
}
return true;
}
} // namespace cloud_provider