blob: 310c2b22c1f0b0d511856fdb8a4138abdca00d45 [file] [log] [blame]
David Reiss00dcccf2007-07-21 01:18:10 +00001// Copyright (c) 2006- Facebook
2// Distributed under the Thrift Software License
3//
4// See accompanying file LICENSE or visit the Thrift site at:
5// http://developers.facebook.com/thrift/
6
7#ifndef _THRIFT_PROTOCOL_TDEBUGPROTOCOL_H_
8#define _THRIFT_PROTOCOL_TDEBUGPROTOCOL_H_ 1
9
10#include "TProtocol.h"
11#include "TOneWayProtocol.h"
12
13#include <boost/shared_ptr.hpp>
14
15#include <transport/TTransportUtils.h>
16
David Reiss0c90f6f2008-02-06 22:18:40 +000017namespace facebook { namespace thrift { namespace protocol {
David Reiss00dcccf2007-07-21 01:18:10 +000018
19/*
20
21!!! EXPERIMENTAL CODE !!!
22
23This protocol is very much a work in progress.
24It doesn't handle many cases properly.
25It throws exceptions in many cases.
26It probably segfaults in many cases.
27Bug reports and feature requests are welcome.
28Complaints are not. :R
29
30*/
31
32
33/**
34 * Protocol that prints the payload in a nice human-readable format.
35 * Reading from this protocol is not supported.
36 *
37 * @author David Reiss <dreiss@facebook.com>
38 */
39class TDebugProtocol : public TWriteOnlyProtocol {
40 private:
41 enum write_state_t {
42 UNINIT,
43 STRUCT,
44 LIST,
45 SET,
46 MAP_KEY,
47 MAP_VALUE,
48 };
49
50 public:
51 TDebugProtocol(boost::shared_ptr<TTransport> trans)
52 : TWriteOnlyProtocol(trans, "TDebugProtocol")
David Reissa80f0fb2008-04-08 05:06:15 +000053 , string_limit_(DEFAULT_STRING_LIMIT)
54 , string_prefix_size_(DEFAULT_STRING_PREFIX_SIZE)
David Reiss00dcccf2007-07-21 01:18:10 +000055 {
56 write_state_.push_back(UNINIT);
57 }
58
David Reissa80f0fb2008-04-08 05:06:15 +000059 static const int32_t DEFAULT_STRING_LIMIT = 256;
60 static const int32_t DEFAULT_STRING_PREFIX_SIZE = 16;
61
62 void setStringSizeLimit(int32_t string_limit) {
63 string_limit_ = string_limit;
64 }
65
66 void setStringPrefixSize(int32_t string_prefix_size) {
67 string_prefix_size_ = string_prefix_size;
68 }
69
David Reiss00dcccf2007-07-21 01:18:10 +000070
71 virtual uint32_t writeMessageBegin(const std::string& name,
72 const TMessageType messageType,
73 const int32_t seqid);
74
75 virtual uint32_t writeMessageEnd();
76
77
78 uint32_t writeStructBegin(const std::string& name);
79
80 uint32_t writeStructEnd();
81
82 uint32_t writeFieldBegin(const std::string& name,
83 const TType fieldType,
84 const int16_t fieldId);
85
86 uint32_t writeFieldEnd();
87
88 uint32_t writeFieldStop();
David Reiss0c90f6f2008-02-06 22:18:40 +000089
David Reiss00dcccf2007-07-21 01:18:10 +000090 uint32_t writeMapBegin(const TType keyType,
91 const TType valType,
92 const uint32_t size);
93
94 uint32_t writeMapEnd();
95
96 uint32_t writeListBegin(const TType elemType,
97 const uint32_t size);
98
99 uint32_t writeListEnd();
100
101 uint32_t writeSetBegin(const TType elemType,
102 const uint32_t size);
103
104 uint32_t writeSetEnd();
105
106 uint32_t writeBool(const bool value);
107
108 uint32_t writeByte(const int8_t byte);
109
110 uint32_t writeI16(const int16_t i16);
111
112 uint32_t writeI32(const int32_t i32);
113
114 uint32_t writeI64(const int64_t i64);
115
116 uint32_t writeDouble(const double dub);
117
118 uint32_t writeString(const std::string& str);
119
David Reissc005b1b2008-02-15 01:38:18 +0000120 uint32_t writeBinary(const std::string& str);
121
David Reiss00dcccf2007-07-21 01:18:10 +0000122
123 private:
124 void indentUp();
125 void indentDown();
126 uint32_t writePlain(const std::string& str);
127 uint32_t writeIndented(const std::string& str);
128 uint32_t startItem();
129 uint32_t endItem();
130 uint32_t writeItem(const std::string& str);
131
132 static std::string fieldTypeName(TType type);
133
David Reissa80f0fb2008-04-08 05:06:15 +0000134 int32_t string_limit_;
135 int32_t string_prefix_size_;
136
David Reiss00dcccf2007-07-21 01:18:10 +0000137 std::string indent_str_;
138 static const int indent_inc = 2;
139
140 std::vector<write_state_t> write_state_;
141 std::vector<int> list_idx_;
142};
143
144/**
145 * Constructs debug protocol handlers
146 */
147class TDebugProtocolFactory : public TProtocolFactory {
148 public:
149 TDebugProtocolFactory() {}
150 virtual ~TDebugProtocolFactory() {}
151
152 boost::shared_ptr<TProtocol> getProtocol(boost::shared_ptr<TTransport> trans) {
153 return boost::shared_ptr<TProtocol>(new TDebugProtocol(trans));
154 }
155
156};
157
158}}} // facebook::thrift::protocol
159
160
David Reiss0c90f6f2008-02-06 22:18:40 +0000161namespace facebook { namespace thrift {
David Reiss00dcccf2007-07-21 01:18:10 +0000162
163template<typename ThriftStruct>
164std::string ThriftDebugString(const ThriftStruct& ts) {
165 using namespace facebook::thrift::transport;
166 using namespace facebook::thrift::protocol;
167 TMemoryBuffer* buffer = new TMemoryBuffer;
168 boost::shared_ptr<TTransport> trans(buffer);
169 TDebugProtocol protocol(trans);
170
171 ts.write(&protocol);
172
173 uint8_t* buf;
174 uint32_t size;
175 buffer->getBuffer(&buf, &size);
176 return std::string((char*)buf, (unsigned int)size);
177}
178
179// TODO(dreiss): This is badly broken. Don't use it unless you are me.
180#if 0
181template<typename Object>
182std::string DebugString(const std::vector<Object>& vec) {
183 using namespace facebook::thrift::transport;
184 using namespace facebook::thrift::protocol;
185 TMemoryBuffer* buffer = new TMemoryBuffer;
186 boost::shared_ptr<TTransport> trans(buffer);
187 TDebugProtocol protocol(trans);
188
189 // I am gross!
190 protocol.writeStructBegin("SomeRandomVector");
191
192 // TODO: Fix this with a trait.
193 protocol.writeListBegin((TType)99, vec.size());
194 typename std::vector<Object>::const_iterator it;
195 for (it = vec.begin(); it != vec.end(); ++it) {
196 it->write(&protocol);
197 }
198 protocol.writeListEnd();
199
200 uint8_t* buf;
201 uint32_t size;
202 buffer->getBuffer(&buf, &size);
203 return std::string((char*)buf, (unsigned int)size);
204}
205#endif // 0
206
207}} // facebook::thrift
208
209
210#endif // #ifndef _THRIFT_PROTOCOL_TDEBUGPROTOCOL_H_
211
212