compact_protocol.go 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797
  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 byte) error {
  234. err := p.writeByteDirect(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 preceeding.
  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.ReadByte()
  288. if protocolId != COMPACT_PROTOCOL_ID {
  289. e := fmt.Errorf("Expected protocol id %02x but got %02x", COMPACT_PROTOCOL_ID, protocolId)
  290. return "", typeId, seqId, NewTProtocolExceptionWithType(BAD_VERSION, e)
  291. }
  292. versionAndType, err := p.ReadByte()
  293. version := versionAndType & COMPACT_VERSION_MASK
  294. typeId = TMessageType((versionAndType >> COMPACT_TYPE_SHIFT_AMOUNT) & COMPACT_TYPE_BITS)
  295. if err != nil {
  296. return
  297. }
  298. if version != COMPACT_VERSION {
  299. e := fmt.Errorf("Expected version %02x but got %02x", COMPACT_VERSION, version)
  300. err = NewTProtocolExceptionWithType(BAD_VERSION, e)
  301. return
  302. }
  303. seqId, e := p.readVarint32()
  304. if e != nil {
  305. err = NewTProtocolException(e)
  306. return
  307. }
  308. name, err = p.ReadString()
  309. return
  310. }
  311. func (p *TCompactProtocol) ReadMessageEnd() error { return nil }
  312. // Read a struct begin. There's nothing on the wire for this, but it is our
  313. // opportunity to push a new struct begin marker onto the field stack.
  314. func (p *TCompactProtocol) ReadStructBegin() (name string, err error) {
  315. p.lastField = append(p.lastField, p.lastFieldId)
  316. p.lastFieldId = 0
  317. return
  318. }
  319. // Doesn't actually consume any wire data, just removes the last field for
  320. // this struct from the field stack.
  321. func (p *TCompactProtocol) ReadStructEnd() error {
  322. // consume the last field we read off the wire.
  323. p.lastFieldId = p.lastField[len(p.lastField)-1]
  324. p.lastField = p.lastField[:len(p.lastField)-1]
  325. return nil
  326. }
  327. // Read a field header off the wire.
  328. func (p *TCompactProtocol) ReadFieldBegin() (name string, typeId TType, id int16, err error) {
  329. t, err := p.ReadByte()
  330. if err != nil {
  331. return
  332. }
  333. // if it's a stop, then we can return immediately, as the struct is over.
  334. if (t & 0x0f) == STOP {
  335. return "", STOP, 0, nil
  336. }
  337. // mask off the 4 MSB of the type header. it could contain a field id delta.
  338. modifier := int16((t & 0xf0) >> 4)
  339. if modifier == 0 {
  340. // not a delta. look ahead for the zigzag varint field id.
  341. id, err = p.ReadI16()
  342. if err != nil {
  343. return
  344. }
  345. } else {
  346. // has a delta. add the delta to the last read field id.
  347. id = int16(p.lastFieldId) + modifier
  348. }
  349. typeId, e := p.getTType(tCompactType(t & 0x0f))
  350. if e != nil {
  351. err = NewTProtocolException(e)
  352. return
  353. }
  354. // if this happens to be a boolean field, the value is encoded in the type
  355. if p.isBoolType(t) {
  356. // save the boolean value in a special instance variable.
  357. p.boolValue = (byte(t)&0x0f == COMPACT_BOOLEAN_TRUE)
  358. p.boolValueIsNotNull = true
  359. }
  360. // push the new field onto the field stack so we can keep the deltas going.
  361. p.lastFieldId = int(id)
  362. return
  363. }
  364. func (p *TCompactProtocol) ReadFieldEnd() error { return nil }
  365. // Read a map header off the wire. If the size is zero, skip reading the key
  366. // and value type. This means that 0-length maps will yield TMaps without the
  367. // "correct" types.
  368. func (p *TCompactProtocol) ReadMapBegin() (keyType TType, valueType TType, size int, err error) {
  369. size32, e := p.readVarint32()
  370. if e != nil {
  371. err = NewTProtocolException(e)
  372. return
  373. }
  374. if size32 < 0 {
  375. err = invalidDataLength
  376. return
  377. }
  378. size = int(size32)
  379. keyAndValueType := byte(STOP)
  380. if size != 0 {
  381. keyAndValueType, err = p.ReadByte()
  382. if err != nil {
  383. return
  384. }
  385. }
  386. keyType, _ = p.getTType(tCompactType(keyAndValueType >> 4))
  387. valueType, _ = p.getTType(tCompactType(keyAndValueType & 0xf))
  388. return
  389. }
  390. func (p *TCompactProtocol) ReadMapEnd() error { return nil }
  391. // Read a list header off the wire. If the list size is 0-14, the size will
  392. // be packed into the element type header. If it's a longer list, the 4 MSB
  393. // of the element type header will be 0xF, and a varint will follow with the
  394. // true size.
  395. func (p *TCompactProtocol) ReadListBegin() (elemType TType, size int, err error) {
  396. size_and_type, err := p.ReadByte()
  397. if err != nil {
  398. return
  399. }
  400. size = int((size_and_type >> 4) & 0x0f)
  401. if size == 15 {
  402. size2, e := p.readVarint32()
  403. if e != nil {
  404. err = NewTProtocolException(e)
  405. return
  406. }
  407. if size2 < 0 {
  408. err = invalidDataLength
  409. return
  410. }
  411. size = int(size2)
  412. }
  413. elemType, e := p.getTType(tCompactType(size_and_type))
  414. if e != nil {
  415. err = NewTProtocolException(e)
  416. return
  417. }
  418. return
  419. }
  420. func (p *TCompactProtocol) ReadListEnd() error { return nil }
  421. // Read a set header off the wire. If the set size is 0-14, the size will
  422. // be packed into the element type header. If it's a longer set, the 4 MSB
  423. // of the element type header will be 0xF, and a varint will follow with the
  424. // true size.
  425. func (p *TCompactProtocol) ReadSetBegin() (elemType TType, size int, err error) {
  426. return p.ReadListBegin()
  427. }
  428. func (p *TCompactProtocol) ReadSetEnd() error { return nil }
  429. // Read a boolean off the wire. If this is a boolean field, the value should
  430. // already have been read during readFieldBegin, so we'll just consume the
  431. // pre-stored value. Otherwise, read a byte.
  432. func (p *TCompactProtocol) ReadBool() (value bool, err error) {
  433. if p.boolValueIsNotNull {
  434. p.boolValueIsNotNull = false
  435. return p.boolValue, nil
  436. }
  437. v, err := p.ReadByte()
  438. return v == COMPACT_BOOLEAN_TRUE, err
  439. }
  440. // Read a single byte off the wire. Nothing interesting here.
  441. func (p *TCompactProtocol) ReadByte() (value byte, err error) {
  442. value, err = p.trans.ReadByte()
  443. if err != nil {
  444. return 0, NewTProtocolException(err)
  445. }
  446. return
  447. }
  448. // Read an i16 from the wire as a zigzag varint.
  449. func (p *TCompactProtocol) ReadI16() (value int16, err error) {
  450. v, err := p.ReadI32()
  451. return int16(v), err
  452. }
  453. // Read an i32 from the wire as a zigzag varint.
  454. func (p *TCompactProtocol) ReadI32() (value int32, err error) {
  455. v, e := p.readVarint32()
  456. if e != nil {
  457. return 0, NewTProtocolException(e)
  458. }
  459. value = p.zigzagToInt32(v)
  460. return value, nil
  461. }
  462. // Read an i64 from the wire as a zigzag varint.
  463. func (p *TCompactProtocol) ReadI64() (value int64, err error) {
  464. v, e := p.readVarint64()
  465. if e != nil {
  466. return 0, NewTProtocolException(e)
  467. }
  468. value = p.zigzagToInt64(v)
  469. return value, nil
  470. }
  471. // No magic here - just read a double off the wire.
  472. func (p *TCompactProtocol) ReadDouble() (value float64, err error) {
  473. longBits := p.buffer[0:8]
  474. _, e := io.ReadFull(p.trans, longBits)
  475. if e != nil {
  476. return 0.0, NewTProtocolException(e)
  477. }
  478. return math.Float64frombits(p.bytesToUint64(longBits)), nil
  479. }
  480. // Reads a []byte (via readBinary), and then UTF-8 decodes it.
  481. func (p *TCompactProtocol) ReadString() (value string, err error) {
  482. length, e := p.readVarint32()
  483. if e != nil {
  484. return "", NewTProtocolException(e)
  485. }
  486. if length < 0 {
  487. return "", invalidDataLength
  488. }
  489. if length == 0 {
  490. return "", nil
  491. }
  492. var buf []byte
  493. if length <= int32(len(p.buffer)) {
  494. buf = p.buffer[0:length]
  495. } else {
  496. buf = make([]byte, length)
  497. }
  498. _, e = io.ReadFull(p.trans, buf)
  499. return string(buf), NewTProtocolException(e)
  500. }
  501. // Read a []byte from the wire.
  502. func (p *TCompactProtocol) ReadBinary() (value []byte, err error) {
  503. length, e := p.readVarint32()
  504. if e != nil {
  505. return nil, NewTProtocolException(e)
  506. }
  507. if length == 0 {
  508. return []byte{}, nil
  509. }
  510. if length < 0 {
  511. return nil, invalidDataLength
  512. }
  513. buf := make([]byte, length)
  514. _, e = io.ReadFull(p.trans, buf)
  515. return buf, NewTProtocolException(e)
  516. }
  517. func (p *TCompactProtocol) Flush() (err error) {
  518. return NewTProtocolException(p.trans.Flush())
  519. }
  520. func (p *TCompactProtocol) Skip(fieldType TType) (err error) {
  521. return SkipDefaultDepth(p, fieldType)
  522. }
  523. func (p *TCompactProtocol) Transport() TTransport {
  524. return p.origTransport
  525. }
  526. //
  527. // Internal writing methods
  528. //
  529. // Abstract method for writing the start of lists and sets. List and sets on
  530. // the wire differ only by the type indicator.
  531. func (p *TCompactProtocol) writeCollectionBegin(elemType TType, size int) (int, error) {
  532. if size <= 14 {
  533. return 1, p.writeByteDirect(byte(int32(size<<4) | int32(p.getCompactType(elemType))))
  534. }
  535. err := p.writeByteDirect(0xf0 | byte(p.getCompactType(elemType)))
  536. if err != nil {
  537. return 0, err
  538. }
  539. m, err := p.writeVarint32(int32(size))
  540. return 1 + m, err
  541. }
  542. // Write an i32 as a varint. Results in 1-5 bytes on the wire.
  543. // TODO(pomack): make a permanent buffer like writeVarint64?
  544. func (p *TCompactProtocol) writeVarint32(n int32) (int, error) {
  545. i32buf := p.buffer[0:5]
  546. idx := 0
  547. for {
  548. if (n & ^0x7F) == 0 {
  549. i32buf[idx] = byte(n)
  550. idx++
  551. // p.writeByteDirect(byte(n));
  552. break
  553. // return;
  554. } else {
  555. i32buf[idx] = byte((n & 0x7F) | 0x80)
  556. idx++
  557. // p.writeByteDirect(byte(((n & 0x7F) | 0x80)));
  558. u := uint32(n)
  559. n = int32(u >> 7)
  560. }
  561. }
  562. return p.trans.Write(i32buf[0:idx])
  563. }
  564. // Write an i64 as a varint. Results in 1-10 bytes on the wire.
  565. func (p *TCompactProtocol) writeVarint64(n int64) (int, error) {
  566. varint64out := p.buffer[0:10]
  567. idx := 0
  568. for {
  569. if (n & ^0x7F) == 0 {
  570. varint64out[idx] = byte(n)
  571. idx++
  572. break
  573. } else {
  574. varint64out[idx] = byte((n & 0x7F) | 0x80)
  575. idx++
  576. u := uint64(n)
  577. n = int64(u >> 7)
  578. }
  579. }
  580. return p.trans.Write(varint64out[0:idx])
  581. }
  582. // Convert l into a zigzag long. This allows negative numbers to be
  583. // represented compactly as a varint.
  584. func (p *TCompactProtocol) int64ToZigzag(l int64) int64 {
  585. return (l << 1) ^ (l >> 63)
  586. }
  587. // Convert l into a zigzag long. This allows negative numbers to be
  588. // represented compactly as a varint.
  589. func (p *TCompactProtocol) int32ToZigzag(n int32) int32 {
  590. return (n << 1) ^ (n >> 31)
  591. }
  592. func (p *TCompactProtocol) fixedUint64ToBytes(n uint64, buf []byte) {
  593. binary.LittleEndian.PutUint64(buf, n)
  594. }
  595. func (p *TCompactProtocol) fixedInt64ToBytes(n int64, buf []byte) {
  596. binary.LittleEndian.PutUint64(buf, uint64(n))
  597. }
  598. // Writes a byte without any possiblity of all that field header nonsense.
  599. // Used internally by other writing methods that know they need to write a byte.
  600. func (p *TCompactProtocol) writeByteDirect(b byte) error {
  601. return p.trans.WriteByte(b)
  602. }
  603. // Writes a byte without any possiblity of all that field header nonsense.
  604. func (p *TCompactProtocol) writeIntAsByteDirect(n int) (int, error) {
  605. return 1, p.writeByteDirect(byte(n))
  606. }
  607. //
  608. // Internal reading methods
  609. //
  610. // Read an i32 from the wire as a varint. The MSB of each byte is set
  611. // if there is another byte to follow. This can read up to 5 bytes.
  612. func (p *TCompactProtocol) readVarint32() (int32, error) {
  613. // if the wire contains the right stuff, this will just truncate the i64 we
  614. // read and get us the right sign.
  615. v, err := p.readVarint64()
  616. return int32(v), err
  617. }
  618. // Read an i64 from the wire as a proper varint. The MSB of each byte is set
  619. // if there is another byte to follow. This can read up to 10 bytes.
  620. func (p *TCompactProtocol) readVarint64() (int64, error) {
  621. shift := uint(0)
  622. result := int64(0)
  623. for {
  624. b, err := p.ReadByte()
  625. if err != nil {
  626. return 0, err
  627. }
  628. result |= int64(b&0x7f) << shift
  629. if (b & 0x80) != 0x80 {
  630. break
  631. }
  632. shift += 7
  633. }
  634. return result, nil
  635. }
  636. //
  637. // encoding helpers
  638. //
  639. // Convert from zigzag int to int.
  640. func (p *TCompactProtocol) zigzagToInt32(n int32) int32 {
  641. u := uint32(n)
  642. return int32(u>>1) ^ -(n & 1)
  643. }
  644. // Convert from zigzag long to long.
  645. func (p *TCompactProtocol) zigzagToInt64(n int64) int64 {
  646. u := uint64(n)
  647. return int64(u>>1) ^ -(n & 1)
  648. }
  649. // Note that it's important that the mask bytes are long literals,
  650. // otherwise they'll default to ints, and when you shift an int left 56 bits,
  651. // you just get a messed up int.
  652. func (p *TCompactProtocol) bytesToInt64(b []byte) int64 {
  653. return int64(binary.LittleEndian.Uint64(b))
  654. }
  655. // Note that it's important that the mask bytes are long literals,
  656. // otherwise they'll default to ints, and when you shift an int left 56 bits,
  657. // you just get a messed up int.
  658. func (p *TCompactProtocol) bytesToUint64(b []byte) uint64 {
  659. return binary.LittleEndian.Uint64(b)
  660. }
  661. //
  662. // type testing and converting
  663. //
  664. func (p *TCompactProtocol) isBoolType(b byte) bool {
  665. return (b&0x0f) == COMPACT_BOOLEAN_TRUE || (b&0x0f) == COMPACT_BOOLEAN_FALSE
  666. }
  667. // Given a tCompactType constant, convert it to its corresponding
  668. // TType value.
  669. func (p *TCompactProtocol) getTType(t tCompactType) (TType, error) {
  670. switch byte(t) & 0x0f {
  671. case STOP:
  672. return STOP, nil
  673. case COMPACT_BOOLEAN_FALSE, COMPACT_BOOLEAN_TRUE:
  674. return BOOL, nil
  675. case COMPACT_BYTE:
  676. return BYTE, nil
  677. case COMPACT_I16:
  678. return I16, nil
  679. case COMPACT_I32:
  680. return I32, nil
  681. case COMPACT_I64:
  682. return I64, nil
  683. case COMPACT_DOUBLE:
  684. return DOUBLE, nil
  685. case COMPACT_BINARY:
  686. return STRING, nil
  687. case COMPACT_LIST:
  688. return LIST, nil
  689. case COMPACT_SET:
  690. return SET, nil
  691. case COMPACT_MAP:
  692. return MAP, nil
  693. case COMPACT_STRUCT:
  694. return STRUCT, nil
  695. }
  696. return STOP, TException(fmt.Errorf("don't know what type: %s", t&0x0f))
  697. }
  698. // Given a TType value, find the appropriate TCompactProtocol.Types constant.
  699. func (p *TCompactProtocol) getCompactType(t TType) tCompactType {
  700. return ttypeToCompactType[t]
  701. }