blob: 63f7168e42758ae5595104f085e3b8fd8e01293d [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/developer/debug/zxdb/expr/pretty_rust_tuple.h"
#include "src/developer/debug/zxdb/expr/format.h"
#include "src/developer/debug/zxdb/expr/format_node.h"
#include "src/developer/debug/zxdb/expr/format_options.h"
#include "src/developer/debug/zxdb/expr/resolve_collection.h"
#include "src/developer/debug/zxdb/symbols/base_type.h"
#include "src/developer/debug/zxdb/symbols/modified_type.h"
#include "src/developer/debug/zxdb/symbols/symbol_data_provider.h"
namespace zxdb {
void PrettyRustTuple::Format(FormatNode* node, const FormatOptions& options,
const fxl::RefPtr<EvalContext>& context, fit::deferred_callback cb) {
auto collection = node->value().type()->As<Collection>();
if (collection->GetSpecialType() == Collection::kRustTupleStruct) {
node->set_description_kind(FormatNode::kRustTupleStruct);
} else {
node->set_description_kind(FormatNode::kRustTuple);
}
// Rust tuple (and tuple struct) symbols have the tuple members encoded as "__0", "__1", etc.
for (const auto& lazy_member : collection->data_members()) {
const DataMember* member = lazy_member.Get()->As<DataMember>();
if (!member)
continue;
// Convert the names to indices "__0" -> 0.
auto name = member->GetAssignedName();
if (name.size() > 2 && name[0] == '_' && name[1] == '_')
name.erase(name.begin(), name.begin() + 2);
// In the error case, still append a child so that the child can have the error associated
// with it.
node->children().push_back(std::make_unique<FormatNode>(
name, ResolveNonstaticMember(context, node->value(), FoundMember(collection, member))));
}
}
PrettyRustTuple::EvalFunction PrettyRustTuple::GetMember(const std::string& getter_name) const {
if (getter_name.empty()) {
return EvalFunction();
}
for (const auto& ch : getter_name) {
if (ch < '0' || ch > '9') {
return EvalFunction();
}
}
return [getter_name](const fxl::RefPtr<EvalContext>& context, const ExprValue& object_value,
EvalCallback cb) {
// Rust tuple members are named __0, __1, etc.
EvalExpressionOn(context, object_value, "__" + getter_name, std::move(cb));
};
}
void PrettyRustZirconStatus::Format(FormatNode* node, const FormatOptions& options,
const fxl::RefPtr<EvalContext>& context,
fit::deferred_callback cb) {
auto collection = node->value().type()->As<Collection>();
if (!collection || collection->GetSpecialType() != Collection::kRustTupleStruct) {
return;
}
node->set_description_kind(FormatNode::kRustTupleStruct);
const auto& members = collection->data_members();
if (members.size() != 1) {
return;
}
if (const DataMember* member = members[0].Get()->As<DataMember>()) {
auto child = std::make_unique<FormatNode>(
"0", ResolveNonstaticMember(context, node->value(), FoundMember(collection, member)));
// The status formatter can return immediately, meaning this node gets printed before this
// function is done, so we have to share the return callback, not just pass it along.
auto shared_cb = std::make_shared<fit::deferred_callback>(std::move(cb));
PrettyZxStatusT status_formatter;
status_formatter.Format(child.get(), options, context,
fit::defer_callback([shared_cb]() mutable {}));
child->set_state(FormatNode::kDescribed);
child->set_source(FormatNode::kDescription);
node->children().push_back(std::move(child));
}
}
} // namespace zxdb