blob: 001ca34de7a7637c0c4e9760a7d7413fc4e35d6b [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 <lib/fit/bridge.h>
#include <lib/inspect/cpp/reader.h>
#include <lib/inspect/service/cpp/reader.h>
using inspect::internal::SnapshotTree;
namespace inspect {
namespace {
fit::promise<SnapshotTree> SnapshotTreeFromTree(fuchsia::inspect::TreePtr tree) {
fit::bridge<fuchsia::inspect::TreeContent> content_bridge;
fuchsia::inspect::TreeNameIteratorPtr child_ptr;
tree->GetContent(content_bridge.completer.bind());
tree->ListChildNames(child_ptr.NewRequest());
return fit::join_promises(content_bridge.consumer.promise_or(fit::error()),
ReadAllChildNames(std::move(child_ptr)))
.and_then([tree = std::move(tree)](
std::tuple<fit::result<fuchsia::inspect::TreeContent>,
fit::result<std::vector<std::string>>>& result) mutable
-> fit::promise<SnapshotTree> {
auto& content = std::get<0>(result);
auto& children = std::get<1>(result);
SnapshotTree ret;
if (!content.is_ok() || !children.is_ok() ||
Snapshot::Create(content.take_value().buffer().vmo, &ret.snapshot)) {
return fit::make_result_promise<SnapshotTree>(fit::error());
}
// Sequence all child reads for depth-first traversal.
fit::sequencer seq;
std::vector<fit::promise<SnapshotTree>> child_promises;
for (const auto& child_name : children.value()) {
fuchsia::inspect::TreePtr child_ptr;
tree->OpenChild(child_name, child_ptr.NewRequest());
child_promises.emplace_back(SnapshotTreeFromTree(std::move(child_ptr)).wrap_with(seq));
}
return join_promise_vector(std::move(child_promises))
.and_then(
[ret = std::move(ret), tree = std::move(tree), children = children.take_value()](
std::vector<fit::result<SnapshotTree>>& results) mutable {
ZX_ASSERT(children.size() == results.size());
for (size_t i = 0; i < results.size(); i++) {
if (results[i].is_ok()) {
ret.children.emplace(std::move(children[i]), results[i].take_value());
}
}
return fit::ok(std::move(ret));
});
return fit::make_result_promise<SnapshotTree>(fit::error());
});
}
} // namespace
fit::promise<std::vector<std::string>> ReadAllChildNames(
fuchsia::inspect::TreeNameIteratorPtr iterator) {
fit::bridge<std::vector<std::string>> bridge;
iterator->GetNext(bridge.completer.bind());
return bridge.consumer.promise_or(fit::error())
.then([it = std::move(iterator)](fit::result<std::vector<std::string>>& result) mutable
-> fit::promise<std::vector<std::string>> {
if (!result.is_ok() || result.value().size() == 0) {
return fit::make_ok_promise(std::vector<std::string>());
}
return ReadAllChildNames(std::move(it))
.then(
[ret = result.take_value()](fit::result<std::vector<std::string>>& result) mutable {
if (result.is_ok()) {
for (auto& v : result.take_value()) {
ret.emplace_back(std::move(v));
}
}
return fit::make_ok_promise(std::move(ret));
});
});
}
fit::promise<Hierarchy> ReadFromTree(fuchsia::inspect::TreePtr tree) {
return SnapshotTreeFromTree(std::move(tree)).and_then(internal::ReadFromSnapshotTree);
}
} // namespace inspect