compact_protocol.go 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815
  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. package thrift
  20. import (
  21. "encoding/binary"
  22. "fmt"
  23. "io"
  24. "math"
  25. )
  26. const (
  27. COMPACT_PROTOCOL_ID = 0x082
  28. COMPACT_VERSION = 1
  29. COMPACT_VERSION_MASK = 0x1f
  30. COMPACT_TYPE_MASK = 0x0E0
  31. COMPACT_TYPE_BITS = 0x07
  32. COMPACT_TYPE_SHIFT_AMOUNT = 5
  33. )
  34. type tCompactType byte
  35. const (
  36. COMPACT_BOOLEAN_TRUE = 0x01
  37. COMPACT_BOOLEAN_FALSE = 0x02
  38. COMPACT_BYTE = 0x03
  39. COMPACT_I16 = 0x04
  40. COMPACT_I32 = 0x05
  41. COMPACT_I64 = 0x06
  42. COMPACT_DOUBLE = 0x07
  43. COMPACT_BINARY = 0x08
  44. COMPACT_LIST = 0x09
  45. COMPACT_SET = 0x0A
  46. COMPACT_MAP = 0x0B
  47. COMPACT_STRUCT = 0x0C
  48. )
  49. var (
  50. ttypeToCompactType map[TType]tCompactType
  51. )
  52. func init() {
  53. ttypeToCompactType = map[TType]tCompactType{
  54. STOP: STOP,
  55. BOOL: COMPACT_BOOLEAN_TRUE,
  56. BYTE: COMPACT_BYTE,
  57. I16: COMPACT_I16,
  58. I32: COMPACT_I32,
  59. I64: COMPACT_I64,
  60. DOUBLE: COMPACT_DOUBLE,
  61. STRING: COMPACT_BINARY,
  62. LIST: COMPACT_LIST,
  63. SET: COMPACT_SET,
  64. MAP: COMPACT_MAP,
  65. STRUCT: COMPACT_STRUCT,
  66. }
  67. }
  68. type TCompactProtocolFactory struct{}
  69. func NewTCompactProtocolFactory() *TCompactProtocolFactory {
  70. return &TCompactProtocolFactory{}
  71. }
  72. func (p *TCompactProtocolFactory) GetProtocol(trans TTransport) TProtocol {
  73. return NewTCompactProtocol(trans)
  74. }
  75. type TCompactProtocol struct {
  76. trans TRichTransport
  77. origTransport TTransport
  78. // Used to keep track of the last field for the current and previous structs,
  79. // so we can do the delta stuff.
  80. lastField []int
  81. lastFieldId int
  82. // If we encounter a boolean field begin, save the TField here so it can
  83. // have the value incorporated.
  84. booleanFieldName string
  85. booleanFieldId int16
  86. booleanFieldPending bool
  87. // If we read a field header, and it's a boolean field, save the boolean
  88. // value here so that readBool can use it.
  89. boolValue bool
  90. boolValueIsNotNull bool
  91. buffer [64]byte
  92. }
  93. // Create a TCompactProtocol given a TTransport
  94. func NewTCompactProtocol(trans TTransport) *TCompactProtocol {
  95. p := &TCompactProtocol{origTransport: trans, lastField: []int{}}
  96. if et, ok := trans.(TRichTransport); ok {
  97. p.trans = et
  98. } else {
  99. p.trans = NewTRichTransport(trans)
  100. }
  101. return p
  102. }
  103. //
  104. // Public Writing methods.
  105. //
  106. // Write a message header to the wire. Compact Protocol messages contain the
  107. // protocol version so we can migrate forwards in the future if need be.
  108. func (p *TCompactProtocol) WriteMessageBegin(name string, typeId TMessageType, seqid int32) error {
  109. err := p.writeByteDirect(COMPACT_PROTOCOL_ID)
  110. if err != nil {
  111. return NewTProtocolException(err)
  112. }
  113. err = p.writeByteDirect((COMPACT_VERSION & COMPACT_VERSION_MASK) | ((byte(typeId) << COMPACT_TYPE_SHIFT_AMOUNT) & COMPACT_TYPE_MASK))
  114. if err != nil {
  115. return NewTProtocolException(err)
  116. }
  117. _, err = p.writeVarint32(seqid)
  118. if err != nil {
  119. return NewTProtocolException(err)
  120. }
  121. e := p.WriteString(name)
  122. return e
  123. }
  124. func (p *TCompactProtocol) WriteMessageEnd() error { return nil }
  125. // Write a struct begin. This doesn't actually put anything on the wire. We
  126. // use it as an opportunity to put special placeholder markers on the field
  127. // stack so we can get the field id deltas correct.
  128. func (p *TCompactProtocol) WriteStructBegin(name string) error {
  129. p.lastField = append(p.lastField, p.lastFieldId)
  130. p.lastFieldId = 0
  131. return nil
  132. }
  133. // Write a struct end. This doesn't actually put anything on the wire. We use
  134. // this as an opportunity to pop the last field from the current struct off
  135. // of the field stack.
  136. func (p *TCompactProtocol) WriteStructEnd() error {
  137. p.lastFieldId = p.lastField[len(p.lastField)-1]
  138. p.lastField = p.lastField[:len(p.lastField)-1]
  139. return nil
  140. }
  141. func (p *TCompactProtocol) WriteFieldBegin(name string, typeId TType, id int16) error {
  142. if typeId == BOOL {
  143. // we want to possibly include the value, so we'll wait.
  144. p.booleanFieldName, p.booleanFieldId, p.booleanFieldPending = name, id, true
  145. return nil
  146. }
  147. _, err := p.writeFieldBeginInternal(name, typeId, id, 0xFF)
  148. return NewTProtocolException(err)
  149. }
  150. // The workhorse of writeFieldBegin. It has the option of doing a
  151. // 'type override' of the type header. This is used specifically in the
  152. // boolean field case.
  153. func (p *TCompactProtocol) writeFieldBeginInternal(name string, typeId TType, id int16, typeOverride byte) (int, error) {
  154. // short lastField = lastField_.pop();
  155. // if there's a type override, use that.
  156. var typeToWrite byte
  157. if typeOverride == 0xFF {
  158. typeToWrite = byte(p.getCompactType(typeId))
  159. } else {
  160. typeToWrite = typeOverride
  161. }
  162. // check if we can use delta encoding for the field id
  163. fieldId := int(id)
  164. written := 0
  165. if fieldId > p.lastFieldId && fieldId-p.lastFieldId <= 15 {
  166. // write them together
  167. err := p.writeByteDirect(byte((fieldId-p.lastFieldId)<<4) | typeToWrite)
  168. if err != nil {
  169. return 0, err
  170. }
  171. } else {
  172. // write them separate
  173. err := p.writeByteDirect(typeToWrite)
  174. if err != nil {
  175. return 0, err
  176. }
  177. err = p.WriteI16(id)
  178. written = 1 + 2
  179. if err != nil {
  180. return 0, err
  181. }
  182. }
  183. p.lastFieldId = fieldId
  184. // p.lastField.Push(field.id);
  185. return written, nil
  186. }
  187. func (p *TCompactProtocol) WriteFieldEnd() error { return nil }
  188. func (p *TCompactProtocol) WriteFieldStop() error {
  189. err := p.writeByteDirect(STOP)
  190. return NewTProtocolException(err)
  191. }
  192. func (p *TCompactProtocol) WriteMapBegin(keyType TType, valueType TType, size int) error {
  193. if size == 0 {
  194. err := p.writeByteDirect(0)
  195. return NewTProtocolException(err)
  196. }
  197. _, err := p.writeVarint32(int32(size))
  198. if err != nil {
  199. return NewTProtocolException(err)
  200. }
  201. err = p.writeByteDirect(byte(p.getCompactType(keyType))<<4 | byte(p.getCompactType(valueType)))
  202. return NewTProtocolException(err)
  203. }
  204. func (p *TCompactProtocol) WriteMapEnd() error { return nil }
  205. // Write a list header.
  206. func (p *TCompactProtocol) WriteListBegin(elemType TType, size int) error {
  207. _, err := p.writeCollectionBegin(elemType, size)
  208. return NewTProtocolException(err)
  209. }
  210. func (p *TCompactProtocol) WriteListEnd() error { return nil }
  211. // Write a set header.
  212. func (p *TCompactProtocol) WriteSetBegin(elemType TType, size int) error {
  213. _, err := p.writeCollectionBegin(elemType, size)
  214. return NewTProtocolException(err)
  215. }
  216. func (p *TCompactProtocol) WriteSetEnd() error { return nil }
  217. func (p *TCompactProtocol) WriteBool(value bool) error {
  218. v := byte(COMPACT_BOOLEAN_FALSE)
  219. if value {
  220. v = byte(COMPACT_BOOLEAN_TRUE)
  221. }
  222. if p.booleanFieldPending {
  223. // we haven't written the field header yet
  224. _, err := p.writeFieldBeginInternal(p.booleanFieldName, BOOL, p.booleanFieldId, v)
  225. p.booleanFieldPending = false
  226. return NewTProtocolException(err)
  227. }
  228. // we're not part of a field, so just write the value.
  229. err := p.writeByteDirect(v)
  230. return NewTProtocolException(err)
  231. }
  232. // Write a byte. Nothing to see here!
  233. func (p *TCompactProtocol) WriteByte(value int8) error {
  234. err := p.writeByteDirect(byte(value))
  235. return NewTProtocolException(err)
  236. }
  237. // Write an I16 as a zigzag varint.
  238. func (p *TCompactProtocol) WriteI16(value int16) error {
  239. _, err := p.writeVarint32(p.int32ToZigzag(int32(value)))
  240. return NewTProtocolException(err)
  241. }
  242. // Write an i32 as a zigzag varint.
  243. func (p *TCompactProtocol) WriteI32(value int32) error {
  244. _, err := p.writeVarint32(p.int32ToZigzag(value))
  245. return NewTProtocolException(err)
  246. }
  247. // Write an i64 as a zigzag varint.
  248. func (p *TCompactProtocol) WriteI64(value int64) error {
  249. _, err := p.writeVarint64(p.int64ToZigzag(value))
  250. return NewTProtocolException(err)
  251. }
  252. // Write a double to the wire as 8 bytes.
  253. func (p *TCompactProtocol) WriteDouble(value float64) error {
  254. buf := p.buffer[0:8]
  255. binary.LittleEndian.PutUint64(buf, math.Float64bits(value))
  256. _, err := p.trans.Write(buf)
  257. return NewTProtocolException(err)
  258. }
  259. // Write a string to the wire with a varint size preceding.
  260. func (p *TCompactProtocol) WriteString(value string) error {
  261. _, e := p.writeVarint32(int32(len(value)))
  262. if e != nil {
  263. return NewTProtocolException(e)
  264. }
  265. if len(value) > 0 {
  266. }
  267. _, e = p.trans.WriteString(value)
  268. return e
  269. }
  270. // Write a byte array, using a varint for the size.
  271. func (p *TCompactProtocol) WriteBinary(bin []byte) error {
  272. _, e := p.writeVarint32(int32(len(bin)))
  273. if e != nil {
  274. return NewTProtocolException(e)
  275. }
  276. if len(bin) > 0 {
  277. _, e = p.trans.Write(bin)
  278. return NewTProtocolException(e)
  279. }
  280. return nil
  281. }
  282. //
  283. // Reading methods.
  284. //
  285. // Read a message header.
  286. func (p *TCompactProtocol) ReadMessageBegin() (name string, typeId TMessageType, seqId int32, err error) {
  287. protocolId, err := p.readByteDirect()
  288. if err != nil {
  289. return
  290. }
  291. if protocolId != COMPACT_PROTOCOL_ID {
  292. e := fmt.Errorf("Expected protocol id %02x but got %02x", COMPACT_PROTOCOL_ID, protocolId)
  293. return "", typeId, seqId, NewTProtocolExceptionWithType(BAD_VERSION, e)
  294. }
  295. versionAndType, err := p.readByteDirect()
  296. if err != nil {
  297. return
  298. }
  299. version := versionAndType & COMPACT_VERSION_MASK
  300. typeId = TMessageType((versionAndType >> COMPACT_TYPE_SHIFT_AMOUNT) & COMPACT_TYPE_BITS)
  301. if version != COMPACT_VERSION {
  302. e := fmt.Errorf("Expected version %02x but got %02x", COMPACT_VERSION, version)
  303. err = NewTProtocolExceptionWithType(BAD_VERSION, e)
  304. return
  305. }
  306. seqId, e := p.readVarint32()
  307. if e != nil {
  308. err = NewTProtocolException(e)
  309. return
  310. }
  311. name, err = p.ReadString()
  312. return
  313. }
  314. func (p *TCompactProtocol) ReadMessageEnd() error { return nil }
  315. // Read a struct begin. There's nothing on the wire for this, but it is our
  316. // opportunity to push a new struct begin marker onto the field stack.
  317. func (p *TCompactProtocol) ReadStructBegin() (name string, err error) {
  318. p.lastField = append(p.lastField, p.lastFieldId)
  319. p.lastFieldId = 0
  320. return
  321. }
  322. // Doesn't actually consume any wire data, just removes the last field for
  323. // this struct from the field stack.
  324. func (p *TCompactProtocol) ReadStructEnd() error {
  325. // consume the last field we read off the wire.
  326. p.lastFieldId = p.lastField[len(p.lastField)-1]
  327. p.lastField = p.lastField[:len(p.lastField)-1]
  328. return nil
  329. }
  330. // Read a field header off the wire.
  331. func (p *TCompactProtocol) ReadFieldBegin() (name string, typeId TType, id int16, err error) {
  332. t, err := p.readByteDirect()
  333. if err != nil {
  334. return
  335. }
  336. // if it's a stop, then we can return immediately, as the struct is over.
  337. if (t & 0x0f) == STOP {
  338. return "", STOP, 0, nil
  339. }
  340. // mask off the 4 MSB of the type header. it could contain a field id delta.
  341. modifier := int16((t & 0xf0) >> 4)
  342. if modifier == 0 {
  343. // not a delta. look ahead for the zigzag varint field id.
  344. id, err = p.ReadI16()
  345. if err != nil {
  346. return
  347. }
  348. } else {
  349. // has a delta. add the delta to the last read field id.
  350. id = int16(p.lastFieldId) + modifier
  351. }
  352. typeId, e := p.getTType(tCompactType(t & 0x0f))
  353. if e != nil {
  354. err = NewTProtocolException(e)
  355. return
  356. }
  357. // if this happens to be a boolean field, the value is encoded in the type
  358. if p.isBoolType(t) {
  359. // save the boolean value in a special instance variable.
  360. p.boolValue = (byte(t)&0x0f == COMPACT_BOOLEAN_TRUE)
  361. p.boolValueIsNotNull = true
  362. }
  363. // push the new field onto the field stack so we can keep the deltas going.
  364. p.lastFieldId = int(id)
  365. return
  366. }
  367. func (p *TCompactProtocol) ReadFieldEnd() error { return nil }
  368. // Read a map header off the wire. If the size is zero, skip reading the key
  369. // and value type. This means that 0-length maps will yield TMaps without the
  370. // "correct" types.
  371. func (p *TCompactProtocol) ReadMapBegin() (keyType TType, valueType TType, size int, err error) {
  372. size32, e := p.readVarint32()
  373. if e != nil {
  374. err = NewTProtocolException(e)
  375. return
  376. }
  377. if size32 < 0 {
  378. err = invalidDataLength
  379. return
  380. }
  381. size = int(size32)
  382. keyAndValueType := byte(STOP)
  383. if size != 0 {
  384. keyAndValueType, err = p.readByteDirect()
  385. if err != nil {
  386. return
  387. }
  388. }
  389. keyType, _ = p.getTType(tCompactType(keyAndValueType >> 4))
  390. valueType, _ = p.getTType(tCompactType(keyAndValueType & 0xf))
  391. return
  392. }
  393. func (p *TCompactProtocol) ReadMapEnd() error { return nil }
  394. // Read a list header off the wire. If the list size is 0-14, the size will
  395. // be packed into the element type header. If it's a longer list, the 4 MSB
  396. // of the element type header will be 0xF, and a varint will follow with the
  397. // true size.
  398. func (p *TCompactProtocol) ReadListBegin() (elemType TType, size int, err error) {
  399. size_and_type, err := p.readByteDirect()
  400. if err != nil {
  401. return
  402. }
  403. size = int((size_and_type >> 4) & 0x0f)
  404. if size == 15 {
  405. size2, e := p.readVarint32()
  406. if e != nil {
  407. err = NewTProtocolException(e)
  408. return
  409. }
  410. if size2 < 0 {
  411. err = invalidDataLength
  412. return
  413. }
  414. size = int(size2)
  415. }
  416. elemType, e := p.getTType(tCompactType(size_and_type))
  417. if e != nil {
  418. err = NewTProtocolException(e)
  419. return
  420. }
  421. return
  422. }
  423. func (p *TCompactProtocol) ReadListEnd() error { return nil }
  424. // Read a set header off the wire. If the set size is 0-14, the size will
  425. // be packed into the element type header. If it's a longer set, the 4 MSB
  426. // of the element type header will be 0xF, and a varint will follow with the
  427. // true size.
  428. func (p *TCompactProtocol) ReadSetBegin() (elemType TType, size int, err error) {
  429. return p.ReadListBegin()
  430. }
  431. func (p *TCompactProtocol) ReadSetEnd() error { return nil }
  432. // Read a boolean off the wire. If this is a boolean field, the value should
  433. // already have been read during readFieldBegin, so we'll just consume the
  434. // pre-stored value. Otherwise, read a byte.
  435. func (p *TCompactProtocol) ReadBool() (value bool, err error) {
  436. if p.boolValueIsNotNull {
  437. p.boolValueIsNotNull = false
  438. return p.boolValue, nil
  439. }
  440. v, err := p.readByteDirect()
  441. return v == COMPACT_BOOLEAN_TRUE, err
  442. }
  443. // Read a single byte off the wire. Nothing interesting here.
  444. func (p *TCompactProtocol) ReadByte() (int8, error) {
  445. v, err := p.readByteDirect()
  446. if err != nil {
  447. return 0, NewTProtocolException(err)
  448. }
  449. return int8(v), err
  450. }
  451. // Read an i16 from the wire as a zigzag varint.
  452. func (p *TCompactProtocol) ReadI16() (value int16, err error) {
  453. v, err := p.ReadI32()
  454. return int16(v), err
  455. }
  456. // Read an i32 from the wire as a zigzag varint.
  457. func (p *TCompactProtocol) ReadI32() (value int32, err error) {
  458. v, e := p.readVarint32()
  459. if e != nil {
  460. return 0, NewTProtocolException(e)
  461. }
  462. value = p.zigzagToInt32(v)
  463. return value, nil
  464. }
  465. // Read an i64 from the wire as a zigzag varint.
  466. func (p *TCompactProtocol) ReadI64() (value int64, err error) {
  467. v, e := p.readVarint64()
  468. if e != nil {
  469. return 0, NewTProtocolException(e)
  470. }
  471. value = p.zigzagToInt64(v)
  472. return value, nil
  473. }
  474. // No magic here - just read a double off the wire.
  475. func (p *TCompactProtocol) ReadDouble() (value float64, err error) {
  476. longBits := p.buffer[0:8]
  477. _, e := io.ReadFull(p.trans, longBits)
  478. if e != nil {
  479. return 0.0, NewTProtocolException(e)
  480. }
  481. return math.Float64frombits(p.bytesToUint64(longBits)), nil
  482. }
  483. // Reads a []byte (via readBinary), and then UTF-8 decodes it.
  484. func (p *TCompactProtocol) ReadString() (value string, err error) {
  485. length, e := p.readVarint32()
  486. if e != nil {
  487. return "", NewTProtocolException(e)
  488. }
  489. if length < 0 {
  490. return "", invalidDataLength
  491. }
  492. if uint64(length) > p.trans.RemainingBytes() {
  493. return "", invalidDataLength
  494. }
  495. if length == 0 {
  496. return "", nil
  497. }
  498. var buf []byte
  499. if length <= int32(len(p.buffer)) {
  500. buf = p.buffer[0:length]
  501. } else {
  502. buf = make([]byte, length)
  503. }
  504. _, e = io.ReadFull(p.trans, buf)
  505. return string(buf), NewTProtocolException(e)
  506. }
  507. // Read a []byte from the wire.
  508. func (p *TCompactProtocol) ReadBinary() (value []byte, err error) {
  509. length, e := p.readVarint32()
  510. if e != nil {
  511. return nil, NewTProtocolException(e)
  512. }
  513. if length == 0 {
  514. return []byte{}, nil
  515. }
  516. if length < 0 {
  517. return nil, invalidDataLength
  518. }
  519. if uint64(length) > p.trans.RemainingBytes() {
  520. return nil, invalidDataLength
  521. }
  522. buf := make([]byte, length)
  523. _, e = io.ReadFull(p.trans, buf)
  524. return buf, NewTProtocolException(e)
  525. }
  526. func (p *TCompactProtocol) Flush() (err error) {
  527. return NewTProtocolException(p.trans.Flush())
  528. }
  529. func (p *TCompactProtocol) Skip(fieldType TType) (err error) {
  530. return SkipDefaultDepth(p, fieldType)
  531. }
  532. func (p *TCompactProtocol) Transport() TTransport {
  533. return p.origTransport
  534. }
  535. //
  536. // Internal writing methods
  537. //
  538. // Abstract method for writing the start of lists and sets. List and sets on
  539. // the wire differ only by the type indicator.
  540. func (p *TCompactProtocol) writeCollectionBegin(elemType TType, size int) (int, error) {
  541. if size <= 14 {
  542. return 1, p.writeByteDirect(byte(int32(size<<4) | int32(p.getCompactType(elemType))))
  543. }
  544. err := p.writeByteDirect(0xf0 | byte(p.getCompactType(elemType)))
  545. if err != nil {
  546. return 0, err
  547. }
  548. m, err := p.writeVarint32(int32(size))
  549. return 1 + m, err
  550. }
  551. // Write an i32 as a varint. Results in 1-5 bytes on the wire.
  552. // TODO(pomack): make a permanent buffer like writeVarint64?
  553. func (p *TCompactProtocol) writeVarint32(n int32) (int, error) {
  554. i32buf := p.buffer[0:5]
  555. idx := 0
  556. for {
  557. if (n & ^0x7F) == 0 {
  558. i32buf[idx] = byte(n)
  559. idx++
  560. // p.writeByteDirect(byte(n));
  561. break
  562. // return;
  563. } else {
  564. i32buf[idx] = byte((n & 0x7F) | 0x80)
  565. idx++
  566. // p.writeByteDirect(byte(((n & 0x7F) | 0x80)));
  567. u := uint32(n)
  568. n = int32(u >> 7)
  569. }
  570. }
  571. return p.trans.Write(i32buf[0:idx])
  572. }
  573. // Write an i64 as a varint. Results in 1-10 bytes on the wire.
  574. func (p *TCompactProtocol) writeVarint64(n int64) (int, error) {
  575. varint64out := p.buffer[0:10]
  576. idx := 0
  577. for {
  578. if (n & ^0x7F) == 0 {
  579. varint64out[idx] = byte(n)
  580. idx++
  581. break
  582. } else {
  583. varint64out[idx] = byte((n & 0x7F) | 0x80)
  584. idx++
  585. u := uint64(n)
  586. n = int64(u >> 7)
  587. }
  588. }
  589. return p.trans.Write(varint64out[0:idx])
  590. }
  591. // Convert l into a zigzag long. This allows negative numbers to be
  592. // represented compactly as a varint.
  593. func (p *TCompactProtocol) int64ToZigzag(l int64) int64 {
  594. return (l << 1) ^ (l >> 63)
  595. }
  596. // Convert l into a zigzag long. This allows negative numbers to be
  597. // represented compactly as a varint.
  598. func (p *TCompactProtocol) int32ToZigzag(n int32) int32 {
  599. return (n << 1) ^ (n >> 31)
  600. }
  601. func (p *TCompactProtocol) fixedUint64ToBytes(n uint64, buf []byte) {
  602. binary.LittleEndian.PutUint64(buf, n)
  603. }
  604. func (p *TCompactProtocol) fixedInt64ToBytes(n int64, buf []byte) {
  605. binary.LittleEndian.PutUint64(buf, uint64(n))
  606. }
  607. // Writes a byte without any possibility of all that field header nonsense.
  608. // Used internally by other writing methods that know they need to write a byte.
  609. func (p *TCompactProtocol) writeByteDirect(b byte) error {
  610. return p.trans.WriteByte(b)
  611. }
  612. // Writes a byte without any possibility of all that field header nonsense.
  613. func (p *TCompactProtocol) writeIntAsByteDirect(n int) (int, error) {
  614. return 1, p.writeByteDirect(byte(n))
  615. }
  616. //
  617. // Internal reading methods
  618. //
  619. // Read an i32 from the wire as a varint. The MSB of each byte is set
  620. // if there is another byte to follow. This can read up to 5 bytes.
  621. func (p *TCompactProtocol) readVarint32() (int32, error) {
  622. // if the wire contains the right stuff, this will just truncate the i64 we
  623. // read and get us the right sign.
  624. v, err := p.readVarint64()
  625. return int32(v), err
  626. }
  627. // Read an i64 from the wire as a proper varint. The MSB of each byte is set
  628. // if there is another byte to follow. This can read up to 10 bytes.
  629. func (p *TCompactProtocol) readVarint64() (int64, error) {
  630. shift := uint(0)
  631. result := int64(0)
  632. for {
  633. b, err := p.readByteDirect()
  634. if err != nil {
  635. return 0, err
  636. }
  637. result |= int64(b&0x7f) << shift
  638. if (b & 0x80) != 0x80 {
  639. break
  640. }
  641. shift += 7
  642. }
  643. return result, nil
  644. }
  645. // Read a byte, unlike ReadByte that reads Thrift-byte that is i8.
  646. func (p *TCompactProtocol) readByteDirect() (byte, error) {
  647. return p.trans.ReadByte()
  648. }
  649. //
  650. // encoding helpers
  651. //
  652. // Convert from zigzag int to int.
  653. func (p *TCompactProtocol) zigzagToInt32(n int32) int32 {
  654. u := uint32(n)
  655. return int32(u>>1) ^ -(n & 1)
  656. }
  657. // Convert from zigzag long to long.
  658. func (p *TCompactProtocol) zigzagToInt64(n int64) int64 {
  659. u := uint64(n)
  660. return int64(u>>1) ^ -(n & 1)
  661. }
  662. // Note that it's important that the mask bytes are long literals,
  663. // otherwise they'll default to ints, and when you shift an int left 56 bits,
  664. // you just get a messed up int.
  665. func (p *TCompactProtocol) bytesToInt64(b []byte) int64 {
  666. return int64(binary.LittleEndian.Uint64(b))
  667. }
  668. // Note that it's important that the mask bytes are long literals,
  669. // otherwise they'll default to ints, and when you shift an int left 56 bits,
  670. // you just get a messed up int.
  671. func (p *TCompactProtocol) bytesToUint64(b []byte) uint64 {
  672. return binary.LittleEndian.Uint64(b)
  673. }
  674. //
  675. // type testing and converting
  676. //
  677. func (p *TCompactProtocol) isBoolType(b byte) bool {
  678. return (b&0x0f) == COMPACT_BOOLEAN_TRUE || (b&0x0f) == COMPACT_BOOLEAN_FALSE
  679. }
  680. // Given a tCompactType constant, convert it to its corresponding
  681. // TType value.
  682. func (p *TCompactProtocol) getTType(t tCompactType) (TType, error) {
  683. switch byte(t) & 0x0f {
  684. case STOP:
  685. return STOP, nil
  686. case COMPACT_BOOLEAN_FALSE, COMPACT_BOOLEAN_TRUE:
  687. return BOOL, nil
  688. case COMPACT_BYTE:
  689. return BYTE, nil
  690. case COMPACT_I16:
  691. return I16, nil
  692. case COMPACT_I32:
  693. return I32, nil
  694. case COMPACT_I64:
  695. return I64, nil
  696. case COMPACT_DOUBLE:
  697. return DOUBLE, nil
  698. case COMPACT_BINARY:
  699. return STRING, nil
  700. case COMPACT_LIST:
  701. return LIST, nil
  702. case COMPACT_SET:
  703. return SET, nil
  704. case COMPACT_MAP:
  705. return MAP, nil
  706. case COMPACT_STRUCT:
  707. return STRUCT, nil
  708. }
  709. return STOP, TException(fmt.Errorf("don't know what type: %d", t&0x0f))
  710. }
  711. // Given a TType value, find the appropriate TCompactProtocol.Types constant.
  712. func (p *TCompactProtocol) getCompactType(t TType) tCompactType {
  713. return ttypeToCompactType[t]
  714. }