compact_protocol.go 24 KB

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