flexbuffers.py 43 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592
  1. # Lint as: python3
  2. # Copyright 2020 Google Inc. All rights reserved.
  3. #
  4. # Licensed under the Apache License, Version 2.0 (the "License");
  5. # you may not use this file except in compliance with the License.
  6. # You may obtain a copy of the License at
  7. #
  8. # http://www.apache.org/licenses/LICENSE-2.0
  9. #
  10. # Unless required by applicable law or agreed to in writing, software
  11. # distributed under the License is distributed on an "AS IS" BASIS,
  12. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. # See the License for the specific language governing permissions and
  14. # limitations under the License.
  15. """Implementation of FlexBuffers binary format.
  16. For more info check https://google.github.io/flatbuffers/flexbuffers.html and
  17. corresponding C++ implementation at
  18. https://github.com/google/flatbuffers/blob/master/include/flatbuffers/flexbuffers.h
  19. """
  20. # pylint: disable=invalid-name
  21. # TODO(dkovalev): Add type hints everywhere, so tools like pytypes could work.
  22. import array
  23. import contextlib
  24. import enum
  25. import struct
  26. __all__ = ('Type', 'Builder', 'GetRoot', 'Dumps', 'Loads')
  27. class BitWidth(enum.IntEnum):
  28. """Supported bit widths of value types.
  29. These are used in the lower 2 bits of a type field to determine the size of
  30. the elements (and or size field) of the item pointed to (e.g. vector).
  31. """
  32. W8 = 0 # 2^0 = 1 byte
  33. W16 = 1 # 2^1 = 2 bytes
  34. W32 = 2 # 2^2 = 4 bytes
  35. W64 = 3 # 2^3 = 8 bytes
  36. @staticmethod
  37. def U(value):
  38. """Returns the minimum `BitWidth` to encode unsigned integer value."""
  39. assert value >= 0
  40. if value < (1 << 8):
  41. return BitWidth.W8
  42. elif value < (1 << 16):
  43. return BitWidth.W16
  44. elif value < (1 << 32):
  45. return BitWidth.W32
  46. elif value < (1 << 64):
  47. return BitWidth.W64
  48. else:
  49. raise ValueError('value is too big to encode: %s' % value)
  50. @staticmethod
  51. def I(value):
  52. """Returns the minimum `BitWidth` to encode signed integer value."""
  53. # -2^(n-1) <= value < 2^(n-1)
  54. # -2^n <= 2 * value < 2^n
  55. # 2 * value < 2^n, when value >= 0 or 2 * (-value) <= 2^n, when value < 0
  56. # 2 * value < 2^n, when value >= 0 or 2 * (-value) - 1 < 2^n, when value < 0
  57. #
  58. # if value >= 0:
  59. # return BitWidth.U(2 * value)
  60. # else:
  61. # return BitWidth.U(2 * (-value) - 1) # ~x = -x - 1
  62. value *= 2
  63. return BitWidth.U(value if value >= 0 else ~value)
  64. @staticmethod
  65. def F(value):
  66. """Returns the `BitWidth` to encode floating point value."""
  67. if struct.unpack('<f', struct.pack('<f', value))[0] == value:
  68. return BitWidth.W32
  69. return BitWidth.W64
  70. @staticmethod
  71. def B(byte_width):
  72. return {1: BitWidth.W8, 2: BitWidth.W16, 4: BitWidth.W32, 8: BitWidth.W64}[
  73. byte_width
  74. ]
  75. I = {1: 'b', 2: 'h', 4: 'i', 8: 'q'} # Integer formats
  76. U = {1: 'B', 2: 'H', 4: 'I', 8: 'Q'} # Unsigned integer formats
  77. F = {4: 'f', 8: 'd'} # Floating point formats
  78. def _Unpack(fmt, buf):
  79. return struct.unpack('<%s' % fmt[len(buf)], buf)[0]
  80. def _UnpackVector(fmt, buf, length):
  81. byte_width = len(buf) // length
  82. return struct.unpack('<%d%s' % (length, fmt[byte_width]), buf)
  83. def _Pack(fmt, value, byte_width):
  84. return struct.pack('<%s' % fmt[byte_width], value)
  85. def _PackVector(fmt, values, byte_width):
  86. return struct.pack('<%d%s' % (len(values), fmt[byte_width]), *values)
  87. def _Mutate(fmt, buf, value, byte_width, value_bit_width):
  88. if (1 << value_bit_width) <= byte_width:
  89. buf[:byte_width] = _Pack(fmt, value, byte_width)
  90. return True
  91. return False
  92. # Computes how many bytes you'd have to pad to be able to write an
  93. # "scalar_size" scalar if the buffer had grown to "buf_size",
  94. # "scalar_size" is a power of two.
  95. def _PaddingBytes(buf_size, scalar_size):
  96. # ((buf_size + (scalar_size - 1)) // scalar_size) * scalar_size - buf_size
  97. return -buf_size & (scalar_size - 1)
  98. def _ShiftSlice(s, offset, length):
  99. start = offset + (0 if s.start is None else s.start)
  100. stop = offset + (length if s.stop is None else s.stop)
  101. return slice(start, stop, s.step)
  102. # https://en.cppreference.com/w/cpp/algorithm/lower_bound
  103. def _LowerBound(values, value, pred):
  104. """Implementation of C++ std::lower_bound() algorithm."""
  105. first, last = 0, len(values)
  106. count = last - first
  107. while count > 0:
  108. i = first
  109. step = count // 2
  110. i += step
  111. if pred(values[i], value):
  112. i += 1
  113. first = i
  114. count -= step + 1
  115. else:
  116. count = step
  117. return first
  118. # https://en.cppreference.com/w/cpp/algorithm/binary_search
  119. def _BinarySearch(values, value, pred=lambda x, y: x < y):
  120. """Implementation of C++ std::binary_search() algorithm."""
  121. index = _LowerBound(values, value, pred)
  122. if index != len(values) and not pred(value, values[index]):
  123. return index
  124. return -1
  125. class Type(enum.IntEnum):
  126. """Supported types of encoded data.
  127. These are used as the upper 6 bits of a type field to indicate the actual
  128. type.
  129. """
  130. NULL = 0
  131. INT = 1
  132. UINT = 2
  133. FLOAT = 3
  134. # Types above stored inline, types below store an offset.
  135. KEY = 4
  136. STRING = 5
  137. INDIRECT_INT = 6
  138. INDIRECT_UINT = 7
  139. INDIRECT_FLOAT = 8
  140. MAP = 9
  141. VECTOR = 10 # Untyped.
  142. VECTOR_INT = 11 # Typed any size (stores no type table).
  143. VECTOR_UINT = 12
  144. VECTOR_FLOAT = 13
  145. VECTOR_KEY = 14
  146. # DEPRECATED, use VECTOR or VECTOR_KEY instead.
  147. # Read test.cpp/FlexBuffersDeprecatedTest() for details on why.
  148. VECTOR_STRING_DEPRECATED = 15
  149. VECTOR_INT2 = 16 # Typed tuple (no type table, no size field).
  150. VECTOR_UINT2 = 17
  151. VECTOR_FLOAT2 = 18
  152. VECTOR_INT3 = 19 # Typed triple (no type table, no size field).
  153. VECTOR_UINT3 = 20
  154. VECTOR_FLOAT3 = 21
  155. VECTOR_INT4 = 22 # Typed quad (no type table, no size field).
  156. VECTOR_UINT4 = 23
  157. VECTOR_FLOAT4 = 24
  158. BLOB = 25
  159. BOOL = 26
  160. VECTOR_BOOL = 36 # To do the same type of conversion of type to vector type
  161. @staticmethod
  162. def Pack(type_, bit_width):
  163. return (int(type_) << 2) | bit_width
  164. @staticmethod
  165. def Unpack(packed_type):
  166. return 1 << (packed_type & 0b11), Type(packed_type >> 2)
  167. @staticmethod
  168. def IsInline(type_):
  169. return type_ <= Type.FLOAT or type_ == Type.BOOL
  170. @staticmethod
  171. def IsTypedVector(type_):
  172. return (
  173. Type.VECTOR_INT <= type_ <= Type.VECTOR_STRING_DEPRECATED
  174. or type_ == Type.VECTOR_BOOL
  175. )
  176. @staticmethod
  177. def IsTypedVectorElementType(type_):
  178. return Type.INT <= type_ <= Type.STRING or type_ == Type.BOOL
  179. @staticmethod
  180. def ToTypedVectorElementType(type_):
  181. if not Type.IsTypedVector(type_):
  182. raise ValueError('must be typed vector type')
  183. return Type(type_ - Type.VECTOR_INT + Type.INT)
  184. @staticmethod
  185. def IsFixedTypedVector(type_):
  186. return Type.VECTOR_INT2 <= type_ <= Type.VECTOR_FLOAT4
  187. @staticmethod
  188. def IsFixedTypedVectorElementType(type_):
  189. return Type.INT <= type_ <= Type.FLOAT
  190. @staticmethod
  191. def ToFixedTypedVectorElementType(type_):
  192. if not Type.IsFixedTypedVector(type_):
  193. raise ValueError('must be fixed typed vector type')
  194. # 3 types each, starting from length 2.
  195. fixed_type = type_ - Type.VECTOR_INT2
  196. return Type(fixed_type % 3 + Type.INT), fixed_type // 3 + 2
  197. @staticmethod
  198. def ToTypedVector(element_type, fixed_len=0):
  199. """Converts element type to corresponding vector type.
  200. Args:
  201. element_type: vector element type
  202. fixed_len: number of elements: 0 for typed vector; 2, 3, or 4 for fixed
  203. typed vector.
  204. Returns:
  205. Typed vector type or fixed typed vector type.
  206. """
  207. if fixed_len == 0:
  208. if not Type.IsTypedVectorElementType(element_type):
  209. raise ValueError('must be typed vector element type')
  210. else:
  211. if not Type.IsFixedTypedVectorElementType(element_type):
  212. raise ValueError('must be fixed typed vector element type')
  213. offset = element_type - Type.INT
  214. if fixed_len == 0:
  215. return Type(offset + Type.VECTOR_INT) # TypedVector
  216. elif fixed_len == 2:
  217. return Type(offset + Type.VECTOR_INT2) # FixedTypedVector
  218. elif fixed_len == 3:
  219. return Type(offset + Type.VECTOR_INT3) # FixedTypedVector
  220. elif fixed_len == 4:
  221. return Type(offset + Type.VECTOR_INT4) # FixedTypedVector
  222. else:
  223. raise ValueError('unsupported fixed_len: %s' % fixed_len)
  224. class Buf:
  225. """Class to access underlying buffer object starting from the given offset."""
  226. def __init__(self, buf, offset):
  227. self._buf = buf
  228. self._offset = offset if offset >= 0 else len(buf) + offset
  229. self._length = len(buf) - self._offset
  230. def __getitem__(self, key):
  231. if isinstance(key, slice):
  232. return self._buf[_ShiftSlice(key, self._offset, self._length)]
  233. elif isinstance(key, int):
  234. return self._buf[self._offset + key]
  235. else:
  236. raise TypeError('invalid key type')
  237. def __setitem__(self, key, value):
  238. if isinstance(key, slice):
  239. self._buf[_ShiftSlice(key, self._offset, self._length)] = value
  240. elif isinstance(key, int):
  241. self._buf[self._offset + key] = key
  242. else:
  243. raise TypeError('invalid key type')
  244. def __repr__(self):
  245. return 'buf[%d:]' % self._offset
  246. def Find(self, sub):
  247. """Returns the lowest index where the sub subsequence is found."""
  248. return self._buf[self._offset :].find(sub)
  249. def Slice(self, offset):
  250. """Returns new `Buf` which starts from the given offset."""
  251. return Buf(self._buf, self._offset + offset)
  252. def Indirect(self, offset, byte_width):
  253. """Return new `Buf` based on the encoded offset (indirect encoding)."""
  254. return self.Slice(offset - _Unpack(U, self[offset : offset + byte_width]))
  255. class Object:
  256. """Base class for all non-trivial data accessors."""
  257. __slots__ = '_buf', '_byte_width'
  258. def __init__(self, buf, byte_width):
  259. self._buf = buf
  260. self._byte_width = byte_width
  261. @property
  262. def ByteWidth(self):
  263. return self._byte_width
  264. class Sized(Object):
  265. """Base class for all data accessors which need to read encoded size."""
  266. __slots__ = ('_size',)
  267. def __init__(self, buf, byte_width, size=0):
  268. super().__init__(buf, byte_width)
  269. if size == 0:
  270. self._size = _Unpack(U, self.SizeBytes)
  271. else:
  272. self._size = size
  273. @property
  274. def SizeBytes(self):
  275. return self._buf[-self._byte_width : 0]
  276. def __len__(self):
  277. return self._size
  278. class Blob(Sized):
  279. """Data accessor for the encoded blob bytes."""
  280. __slots__ = ()
  281. @property
  282. def Bytes(self):
  283. return self._buf[0 : len(self)]
  284. def __repr__(self):
  285. return 'Blob(%s, size=%d)' % (self._buf, len(self))
  286. class String(Sized):
  287. """Data accessor for the encoded string bytes."""
  288. __slots__ = ()
  289. @property
  290. def Bytes(self):
  291. return self._buf[0 : len(self)]
  292. def Mutate(self, value):
  293. """Mutates underlying string bytes in place.
  294. Args:
  295. value: New string to replace the existing one. New string must have less
  296. or equal UTF-8-encoded bytes than the existing one to successfully
  297. mutate underlying byte buffer.
  298. Returns:
  299. Whether the value was mutated or not.
  300. """
  301. encoded = value.encode('utf-8')
  302. n = len(encoded)
  303. if n <= len(self):
  304. self._buf[-self._byte_width : 0] = _Pack(U, n, self._byte_width)
  305. self._buf[0:n] = encoded
  306. self._buf[n : len(self)] = bytearray(len(self) - n)
  307. return True
  308. return False
  309. def __str__(self):
  310. return self.Bytes.decode('utf-8')
  311. def __repr__(self):
  312. return 'String(%s, size=%d)' % (self._buf, len(self))
  313. class Key(Object):
  314. """Data accessor for the encoded key bytes."""
  315. __slots__ = ()
  316. def __init__(self, buf, byte_width):
  317. assert byte_width == 1
  318. super().__init__(buf, byte_width)
  319. @property
  320. def Bytes(self):
  321. return self._buf[0 : len(self)]
  322. def __len__(self):
  323. return self._buf.Find(0)
  324. def __str__(self):
  325. return self.Bytes.decode('ascii')
  326. def __repr__(self):
  327. return 'Key(%s, size=%d)' % (self._buf, len(self))
  328. class Vector(Sized):
  329. """Data accessor for the encoded vector bytes."""
  330. __slots__ = ()
  331. def __getitem__(self, index):
  332. if index < 0 or index >= len(self):
  333. raise IndexError(
  334. 'vector index %s is out of [0, %d) range' % (index, len(self))
  335. )
  336. packed_type = self._buf[len(self) * self._byte_width + index]
  337. buf = self._buf.Slice(index * self._byte_width)
  338. return Ref.PackedType(buf, self._byte_width, packed_type)
  339. @property
  340. def Value(self):
  341. """Returns the underlying encoded data as a list object."""
  342. return [e.Value for e in self]
  343. def __repr__(self):
  344. return 'Vector(%s, byte_width=%d, size=%d)' % (
  345. self._buf,
  346. self._byte_width,
  347. self._size,
  348. )
  349. class TypedVector(Sized):
  350. """Data accessor for the encoded typed vector or fixed typed vector bytes."""
  351. __slots__ = '_element_type', '_size'
  352. def __init__(self, buf, byte_width, element_type, size=0):
  353. super().__init__(buf, byte_width, size)
  354. if element_type == Type.STRING:
  355. # These can't be accessed as strings, since we don't know the bit-width
  356. # of the size field, see the declaration of
  357. # FBT_VECTOR_STRING_DEPRECATED above for details.
  358. # We change the type here to be keys, which are a subtype of strings,
  359. # and will ignore the size field. This will truncate strings with
  360. # embedded nulls.
  361. element_type = Type.KEY
  362. self._element_type = element_type
  363. @property
  364. def Bytes(self):
  365. return self._buf[: self._byte_width * len(self)]
  366. @property
  367. def ElementType(self):
  368. return self._element_type
  369. def __getitem__(self, index):
  370. if index < 0 or index >= len(self):
  371. raise IndexError(
  372. 'vector index %s is out of [0, %d) range' % (index, len(self))
  373. )
  374. buf = self._buf.Slice(index * self._byte_width)
  375. return Ref(buf, self._byte_width, 1, self._element_type)
  376. @property
  377. def Value(self):
  378. """Returns underlying data as list object."""
  379. if not self:
  380. return []
  381. if self._element_type is Type.BOOL:
  382. return [bool(e) for e in _UnpackVector(U, self.Bytes, len(self))]
  383. elif self._element_type is Type.INT:
  384. return list(_UnpackVector(I, self.Bytes, len(self)))
  385. elif self._element_type is Type.UINT:
  386. return list(_UnpackVector(U, self.Bytes, len(self)))
  387. elif self._element_type is Type.FLOAT:
  388. return list(_UnpackVector(F, self.Bytes, len(self)))
  389. elif self._element_type is Type.KEY:
  390. return [e.AsKey for e in self]
  391. elif self._element_type is Type.STRING:
  392. return [e.AsString for e in self]
  393. else:
  394. raise TypeError('unsupported element_type: %s' % self._element_type)
  395. def __repr__(self):
  396. return 'TypedVector(%s, byte_width=%d, element_type=%s, size=%d)' % (
  397. self._buf,
  398. self._byte_width,
  399. self._element_type,
  400. self._size,
  401. )
  402. class Map(Vector):
  403. """Data accessor for the encoded map bytes."""
  404. @staticmethod
  405. def CompareKeys(a, b):
  406. if isinstance(a, Ref):
  407. a = a.AsKeyBytes
  408. if isinstance(b, Ref):
  409. b = b.AsKeyBytes
  410. return a < b
  411. def __getitem__(self, key):
  412. if isinstance(key, int):
  413. return super().__getitem__(key)
  414. index = _BinarySearch(self.Keys, key.encode('ascii'), self.CompareKeys)
  415. if index != -1:
  416. return super().__getitem__(index)
  417. raise KeyError(key)
  418. @property
  419. def Keys(self):
  420. byte_width = _Unpack(
  421. U, self._buf[-2 * self._byte_width : -self._byte_width]
  422. )
  423. buf = self._buf.Indirect(-3 * self._byte_width, self._byte_width)
  424. return TypedVector(buf, byte_width, Type.KEY)
  425. @property
  426. def Values(self):
  427. return Vector(self._buf, self._byte_width)
  428. @property
  429. def Value(self):
  430. return {k.Value: v.Value for k, v in zip(self.Keys, self.Values)}
  431. def __repr__(self):
  432. return 'Map(%s, size=%d)' % (self._buf, len(self))
  433. class Ref:
  434. """Data accessor for the encoded data bytes."""
  435. __slots__ = '_buf', '_parent_width', '_byte_width', '_type'
  436. @staticmethod
  437. def PackedType(buf, parent_width, packed_type):
  438. byte_width, type_ = Type.Unpack(packed_type)
  439. return Ref(buf, parent_width, byte_width, type_)
  440. def __init__(self, buf, parent_width, byte_width, type_):
  441. self._buf = buf
  442. self._parent_width = parent_width
  443. self._byte_width = byte_width
  444. self._type = type_
  445. def __repr__(self):
  446. return 'Ref(%s, parent_width=%d, byte_width=%d, type_=%s)' % (
  447. self._buf,
  448. self._parent_width,
  449. self._byte_width,
  450. self._type,
  451. )
  452. @property
  453. def _Bytes(self):
  454. return self._buf[: self._parent_width]
  455. def _ConvertError(self, target_type):
  456. raise TypeError('cannot convert %s to %s' % (self._type, target_type))
  457. def _Indirect(self):
  458. return self._buf.Indirect(0, self._parent_width)
  459. @property
  460. def IsNull(self):
  461. return self._type is Type.NULL
  462. @property
  463. def IsBool(self):
  464. return self._type is Type.BOOL
  465. @property
  466. def AsBool(self):
  467. if self._type is Type.BOOL:
  468. return bool(_Unpack(U, self._Bytes))
  469. else:
  470. return self.AsInt != 0
  471. def MutateBool(self, value):
  472. """Mutates underlying boolean value bytes in place.
  473. Args:
  474. value: New boolean value.
  475. Returns:
  476. Whether the value was mutated or not.
  477. """
  478. return self.IsBool and _Mutate(
  479. U, self._buf, value, self._parent_width, BitWidth.W8
  480. )
  481. @property
  482. def IsNumeric(self):
  483. return self.IsInt or self.IsFloat
  484. @property
  485. def IsInt(self):
  486. return self._type in (
  487. Type.INT,
  488. Type.INDIRECT_INT,
  489. Type.UINT,
  490. Type.INDIRECT_UINT,
  491. )
  492. @property
  493. def AsInt(self):
  494. """Returns current reference as integer value."""
  495. if self.IsNull:
  496. return 0
  497. elif self.IsBool:
  498. return int(self.AsBool)
  499. elif self._type is Type.INT:
  500. return _Unpack(I, self._Bytes)
  501. elif self._type is Type.INDIRECT_INT:
  502. return _Unpack(I, self._Indirect()[: self._byte_width])
  503. if self._type is Type.UINT:
  504. return _Unpack(U, self._Bytes)
  505. elif self._type is Type.INDIRECT_UINT:
  506. return _Unpack(U, self._Indirect()[: self._byte_width])
  507. elif self.IsString:
  508. return len(self.AsString)
  509. elif self.IsKey:
  510. return len(self.AsKey)
  511. elif self.IsBlob:
  512. return len(self.AsBlob)
  513. elif self.IsVector:
  514. return len(self.AsVector)
  515. elif self.IsTypedVector:
  516. return len(self.AsTypedVector)
  517. elif self.IsFixedTypedVector:
  518. return len(self.AsFixedTypedVector)
  519. else:
  520. raise self._ConvertError(Type.INT)
  521. def MutateInt(self, value):
  522. """Mutates underlying integer value bytes in place.
  523. Args:
  524. value: New integer value. It must fit to the byte size of the existing
  525. encoded value.
  526. Returns:
  527. Whether the value was mutated or not.
  528. """
  529. if self._type is Type.INT:
  530. return _Mutate(I, self._buf, value, self._parent_width, BitWidth.I(value))
  531. elif self._type is Type.INDIRECT_INT:
  532. return _Mutate(
  533. I, self._Indirect(), value, self._byte_width, BitWidth.I(value)
  534. )
  535. elif self._type is Type.UINT:
  536. return _Mutate(U, self._buf, value, self._parent_width, BitWidth.U(value))
  537. elif self._type is Type.INDIRECT_UINT:
  538. return _Mutate(
  539. U, self._Indirect(), value, self._byte_width, BitWidth.U(value)
  540. )
  541. else:
  542. return False
  543. @property
  544. def IsFloat(self):
  545. return self._type in (Type.FLOAT, Type.INDIRECT_FLOAT)
  546. @property
  547. def AsFloat(self):
  548. """Returns current reference as floating point value."""
  549. if self.IsNull:
  550. return 0.0
  551. elif self.IsBool:
  552. return float(self.AsBool)
  553. elif self.IsInt:
  554. return float(self.AsInt)
  555. elif self._type is Type.FLOAT:
  556. return _Unpack(F, self._Bytes)
  557. elif self._type is Type.INDIRECT_FLOAT:
  558. return _Unpack(F, self._Indirect()[: self._byte_width])
  559. elif self.IsString:
  560. return float(self.AsString)
  561. elif self.IsVector:
  562. return float(len(self.AsVector))
  563. elif self.IsTypedVector():
  564. return float(len(self.AsTypedVector))
  565. elif self.IsFixedTypedVector():
  566. return float(len(self.FixedTypedVector))
  567. else:
  568. raise self._ConvertError(Type.FLOAT)
  569. def MutateFloat(self, value):
  570. """Mutates underlying floating point value bytes in place.
  571. Args:
  572. value: New float value. It must fit to the byte size of the existing
  573. encoded value.
  574. Returns:
  575. Whether the value was mutated or not.
  576. """
  577. if self._type is Type.FLOAT:
  578. return _Mutate(
  579. F,
  580. self._buf,
  581. value,
  582. self._parent_width,
  583. BitWidth.B(self._parent_width),
  584. )
  585. elif self._type is Type.INDIRECT_FLOAT:
  586. return _Mutate(
  587. F,
  588. self._Indirect(),
  589. value,
  590. self._byte_width,
  591. BitWidth.B(self._byte_width),
  592. )
  593. else:
  594. return False
  595. @property
  596. def IsKey(self):
  597. return self._type is Type.KEY
  598. @property
  599. def AsKeyBytes(self):
  600. if self.IsKey:
  601. return Key(self._Indirect(), self._byte_width).Bytes
  602. else:
  603. raise self._ConvertError(Type.KEY)
  604. @property
  605. def AsKey(self):
  606. if self.IsKey:
  607. return str(Key(self._Indirect(), self._byte_width))
  608. else:
  609. raise self._ConvertError(Type.KEY)
  610. @property
  611. def IsString(self):
  612. return self._type is Type.STRING
  613. @property
  614. def AsStringBytes(self):
  615. if self.IsString:
  616. return String(self._Indirect(), self._byte_width).Bytes
  617. elif self.IsKey:
  618. return self.AsKeyBytes
  619. else:
  620. raise self._ConvertError(Type.STRING)
  621. @property
  622. def AsString(self):
  623. if self.IsString:
  624. return str(String(self._Indirect(), self._byte_width))
  625. elif self.IsKey:
  626. return self.AsKey
  627. else:
  628. raise self._ConvertError(Type.STRING)
  629. def MutateString(self, value):
  630. return String(self._Indirect(), self._byte_width).Mutate(value)
  631. @property
  632. def IsBlob(self):
  633. return self._type is Type.BLOB
  634. @property
  635. def AsBlob(self):
  636. if self.IsBlob:
  637. return Blob(self._Indirect(), self._byte_width).Bytes
  638. else:
  639. raise self._ConvertError(Type.BLOB)
  640. @property
  641. def IsAnyVector(self):
  642. return self.IsVector or self.IsTypedVector or self.IsFixedTypedVector()
  643. @property
  644. def IsVector(self):
  645. return self._type in (Type.VECTOR, Type.MAP)
  646. @property
  647. def AsVector(self):
  648. if self.IsVector:
  649. return Vector(self._Indirect(), self._byte_width)
  650. else:
  651. raise self._ConvertError(Type.VECTOR)
  652. @property
  653. def IsTypedVector(self):
  654. return Type.IsTypedVector(self._type)
  655. @property
  656. def AsTypedVector(self):
  657. if self.IsTypedVector:
  658. return TypedVector(
  659. self._Indirect(),
  660. self._byte_width,
  661. Type.ToTypedVectorElementType(self._type),
  662. )
  663. else:
  664. raise self._ConvertError('TYPED_VECTOR')
  665. @property
  666. def IsFixedTypedVector(self):
  667. return Type.IsFixedTypedVector(self._type)
  668. @property
  669. def AsFixedTypedVector(self):
  670. if self.IsFixedTypedVector:
  671. element_type, size = Type.ToFixedTypedVectorElementType(self._type)
  672. return TypedVector(self._Indirect(), self._byte_width, element_type, size)
  673. else:
  674. raise self._ConvertError('FIXED_TYPED_VECTOR')
  675. @property
  676. def IsMap(self):
  677. return self._type is Type.MAP
  678. @property
  679. def AsMap(self):
  680. if self.IsMap:
  681. return Map(self._Indirect(), self._byte_width)
  682. else:
  683. raise self._ConvertError(Type.MAP)
  684. @property
  685. def Value(self):
  686. """Converts current reference to value of corresponding type.
  687. This is equivalent to calling `AsInt` for integer values, `AsFloat` for
  688. floating point values, etc.
  689. Returns:
  690. Value of corresponding type.
  691. """
  692. if self.IsNull:
  693. return None
  694. elif self.IsBool:
  695. return self.AsBool
  696. elif self.IsInt:
  697. return self.AsInt
  698. elif self.IsFloat:
  699. return self.AsFloat
  700. elif self.IsString:
  701. return self.AsString
  702. elif self.IsKey:
  703. return self.AsKey
  704. elif self.IsBlob:
  705. return self.AsBlob
  706. elif self.IsMap:
  707. return self.AsMap.Value
  708. elif self.IsVector:
  709. return self.AsVector.Value
  710. elif self.IsTypedVector:
  711. return self.AsTypedVector.Value
  712. elif self.IsFixedTypedVector:
  713. return self.AsFixedTypedVector.Value
  714. else:
  715. raise TypeError('cannot convert %r to value' % self)
  716. def _IsIterable(obj):
  717. try:
  718. iter(obj)
  719. return True
  720. except TypeError:
  721. return False
  722. class Value:
  723. """Class to represent given value during the encoding process."""
  724. @staticmethod
  725. def Null():
  726. return Value(0, Type.NULL, BitWidth.W8)
  727. @staticmethod
  728. def Bool(value):
  729. return Value(value, Type.BOOL, BitWidth.W8)
  730. @staticmethod
  731. def Int(value, bit_width):
  732. return Value(value, Type.INT, bit_width)
  733. @staticmethod
  734. def UInt(value, bit_width):
  735. return Value(value, Type.UINT, bit_width)
  736. @staticmethod
  737. def Float(value, bit_width):
  738. return Value(value, Type.FLOAT, bit_width)
  739. @staticmethod
  740. def Key(offset):
  741. return Value(offset, Type.KEY, BitWidth.W8)
  742. def __init__(self, value, type_, min_bit_width):
  743. self._value = value
  744. self._type = type_
  745. # For scalars: of itself, for vector: of its elements, for string: length.
  746. self._min_bit_width = min_bit_width
  747. @property
  748. def Value(self):
  749. return self._value
  750. @property
  751. def Type(self):
  752. return self._type
  753. @property
  754. def MinBitWidth(self):
  755. return self._min_bit_width
  756. def StoredPackedType(self, parent_bit_width=BitWidth.W8):
  757. return Type.Pack(self._type, self.StoredWidth(parent_bit_width))
  758. # We have an absolute offset, but want to store a relative offset
  759. # elem_index elements beyond the current buffer end. Since whether
  760. # the relative offset fits in a certain byte_width depends on
  761. # the size of the elements before it (and their alignment), we have
  762. # to test for each size in turn.
  763. def ElemWidth(self, buf_size, elem_index=0):
  764. if Type.IsInline(self._type):
  765. return self._min_bit_width
  766. for byte_width in 1, 2, 4, 8:
  767. offset_loc = (
  768. buf_size
  769. + _PaddingBytes(buf_size, byte_width)
  770. + elem_index * byte_width
  771. )
  772. bit_width = BitWidth.U(offset_loc - self._value)
  773. if byte_width == (1 << bit_width):
  774. return bit_width
  775. raise ValueError('relative offset is too big')
  776. def StoredWidth(self, parent_bit_width=BitWidth.W8):
  777. if Type.IsInline(self._type):
  778. return max(self._min_bit_width, parent_bit_width)
  779. return self._min_bit_width
  780. def __repr__(self):
  781. return 'Value(%s, %s, %s)' % (self._value, self._type, self._min_bit_width)
  782. def __str__(self):
  783. return str(self._value)
  784. def InMap(func):
  785. def wrapper(self, *args, **kwargs):
  786. if isinstance(args[0], str):
  787. self.Key(args[0])
  788. func(self, *args[1:], **kwargs)
  789. else:
  790. func(self, *args, **kwargs)
  791. return wrapper
  792. def InMapForString(func):
  793. def wrapper(self, *args):
  794. if len(args) == 1:
  795. func(self, args[0])
  796. elif len(args) == 2:
  797. self.Key(args[0])
  798. func(self, args[1])
  799. else:
  800. raise ValueError('invalid number of arguments')
  801. return wrapper
  802. class Pool:
  803. """Collection of (data, offset) pairs sorted by data for quick access."""
  804. def __init__(self):
  805. self._pool = [] # sorted list of (data, offset) tuples
  806. def FindOrInsert(self, data, offset):
  807. do = data, offset
  808. index = _BinarySearch(self._pool, do, lambda a, b: a[0] < b[0])
  809. if index != -1:
  810. _, offset = self._pool[index]
  811. return offset
  812. self._pool.insert(index, do)
  813. return None
  814. def Clear(self):
  815. self._pool = []
  816. @property
  817. def Elements(self):
  818. return [data for data, _ in self._pool]
  819. class Builder:
  820. """Helper class to encode structural data into flexbuffers format."""
  821. def __init__(
  822. self,
  823. share_strings=False,
  824. share_keys=True,
  825. force_min_bit_width=BitWidth.W8,
  826. ):
  827. self._share_strings = share_strings
  828. self._share_keys = share_keys
  829. self._force_min_bit_width = force_min_bit_width
  830. self._string_pool = Pool()
  831. self._key_pool = Pool()
  832. self._finished = False
  833. self._buf = bytearray()
  834. self._stack = []
  835. def __len__(self):
  836. return len(self._buf)
  837. @property
  838. def StringPool(self):
  839. return self._string_pool
  840. @property
  841. def KeyPool(self):
  842. return self._key_pool
  843. def Clear(self):
  844. self._string_pool.Clear()
  845. self._key_pool.Clear()
  846. self._finished = False
  847. self._buf = bytearray()
  848. self._stack = []
  849. def Finish(self):
  850. """Finishes encoding process and returns underlying buffer."""
  851. if self._finished:
  852. raise RuntimeError('builder has been already finished')
  853. # If you hit this exception, you likely have objects that were never
  854. # included in a parent. You need to have exactly one root to finish a
  855. # buffer. Check your Start/End calls are matched, and all objects are inside
  856. # some other object.
  857. if len(self._stack) != 1:
  858. raise RuntimeError('internal stack size must be one')
  859. value = self._stack[0]
  860. byte_width = self._Align(value.ElemWidth(len(self._buf)))
  861. self._WriteAny(value, byte_width=byte_width) # Root value
  862. self._Write(U, value.StoredPackedType(), byte_width=1) # Root type
  863. self._Write(U, byte_width, byte_width=1) # Root size
  864. self.finished = True
  865. return self._buf
  866. def _ReadKey(self, offset):
  867. key = self._buf[offset:]
  868. return key[: key.find(0)]
  869. def _Align(self, alignment):
  870. byte_width = 1 << alignment
  871. self._buf.extend(b'\x00' * _PaddingBytes(len(self._buf), byte_width))
  872. return byte_width
  873. def _Write(self, fmt, value, byte_width):
  874. self._buf.extend(_Pack(fmt, value, byte_width))
  875. def _WriteVector(self, fmt, values, byte_width):
  876. self._buf.extend(_PackVector(fmt, values, byte_width))
  877. def _WriteOffset(self, offset, byte_width):
  878. relative_offset = len(self._buf) - offset
  879. assert byte_width == 8 or relative_offset < (1 << (8 * byte_width))
  880. self._Write(U, relative_offset, byte_width)
  881. def _WriteAny(self, value, byte_width):
  882. fmt = {
  883. Type.NULL: U,
  884. Type.BOOL: U,
  885. Type.INT: I,
  886. Type.UINT: U,
  887. Type.FLOAT: F,
  888. }.get(value.Type)
  889. if fmt:
  890. self._Write(fmt, value.Value, byte_width)
  891. else:
  892. self._WriteOffset(value.Value, byte_width)
  893. def _WriteBlob(self, data, append_zero, type_):
  894. bit_width = BitWidth.U(len(data))
  895. byte_width = self._Align(bit_width)
  896. self._Write(U, len(data), byte_width)
  897. loc = len(self._buf)
  898. self._buf.extend(data)
  899. if append_zero:
  900. self._buf.append(0)
  901. self._stack.append(Value(loc, type_, bit_width))
  902. return loc
  903. def _WriteScalarVector(self, element_type, byte_width, elements, fixed):
  904. """Writes scalar vector elements to the underlying buffer."""
  905. bit_width = BitWidth.B(byte_width)
  906. # If you get this exception, you're trying to write a vector with a size
  907. # field that is bigger than the scalars you're trying to write (e.g. a
  908. # byte vector > 255 elements). For such types, write a "blob" instead.
  909. if BitWidth.U(len(elements)) > bit_width:
  910. raise ValueError('too many elements for the given byte_width')
  911. self._Align(bit_width)
  912. if not fixed:
  913. self._Write(U, len(elements), byte_width)
  914. loc = len(self._buf)
  915. fmt = {Type.INT: I, Type.UINT: U, Type.FLOAT: F}.get(element_type)
  916. if not fmt:
  917. raise TypeError('unsupported element_type')
  918. self._WriteVector(fmt, elements, byte_width)
  919. type_ = Type.ToTypedVector(element_type, len(elements) if fixed else 0)
  920. self._stack.append(Value(loc, type_, bit_width))
  921. return loc
  922. def _CreateVector(self, elements, typed, fixed, keys=None):
  923. """Writes vector elements to the underlying buffer."""
  924. length = len(elements)
  925. if fixed and not typed:
  926. raise ValueError('fixed vector must be typed')
  927. # Figure out smallest bit width we can store this vector with.
  928. bit_width = max(self._force_min_bit_width, BitWidth.U(length))
  929. prefix_elems = 1 # Vector size
  930. if keys:
  931. bit_width = max(bit_width, keys.ElemWidth(len(self._buf)))
  932. prefix_elems += 2 # Offset to the keys vector and its byte width.
  933. vector_type = Type.KEY
  934. # Check bit widths and types for all elements.
  935. for i, e in enumerate(elements):
  936. bit_width = max(bit_width, e.ElemWidth(len(self._buf), prefix_elems + i))
  937. if typed:
  938. if i == 0:
  939. vector_type = e.Type
  940. else:
  941. if vector_type != e.Type:
  942. raise RuntimeError('typed vector elements must be of the same type')
  943. if fixed and not Type.IsFixedTypedVectorElementType(vector_type):
  944. raise RuntimeError('must be fixed typed vector element type')
  945. byte_width = self._Align(bit_width)
  946. # Write vector. First the keys width/offset if available, and size.
  947. if keys:
  948. self._WriteOffset(keys.Value, byte_width)
  949. self._Write(U, 1 << keys.MinBitWidth, byte_width)
  950. if not fixed:
  951. self._Write(U, length, byte_width)
  952. # Then the actual data.
  953. loc = len(self._buf)
  954. for e in elements:
  955. self._WriteAny(e, byte_width)
  956. # Then the types.
  957. if not typed:
  958. for e in elements:
  959. self._buf.append(e.StoredPackedType(bit_width))
  960. if keys:
  961. type_ = Type.MAP
  962. else:
  963. if typed:
  964. type_ = Type.ToTypedVector(vector_type, length if fixed else 0)
  965. else:
  966. type_ = Type.VECTOR
  967. return Value(loc, type_, bit_width)
  968. def _PushIndirect(self, value, type_, bit_width):
  969. byte_width = self._Align(bit_width)
  970. loc = len(self._buf)
  971. fmt = {Type.INDIRECT_INT: I, Type.INDIRECT_UINT: U, Type.INDIRECT_FLOAT: F}[
  972. type_
  973. ]
  974. self._Write(fmt, value, byte_width)
  975. self._stack.append(Value(loc, type_, bit_width))
  976. @InMapForString
  977. def String(self, value):
  978. """Encodes string value."""
  979. reset_to = len(self._buf)
  980. encoded = value.encode('utf-8')
  981. loc = self._WriteBlob(encoded, append_zero=True, type_=Type.STRING)
  982. if self._share_strings:
  983. prev_loc = self._string_pool.FindOrInsert(encoded, loc)
  984. if prev_loc is not None:
  985. del self._buf[reset_to:]
  986. self._stack[-1]._value = loc = prev_loc # pylint: disable=protected-access
  987. return loc
  988. @InMap
  989. def Blob(self, value):
  990. """Encodes binary blob value.
  991. Args:
  992. value: A byte/bytearray value to encode
  993. Returns:
  994. Offset of the encoded value in underlying the byte buffer.
  995. """
  996. return self._WriteBlob(value, append_zero=False, type_=Type.BLOB)
  997. def Key(self, value):
  998. """Encodes key value.
  999. Args:
  1000. value: A byte/bytearray/str value to encode. Byte object must not contain
  1001. zero bytes. String object must be convertible to ASCII.
  1002. Returns:
  1003. Offset of the encoded value in the underlying byte buffer.
  1004. """
  1005. if isinstance(value, (bytes, bytearray)):
  1006. encoded = value
  1007. else:
  1008. encoded = value.encode('ascii')
  1009. if 0 in encoded:
  1010. raise ValueError('key contains zero byte')
  1011. loc = len(self._buf)
  1012. self._buf.extend(encoded)
  1013. self._buf.append(0)
  1014. if self._share_keys:
  1015. prev_loc = self._key_pool.FindOrInsert(encoded, loc)
  1016. if prev_loc is not None:
  1017. del self._buf[loc:]
  1018. loc = prev_loc
  1019. self._stack.append(Value.Key(loc))
  1020. return loc
  1021. def Null(self, key=None):
  1022. """Encodes None value."""
  1023. if key:
  1024. self.Key(key)
  1025. self._stack.append(Value.Null())
  1026. @InMap
  1027. def Bool(self, value):
  1028. """Encodes boolean value.
  1029. Args:
  1030. value: A boolean value.
  1031. """
  1032. self._stack.append(Value.Bool(value))
  1033. @InMap
  1034. def Int(self, value, byte_width=0):
  1035. """Encodes signed integer value.
  1036. Args:
  1037. value: A signed integer value.
  1038. byte_width: Number of bytes to use: 1, 2, 4, or 8.
  1039. """
  1040. bit_width = BitWidth.I(value) if byte_width == 0 else BitWidth.B(byte_width)
  1041. self._stack.append(Value.Int(value, bit_width))
  1042. @InMap
  1043. def IndirectInt(self, value, byte_width=0):
  1044. """Encodes signed integer value indirectly.
  1045. Args:
  1046. value: A signed integer value.
  1047. byte_width: Number of bytes to use: 1, 2, 4, or 8.
  1048. """
  1049. bit_width = BitWidth.I(value) if byte_width == 0 else BitWidth.B(byte_width)
  1050. self._PushIndirect(value, Type.INDIRECT_INT, bit_width)
  1051. @InMap
  1052. def UInt(self, value, byte_width=0):
  1053. """Encodes unsigned integer value.
  1054. Args:
  1055. value: An unsigned integer value.
  1056. byte_width: Number of bytes to use: 1, 2, 4, or 8.
  1057. """
  1058. bit_width = BitWidth.U(value) if byte_width == 0 else BitWidth.B(byte_width)
  1059. self._stack.append(Value.UInt(value, bit_width))
  1060. @InMap
  1061. def IndirectUInt(self, value, byte_width=0):
  1062. """Encodes unsigned integer value indirectly.
  1063. Args:
  1064. value: An unsigned integer value.
  1065. byte_width: Number of bytes to use: 1, 2, 4, or 8.
  1066. """
  1067. bit_width = BitWidth.U(value) if byte_width == 0 else BitWidth.B(byte_width)
  1068. self._PushIndirect(value, Type.INDIRECT_UINT, bit_width)
  1069. @InMap
  1070. def Float(self, value, byte_width=0):
  1071. """Encodes floating point value.
  1072. Args:
  1073. value: A floating point value.
  1074. byte_width: Number of bytes to use: 4 or 8.
  1075. """
  1076. bit_width = BitWidth.F(value) if byte_width == 0 else BitWidth.B(byte_width)
  1077. self._stack.append(Value.Float(value, bit_width))
  1078. @InMap
  1079. def IndirectFloat(self, value, byte_width=0):
  1080. """Encodes floating point value indirectly.
  1081. Args:
  1082. value: A floating point value.
  1083. byte_width: Number of bytes to use: 4 or 8.
  1084. """
  1085. bit_width = BitWidth.F(value) if byte_width == 0 else BitWidth.B(byte_width)
  1086. self._PushIndirect(value, Type.INDIRECT_FLOAT, bit_width)
  1087. def _StartVector(self):
  1088. """Starts vector construction."""
  1089. return len(self._stack)
  1090. def _EndVector(self, start, typed, fixed):
  1091. """Finishes vector construction by encodung its elements."""
  1092. vec = self._CreateVector(self._stack[start:], typed, fixed)
  1093. del self._stack[start:]
  1094. self._stack.append(vec)
  1095. return vec.Value
  1096. @contextlib.contextmanager
  1097. def Vector(self, key=None):
  1098. if key:
  1099. self.Key(key)
  1100. try:
  1101. start = self._StartVector()
  1102. yield self
  1103. finally:
  1104. self._EndVector(start, typed=False, fixed=False)
  1105. @InMap
  1106. def VectorFromElements(self, elements):
  1107. """Encodes sequence of any elements as a vector.
  1108. Args:
  1109. elements: sequence of elements, they may have different types.
  1110. """
  1111. with self.Vector():
  1112. for e in elements:
  1113. self.Add(e)
  1114. @contextlib.contextmanager
  1115. def TypedVector(self, key=None):
  1116. if key:
  1117. self.Key(key)
  1118. try:
  1119. start = self._StartVector()
  1120. yield self
  1121. finally:
  1122. self._EndVector(start, typed=True, fixed=False)
  1123. @InMap
  1124. def TypedVectorFromElements(self, elements, element_type=None):
  1125. """Encodes sequence of elements of the same type as typed vector.
  1126. Args:
  1127. elements: Sequence of elements, they must be of the same type.
  1128. element_type: Suggested element type. Setting it to None means determining
  1129. correct value automatically based on the given elements.
  1130. """
  1131. if isinstance(elements, array.array):
  1132. if elements.typecode == 'f':
  1133. self._WriteScalarVector(Type.FLOAT, 4, elements, fixed=False)
  1134. elif elements.typecode == 'd':
  1135. self._WriteScalarVector(Type.FLOAT, 8, elements, fixed=False)
  1136. elif elements.typecode in ('b', 'h', 'i', 'l', 'q'):
  1137. self._WriteScalarVector(
  1138. Type.INT, elements.itemsize, elements, fixed=False
  1139. )
  1140. elif elements.typecode in ('B', 'H', 'I', 'L', 'Q'):
  1141. self._WriteScalarVector(
  1142. Type.UINT, elements.itemsize, elements, fixed=False
  1143. )
  1144. else:
  1145. raise ValueError('unsupported array typecode: %s' % elements.typecode)
  1146. else:
  1147. add = self.Add if element_type is None else self.Adder(element_type)
  1148. with self.TypedVector():
  1149. for e in elements:
  1150. add(e)
  1151. @InMap
  1152. def FixedTypedVectorFromElements(
  1153. self, elements, element_type=None, byte_width=0
  1154. ):
  1155. """Encodes sequence of elements of the same type as fixed typed vector.
  1156. Args:
  1157. elements: Sequence of elements, they must be of the same type. Allowed
  1158. types are `Type.INT`, `Type.UINT`, `Type.FLOAT`. Allowed number of
  1159. elements are 2, 3, or 4.
  1160. element_type: Suggested element type. Setting it to None means determining
  1161. correct value automatically based on the given elements.
  1162. byte_width: Number of bytes to use per element. For `Type.INT` and
  1163. `Type.UINT`: 1, 2, 4, or 8. For `Type.FLOAT`: 4 or 8. Setting it to 0
  1164. means determining correct value automatically based on the given
  1165. elements.
  1166. """
  1167. if not 2 <= len(elements) <= 4:
  1168. raise ValueError('only 2, 3, or 4 elements are supported')
  1169. types = {type(e) for e in elements}
  1170. if len(types) != 1:
  1171. raise TypeError('all elements must be of the same type')
  1172. (type_,) = types
  1173. if element_type is None:
  1174. element_type = {int: Type.INT, float: Type.FLOAT}.get(type_)
  1175. if not element_type:
  1176. raise TypeError('unsupported element_type: %s' % type_)
  1177. if byte_width == 0:
  1178. width = {
  1179. Type.UINT: BitWidth.U,
  1180. Type.INT: BitWidth.I,
  1181. Type.FLOAT: BitWidth.F,
  1182. }[element_type]
  1183. byte_width = 1 << max(width(e) for e in elements)
  1184. self._WriteScalarVector(element_type, byte_width, elements, fixed=True)
  1185. def _StartMap(self):
  1186. """Starts map construction."""
  1187. return len(self._stack)
  1188. def _EndMap(self, start):
  1189. """Finishes map construction by encodung its elements."""
  1190. # Interleaved keys and values on the stack.
  1191. stack = self._stack[start:]
  1192. if len(stack) % 2 != 0:
  1193. raise RuntimeError('must be even number of keys and values')
  1194. for key in stack[::2]:
  1195. if key.Type is not Type.KEY:
  1196. raise RuntimeError('all map keys must be of %s type' % Type.KEY)
  1197. pairs = zip(stack[::2], stack[1::2]) # [(key, value), ...]
  1198. pairs = sorted(pairs, key=lambda pair: self._ReadKey(pair[0].Value))
  1199. del self._stack[start:]
  1200. for pair in pairs:
  1201. self._stack.extend(pair)
  1202. keys = self._CreateVector(self._stack[start::2], typed=True, fixed=False)
  1203. values = self._CreateVector(
  1204. self._stack[start + 1 :: 2], typed=False, fixed=False, keys=keys
  1205. )
  1206. del self._stack[start:]
  1207. self._stack.append(values)
  1208. return values.Value
  1209. @contextlib.contextmanager
  1210. def Map(self, key=None):
  1211. if key:
  1212. self.Key(key)
  1213. try:
  1214. start = self._StartMap()
  1215. yield self
  1216. finally:
  1217. self._EndMap(start)
  1218. def MapFromElements(self, elements):
  1219. start = self._StartMap()
  1220. for k, v in elements.items():
  1221. self.Key(k)
  1222. self.Add(v)
  1223. self._EndMap(start)
  1224. def Adder(self, type_):
  1225. return {
  1226. Type.BOOL: self.Bool,
  1227. Type.INT: self.Int,
  1228. Type.INDIRECT_INT: self.IndirectInt,
  1229. Type.UINT: self.UInt,
  1230. Type.INDIRECT_UINT: self.IndirectUInt,
  1231. Type.FLOAT: self.Float,
  1232. Type.INDIRECT_FLOAT: self.IndirectFloat,
  1233. Type.KEY: self.Key,
  1234. Type.BLOB: self.Blob,
  1235. Type.STRING: self.String,
  1236. }[type_]
  1237. @InMapForString
  1238. def Add(self, value):
  1239. """Encodes value of any supported type."""
  1240. if value is None:
  1241. self.Null()
  1242. elif isinstance(value, bool):
  1243. self.Bool(value)
  1244. elif isinstance(value, int):
  1245. self.Int(value)
  1246. elif isinstance(value, float):
  1247. self.Float(value)
  1248. elif isinstance(value, str):
  1249. self.String(value)
  1250. elif isinstance(value, (bytes, bytearray)):
  1251. self.Blob(value)
  1252. elif isinstance(value, dict):
  1253. with self.Map():
  1254. for k, v in value.items():
  1255. self.Key(k)
  1256. self.Add(v)
  1257. elif isinstance(value, array.array):
  1258. self.TypedVectorFromElements(value)
  1259. elif _IsIterable(value):
  1260. self.VectorFromElements(value)
  1261. else:
  1262. raise TypeError('unsupported python type: %s' % type(value))
  1263. @property
  1264. def LastValue(self):
  1265. return self._stack[-1]
  1266. @InMap
  1267. def ReuseValue(self, value):
  1268. self._stack.append(value)
  1269. def GetRoot(buf):
  1270. """Returns root `Ref` object for the given buffer."""
  1271. if len(buf) < 3:
  1272. raise ValueError('buffer is too small')
  1273. byte_width = buf[-1]
  1274. return Ref.PackedType(
  1275. Buf(buf, -(2 + byte_width)), byte_width, packed_type=buf[-2]
  1276. )
  1277. def Dumps(obj):
  1278. """Returns bytearray with the encoded python object."""
  1279. fbb = Builder()
  1280. fbb.Add(obj)
  1281. return fbb.Finish()
  1282. def Loads(buf):
  1283. """Returns python object decoded from the buffer."""
  1284. return GetRoot(buf).Value