国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Protobuf編碼規(guī)則

這篇具有很好參考價值的文章主要介紹了Protobuf編碼規(guī)則。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報違法"按鈕提交疑問。

支持類型

該表顯示了在?.proto?文件中指定的類型,以及自動生成的類中的相應(yīng)類型:

.proto Type Notes C++ Type Java/Kotlin Type[1] Java/Kotlin 類型 [1] Python Type[3] Go Type Ruby Type C# Type PHP Type Dart Type
double double double float float64 Float double float double
float float float float float32 Float float float double
int32 varint編碼。對于負(fù)數(shù)編碼效率低下——如果字段可能有負(fù)值,建議改用 sint32。 int32 int int int32 Fixnum or Bignum (as required) int integer int
int64 varint編碼。對于負(fù)數(shù)編碼效率低下——如果字段可能有負(fù)值,建議改用 sint64。 int64 long int/long int64 Bignum long integer/string Int64
uint32 varint編碼。 uint32 int int/long uint32 Fixnum or Bignum (as required) uint integer int
uint64 varint編碼。 uint64 long int/long uint64 Bignum ulong integer/string Int64
sint32 zigzag和varint編碼。有符號的 int 值。比常規(guī)的 int32 能更高效地編碼負(fù)數(shù)。 int32 int int int32 Fixnum or Bignum (as required) ) int integer int
sint64 zigzag和varint編碼。有符號的 int 值。比常規(guī)的 int64 能更高效地編碼負(fù)數(shù)。 int64 long int/long int64 Bignum long integer/string Int64
fixed32 總是四個字節(jié)。如果值通常大于 2\(^{28}\) ,則比 uint32 更有效。 uint32 int int/long uint32 Fixnum or Bignum (as required) uint integer int
fixed64 總是八個字節(jié)。如果值通常大于 2\({^56}\) ,則比 uint64 更有效。 uint64 long int/long uint64 Bignum ulong integer/string Int64
sfixed32 總是四個字節(jié)。 int32 int int int32 Fixnum or Bignum (as required) int integer int
sfixed64 總是八個字節(jié)。 int64 long int/long int64 Bignum long integer/string Int64
bool bool boolean bool bool TrueClass/FalseClass bool boolean bool
string 字符串必須始終包含 UTF-8 編碼或 7 位 ASCII 文本,并且不能長于 2\(^{32}\) 。 string String str/unicode string String (UTF-8) string string String
bytes 可以包含任何不超過 2\(^{32}\) 的任意字節(jié)序列。 string ByteString str (Python 2) bytes (Python 3) []byte String (ASCII-8BIT) ByteString string List

消息結(jié)構(gòu)

對于傳統(tǒng)的 xml 或者 json 等方式的序列化中,編碼時直接將 key 本身加進(jìn)去,例如:

{
    "foo": 1,
    "bar": 2
}

這樣最大的好處就是可讀性強(qiáng),但是缺點(diǎn)也很明顯,傳輸效率低,每次都需要傳輸重復(fù)的字段名。Protobuf 使用了另一種方式,將每一個字段進(jìn)行編號,這個編號被稱為 field number 。通過 field_number 的方式解決 json 等方式重復(fù)傳輸字段名導(dǎo)致的效率低下問題,例如:

message {
  int32  foo = 1;
  string bar = 2;
}

field_number 的類型被稱為wire types,目前有六種類型:VARINT,?I64,?LEN,?SGROUP,?EGROUP, and?I32 (注:類型3和4已廢棄),因此需要至少3位來區(qū)分:

ID Name Used For
0 VARINT int32, int64, uint32, uint64, sint32, sint64, bool, enum
1 I64 fixed64, sfixed64, double
2 LEN string, bytes, embedded messages, packed repeated fields
3 SGROUP group start (deprecated)
4 EGROUP group end (deprecated)
5 I32 fixed32, sfixed32, float

當(dāng) message 被編碼時,每一個 key-value 包含 <tag> <type> <paylog>,其結(jié)構(gòu)如下:

+--------------+-----------+---------+
| field_number | wire_type | payload |
+--------------+-----------+---------+
    |               |             |
    |               |             |          +---------------+
    +---------------+             +--------->| (length) data |
    |      tag      |                        +---------------+
    +---------------+

  • field_number 和 wire_type 被稱為 tag,使用一個字節(jié)來表示(這里指編碼前的一個字節(jié),通過Varint編碼后可能并非一個字節(jié))。其值為 (field_number << 3) | wire_type ,換句話說低3位解釋了wire_type,剩余的位則解釋了field_number。
  • payload 則為 value 具體值,根據(jù) wire_type 的類型決定是否是采用 Length-Delimited 記錄

