1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements. See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership. The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License. You may obtain a copy of the License at
9  *
10  *   http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied. See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  */
19 
20 #ifndef _THRIFT_TRANSPORT_TVIRTUALTRANSPORT_H_
21 #define _THRIFT_TRANSPORT_TVIRTUALTRANSPORT_H_ 1
22 
23 #include <thrift/transport/TTransport.h>
24 
25 namespace apache {
26 namespace thrift {
27 namespace transport {
28 
29 /**
30  * Helper class that provides default implementations of TTransport methods.
31  *
32  * This class provides default implementations of read(), readAll(), write(),
33  * borrow() and consume().
34  *
35  * In the TTransport base class, each of these methods simply invokes its
36  * virtual counterpart.  This class overrides them to always perform the
37  * default behavior, without a virtual function call.
38  *
39  * The primary purpose of this class is to serve as a base class for
40  * TVirtualTransport, and prevent infinite recursion if one of its subclasses
41  * does not override the TTransport implementation of these methods.  (Since
42  * TVirtualTransport::read_virt() calls read(), and TTransport::read() calls
43  * read_virt().)
44  */
45 class TTransportDefaults : public TTransport {
46 public:
47   /*
48    * TTransport *_virt() methods provide reasonable default implementations.
49    * Invoke them non-virtually.
50    */
read(uint8_t * buf,uint32_t len)51   uint32_t read(uint8_t* buf, uint32_t len) { return this->TTransport::read_virt(buf, len); }
readAll(uint8_t * buf,uint32_t len)52   uint32_t readAll(uint8_t* buf, uint32_t len) { return this->TTransport::readAll_virt(buf, len); }
write(const uint8_t * buf,uint32_t len)53   void write(const uint8_t* buf, uint32_t len) { this->TTransport::write_virt(buf, len); }
borrow(uint8_t * buf,uint32_t * len)54   const uint8_t* borrow(uint8_t* buf, uint32_t* len) {
55     return this->TTransport::borrow_virt(buf, len);
56   }
consume(uint32_t len)57   void consume(uint32_t len) { this->TTransport::consume_virt(len); }
58 
59 protected:
TTransport(config)60   TTransportDefaults(std::shared_ptr<TConfiguration> config = nullptr) : TTransport(config) {}
61 };
62 
63 /**
64  * Helper class to provide polymorphism for subclasses of TTransport.
65  *
66  * This class implements *_virt() methods of TTransport, to call the
67  * non-virtual versions of these functions in the proper subclass.
68  *
69  * To define your own transport class using TVirtualTransport:
70  * 1) Derive your subclass from TVirtualTransport<your class>
71  *    e.g:  class MyTransport : public TVirtualTransport<MyTransport> {
72  * 2) Provide your own implementations of read(), readAll(), etc.
73  *    These methods should be non-virtual.
74  *
75  * Transport implementations that need to use virtual inheritance when
76  * inheriting from TTransport cannot use TVirtualTransport.
77  *
78  * @author Chad Walters <chad@powerset.com>
79  */
80 template <class Transport_, class Super_ = TTransportDefaults>
81 class TVirtualTransport : public Super_ {
82 public:
83   /*
84    * Implementations of the *_virt() functions, to call the subclass's
85    * non-virtual implementation function.
86    */
read_virt(uint8_t * buf,uint32_t len)87   uint32_t read_virt(uint8_t* buf, uint32_t len) override {
88     return static_cast<Transport_*>(this)->read(buf, len);
89   }
90 
readAll_virt(uint8_t * buf,uint32_t len)91   uint32_t readAll_virt(uint8_t* buf, uint32_t len) override {
92     return static_cast<Transport_*>(this)->readAll(buf, len);
93   }
94 
write_virt(const uint8_t * buf,uint32_t len)95   void write_virt(const uint8_t* buf, uint32_t len) override {
96     static_cast<Transport_*>(this)->write(buf, len);
97   }
98 
borrow_virt(uint8_t * buf,uint32_t * len)99   const uint8_t* borrow_virt(uint8_t* buf, uint32_t* len) override {
100     return static_cast<Transport_*>(this)->borrow(buf, len);
101   }
102 
consume_virt(uint32_t len)103   void consume_virt(uint32_t len) override { static_cast<Transport_*>(this)->consume(len); }
104 
105   /*
106    * Provide a default readAll() implementation that invokes
107    * read() non-virtually.
108    *
109    * Note: subclasses that use TVirtualTransport to derive from another
110    * transport implementation (i.e., not TTransportDefaults) should beware that
111    * this may override any non-default readAll() implementation provided by
112    * the parent transport class.  They may need to redefine readAll() to call
113    * the correct parent implementation, if desired.
114    */
readAll(uint8_t * buf,uint32_t len)115   uint32_t readAll(uint8_t* buf, uint32_t len) {
116     auto* trans = static_cast<Transport_*>(this);
117     return ::apache::thrift::transport::readAll(*trans, buf, len);
118   }
119 
120 protected:
TVirtualTransport()121   TVirtualTransport() : Super_() {}
122 
123   /*
124    * Templatized constructors, to allow arguments to be passed to the Super_
125    * constructor.  Currently we only support 0, 1, or 2 arguments, but
126    * additional versions can be added as needed.
127    */
128   template <typename Arg_>
TVirtualTransport(Arg_ const & arg)129   TVirtualTransport(Arg_ const& arg)
130     : Super_(arg) {}
131 
132   template <typename Arg1_, typename Arg2_>
TVirtualTransport(Arg1_ const & a1,Arg2_ const & a2)133   TVirtualTransport(Arg1_ const& a1, Arg2_ const& a2)
134     : Super_(a1, a2) {}
135 };
136 }
137 }
138 } // apache::thrift::transport
139 
140 #endif // #ifndef _THRIFT_TRANSPORT_TVIRTUALTRANSPORT_H_
141