采用c++的注释规范。
//表示注释一行,/**/表示注释范围中的所有代码。
void
struct
bool
byte
short
int
double
float
long
string
vector
map
key
routekey
module
interface
out
require
optional
false
true
enum
const
所有标识符不能带有’tars_’符号,且必须以字母开头,同时不能和关键字冲突。
支持的基本类型包括以下:
void
:只能在函数的返回值表示
bool
:布尔类型,映射到 tars::Bool
byte
:有符号字符,映射到 tars::Char
short
:有符号短整型,映射到 tars::Short
int
:有符号整型,映射到 tars::Int32
long
:有符号长整型,映射到 tars::Int64
float
:映射到 tars::Float
double
:映射到 tars::Double
string
:映射到 std::string,java:String
unsigned byte
:无符号字符,c++映射到 unsigend char
其它版本 tars::Short
unsigned short
:无符号短整形c++映射到 unsigned short
其它版本 tars::Int32
Unsigned int
:无符号整形c++映射到 unsigned int
其它版本 tars::Int64
枚举类型的定义如下:
enum TE
{
E1,
E2,
E3
};
说明:
Tars文件中可以定义常量,例如:
const int a = 0;
const string s = “abc”;
说明:
结构定义如下:
struct Test
{
0 require string s;
1 optional int i = 23;
};
key[Test, s, i];
说明:
key说明:
key详细说明:
其他说明:
序列用vector来定义,如下:
vector<int> vi;
字典用map来定义,如下:
map<int, string> m;
说明:
结构中可以定义数组类型,数组用[]来定义,如下:
byte m[5];
说明:
mLen
vector<类型>
byte m[5]
等价于定义vector<byte>:5
结构中可以定义byte指针类型,指针用*来定义,如下:
byte *m;
指针类型使用时需要提前预分配内存块,指针需要内存时通过偏移指向预分配内存块,减少解码过程中的内存申请。
说明:
vector<类型>
任何struct
,map
,vector
都可以嵌套;
接口定义如下,例如:
interface Demo
{
int get(out vector<map<int, string>> v);
int set(vector<map<int, string>> v);
};
说明:
所有的struct,interface必须在名字空间中,例如:
module MemCache
{
struct Key
{
0 require string s;
};
struct Value
{
0 require string s;
};
interface MemCacheI
{
int get(Key k, out Value v);
int set(Key k, Value v);
};
};
说明:
每一个数据由两个部分组成,如下图:
| 头信息 | 实际数据 |
而其中头信息包括以下几个部分:
| Type(4 bits) | Tag 1(4 bits) | Tag 2(1 byte) |
Tag 2
是可选的,当Tag
的值不超过14时,只需要用Tag 1
就可以表示;当Tag
的值超过14而小于256时,Tag 1
固定为15,而用Tag 2
表示Tag
的值。Tag
不允许大于255。
Type
表示类型,用4个二进制位表示,取值范围是0~15,用来标识该数据的类型。不同类型的数据,其后紧跟着的实际数据的长度和格式都是不一样的,详见一下的类型表。
Tag
由Tag 1
和Tag 2
一起表示。取值范围是0~255,即该数据在结构中的字段ID,用来区分不同的字段。
注意,这里的类型与tars文件定义的类型是两个不同的概念,这里的类型只是标识数据存储的类型,而不是数据定义的类型。
取值 | 类型 | 备注 |
---|---|---|
0 | int1 | 紧跟1个字节整型数据 |
1 | int2 | 紧跟2个字节整型数据 |
2 | int4 | 紧跟4个字节整型数据 |
3 | int8 | 紧跟8个字节整型数据 |
4 | float | 紧跟4个字节浮点型数据 |
5 | double | 紧跟8个字节浮点型数据 |
6 | String1 | 紧跟1个字节长度,再跟内容 |
7 | String4 | 紧跟4个字节长度,再跟内容 |
8 | Map | 紧跟一个整型数据表示Map的大小,再跟[key, value]对列表 |
9 | List | 紧跟一个整型数据表示List的大小,再跟元素列表 |
10 | 自定义结构开始 | 自定义结构开始标志 |
11 | 自定义结构结束 | 自定义结构结束标志,Tag为0 |
12 | 数字0 | 表示数字0,后面不跟数据 |
13 | SimpleList | 简单列表(目前用在byte数组),紧跟一个类型字段(目前只支持byte),紧跟一个整型数据表示长度,再跟byte数据 |
1.基本类型(包括int1
、int2
、int4
、int8
、float
、double
)
头信息后紧跟数值数据。char、bool也被看作整型。所有的整型数据之间不做区分,也就是说一个short的值可以赋值给一个int。
2.数字0
头信息后不跟数据,表示数值0。所有基本类型的0值都可以这样来表示。
这是考虑到数字0出现的概率比较大,所以单独提一个类型,以节省空间。
3.字符串(包括String1、String4)
String1跟一个字节的长度(该长度数据不包括头信息),接着紧跟内容。
String4与之类似。
4.Map
紧跟一个整形数据(包括头信息)表示Map的大小,然后紧跟[Key数据(Tag为0),Value数据(Tag为1)]对列表。
5.List
紧跟一个整形数据(包括头信息)表示List
的大小,然后紧跟元素列表(Tag
为0)
6.自定义结构开始
自定义结构开始标志,后面紧跟字段数据,字段按照tag升序顺序排列
7.自定义结构结束
自定义结构结束标志,Tag为0
对于自定义结构的持久化,由开始标志与结束标志来标识。
比如如下结构定义:
struct TestInfo
{
1 require int ii = 34;
2 optional string s = "abc";
};
struct TestInfo2
{
1 require TestInfo t;
2 require int a = 12345;
};
其中,默认的TestInfo2结构编码后结果为:
TUP底层协议完全采用Tars定义,与Tars的底层数据包定义一致,其中require
的字段为TUP必须的字段,optional
为访问Tars服务时额外需要用到的字段。
//请求包体
struct RequestPacket
{
1 require short iVersion; //版本号
2 optional byte cPacketType; //包类型
3 optional int iMessageType; //消息类型
4 require int iRequestId; //请求ID
5 require string sServantName; //servant名字
6 require string sFuncName; //函数名称
7 require vector<byte> sBuffer; //二进制buffer
8 optional int iTimeout; //超时时间(毫秒)
9 optional map<string, string> context; //业务上下文
10 optional map<string, string> status; //框架协议上下文
};
//响应包体
struct ResponsePacket
{
1 require short iVersion; //版本号
2 optional byte cPacketType; //包类型
3 require int iRequestId; //请求ID
4 optional int iMessageType; //消息类型
5 optional int iRet; //返回值
6 require vector<byte> sBuffer; //二进制流
7 optional map<string, string> status; //协议上下文
8 optional string sResultDesc; //结果描述
};
//返回值
const int TAFSERVERSUCCESS = 0; //服务器端处理成功
const int TAFSERVERDECODEERR = -1; //服务器端解码异常
const int TAFSERVERENCODEERR = -2; //服务器端编码异常
const int TAFSERVERNOFUNCERR = -3; //服务器端没有该函数
const int TAFSERVERNOSERVANTERR = -4; //服务器端没有该Servant对象
const int TAFSERVERRESETGRID = -5; //服务器端灰度状态不一致
const int TAFSERVERQUEUETIMEOUT = -6; //服务器队列超过限制
const int TAFASYNCCALLTIMEOUT = -7; //异步调用超时
const int TAFINVOKETIMEOUT = -7; //调用超时
const int TAFPROXYCONNECTERR = -8; //proxy链接异常
const int TAFSERVEROVERLOAD = -9; //服务器端超负载,超过队列长度
const int TAFADAPTERNULL = -10; //客户端选路为空,服务不存在或者所有服务down掉了
const int TAFINVOKEBYINVALIDESET = -11; //客户端按set规则调用非法
const int TAFCLIENTDECODEERR = -12; //客户端解码异常
const int TAFSERVERUNKNOWNERR = -99; //服务器端位置异常
(Notice: Origin official document is Here)