00001 #ifndef _BOOST_RPC_PROTOCOL_BUFFERS_HPP_
00002 #define _BOOST_RPC_PROTOCOL_BUFFERS_HPP_
00003 #include <boost/rpc/datastream/datastream.hpp>
00004 #include <boost/rpc/varint.hpp>
00005 #include <boost/rpc/errors.hpp>
00006 #include <boost/rpc/required.hpp>
00007 #include <boost/reflect/reflect.hpp>
00008 #include <boost/optional.hpp>
00009 #include <boost/throw_exception.hpp>
00010 #include <boost/fusion/container/vector.hpp>
00011 #include <boost/fusion/algorithm.hpp>
00012 #include <boost/fusion/support/is_sequence.hpp>
00013 #include <boost/fusion/sequence/intrinsic/size.hpp>
00014
00015 #include <iostream>
00016 #include <boost/cmt/log/log.hpp>
00017
00018 namespace boost { namespace rpc { namespace protocol_buffer {
00019
00020 namespace detail {
00021
00022 enum protocol_buf_wire_types
00023 {
00024 varint = 0,
00025 bit64 = 1,
00026 length_delimited = 2,
00027 bit8 = 3,
00028 bit16 = 4,
00029 bit32 = 5,
00030 bit0 = 6
00031 };
00032
00033 template<typename T, int fund, uint32_t size>
00034 struct get_wire_type_impl{ enum wire_type { value = length_delimited }; };
00035
00036 template<>
00037 struct get_wire_type_impl<unsigned_int,0,1>{ enum wire_type { value = varint }; };
00038 template<>
00039 struct get_wire_type_impl<signed_int,0,1> { enum wire_type { value = varint }; };
00040
00041 template<typename T>
00042 struct get_wire_type_impl<T,1,1>{ enum wire_type { value = bit8 }; };
00043 template<typename T>
00044 struct get_wire_type_impl<T,1,2>{ enum wire_type { value = bit16 }; };
00045 template<typename T>
00046 struct get_wire_type_impl<T,1,4>{ enum wire_type { value = bit32 }; };
00047 template<typename T>
00048 struct get_wire_type_impl<T,1,8>{ enum wire_type { value = bit64 }; };
00049 template<typename T>
00050 struct get_wire_type : get_wire_type_impl<T,boost::is_fundamental<T>::value,sizeof(T)>{};
00051
00052
00053 template<typename T,typename T2>
00054 bool unpack_message_visitor( boost::rpc::datastream<T2>& is, T& val );
00055
00056 template<typename DataStreamType>
00057 class unpack_field_visitor
00058 {
00059 boost::rpc::datastream<DataStreamType>& is;
00060 uint32_t m_field;
00061 uint32_t m_type;
00062 public:
00063 unpack_field_visitor( boost::rpc::datastream<DataStreamType>& _is, uint32_t f = -1, uint32_t t = -1 )
00064 :is(_is),m_field(f),m_type(t),error(true){}
00065 bool error;
00066 template<typename Class>
00067 void start( Class, const char* anem ){}
00068
00069 template<typename Class>
00070 void end( Class, const char* anem ){}
00071
00072
00073
00074
00075 template<typename T, typename Flags>
00076 void unpack( T& value, const char* name, Flags key, boost::true_type _is_fundamental )
00077 {
00078 if( key != m_field || m_type != get_wire_type<T>::value )
00079 {
00080 BOOST_THROW_EXCEPTION( boost::rpc::protocol_buffer::key_type_mismatch(name) );
00081 error = true;
00082 return;
00083 }
00084 is >> value;
00085 error = !is.valid();
00086 }
00087
00088
00089
00090 template<typename T, typename Flags>
00091 void unpack( T& value, const char* name, Flags key )
00092 {
00093 dlog( "key %1% m_field %2% m_type %3%", key, m_field, m_type );
00094 unpack( value, name, key, typename boost::is_fundamental<T>::type() );
00095 }
00096
00097
00098
00099
00100 template<typename T, typename Flags>
00101 void unpack( T& value, const char* name, Flags key, boost::false_type _is_not_fundamental )
00102 {
00103 if( key != m_field || m_type != get_wire_type<T>::value )
00104 {
00105 std::cerr << "Error unpacking field '"<<name<<"', key/type mismatch\n";
00106 BOOST_THROW_EXCEPTION( boost::rpc::protocol_buffer::key_type_mismatch(name) );
00107 error = true;
00108 return;
00109 }
00110 unsigned_int size;
00111 is >> size;
00112
00113 if( is.remaining() >= size.value )
00114 {
00115 datastream<DataStreamType> is2( is.pos(), size.value );
00116 if( !unpack_message_visitor( is2, value ) )
00117 return;
00118 }
00119 else
00120 {
00121 std::cerr << "Error unpacking field '"<<name<<"', size is larger than remaining datastream\n";
00122 BOOST_THROW_EXCEPTION( boost::rpc::protocol_buffer::field_size_larger_than_buffer(name) );
00123 error = true;
00124 }
00125 is.skip(size);
00126 error = !is.valid();
00127 }
00128 template<typename Flags>
00129 void unpack( signed_int& value, const char* name, Flags key, boost::false_type _is_not_fundamental )
00130 {
00131 if( key != m_field || m_type != varint )
00132 {
00133 std::cerr << "Error unpacking field '"<<name<<"', key/type mismatch\n";
00134 BOOST_THROW_EXCEPTION( boost::rpc::protocol_buffer::key_type_mismatch(name) );
00135 error = true;
00136 return;
00137 }
00138 is >> value;
00139 error = false;
00140 }
00141 template<typename Flags>
00142 void unpack( unsigned_int& value, const char* name, Flags key, boost::false_type _is_not_fundamental )
00143 {
00144 if( key != m_field || m_type != varint )
00145 {
00146 std::cerr << "Error unpacking field '"<<name<<"', key/type mismatch\n";
00147 BOOST_THROW_EXCEPTION( boost::rpc::protocol_buffer::key_type_mismatch(name) );
00148 error = true;
00149 return;
00150 }
00151 is >> value;
00152 error = false;
00153 }
00154
00155 template<typename Flags>
00156 void unpack( std::string& str, const char* name, Flags key, boost::false_type _is_not_fundamental )
00157 {
00158 if( key != m_field || m_type != length_delimited )
00159 {
00160 std::cerr << "Error unpacking field '"<<name<<"', key/type mismatch\n";
00161 BOOST_THROW_EXCEPTION( boost::rpc::protocol_buffer::key_type_mismatch(name) );
00162 error = true;
00163 return;
00164 }
00165 unsigned_int size;
00166 is >> size;
00167 DataStreamType po = is.pos();
00168
00169 if( is.remaining() >= size.value )
00170 {
00171 str = std::string( po, size.value );
00172 is.skip(size.value);
00173 error = false;
00174 return;
00175 }
00176 error = true;
00177 }
00178
00179 template<typename T, typename Flags>
00180 void unpack( boost::optional<T>& value, const char* name, Flags key, boost::false_type _is_not_fundamental )
00181 {
00182 if( !value )
00183 value = T();
00184 wlog( "unapcking optional %1%", name );
00185 unpack( *value, name, key,typename boost::is_fundamental<T>::type() );
00186 }
00187 template<typename T, typename Flags>
00188 void unpack( boost::rpc::required<T>& value, const char* name, Flags key, boost::false_type _is_not_fundamental )
00189 {
00190 if( !value )
00191 value = T();
00192 wlog( "unapcking required %1%", name );
00193 unpack( *value, name, key, typename boost::is_fundamental<T>::type() );
00194 }
00195
00196
00197
00198
00199
00200 template<typename Class, typename T, typename Flags>
00201 void accept_member( Class& c, T (Class::*p), const char* name, Flags key )
00202 {
00203 unpack( c.*p, name, key, typename boost::is_fundamental<T>::type() );
00204 }
00205
00206 template<typename Class, typename Field, typename Alloc, template<typename,typename> class Container, typename Flags>
00207 void accept_member( Class& c, Container<Field,Alloc> (Class::*p), const char* name, Flags key )
00208 {
00209 if( key != m_field || m_type != length_delimited )
00210 {
00211 std::cerr << "Error unpacking field '"<<name<<"', key/type mismatch\n";
00212 BOOST_THROW_EXCEPTION( boost::rpc::protocol_buffer::key_type_mismatch(name) );
00213 error = true;
00214 return;
00215 }
00216
00217 unsigned_int size;
00218 is >> size;
00219
00220 if( is.remaining() >= size.value )
00221 {
00222 datastream<DataStreamType> is2( is.pos(), size.value );
00223 (c.*p).resize( (c.*p).size()+1);
00224 if( !unpack_message_visitor( is2, (c.*p).back() ) )
00225 {
00226 (c.*p).pop_back();
00227 return;
00228 }
00229 }
00230 else
00231 {
00232 std::cerr << "Error unpacking field '"<<name<<"', size is larger than remaining datastream\n";
00233 BOOST_THROW_EXCEPTION( boost::rpc::protocol_buffer::field_size_larger_than_buffer(name) );
00234 error = true;
00235 }
00236 is.skip(size);
00237 error = !is.valid();
00238 }
00239
00240 template<typename Class, typename Alloc, template<typename,typename> class Container, typename Flags>
00241 void accept_member( Class& c, Container<std::string,Alloc> (Class::*p), const char* name, Flags key )
00242 {
00243 if( key != m_field || m_type != length_delimited )
00244 {
00245 std::cerr << "Error unpacking field '"<<name<<"', key/type mismatch\n";
00246 BOOST_THROW_EXCEPTION( boost::rpc::protocol_buffer::key_type_mismatch(name) );
00247 error = true;
00248 return;
00249 }
00250
00251 unsigned_int size;
00252 is >> size;
00253
00254 DataStreamType po = is.pos();
00255
00256 if( is.remaining() >= size.value )
00257 {
00258 (c.*p).push_back( std::string( po, size.value ) );
00259 is.skip(size.value);
00260 error = false;
00261 return;
00262 }
00263 }
00264
00265 template<typename Class>
00266 void not_found( Class c, uint32_t field )
00267 {
00268 BOOST_THROW_EXCEPTION( boost::rpc::protocol_buffer::field_not_found() );
00269 }
00270
00271 };
00272
00273
00274 template<typename T, typename T2, typename Flags>
00275 bool unpack_field( boost::rpc::datastream<T2>& is, T& val, Flags key, int type )
00276 {
00277 unpack_field_visitor<T2> upfv(is, key, type);
00278 boost::reflect::reflector<T>::visit( val, upfv, key );
00279 return !upfv.error;
00280 }
00281 template<typename T2, typename Flags>
00282 bool unpack_field( boost::rpc::datastream<T2>& is, std::string& val, Flags key, int type )
00283 {
00284 unsigned_int size;
00285 is >> size;
00286 T2 p = is.pos();
00287 is.skip(size.value);
00288 if( is.valid() )
00289 {
00290 val = std::string( p, is.pos() );
00291 }
00292 return !is.valid();
00293 }
00294
00295
00296
00297
00298
00299 template<typename IsSequence>
00300 struct unpack_message_selector
00301 {
00302 template<typename T,typename T2>
00303 static inline bool unpack_message( boost::rpc::datastream<T2>& is, T& val )
00304 {
00305
00306 while( is.remaining() )
00307 {
00308
00309 unsigned_int tkey;
00310 is >> tkey;
00311 if( !is.valid() )
00312 return false;
00313
00314 int type = tkey.value & 0x07;
00315 uint32_t key = tkey.value >> 3;
00316 if( !unpack_field( is, val, key, type ) )
00317 {
00318 std::cerr <<"error unpacking field "<<key<<std::endl;
00319 return false;
00320 }
00321 }
00322 return true;
00323 }
00324 };
00325
00326
00327
00328 template<>
00329 struct unpack_message_selector<boost::integral_constant<bool, true> >
00330 {
00331
00332
00333
00334
00335
00336
00337
00338
00339 template<typename Sequence, int32_t Index =
00340 boost::fusion::result_of::size<Sequence>::type::value>
00341 struct helper
00342 {
00343 template<typename StreamType>
00344 static inline bool unpack_field( boost::rpc::datastream<StreamType>& is,
00345 Sequence& seq, uint32_t key, uint32_t type )
00346 {
00347 if( (Index -1)== key )
00348 {
00349 unpack_field_visitor<StreamType> ufv( is, key, type );
00350 ufv.unpack( boost::fusion::at_c<Index-1>(seq), 0, key );
00351 return true;
00352 }
00353 else
00354 {
00355 helper<Sequence,(Index-1)>::unpack_field( is, seq, key, type );
00356 }
00357 }
00358 };
00359
00360 template<typename Sequence>
00361 struct helper<Sequence,0>
00362 {
00363 template<typename StreamType>
00364 static inline bool unpack_field( boost::rpc::datastream<StreamType>& is,
00365 Sequence& seq, uint32_t key, uint32_t type )
00366 {
00367 return false;
00368 }
00369 };
00370
00371 template<typename Sequence,typename T2>
00372 static inline bool unpack_message( boost::rpc::datastream<T2>& is, Sequence& val )
00373 {
00374 while( is.remaining() )
00375 {
00376
00377 unsigned_int tkey;
00378 is >> tkey;
00379 if( !is.valid() )
00380 return false;
00381
00382 int type = tkey.value & 0x07;
00383 uint32_t key = tkey.value >> 3;
00384 if( !helper<Sequence>::unpack_field( is, val, key, type ) )
00385 {
00386 std::cerr <<"error unpacking field "<<key<<std::endl;
00387 return false;
00388 }
00389 }
00390 return true;
00391 }
00392 };
00393
00394
00395
00396
00397
00398
00399 template<typename T,typename T2>
00400 bool unpack_message_visitor( boost::rpc::datastream<T2>& is, T& val )
00401 {
00402 return unpack_message_selector<typename boost::fusion::traits::is_sequence<T>::type>::unpack_message(is,val);
00403 }
00404
00405
00406 template<typename DataStreamType>
00407 class pack_message_visitor
00408 {
00409 public:
00410 pack_message_visitor( boost::rpc::datastream<DataStreamType>& os )
00411 :m_os(os){}
00412
00413 template<typename Class>
00414 void start( Class, const char* anem ){}
00415
00416 template<typename Class>
00417 void end( Class, const char* anem ){}
00418
00419
00420
00421
00422 template<typename T, typename Flags>
00423 void pack_field( const T& value, const char* name, Flags key, boost::true_type _is_fundamental )
00424 {
00425 m_os << unsigned_int( uint32_t(key) << 3 | get_wire_type<T>::value );
00426 m_os << value;
00427 }
00428
00429
00430
00431
00432
00433 template< typename T, typename Flags>
00434 void pack_field( const T& value, const char* name, Flags key, boost::false_type _is_not_fundamental )
00435 {
00436 m_os <<unsigned_int( uint32_t(key) << 3 | length_delimited );
00437
00438 unsigned_int s(boost::rpc::protocol_buffer::packsize(value));
00439 m_os << s;
00440 pack( value );
00441 }
00442
00443 template<typename DST>
00444 struct visit_sequence
00445 {
00446 visit_sequence( datastream<DST>& _ds ):id(0),pmv(_ds){}
00447
00448 mutable uint32_t id;
00449 mutable pack_message_visitor<DST> pmv;
00450
00451 template<typename T>
00452 void operator() ( const T& v )const
00453 {
00454 pmv.pack_field(v,0,id, typename boost::is_fundamental<T>::type());
00455 ++id;
00456 }
00457 };
00458
00459 template< typename T>
00460 void pack( const T& value, boost::false_type _is_not_fundamental, boost::mpl::true_ _is_fusion_sequence)
00461 {
00462 visit_sequence<DataStreamType> pack_vector(m_os);
00463 boost::fusion::for_each( value, pack_vector );
00464 }
00465 template< typename T>
00466 void pack( const T& value, boost::false_type _is_not_fundamental, boost::mpl::false_ _is_not_fusion_sequence)
00467 {
00468 detail::pack_message_visitor<DataStreamType> pack_visitor( m_os );
00469 boost::reflect::reflector<T>::visit( value, pack_visitor, -1 );
00470 }
00471
00472 void pack( const std::string& value, boost::false_type _is_not_fundamental, boost::mpl::false_ _is_not_fusion_sequence)
00473 {
00474 uint32_t size = value.size();
00475 m_os <<unsigned_int( size );
00476 m_os.write( value.c_str(), size );
00477 }
00478
00479 template< typename T >
00480 void pack( const T& value, boost::true_type _is_fundamental, boost::mpl::false_ _is_not_fusion_sequence)
00481 {
00482 m_os << value;
00483 }
00484 template< typename T >
00485 void pack( const T& value )
00486 {
00487 pack( value, typename boost::is_fundamental<T>::type(), typename boost::fusion::traits::is_sequence<T>::type() );
00488 }
00489
00490 template<typename Flags>
00491 void pack_field( const signed_int& value, const char* name, Flags key, boost::false_type _is_not_fundamental )
00492 {
00493 m_os << unsigned_int( uint32_t(key) << 3 | varint );
00494 m_os << value;
00495 }
00496 template<typename Flags>
00497 void pack_field( const unsigned_int& value, const char* name, Flags key, boost::false_type _is_not_fundamental )
00498 {
00499 m_os << unsigned_int( uint32_t(key) << 3 | varint );
00500 m_os << value;
00501 }
00502 template<typename Flags>
00503 void pack_field( const std::string& value, const char* name, Flags key, boost::false_type _is_not_fundamental )
00504 {
00505 m_os <<unsigned_int( uint32_t(key) << 3 | length_delimited );
00506 pack( value );
00507 }
00508 template<typename T, typename Flags>
00509 void pack_field( const boost::optional<T>& value, const char* name, Flags key, boost::false_type _is_not_fundamental )
00510 {
00511 if( !!value )
00512 pack_field( *value, name, key, typename boost::is_fundamental<T>::type() );
00513 }
00514 template<typename T, typename Flags>
00515 void pack_field( const typename boost::rpc::required<T>& value, const char* name, Flags key, boost::false_type _is_not_fundamental )
00516 {
00517 if( !!value )
00518 pack_field( *value, name, key, typename boost::is_fundamental<T>::type() );
00519 else
00520 BOOST_THROW_EXCEPTION( boost::rpc::required_field_not_set() );
00521 }
00522
00523 template<typename Class, typename T, typename Flags>
00524 void accept_member( const Class& c, T (Class::*p), const char* name, Flags key )
00525 {
00526 pack_field( c.*p, name, key, typename boost::is_fundamental<T>::type() );
00527 }
00528
00529
00530
00531
00532 template<typename Class, typename Field, typename Alloc, template<typename,typename> class Container, typename Flags>
00533 void accept_member( const Class& c, Container<Field,Alloc> (Class::*p), const char* name, Flags key )
00534 {
00535 if( (c.*p).size() )
00536 {
00537 typename Container<Field,Alloc >::const_iterator itr = (c.*p).begin();
00538 typename Container<Field,Alloc >::const_iterator end = (c.*p).end();
00539 while( itr != end )
00540 {
00541 pack_field( *itr, name, key, typename boost::is_fundamental<Field>::type() );
00542 ++itr;
00543 }
00544 }
00545 }
00546 template<typename Class>
00547 void not_found( Class c, uint32_t field )
00548 {
00549 BOOST_THROW_EXCEPTION( boost::rpc::protocol_buffer::field_not_found() );
00550 }
00551
00552 private:
00553 boost::rpc::datastream<DataStreamType>& m_os;
00554 };
00555
00556 }
00557
00558 template<typename T>
00559 size_t packsize( const T& v )
00560 {
00561 boost::rpc::datastream<size_t> ps;
00562 detail::pack_message_visitor<size_t> size_visitor( ps );
00563 size_visitor.pack(v);
00564
00565 return ps.tellp();
00566 }
00567 template<typename T>
00568 void pack( char* loc, size_t loc_size, const T& v )
00569 {
00570 boost::rpc::datastream<char*> ds(loc, loc_size);
00571 detail::pack_message_visitor<char*> pack_visitor( ds );
00572 pack_visitor.pack(v);
00573 }
00574 template<typename T, typename DataStreamType>
00575 void pack( boost::rpc::datastream<DataStreamType>& ds, const T& v )
00576 {
00577 detail::pack_message_visitor<DataStreamType> pack_visitor( ds );
00578 pack_visitor.pack(v);
00579 }
00580 template<typename T>
00581 void pack( std::vector<char>& msg, const T& v )
00582 {
00583 msg.resize(packsize(v));
00584 pack( &msg.front(), msg.size(), v );
00585 }
00586 template<typename T>
00587 void pack( std::string& msg, const T& v )
00588 {
00589 msg.resize(packsize(v));
00590 pack( msg.c_str(), msg.size(), v );
00591 }
00592
00593 template<typename T>
00594 void unpack( const char* msg, size_t msg_size, T& v )
00595 {
00596 elog( "unpack '%1%'", boost::reflect::get_typeinfo<T>::name() );
00597 boost::rpc::datastream<const char*> ds(msg,msg_size);
00598 detail::unpack_message_visitor( ds, v );
00599
00600
00601
00602 }
00603
00604 template<typename T>
00605 void unpack( const std::vector<char>& msg, T& v )
00606 {
00607 if( msg.size() )
00608 unpack( &msg.front(), msg.size(), v );
00609 }
00610
00611
00612 } } }
00613
00614 #endif // _BOOST_RPC_DETAIL_PROTOCOL_BUFFERS_HPP_
00615