// 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/format.h"

#include <lib/syslog/cpp/macros.h>

#include "src/developer/debug/zxdb/common/adapters.h"
#include "src/developer/debug/zxdb/common/string_util.h"
#include "src/developer/debug/zxdb/expr/eval_context.h"
#include "src/developer/debug/zxdb/expr/expr.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/pretty_type_manager.h"
#include "src/developer/debug/zxdb/expr/resolve_array.h"
#include "src/developer/debug/zxdb/expr/resolve_collection.h"
#include "src/developer/debug/zxdb/expr/resolve_ptr_ref.h"
#include "src/developer/debug/zxdb/expr/resolve_variant.h"
#include "src/developer/debug/zxdb/symbols/arch.h"
#include "src/developer/debug/zxdb/symbols/array_type.h"
#include "src/developer/debug/zxdb/symbols/base_type.h"
#include "src/developer/debug/zxdb/symbols/collection.h"
#include "src/developer/debug/zxdb/symbols/dwarf_tag.h"
#include "src/developer/debug/zxdb/symbols/enumeration.h"
#include "src/developer/debug/zxdb/symbols/inherited_from.h"
#include "src/developer/debug/zxdb/symbols/member_ptr.h"
#include "src/developer/debug/zxdb/symbols/modified_type.h"
#include "src/developer/debug/zxdb/symbols/symbol_data_provider.h"
#include "src/developer/debug/zxdb/symbols/variant.h"
#include "src/developer/debug/zxdb/symbols/variant_part.h"
#include "src/lib/fxl/strings/string_printf.h"