額外一提的是由于 tag 結(jié)構(gòu)如上所述,因此對于使用 Varint 編碼的 1個字節(jié)來說去除最高位標(biāo)志位和低三位保留給 wire_type使用,剩下四位能夠表示[0, 15] 的字段標(biāo)識,超過則需要使用多于一個字節(jié)來存儲 tag 信息,因此盡可能將頻繁使用的字段的字段標(biāo)識定義在 [0, 15] 直接。

編碼規(guī)則

Protobuf 使用一種緊湊的二進(jìn)制格式來編碼消息。編碼規(guī)則包括以下幾個方面:

  • 每個字段都有一個唯一的標(biāo)識符和一個類型,標(biāo)識符和類型信息一起構(gòu)成了字段的 tag。
  • 字段的 tag 采用 Varint 編碼方式進(jìn)行編碼,可以節(jié)省空間。
  • 字符串類型的字段采用長度前綴方式進(jìn)行編碼,先編碼字符串的長度,再編碼字符串本身。
  • 重復(fù)的字段可以使用 repeated 關(guān)鍵字進(jìn)行定義,編碼時將重復(fù)的值按照順序編碼成一個列表。

Varint 編碼

Varint 是一種可變長度的編碼方式,可以將一個整數(shù)編碼成一個字節(jié)序列。值越小的數(shù)字,使用越少的字節(jié)數(shù)表示。它的原理是通過減少表示數(shù)字的字節(jié)數(shù)從而實(shí)現(xiàn)數(shù)據(jù)體積壓縮。
Varint 編碼的規(guī)則如下:

  • 對于值小于 128 的整數(shù),直接編碼為一個字節(jié);
  • 對于值大于等于 128 的整數(shù),將低 7 位編碼到第一個字節(jié)中,將高位編碼到后續(xù)的字節(jié)中,并在最高位添加一個標(biāo)志位(1 表示后續(xù)還有字節(jié),0 表示當(dāng)前字節(jié)是最后一個字節(jié))。每個字節(jié)的最高位也稱 MSB(most significant bit)。
    在解碼的時候,如果讀到的字節(jié)的 MSB 是 1 話,則表示還有后序字節(jié),一直讀到 MSB 為 0 的字節(jié)為止。
    例如,int32類型、field_number為1、值位 300 的 Varint 編碼為:
// 300 的二進(jìn)制
00000001 00101100
// 按7位切割
00 0000010 0101100
// 高位全0省略
0000010 0101100
// 逆序,使用的小端字節(jié)序
0101100 0000010
// 每一組加上msb,除了最后一組是msb是0,其他的都為1
10101100 00000010
// 十六進(jìn)制指
ac 02

// 按照 protobuf 的消息結(jié)構(gòu),其完整位
08 ac 02
|   |__|__ payload
|   
|----------- tag (field-number << 3 | wire-type) = (1 << 3 | 0) = 0x08

ZigZag編碼

對于 int32/int64 的 proto type,值大于 0 時直接使用 Varint 編碼,而值為負(fù)數(shù)時做了符號拓展,轉(zhuǎn)換為 int64 的類型,再做 Varint 編碼。負(fù)數(shù)高位為1,因此對于負(fù)數(shù)固定需要十個字節(jié)( ceil(64 / 7) = 10 )。(這里有個值得思考的問題是對于 int32 類型的負(fù)數(shù)為什么要轉(zhuǎn)換為 int64 來處理?不轉(zhuǎn)換的話使用5個字節(jié)就能夠完成編碼了。網(wǎng)上的一個說法是為了轉(zhuǎn)換為 int64 類型時沒有兼容性問題,此處由于還未閱讀過源碼,不知道內(nèi)部是怎么處理的,因此暫時也沒想通為什么因為兼容性問題需要做符號拓展。因為按照 Varint 編碼規(guī)則解碼的話,直接讀取出來的值賦值給 int64 的類型也沒有問題。int32 negative numbers)

