2014-05-30 08:53:19 +00:00
/*
This file is part of Telegram Desktop ,
2018-01-03 10:23:14 +00:00
the official desktop application for the Telegram messaging service .
2014-05-30 08:53:19 +00:00
2018-01-03 10:23:14 +00:00
For license and copyright information please follow this link :
https : //github.com/telegramdesktop/tdesktop/blob/master/LEGAL
2014-05-30 08:53:19 +00:00
*/
# pragma once
2016-04-12 21:31:28 +00:00
# include "core/basic_types.h"
2017-08-31 16:28:58 +00:00
# include "base/flags.h"
2018-03-27 12:16:00 +00:00
# include "base/bytes.h"
2014-05-30 08:53:19 +00:00
2016-03-24 08:57:11 +00:00
namespace MTP {
2015-02-19 11:30:16 +00:00
2016-03-24 08:57:11 +00:00
// type DcId represents actual data center id, while in most cases
// we use some shifted ids, like DcId() + X * DCShift
2017-02-25 16:44:02 +00:00
using DcId = int32 ;
2017-02-27 18:47:29 +00:00
using ShiftedDcId = int32 ;
2014-05-30 08:53:19 +00:00
2017-03-09 18:13:55 +00:00
} // namespace MTP
2014-05-30 08:53:19 +00:00
2017-02-25 16:44:02 +00:00
using mtpPrime = int32 ;
using mtpRequestId = int32 ;
using mtpMsgId = uint64 ;
using mtpPingId = uint64 ;
2014-05-30 08:53:19 +00:00
2017-02-25 16:44:02 +00:00
using mtpBuffer = QVector < mtpPrime > ;
using mtpTypeId = uint32 ;
2014-05-30 08:53:19 +00:00
class mtpRequestData ;
2017-12-18 09:07:18 +00:00
class mtpRequest : public std : : shared_ptr < mtpRequestData > {
2014-05-30 08:53:19 +00:00
public :
2017-08-12 07:17:33 +00:00
mtpRequest ( ) = default ;
2017-12-18 09:07:18 +00:00
explicit mtpRequest ( mtpRequestData * ptr )
: std : : shared_ptr < mtpRequestData > ( ptr ) {
2014-05-30 08:53:19 +00:00
}
2014-11-14 23:23:35 +00:00
uint32 innerLength ( ) const ;
2014-05-30 08:53:19 +00:00
void write ( mtpBuffer & to ) const ;
2017-02-25 16:44:02 +00:00
using ResponseType = void ; // don't know real response type =(
2014-05-30 08:53:19 +00:00
} ;
class mtpRequestData : public mtpBuffer {
public :
// in toSend: = 0 - must send in container, > 0 - can send without container
// in haveSent: = 0 - container with msgIds, > 0 - when was sent
2017-08-12 07:17:33 +00:00
TimeMs msDate = 0 ;
2014-11-14 23:23:35 +00:00
2017-08-12 07:17:33 +00:00
mtpRequestId requestId = 0 ;
2014-11-05 17:43:32 +00:00
mtpRequest after ;
2017-08-12 07:17:33 +00:00
bool needsLayer = false ;
2014-05-30 08:53:19 +00:00
2017-08-12 07:17:33 +00:00
mtpRequestData ( bool /* sure*/ ) {
2014-05-30 08:53:19 +00:00
}
2017-08-12 07:17:33 +00:00
static mtpRequest prepare ( uint32 requestSize , uint32 maxSize = 0 ) ;
static void padding ( mtpRequest & request ) ;
2014-05-30 08:53:19 +00:00
2017-12-18 12:40:15 +00:00
template < typename TRequest >
static mtpRequest serialize ( const TRequest & request ) {
const auto requestSize = request . innerLength ( ) > > 2 ;
auto serialized = prepare ( requestSize ) ;
request . write ( * serialized ) ;
return serialized ;
}
2014-05-30 08:53:19 +00:00
static uint32 messageSize ( const mtpRequest & request ) {
if ( request - > size ( ) < 9 ) return 0 ;
2014-11-14 23:23:35 +00:00
return 4 + ( request . innerLength ( ) > > 2 ) ; // 2: msg_id, 1: seq_no, q: message_length
2014-05-30 08:53:19 +00:00
}
static bool isSentContainer ( const mtpRequest & request ) ; // "request-like" wrap for msgIds vector
static bool isStateRequest ( const mtpRequest & request ) ;
2017-08-12 07:17:33 +00:00
static bool needAck ( const mtpRequest & request ) {
if ( request - > size ( ) < 9 ) return false ;
return mtpRequestData : : needAckByType ( ( * request ) [ 8 ] ) ;
}
2014-05-30 08:53:19 +00:00
static bool needAckByType ( mtpTypeId type ) ;
private :
2017-08-12 07:17:33 +00:00
static uint32 _padding ( uint32 requestSize ) ;
2014-05-30 08:53:19 +00:00
} ;
2017-02-25 16:44:02 +00:00
using mtpPreRequestMap = QMap < mtpRequestId , mtpRequest > ;
using mtpRequestMap = QMap < mtpMsgId , mtpRequest > ;
using mtpMsgIdsSet = QMap < mtpMsgId , bool > ;
2014-05-30 08:53:19 +00:00
class mtpRequestIdsMap : public QMap < mtpMsgId , mtpRequestId > {
public :
2017-02-25 16:44:02 +00:00
using ParentType = QMap < mtpMsgId , mtpRequestId > ;
2014-05-30 08:53:19 +00:00
mtpMsgId min ( ) const {
return size ( ) ? cbegin ( ) . key ( ) : 0 ;
}
mtpMsgId max ( ) const {
ParentType : : const_iterator e ( cend ( ) ) ;
return size ( ) ? ( - - e ) . key ( ) : 0 ;
}
} ;
class mtpErrorUnexpected : public Exception {
public :
2015-10-03 10:09:09 +00:00
mtpErrorUnexpected ( mtpTypeId typeId , const QString & type ) : Exception ( QString ( " MTP Unexpected type id #%1 read in %2 " ) . arg ( uint32 ( typeId ) , 0 , 16 ) . arg ( type ) , false ) { // maybe api changed?..
2014-05-30 08:53:19 +00:00
}
2017-08-12 07:17:33 +00:00
2014-05-30 08:53:19 +00:00
} ;
class mtpErrorInsufficient : public Exception {
public :
mtpErrorInsufficient ( ) : Exception ( " MTP Insufficient bytes in input buffer " ) {
}
2017-08-12 07:17:33 +00:00
2014-05-30 08:53:19 +00:00
} ;
class mtpErrorBadTypeId : public Exception {
public :
mtpErrorBadTypeId ( mtpTypeId typeId , const QString & type ) : Exception ( QString ( " MTP Bad type id %1 passed to constructor of %2 " ) . arg ( typeId ) . arg ( type ) ) {
}
2017-08-12 07:17:33 +00:00
2014-05-30 08:53:19 +00:00
} ;
2017-03-11 17:03:36 +00:00
namespace MTP {
namespace internal {
class TypeData {
2014-05-30 08:53:19 +00:00
public :
2017-03-11 17:03:36 +00:00
TypeData ( ) = default ;
TypeData ( const TypeData & other ) = delete ;
TypeData ( TypeData & & other ) = delete ;
TypeData & operator = ( const TypeData & other ) = delete ;
TypeData & operator = ( TypeData & & other ) = delete ;
2017-03-13 15:40:21 +00:00
virtual ~ TypeData ( ) {
}
private :
2017-03-11 17:03:36 +00:00
void incrementCounter ( ) const {
_counter . ref ( ) ;
}
bool decrementCounter ( ) const {
return _counter . deref ( ) ;
2014-05-30 08:53:19 +00:00
}
2017-03-13 15:40:21 +00:00
friend class TypeDataOwner ;
2014-05-30 08:53:19 +00:00
2017-03-11 17:03:36 +00:00
mutable QAtomicInt _counter = { 1 } ;
2014-05-30 08:53:19 +00:00
} ;
2017-03-11 17:03:36 +00:00
class TypeDataOwner {
2014-05-30 08:53:19 +00:00
public :
2017-03-11 17:03:36 +00:00
TypeDataOwner ( TypeDataOwner & & other ) : _data ( base : : take ( other . _data ) ) {
}
TypeDataOwner ( const TypeDataOwner & other ) : _data ( other . _data ) {
incrementCounter ( ) ;
}
TypeDataOwner & operator = ( TypeDataOwner & & other ) {
if ( other . _data ! = _data ) {
decrementCounter ( ) ;
_data = base : : take ( other . _data ) ;
}
return * this ;
}
TypeDataOwner & operator = ( const TypeDataOwner & other ) {
if ( other . _data ! = _data ) {
setData ( other . _data ) ;
incrementCounter ( ) ;
}
return * this ;
}
~ TypeDataOwner ( ) {
decrementCounter ( ) ;
}
2014-05-30 08:53:19 +00:00
protected :
2017-03-11 17:03:36 +00:00
TypeDataOwner ( ) = default ;
TypeDataOwner ( const TypeData * data ) : _data ( data ) {
}
void setData ( const TypeData * data ) {
decrementCounter ( ) ;
_data = data ;
}
2017-08-12 07:17:33 +00:00
// Unsafe cast, type should be checked by the caller.
2017-03-11 17:03:36 +00:00
template < typename DataType >
const DataType & queryData ( ) const {
2017-08-12 07:17:33 +00:00
Expects ( _data ! = nullptr ) ;
2017-03-11 17:03:36 +00:00
return static_cast < const DataType & > ( * _data ) ;
}
private :
void incrementCounter ( ) {
if ( _data ) {
_data - > incrementCounter ( ) ;
}
}
void decrementCounter ( ) {
if ( _data & & ! _data - > decrementCounter ( ) ) {
delete base : : take ( _data ) ;
}
2014-05-30 08:53:19 +00:00
}
2017-03-11 17:03:36 +00:00
const TypeData * _data = nullptr ;
2017-03-09 18:13:55 +00:00
2014-05-30 08:53:19 +00:00
} ;
2017-03-11 17:03:36 +00:00
} // namespace internal
} // namespace MTP
2014-05-30 08:53:19 +00:00
enum {
// core types
mtpc_int = 0xa8509bda ,
mtpc_long = 0x22076cba ,
mtpc_int128 = 0x4bb5362b ,
mtpc_int256 = 0x929c32f ,
mtpc_double = 0x2210c154 ,
mtpc_string = 0xb5286e24 ,
mtpc_vector = 0x1cb5c415 ,
// layers
mtpc_invokeWithLayer1 = 0x53835315 ,
mtpc_invokeWithLayer2 = 0x289dd1f6 ,
mtpc_invokeWithLayer3 = 0xb7475268 ,
mtpc_invokeWithLayer4 = 0xdea0d430 ,
mtpc_invokeWithLayer5 = 0x417a57ae ,
mtpc_invokeWithLayer6 = 0x3a64d54d ,
mtpc_invokeWithLayer7 = 0xa5be56d3 ,
mtpc_invokeWithLayer8 = 0xe9abd9fd ,
mtpc_invokeWithLayer9 = 0x76715a63 ,
mtpc_invokeWithLayer10 = 0x39620c41 ,
mtpc_invokeWithLayer11 = 0xa6b88fdf ,
mtpc_invokeWithLayer12 = 0xdda60d3c ,
mtpc_invokeWithLayer13 = 0x427c8ea2 ,
mtpc_invokeWithLayer14 = 0x2b9b08fa ,
2014-07-04 11:12:54 +00:00
mtpc_invokeWithLayer15 = 0xb4418b64 ,
2014-10-22 18:39:03 +00:00
mtpc_invokeWithLayer16 = 0xcf5f0987 ,
mtpc_invokeWithLayer17 = 0x50858a19 ,
mtpc_invokeWithLayer18 = 0x1c900537 ,
2014-05-30 08:53:19 +00:00
// manually parsed
mtpc_rpc_result = 0xf35c6d01 ,
mtpc_msg_container = 0x73f1f8dc ,
// mtpc_msg_copy = 0xe06046b2,
mtpc_gzip_packed = 0x3072cfa1
} ;
2014-06-14 19:32:11 +00:00
static const mtpTypeId mtpc_bytes = mtpc_string ;
2016-03-19 16:55:15 +00:00
static const mtpTypeId mtpc_flags = mtpc_int ;
2014-06-14 19:32:11 +00:00
static const mtpTypeId mtpc_core_message = - 1 ; // undefined type, but is used
static const mtpTypeId mtpLayers [ ] = {
2015-10-23 16:06:56 +00:00
mtpTypeId ( mtpc_invokeWithLayer1 ) ,
mtpTypeId ( mtpc_invokeWithLayer2 ) ,
mtpTypeId ( mtpc_invokeWithLayer3 ) ,
mtpTypeId ( mtpc_invokeWithLayer4 ) ,
mtpTypeId ( mtpc_invokeWithLayer5 ) ,
mtpTypeId ( mtpc_invokeWithLayer6 ) ,
mtpTypeId ( mtpc_invokeWithLayer7 ) ,
mtpTypeId ( mtpc_invokeWithLayer8 ) ,
mtpTypeId ( mtpc_invokeWithLayer9 ) ,
mtpTypeId ( mtpc_invokeWithLayer10 ) ,
mtpTypeId ( mtpc_invokeWithLayer11 ) ,
mtpTypeId ( mtpc_invokeWithLayer12 ) ,
mtpTypeId ( mtpc_invokeWithLayer13 ) ,
mtpTypeId ( mtpc_invokeWithLayer14 ) ,
mtpTypeId ( mtpc_invokeWithLayer15 ) ,
mtpTypeId ( mtpc_invokeWithLayer16 ) ,
mtpTypeId ( mtpc_invokeWithLayer17 ) ,
mtpTypeId ( mtpc_invokeWithLayer18 ) ,
2015-10-19 21:16:17 +00:00
} ;
static const uint32 mtpLayerMaxSingle = sizeof ( mtpLayers ) / sizeof ( mtpLayers [ 0 ] ) ;
2014-05-30 08:53:19 +00:00
template < typename bareT >
class MTPBoxed : public bareT {
public :
2017-08-12 07:17:33 +00:00
using bareT : : bareT ;
2017-03-09 19:15:31 +00:00
MTPBoxed ( ) = default ;
2017-08-12 07:17:33 +00:00
MTPBoxed ( const MTPBoxed < bareT > & v ) = default ;
MTPBoxed < bareT > & operator = ( const MTPBoxed < bareT > & v ) = default ;
2014-05-30 08:53:19 +00:00
MTPBoxed ( const bareT & v ) : bareT ( v ) {
}
MTPBoxed < bareT > & operator = ( const bareT & v ) {
* ( ( bareT * ) this ) = v ;
return * this ;
}
2014-11-14 23:23:35 +00:00
uint32 innerLength ( ) const {
return sizeof ( mtpTypeId ) + bareT : : innerLength ( ) ;
2014-05-30 08:53:19 +00:00
}
void read ( const mtpPrime * & from , const mtpPrime * end , mtpTypeId cons = 0 ) {
if ( from + 1 > end ) throw mtpErrorInsufficient ( ) ;
cons = ( mtpTypeId ) * ( from + + ) ;
bareT : : read ( from , end , cons ) ;
}
void write ( mtpBuffer & to ) const {
to . push_back ( bareT : : type ( ) ) ;
bareT : : write ( to ) ;
}
2017-03-22 15:38:40 +00:00
using Unboxed = bareT ;
2014-05-30 08:53:19 +00:00
} ;
template < typename T >
class MTPBoxed < MTPBoxed < T > > {
typename T : : CantMakeBoxedBoxedType v ;
} ;
class MTPint {
public :
2017-03-09 19:15:31 +00:00
int32 v = 0 ;
2014-05-30 08:53:19 +00:00
2017-03-09 19:15:31 +00:00
MTPint ( ) = default ;
2014-05-30 08:53:19 +00:00
2014-11-14 23:23:35 +00:00
uint32 innerLength ( ) const {
2014-05-30 08:53:19 +00:00
return sizeof ( int32 ) ;
}
mtpTypeId type ( ) const {
return mtpc_int ;
}
void read ( const mtpPrime * & from , const mtpPrime * end , mtpTypeId cons = mtpc_int ) {
if ( from + 1 > end ) throw mtpErrorInsufficient ( ) ;
if ( cons ! = mtpc_int ) throw mtpErrorUnexpected ( cons , " MTPint " ) ;
v = ( int32 ) * ( from + + ) ;
}
void write ( mtpBuffer & to ) const {
to . push_back ( ( mtpPrime ) v ) ;
}
private :
explicit MTPint ( int32 val ) : v ( val ) {
}
friend MTPint MTP_int ( int32 v ) ;
} ;
inline MTPint MTP_int ( int32 v ) {
return MTPint ( v ) ;
}
2017-02-25 16:44:02 +00:00
using MTPInt = MTPBoxed < MTPint > ;
2014-05-30 08:53:19 +00:00
2017-03-25 15:42:01 +00:00
namespace internal {
struct ZeroFlagsHelper {
} ;
} // namespace internal
2016-03-19 16:55:15 +00:00
template < typename Flags >
class MTPflags {
public :
2017-08-31 16:28:58 +00:00
Flags v = 0 ;
2016-03-19 16:55:15 +00:00
static_assert ( sizeof ( Flags ) = = sizeof ( int32 ) , " MTPflags are allowed only wrapping int32 flag types! " ) ;
2017-03-09 19:15:31 +00:00
MTPflags ( ) = default ;
2017-03-25 15:42:01 +00:00
MTPflags ( internal : : ZeroFlagsHelper helper ) {
}
2016-03-19 16:55:15 +00:00
uint32 innerLength ( ) const {
return sizeof ( Flags ) ;
}
mtpTypeId type ( ) const {
return mtpc_flags ;
}
void read ( const mtpPrime * & from , const mtpPrime * end , mtpTypeId cons = mtpc_flags ) {
if ( from + 1 > end ) throw mtpErrorInsufficient ( ) ;
if ( cons ! = mtpc_flags ) throw mtpErrorUnexpected ( cons , " MTPflags " ) ;
2017-09-26 20:14:56 +00:00
v = Flags : : from_raw ( static_cast < typename Flags : : Type > ( * ( from + + ) ) ) ;
2016-03-19 16:55:15 +00:00
}
void write ( mtpBuffer & to ) const {
2017-09-26 11:49:16 +00:00
to . push_back ( static_cast < mtpPrime > ( v . value ( ) ) ) ;
2016-03-19 16:55:15 +00:00
}
private :
explicit MTPflags ( Flags val ) : v ( val ) {
}
template < typename T >
2017-08-31 16:28:58 +00:00
friend MTPflags < base : : flags < T > > MTP_flags ( base : : flags < T > v ) ;
2017-03-25 15:42:01 +00:00
template < typename T , typename >
2017-08-31 16:28:58 +00:00
friend MTPflags < base : : flags < T > > MTP_flags ( T v ) ;
2017-03-25 15:42:01 +00:00
2016-03-19 16:55:15 +00:00
} ;
template < typename T >
2017-08-31 16:28:58 +00:00
inline MTPflags < base : : flags < T > > MTP_flags ( base : : flags < T > v ) {
return MTPflags < base : : flags < T > > ( v ) ;
2017-03-25 15:42:01 +00:00
}
template < typename T , typename = std : : enable_if_t < ! std : : is_same < T , int > : : value > >
2017-08-31 16:28:58 +00:00
inline MTPflags < base : : flags < T > > MTP_flags ( T v ) {
return MTPflags < base : : flags < T > > ( v ) ;
2017-03-25 15:42:01 +00:00
}
inline internal : : ZeroFlagsHelper MTP_flags ( void ( internal : : ZeroFlagsHelper : : * ) ( ) ) {
return internal : : ZeroFlagsHelper ( ) ;
2016-03-19 16:55:15 +00:00
}
template < typename Flags >
using MTPFlags = MTPBoxed < MTPflags < Flags > > ;
2014-05-30 08:53:19 +00:00
inline bool operator = = ( const MTPint & a , const MTPint & b ) {
return a . v = = b . v ;
}
inline bool operator ! = ( const MTPint & a , const MTPint & b ) {
return a . v ! = b . v ;
}
class MTPlong {
public :
2017-03-09 19:15:31 +00:00
uint64 v = 0 ;
2014-05-30 08:53:19 +00:00
2017-03-09 19:15:31 +00:00
MTPlong ( ) = default ;
2014-05-30 08:53:19 +00:00
2014-11-14 23:23:35 +00:00
uint32 innerLength ( ) const {
2014-05-30 08:53:19 +00:00
return sizeof ( uint64 ) ;
}
mtpTypeId type ( ) const {
return mtpc_long ;
}
void read ( const mtpPrime * & from , const mtpPrime * end , mtpTypeId cons = mtpc_long ) {
if ( from + 2 > end ) throw mtpErrorInsufficient ( ) ;
if ( cons ! = mtpc_long ) throw mtpErrorUnexpected ( cons , " MTPlong " ) ;
v = ( uint64 ) ( ( ( uint32 * ) from ) [ 0 ] ) | ( ( uint64 ) ( ( ( uint32 * ) from ) [ 1 ] ) < < 32 ) ;
from + = 2 ;
}
void write ( mtpBuffer & to ) const {
to . push_back ( ( mtpPrime ) ( v & 0xFFFFFFFFL ) ) ;
to . push_back ( ( mtpPrime ) ( v > > 32 ) ) ;
}
private :
explicit MTPlong ( uint64 val ) : v ( val ) {
}
friend MTPlong MTP_long ( uint64 v ) ;
} ;
inline MTPlong MTP_long ( uint64 v ) {
return MTPlong ( v ) ;
}
2017-02-25 16:44:02 +00:00
using MTPLong = MTPBoxed < MTPlong > ;
2014-05-30 08:53:19 +00:00
inline bool operator = = ( const MTPlong & a , const MTPlong & b ) {
return a . v = = b . v ;
}
inline bool operator ! = ( const MTPlong & a , const MTPlong & b ) {
return a . v ! = b . v ;
}
class MTPint128 {
public :
2017-03-09 19:15:31 +00:00
uint64 l = 0 ;
uint64 h = 0 ;
2014-05-30 08:53:19 +00:00
2017-03-09 19:15:31 +00:00
MTPint128 ( ) = default ;
2014-05-30 08:53:19 +00:00
2014-11-14 23:23:35 +00:00
uint32 innerLength ( ) const {
2014-05-30 08:53:19 +00:00
return sizeof ( uint64 ) + sizeof ( uint64 ) ;
}
mtpTypeId type ( ) const {
return mtpc_int128 ;
}
void read ( const mtpPrime * & from , const mtpPrime * end , mtpTypeId cons = mtpc_int128 ) {
if ( from + 4 > end ) throw mtpErrorInsufficient ( ) ;
if ( cons ! = mtpc_int128 ) throw mtpErrorUnexpected ( cons , " MTPint128 " ) ;
l = ( uint64 ) ( ( ( uint32 * ) from ) [ 0 ] ) | ( ( uint64 ) ( ( ( uint32 * ) from ) [ 1 ] ) < < 32 ) ;
h = ( uint64 ) ( ( ( uint32 * ) from ) [ 2 ] ) | ( ( uint64 ) ( ( ( uint32 * ) from ) [ 3 ] ) < < 32 ) ;
from + = 4 ;
}
void write ( mtpBuffer & to ) const {
to . push_back ( ( mtpPrime ) ( l & 0xFFFFFFFFL ) ) ;
to . push_back ( ( mtpPrime ) ( l > > 32 ) ) ;
to . push_back ( ( mtpPrime ) ( h & 0xFFFFFFFFL ) ) ;
to . push_back ( ( mtpPrime ) ( h > > 32 ) ) ;
}
private :
explicit MTPint128 ( uint64 low , uint64 high ) : l ( low ) , h ( high ) {
}
friend MTPint128 MTP_int128 ( uint64 l , uint64 h ) ;
} ;
inline MTPint128 MTP_int128 ( uint64 l , uint64 h ) {
return MTPint128 ( l , h ) ;
}
2017-02-25 16:44:02 +00:00
using MTPInt128 = MTPBoxed < MTPint128 > ;
2014-05-30 08:53:19 +00:00
inline bool operator = = ( const MTPint128 & a , const MTPint128 & b ) {
return a . l = = b . l & & a . h = = b . h ;
}
inline bool operator ! = ( const MTPint128 & a , const MTPint128 & b ) {
return a . l ! = b . l | | a . h ! = b . h ;
}
class MTPint256 {
public :
MTPint128 l ;
MTPint128 h ;
2017-03-09 19:15:31 +00:00
MTPint256 ( ) = default ;
2014-05-30 08:53:19 +00:00
2014-11-14 23:23:35 +00:00
uint32 innerLength ( ) const {
return l . innerLength ( ) + h . innerLength ( ) ;
2014-05-30 08:53:19 +00:00
}
mtpTypeId type ( ) const {
return mtpc_int256 ;
}
void read ( const mtpPrime * & from , const mtpPrime * end , mtpTypeId cons = mtpc_int256 ) {
if ( cons ! = mtpc_int256 ) throw mtpErrorUnexpected ( cons , " MTPint256 " ) ;
l . read ( from , end ) ;
h . read ( from , end ) ;
}
void write ( mtpBuffer & to ) const {
l . write ( to ) ;
h . write ( to ) ;
}
private :
explicit MTPint256 ( MTPint128 low , MTPint128 high ) : l ( low ) , h ( high ) {
}
friend MTPint256 MTP_int256 ( const MTPint128 & l , const MTPint128 & h ) ;
} ;
inline MTPint256 MTP_int256 ( const MTPint128 & l , const MTPint128 & h ) {
return MTPint256 ( l , h ) ;
}
2017-02-25 16:44:02 +00:00
using MTPInt256 = MTPBoxed < MTPint256 > ;
2014-05-30 08:53:19 +00:00
inline bool operator = = ( const MTPint256 & a , const MTPint256 & b ) {
return a . l = = b . l & & a . h = = b . h ;
}
inline bool operator ! = ( const MTPint256 & a , const MTPint256 & b ) {
return a . l ! = b . l | | a . h ! = b . h ;
}
class MTPdouble {
public :
2017-03-09 19:15:31 +00:00
float64 v = 0. ;
2016-01-11 15:43:29 +00:00
2017-03-09 19:15:31 +00:00
MTPdouble ( ) = default ;
2014-05-30 08:53:19 +00:00
2014-11-14 23:23:35 +00:00
uint32 innerLength ( ) const {
2014-05-30 08:53:19 +00:00
return sizeof ( float64 ) ;
}
mtpTypeId type ( ) const {
return mtpc_double ;
}
void read ( const mtpPrime * & from , const mtpPrime * end , mtpTypeId cons = mtpc_double ) {
if ( from + 2 > end ) throw mtpErrorInsufficient ( ) ;
if ( cons ! = mtpc_double ) throw mtpErrorUnexpected ( cons , " MTPdouble " ) ;
* ( uint64 * ) ( & v ) = ( uint64 ) ( ( ( uint32 * ) from ) [ 0 ] ) | ( ( uint64 ) ( ( ( uint32 * ) from ) [ 1 ] ) < < 32 ) ;
from + = 2 ;
}
void write ( mtpBuffer & to ) const {
uint64 iv = * ( uint64 * ) ( & v ) ;
to . push_back ( ( mtpPrime ) ( iv & 0xFFFFFFFFL ) ) ;
to . push_back ( ( mtpPrime ) ( iv > > 32 ) ) ;
}
private :
explicit MTPdouble ( float64 val ) : v ( val ) {
}
friend MTPdouble MTP_double ( float64 v ) ;
} ;
inline MTPdouble MTP_double ( float64 v ) {
return MTPdouble ( v ) ;
}
2017-02-25 16:44:02 +00:00
using MTPDouble = MTPBoxed < MTPdouble > ;
2014-05-30 08:53:19 +00:00
inline bool operator = = ( const MTPdouble & a , const MTPdouble & b ) {
return a . v = = b . v ;
}
inline bool operator ! = ( const MTPdouble & a , const MTPdouble & b ) {
return a . v ! = b . v ;
}
2017-03-10 19:46:28 +00:00
class MTPstring ;
using MTPbytes = MTPstring ;
2014-05-30 08:53:19 +00:00
2017-03-10 19:46:28 +00:00
class MTPstring {
2014-05-30 08:53:19 +00:00
public :
2017-03-09 19:15:31 +00:00
MTPstring ( ) = default ;
2014-05-30 08:53:19 +00:00
2017-08-12 07:17:33 +00:00
uint32 innerLength ( ) const ;
2014-05-30 08:53:19 +00:00
mtpTypeId type ( ) const {
return mtpc_string ;
}
2017-08-12 07:17:33 +00:00
void read ( const mtpPrime * & from , const mtpPrime * end , mtpTypeId cons = mtpc_string ) ;
void write ( mtpBuffer & to ) const ;
2014-05-30 08:53:19 +00:00
2017-03-10 19:46:28 +00:00
QByteArray v ;
2014-05-30 08:53:19 +00:00
private :
2017-03-10 19:46:28 +00:00
explicit MTPstring ( QByteArray & & data ) : v ( std : : move ( data ) ) {
2014-05-30 08:53:19 +00:00
}
2016-09-29 11:37:16 +00:00
friend MTPstring MTP_string ( const std : : string & v ) ;
2014-05-30 08:53:19 +00:00
friend MTPstring MTP_string ( const QString & v ) ;
friend MTPstring MTP_string ( const char * v ) ;
2016-04-01 10:23:40 +00:00
2017-03-10 19:46:28 +00:00
friend MTPbytes MTP_bytes ( const QByteArray & v ) ;
friend MTPbytes MTP_bytes ( QByteArray & & v ) ;
2017-03-09 18:13:55 +00:00
2014-05-30 08:53:19 +00:00
} ;
2017-03-10 19:46:28 +00:00
using MTPString = MTPBoxed < MTPstring > ;
using MTPBytes = MTPBoxed < MTPbytes > ;
2016-09-29 11:37:16 +00:00
inline MTPstring MTP_string ( const std : : string & v ) {
2017-03-10 19:46:28 +00:00
return MTPstring ( QByteArray ( v . data ( ) , v . size ( ) ) ) ;
2014-05-30 08:53:19 +00:00
}
inline MTPstring MTP_string ( const QString & v ) {
2017-03-10 19:46:28 +00:00
return MTPstring ( v . toUtf8 ( ) ) ;
2014-05-30 08:53:19 +00:00
}
inline MTPstring MTP_string ( const char * v ) {
2017-03-10 19:46:28 +00:00
return MTPstring ( QByteArray ( v , strlen ( v ) ) ) ;
2014-05-30 08:53:19 +00:00
}
2016-04-07 16:49:15 +00:00
MTPstring MTP_string ( const QByteArray & v ) = delete ;
2016-04-01 10:23:40 +00:00
inline MTPbytes MTP_bytes ( const QByteArray & v ) {
2017-03-10 19:46:28 +00:00
return MTPbytes ( QByteArray ( v ) ) ;
}
inline MTPbytes MTP_bytes ( QByteArray & & v ) {
return MTPbytes ( std : : move ( v ) ) ;
2016-04-01 10:23:40 +00:00
}
2018-03-27 12:16:00 +00:00
inline MTPbytes MTP_bytes ( bytes : : const_span buffer ) {
return MTP_bytes ( QByteArray (
reinterpret_cast < const char * > ( buffer . data ( ) ) ,
buffer . size ( ) ) ) ;
2017-04-19 18:06:01 +00:00
}
2018-03-27 12:16:00 +00:00
inline MTPbytes MTP_bytes ( const bytes : : vector & buffer ) {
return MTP_bytes ( bytes : : make_span ( buffer ) ) ;
2017-04-19 18:06:01 +00:00
}
2014-05-30 08:53:19 +00:00
inline bool operator = = ( const MTPstring & a , const MTPstring & b ) {
2017-03-10 19:46:28 +00:00
return a . v = = b . v ;
2014-05-30 08:53:19 +00:00
}
inline bool operator ! = ( const MTPstring & a , const MTPstring & b ) {
2017-03-10 19:46:28 +00:00
return a . v ! = b . v ;
2014-05-30 08:53:19 +00:00
}
inline QString qs ( const MTPstring & v ) {
2017-03-10 19:46:28 +00:00
return QString : : fromUtf8 ( v . v ) ;
2015-01-02 14:55:24 +00:00
}
inline QByteArray qba ( const MTPstring & v ) {
2017-03-10 19:46:28 +00:00
return v . v ;
2014-05-30 08:53:19 +00:00
}
template < typename T >
2017-03-10 19:46:28 +00:00
class MTPvector {
2014-05-30 08:53:19 +00:00
public :
2017-03-09 19:15:31 +00:00
MTPvector ( ) = default ;
2014-05-30 08:53:19 +00:00
2014-11-14 23:23:35 +00:00
uint32 innerLength ( ) const {
2014-05-30 08:53:19 +00:00
uint32 result ( sizeof ( uint32 ) ) ;
2017-03-10 19:46:28 +00:00
for_const ( auto & item , v ) {
2017-03-09 18:13:55 +00:00
result + = item . innerLength ( ) ;
2014-05-30 08:53:19 +00:00
}
return result ;
}
mtpTypeId type ( ) const {
return mtpc_vector ;
}
void read ( const mtpPrime * & from , const mtpPrime * end , mtpTypeId cons = mtpc_vector ) {
if ( from + 1 > end ) throw mtpErrorInsufficient ( ) ;
if ( cons ! = mtpc_vector ) throw mtpErrorUnexpected ( cons , " MTPvector " ) ;
2017-03-09 19:15:31 +00:00
auto count = static_cast < uint32 > ( * ( from + + ) ) ;
2014-05-30 08:53:19 +00:00
2017-03-09 19:15:31 +00:00
auto vector = QVector < T > ( count , T ( ) ) ;
for ( auto & item : vector ) {
item . read ( from , end ) ;
2014-05-30 08:53:19 +00:00
}
2017-03-10 19:46:28 +00:00
v = std : : move ( vector ) ;
2014-05-30 08:53:19 +00:00
}
void write ( mtpBuffer & to ) const {
2017-03-10 19:46:28 +00:00
to . push_back ( v . size ( ) ) ;
for_const ( auto & item , v ) {
2017-03-09 18:13:55 +00:00
item . write ( to ) ;
2014-05-30 08:53:19 +00:00
}
}
2017-03-10 19:46:28 +00:00
QVector < T > v ;
2014-05-30 08:53:19 +00:00
private :
2017-03-10 19:46:28 +00:00
explicit MTPvector ( QVector < T > & & data ) : v ( std : : move ( data ) ) {
2014-05-30 08:53:19 +00:00
}
2016-03-20 08:16:35 +00:00
template < typename U >
friend MTPvector < U > MTP_vector ( uint32 count ) ;
template < typename U >
friend MTPvector < U > MTP_vector ( uint32 count , const U & value ) ;
template < typename U >
friend MTPvector < U > MTP_vector ( const QVector < U > & v ) ;
2017-03-09 18:13:55 +00:00
template < typename U >
friend MTPvector < U > MTP_vector ( QVector < U > & & v ) ;
2014-05-30 08:53:19 +00:00
} ;
template < typename T >
inline MTPvector < T > MTP_vector ( uint32 count ) {
2017-03-10 19:46:28 +00:00
return MTPvector < T > ( QVector < T > ( count ) ) ;
2014-05-30 08:53:19 +00:00
}
template < typename T >
2014-11-05 17:43:32 +00:00
inline MTPvector < T > MTP_vector ( uint32 count , const T & value ) {
2017-03-10 19:46:28 +00:00
return MTPvector < T > ( QVector < T > ( count , value ) ) ;
2014-11-05 17:43:32 +00:00
}
template < typename T >
2014-05-30 08:53:19 +00:00
inline MTPvector < T > MTP_vector ( const QVector < T > & v ) {
2017-03-10 19:46:28 +00:00
return MTPvector < T > ( QVector < T > ( v ) ) ;
2017-03-09 18:13:55 +00:00
}
template < typename T >
inline MTPvector < T > MTP_vector ( QVector < T > & & v ) {
2017-03-10 19:46:28 +00:00
return MTPvector < T > ( std : : move ( v ) ) ;
2014-05-30 08:53:19 +00:00
}
template < typename T >
2016-03-19 16:55:15 +00:00
using MTPVector = MTPBoxed < MTPvector < T > > ;
2014-05-30 08:53:19 +00:00
template < typename T >
inline bool operator = = ( const MTPvector < T > & a , const MTPvector < T > & b ) {
return a . c_vector ( ) . v = = b . c_vector ( ) . v ;
}
template < typename T >
inline bool operator ! = ( const MTPvector < T > & a , const MTPvector < T > & b ) {
return a . c_vector ( ) . v ! = b . c_vector ( ) . v ;
}
// Human-readable text serialization
2014-10-20 22:49:37 +00:00
struct MTPStringLogger {
MTPStringLogger ( ) : p ( new char [ MTPDebugBufferSize ] ) , size ( 0 ) , alloced ( MTPDebugBufferSize ) {
}
~ MTPStringLogger ( ) {
delete [ ] p ;
}
2014-05-30 08:53:19 +00:00
2014-10-20 22:49:37 +00:00
MTPStringLogger & add ( const QString & data ) {
2017-03-09 18:13:55 +00:00
auto d = data . toUtf8 ( ) ;
2014-10-20 22:49:37 +00:00
return add ( d . constData ( ) , d . size ( ) ) ;
}
2014-05-30 08:53:19 +00:00
2014-10-20 22:49:37 +00:00
MTPStringLogger & add ( const char * data , int32 len = - 1 ) {
if ( len < 0 ) len = strlen ( data ) ;
if ( ! len ) return ( * this ) ;
2014-05-30 08:53:19 +00:00
2014-10-25 09:25:18 +00:00
ensureLength ( len ) ;
2014-10-20 22:49:37 +00:00
memcpy ( p + size , data , len ) ;
size + = len ;
return ( * this ) ;
}
2014-10-25 09:25:18 +00:00
MTPStringLogger & addSpaces ( int32 level ) {
int32 len = level * 2 ;
if ( ! len ) return ( * this ) ;
ensureLength ( len ) ;
for ( char * ptr = p + size , * end = ptr + len ; ptr ! = end ; + + ptr ) {
* ptr = ' ' ;
}
size + = len ;
return ( * this ) ;
}
void ensureLength ( int32 add ) {
if ( size + add < = alloced ) return ;
int32 newsize = size + add ;
if ( newsize % MTPDebugBufferSize ) newsize + = MTPDebugBufferSize - ( newsize % MTPDebugBufferSize ) ;
char * b = new char [ newsize ] ;
memcpy ( b , p , size ) ;
alloced = newsize ;
2016-03-24 13:27:34 +00:00
delete [ ] p ;
2014-10-25 09:25:18 +00:00
p = b ;
}
2014-10-20 22:49:37 +00:00
char * p ;
int32 size , alloced ;
} ;
2014-05-30 08:53:19 +00:00
2014-10-20 22:49:37 +00:00
void mtpTextSerializeType ( MTPStringLogger & to , const mtpPrime * & from , const mtpPrime * end , mtpPrime cons = 0 , uint32 level = 0 , mtpPrime vcons = 0 ) ;
2014-05-30 08:53:19 +00:00
2014-10-20 22:49:37 +00:00
void mtpTextSerializeCore ( MTPStringLogger & to , const mtpPrime * & from , const mtpPrime * end , mtpTypeId cons , uint32 level , mtpPrime vcons = 0 ) ;
2014-05-30 08:53:19 +00:00
2014-10-20 22:49:37 +00:00
inline QString mtpTextSerialize ( const mtpPrime * & from , const mtpPrime * end ) {
MTPStringLogger to ;
2015-10-03 10:09:09 +00:00
try {
mtpTextSerializeType ( to , from , end , mtpc_core_message ) ;
} catch ( Exception & e ) {
to . add ( " [ERROR] ( " ) . add ( e . what ( ) ) . add ( " ) " ) ;
}
2014-10-20 22:49:37 +00:00
return QString : : fromUtf8 ( to . p , to . size ) ;
2014-05-30 08:53:19 +00:00
}