string t_go_generator::render_const_value()

in thrift/compiler/generate/t_go_generator.cc [1119:1295]


string t_go_generator::render_const_value(
    const t_type* type,
    const t_const_value* value,
    const string& name,
    bool is_optional) {
  type = type->get_true_type();
  std::ostringstream out;

  if (type->is_base_type()) {
    t_base_type::t_base tbase = ((t_base_type*)type)->get_base();

    switch (tbase) {
      case t_base_type::TYPE_STRING:
        if (is_optional) {
          f_const_vars_ << "var const_lit_" << name << " "
                        << type_to_go_type(type) << " = " << '"'
                        << get_escaped_string(value) << '"' << endl;
          out << "&const_lit_" << name;
        } else {
          out << '"' << get_escaped_string(value) << '"';
        }
        break;
      case t_base_type::TYPE_BINARY:
        out << "[]byte(\"" << get_escaped_string(value) << "\")";
        break;
      case t_base_type::TYPE_BOOL:
        out << (value->get_integer() > 0 ? "true" : "false");
        break;

      case t_base_type::TYPE_BYTE:
      case t_base_type::TYPE_I16:
      case t_base_type::TYPE_I32:
      case t_base_type::TYPE_I64:
        if (is_optional) {
          f_const_vars_ << "var const_lit_" << name << " "
                        << type_to_go_type(type) << " = "
                        << value->get_integer() << endl;
          out << "&const_lit_" << name;
        } else {
          out << value->get_integer();
        }
        break;

      case t_base_type::TYPE_DOUBLE:
      case t_base_type::TYPE_FLOAT: {
        if (is_optional) {
          f_const_vars_ << "var const_lit_" << name << " "
                        << type_to_go_type(type) << " = ";
        }

        std::ostringstream& value_out = (is_optional ? f_const_vars_ : out);
        if (value->get_type() == t_const_value::CV_INTEGER) {
          value_out << value->get_integer();
        } else {
          value_out << value->get_double();
        }

        if (is_optional) {
          f_const_vars_ << endl;
          out << "&const_lit_" << name;
        }

        break;
      }

      default:
        throw std::runtime_error(
            "compiler error: no const of base type " +
            t_base_type::t_base_name(tbase));
    }
  } else if (type->is_enum()) {
    if (is_optional) {
      f_const_vars_ << "var const_lit_" << name << " " << type_to_go_type(type)
                    << " = " << value->get_integer() << endl;
      out << "&const_lit_" << name;
    } else {
      out << value->get_integer();
    }
  } else if (type->is_struct() || type->is_xception()) {
    out << "&" << publicize(type_name(type)) << "{";
    indent_up();
    out << endl;
    const vector<t_field*>& fields = ((t_struct*)type)->get_members();
    vector<t_field*>::const_iterator f_iter;
    const vector<pair<t_const_value*, t_const_value*>>& val = value->get_map();
    vector<pair<t_const_value*, t_const_value*>>::const_iterator v_iter;

    if (((t_struct*)type)->is_union()) {
      for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
        (*f_iter)->set_req(t_field::e_req::optional);
      }
    }

    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
      const t_type* field_type = nullptr;
      bool is_field_optional = false;
      string field_name;

      for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
        if ((*f_iter)->get_name() == v_iter->first->get_string()) {
          field_name = name + "_" + (*f_iter)->get_name();
          field_type = (*f_iter)->get_type();
          is_field_optional =
              ((*f_iter)->get_req() == t_field::e_req::optional);
          break;
        }
      }

      if (field_type == nullptr) {
        throw std::runtime_error(
            "type error: " + type->get_name() + " has no field " +
            v_iter->first->get_string());
      }

      out << indent() << publicize(v_iter->first->get_string()) << ": "
          << render_const_value(
                 field_type, v_iter->second, field_name, is_field_optional)
          << "," << endl;
    }
    indent_down();
    out << indent() << "}";

  } else if (type->is_map()) {
    const t_type* ktype = ((t_map*)type)->get_key_type();
    const t_type* vtype = ((t_map*)type)->get_val_type();
    const vector<pair<t_const_value*, t_const_value*>>& val = value->get_map();
    out << "map[" << type_to_go_key_type(ktype) << "]" << type_to_go_type(vtype)
        << "{" << endl;
    indent_up();
    vector<pair<t_const_value*, t_const_value*>>::const_iterator v_iter;

    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
      auto idx = std::to_string(std::distance(val.begin(), v_iter));
      out << indent() << render_const_value(ktype, v_iter->first, name) << ": "
          << render_const_value(vtype, v_iter->second, name + "_" + idx) << ","
          << endl;
    }

    indent_down();
    out << indent() << "}";
  } else if (type->is_list()) {
    const t_type* etype = ((t_list*)type)->get_elem_type();
    const vector<t_const_value*>& val = value->get_list();
    out << "[]" << type_to_go_type(etype) << "{" << endl;
    indent_up();
    vector<t_const_value*>::const_iterator v_iter;

    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
      auto idx = std::to_string(std::distance(val.begin(), v_iter));
      out << indent() << render_const_value(etype, *v_iter, name + "_" + idx)
          << "," << endl;
    }

    indent_down();
    out << indent() << "}";
  } else if (type->is_set()) {
    const t_type* etype = ((t_set*)type)->get_elem_type();
    const vector<t_const_value*>& val = value->get_list();
    out << "[]" << type_to_go_key_type(etype) << "{" << endl;
    indent_up();
    vector<t_const_value*>::const_iterator v_iter;

    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
      auto idx = std::to_string(std::distance(val.begin(), v_iter));
      out << indent() << render_const_value(etype, *v_iter, name + "_" + idx)
          << ", ";
    }

    indent_down();
    out << indent() << "}";
  } else {
    throw std::runtime_error(
        "CANNOT GENERATE CONSTANT FOR TYPE: " + type->get_name());
  }

  return out.str();
}