Spicy
struct.h
1 // Copyright (c) 2020-2021 by the Zeek Project. See LICENSE for details.
2 
3 #pragma once
4 
5 #include <string>
6 
7 #include <hilti/rt/extension-points.h>
8 #include <hilti/rt/result.h>
9 #include <hilti/rt/util.h>
10 
11 namespace hilti::rt {
12 
13 namespace trait {
14 struct isStruct {};
15 struct hasParameters {};
16 } // namespace trait
17 
18 namespace struct_ {
19 
20 template<class T>
21 inline auto& value_or_exception(const std::optional<T>& t, const char* location) {
22  if ( t.has_value() )
23  return t.value();
24 
25  throw AttributeNotSet("struct attribute not set", location);
26 }
27 } // namespace struct_
28 
29 namespace detail::adl {
30 
31 template<typename>
32 constexpr std::false_type has__str__helper(long);
33 
34 template<typename T>
35 constexpr auto has__str__helper(int) -> decltype(std::declval<T>().__str__(), std::true_type{});
36 
37 template<typename T>
38 using has__str__ = decltype(has__str__helper<T>(0));
39 
40 template<typename T, typename std::enable_if_t<std::is_base_of<trait::isStruct, T>::value>* = nullptr>
41 inline std::string to_string(const T& x, adl::tag /*unused*/) {
42  if constexpr ( has__str__<T>() ) {
43  if ( auto s = T(x).__str__() ) // copy because we need a non-const T
44  return *s;
45  }
46 
47  std::string fields;
48  bool first = true;
49 
50  auto render_one = [&](auto k, auto v) {
51  if ( ! first )
52  fields += ", ";
53  else
54  first = false;
55 
56  fields += fmt("$%s=%s", k, hilti::rt::to_string(v));
57  };
58 
59  x.__visit(render_one);
60  return fmt("[%s]", fields);
61 }
62 
63 } // namespace detail::adl
64 
65 } // namespace hilti::rt
std::string to_string(T &&x)
Definition: extension-points.h:26
Definition: any.h:7
Definition: struct.h:14
Definition: struct.h:15
Definition: location.h:94
std::string fmt(const char *fmt, const Args &... args)
Definition: fmt.h:13