很明顯,這樣對于負(fù)數(shù)的編碼是非常低效的。因此 protobuf 引入 sint32sint64,在編碼時先將數(shù)字使用 ZigZag 編碼,然后再使用 Varint 編碼。
ZigZag 編碼將有符號數(shù)映射為無符號數(shù),對應(yīng)的編解碼規(guī)則如下:

static uint32_t ZigZagEncode32(int32_t v) {  
	// Note: the right-shift must be arithmetic  
	// Note: left shift must be unsigned because of overflow
    return (static_cast<uint32_t>(v) << 1) ^ static_cast<uint32_t>(v >> 31);  
}

static uint64_t ZigZagEncode64(int64_t v) {  
	// Note: the right-shift must be arithmetic  
	// Note: left shift must be unsigned because of overflow
    return (static_cast<uint64_t>(v) << 1) ^ static_cast<uint64_t>(v >> 63);  
}

int32_t ZigZagDecode32(uint32_t n) {
    // Note: Using unsigned types prevent undefined behavior
    return static_cast<int32_t>((n >> 1) ^ (~(n & 1) + 1));
} 

static int64_t ZigZagDecode64(uint64_t n) {
    // Note: Using unsigned types prevent undefined behavior
    return static_cast<int64_t>((n >> 1) ^ (~(n & 1) + 1));
}

因此如果傳輸?shù)臄?shù)據(jù)中可能包含有負(fù)數(shù),那么應(yīng)該使用 sint32/sint64 類型。因為 protobuf 中只定義了為這兩種數(shù)據(jù)類型進(jìn)行 ZigZag 編碼再使用 Varint 編碼。

Length-delimited 編碼

wire_typeLEN,由于其具有動態(tài)長度,因此其由一個 Length 值保存長度大小,這個 Length 同樣通過 Varint 編碼,最后是其內(nèi)容。
參照以下例子:文章來源地址http://www.zghlxwxcb.cn/news/detail-431863.html

message Test2 {
  optional string b = 2;
}

b = "testing"

12 07 [74 65 73 74 69 6e 67]
|  |   t  e  s  t  i  n  g
|  |  |__|__|__|__|__|__ body 的 ASCII 碼
|  |
|  |__ length = 6 = 0x06
|      
|__ Tag (field-number << 3 | wire-type) = (2 << 3 | 2) = 18 = 0x12

