diff options
Diffstat (limited to 'froofle/protobuf/internal')
-rw-r--r-- | froofle/protobuf/internal/__init__.py | 0 | ||||
-rw-r--r-- | froofle/protobuf/internal/decoder.py | 209 | ||||
-rw-r--r-- | froofle/protobuf/internal/encoder.py | 206 | ||||
-rw-r--r-- | froofle/protobuf/internal/input_stream.py | 326 | ||||
-rw-r--r-- | froofle/protobuf/internal/message_listener.py | 69 | ||||
-rw-r--r-- | froofle/protobuf/internal/output_stream.py | 125 | ||||
-rw-r--r-- | froofle/protobuf/internal/type_checkers.py | 268 | ||||
-rw-r--r-- | froofle/protobuf/internal/wire_format.py | 236 |
8 files changed, 0 insertions, 1439 deletions
diff --git a/froofle/protobuf/internal/__init__.py b/froofle/protobuf/internal/__init__.py deleted file mode 100644 index e69de29b..00000000 --- a/froofle/protobuf/internal/__init__.py +++ /dev/null | |||
diff --git a/froofle/protobuf/internal/decoder.py b/froofle/protobuf/internal/decoder.py deleted file mode 100644 index 2dd4c96e..00000000 --- a/froofle/protobuf/internal/decoder.py +++ /dev/null | |||
@@ -1,209 +0,0 @@ | |||
1 | # Protocol Buffers - Google's data interchange format | ||
2 | # Copyright 2008 Google Inc. All rights reserved. | ||
3 | # http://code.google.com/p/protobuf/ | ||
4 | # | ||
5 | # Redistribution and use in source and binary forms, with or without | ||
6 | # modification, are permitted provided that the following conditions are | ||
7 | # met: | ||
8 | # | ||
9 | # * Redistributions of source code must retain the above copyright | ||
10 | # notice, this list of conditions and the following disclaimer. | ||
11 | # * Redistributions in binary form must reproduce the above | ||
12 | # copyright notice, this list of conditions and the following disclaimer | ||
13 | # in the documentation and/or other materials provided with the | ||
14 | # distribution. | ||
15 | # * Neither the name of Google Inc. nor the names of its | ||
16 | # contributors may be used to endorse or promote products derived from | ||
17 | # this software without specific prior written permission. | ||
18 | # | ||
19 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
20 | # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
21 | # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
22 | # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
23 | # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
24 | # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
25 | # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
26 | # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
27 | # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
28 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
29 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
30 | |||
31 | """Class for decoding protocol buffer primitives. | ||
32 | |||
33 | Contains the logic for decoding every logical protocol field type | ||
34 | from one of the 5 physical wire types. | ||
35 | """ | ||
36 | |||
37 | __author__ = 'robinson@google.com (Will Robinson)' | ||
38 | |||
39 | import struct | ||
40 | from froofle.protobuf import message | ||
41 | from froofle.protobuf.internal import input_stream | ||
42 | from froofle.protobuf.internal import wire_format | ||
43 | |||
44 | |||
45 | |||
46 | # Note that much of this code is ported from //net/proto/ProtocolBuffer, and | ||
47 | # that the interface is strongly inspired by WireFormat from the C++ proto2 | ||
48 | # implementation. | ||
49 | |||
50 | |||
51 | class Decoder(object): | ||
52 | |||
53 | """Decodes logical protocol buffer fields from the wire.""" | ||
54 | |||
55 | def __init__(self, s): | ||
56 | """Initializes the decoder to read from s. | ||
57 | |||
58 | Args: | ||
59 | s: An immutable sequence of bytes, which must be accessible | ||
60 | via the Python buffer() primitive (i.e., buffer(s)). | ||
61 | """ | ||
62 | self._stream = input_stream.InputStream(s) | ||
63 | |||
64 | def EndOfStream(self): | ||
65 | """Returns true iff we've reached the end of the bytes we're reading.""" | ||
66 | return self._stream.EndOfStream() | ||
67 | |||
68 | def Position(self): | ||
69 | """Returns the 0-indexed position in |s|.""" | ||
70 | return self._stream.Position() | ||
71 | |||
72 | def ReadFieldNumberAndWireType(self): | ||
73 | """Reads a tag from the wire. Returns a (field_number, wire_type) pair.""" | ||
74 | tag_and_type = self.ReadUInt32() | ||
75 | return wire_format.UnpackTag(tag_and_type) | ||
76 | |||
77 | def SkipBytes(self, bytes): | ||
78 | """Skips the specified number of bytes on the wire.""" | ||
79 | self._stream.SkipBytes(bytes) | ||
80 | |||
81 | # Note that the Read*() methods below are not exactly symmetrical with the | ||
82 | # corresponding Encoder.Append*() methods. Those Encoder methods first | ||
83 | # encode a tag, but the Read*() methods below assume that the tag has already | ||
84 | # been read, and that the client wishes to read a field of the specified type | ||
85 | # starting at the current position. | ||
86 | |||
87 | def ReadInt32(self): | ||
88 | """Reads and returns a signed, varint-encoded, 32-bit integer.""" | ||
89 | return self._stream.ReadVarint32() | ||
90 | |||
91 | def ReadInt64(self): | ||
92 | """Reads and returns a signed, varint-encoded, 64-bit integer.""" | ||
93 | return self._stream.ReadVarint64() | ||
94 | |||
95 | def ReadUInt32(self): | ||
96 | """Reads and returns an signed, varint-encoded, 32-bit integer.""" | ||
97 | return self._stream.ReadVarUInt32() | ||
98 | |||
99 | def ReadUInt64(self): | ||
100 | """Reads and returns an signed, varint-encoded,64-bit integer.""" | ||
101 | return self._stream.ReadVarUInt64() | ||
102 | |||
103 | def ReadSInt32(self): | ||
104 | """Reads and returns a signed, zigzag-encoded, varint-encoded, | ||
105 | 32-bit integer.""" | ||
106 | return wire_format.ZigZagDecode(self._stream.ReadVarUInt32()) | ||
107 | |||
108 | def ReadSInt64(self): | ||
109 | """Reads and returns a signed, zigzag-encoded, varint-encoded, | ||
110 | 64-bit integer.""" | ||
111 | return wire_format.ZigZagDecode(self._stream.ReadVarUInt64()) | ||
112 | |||
113 | def ReadFixed32(self): | ||
114 | """Reads and returns an unsigned, fixed-width, 32-bit integer.""" | ||
115 | return self._stream.ReadLittleEndian32() | ||
116 | |||
117 | def ReadFixed64(self): | ||
118 | """Reads and returns an unsigned, fixed-width, 64-bit integer.""" | ||
119 | return self._stream.ReadLittleEndian64() | ||
120 | |||
121 | def ReadSFixed32(self): | ||
122 | """Reads and returns a signed, fixed-width, 32-bit integer.""" | ||
123 | value = self._stream.ReadLittleEndian32() | ||
124 | if value >= (1 << 31): | ||
125 | value -= (1 << 32) | ||
126 | return value | ||
127 | |||
128 | def ReadSFixed64(self): | ||
129 | """Reads and returns a signed, fixed-width, 64-bit integer.""" | ||
130 | value = self._stream.ReadLittleEndian64() | ||
131 | if value >= (1 << 63): | ||
132 | value -= (1 << 64) | ||
133 | return value | ||
134 | |||
135 | def ReadFloat(self): | ||
136 | """Reads and returns a 4-byte floating-point number.""" | ||
137 | serialized = self._stream.ReadBytes(4) | ||
138 | return struct.unpack('f', serialized)[0] | ||
139 | |||
140 | def ReadDouble(self): | ||
141 | """Reads and returns an 8-byte floating-point number.""" | ||
142 | serialized = self._stream.ReadBytes(8) | ||
143 | return struct.unpack('d', serialized)[0] | ||
144 | |||
145 | def ReadBool(self): | ||
146 | """Reads and returns a bool.""" | ||
147 | i = self._stream.ReadVarUInt32() | ||
148 | return bool(i) | ||
149 | |||
150 | def ReadEnum(self): | ||
151 | """Reads and returns an enum value.""" | ||
152 | return self._stream.ReadVarUInt32() | ||
153 | |||
154 | def ReadString(self): | ||
155 | """Reads and returns a length-delimited string.""" | ||
156 | bytes = self.ReadBytes() | ||
157 | return unicode(bytes, 'utf-8') | ||
158 | |||
159 | def ReadBytes(self): | ||
160 | """Reads and returns a length-delimited byte sequence.""" | ||
161 | length = self._stream.ReadVarUInt32() | ||
162 | return self._stream.ReadBytes(length) | ||
163 | |||
164 | def ReadMessageInto(self, msg): | ||
165 | """Calls msg.MergeFromString() to merge | ||
166 | length-delimited serialized message data into |msg|. | ||
167 | |||
168 | REQUIRES: The decoder must be positioned at the serialized "length" | ||
169 | prefix to a length-delmiited serialized message. | ||
170 | |||
171 | POSTCONDITION: The decoder is positioned just after the | ||
172 | serialized message, and we have merged those serialized | ||
173 | contents into |msg|. | ||
174 | """ | ||
175 | length = self._stream.ReadVarUInt32() | ||
176 | sub_buffer = self._stream.GetSubBuffer(length) | ||
177 | num_bytes_used = msg.MergeFromString(sub_buffer) | ||
178 | if num_bytes_used != length: | ||
179 | raise message.DecodeError( | ||
180 | 'Submessage told to deserialize from %d-byte encoding, ' | ||
181 | 'but used only %d bytes' % (length, num_bytes_used)) | ||
182 | self._stream.SkipBytes(num_bytes_used) | ||
183 | |||
184 | def ReadGroupInto(self, expected_field_number, group): | ||
185 | """Calls group.MergeFromString() to merge | ||
186 | END_GROUP-delimited serialized message data into |group|. | ||
187 | We'll raise an exception if we don't find an END_GROUP | ||
188 | tag immediately after the serialized message contents. | ||
189 | |||
190 | REQUIRES: The decoder is positioned just after the START_GROUP | ||
191 | tag for this group. | ||
192 | |||
193 | POSTCONDITION: The decoder is positioned just after the | ||
194 | END_GROUP tag for this group, and we have merged | ||
195 | the contents of the group into |group|. | ||
196 | """ | ||
197 | sub_buffer = self._stream.GetSubBuffer() # No a priori length limit. | ||
198 | num_bytes_used = group.MergeFromString(sub_buffer) | ||
199 | if num_bytes_used < 0: | ||
200 | raise message.DecodeError('Group message reported negative bytes read.') | ||
201 | self._stream.SkipBytes(num_bytes_used) | ||
202 | field_number, field_type = self.ReadFieldNumberAndWireType() | ||
203 | if field_type != wire_format.WIRETYPE_END_GROUP: | ||
204 | raise message.DecodeError('Group message did not end with an END_GROUP.') | ||
205 | if field_number != expected_field_number: | ||
206 | raise message.DecodeError('END_GROUP tag had field ' | ||
207 | 'number %d, was expecting field number %d' % ( | ||
208 | field_number, expected_field_number)) | ||
209 | # We're now positioned just after the END_GROUP tag. Perfect. | ||
diff --git a/froofle/protobuf/internal/encoder.py b/froofle/protobuf/internal/encoder.py deleted file mode 100644 index 8b924b3e..00000000 --- a/froofle/protobuf/internal/encoder.py +++ /dev/null | |||
@@ -1,206 +0,0 @@ | |||
1 | # Protocol Buffers - Google's data interchange format | ||
2 | # Copyright 2008 Google Inc. All rights reserved. | ||
3 | # http://code.google.com/p/protobuf/ | ||
4 | # | ||
5 | # Redistribution and use in source and binary forms, with or without | ||
6 | # modification, are permitted provided that the following conditions are | ||
7 | # met: | ||
8 | # | ||
9 | # * Redistributions of source code must retain the above copyright | ||
10 | # notice, this list of conditions and the following disclaimer. | ||
11 | # * Redistributions in binary form must reproduce the above | ||
12 | # copyright notice, this list of conditions and the following disclaimer | ||
13 | # in the documentation and/or other materials provided with the | ||
14 | # distribution. | ||
15 | # * Neither the name of Google Inc. nor the names of its | ||
16 | # contributors may be used to endorse or promote products derived from | ||
17 | # this software without specific prior written permission. | ||
18 | # | ||
19 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
20 | # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
21 | # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
22 | # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
23 | # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
24 | # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
25 | # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
26 | # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
27 | # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
28 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
29 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
30 | |||
31 | """Class for encoding protocol message primitives. | ||
32 | |||
33 | Contains the logic for encoding every logical protocol field type | ||
34 | into one of the 5 physical wire types. | ||
35 | """ | ||
36 | |||
37 | __author__ = 'robinson@google.com (Will Robinson)' | ||
38 | |||
39 | import struct | ||
40 | from froofle.protobuf import message | ||
41 | from froofle.protobuf.internal import wire_format | ||
42 | from froofle.protobuf.internal import output_stream | ||
43 | |||
44 | |||
45 | # Note that much of this code is ported from //net/proto/ProtocolBuffer, and | ||
46 | # that the interface is strongly inspired by WireFormat from the C++ proto2 | ||
47 | # implementation. | ||
48 | |||
49 | |||
50 | class Encoder(object): | ||
51 | |||
52 | """Encodes logical protocol buffer fields to the wire format.""" | ||
53 | |||
54 | def __init__(self): | ||
55 | self._stream = output_stream.OutputStream() | ||
56 | |||
57 | def ToString(self): | ||
58 | """Returns all values encoded in this object as a string.""" | ||
59 | return self._stream.ToString() | ||
60 | |||
61 | # All the Append*() methods below first append a tag+type pair to the buffer | ||
62 | # before appending the specified value. | ||
63 | |||
64 | def AppendInt32(self, field_number, value): | ||
65 | """Appends a 32-bit integer to our buffer, varint-encoded.""" | ||
66 | self._AppendTag(field_number, wire_format.WIRETYPE_VARINT) | ||
67 | self._stream.AppendVarint32(value) | ||
68 | |||
69 | def AppendInt64(self, field_number, value): | ||
70 | """Appends a 64-bit integer to our buffer, varint-encoded.""" | ||
71 | self._AppendTag(field_number, wire_format.WIRETYPE_VARINT) | ||
72 | self._stream.AppendVarint64(value) | ||
73 | |||
74 | def AppendUInt32(self, field_number, unsigned_value): | ||
75 | """Appends an unsigned 32-bit integer to our buffer, varint-encoded.""" | ||
76 | self._AppendTag(field_number, wire_format.WIRETYPE_VARINT) | ||
77 | self._stream.AppendVarUInt32(unsigned_value) | ||
78 | |||
79 | def AppendUInt64(self, field_number, unsigned_value): | ||
80 | """Appends an unsigned 64-bit integer to our buffer, varint-encoded.""" | ||
81 | self._AppendTag(field_number, wire_format.WIRETYPE_VARINT) | ||
82 | self._stream.AppendVarUInt64(unsigned_value) | ||
83 | |||
84 | def AppendSInt32(self, field_number, value): | ||
85 | """Appends a 32-bit integer to our buffer, zigzag-encoded and then | ||
86 | varint-encoded. | ||
87 | """ | ||
88 | self._AppendTag(field_number, wire_format.WIRETYPE_VARINT) | ||
89 | zigzag_value = wire_format.ZigZagEncode(value) | ||
90 | self._stream.AppendVarUInt32(zigzag_value) | ||
91 | |||
92 | def AppendSInt64(self, field_number, value): | ||
93 | """Appends a 64-bit integer to our buffer, zigzag-encoded and then | ||
94 | varint-encoded. | ||
95 | """ | ||
96 | self._AppendTag(field_number, wire_format.WIRETYPE_VARINT) | ||
97 | zigzag_value = wire_format.ZigZagEncode(value) | ||
98 | self._stream.AppendVarUInt64(zigzag_value) | ||
99 | |||
100 | def AppendFixed32(self, field_number, unsigned_value): | ||
101 | """Appends an unsigned 32-bit integer to our buffer, in little-endian | ||
102 | byte-order. | ||
103 | """ | ||
104 | self._AppendTag(field_number, wire_format.WIRETYPE_FIXED32) | ||
105 | self._stream.AppendLittleEndian32(unsigned_value) | ||
106 | |||
107 | def AppendFixed64(self, field_number, unsigned_value): | ||
108 | """Appends an unsigned 64-bit integer to our buffer, in little-endian | ||
109 | byte-order. | ||
110 | """ | ||
111 | self._AppendTag(field_number, wire_format.WIRETYPE_FIXED64) | ||
112 | self._stream.AppendLittleEndian64(unsigned_value) | ||
113 | |||
114 | def AppendSFixed32(self, field_number, value): | ||
115 | """Appends a signed 32-bit integer to our buffer, in little-endian | ||
116 | byte-order. | ||
117 | """ | ||
118 | sign = (value & 0x80000000) and -1 or 0 | ||
119 | if value >> 32 != sign: | ||
120 | raise message.EncodeError('SFixed32 out of range: %d' % value) | ||
121 | self._AppendTag(field_number, wire_format.WIRETYPE_FIXED32) | ||
122 | self._stream.AppendLittleEndian32(value & 0xffffffff) | ||
123 | |||
124 | def AppendSFixed64(self, field_number, value): | ||
125 | """Appends a signed 64-bit integer to our buffer, in little-endian | ||
126 | byte-order. | ||
127 | """ | ||
128 | sign = (value & 0x8000000000000000) and -1 or 0 | ||
129 | if value >> 64 != sign: | ||
130 | raise message.EncodeError('SFixed64 out of range: %d' % value) | ||
131 | self._AppendTag(field_number, wire_format.WIRETYPE_FIXED64) | ||
132 | self._stream.AppendLittleEndian64(value & 0xffffffffffffffff) | ||
133 | |||
134 | def AppendFloat(self, field_number, value): | ||
135 | """Appends a floating-point number to our buffer.""" | ||
136 | self._AppendTag(field_number, wire_format.WIRETYPE_FIXED32) | ||
137 | self._stream.AppendRawBytes(struct.pack('f', value)) | ||
138 | |||
139 | def AppendDouble(self, field_number, value): | ||
140 | """Appends a double-precision floating-point number to our buffer.""" | ||
141 | self._AppendTag(field_number, wire_format.WIRETYPE_FIXED64) | ||
142 | self._stream.AppendRawBytes(struct.pack('d', value)) | ||
143 | |||
144 | def AppendBool(self, field_number, value): | ||
145 | """Appends a boolean to our buffer.""" | ||
146 | self.AppendInt32(field_number, value) | ||
147 | |||
148 | def AppendEnum(self, field_number, value): | ||
149 | """Appends an enum value to our buffer.""" | ||
150 | self.AppendInt32(field_number, value) | ||
151 | |||
152 | def AppendString(self, field_number, value): | ||
153 | """Appends a length-prefixed unicode string, encoded as UTF-8 to our buffer, | ||
154 | with the length varint-encoded. | ||
155 | """ | ||
156 | self.AppendBytes(field_number, value.encode('utf-8')) | ||
157 | |||
158 | def AppendBytes(self, field_number, value): | ||
159 | """Appends a length-prefixed sequence of bytes to our buffer, with the | ||
160 | length varint-encoded. | ||
161 | """ | ||
162 | self._AppendTag(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED) | ||
163 | self._stream.AppendVarUInt32(len(value)) | ||
164 | self._stream.AppendRawBytes(value) | ||
165 | |||
166 | # TODO(robinson): For AppendGroup() and AppendMessage(), we'd really like to | ||
167 | # avoid the extra string copy here. We can do so if we widen the Message | ||
168 | # interface to be able to serialize to a stream in addition to a string. The | ||
169 | # challenge when thinking ahead to the Python/C API implementation of Message | ||
170 | # is finding a stream-like Python thing to which we can write raw bytes | ||
171 | # from C. I'm not sure such a thing exists(?). (array.array is pretty much | ||
172 | # what we want, but it's not directly exposed in the Python/C API). | ||
173 | |||
174 | def AppendGroup(self, field_number, group): | ||
175 | """Appends a group to our buffer. | ||
176 | """ | ||
177 | self._AppendTag(field_number, wire_format.WIRETYPE_START_GROUP) | ||
178 | self._stream.AppendRawBytes(group.SerializeToString()) | ||
179 | self._AppendTag(field_number, wire_format.WIRETYPE_END_GROUP) | ||
180 | |||
181 | def AppendMessage(self, field_number, msg): | ||
182 | """Appends a nested message to our buffer. | ||
183 | """ | ||
184 | self._AppendTag(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED) | ||
185 | self._stream.AppendVarUInt32(msg.ByteSize()) | ||
186 | self._stream.AppendRawBytes(msg.SerializeToString()) | ||
187 | |||
188 | def AppendMessageSetItem(self, field_number, msg): | ||
189 | """Appends an item using the message set wire format. | ||
190 | |||
191 | The message set message looks like this: | ||
192 | message MessageSet { | ||
193 | repeated group Item = 1 { | ||
194 | required int32 type_id = 2; | ||
195 | required string message = 3; | ||
196 | } | ||
197 | } | ||
198 | """ | ||
199 | self._AppendTag(1, wire_format.WIRETYPE_START_GROUP) | ||
200 | self.AppendInt32(2, field_number) | ||
201 | self.AppendMessage(3, msg) | ||
202 | self._AppendTag(1, wire_format.WIRETYPE_END_GROUP) | ||
203 | |||
204 | def _AppendTag(self, field_number, wire_type): | ||
205 | """Appends a tag containing field number and wire type information.""" | ||
206 | self._stream.AppendVarUInt32(wire_format.PackTag(field_number, wire_type)) | ||
diff --git a/froofle/protobuf/internal/input_stream.py b/froofle/protobuf/internal/input_stream.py deleted file mode 100644 index 26a26dcf..00000000 --- a/froofle/protobuf/internal/input_stream.py +++ /dev/null | |||
@@ -1,326 +0,0 @@ | |||
1 | # Protocol Buffers - Google's data interchange format | ||
2 | # Copyright 2008 Google Inc. All rights reserved. | ||
3 | # http://code.google.com/p/protobuf/ | ||
4 | # | ||
5 | # Redistribution and use in source and binary forms, with or without | ||
6 | # modification, are permitted provided that the following conditions are | ||
7 | # met: | ||
8 | # | ||
9 | # * Redistributions of source code must retain the above copyright | ||
10 | # notice, this list of conditions and the following disclaimer. | ||
11 | # * Redistributions in binary form must reproduce the above | ||
12 | # copyright notice, this list of conditions and the following disclaimer | ||
13 | # in the documentation and/or other materials provided with the | ||
14 | # distribution. | ||
15 | # * Neither the name of Google Inc. nor the names of its | ||
16 | # contributors may be used to endorse or promote products derived from | ||
17 | # this software without specific prior written permission. | ||
18 | # | ||
19 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
20 | # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
21 | # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
22 | # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
23 | # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
24 | # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
25 | # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
26 | # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
27 | # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
28 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
29 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
30 | |||
31 | """InputStream is the primitive interface for reading bits from the wire. | ||
32 | |||
33 | All protocol buffer deserialization can be expressed in terms of | ||
34 | the InputStream primitives provided here. | ||
35 | """ | ||
36 | |||
37 | __author__ = 'robinson@google.com (Will Robinson)' | ||
38 | |||
39 | import struct | ||
40 | from array import array | ||
41 | from froofle.protobuf import message | ||
42 | from froofle.protobuf.internal import wire_format | ||
43 | |||
44 | |||
45 | # Note that much of this code is ported from //net/proto/ProtocolBuffer, and | ||
46 | # that the interface is strongly inspired by CodedInputStream from the C++ | ||
47 | # proto2 implementation. | ||
48 | |||
49 | |||
50 | class InputStreamBuffer(object): | ||
51 | |||
52 | """Contains all logic for reading bits, and dealing with stream position. | ||
53 | |||
54 | If an InputStream method ever raises an exception, the stream is left | ||
55 | in an indeterminate state and is not safe for further use. | ||
56 | """ | ||
57 | |||
58 | def __init__(self, s): | ||
59 | # What we really want is something like array('B', s), where elements we | ||
60 | # read from the array are already given to us as one-byte integers. BUT | ||
61 | # using array() instead of buffer() would force full string copies to result | ||
62 | # from each GetSubBuffer() call. | ||
63 | # | ||
64 | # So, if the N serialized bytes of a single protocol buffer object are | ||
65 | # split evenly between 2 child messages, and so on recursively, using | ||
66 | # array('B', s) instead of buffer() would incur an additional N*logN bytes | ||
67 | # copied during deserialization. | ||
68 | # | ||
69 | # The higher constant overhead of having to ord() for every byte we read | ||
70 | # from the buffer in _ReadVarintHelper() could definitely lead to worse | ||
71 | # performance in many real-world scenarios, even if the asymptotic | ||
72 | # complexity is better. However, our real answer is that the mythical | ||
73 | # Python/C extension module output mode for the protocol compiler will | ||
74 | # be blazing-fast and will eliminate most use of this class anyway. | ||
75 | self._buffer = buffer(s) | ||
76 | self._pos = 0 | ||
77 | |||
78 | def EndOfStream(self): | ||
79 | """Returns true iff we're at the end of the stream. | ||
80 | If this returns true, then a call to any other InputStream method | ||
81 | will raise an exception. | ||
82 | """ | ||
83 | return self._pos >= len(self._buffer) | ||
84 | |||
85 | def Position(self): | ||
86 | """Returns the current position in the stream, or equivalently, the | ||
87 | number of bytes read so far. | ||
88 | """ | ||
89 | return self._pos | ||
90 | |||
91 | def GetSubBuffer(self, size=None): | ||
92 | """Returns a sequence-like object that represents a portion of our | ||
93 | underlying sequence. | ||
94 | |||
95 | Position 0 in the returned object corresponds to self.Position() | ||
96 | in this stream. | ||
97 | |||
98 | If size is specified, then the returned object ends after the | ||
99 | next "size" bytes in this stream. If size is not specified, | ||
100 | then the returned object ends at the end of this stream. | ||
101 | |||
102 | We guarantee that the returned object R supports the Python buffer | ||
103 | interface (and thus that the call buffer(R) will work). | ||
104 | |||
105 | Note that the returned buffer is read-only. | ||
106 | |||
107 | The intended use for this method is for nested-message and nested-group | ||
108 | deserialization, where we want to make a recursive MergeFromString() | ||
109 | call on the portion of the original sequence that contains the serialized | ||
110 | nested message. (And we'd like to do so without making unnecessary string | ||
111 | copies). | ||
112 | |||
113 | REQUIRES: size is nonnegative. | ||
114 | """ | ||
115 | # Note that buffer() doesn't perform any actual string copy. | ||
116 | if size is None: | ||
117 | return buffer(self._buffer, self._pos) | ||
118 | else: | ||
119 | if size < 0: | ||
120 | raise message.DecodeError('Negative size %d' % size) | ||
121 | return buffer(self._buffer, self._pos, size) | ||
122 | |||
123 | def SkipBytes(self, num_bytes): | ||
124 | """Skip num_bytes bytes ahead, or go to the end of the stream, whichever | ||
125 | comes first. | ||
126 | |||
127 | REQUIRES: num_bytes is nonnegative. | ||
128 | """ | ||
129 | if num_bytes < 0: | ||
130 | raise message.DecodeError('Negative num_bytes %d' % num_bytes) | ||
131 | self._pos += num_bytes | ||
132 | self._pos = min(self._pos, len(self._buffer)) | ||
133 | |||
134 | def ReadBytes(self, size): | ||
135 | """Reads up to 'size' bytes from the stream, stopping early | ||
136 | only if we reach the end of the stream. Returns the bytes read | ||
137 | as a string. | ||
138 | """ | ||
139 | if size < 0: | ||
140 | raise message.DecodeError('Negative size %d' % size) | ||
141 | s = (self._buffer[self._pos : self._pos + size]) | ||
142 | self._pos += len(s) # Only advance by the number of bytes actually read. | ||
143 | return s | ||
144 | |||
145 | def ReadLittleEndian32(self): | ||
146 | """Interprets the next 4 bytes of the stream as a little-endian | ||
147 | encoded, unsiged 32-bit integer, and returns that integer. | ||
148 | """ | ||
149 | try: | ||
150 | i = struct.unpack(wire_format.FORMAT_UINT32_LITTLE_ENDIAN, | ||
151 | self._buffer[self._pos : self._pos + 4]) | ||
152 | self._pos += 4 | ||
153 | return i[0] # unpack() result is a 1-element tuple. | ||
154 | except struct.error, e: | ||
155 | raise message.DecodeError(e) | ||
156 | |||
157 | def ReadLittleEndian64(self): | ||
158 | """Interprets the next 8 bytes of the stream as a little-endian | ||
159 | encoded, unsiged 64-bit integer, and returns that integer. | ||
160 | """ | ||
161 | try: | ||
162 | i = struct.unpack(wire_format.FORMAT_UINT64_LITTLE_ENDIAN, | ||
163 | self._buffer[self._pos : self._pos + 8]) | ||
164 | self._pos += 8 | ||
165 | return i[0] # unpack() result is a 1-element tuple. | ||
166 | except struct.error, e: | ||
167 | raise message.DecodeError(e) | ||
168 | |||
169 | def ReadVarint32(self): | ||
170 | """Reads a varint from the stream, interprets this varint | ||
171 | as a signed, 32-bit integer, and returns the integer. | ||
172 | """ | ||
173 | i = self.ReadVarint64() | ||
174 | if not wire_format.INT32_MIN <= i <= wire_format.INT32_MAX: | ||
175 | raise message.DecodeError('Value out of range for int32: %d' % i) | ||
176 | return int(i) | ||
177 | |||
178 | def ReadVarUInt32(self): | ||
179 | """Reads a varint from the stream, interprets this varint | ||
180 | as an unsigned, 32-bit integer, and returns the integer. | ||
181 | """ | ||
182 | i = self.ReadVarUInt64() | ||
183 | if i > wire_format.UINT32_MAX: | ||
184 | raise message.DecodeError('Value out of range for uint32: %d' % i) | ||
185 | return i | ||
186 | |||
187 | def ReadVarint64(self): | ||
188 | """Reads a varint from the stream, interprets this varint | ||
189 | as a signed, 64-bit integer, and returns the integer. | ||
190 | """ | ||
191 | i = self.ReadVarUInt64() | ||
192 | if i > wire_format.INT64_MAX: | ||
193 | i -= (1 << 64) | ||
194 | return i | ||
195 | |||
196 | def ReadVarUInt64(self): | ||
197 | """Reads a varint from the stream, interprets this varint | ||
198 | as an unsigned, 64-bit integer, and returns the integer. | ||
199 | """ | ||
200 | i = self._ReadVarintHelper() | ||
201 | if not 0 <= i <= wire_format.UINT64_MAX: | ||
202 | raise message.DecodeError('Value out of range for uint64: %d' % i) | ||
203 | return i | ||
204 | |||
205 | def _ReadVarintHelper(self): | ||
206 | """Helper for the various varint-reading methods above. | ||
207 | Reads an unsigned, varint-encoded integer from the stream and | ||
208 | returns this integer. | ||
209 | |||
210 | Does no bounds checking except to ensure that we read at most as many bytes | ||
211 | as could possibly be present in a varint-encoded 64-bit number. | ||
212 | """ | ||
213 | result = 0 | ||
214 | shift = 0 | ||
215 | while 1: | ||
216 | if shift >= 64: | ||
217 | raise message.DecodeError('Too many bytes when decoding varint.') | ||
218 | try: | ||
219 | b = ord(self._buffer[self._pos]) | ||
220 | except IndexError: | ||
221 | raise message.DecodeError('Truncated varint.') | ||
222 | self._pos += 1 | ||
223 | result |= ((b & 0x7f) << shift) | ||
224 | shift += 7 | ||
225 | if not (b & 0x80): | ||
226 | return result | ||
227 | |||
228 | class InputStreamArray(object): | ||
229 | def __init__(self, s): | ||
230 | self._buffer = array('B', s) | ||
231 | self._pos = 0 | ||
232 | |||
233 | def EndOfStream(self): | ||
234 | return self._pos >= len(self._buffer) | ||
235 | |||
236 | def Position(self): | ||
237 | return self._pos | ||
238 | |||
239 | def GetSubBuffer(self, size=None): | ||
240 | if size is None: | ||
241 | return self._buffer[self._pos : ].tostring() | ||
242 | else: | ||
243 | if size < 0: | ||
244 | raise message.DecodeError('Negative size %d' % size) | ||
245 | return self._buffer[self._pos : self._pos + size].tostring() | ||
246 | |||
247 | def SkipBytes(self, num_bytes): | ||
248 | if num_bytes < 0: | ||
249 | raise message.DecodeError('Negative num_bytes %d' % num_bytes) | ||
250 | self._pos += num_bytes | ||
251 | self._pos = min(self._pos, len(self._buffer)) | ||
252 | |||
253 | def ReadBytes(self, size): | ||
254 | if size < 0: | ||
255 | raise message.DecodeError('Negative size %d' % size) | ||
256 | s = self._buffer[self._pos : self._pos + size].tostring() | ||
257 | self._pos += len(s) # Only advance by the number of bytes actually read. | ||
258 | return s | ||
259 | |||
260 | def ReadLittleEndian32(self): | ||
261 | try: | ||
262 | i = struct.unpack(wire_format.FORMAT_UINT32_LITTLE_ENDIAN, | ||
263 | self._buffer[self._pos : self._pos + 4]) | ||
264 | self._pos += 4 | ||
265 | return i[0] # unpack() result is a 1-element tuple. | ||
266 | except struct.error, e: | ||
267 | raise message.DecodeError(e) | ||
268 | |||
269 | def ReadLittleEndian64(self): | ||
270 | try: | ||
271 | i = struct.unpack(wire_format.FORMAT_UINT64_LITTLE_ENDIAN, | ||
272 | self._buffer[self._pos : self._pos + 8]) | ||
273 | self._pos += 8 | ||
274 | return i[0] # unpack() result is a 1-element tuple. | ||
275 | except struct.error, e: | ||
276 | raise message.DecodeError(e) | ||
277 | |||
278 | def ReadVarint32(self): | ||
279 | i = self.ReadVarint64() | ||
280 | if not wire_format.INT32_MIN <= i <= wire_format.INT32_MAX: | ||
281 | raise message.DecodeError('Value out of range for int32: %d' % i) | ||
282 | return int(i) | ||
283 | |||
284 | def ReadVarUInt32(self): | ||
285 | i = self.ReadVarUInt64() | ||
286 | if i > wire_format.UINT32_MAX: | ||
287 | raise message.DecodeError('Value out of range for uint32: %d' % i) | ||
288 | return i | ||
289 | |||
290 | def ReadVarint64(self): | ||
291 | i = self.ReadVarUInt64() | ||
292 | if i > wire_format.INT64_MAX: | ||
293 | i -= (1 << 64) | ||
294 | return i | ||
295 | |||
296 | def ReadVarUInt64(self): | ||
297 | i = self._ReadVarintHelper() | ||
298 | if not 0 <= i <= wire_format.UINT64_MAX: | ||
299 | raise message.DecodeError('Value out of range for uint64: %d' % i) | ||
300 | return i | ||
301 | |||
302 | def _ReadVarintHelper(self): | ||
303 | result = 0 | ||
304 | shift = 0 | ||
305 | while 1: | ||
306 | if shift >= 64: | ||
307 | raise message.DecodeError('Too many bytes when decoding varint.') | ||
308 | try: | ||
309 | b = self._buffer[self._pos] | ||
310 | except IndexError: | ||
311 | raise message.DecodeError('Truncated varint.') | ||
312 | self._pos += 1 | ||
313 | result |= ((b & 0x7f) << shift) | ||
314 | shift += 7 | ||
315 | if not (b & 0x80): | ||
316 | return result | ||
317 | |||
318 | try: | ||
319 | buffer("") | ||
320 | InputStream = InputStreamBuffer | ||
321 | except NotImplementedError: | ||
322 | # Google App Engine: dev_appserver.py | ||
323 | InputStream = InputStreamArray | ||
324 | except RuntimeError: | ||
325 | # Google App Engine: production | ||
326 | InputStream = InputStreamArray | ||
diff --git a/froofle/protobuf/internal/message_listener.py b/froofle/protobuf/internal/message_listener.py deleted file mode 100644 index 43978952..00000000 --- a/froofle/protobuf/internal/message_listener.py +++ /dev/null | |||
@@ -1,69 +0,0 @@ | |||
1 | # Protocol Buffers - Google's data interchange format | ||
2 | # Copyright 2008 Google Inc. All rights reserved. | ||
3 | # http://code.google.com/p/protobuf/ | ||
4 | # | ||
5 | # Redistribution and use in source and binary forms, with or without | ||
6 | # modification, are permitted provided that the following conditions are | ||
7 | # met: | ||
8 | # | ||
9 | # * Redistributions of source code must retain the above copyright | ||
10 | # notice, this list of conditions and the following disclaimer. | ||
11 | # * Redistributions in binary form must reproduce the above | ||
12 | # copyright notice, this list of conditions and the following disclaimer | ||
13 | # in the documentation and/or other materials provided with the | ||
14 | # distribution. | ||
15 | # * Neither the name of Google Inc. nor the names of its | ||
16 | # contributors may be used to endorse or promote products derived from | ||
17 | # this software without specific prior written permission. | ||
18 | # | ||
19 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
20 | # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
21 | # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
22 | # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
23 | # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
24 | # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
25 | # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
26 | # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
27 | # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
28 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
29 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
30 | |||
31 | """Defines a listener interface for observing certain | ||
32 | state transitions on Message objects. | ||
33 | |||
34 | Also defines a null implementation of this interface. | ||
35 | """ | ||
36 | |||
37 | __author__ = 'robinson@google.com (Will Robinson)' | ||
38 | |||
39 | |||
40 | class MessageListener(object): | ||
41 | |||
42 | """Listens for transitions to nonempty and for invalidations of cached | ||
43 | byte sizes. Meant to be registered via Message._SetListener(). | ||
44 | """ | ||
45 | |||
46 | def TransitionToNonempty(self): | ||
47 | """Called the *first* time that this message becomes nonempty. | ||
48 | Implementations are free (but not required) to call this method multiple | ||
49 | times after the message has become nonempty. | ||
50 | """ | ||
51 | raise NotImplementedError | ||
52 | |||
53 | def ByteSizeDirty(self): | ||
54 | """Called *every* time the cached byte size value | ||
55 | for this object is invalidated (transitions from being | ||
56 | "clean" to "dirty"). | ||
57 | """ | ||
58 | raise NotImplementedError | ||
59 | |||
60 | |||
61 | class NullMessageListener(object): | ||
62 | |||
63 | """No-op MessageListener implementation.""" | ||
64 | |||
65 | def TransitionToNonempty(self): | ||
66 | pass | ||
67 | |||
68 | def ByteSizeDirty(self): | ||
69 | pass | ||
diff --git a/froofle/protobuf/internal/output_stream.py b/froofle/protobuf/internal/output_stream.py deleted file mode 100644 index f62cd1c4..00000000 --- a/froofle/protobuf/internal/output_stream.py +++ /dev/null | |||
@@ -1,125 +0,0 @@ | |||
1 | # Protocol Buffers - Google's data interchange format | ||
2 | # Copyright 2008 Google Inc. All rights reserved. | ||
3 | # http://code.google.com/p/protobuf/ | ||
4 | # | ||
5 | # Redistribution and use in source and binary forms, with or without | ||
6 | # modification, are permitted provided that the following conditions are | ||
7 | # met: | ||
8 | # | ||
9 | # * Redistributions of source code must retain the above copyright | ||
10 | # notice, this list of conditions and the following disclaimer. | ||
11 | # * Redistributions in binary form must reproduce the above | ||
12 | # copyright notice, this list of conditions and the following disclaimer | ||
13 | # in the documentation and/or other materials provided with the | ||
14 | # distribution. | ||
15 | # * Neither the name of Google Inc. nor the names of its | ||
16 | # contributors may be used to endorse or promote products derived from | ||
17 | # this software without specific prior written permission. | ||
18 | # | ||
19 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
20 | # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
21 | # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
22 | # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
23 | # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
24 | # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
25 | # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
26 | # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
27 | # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
28 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
29 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
30 | |||
31 | """OutputStream is the primitive interface for sticking bits on the wire. | ||
32 | |||
33 | All protocol buffer serialization can be expressed in terms of | ||
34 | the OutputStream primitives provided here. | ||
35 | """ | ||
36 | |||
37 | __author__ = 'robinson@google.com (Will Robinson)' | ||
38 | |||
39 | import array | ||
40 | import struct | ||
41 | from froofle.protobuf import message | ||
42 | from froofle.protobuf.internal import wire_format | ||
43 | |||
44 | |||
45 | |||
46 | # Note that much of this code is ported from //net/proto/ProtocolBuffer, and | ||
47 | # that the interface is strongly inspired by CodedOutputStream from the C++ | ||
48 | # proto2 implementation. | ||
49 | |||
50 | |||
51 | class OutputStream(object): | ||
52 | |||
53 | """Contains all logic for writing bits, and ToString() to get the result.""" | ||
54 | |||
55 | def __init__(self): | ||
56 | self._buffer = array.array('B') | ||
57 | |||
58 | def AppendRawBytes(self, raw_bytes): | ||
59 | """Appends raw_bytes to our internal buffer.""" | ||
60 | self._buffer.fromstring(raw_bytes) | ||
61 | |||
62 | def AppendLittleEndian32(self, unsigned_value): | ||
63 | """Appends an unsigned 32-bit integer to the internal buffer, | ||
64 | in little-endian byte order. | ||
65 | """ | ||
66 | if not 0 <= unsigned_value <= wire_format.UINT32_MAX: | ||
67 | raise message.EncodeError( | ||
68 | 'Unsigned 32-bit out of range: %d' % unsigned_value) | ||
69 | self._buffer.fromstring(struct.pack( | ||
70 | wire_format.FORMAT_UINT32_LITTLE_ENDIAN, unsigned_value)) | ||
71 | |||
72 | def AppendLittleEndian64(self, unsigned_value): | ||
73 | """Appends an unsigned 64-bit integer to the internal buffer, | ||
74 | in little-endian byte order. | ||
75 | """ | ||
76 | if not 0 <= unsigned_value <= wire_format.UINT64_MAX: | ||
77 | raise message.EncodeError( | ||
78 | 'Unsigned 64-bit out of range: %d' % unsigned_value) | ||
79 | self._buffer.fromstring(struct.pack( | ||
80 | wire_format.FORMAT_UINT64_LITTLE_ENDIAN, unsigned_value)) | ||
81 | |||
82 | def AppendVarint32(self, value): | ||
83 | """Appends a signed 32-bit integer to the internal buffer, | ||
84 | encoded as a varint. (Note that a negative varint32 will | ||
85 | always require 10 bytes of space.) | ||
86 | """ | ||
87 | if not wire_format.INT32_MIN <= value <= wire_format.INT32_MAX: | ||
88 | raise message.EncodeError('Value out of range: %d' % value) | ||
89 | self.AppendVarint64(value) | ||
90 | |||
91 | def AppendVarUInt32(self, value): | ||
92 | """Appends an unsigned 32-bit integer to the internal buffer, | ||
93 | encoded as a varint. | ||
94 | """ | ||
95 | if not 0 <= value <= wire_format.UINT32_MAX: | ||
96 | raise message.EncodeError('Value out of range: %d' % value) | ||
97 | self.AppendVarUInt64(value) | ||
98 | |||
99 | def AppendVarint64(self, value): | ||
100 | """Appends a signed 64-bit integer to the internal buffer, | ||
101 | encoded as a varint. | ||
102 | """ | ||
103 | if not wire_format.INT64_MIN <= value <= wire_format.INT64_MAX: | ||
104 | raise message.EncodeError('Value out of range: %d' % value) | ||
105 | if value < 0: | ||
106 | value += (1 << 64) | ||
107 | self.AppendVarUInt64(value) | ||
108 | |||
109 | def AppendVarUInt64(self, unsigned_value): | ||
110 | """Appends an unsigned 64-bit integer to the internal buffer, | ||
111 | encoded as a varint. | ||
112 | """ | ||
113 | if not 0 <= unsigned_value <= wire_format.UINT64_MAX: | ||
114 | raise message.EncodeError('Value out of range: %d' % unsigned_value) | ||
115 | while True: | ||
116 | bits = unsigned_value & 0x7f | ||
117 | unsigned_value >>= 7 | ||
118 | if not unsigned_value: | ||
119 | self._buffer.append(bits) | ||
120 | break | ||
121 | self._buffer.append(0x80|bits) | ||
122 | |||
123 | def ToString(self): | ||
124 | """Returns a string containing the bytes in our internal buffer.""" | ||
125 | return self._buffer.tostring() | ||
diff --git a/froofle/protobuf/internal/type_checkers.py b/froofle/protobuf/internal/type_checkers.py deleted file mode 100644 index aaf7a844..00000000 --- a/froofle/protobuf/internal/type_checkers.py +++ /dev/null | |||
@@ -1,268 +0,0 @@ | |||
1 | # Protocol Buffers - Google's data interchange format | ||
2 | # Copyright 2008 Google Inc. All rights reserved. | ||
3 | # http://code.google.com/p/protobuf/ | ||
4 | # | ||
5 | # Redistribution and use in source and binary forms, with or without | ||
6 | # modification, are permitted provided that the following conditions are | ||
7 | # met: | ||
8 | # | ||
9 | # * Redistributions of source code must retain the above copyright | ||
10 | # notice, this list of conditions and the following disclaimer. | ||
11 | # * Redistributions in binary form must reproduce the above | ||
12 | # copyright notice, this list of conditions and the following disclaimer | ||
13 | # in the documentation and/or other materials provided with the | ||
14 | # distribution. | ||
15 | # * Neither the name of Google Inc. nor the names of its | ||
16 | # contributors may be used to endorse or promote products derived from | ||
17 | # this software without specific prior written permission. | ||
18 | # | ||
19 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
20 | # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
21 | # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
22 | # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
23 | # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
24 | # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
25 | # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
26 | # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
27 | # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
28 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
29 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
30 | |||
31 | """Provides type checking routines. | ||
32 | |||
33 | This module defines type checking utilities in the forms of dictionaries: | ||
34 | |||
35 | VALUE_CHECKERS: A dictionary of field types and a value validation object. | ||
36 | TYPE_TO_BYTE_SIZE_FN: A dictionary with field types and a size computing | ||
37 | function. | ||
38 | TYPE_TO_SERIALIZE_METHOD: A dictionary with field types and serialization | ||
39 | function. | ||
40 | FIELD_TYPE_TO_WIRE_TYPE: A dictionary with field typed and their | ||
41 | coresponding wire types. | ||
42 | TYPE_TO_DESERIALIZE_METHOD: A dictionary with field types and deserialization | ||
43 | function. | ||
44 | """ | ||
45 | |||
46 | __author__ = 'robinson@google.com (Will Robinson)' | ||
47 | |||
48 | from froofle.protobuf.internal import decoder | ||
49 | from froofle.protobuf.internal import encoder | ||
50 | from froofle.protobuf.internal import wire_format | ||
51 | from froofle.protobuf import descriptor | ||
52 | |||
53 | _FieldDescriptor = descriptor.FieldDescriptor | ||
54 | |||
55 | |||
56 | def GetTypeChecker(cpp_type, field_type): | ||
57 | """Returns a type checker for a message field of the specified types. | ||
58 | |||
59 | Args: | ||
60 | cpp_type: C++ type of the field (see descriptor.py). | ||
61 | field_type: Protocol message field type (see descriptor.py). | ||
62 | |||
63 | Returns: | ||
64 | An instance of TypeChecker which can be used to verify the types | ||
65 | of values assigned to a field of the specified type. | ||
66 | """ | ||
67 | if (cpp_type == _FieldDescriptor.CPPTYPE_STRING and | ||
68 | field_type == _FieldDescriptor.TYPE_STRING): | ||
69 | return UnicodeValueChecker() | ||
70 | return _VALUE_CHECKERS[cpp_type] | ||
71 | |||
72 | |||
73 | # None of the typecheckers below make any attempt to guard against people | ||
74 | # subclassing builtin types and doing weird things. We're not trying to | ||
75 | # protect against malicious clients here, just people accidentally shooting | ||
76 | # themselves in the foot in obvious ways. | ||
77 | |||
78 | class TypeChecker(object): | ||
79 | |||
80 | """Type checker used to catch type errors as early as possible | ||
81 | when the client is setting scalar fields in protocol messages. | ||
82 | """ | ||
83 | |||
84 | def __init__(self, *acceptable_types): | ||
85 | self._acceptable_types = acceptable_types | ||
86 | |||
87 | def CheckValue(self, proposed_value): | ||
88 | if not isinstance(proposed_value, self._acceptable_types): | ||
89 | message = ('%.1024r has type %s, but expected one of: %s' % | ||
90 | (proposed_value, type(proposed_value), self._acceptable_types)) | ||
91 | raise TypeError(message) | ||
92 | |||
93 | |||
94 | # IntValueChecker and its subclasses perform integer type-checks | ||
95 | # and bounds-checks. | ||
96 | class IntValueChecker(object): | ||
97 | |||
98 | """Checker used for integer fields. Performs type-check and range check.""" | ||
99 | |||
100 | def CheckValue(self, proposed_value): | ||
101 | if not isinstance(proposed_value, (int, long)): | ||
102 | message = ('%.1024r has type %s, but expected one of: %s' % | ||
103 | (proposed_value, type(proposed_value), (int, long))) | ||
104 | raise TypeError(message) | ||
105 | if not self._MIN <= proposed_value <= self._MAX: | ||
106 | raise ValueError('Value out of range: %d' % proposed_value) | ||
107 | |||
108 | |||
109 | class UnicodeValueChecker(object): | ||
110 | |||
111 | """Checker used for string fields.""" | ||
112 | |||
113 | def CheckValue(self, proposed_value): | ||
114 | if not isinstance(proposed_value, (str, unicode)): | ||
115 | message = ('%.1024r has type %s, but expected one of: %s' % | ||
116 | (proposed_value, type(proposed_value), (str, unicode))) | ||
117 | raise TypeError(message) | ||
118 | |||
119 | # If the value is of type 'str' make sure that it is in 7-bit ASCII | ||
120 | # encoding. | ||
121 | if isinstance(proposed_value, str): | ||
122 | try: | ||
123 | unicode(proposed_value, 'ascii') | ||
124 | except UnicodeDecodeError: | ||
125 | raise ValueError('%.1024r isn\'t in 7-bit ASCII encoding.' | ||
126 | % (proposed_value)) | ||
127 | |||
128 | |||
129 | class Int32ValueChecker(IntValueChecker): | ||
130 | # We're sure to use ints instead of longs here since comparison may be more | ||
131 | # efficient. | ||
132 | _MIN = -2147483648 | ||
133 | _MAX = 2147483647 | ||
134 | |||
135 | |||
136 | class Uint32ValueChecker(IntValueChecker): | ||
137 | _MIN = 0 | ||
138 | _MAX = (1 << 32) - 1 | ||
139 | |||
140 | |||
141 | class Int64ValueChecker(IntValueChecker): | ||
142 | _MIN = -(1 << 63) | ||
143 | _MAX = (1 << 63) - 1 | ||
144 | |||
145 | |||
146 | class Uint64ValueChecker(IntValueChecker): | ||
147 | _MIN = 0 | ||
148 | _MAX = (1 << 64) - 1 | ||
149 | |||
150 | |||
151 | # Type-checkers for all scalar CPPTYPEs. | ||
152 | _VALUE_CHECKERS = { | ||
153 | _FieldDescriptor.CPPTYPE_INT32: Int32ValueChecker(), | ||
154 | _FieldDescriptor.CPPTYPE_INT64: Int64ValueChecker(), | ||
155 | _FieldDescriptor.CPPTYPE_UINT32: Uint32ValueChecker(), | ||
156 | _FieldDescriptor.CPPTYPE_UINT64: Uint64ValueChecker(), | ||
157 | _FieldDescriptor.CPPTYPE_DOUBLE: TypeChecker( | ||
158 | float, int, long), | ||
159 | _FieldDescriptor.CPPTYPE_FLOAT: TypeChecker( | ||
160 | float, int, long), | ||
161 | _FieldDescriptor.CPPTYPE_BOOL: TypeChecker(bool, int), | ||
162 | _FieldDescriptor.CPPTYPE_ENUM: Int32ValueChecker(), | ||
163 | _FieldDescriptor.CPPTYPE_STRING: TypeChecker(str), | ||
164 | } | ||
165 | |||
166 | |||
167 | # Map from field type to a function F, such that F(field_num, value) | ||
168 | # gives the total byte size for a value of the given type. This | ||
169 | # byte size includes tag information and any other additional space | ||
170 | # associated with serializing "value". | ||
171 | TYPE_TO_BYTE_SIZE_FN = { | ||
172 | _FieldDescriptor.TYPE_DOUBLE: wire_format.DoubleByteSize, | ||
173 | _FieldDescriptor.TYPE_FLOAT: wire_format.FloatByteSize, | ||
174 | _FieldDescriptor.TYPE_INT64: wire_format.Int64ByteSize, | ||
175 | _FieldDescriptor.TYPE_UINT64: wire_format.UInt64ByteSize, | ||
176 | _FieldDescriptor.TYPE_INT32: wire_format.Int32ByteSize, | ||
177 | _FieldDescriptor.TYPE_FIXED64: wire_format.Fixed64ByteSize, | ||
178 | _FieldDescriptor.TYPE_FIXED32: wire_format.Fixed32ByteSize, | ||
179 | _FieldDescriptor.TYPE_BOOL: wire_format.BoolByteSize, | ||
180 | _FieldDescriptor.TYPE_STRING: wire_format.StringByteSize, | ||
181 | _FieldDescriptor.TYPE_GROUP: wire_format.GroupByteSize, | ||
182 | _FieldDescriptor.TYPE_MESSAGE: wire_format.MessageByteSize, | ||
183 | _FieldDescriptor.TYPE_BYTES: wire_format.BytesByteSize, | ||
184 | _FieldDescriptor.TYPE_UINT32: wire_format.UInt32ByteSize, | ||
185 | _FieldDescriptor.TYPE_ENUM: wire_format.EnumByteSize, | ||
186 | _FieldDescriptor.TYPE_SFIXED32: wire_format.SFixed32ByteSize, | ||
187 | _FieldDescriptor.TYPE_SFIXED64: wire_format.SFixed64ByteSize, | ||
188 | _FieldDescriptor.TYPE_SINT32: wire_format.SInt32ByteSize, | ||
189 | _FieldDescriptor.TYPE_SINT64: wire_format.SInt64ByteSize | ||
190 | } | ||
191 | |||
192 | |||
193 | # Maps from field type to an unbound Encoder method F, such that | ||
194 | # F(encoder, field_number, value) will append the serialization | ||
195 | # of a value of this type to the encoder. | ||
196 | _Encoder = encoder.Encoder | ||
197 | TYPE_TO_SERIALIZE_METHOD = { | ||
198 | _FieldDescriptor.TYPE_DOUBLE: _Encoder.AppendDouble, | ||
199 | _FieldDescriptor.TYPE_FLOAT: _Encoder.AppendFloat, | ||
200 | _FieldDescriptor.TYPE_INT64: _Encoder.AppendInt64, | ||
201 | _FieldDescriptor.TYPE_UINT64: _Encoder.AppendUInt64, | ||
202 | _FieldDescriptor.TYPE_INT32: _Encoder.AppendInt32, | ||
203 | _FieldDescriptor.TYPE_FIXED64: _Encoder.AppendFixed64, | ||
204 | _FieldDescriptor.TYPE_FIXED32: _Encoder.AppendFixed32, | ||
205 | _FieldDescriptor.TYPE_BOOL: _Encoder.AppendBool, | ||
206 | _FieldDescriptor.TYPE_STRING: _Encoder.AppendString, | ||
207 | _FieldDescriptor.TYPE_GROUP: _Encoder.AppendGroup, | ||
208 | _FieldDescriptor.TYPE_MESSAGE: _Encoder.AppendMessage, | ||
209 | _FieldDescriptor.TYPE_BYTES: _Encoder.AppendBytes, | ||
210 | _FieldDescriptor.TYPE_UINT32: _Encoder.AppendUInt32, | ||
211 | _FieldDescriptor.TYPE_ENUM: _Encoder.AppendEnum, | ||
212 | _FieldDescriptor.TYPE_SFIXED32: _Encoder.AppendSFixed32, | ||
213 | _FieldDescriptor.TYPE_SFIXED64: _Encoder.AppendSFixed64, | ||
214 | _FieldDescriptor.TYPE_SINT32: _Encoder.AppendSInt32, | ||
215 | _FieldDescriptor.TYPE_SINT64: _Encoder.AppendSInt64, | ||
216 | } | ||
217 | |||
218 | |||
219 | # Maps from field type to expected wiretype. | ||
220 | FIELD_TYPE_TO_WIRE_TYPE = { | ||
221 | _FieldDescriptor.TYPE_DOUBLE: wire_format.WIRETYPE_FIXED64, | ||
222 | _FieldDescriptor.TYPE_FLOAT: wire_format.WIRETYPE_FIXED32, | ||
223 | _FieldDescriptor.TYPE_INT64: wire_format.WIRETYPE_VARINT, | ||
224 | _FieldDescriptor.TYPE_UINT64: wire_format.WIRETYPE_VARINT, | ||
225 | _FieldDescriptor.TYPE_INT32: wire_format.WIRETYPE_VARINT, | ||
226 | _FieldDescriptor.TYPE_FIXED64: wire_format.WIRETYPE_FIXED64, | ||
227 | _FieldDescriptor.TYPE_FIXED32: wire_format.WIRETYPE_FIXED32, | ||
228 | _FieldDescriptor.TYPE_BOOL: wire_format.WIRETYPE_VARINT, | ||
229 | _FieldDescriptor.TYPE_STRING: | ||
230 | wire_format.WIRETYPE_LENGTH_DELIMITED, | ||
231 | _FieldDescriptor.TYPE_GROUP: wire_format.WIRETYPE_START_GROUP, | ||
232 | _FieldDescriptor.TYPE_MESSAGE: | ||
233 | wire_format.WIRETYPE_LENGTH_DELIMITED, | ||
234 | _FieldDescriptor.TYPE_BYTES: | ||
235 | wire_format.WIRETYPE_LENGTH_DELIMITED, | ||
236 | _FieldDescriptor.TYPE_UINT32: wire_format.WIRETYPE_VARINT, | ||
237 | _FieldDescriptor.TYPE_ENUM: wire_format.WIRETYPE_VARINT, | ||
238 | _FieldDescriptor.TYPE_SFIXED32: wire_format.WIRETYPE_FIXED32, | ||
239 | _FieldDescriptor.TYPE_SFIXED64: wire_format.WIRETYPE_FIXED64, | ||
240 | _FieldDescriptor.TYPE_SINT32: wire_format.WIRETYPE_VARINT, | ||
241 | _FieldDescriptor.TYPE_SINT64: wire_format.WIRETYPE_VARINT, | ||
242 | } | ||
243 | |||
244 | |||
245 | # Maps from field type to an unbound Decoder method F, | ||
246 | # such that F(decoder) will read a field of the requested type. | ||
247 | # | ||
248 | # Note that Message and Group are intentionally missing here. | ||
249 | # They're handled by _RecursivelyMerge(). | ||
250 | _Decoder = decoder.Decoder | ||
251 | TYPE_TO_DESERIALIZE_METHOD = { | ||
252 | _FieldDescriptor.TYPE_DOUBLE: _Decoder.ReadDouble, | ||
253 | _FieldDescriptor.TYPE_FLOAT: _Decoder.ReadFloat, | ||
254 | _FieldDescriptor.TYPE_INT64: _Decoder.ReadInt64, | ||
255 | _FieldDescriptor.TYPE_UINT64: _Decoder.ReadUInt64, | ||
256 | _FieldDescriptor.TYPE_INT32: _Decoder.ReadInt32, | ||
257 | _FieldDescriptor.TYPE_FIXED64: _Decoder.ReadFixed64, | ||
258 | _FieldDescriptor.TYPE_FIXED32: _Decoder.ReadFixed32, | ||
259 | _FieldDescriptor.TYPE_BOOL: _Decoder.ReadBool, | ||
260 | _FieldDescriptor.TYPE_STRING: _Decoder.ReadString, | ||
261 | _FieldDescriptor.TYPE_BYTES: _Decoder.ReadBytes, | ||
262 | _FieldDescriptor.TYPE_UINT32: _Decoder.ReadUInt32, | ||
263 | _FieldDescriptor.TYPE_ENUM: _Decoder.ReadEnum, | ||
264 | _FieldDescriptor.TYPE_SFIXED32: _Decoder.ReadSFixed32, | ||
265 | _FieldDescriptor.TYPE_SFIXED64: _Decoder.ReadSFixed64, | ||
266 | _FieldDescriptor.TYPE_SINT32: _Decoder.ReadSInt32, | ||
267 | _FieldDescriptor.TYPE_SINT64: _Decoder.ReadSInt64, | ||
268 | } | ||
diff --git a/froofle/protobuf/internal/wire_format.py b/froofle/protobuf/internal/wire_format.py deleted file mode 100644 index 4d823c8d..00000000 --- a/froofle/protobuf/internal/wire_format.py +++ /dev/null | |||
@@ -1,236 +0,0 @@ | |||
1 | # Protocol Buffers - Google's data interchange format | ||
2 | # Copyright 2008 Google Inc. All rights reserved. | ||
3 | # http://code.google.com/p/protobuf/ | ||
4 | # | ||
5 | # Redistribution and use in source and binary forms, with or without | ||
6 | # modification, are permitted provided that the following conditions are | ||
7 | # met: | ||
8 | # | ||
9 | # * Redistributions of source code must retain the above copyright | ||
10 | # notice, this list of conditions and the following disclaimer. | ||
11 | # * Redistributions in binary form must reproduce the above | ||
12 | # copyright notice, this list of conditions and the following disclaimer | ||
13 | # in the documentation and/or other materials provided with the | ||
14 | # distribution. | ||
15 | # * Neither the name of Google Inc. nor the names of its | ||
16 | # contributors may be used to endorse or promote products derived from | ||
17 | # this software without specific prior written permission. | ||
18 | # | ||
19 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
20 | # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
21 | # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
22 | # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
23 | # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
24 | # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
25 | # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
26 | # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
27 | # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
28 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
29 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
30 | |||
31 | """Constants and static functions to support protocol buffer wire format.""" | ||
32 | |||
33 | __author__ = 'robinson@google.com (Will Robinson)' | ||
34 | |||
35 | import struct | ||
36 | from froofle.protobuf import message | ||
37 | |||
38 | |||
39 | TAG_TYPE_BITS = 3 # Number of bits used to hold type info in a proto tag. | ||
40 | _TAG_TYPE_MASK = (1 << TAG_TYPE_BITS) - 1 # 0x7 | ||
41 | |||
42 | # These numbers identify the wire type of a protocol buffer value. | ||
43 | # We use the least-significant TAG_TYPE_BITS bits of the varint-encoded | ||
44 | # tag-and-type to store one of these WIRETYPE_* constants. | ||
45 | # These values must match WireType enum in //net/proto2/public/wire_format.h. | ||
46 | WIRETYPE_VARINT = 0 | ||
47 | WIRETYPE_FIXED64 = 1 | ||
48 | WIRETYPE_LENGTH_DELIMITED = 2 | ||
49 | WIRETYPE_START_GROUP = 3 | ||
50 | WIRETYPE_END_GROUP = 4 | ||
51 | WIRETYPE_FIXED32 = 5 | ||
52 | _WIRETYPE_MAX = 5 | ||
53 | |||
54 | |||
55 | # Bounds for various integer types. | ||
56 | INT32_MAX = int((1 << 31) - 1) | ||
57 | INT32_MIN = int(-(1 << 31)) | ||
58 | UINT32_MAX = (1 << 32) - 1 | ||
59 | |||
60 | INT64_MAX = (1 << 63) - 1 | ||
61 | INT64_MIN = -(1 << 63) | ||
62 | UINT64_MAX = (1 << 64) - 1 | ||
63 | |||
64 | # "struct" format strings that will encode/decode the specified formats. | ||
65 | FORMAT_UINT32_LITTLE_ENDIAN = '<I' | ||
66 | FORMAT_UINT64_LITTLE_ENDIAN = '<Q' | ||
67 | |||
68 | |||
69 | # We'll have to provide alternate implementations of AppendLittleEndian*() on | ||
70 | # any architectures where these checks fail. | ||
71 | if struct.calcsize(FORMAT_UINT32_LITTLE_ENDIAN) != 4: | ||
72 | raise AssertionError('Format "I" is not a 32-bit number.') | ||
73 | if struct.calcsize(FORMAT_UINT64_LITTLE_ENDIAN) != 8: | ||
74 | raise AssertionError('Format "Q" is not a 64-bit number.') | ||
75 | |||
76 | |||
77 | def PackTag(field_number, wire_type): | ||
78 | """Returns an unsigned 32-bit integer that encodes the field number and | ||
79 | wire type information in standard protocol message wire format. | ||
80 | |||
81 | Args: | ||
82 | field_number: Expected to be an integer in the range [1, 1 << 29) | ||
83 | wire_type: One of the WIRETYPE_* constants. | ||
84 | """ | ||
85 | if not 0 <= wire_type <= _WIRETYPE_MAX: | ||
86 | raise message.EncodeError('Unknown wire type: %d' % wire_type) | ||
87 | return (field_number << TAG_TYPE_BITS) | wire_type | ||
88 | |||
89 | |||
90 | def UnpackTag(tag): | ||
91 | """The inverse of PackTag(). Given an unsigned 32-bit number, | ||
92 | returns a (field_number, wire_type) tuple. | ||
93 | """ | ||
94 | return (tag >> TAG_TYPE_BITS), (tag & _TAG_TYPE_MASK) | ||
95 | |||
96 | |||
97 | def ZigZagEncode(value): | ||
98 | """ZigZag Transform: Encodes signed integers so that they can be | ||
99 | effectively used with varint encoding. See wire_format.h for | ||
100 | more details. | ||
101 | """ | ||
102 | if value >= 0: | ||
103 | return value << 1 | ||
104 | return (value << 1) ^ (~0) | ||
105 | |||
106 | |||
107 | def ZigZagDecode(value): | ||
108 | """Inverse of ZigZagEncode().""" | ||
109 | if not value & 0x1: | ||
110 | return value >> 1 | ||
111 | return (value >> 1) ^ (~0) | ||
112 | |||
113 | |||
114 | |||
115 | # The *ByteSize() functions below return the number of bytes required to | ||
116 | # serialize "field number + type" information and then serialize the value. | ||
117 | |||
118 | |||
119 | def Int32ByteSize(field_number, int32): | ||
120 | return Int64ByteSize(field_number, int32) | ||
121 | |||
122 | |||
123 | def Int64ByteSize(field_number, int64): | ||
124 | # Have to convert to uint before calling UInt64ByteSize(). | ||
125 | return UInt64ByteSize(field_number, 0xffffffffffffffff & int64) | ||
126 | |||
127 | |||
128 | def UInt32ByteSize(field_number, uint32): | ||
129 | return UInt64ByteSize(field_number, uint32) | ||
130 | |||
131 | |||
132 | def UInt64ByteSize(field_number, uint64): | ||
133 | return _TagByteSize(field_number) + _VarUInt64ByteSizeNoTag(uint64) | ||
134 | |||
135 | |||
136 | def SInt32ByteSize(field_number, int32): | ||
137 | return UInt32ByteSize(field_number, ZigZagEncode(int32)) | ||
138 | |||
139 | |||
140 | def SInt64ByteSize(field_number, int64): | ||
141 | return UInt64ByteSize(field_number, ZigZagEncode(int64)) | ||
142 | |||
143 | |||
144 | def Fixed32ByteSize(field_number, fixed32): | ||
145 | return _TagByteSize(field_number) + 4 | ||
146 | |||
147 | |||
148 | def Fixed64ByteSize(field_number, fixed64): | ||
149 | return _TagByteSize(field_number) + 8 | ||
150 | |||
151 | |||
152 | def SFixed32ByteSize(field_number, sfixed32): | ||
153 | return _TagByteSize(field_number) + 4 | ||
154 | |||
155 | |||
156 | def SFixed64ByteSize(field_number, sfixed64): | ||
157 | return _TagByteSize(field_number) + 8 | ||
158 | |||
159 | |||
160 | def FloatByteSize(field_number, flt): | ||
161 | return _TagByteSize(field_number) + 4 | ||
162 | |||
163 | |||
164 | def DoubleByteSize(field_number, double): | ||
165 | return _TagByteSize(field_number) + 8 | ||
166 | |||
167 | |||
168 | def BoolByteSize(field_number, b): | ||
169 | return _TagByteSize(field_number) + 1 | ||
170 | |||
171 | |||
172 | def EnumByteSize(field_number, enum): | ||
173 | return UInt32ByteSize(field_number, enum) | ||
174 | |||
175 | |||
176 | def StringByteSize(field_number, string): | ||
177 | return BytesByteSize(field_number, string.encode('utf-8')) | ||
178 | |||
179 | |||
180 | def BytesByteSize(field_number, b): | ||
181 | return (_TagByteSize(field_number) | ||
182 | + _VarUInt64ByteSizeNoTag(len(b)) | ||
183 | + len(b)) | ||
184 | |||
185 | |||
186 | def GroupByteSize(field_number, message): | ||
187 | return (2 * _TagByteSize(field_number) # START and END group. | ||
188 | + message.ByteSize()) | ||
189 | |||
190 | |||
191 | def MessageByteSize(field_number, message): | ||
192 | return (_TagByteSize(field_number) | ||
193 | + _VarUInt64ByteSizeNoTag(message.ByteSize()) | ||
194 | + message.ByteSize()) | ||
195 | |||
196 | |||
197 | def MessageSetItemByteSize(field_number, msg): | ||
198 | # First compute the sizes of the tags. | ||
199 | # There are 2 tags for the beginning and ending of the repeated group, that | ||
200 | # is field number 1, one with field number 2 (type_id) and one with field | ||
201 | # number 3 (message). | ||
202 | total_size = (2 * _TagByteSize(1) + _TagByteSize(2) + _TagByteSize(3)) | ||
203 | |||
204 | # Add the number of bytes for type_id. | ||
205 | total_size += _VarUInt64ByteSizeNoTag(field_number) | ||
206 | |||
207 | message_size = msg.ByteSize() | ||
208 | |||
209 | # The number of bytes for encoding the length of the message. | ||
210 | total_size += _VarUInt64ByteSizeNoTag(message_size) | ||
211 | |||
212 | # The size of the message. | ||
213 | total_size += message_size | ||
214 | return total_size | ||
215 | |||
216 | |||
217 | # Private helper functions for the *ByteSize() functions above. | ||
218 | |||
219 | |||
220 | def _TagByteSize(field_number): | ||
221 | """Returns the bytes required to serialize a tag with this field number.""" | ||
222 | # Just pass in type 0, since the type won't affect the tag+type size. | ||
223 | return _VarUInt64ByteSizeNoTag(PackTag(field_number, 0)) | ||
224 | |||
225 | |||
226 | def _VarUInt64ByteSizeNoTag(uint64): | ||
227 | """Returns the bytes required to serialize a single varint. | ||
228 | uint64 must be unsigned. | ||
229 | """ | ||
230 | if uint64 > UINT64_MAX: | ||
231 | raise message.EncodeError('Value out of range: %d' % uint64) | ||
232 | bytes = 1 | ||
233 | while uint64 > 0x7f: | ||
234 | bytes += 1 | ||
235 | uint64 >>= 7 | ||
236 | return bytes | ||