1 //
2 // Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2021
3 //
4 // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 //
7 #pragma once
8 
9 #include "td/utils/common.h"
10 #include "td/utils/SharedSlice.h"
11 #include "td/utils/Slice.h"
12 #include "td/utils/SliceBuilder.h"
13 #include "td/utils/UInt.h"
14 
15 namespace td {
16 
17 class TlStorerToString {
18   string result;
19   size_t shift = 0;
20 
store_field_begin(const char * name)21   void store_field_begin(const char *name) {
22     result.append(shift, ' ');
23     if (name && name[0]) {
24       result += name;
25       result += " = ";
26     }
27   }
28 
store_field_end()29   void store_field_end() {
30     result += '\n';
31   }
32 
store_long(int64 value)33   void store_long(int64 value) {
34     result += (PSLICE() << value).c_str();
35   }
36 
store_binary(Slice data)37   void store_binary(Slice data) {
38     static const char *hex = "0123456789ABCDEF";
39 
40     result.append("{ ", 2);
41     for (auto c : data) {
42       unsigned char byte = c;
43       result += hex[byte >> 4];
44       result += hex[byte & 15];
45       result += ' ';
46     }
47     result += '}';
48   }
49 
50  public:
51   TlStorerToString() = default;
52   TlStorerToString(const TlStorerToString &other) = delete;
53   TlStorerToString &operator=(const TlStorerToString &other) = delete;
54 
store_field(const char * name,bool value)55   void store_field(const char *name, bool value) {
56     store_field_begin(name);
57     result += (value ? "true" : "false");
58     store_field_end();
59   }
60 
store_field(const char * name,int32 value)61   void store_field(const char *name, int32 value) {
62     store_field(name, static_cast<int64>(value));
63   }
64 
store_field(const char * name,int64 value)65   void store_field(const char *name, int64 value) {
66     store_field_begin(name);
67     store_long(value);
68     store_field_end();
69   }
70 
store_field(const char * name,double value)71   void store_field(const char *name, double value) {
72     store_field_begin(name);
73     result += (PSLICE() << value).c_str();
74     store_field_end();
75   }
76 
store_field(const char * name,const char * value)77   void store_field(const char *name, const char *value) {
78     store_field_begin(name);
79     result += value;
80     store_field_end();
81   }
82 
store_field(const char * name,const string & value)83   void store_field(const char *name, const string &value) {
84     store_field_begin(name);
85     result += '"';
86     result += value;
87     result += '"';
88     store_field_end();
89   }
90 
store_field(const char * name,const SecureString & value)91   void store_field(const char *name, const SecureString &value) {
92     store_field_begin(name);
93     result.append("<secret>");
94     store_field_end();
95   }
96 
97   template <class T>
store_field(const char * name,const T & value)98   void store_field(const char *name, const T &value) {
99     store_field_begin(name);
100     result.append(value.data(), value.size());
101     store_field_end();
102   }
103 
store_bytes_field(const char * name,const SecureString & value)104   void store_bytes_field(const char *name, const SecureString &value) {
105     store_field_begin(name);
106     result.append("<secret>");
107     store_field_end();
108   }
109 
110   template <class BytesT>
store_bytes_field(const char * name,const BytesT & value)111   void store_bytes_field(const char *name, const BytesT &value) {
112     static const char *hex = "0123456789ABCDEF";
113 
114     store_field_begin(name);
115     result.append("bytes [");
116     store_long(static_cast<int64>(value.size()));
117     result.append("] { ");
118     size_t len = min(static_cast<size_t>(64), value.size());
119     for (size_t i = 0; i < len; i++) {
120       int b = value[static_cast<int>(i)] & 0xff;
121       result += hex[b >> 4];
122       result += hex[b & 15];
123       result += ' ';
124     }
125     if (len < value.size()) {
126       result.append("...");
127     }
128     result += '}';
129     store_field_end();
130   }
131 
132   template <class ObjectT>
store_object_field(const char * name,const ObjectT * value)133   void store_object_field(const char *name, const ObjectT *value) {
134     if (value == nullptr) {
135       store_field(name, "null");
136     } else {
137       value->store(*this, name);
138     }
139   }
140 
store_field(const char * name,const UInt128 & value)141   void store_field(const char *name, const UInt128 &value) {
142     store_field_begin(name);
143     store_binary(as_slice(value));
144     store_field_end();
145   }
146 
store_field(const char * name,const UInt256 & value)147   void store_field(const char *name, const UInt256 &value) {
148     store_field_begin(name);
149     store_binary(as_slice(value));
150     store_field_end();
151   }
152 
store_vector_begin(const char * field_name,size_t vector_size)153   void store_vector_begin(const char *field_name, size_t vector_size) {
154     store_field_begin(field_name);
155     result += "vector[";
156     result += (PSLICE() << vector_size).c_str();
157     result += "] {\n";
158     shift += 2;
159   }
160 
store_class_begin(const char * field_name,const char * class_name)161   void store_class_begin(const char *field_name, const char *class_name) {
162     store_field_begin(field_name);
163     result += class_name;
164     result += " {\n";
165     shift += 2;
166   }
167 
store_class_end()168   void store_class_end() {
169     CHECK(shift >= 2);
170     shift -= 2;
171     result.append(shift, ' ');
172     result += "}\n";
173   }
174 
move_as_string()175   string move_as_string() {
176     return std::move(result);
177   }
178 };
179 
180 }  // namespace td
181