+def varint_max_size(max_value):
+ '''Returns the maximum number of bytes a varint can take when encoded.'''
+ for i in range(1, 11):
+ if (max_value >> (i * 7)) == 0:
+ return i
+ raise ValueError("Value too large for varint: " + str(max_value))
+
+assert varint_max_size(0) == 1
+assert varint_max_size(127) == 1
+assert varint_max_size(128) == 2
+
+class EncodedSize:
+ '''Class used to represent the encoded size of a field or a message.
+ Consists of a combination of symbolic sizes and integer sizes.'''
+ def __init__(self, value = 0, symbols = []):
+ if isinstance(value, (str, Names)):
+ symbols = [str(value)]
+ value = 0
+ self.value = value
+ self.symbols = symbols
+
+ def __add__(self, other):
+ if isinstance(other, (int, long)):
+ return EncodedSize(self.value + other, self.symbols)
+ elif isinstance(other, (str, Names)):
+ return EncodedSize(self.value, self.symbols + [str(other)])
+ elif isinstance(other, EncodedSize):
+ return EncodedSize(self.value + other.value, self.symbols + other.symbols)
+ else:
+ raise ValueError("Cannot add size: " + repr(other))
+
+ def __mul__(self, other):
+ if isinstance(other, (int, long)):
+ return EncodedSize(self.value * other, [str(other) + '*' + s for s in self.symbols])
+ else:
+ raise ValueError("Cannot multiply size: " + repr(other))
+
+ def __str__(self):
+ if not self.symbols:
+ return str(self.value)
+ else:
+ return '(' + str(self.value) + ' + ' + ' + '.join(self.symbols) + ')'
+
+ def upperlimit(self):
+ if not self.symbols:
+ return self.value
+ else:
+ return 2**32 - 1
+