namespace zxdb {

namespace {

using NumFormat = FormatOptions::NumFormat;

// Returns true if the base type is some kind of number such that the NumFormat of the format
// options should be applied.
bool IsNumericBaseType(int base_type) {
  return base_type == BaseType::kBaseTypeSigned || base_type == BaseType::kBaseTypeUnsigned ||
         base_type == BaseType::kBaseTypeBoolean || base_type == BaseType::kBaseTypeFloat ||
         base_type == BaseType::kBaseTypeSignedChar ||
         base_type == BaseType::kBaseTypeUnsignedChar || base_type == BaseType::kBaseTypeUTF;
}

// Returns true if the given type (assumed to be a pointer) is a pointer to a function (but NOT a
// member function).
bool IsPointerToFunction(const ModifiedType* pointer) {
  FX_DCHECK(pointer->tag() == DwarfTag::kPointerType);
  return !!pointer->modified().Get()->As<FunctionType>();
}

void FormatBoolean(FormatNode* node) {
  uint64_t int_val = 0;
  Err err = node->value().PromoteTo64(&int_val);
  if (err.has_error())
    node->set_err(err);
  else if (int_val)
    node->set_description("true");
  else
    node->set_description("false");
}

void FormatFloat(FormatNode* node) {
  const ExprValue& value = node->value();
  switch (node->value().data().size()) {
    case sizeof(float):
      node->set_description(fxl::StringPrintf("%g", value.GetAs<float>()));
      break;
    case sizeof(double):
      node->set_description(fxl::StringPrintf("%g", value.GetAs<double>()));
      break;
    default:
      node->set_err(Err(
          fxl::StringPrintf("Unknown float of size %d", static_cast<int>(value.data().size()))));
      break;
  }
}

void FormatSignedInt(FormatNode* node) {
  int64_t int_val = 0;
  Err err = node->value().PromoteTo64(&int_val);
  if (err.has_error())
    node->set_err(err);
  else
    node->set_description(fxl::StringPrintf("%" PRId64, int_val));
}

void FormatUnsignedInt(FormatNode* node, const FormatOptions& options) {
  // All > 64-bit output needs a separate code path since they can't be printf'ed. We only ever
  // bother to output this as 0-padded hex. This could be enhanced in the future, and the hex and
  // bin output already supports 128-bit output if needed.
  if (node->value().data().size() > sizeof(uint64_t)) {
    // This assumes little-endian.
    std::string desc = "0x";
    for (uint8_t b : Reversed(node->value().data().bytes()))
      desc.append(fxl::StringPrintf("%02x", b));
    node->set_description(std::move(desc));
    return;
  }

  // This formatter handles unsigned, binary, and hex output.
  uint64_t int_val = 0;
  Err err = node->value().PromoteTo64(&int_val);
  if (err.has_error()) {
    node->set_err(err);
  } else if (options.num_format == NumFormat::kBin) {
    int pad_to = options.zero_pad_hex_bin ? node->value().data().size() * 8 : 0;
    // It might be nice to use a language-specific digits separator here ('_' for Rust) but the
    // source language information isn't easily avilable at this point.
    node->set_description(to_bin_string(int_val, pad_to, true, '\''));
  } else if (options.num_format == NumFormat::kHex) {
    int pad_to = options.zero_pad_hex_bin ? node->value().data().size() * 2 : 0;
    node->set_description(to_hex_string(int_val, pad_to));
  } else {
    node->set_description(std::to_string(int_val));
  }
}

// Returns true if the given symbol points to a character type that would appear in a pretty-printed
// string.
bool IsCharacterType(const fxl::RefPtr<EvalContext>& eval_context, const Type* type) {
  if (!type)
    return false;
  fxl::RefPtr<Type> concrete = eval_context->GetConcreteType(type);

  // Expect a 1-byte character type.
  // TODO(brettw) handle Unicode.
  if (concrete->byte_size() != 1)
    return false;
  const BaseType* base_type = concrete->As<BaseType>();
  if (!base_type)
    return false;

  return base_type->base_type() == BaseType::kBaseTypeSignedChar ||
         base_type->base_type() == BaseType::kBaseTypeUnsignedChar;
}

void FormatChar(FormatNode* node) {
  // Just take the first byte for all char.
  // TODO(brettw) handle unicode, etc.
  if (node->value().data().empty()) {
    node->set_err(Err("Invalid char type"));
    return;
  }
  std::string str;
  str.push_back('\'');
  AppendCEscapedChar(node->value().data().bytes()[0], &str);
  str.push_back('\'');
  node->set_description(std::move(str));
}

void FormatEnum(FormatNode* node, const Enumeration* enum_type, const FormatOptions& options) {
  // Get the value out casted to a uint64.
  Err err;
  uint64_t numeric_value;
  if (enum_type->is_signed()) {
    int64_t signed_value;
    err = node->value().PromoteTo64(&signed_value);
    if (!err.has_error())
      numeric_value = static_cast<uint64_t>(signed_value);
  } else {
    err = node->value().PromoteTo64(&numeric_value);
  }
  if (err.has_error()) {
    node->set_err(err);
    return;
  }

  // When the output is marked for a specific numeric type, always skip name lookup and output the
  // numeric value below instead.
  if (options.num_format == NumFormat::kDefault) {
    const auto& map = enum_type->values();
    auto found = map.find(numeric_value);
    if (found != map.end()) {
      // Got the enum value string.
      node->set_description(found->second);
      return;
    }
    // Not found, fall through to numeric formatting.
  }

  // Invalid enum values of explicitly overridden numeric formatting gets printed as a number.
  // Be explicit about the number formatting since the enum won't be a BaseType.
  FormatOptions modified_opts = options;
  if (modified_opts.num_format == NumFormat::kDefault)
    modified_opts.num_format = enum_type->is_signed() ? NumFormat::kSigned : NumFormat::kUnsigned;
  FormatNumericNode(node, modified_opts);
}

// Rust enums will resolve to a different type. We put the resolved type in a child of this node.
// As with references, this is not the best presentation for a GUI. See FormatReference() for
// some thoughts on how this could be improved.
//
// The active variant will have a set of data members of which only one will be used. It will refer
// to a collection which will have the set of members. This structure will vary according to the
// type of enum:
//   EnumWithNoValue
//       The struct will have no members.
//   OneValue(u32)
//       The struct will have one member named __0
//   Tuple(u32, u32, etc.)
//       The struct will have two values, __0 and __1, etc.
//   Struct{x:u32, y:u32}
//       The struct will have "x" and "y" members.
void FormatRustEnum(FormatNode* node, const Collection* coll, const FormatOptions& options,
                    const fxl::RefPtr<EvalContext>& eval_context) {
  node->set_description_kind(FormatNode::kRustEnum);

  const VariantPart* variant_part = coll->variant_part().Get()->As<VariantPart>();
  if (!variant_part) {
    node->set_err(Err("Missing variant part for Rust enum."));
    return;
  }

  fxl::RefPtr<Variant> variant;
  Err err = ResolveVariant(eval_context, node->value(), coll, variant_part, &variant);
  if (err.has_error()) {
    node->set_err(err);
    return;
  }

  // Add each variant data member as a child of this node. In Rust we expect exactly one but it
  // can't hurt to be general.
  std::string enum_name;
  for (const auto& lazy_member : variant->data_members()) {
    const DataMember* member = lazy_member.Get()->As<DataMember>();
    if (!member)
      continue;

    // Save the first member's name to be the name of the whole enum, even if there are no data
    // members. Normally there will be exactly one.
    if (enum_name.empty())
      enum_name = member->GetAssignedName();

    // In the error case, still append a child so that the child can have the error associated with
    // it. Note that Rust enums are never static nor virtual so we can use the synchronous variant.
    node->children().push_back(std::make_unique<FormatNode>(
        member->GetAssignedName(),
        ResolveNonstaticMember(eval_context, node->value(), FoundMember(coll, member))));
  }

  // Name for the whole node.
  node->set_description(enum_name);
}

void FormatCollection(FormatNode* node, const Collection* coll, const FormatOptions& options,
                      const fxl::RefPtr<EvalContext>& eval_context) {
  if (coll->is_declaration()) {
    // Sometimes a value will have a type that's a forward declaration and we couldn't resolve its
    // concrete type. Print an error instead of "{}".
    node->set_err(Err("No definition."));
    return;
  }

  // Special-cases of collections.
  if (coll->GetSpecialType() == Collection::kRustEnum) {
    FormatRustEnum(node, coll, options, std::move(eval_context));
    return;
  }

  // Base classes.
  for (const auto& lazy_inherited : coll->inherited_from()) {
    const InheritedFrom* inherited = lazy_inherited.Get()->As<InheritedFrom>();
    if (!inherited)
      continue;

    auto from_coll = eval_context->GetConcreteTypeAs<Collection>(inherited->from());
    if (!from_coll)
      continue;

    // Some base classes are empty. Only show if this base class or any of its base classes have
    // member values.
    VisitResult has_members_result =
        VisitClassHierarchy(from_coll.get(), [eval_context](const InheritancePath& path) {
          auto base_coll = eval_context->GetConcreteTypeAs<Collection>(path.base());
          if (!base_coll)
            return VisitResult::kContinue;  // No concrete base class, skip.

          if (base_coll->data_members().empty())
            return VisitResult::kContinue;
          return VisitResult::kDone;
        });
    if (has_members_result == VisitResult::kContinue)
      continue;

    // Derived class nodes are named by the type of the base class.
    std::unique_ptr<FormatNode> base_class_node = std::make_unique<FormatNode>(
        from_coll->GetFullName(), ResolveInherited(eval_context, node->value(), inherited));
    base_class_node->set_child_kind(FormatNode::kBaseClass);
    node->children().push_back(std::move(base_class_node));
  }

  // Data members.
  for (const auto& lazy_member : coll->data_members()) {
    const DataMember* member = lazy_member.Get()->As<DataMember>();
    if (!member)
      continue;

    if (member->artificial())
      continue;  // Skip compiler-generated data.

    // Skip static data members. This could potentially be revisited. This generally gives
    // duplicated and uninteresting data in the view, and the user can still explicitly type the
    // name if desired.
    //
    // To implement we should probably append a FormatNode with a lambda that gets the right
    // value. It can be asynchronously expanded layer. That way this function doesn't need to
    // handle any asynchronous state.
    if (member->is_external())
      continue;

    node->children().push_back(std::make_unique<FormatNode>(
        member->GetAssignedName(),
        ResolveNonstaticMember(eval_context, node->value(), FoundMember(coll, member))));
  }

  node->set_description_kind(FormatNode::kCollection);
}

// For now a reference is formatted like a pointer where the outer node is the address, and the
// inner node is the "dereferenced" value. This is nice because it keeps the formatting code
// synchronous, while only the value resolution (in the child node) needs to be asynchronous.
//
// If this is put into a GUI, we'll want the reference value to be in the main description and not
// have any children. Visual Studio shows references the same as if it was a value which is probably
// the correct behavior.
//
// To do this we'll likely want to add another ExprValue to the FormatNode (maybe it's in a
// std::optional?) that contains the "resolved value" of the node. This would also be useful for
// Rust enums.
void FormatReference(FormatNode* node, const FormatOptions& options,
                     const fxl::RefPtr<EvalContext>& eval_context) {
  node->set_description_kind(FormatNode::kReference);

  Err err = node->value().EnsureSizeIs(kTargetPointerSize);
  if (err.has_error()) {
    node->set_err(err);
    return;
  }

  // The address goes in the description (see note above).
  node->set_description(to_hex_string(node->value().GetAs<TargetPointer>()));

  auto deref_node = std::make_unique<FormatNode>(
      std::string(),
      [ref = node->value()](const fxl::RefPtr<EvalContext>& context,
                            fit::callback<void(const Err& err, ExprValue value)> cb) {
        EnsureResolveReference(context, ref, ErrOrValue::FromPairCallback(std::move(cb)));
      });
  deref_node->set_child_kind(FormatNode::kPointerExpansion);
  node->children().push_back(std::move(deref_node));
}

void FormatFunctionPointer(FormatNode* node, const FormatOptions& options,
                           const fxl::RefPtr<EvalContext>& eval_context) {
  node->set_description_kind(FormatNode::kFunctionPointer);

  Err err = node->value().EnsureSizeIs(kTargetPointerSize);
  if (err.has_error()) {
    node->set_err(err);
    return;
  }

  TargetPointer address = node->value().GetAs<TargetPointer>();
  if (address == 0) {
    // Special-case null pointers. Don't bother trying to decode the address.
    node->set_description("0x0");
    return;
  }

  // Allow overrides for the number format. Normally one would expect to provide a hex override to
  // get the address rather than the resolved
  // function name.
  if (options.num_format != NumFormat::kDefault) {
    FormatNumericNode(node, options);
    return;
  }

  // Try to symbolize the function being pointed to.
  Location loc = eval_context->GetLocationForAddress(address);
  std::string function_name;
  if (loc.symbol()) {
    if (const Function* func = loc.symbol().Get()->As<Function>())
      function_name = func->GetFullName();
  }
  if (function_name.empty()) {
    // No function name, just print out the address.
    node->set_description(to_hex_string(address));
  } else {
    node->set_description("&" + function_name);
  }
}

void FormatMemberPtr(FormatNode* node, const MemberPtr* type, const FormatOptions& options,
                     const fxl::RefPtr<EvalContext>& eval_context) {
  const Type* container_type = type->container_type().Get()->As<Type>();
  const Type* pointed_to_type = type->member_type().Get()->As<Type>();
  if (!container_type || !pointed_to_type) {
    node->set_err(Err("Missing symbol information."));
    return;
  }

  if (const FunctionType* func = pointed_to_type->As<FunctionType>()) {
    // Pointers to member functions can be handled just like regular function pointers.
    FormatFunctionPointer(node, options, eval_context);
  } else {
    // Pointers to data.
    node->set_description_kind(FormatNode::kOther);
    if (Err err = node->value().EnsureSizeIs(kTargetPointerSize); err.has_error()) {
      node->set_err(err);
      return;
    }

    // The address goes in the description.
    //
    // TODO(brettw) it would be nice if this interrogated the type and figured out the name of the
    // member being pointed to. The address is not very helpful.
    node->set_description(to_hex_string(node->value().GetAs<TargetPointer>()));
  }
}

void FormatCharPointer(FormatNode* node, const Type* char_type, const FormatOptions& options,
                       const fxl::RefPtr<EvalContext>& eval_context, fit::deferred_callback cb) {
  node->set_description_kind(FormatNode::kString);

  // Extracts the pointer and calls the general "char*" formatter.
  if (node->value().data().size() != kTargetPointerSize) {
    node->set_err(Err("Bad pointer data."));
    return;
  }
  FormatCharPointerNode(node, node->value().GetAs<TargetPointer>(), char_type, std::nullopt,
                        options, eval_context, std::move(cb));
}

// Attempts to format arrays, char arrays, and char pointers. Because these are many different types
// this is handled by a separate helper function.
//
// Returns true if the node was formatted by this function. If the operation is asynchronous the
// callback will be moved from to defer it until the async operation is complete.
//
// A false return value means this was not an array or a string and other types of formatting should
// be attempted. The callback will be unmodified.
bool TryFormatArrayOrString(FormatNode* node, const Type* type, const FormatOptions& options,
                            const fxl::RefPtr<EvalContext>& eval_context,
                            fit::deferred_callback& cb) {
  FX_DCHECK(type == type->StripCVT());

  if (type->tag() == DwarfTag::kPointerType) {
    // Any pointer type (we only char about char*).
    const ModifiedType* modified = type->As<ModifiedType>();
    if (!modified)
      return false;

    const Type* char_type = modified->modified().Get()->As<Type>();
    if (IsCharacterType(eval_context, char_type)) {
      FormatCharPointer(node, char_type, options, eval_context, std::move(cb));
      return true;
    }
    return false;  // All other pointer types are unhandled.
  } else if (type->tag() == DwarfTag::kArrayType) {
    // Any array type with a known size (we care about both).
    const ArrayType* array = type->As<ArrayType>();
    if (!array)
      return false;

    if (!array->num_elts()) {
      // Unknown array size, see ArrayType header for what this means. Nothing to do in this case.
      node->SetDescribedError(Err("Array with unknown size, use syntax 'array@size' to specify."));
      return true;
    }

    auto value_type = eval_context->GetConcreteType(array->value_type());
    if (!value_type)
      return false;

    if (IsCharacterType(eval_context, value_type.get())) {
      size_t length = *array->num_elts();
      bool truncated = false;
      if (length > options.max_array_size) {
        length = options.max_array_size;
        truncated = true;
      }
      FormatCharArrayNode(node, value_type, node->value().data().bytes().data(), length, true,
                          truncated);
    } else {
      FormatArrayNode(node, node->value(), *array->num_elts(), options, eval_context,
                      std::move(cb));
    }
    return true;
  }
  return false;
}

// Unspecified types are normally nullptr_t and print as a number (probably 0x0).
void FormatUnspecified(FormatNode* node) {
  node->set_description_kind(FormatNode::kOther);

  uint64_t unspecified_value = 0;
  if (node->value().PromoteTo64(&unspecified_value).has_error())
    node->set_description("<unspecified>");
  else
    node->set_description(to_hex_string(unspecified_value));
}

// Given a node with a value already filled, fills the description.
void FillFormatNodeDescriptionFromValue(FormatNode* node, const FormatOptions& options,
                                        const fxl::RefPtr<EvalContext>& context,
                                        fit::deferred_callback cb) {
  FX_DCHECK(node->state() != FormatNode::kUnevaluated);
  if (node->state() == FormatNode::kEmpty || node->err().has_error()) {
    node->set_state(FormatNode::kDescribed);
    return;
  }

  // All code paths below convert to "described" state.
  node->set_state(FormatNode::kDescribed);
  node->set_description(std::string());
  node->set_description_kind(FormatNode::kNone);
  node->children().clear();
  node->set_err(Err());

  // Format type name.
  if (!node->value().type()) {
    node->set_err(Err("No type"));
    return;
  }
  node->set_type(node->value().type()->GetFullName());

  // Check for pretty-printers. This also happens again below if the type changed.
  if (options.enable_pretty_printing &&
      context->GetPrettyTypeManager().Format(node, node->value().type(), options, context, cb))
    return;

  // Trim "const", "volatile", etc. and follow typedef and using for the type checking below.
  //
  // Always use this variable below instead of value.type().
  fxl::RefPtr<Type> type = context->GetConcreteType(node->value().type());

  // Anything that's not a collection must be completely known for formatting. Collection resolution
  // can handle some members that are optimized out but some not.
  if (const Collection* coll = type->As<Collection>(); !coll && !node->value().data().all_valid()) {
    node->set_err(Err::OptimizedOut());
    return;
  }

  // Check for pretty-printers again now that we've resolved concrete types. Either the source or
  // the destination of a typedef could have a pretty-printer.
  if (options.enable_pretty_printing && type.get() != node->value().type() &&
      context->GetPrettyTypeManager().Format(node, type.get(), options, context, cb))
    return;

  // Arrays and strings.
  if (TryFormatArrayOrString(node, type.get(), options, context, cb))
    return;

  if (const ModifiedType* modified_type = type->As<ModifiedType>()) {
    // Modified types (references were handled above).
    switch (modified_type->tag()) {
      case DwarfTag::kPointerType:
        // Function pointers need special handling.
        if (IsPointerToFunction(modified_type))
          FormatFunctionPointer(node, options, context);
        else
          FormatPointerNode(node, node->value(), options);
        break;
      case DwarfTag::kReferenceType:
      case DwarfTag::kRvalueReferenceType:
        FormatReference(node, options, context);
        break;
      default:
        node->set_err(Err("Unhandled type modifier 0x%x, please file a bug.",
                          static_cast<unsigned>(modified_type->tag())));
        break;
    }
  } else if (const BaseType* base_type = type->As<BaseType>()) {
    if (IsNumericBaseType(node->value().GetBaseType())) {
      // Numeric types.
      FormatNumericNode(node, options);
    } else if (base_type->base_type() == BaseType::kBaseTypeNone) {
      // Special encoding for "void".
      node->set_description("void");
      node->set_description_kind(FormatNode::kOther);
    } else {
      node->set_err(Err("Unsupported base type %d.", base_type->base_type()));
    }
  } else if (const MemberPtr* member_ptr = type->As<MemberPtr>()) {
    // Pointers to class/struct members.
    FormatMemberPtr(node, member_ptr, options, context);
  } else if (const FunctionType* func = type->As<FunctionType>()) {
    // Functions. These don't have a direct C++ equivalent without being
    // modified by a "pointer". Assume these act like pointers to functions.
    FormatFunctionPointer(node, options, context);
  } else if (const Enumeration* enum_type = type->As<Enumeration>()) {
    // Enumerations.
    FormatEnum(node, enum_type, options);
  } else if (const Collection* coll = type->As<Collection>()) {
    // Collections (structs, classes, and unions).
    FormatCollection(node, coll, options, context);
  } else if (type->tag() == DwarfTag::kUnspecifiedType) {
    // Unspecified (nullptr_t).
    FormatUnspecified(node);
  } else {
    node->set_err(Err("Unsupported type: " + DwarfTagToString(type->tag())));
  }
}

}  // namespace

void FillFormatNodeValue(FormatNode* node, const fxl::RefPtr<EvalContext>& context,
                         fit::deferred_callback cb) {
  switch (node->source()) {
    case FormatNode::kValue:
      // Already has the value.
      return;
    case FormatNode::kExpression: {
      // Evaluate the expression.
      // TODO(brettw) remove this make_shared when EvalExpression takes a fit::callback.
      auto shared_cb = std::make_shared<fit::deferred_callback>(std::move(cb));
      EvalExpression(node->expression(), context, true,
                     [weak_node = node->GetWeakPtr(), shared_cb](ErrOrValue value) {
                       if (!weak_node)
                         return;
                       if (value.has_error()) {
                         weak_node->set_err(value.err());
                         weak_node->SetValue(ExprValue());
                       } else {
                         weak_node->SetValue(value.take_value());
                       }
                     });
      return;
    }
    case FormatNode::kProgramatic:
      // Lambda provides the value.
      node->FillProgramaticValue(std::move(context), std::move(cb));
      return;
    case FormatNode::kDescription:
      return;
  }
  FX_NOTREACHED();
}

void FillFormatNodeDescription(FormatNode* node, const FormatOptions& options,
                               const fxl::RefPtr<EvalContext>& context, fit::deferred_callback cb) {
  if (node->state() == FormatNode::kEmpty || node->err().has_error()) {
    node->set_state(FormatNode::kDescribed);
    return;
  }

  if (node->source() == FormatNode::kDescription) {
    return;
  }

  if (node->state() == FormatNode::kUnevaluated) {
    // Need to compute the value (possibly asynchronously).
    FillFormatNodeValue(node, context,
                        fit::defer_callback([weak_node = node->GetWeakPtr(), options, context,
                                             cb = std::move(cb)]() mutable {
                          if (weak_node) {
                            FillFormatNodeDescriptionFromValue(weak_node.get(), options, context,
                                                               std::move(cb));
                          }
                        }));
  } else {
    // Value already available, can format now.
    FillFormatNodeDescriptionFromValue(node, options, context, std::move(cb));
  }
}

void FormatNumericNode(FormatNode* node, const FormatOptions& options) {
  if (!node->value().data().all_valid()) {
    node->set_err(Err::OptimizedOut());
    return;
  }

  node->set_description_kind(FormatNode::kBaseType);

  if (node->value().data().size() > sizeof(uint64_t)) {
    // All >64-bit values get formatted as hex because we can't easily give these things to
    // printf.
    FormatUnsignedInt(node, options);
    return;
  }

  if (options.num_format != NumFormat::kDefault) {
    // Overridden format option.
    switch (options.num_format) {
      case NumFormat::kUnsigned:
      case NumFormat::kBin:
      case NumFormat::kHex:
        FormatUnsignedInt(node, options);
        break;
      case NumFormat::kSigned:
        FormatSignedInt(node);
        break;
      case NumFormat::kChar:
        FormatChar(node);
        break;
      case NumFormat::kDefault:
        // Prevent warning for unused enum type.
        break;
    }
  } else {
    // Default handling for base types based on the number.
    switch (node->value().GetBaseType()) {
      case BaseType::kBaseTypeBoolean:
        FormatBoolean(node);
        break;
      case BaseType::kBaseTypeFloat:
        FormatFloat(node);
        break;
      case BaseType::kBaseTypeSigned:
        FormatSignedInt(node);
        break;
      case BaseType::kBaseTypeUnsigned:
        FormatUnsignedInt(node, options);
        break;
      case BaseType::kBaseTypeSignedChar:
      case BaseType::kBaseTypeUnsignedChar:
      case BaseType::kBaseTypeUTF:
        FormatChar(node);
        break;
    }
  }
}

// Sometimes we know the real length of the array as in c "char[12]" type. In this case the expanded
// children should always include all elements, even if there is a null in the middle. This is what
// length_was_known means. When unset we assume a guessed length (as in "char*"), stop at the first
// null, and don't include it.
//
// TODO(brettw) currently this handles 8-bit characters only.
void FormatCharArrayNode(FormatNode* node, fxl::RefPtr<Type> char_type, const uint8_t* data,
                         size_t length, bool length_was_known, bool truncated) {
  node->set_description_kind(FormatNode::kString);

  // Expect the string to be null-terminated. If we didn't find a null before the end of the buffer,
  // mark as truncated.
  size_t output_len = strnlen(reinterpret_cast<const char*>(data), length);

  // It's possible a null happened before the end of the buffer, in which case it's no longer
  // truncated.
  if (output_len < length)
    truncated = false;

  // Generate the string in the description. Stop at the first null (computed above) and don't
  // include it.
  std::string result("\"");
  for (size_t i = 0; i < output_len; i++)
    AppendCEscapedChar(data[i], &result);
  result.push_back('"');

  // Add children to the first null unless the length was known in advance.
  size_t child_len = length_was_known ? length : output_len;
  for (size_t i = 0; i < child_len; i++) {
    auto char_node = std::make_unique<FormatNode>(fxl::StringPrintf("[%zu]", i),
                                                  ExprValue(char_type, {data[i]}));
    char_node->set_child_kind(FormatNode::kArrayItem);
    node->children().push_back(std::move(char_node));
  }

  // Add an indication if the string was truncated to the max size.
  if (truncated) {
    result += "...";
    node->children().push_back(std::make_unique<FormatNode>("..."));
  }

  node->set_description(result);
  node->set_state(FormatNode::kDescribed);
}

void FormatCharPointerNode(FormatNode* node, uint64_t ptr, const Type* char_type,
                           std::optional<uint32_t> length, const FormatOptions& options,
                           const fxl::RefPtr<EvalContext>& eval_context,
                           fit::deferred_callback cb) {
  node->set_description_kind(FormatNode::kString);

  if (!ptr) {
    // Special-case null pointers to just print a null address.
    node->set_description("0x0");
    return;
  }

  if (length && *length == 0) {
    // Empty string.
    node->set_description("\"\"");
    return;
  }

  // Speculatively request the max string size.
  uint32_t bytes_to_fetch;
  bool truncated = false;
  if (length) {
    if (*length > options.max_array_size) {
      bytes_to_fetch = options.max_array_size;
      truncated = true;
    } else {
      bytes_to_fetch = *length;
    }
  } else {
    bytes_to_fetch = options.max_array_size;

    // Report as truncated because if the string goes to the end of this array it will be.
    // FormatCharArrayNode will clear this flag if it finds a null before the end of the buffer.
    //
    // Don't want to set truncated if the data ended before the requested size, this means it
    // hit the end of valid memory, so we're not omitting data by only showing that part of it.
    truncated = true;
  }

  if (bytes_to_fetch == 0) {
    // No array data should be fetched. Indicate that the result was truncated.
    node->set_description("\"\"...");
    return;
  }

  fxl::RefPtr<SymbolDataProvider> data_provider = eval_context->GetDataProvider();

  data_provider->GetMemoryAsync(ptr, bytes_to_fetch,
                                [ptr, bytes_to_fetch, char_type = RefPtrTo(char_type), truncated,
                                 weak_node = node->GetWeakPtr(), cb = std::move(cb)](
                                    const Err& err, std::vector<uint8_t> data) mutable {
                                  if (!weak_node)
                                    return;

                                  if (data.empty()) {
                                    // Should not have requested 0 size, so it if came back empty
                                    // the pointer was invalid.
                                    weak_node->set_err(Err("0x%" PRIx64 " invalid pointer", ptr));
                                    return;
                                  }

                                  bool new_truncated = truncated && data.size() == bytes_to_fetch;
                                  FormatCharArrayNode(weak_node.get(), char_type, data.data(),
                                                      data.size(), false, new_truncated);
                                });
}

void FormatArrayNode(FormatNode* node, const ExprValue& value, int elt_count,
                     const FormatOptions& options, const fxl::RefPtr<EvalContext>& eval_context,
                     fit::deferred_callback cb) {
  node->set_description_kind(FormatNode::kArray);

  if (elt_count < 0)
    return node->SetDescribedError(Err("Invalid array size of %d.", elt_count));
  int print_count = std::min(static_cast<int>(options.max_array_size), elt_count);

  ResolveArray(eval_context, value, 0, print_count,
               [weak_node = node->GetWeakPtr(), elt_count,
                cb = std::move(cb)](ErrOrValueVector result) mutable {
                 if (!weak_node)
                   return;
                 FormatNode* node = weak_node.get();

                 if (result.has_error())
                   return node->SetDescribedError(result.err());

                 for (size_t i = 0; i < result.value().size(); i++) {
                   auto item_node = std::make_unique<FormatNode>(fxl::StringPrintf("[%zu]", i),
                                                                 std::move(result.value()[i]));
                   item_node->set_child_kind(FormatNode::kArrayItem);
                   node->children().push_back(std::move(item_node));
                 }

                 if (static_cast<uint32_t>(elt_count) > result.value().size()) {
                   // Add "..." annotation to show some things were clipped.
                   //
                   // TODO(brettW) We may want to put a flag on the node that it was clipped,
                   // and also indicate the number of clipped elements.
                   node->children().push_back(std::make_unique<FormatNode>("..."));
                 }
               });
}

void FormatPointerNode(FormatNode* node, const ExprValue& value, const FormatOptions& options) {
  node->set_description_kind(FormatNode::kPointer);

  // Note: don't make assumptions about the type of value.type() since it isn't necessarily a
  // ModifiedType representing a pointer, but could be other things like a pointer to a member.

  Err err = value.EnsureSizeIs(kTargetPointerSize);
  if (err.has_error()) {
    node->set_err(err);
    return;
  }

  // The address goes in the description.
  TargetPointer pointer_value = value.GetAs<TargetPointer>();
  node->set_description(to_hex_string(pointer_value));

  // Make a child node that's the dereferenced pointer value. If/when we support GUIs, we should
  // probably remove the intermediate node and put the dereferenced struct members directly as
  // children on this node. Otherwise it's an annoying extra step to expand to things.
  if (pointer_value != 0) {
    // Use our name but with a "*" to show it dereferenced.
    auto deref_node = std::make_unique<FormatNode>(
        "*" + node->name(),
        [ptr_value = value](const fxl::RefPtr<EvalContext>& context,
                            fit::callback<void(const Err& err, ExprValue value)> cb) {
          ResolvePointer(context, ptr_value, ErrOrValue::FromPairCallback(std::move(cb)));
        });
    deref_node->set_child_kind(FormatNode::kPointerExpansion);
    node->children().push_back(std::move(deref_node));
  }
}

void FormatWrapper(FormatNode* node, const std::string& description, const std::string& prefix,
                   const std::string& suffix, const std::string& contained_name,
                   ErrOrValue contained_value) {
  // Declare it as a pointer with the value as the pointed-to thing.
  node->set_description_kind(FormatNode::kWrapper);
  node->set_description(description);
  node->set_wrapper_prefix(prefix);
  node->set_wrapper_suffix(suffix);

  node->children().push_back(
      std::make_unique<FormatNode>(contained_name, std::move(contained_value)));
}

void FormatWrapper(FormatNode* node, const std::string& description, const std::string& prefix,
                   const std::string& suffix, const std::string& contained_name,
                   FormatNode::GetProgramaticValue value_getter) {
  // Declare it as a pointer with the value as the pointed-to thing.
  node->set_description_kind(FormatNode::kWrapper);
  node->set_description(description);
  node->set_wrapper_prefix(prefix);
  node->set_wrapper_suffix(suffix);

  node->children().push_back(std::make_unique<FormatNode>(contained_name, std::move(value_getter)));
}

void AppendCEscapedChar(uint8_t ch, std::string* dest) {
  if (ch == '\'' || ch == '\"' || ch == '\\') {
    // These characters get backslash-escaped.
    dest->push_back('\\');
    dest->push_back(ch);
  } else if (ch == '\n') {
    dest->append("\\n");
  } else if (ch == '\r') {
    dest->append("\\r");
  } else if (ch == '\t') {
    dest->append("\\t");
  } else if (isprint(ch)) {
    dest->push_back(ch);
  } else {
    // Hex-encode everything else.
    *dest += fxl::StringPrintf("\\x%02x", static_cast<unsigned>(ch));
  }
}

}  // namespace zxdb
