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
20package thrift
21
22import (
23	"errors"
24)
25
26const (
27	VERSION_MASK = 0xffff0000
28	VERSION_1    = 0x80010000
29)
30
31type TProtocol interface {
32	WriteMessageBegin(name string, typeId TMessageType, seqid int32) error
33	WriteMessageEnd() error
34	WriteStructBegin(name string) error
35	WriteStructEnd() error
36	WriteFieldBegin(name string, typeId TType, id int16) error
37	WriteFieldEnd() error
38	WriteFieldStop() error
39	WriteMapBegin(keyType TType, valueType TType, size int) error
40	WriteMapEnd() error
41	WriteListBegin(elemType TType, size int) error
42	WriteListEnd() error
43	WriteSetBegin(elemType TType, size int) error
44	WriteSetEnd() error
45	WriteBool(value bool) error
46	WriteByte(value int8) error
47	WriteI16(value int16) error
48	WriteI32(value int32) error
49	WriteI64(value int64) error
50	WriteDouble(value float64) error
51	WriteString(value string) error
52	WriteBinary(value []byte) error
53
54	ReadMessageBegin() (name string, typeId TMessageType, seqid int32, err error)
55	ReadMessageEnd() error
56	ReadStructBegin() (name string, err error)
57	ReadStructEnd() error
58	ReadFieldBegin() (name string, typeId TType, id int16, err error)
59	ReadFieldEnd() error
60	ReadMapBegin() (keyType TType, valueType TType, size int, err error)
61	ReadMapEnd() error
62	ReadListBegin() (elemType TType, size int, err error)
63	ReadListEnd() error
64	ReadSetBegin() (elemType TType, size int, err error)
65	ReadSetEnd() error
66	ReadBool() (value bool, err error)
67	ReadByte() (value int8, err error)
68	ReadI16() (value int16, err error)
69	ReadI32() (value int32, err error)
70	ReadI64() (value int64, err error)
71	ReadDouble() (value float64, err error)
72	ReadString() (value string, err error)
73	ReadBinary() (value []byte, err error)
74
75	Skip(fieldType TType) (err error)
76	Flush() (err error)
77
78	Transport() TTransport
79}
80
81// The maximum recursive depth the skip() function will traverse
82const DEFAULT_RECURSION_DEPTH = 64
83
84// Skips over the next data element from the provided input TProtocol object.
85func SkipDefaultDepth(prot TProtocol, typeId TType) (err error) {
86	return Skip(prot, typeId, DEFAULT_RECURSION_DEPTH)
87}
88
89// Skips over the next data element from the provided input TProtocol object.
90func Skip(self TProtocol, fieldType TType, maxDepth int) (err error) {
91
92    if maxDepth <= 0 {
93		return NewTProtocolExceptionWithType( DEPTH_LIMIT, errors.New("Depth limit exceeded"))
94	}
95
96	switch fieldType {
97	case STOP:
98		return
99	case BOOL:
100		_, err = self.ReadBool()
101		return
102	case BYTE:
103		_, err = self.ReadByte()
104		return
105	case I16:
106		_, err = self.ReadI16()
107		return
108	case I32:
109		_, err = self.ReadI32()
110		return
111	case I64:
112		_, err = self.ReadI64()
113		return
114	case DOUBLE:
115		_, err = self.ReadDouble()
116		return
117	case STRING:
118		_, err = self.ReadString()
119		return
120	case STRUCT:
121		if _, err = self.ReadStructBegin(); err != nil {
122			return err
123		}
124		for {
125			_, typeId, _, _ := self.ReadFieldBegin()
126			if typeId == STOP {
127				break
128			}
129			err := Skip(self, typeId, maxDepth-1)
130			if err != nil {
131				return err
132			}
133			self.ReadFieldEnd()
134		}
135		return self.ReadStructEnd()
136	case MAP:
137		keyType, valueType, size, err := self.ReadMapBegin()
138		if err != nil {
139			return err
140		}
141		for i := 0; i < size; i++ {
142			err := Skip(self, keyType, maxDepth-1)
143			if err != nil {
144				return err
145			}
146			self.Skip(valueType)
147		}
148		return self.ReadMapEnd()
149	case SET:
150		elemType, size, err := self.ReadSetBegin()
151		if err != nil {
152			return err
153		}
154		for i := 0; i < size; i++ {
155			err := Skip(self, elemType, maxDepth-1)
156			if err != nil {
157				return err
158			}
159		}
160		return self.ReadSetEnd()
161	case LIST:
162		elemType, size, err := self.ReadListBegin()
163		if err != nil {
164			return err
165		}
166		for i := 0; i < size; i++ {
167			err := Skip(self, elemType, maxDepth-1)
168			if err != nil {
169				return err
170			}
171		}
172		return self.ReadListEnd()
173	}
174	return nil
175}
176