到了這里,關(guān)于Protobuf編碼規(guī)則的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請點(diǎn)擊違法舉報進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • Buf 教程 - 使用 Protobuf 生成 Golang 代碼和 Typescript 類型定義

    Buf 教程 - 使用 Protobuf 生成 Golang 代碼和 Typescript 類型定義

    Buf 是一款更高效、開發(fā)者友好的 Protobuf API 管理工具,不僅支持代碼生成,還支持插件和 Protobuf 格式化。 我們可以使用 Buf 替代原本基于 Protoc 的代碼生成流程,一方面可以統(tǒng)一管理團(tuán)隊 Protoc 插件的版本、代碼生成配置,另一方面可以簡化項目開發(fā)配置。 本文將會用兩部分

    2024年02月08日
    瀏覽(47)
  • 一文讀懂UTF-8的編碼規(guī)則

    一文讀懂UTF-8的編碼規(guī)則

    之前寫過一篇文章“一文徹底搞懂計算機(jī)中文編碼”里面只是介紹了GB2312編碼知識,關(guān)于utf8沒有涉及到,經(jīng)過查詢資料發(fā)現(xiàn)utf8是對unicode的一種可變長度字符編碼,所以再記錄一下。 現(xiàn)在國家對于信息技術(shù)中文編碼字符集制定的標(biāo)準(zhǔn)是《GB 18030-2022 信息技術(shù) 中文編碼字符集》

    2024年02月07日
    瀏覽(26)
  • 在Winform應(yīng)用中增加通用的業(yè)務(wù)編碼規(guī)則生成

    在Winform應(yīng)用中增加通用的業(yè)務(wù)編碼規(guī)則生成

    在我們很多應(yīng)用系統(tǒng)中,往往都需要根據(jù)實(shí)際情況生成一些編碼規(guī)則,如訂單號、入庫單號、出庫單號、退貨單號等等,我們有時候根據(jù)規(guī)則自行增加一個函數(shù)來生成處理,不過我們仔細(xì)觀察后,發(fā)現(xiàn)它們的編碼規(guī)則有很大的共通性,因此可以考慮使用一些通用的業(yè)務(wù)編碼規(guī)

    2024年02月05日
    瀏覽(16)
  • JavaScript 類型判斷及類型轉(zhuǎn)換規(guī)則

    JavaScript 類型判斷及類型轉(zhuǎn)換規(guī)則

    ?創(chuàng)作者:全棧弄潮兒 ?? 個人主頁: 全棧弄潮兒的個人主頁 ??? 個人社區(qū),歡迎你的加入:全棧弄潮兒的個人社區(qū) ?? 專欄地址,歡迎訂閱:前端架構(gòu)師之路 JavaScript 具有七種內(nèi)置數(shù)據(jù)類型,它們分別是: null undefined boolean number string object symbol 其中,前面五種為基本類

    2024年01月19日
    瀏覽(25)
  • 基本數(shù)據(jù)類型轉(zhuǎn)換(基本數(shù)據(jù)類型之間的運(yùn)算規(guī)則)

    基本數(shù)據(jù)類型轉(zhuǎn)換(基本數(shù)據(jù)類型之間的運(yùn)算規(guī)則)

    前提:這里討論只是7種基本數(shù)據(jù)類型變量間的運(yùn)算。不包含boolean類型的。?? 自動類型轉(zhuǎn)換:容量小的類型自動轉(zhuǎn)換為容量大的數(shù)據(jù)類型。數(shù)據(jù)類型按容量大小排序為: 有多種類型的數(shù)據(jù)混合運(yùn)算時,系統(tǒng)首先自動將所有數(shù)據(jù)?轉(zhuǎn)換成容量最大的那種數(shù)據(jù)類型,然后再進(jìn)行計

    2024年02月15日
    瀏覽(23)
  • C++ 類型兼容規(guī)則

    C++ 類型兼容規(guī)則

    類型兼容規(guī)則是指在需要基類對象的任何地方,都可以使用公有派生類的對象來替代。 通過公有繼承,派生類得到了基類中除構(gòu)造函數(shù)和析構(gòu)函數(shù)之外的所有成員。這樣,公有派生類實(shí)際就具備了基類的所有功能,凡是基類能解決的問題,公有派生類都可以解決。類型兼容規(guī)

    2024年02月14日
    瀏覽(23)
  • 『C語言』隱式類型轉(zhuǎn)換規(guī)則

    『C語言』隱式類型轉(zhuǎn)換規(guī)則

    ?? 博客主頁 : 小羊失眠啦. ?? 系列專欄 : C語言 ??? 每日語錄 : 但行前路,不負(fù)韶華! ?? 感謝大家點(diǎn)贊??收藏?評論?? 今天小羊又來給鐵汁們分享關(guān)于C語言的 隱式類型轉(zhuǎn)換規(guī)則 ,在C語言中類型轉(zhuǎn)換方式可分為 隱式類型轉(zhuǎn)換 和 顯式類型轉(zhuǎn)換 (強(qiáng)制類型轉(zhuǎn)換),

    2024年02月12日
    瀏覽(18)
  • Sentinel限流規(guī)則支持流控效果

    Sentinel限流規(guī)則支持流控效果

    流控效果是指請求達(dá)到流控閾值時應(yīng)該采取的措施,包括三種: 1.快速失?。哼_(dá)到閾值后,新的請求會被立即拒絕并拋出FlowException異常。是默認(rèn)的處理方式。 2.warm up:預(yù)熱模式,對超出閾值的請求同樣是拒絕并拋出異常。但這種模式閾值會動態(tài)變化,從一個較小值逐漸增加

    2024年01月22日
    瀏覽(40)
  • 編碼類型 ASCII URLcode編碼 Unicode編碼 utf編碼理解

    編碼類型 ASCII URLcode編碼 Unicode編碼 utf編碼理解

    bin是二進(jìn)制 oct是八進(jìn)制 hex是16進(jìn)制 Ord() 檢測 ASCII 碼, python3 也可查中文 phello/p !-- 等同于 -- 十進(jìn)制 p # 104 ; #101;#108;#108;#111;/p !-- 等同于 -- ?? 2.? 十六進(jìn)制 p #x 68 ; #x65;#x6c;#x6c;#x6f;/p Cyberchef---實(shí)體編碼轉(zhuǎn)換工具 lt;scriptgt;?? 雖然前端頁面可以識別這種編碼但是不會執(zhí)行語句功

    2024年02月16日
    瀏覽(29)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包