Browse Source

add nanopb (manual)

Philippe G 3 years ago
parent
commit
39f5a81238
100 changed files with 18441 additions and 0 deletions
  1. 31 0
      components/spotify/cspot/bell/nanopb/.gitignore
  2. 32 0
      components/spotify/cspot/bell/nanopb/.travis.yml
  3. 100 0
      components/spotify/cspot/bell/nanopb/AUTHORS.txt
  4. 21 0
      components/spotify/cspot/bell/nanopb/BUILD.bazel
  5. 522 0
      components/spotify/cspot/bell/nanopb/CHANGELOG.txt
  6. 143 0
      components/spotify/cspot/bell/nanopb/CMakeLists.txt
  7. 32 0
      components/spotify/cspot/bell/nanopb/CONTRIBUTING.md
  8. 20 0
      components/spotify/cspot/bell/nanopb/LICENSE.txt
  9. 63 0
      components/spotify/cspot/bell/nanopb/Package.swift
  10. 108 0
      components/spotify/cspot/bell/nanopb/README.md
  11. 1 0
      components/spotify/cspot/bell/nanopb/WORKSPACE
  12. 6 0
      components/spotify/cspot/bell/nanopb/build.py
  13. 7 0
      components/spotify/cspot/bell/nanopb/conan-wrapper/CMakeLists.txt
  14. 33 0
      components/spotify/cspot/bell/nanopb/conanfile.py
  15. 23 0
      components/spotify/cspot/bell/nanopb/docs/Makefile
  16. 579 0
      components/spotify/cspot/bell/nanopb/docs/concepts.md
  17. 2869 0
      components/spotify/cspot/bell/nanopb/docs/generator_flow.svg
  18. 158 0
      components/spotify/cspot/bell/nanopb/docs/index.md
  19. BIN
      components/spotify/cspot/bell/nanopb/docs/logo/logo.png
  20. 1464 0
      components/spotify/cspot/bell/nanopb/docs/logo/logo.svg
  21. BIN
      components/spotify/cspot/bell/nanopb/docs/logo/logo16px.png
  22. BIN
      components/spotify/cspot/bell/nanopb/docs/logo/logo48px.png
  23. 233 0
      components/spotify/cspot/bell/nanopb/docs/lsr.css
  24. 618 0
      components/spotify/cspot/bell/nanopb/docs/migration.md
  25. 1034 0
      components/spotify/cspot/bell/nanopb/docs/reference.md
  26. 92 0
      components/spotify/cspot/bell/nanopb/docs/security.md
  27. 173 0
      components/spotify/cspot/bell/nanopb/docs/whats_new.md
  28. 18 0
      components/spotify/cspot/bell/nanopb/examples/cmake_relpath/CMakeLists.txt
  29. 18 0
      components/spotify/cspot/bell/nanopb/examples/cmake_relpath/README.txt
  30. 11 0
      components/spotify/cspot/bell/nanopb/examples/cmake_relpath/proto/simple.proto
  31. 5 0
      components/spotify/cspot/bell/nanopb/examples/cmake_relpath/proto/sub/unlucky.proto
  32. 73 0
      components/spotify/cspot/bell/nanopb/examples/cmake_relpath/simple.c
  33. 16 0
      components/spotify/cspot/bell/nanopb/examples/cmake_simple/CMakeLists.txt
  34. 18 0
      components/spotify/cspot/bell/nanopb/examples/cmake_simple/README.txt
  35. 71 0
      components/spotify/cspot/bell/nanopb/examples/cmake_simple/simple.c
  36. 9 0
      components/spotify/cspot/bell/nanopb/examples/cmake_simple/simple.proto
  37. 17 0
      components/spotify/cspot/bell/nanopb/examples/network_server/Makefile
  38. 60 0
      components/spotify/cspot/bell/nanopb/examples/network_server/README.txt
  39. 138 0
      components/spotify/cspot/bell/nanopb/examples/network_server/client.c
  40. 43 0
      components/spotify/cspot/bell/nanopb/examples/network_server/common.c
  41. 9 0
      components/spotify/cspot/bell/nanopb/examples/network_server/common.h
  42. 16 0
      components/spotify/cspot/bell/nanopb/examples/network_server/fileproto.options
  43. 20 0
      components/spotify/cspot/bell/nanopb/examples/network_server/fileproto.proto
  44. 164 0
      components/spotify/cspot/bell/nanopb/examples/network_server/server.c
  45. 5 0
      components/spotify/cspot/bell/nanopb/examples/platformio/.gitignore
  46. 35 0
      components/spotify/cspot/bell/nanopb/examples/platformio/platformio.ini
  47. 1 0
      components/spotify/cspot/bell/nanopb/examples/platformio/proto/pio_with_options.options
  48. 5 0
      components/spotify/cspot/bell/nanopb/examples/platformio/proto/pio_with_options.proto
  49. 5 0
      components/spotify/cspot/bell/nanopb/examples/platformio/proto/pio_without_options.proto
  50. 35 0
      components/spotify/cspot/bell/nanopb/examples/platformio/src/pio_with_options.c
  51. 35 0
      components/spotify/cspot/bell/nanopb/examples/platformio/src/pio_without_options.c
  52. 9 0
      components/spotify/cspot/bell/nanopb/examples/platformio/src/test.h
  53. 22 0
      components/spotify/cspot/bell/nanopb/examples/simple/Makefile
  54. 29 0
      components/spotify/cspot/bell/nanopb/examples/simple/README.txt
  55. 71 0
      components/spotify/cspot/bell/nanopb/examples/simple/simple.c
  56. 9 0
      components/spotify/cspot/bell/nanopb/examples/simple/simple.proto
  57. 20 0
      components/spotify/cspot/bell/nanopb/examples/using_union_messages/Makefile
  58. 55 0
      components/spotify/cspot/bell/nanopb/examples/using_union_messages/README.txt
  59. 95 0
      components/spotify/cspot/bell/nanopb/examples/using_union_messages/decode.c
  60. 90 0
      components/spotify/cspot/bell/nanopb/examples/using_union_messages/encode.c
  61. 32 0
      components/spotify/cspot/bell/nanopb/examples/using_union_messages/unionproto.proto
  62. 371 0
      components/spotify/cspot/bell/nanopb/extra/FindNanopb.cmake
  63. 11 0
      components/spotify/cspot/bell/nanopb/extra/nanopb-config-version.cmake.in
  64. 1 0
      components/spotify/cspot/bell/nanopb/extra/nanopb-config.cmake
  65. 37 0
      components/spotify/cspot/bell/nanopb/extra/nanopb.mk
  66. 120 0
      components/spotify/cspot/bell/nanopb/extra/pb_syshdr.h
  67. 20 0
      components/spotify/cspot/bell/nanopb/extra/poetry/poetry_build.sh
  68. 31 0
      components/spotify/cspot/bell/nanopb/extra/poetry/pyproject.toml
  69. 2361 0
      components/spotify/cspot/bell/nanopb/generator/nanopb_generator.py
  70. 13 0
      components/spotify/cspot/bell/nanopb/generator/nanopb_generator.py2
  71. 148 0
      components/spotify/cspot/bell/nanopb/generator/platformio_generator.py
  72. 10 0
      components/spotify/cspot/bell/nanopb/generator/proto/Makefile
  73. 36 0
      components/spotify/cspot/bell/nanopb/generator/proto/__init__.py
  74. 43 0
      components/spotify/cspot/bell/nanopb/generator/proto/_utils.py
  75. 872 0
      components/spotify/cspot/bell/nanopb/generator/proto/google/protobuf/descriptor.proto
  76. 179 0
      components/spotify/cspot/bell/nanopb/generator/proto/nanopb.proto
  77. 28 0
      components/spotify/cspot/bell/nanopb/generator/protoc
  78. 13 0
      components/spotify/cspot/bell/nanopb/generator/protoc-gen-nanopb
  79. 16 0
      components/spotify/cspot/bell/nanopb/generator/protoc-gen-nanopb-py2
  80. 12 0
      components/spotify/cspot/bell/nanopb/generator/protoc-gen-nanopb.bat
  81. 9 0
      components/spotify/cspot/bell/nanopb/generator/protoc.bat
  82. 42 0
      components/spotify/cspot/bell/nanopb/library.json
  83. 895 0
      components/spotify/cspot/bell/nanopb/pb.h
  84. 388 0
      components/spotify/cspot/bell/nanopb/pb_common.c
  85. 49 0
      components/spotify/cspot/bell/nanopb/pb_common.h
  86. 1713 0
      components/spotify/cspot/bell/nanopb/pb_decode.c
  87. 199 0
      components/spotify/cspot/bell/nanopb/pb_decode.h
  88. 1001 0
      components/spotify/cspot/bell/nanopb/pb_encode.c
  89. 185 0
      components/spotify/cspot/bell/nanopb/pb_encode.h
  90. 3 0
      components/spotify/cspot/bell/nanopb/spm-test/objc/c-header.c
  91. 3 0
      components/spotify/cspot/bell/nanopb/spm-test/objc/objc-header.m
  92. 1 0
      components/spotify/cspot/bell/nanopb/spm-test/objc/objc-module.m
  93. 3 0
      components/spotify/cspot/bell/nanopb/spm-test/objc/objc-qualified.m
  94. 1 0
      components/spotify/cspot/bell/nanopb/spm-test/swift/main.swift
  95. 1 0
      components/spotify/cspot/bell/nanopb/spm_headers/nanopb/pb.h
  96. 1 0
      components/spotify/cspot/bell/nanopb/spm_headers/nanopb/pb_common.h
  97. 1 0
      components/spotify/cspot/bell/nanopb/spm_headers/nanopb/pb_decode.h
  98. 1 0
      components/spotify/cspot/bell/nanopb/spm_headers/nanopb/pb_encode.h
  99. 1 0
      components/spotify/cspot/bell/nanopb/spm_headers/pb.h
  100. 1 0
      components/spotify/cspot/bell/nanopb/spm_headers/pb_common.h

+ 31 - 0
components/spotify/cspot/bell/nanopb/.gitignore

@@ -0,0 +1,31 @@
+*.gcda
+*.gcno
+*.gcov
+*.o
+*.pb.c
+*.pb.h
+*.pb
+*.pyc
+*_pb2.py
+*~
+*.tar.gz
+.sconsign.dblite
+config.log
+.sconf_temp
+tests/build
+julkaisu.txt
+dist
+docs/*.html
+docs/generator_flow.png
+examples/simple/simple
+examples/network_server/client
+examples/network_server/server
+examples/using_double_on_avr/decode_double
+examples/using_double_on_avr/encode_double
+examples/using_double_on_avr/test_conversions
+examples/using_union_messages/decode
+examples/using_union_messages/encode
+generator/nanopb_pb2.pyc
+!generator-bin/**/*
+bazel-*
+extra/poetry/build

+ 32 - 0
components/spotify/cspot/bell/nanopb/.travis.yml

@@ -0,0 +1,32 @@
+language: c
+dist: focal
+
+# Test using both gcc and clang
+env:
+    - CC=gcc     CXX=g++
+    - CC=clang   CXX=clang++
+
+addons:
+    apt:
+        packages:
+            - scons
+            - python3
+            - python3-protobuf
+            - protobuf-compiler
+
+
+before_install:
+    - export PATH=$HOME/.local/bin:$HOME/protobuf/bin:$PATH
+    - export MAKEFLAGS=-j$(nproc)
+    - $CC --version
+    - $CXX --version
+    - python --version
+    - lsb_release -a
+
+script:
+    - pushd tests && scons CC=$CC CXX=$CXX && popd
+
+notifications:
+    email:
+        recipients:
+            - jpa@travis.mail.kapsi.fi

+ 100 - 0
components/spotify/cspot/bell/nanopb/AUTHORS.txt

@@ -0,0 +1,100 @@
+Petteri Aimonen <jpa@npb.mail.kapsi.fi>
+Michael Poole <mdpoole@troilus.org>
+Daniel Kan <extremeblue99@gmail.com>
+Stan Hu <stanhu@aclimalabs.com>
+David Hotham <david.hotham@blueyonder.co.uk>
+Steffen Siering <steffen siering gmail com>
+Jens Steinhauser <jens.steinhauser@gmail.com>
+Pavel Ilin <ilin.pa@gmail.com>
+Kent Ryhorchuk <kryhorchuk@xeralux.com>
+Martin Donath <scifish@gmail.com>
+Oliver Lee <oliverzlee@gmail.com>
+Michael Haberler <git@mah.priv.at>
+Nicolas Colomer <ncolomer@viadeoteam.com>
+Ivan Kravets <me@ikravets.com>
+Kyle Manna <kyle@kylemanna.com>
+Benjamin Kamath <ben.kamath@synapse.com>
+Andrew Ruder <andrew.ruder@elecsyscorp.com>
+Kenshi Kawaguchi <kenshi@recurse.ca>
+isotes <isotes@gmail.com>
+Maxim Khitrov <max@mxcrypt.com>
+Yaniv Mordekhay <yanivmo@users.noreply.github.com>
+Ming Zhao <mzhao@luminatewireless.com>
+Google, Inc.
+Tom Roeder <tmroeder@google.com>
+Piotr Sikora <piotrsikora@google.com>
+Bernhard Krämer <bdkrae@gmail.com>
+Konstantin Podsvirov <konstantin@podsvirov.pro>
+William A. Kennington III <wak@google.com>
+Guillaume Lager <g.lager@innoseis.com>
+Tobias Haegermarck <tobias.haegermarck@gmail.com>
+Justin DeMartino <jdemarti@gmail.com>
+Constantine Grantcharov <cgrantcharov@trustpointinnovation.com>
+Nick Ewalt <nicholasewalt@google.com>
+Harald Fernengel <harryf@gmx.com>
+Alice Wang <aw@squareup.com>
+Kevin Fitch <kfitch42@gmail.com>
+Kamal Marhubi <kamal@marhubi.com>
+Elco Jacobs <elco@brewpi.com>
+Sébastien Morin <sebastien.morin@primerogames.com>
+Dave Flogeras <dflogeras2@gmail.com>
+Edward Z. Yang <ezyang@mit.edu>
+Robbie Shade <rjshade@google.com>
+Andrew Ballinger <andrewballinger@stratisopt.com>
+Hamina, Juha-Pekka <Juha-Pekka.Hamina@nordicsemi.no>
+Jason Bishop <jason.bishop@bigassfans.com>
+matejcik <ja@matejcik.cz>
+Tobias Müller <Tobias_Mueller@twam.info>
+Jari Vetoniemi <mailroxas@gmail.com>
+Gabriel Staples <ercaguy@gmail.com>
+Amarnath <amarnath.h.96@gmail.com>
+Michal Rostecki <mrostecki@suse.de>
+Pei Wang <wangpei10@baidu.com>
+Noah Pendleton <2538614+noahp@users.noreply.github.com>
+Pavol Rusnak <pavol@rusnak.io>
+der-imp <falkjan@msn.com>
+Mark Hill <markleehill@gmail.com>
+Torfinn Berset <torfinn@bloom-life.com>
+Bo Langgaard Lind <bo.langgaard.lind@gmail.com>
+Stephane Dorre <stephane.dorre@cobi.bike>
+Phillip Cao <Phillip.Cao@fphcare.co.nz>
+Melvin Wang <melvin.mc.wang@gmail.com>
+Joshua Salzedo <thHunkn0WNd@gmail.com>
+Adam Klama <klama.adam@gmail.com>
+Anton Matosov <amatosov@roblox.com>
+berni155 <bdkrae@gmail.com>
+bolind <bolind@users.noreply.github.com>
+David Lin <dtwlin@google.com>
+dch <david.hotham@blueyonder.co.uk>
+devjoa <devjoa@gmail.com>
+Evan Fisher <schleb@gmail.com>
+Fay <fay2003hiend@gmail.com>
+Florian Märkl <info@florianmaerkl.de>
+Franck <franck.sehedic@ledger.fr>
+Ilya Averyanov <i.averyanov@geoscan.aero>
+John Ullman <jrullman@google.com>
+Ket3r <peter.kempter@gmail.com>
+maciej <maciej.matuszak@gmail.com>
+Marek Zukal <marek.zukal@gmail.com>
+Paul Beusterien <paulbeusterien@google.com>
+Rogers Guedes <rogers.guedes@smdautomacao.com>
+Stefan R. Filipek <srfilipek@gmail.com>
+T. Carl Beery <beeryt@users.noreply.github.com>
+Vitali Lovich <vlovich@google.com>
+Vojtěch Boček <vbocek@gmail.com>
+Wael Nasreddine <wael.nasreddine@gmail.com>
+wangli28 <wangli28@beyondsoft.com>
+Zukaitis <gediminas.zukaitis@office.auriga.msk>
+Alex Pacini <alexpacini90@gmail.com>
+Cong <congusbongus@gmail.com>
+kurddt <kurddt@users.noreply.github.com>
+otopetrik <oto.petrik@gmail.com>
+Psy-Kai <psykai1993@googlemail.com>
+a1lu <a1lu@users.noreply.github.com>
+L <46594312+WakandaO2@users.noreply.github.com>
+Melvin Wang <mwang@sibros.tech>
+Tim Gates <tim.gates@iress.com>
+leabut <leabut@users.noreply.github.com>
+Angel ILIEV <a.v.iliev13@gmail.com>
+Jakub Tymejczyk <jakub@tymejczyk.pl>
+Matthew Simmons <simmonmt@acm.org>

+ 21 - 0
components/spotify/cspot/bell/nanopb/BUILD.bazel

@@ -0,0 +1,21 @@
+licenses(["notice"])
+
+exports_files(["LICENSE.txt"])
+
+package(default_visibility = ["//visibility:public"])
+
+cc_library(
+    name = "nanopb",
+    srcs = [
+        "pb_common.c",
+        "pb_decode.c",
+        "pb_encode.c",
+    ],
+    hdrs = [
+        "pb.h",
+        "pb_common.h",
+        "pb_decode.h",
+        "pb_encode.h",
+    ],
+    visibility = ["//visibility:public"],
+)

+ 522 - 0
components/spotify/cspot/bell/nanopb/CHANGELOG.txt

@@ -0,0 +1,522 @@
+nanopb-0.4.5 (2021-03-22)
+ Fix invalid free() with oneof (#647, GHSA-7mv5-5mxh-qg88)
+ Fix unordered field numbers inside oneof causing fields to be ignored (#617)
+ Fix pb_decode() not initializing fields inside oneof (#635
+ Fix compiler errors with complex oneof hierarchy and sizeof() (#610)
+ Fix descriptor width calculation for 64-bit types (#644)
+ Fix compiler error in generated initializer for submessage callback (#631)
+ Fix duplicate union definition in generated file (#637)
+ Fix test case build error on SCons 4.1.0
+ Pip package: include nanopb_pb2.py (#629)
+ Make generator consider dependencies recursively (#610)
+ Bazel build system updates (#633)
+ Add support for including comments from .proto file (#85, #645)
+
+nanopb-0.4.4 (2020-11-25)
+ Fix memory leak with oneofs and PB_ENABLE_MALLOC (#615, GHSA-85rr-4rh9-hhwh)
+ Fix generator error when oneof contains a single unresolved field size (#610)
+ Fix unsigned enums not working correctly inside OneOf (#611)
+ Fix recursion depth exceeded error in generator (#493)
+ Add '--version' option to nanopb_generator.py (#607)
+ Add support for proto3 optional fields introduced in protoc 3.12 (#591)
+ Add better error message when enum type is not found (#592)
+ Allow specifying descriptorsize on field level also (#546)
+ Allow multiple targets to be created by calling NANOPB_GENERATE_CPP() (#596)
+ Conanfile: Add protobuf-nanopb library to cpp_info.libs (#605)
+ Include version number in generator verbose output
+ Convert documentation to markdown format (#587)
+ Remove outdated transitional generator/nanopb/options.proto.
+ Test case improvements
+ Documentation improvements
+
+nanopb-0.4.3 (2020-09-21)
+ Fix generator error when output is in current directory (#553)
+ Fix issue with unknown message sizes being referred inside oneof encoded size calculation (#569)
+ Fix problem with [default=xxxx, (nanopb).proto3=true] field option combination (#558)
+ Fix cross compilation with Conan build system (#568)
+ Better support C++ types in generated structs (#577)
+ CMake rule improvements (#554, #555, #556, #561, #564)
+ Generator: fix compatibility bug with Python 3.1 and earlier
+ Make Linux and Mac packages use grpcio protoc
+ Make pb_decode_varint32() reject overlong varint encodings.
+ Performance optimizations
+ Test case improvements
+ Documentation improvements
+
+NOTE: version 0.4.3 changes layout of pb_msgdesc_t. It requires recompiling .pb.c files and
+thus breaks ABI compatibility. In general, ABI compatibility is not currently maintained
+between any nanopb versions.
+
+NOTE: There was an apparent false positive virus identification by Windows Defender of the
+PyInstaller 3.6 based Windows package nanopb-0.4.3-windows-x86.zip. The package was replaced
+by nanopb-0.4.3-p1-windows-x86.zip with rebuilt PyInstaller 4.0, which seems to avoid the problem.
+Actual nanopb code is unchanged between the packages.
+
+nanopb-0.4.2 (2020-06-23)
+ Fix buffer overflow when encoding bytes with size set to 65535 (#547, GHSA-3p39-mfxg-hrq4)
+ Fix segfault with pointer fields and proto3_singular_msgs = true. (#504,#505)
+ Fix Windows 10 temp file handling (#486)
+ Fix macro name conflicts (ATMEGA32U4 UENUM and more) (#522)
+ Fix generator error with nested messages and default values (#487)
+ Fix nanopb_generator exception on enums with aliases (#535)
+ Fix compile error when struct members are called X or a (#492)
+ Fix sizeof(union ...) fallback not compiling with C++ (#415, #494)
+ Fix "missing required field" error with submessage callback (#544)
+ Fix field descriptor sizing with submsg_callback option (#545)
+ Fix protoc calling on Python 2 (#503)
+ Fix handling of varying NaN representations in PB_CONVERT_DOUBLE_FLOAT (#543)
+ Fix clang undefined behavior sanitizer errors.
+ Change generator to use Python 3 by default (#441, #509)
+ Binary packages updated to use Python 3 and grpcio-tools
+ Add support for infinity and nan floating-point defaults (#530, #538)
+ Add generator option sort_by_tag (#542)
+ Add type_override option to override type defined in .proto (#497)
+ Set proto2 enum fields to first value when no default is given, even if nonzero (#532,#539)
+ Include protoc-gen-nanopb in path in protoc wrapper script
+ Properly pass error status from protoc wrapper when calling binary protoc
+ Generator: pass --include_imports when calling protoc (#494)
+ Create intermediate directories when writing files to relative path (#512)
+ Add current directory to include path for protoc (#499)
+ Update readme to use nanopb_generator.py directly
+ Regression test for proto3 incorrectly considered empty (#504)
+ CMake: change package name to Nanopb for cmake 3.17 compatibility (#506)
+ CMake: remove find_package(PythonInterp) (#508)
+ CMake: use split --nanopb_opt only on protoc >= 3.6 (#515)
+ CMake: Relax python version spec, allowing Python3. (#534)
+ Swift package manager (#549)
+ Rename BUILD as BUILD.bazel (#537)
+
+Note: Windows binary packages in 0.4.2 and later require Windows 7 or newer.
+
+nanopb-0.4.1 (2020-02-02)
+ Fix invalid free() after failed realloc() (GHSA-gcx3-7m76-287p)
+ Avoid overflows in allocation for packed fields.
+ Verify stream size before allocating string / bytes.
+ Add workaround for avr-libc realloc() bug (#475)
+ Fix bug with field numbers >255 (#407)
+ Fix compilation error on platforms without uint8_t (#485)
+ Fix warnings on Python3.8 (#399, #467)
+ Make fixed_count option work when combined with FT_POINTER.
+ Add missing #define for submsg callbacks, add regression test (#472)
+ Fix ImportError when using generator/protoc with Python 3
+ Remove accidental debug code in generator
+ Reduce stack usage (#484)
+ Remove PB_FIELDINFO_WIDTH option (#473)
+ Add nanopb-specific package name option (#422)
+ Add testcase for Any type (#163)
+ Add exclude option also from .proto/.options
+ Set default include path in the grpc_tools protoc wrapper.
+ Add workaround for python-protobuf 3.6.1 bug (#478)
+ Detect invalid wire type when decoding fields.
+ Improved fuzz testing
+
+nanopb-0.4.0 (2019-12-20)
+ New field descriptor format.
+ Make nanopb_generator automatically compile .proto files (#462)
+ Allow installing as Python package from pip (#460)
+ Use protoc from grpcio-tools Python package if available (#463)
+ Change proto3 message types to be optional (#308, #452)
+ Add pb_decode_ex(), pb_encode_ex() functions.
+ Automatically rebuild nanopb_pb2.py
+ Use plugin.proto that comes with python-protobuf (#234)
+
+ Allow specifying a per-message callback. (#175)
+ Improve callback handling inside oneofs. (#175)
+
+ Introduce new compile time flag: PB_VALIDATE_UTF8 (#437)
+ Add TypenameMangling.M_PACKAGE_INITIALS (#394)
+ Introduce new compile time flag: PB_ENCODE_ARRAYS_UNPACKED (#427)
+ Add default_has option (#423)
+ Add option for including extra files from .pb.h
+ Add generator option to error out on unmatched options (#458)
+ Generator: Allow comma separated options in plugin mode (#343)
+ Allow comma-separated option parsing to handle `#include` (#450)
+ Remove timestamp from generated files by default, add -t to keep it.
+ Make --no-strip-path default (#326)
+ Fix .options file case sensitivity on Windows.
+ Fix generator error with mangle_names option (#380)
+ Take int_size setting into account in calculating message sizes (#373)
+ .gitignore: don't ignore generator-bin files (#419)
+ Cleanup .pb.h header format
+
+ Make tests run on AVR and STM32
+ Add PB_CONVERT_DOUBLE_FLOAT setting to convert doubles on AVR.
+ Store field descriptor constants in flash on AVR (#464)
+ Added "f" suffix to const float declarations. (#453)
+ Fix clang-tidy warnings about using signed integers in binary bitwise operations (#451)
+ Add C++ message descriptors helper (#384)
+ Implement conan recipe (#378)
+ CMake: Split nanopb_out command (#454)
+ CMake: install created shared library(dll) in windows to the binary folder (#447)
+
+nanopb-0.3.9.8 (2021-03-22)
+ Fix invalid free() with oneof (#647, GHSA-7mv5-5mxh-qg88)
+ Don't generate lines with trailing spaces (#622)
+ Verify stream size before allocating string / bytes (#620)
+
+nanopb-0.3.9.7 (2020-11-25)
+ Fix memory leak with oneofs and PB_ENABLE_MALLOC (#615, GHSA-85rr-4rh9-hhwh)
+ Fix unsigned enums not working correctly inside OneOf (#611)
+ Add '--version' option to nanopb_generator.py (#607)
+ SwiftPM rule updates (#567, #585)
+
+nanopb-0.3.9.6 (2020-06-23)
+ Fix buffer overflow when encoding bytes with size set to 65535 (#547, GHSA-3p39-mfxg-hrq4)
+ Fix proto3 submessage improperly considered empty (#504)
+ Fix ImportError when using generator/protoc with Python 3
+ Add build rules for Swift package manager (#549)
+
+nanopb-0.3.9.5 (2020-02-02)
+ Fix invalid free() after failed realloc() (GHSA-gcx3-7m76-287p)
+ Add workaround for avr-libc realloc() bug (#475)
+ Fix empty submessages getting encoded in proto3 mode (#395)
+ Avoid overflows in allocation for packed fields.
+
+nanopb-0.3.9.4 (2019-10-13)
+ Fix undefined behavior with bool fields (#434)
+ Fix enum min/max defines when values are not in order (#405)
+ Fix network_server socket example with zero-length strings (#421)
+ Don't call stream read callback with count=0 (#421)
+ Add compile time flag PB_ENCODE_ARRAYS_UNPACKED (#427)
+
+nanopb-0.3.9.3 (2019-03-08)
+ NOTE: nanopb-0.3.9.3.tar.gz before 2019-03-21 was accidentally from 0.4 branch (#388)
+ Fix fixed size and callback repeated fields inside proto3 submessages (#376, #382, #386)
+ Fix incorrect PB_STATIC_ASSERT for bytes inside oneof (#363)
+ Fix generator error with mangle_names option (#380)
+ Generator: Allow comma separated options in plugin mode (#343)
+
+nanopb-0.3.9.2 (2018-11-10)
+ Erroneous free() when using callbacks combined with PB_ENABLE_MALLOC (#346)
+ Fix possible null-pointer dereference in decode_callback_field (#342)
+ Fix FindNanopb.cmake on Windows (#335)
+ Fix large generator memory usage with oneof fields (#338)
+ Fix error in splint test (#359)
+ Allow cmake to build as a shared library (#352, #353)
+ Add --no-strip-path command line option (#326)
+ Option for flattening nested protobuf names (#333)
+ Documentation fixes (#329, #350, #358)
+ Better error messages (#351)
+
+nanopb-0.3.9.1 (2018-04-14)
+ Fix handling of special characters in string/bytes default values (issue #322)
+ Fix encoding of negative numbers with PB_WITHOUT_64BIT (#285)
+ Fix _zero initializer for enums that don't begin at 0. (#295)
+ Multiple CMake fixes (#296, #299, #304, #312, #320)
+ Fix compiler warnings (#305)
+ Fix scons rules for Python 3
+ Add check for large extension field number (issue #306)
+ Updated included descriptor.proto version (#314)
+ Resolve oneof sizes symbolically when needed (#311)
+ Add fixed_count option (#260)
+ Add some verbose prints in generator (issue #238)
+ Add test/example of using 'map' type. (#289)
+
+nanopb-0.3.9 (2017-09-23)
+ Fix bugs in proto3 encoding of submessages (#256)
+ Fix message size calculation for arrays of size 1 (#253)
+ Fix segfault with FT_CALLBACK inside FT_POINTER (#259)
+ Properly detect truncated tags in corrupted messages (#277)
+ Make pb_decode_varint32 overflow checks exact (#258)
+ Add option to build without 64-bit support (#86)
+ Add options to define source and header file extensions (#264)
+ Add pb_en/decode_nullterminated() (part of #278)
+ Add pb_decode_delimited_noinit (#284)
+ CMake: add dependency for .options file (#265)
+ CMake: change use of relative paths (#250,#271,#273)
+ Better error message for missing max_size option (#281)
+ Travis-CI build fixes (#283)
+ Add Bazel build system file (#266)
+
+nanopb-0.3.8 (2017-03-05)
+ Fix problems with multiple oneofs in same message (#229)
+ Zero-valued extension fields were mistakenly ignored by encoder (#242)
+ Multiple fixes related to proto3 mode (#242, #245, #247, #249)
+ Fix potential unaligned access (#226, #227)
+ Fix documentation for protoc --plugin argument (#239)
+ Extend inline / fixed length bytes array support (#244)
+ Add new option max_length for strings (#107)
+ Make string substream API more robust (#230)
+ Make pb_decode_varint32 public API (#231)
+ Allow overriding proto3 mode (#228)
+ Add optional enum->string mapping function (#223)
+ Add transitional options.proto file (#241)
+ Add better error message on Python library version incompatibility (#240)
+ Include version number in PlatformIO library.json (#222)
+ CMake build script changes (#236, #237)
+ Change download links to https
+ Improvements to test cases.
+
+nanopb-0.3.7 (2016-10-30)
+ Add support for proto3-style singular fields (#182, #206, #216)
+ Updated binary package protoc to version 3.1.0
+ Add FT_INLINE allocation of bytes fields (#211)
+ Include package name in include guard (#207)
+ Fix missing warning with large bytes fields (issue #220)
+ Added CMake project (#208)
+ Add bazel BUILD file for nanopb (#209)
+ Added an AUTHORS file (#211)
+ Documentation updates
+ Improvements to test cases.
+
+nanopb-0.3.6 (2016-06-19)
+ Protect against corrupted _count fields in pb_release (#205)
+ Fix error in STATIC_ASSERT with multiple files (#203)
+ Add -D option to specify output directory (#193)
+ Generate MIN/MAX/ARRAYSIZE defines for enums (#194)
+ Generate comments about uncalculable message sizes (#195)
+ Documentation updates (#196, #201)
+ Improvements to test cases.
+
+nanopb-0.3.5 (2016-02-13)
+ NOTE: If you are using pb_syshdr.h, you will need to add uint_least8_t
+ definition. See docs/migration.rst for details.
+
+ Fix generator crash with Enum inside Oneof (#188)
+ Fix some generator regressions related to .options file path (#172)
+ Add support for platforms without uint8_t (#191)
+ Allow const parameter to pb_istream_from_buffer (#152)
+ Ignore null pointers in pb_release() (#183)
+ Add support for anonymous unions (#184)
+ Add Python3 support to the generator (#169)
+ Add code generator insertion points to generated files (#178)
+ Improvements to CMake script (#181)
+ Improvements to test cases.
+
+nanopb-0.3.4 (2015-09-26)
+ Fix handling of unsigned 8- and 16-bit enums (issue 164)
+ Fix generator on systems where python = python3. (issue 155)
+ Fix compiler warning on GCC 5.x (issue 171)
+ Make the generator better handle imported .protos (issue 165)
+ Add packed_enum option to generator.
+ Add syntax= line to .proto files (issue 167)
+ Add PlatformIO registry manifest file. (pr 156)
+
+nanopb-0.3.3 (2015-04-10)
+ Fix missing files in Linux binary package (issue 146)
+ Fix generator bug when oneof is first field in a message. (issue 142)
+ Fix generator error when long_names:false is combined with Oneofs. (issue 147)
+ Fix oneof submessage initialization bug. (issue 149)
+ Fix problem with plugin options on Python 2.7.2 and older. (issue 153)
+ Fix crash when callback is inside oneof field. (issue 148)
+ Switch to .tar.gz format for Mac OS X packages. (issue 154)
+ Always define enum long names so that cross-file references work. (issue 118)
+ Add msgid generator option. (issue 151)
+ Improve comment support in .options files. (issue 145)
+ Updates for the CMake rule file, add cmake example.
+ Better error messages for syntax errors in .options file
+
+nanopb-0.3.2 (2015-01-24)
+ Fix memory leaks with PB_ENABLE_MALLOC with some submessage hierarchies (issue 138)
+ Implement support for oneofs (C unions). (issues 131, 141)
+ Add int_size option for generator (issue 139)
+ Add compilation option to disable struct packing. (issue 136)
+ Change PB_RETURN_ERROR() macro to avoid compiler warnings (issue 140)
+ Fix build problems with protoc 3.0.0
+ Add support for POINTER type in extensions
+ Initialize also extension fields to defaults in pb_decode().
+ Detect too large varint values when decoding.
+
+nanopb-0.3.1 (2014-09-11)
+ Fix security issue due to size_t overflows. (issue 132)
+ Fix memory leak with duplicated fields and PB_ENABLE_MALLOC
+ Fix crash if pb_release() is called twice.
+ Fix cyclic message support (issue 130)
+ Fix error in generated initializers for repeated pointer fields.
+ Improve tests (issues 113, 126)
+
+nanopb-0.3.0 (2014-08-26)
+ NOTE: See docs/migration.html or online at
+ http://koti.kapsi.fi/~jpa/nanopb/docs/migration.html
+ for changes in this version. Most importantly, you need to add
+ pb_common.c to the list of files to compile.
+
+ Separated field iterator logic to pb_common.c (issue 128)
+ Change the _count fields to use pb_size_t datatype (issue 82)
+ Added PB_ prefix to macro names (issue 106)
+ Added #if version guard to generated files (issue 129)
+ Added migration document
+
+nanopb-0.2.9.5 (2020-06-23)
+ Fix buffer overflow when encoding bytes with size set to 65535 (#547, GHSA-3p39-mfxg-hrq4)
+ Backport Python 3 and protoc 3.x fixes to test cases
+
+nanopb-0.2.9.4 (2020-02-02)
+ Fix invalid free() after failed realloc() (GHSA-gcx3-7m76-287p)
+ Add workaround for avr-libc realloc() bug (#475)
+
+nanopb-0.2.9.3 (2016-06-19)
+ Protect against corrupted _count fields in pb_release (#205)
+
+nanopb-0.2.9.2 (2015-01-24)
+ Fix memory leaks with PB_ENABLE_MALLOC with some submessage hierarchies (issue 138)
+ Fix compilation error with generated initializers for repeated pointer fields
+
+nanopb-0.2.9.1 (2014-09-11)
+ Fix security issue due to size_t overflows. (issue 132)
+ Fix memory leak with duplicated fields and PB_ENABLE_MALLOC
+ Fix crash if pb_release() is called twice.
+
+nanopb-0.2.9 (2014-08-09)
+ NOTE: If you are using the -e option with the generator, you have
+ to prepend . to the argument to get the same behaviour as before.
+
+ Do not automatically add a dot with generator -e option. (issue 122)
+ Fix problem with .options file and extension fields. (issue 125)
+ Don't use SIZE_MAX macro, as it is not in C89. (issue 120)
+ Generate #defines for initializing message structures. (issue 79)
+ Add skip_message option to generator. (issue 121)
+ Add PB_PACKED_STRUCT support for Keil MDK-ARM toolchain (issue 119)
+ Give better messages about the .options file path. (issue 124)
+ Improved tests
+
+nanopb-0.2.8 (2014-05-20)
+ Fix security issue with PB_ENABLE_MALLOC. (issue 117)
+ Add option to not add timestamps to .pb.h and .pb.c preambles. (issue 115)
+ Documentation updates
+ Improved tests
+
+nanopb-0.2.7 (2014-04-07)
+ Fix bug with default values for extension fields (issue 111)
+ Fix some MISRA-C warnings (issue 91)
+ Implemented optional malloc() support (issue 80)
+ Changed pointer-type bytes field datatype
+ Add a "found" field to pb_extension_t (issue 112)
+ Add convenience function pb_get_encoded_size() (issue 16)
+
+nanopb-0.2.6 (2014-02-15)
+ Fix generator error with bytes callback fields (issue 99)
+ Fix warnings about large integer constants (issue 102)
+ Add comments to where STATIC_ASSERT is used (issue 96)
+ Add warning about unknown field names on .options (issue 105)
+ Move descriptor.proto to google/protobuf subdirectory (issue 104)
+ Improved tests
+
+nanopb-0.2.5 (2014-01-01)
+ Fix a bug with encoding negative values in int32 fields (issue 97)
+ Create binary packages of the generator + dependencies (issue 47)
+ Add support for pointer-type fields to the encoder (part of issue 80)
+ Fixed path in FindNanopb.cmake (issue 94)
+ Improved tests
+
+nanopb-0.2.4 (2013-11-07)
+ Remove the deprecated NANOPB_INTERNALS functions from public API.
+ Document the security model.
+ Check array and bytes max sizes when encoding (issue 90)
+ Add #defines for maximum encoded message size (issue 89)
+ Add #define tags for extension fields (issue 93)
+ Fix MISRA C violations (issue 91)
+ Clean up pb_field_t definition with typedefs.
+
+nanopb-0.2.3 (2013-09-18)
+ Improve compatibility by removing ternary operator from initializations (issue 88)
+ Fix build error on Visual C++ (issue 84, patch by Markus Schwarzenberg)
+ Don't stop on unsupported extension fields (issue 83)
+ Add an example pb_syshdr.h file for non-C99 compilers
+ Reorganize tests and examples into subfolders (issue 63)
+ Switch from Makefiles to scons for building the tests
+ Make the tests buildable on Windows
+
+nanopb-0.2.2 (2013-08-18)
+ Add support for extension fields (issue 17)
+ Fix unknown fields in empty message (issue 78)
+ Include the field tags in the generated .pb.h file.
+ Add pb_decode_delimited and pb_encode_delimited wrapper functions (issue 74)
+ Add a section in top of pb.h for changing compilation settings (issue 76)
+ Documentation improvements (issues 12, 77 and others)
+ Improved tests
+
+nanopb-0.2.1 (2013-04-14)
+ NOTE: The default callback function signature has changed.
+       If you don't want to update your code, define PB_OLD_CALLBACK_STYLE.
+ 
+ Change the callback function to use void** (issue 69)
+ Add support for defining the nanopb options in a separate file (issue 12)
+ Add support for packed structs in IAR and MSVC (in addition to GCC) (issue 66)
+ Implement error message support for the encoder side (issue 7)
+ Handle unterminated strings when encoding (issue 68)
+ Fix bug with empty strings in repeated string callbacks (issue 73)
+ Fix regression in 0.2.0 with optional callback fields (issue 70)
+ Fix bugs with empty message types (issues 64, 65)
+ Fix some compiler warnings on clang (issue 67)
+ Some portability improvements (issues 60, 62)
+ Various new generator options
+ Improved tests
+
+nanopb-0.2.0 (2013-03-02)
+ NOTE: This release requires you to regenerate all .pb.c
+       files. Files generated by older versions will not
+       compile anymore.
+
+ Reformat generated .pb.c files using macros (issue 58)
+ Rename PB_HTYPE_ARRAY -> PB_HTYPE_REPEATED
+ Separate PB_HTYPE to PB_ATYPE and PB_HTYPE
+ Move STATIC_ASSERTs to .pb.c file
+ Added CMake file (by Pavel Ilin)
+ Add option to give file extension to generator (by Michael Haberler)
+ Documentation updates
+
+nanopb-0.1.9 (2013-02-13)
+ Fixed error message bugs (issues 52, 56)
+ Sanitize #ifndef filename (issue 50)
+ Performance improvements
+ Add compile-time option PB_BUFFER_ONLY
+ Add Java package name to nanopb.proto
+ Check for sizeof(double) == 8 (issue 54)
+ Added generator option to ignore some fields. (issue 51)
+ Added generator option to make message structs packed. (issue 49)
+ Add more test cases.
+
+nanopb-0.1.8 (2012-12-13)
+ Fix bugs in the enum short names introduced in 0.1.7 (issues 42, 43)
+ Fix STATIC_ASSERT macro when using multiple .proto files. (issue 41)
+ Fix missing initialization of istream.errmsg
+ Make tests/Makefile work for non-gcc compilers (issue 40)
+
+nanopb-0.1.7 (2012-11-11)
+ Remove "skip" mode from pb_istream_t callbacks. Example implementation had a bug. (issue 37)
+ Add option to use shorter names for enum values (issue 38)
+ Improve options support in generator (issues 12, 30)
+ Add nanopb version number to generated files (issue 36)
+ Add extern "C" to generated headers (issue 35)
+ Add names for structs to allow forward declaration (issue 39)
+ Add buffer size check in example (issue 34)
+ Fix build warnings on MS compilers (issue 33)
+
+nanopb-0.1.6 (2012-09-02)
+ Reorganize the field decoder interface (issue 2)
+ Improve performance in submessage decoding (issue 28)
+ Implement error messages in the decoder side (issue 7)
+ Extended testcases (alltypes test is now complete).
+ Fix some compiler warnings (issues 25, 26, 27, 32).
+
+nanopb-0.1.5 (2012-08-04)
+ Fix bug in decoder with packed arrays (issue 23).
+ Extended testcases.
+ Fix some compiler warnings.
+
+nanopb-0.1.4 (2012-07-05)
+ Add compile-time options for easy-to-use >255 field support.
+ Improve the detection of missing required fields.
+ Added example on how to handle union messages.
+ Fix generator error with .proto without messages.
+ Fix problems that stopped the code from compiling with some compilers.
+ Fix some compiler warnings.
+
+nanopb-0.1.3 (2012-06-12)
+ Refactor the field encoder interface.
+ Improve generator error messages (issue 5)
+ Add descriptor.proto into the #include exclusion list
+ Fix some compiler warnings.
+
+nanopb-0.1.2 (2012-02-15)
+ Make the generator to generate include for other .proto files (issue 4).
+ Fixed generator not working on Windows (issue 3)
+
+nanopb-0.1.1 (2012-01-14)
+ Fixed bug in encoder with 'bytes' fields (issue 1).
+ Fixed a bug in the generator that caused a compiler error on sfixed32 and sfixed64 fields.
+ Extended testcases.
+
+nanopb-0.1.0 (2012-01-06)
+ First stable release.

+ 143 - 0
components/spotify/cspot/bell/nanopb/CMakeLists.txt

@@ -0,0 +1,143 @@
+cmake_minimum_required(VERSION 2.8.12)
+
+project(nanopb C)
+
+set(nanopb_VERSION_STRING nanopb-0.4.6-dev)
+set(nanopb_SOVERSION 0)
+
+string(REPLACE "nanopb-" "" nanopb_VERSION ${nanopb_VERSION_STRING})
+
+option(BUILD_SHARED_LIBS "Build shared libraries" OFF)
+option(BUILD_STATIC_LIBS "Build static libraries" ON)
+
+option(nanopb_BUILD_RUNTIME "Build the headers and libraries needed at runtime" ON)
+option(nanopb_BUILD_GENERATOR "Build the protoc plugin for code generation" ON)
+option(nanopb_MSVC_STATIC_RUNTIME "Link static runtime libraries" ON)
+
+find_program(nanopb_PROTOC_PATH protoc)
+if(NOT EXISTS ${nanopb_PROTOC_PATH})
+    message(FATAL_ERROR "protoc compiler not found")
+endif()
+
+if(NOT DEFINED CMAKE_DEBUG_POSTFIX)
+    set(CMAKE_DEBUG_POSTFIX "d")
+endif()
+
+include(GNUInstallDirs)
+
+if(MSVC AND nanopb_MSVC_STATIC_RUNTIME)
+    foreach(flag_var
+            CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE
+            CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO)
+        if(${flag_var} MATCHES "/MD")
+            string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}")
+        endif(${flag_var} MATCHES "/MD")
+    endforeach(flag_var)
+endif()
+
+if(NOT DEFINED CMAKE_INSTALL_CMAKEDIR)
+    set(CMAKE_INSTALL_CMAKEDIR "${CMAKE_INSTALL_LIBDIR}/cmake/nanopb")
+endif()
+
+find_package(Python REQUIRED COMPONENTS Interpreter)
+execute_process(
+    COMMAND ${Python_EXECUTABLE} -c
+        "import os.path, sys, sysconfig; print(os.path.relpath(sysconfig.get_path('purelib'), start=sys.prefix))"
+    OUTPUT_VARIABLE PYTHON_INSTDIR
+    OUTPUT_STRIP_TRAILING_WHITESPACE
+)
+
+if(nanopb_BUILD_GENERATOR)
+    set(generator_protos nanopb)
+
+    foreach(generator_proto IN LISTS generator_protos)
+        string(REGEX REPLACE "([^;]+)" "${PROJECT_SOURCE_DIR}/generator/proto/\\1.proto" generator_proto_file "${generator_proto}")
+        string(REGEX REPLACE "([^;]+)" "\\1_pb2.py" generator_proto_py_file "${generator_proto}")
+        add_custom_command(
+            OUTPUT ${generator_proto_py_file}
+            COMMAND ${nanopb_PROTOC_PATH} --python_out=${PROJECT_BINARY_DIR} -I${PROJECT_SOURCE_DIR}/generator/proto ${generator_proto_file}
+            DEPENDS ${generator_proto_file}
+        )
+        add_custom_target("generate_${generator_proto_py_file}" ALL DEPENDS ${generator_proto_py_file})
+        install(
+            FILES ${PROJECT_BINARY_DIR}/${generator_proto_py_file}
+                  ${generator_proto_file}
+            DESTINATION ${PYTHON_INSTDIR}/proto/
+        )
+    endforeach()
+endif()
+
+install(FILES generator/proto/_utils.py
+        DESTINATION ${PYTHON_INSTDIR}/proto/)
+
+if(WIN32)
+    install(
+        PROGRAMS
+            generator/nanopb_generator.py
+            generator/protoc-gen-nanopb.bat
+        DESTINATION ${CMAKE_INSTALL_BINDIR}
+    )
+else()
+    install(
+        PROGRAMS
+            generator/nanopb_generator.py
+            generator/protoc-gen-nanopb
+        DESTINATION ${CMAKE_INSTALL_BINDIR}
+    )
+endif()
+
+if(nanopb_BUILD_RUNTIME)
+    if(BUILD_SHARED_LIBS)
+        add_library(protobuf-nanopb SHARED
+            pb.h
+            pb_common.h
+            pb_common.c
+            pb_encode.h
+            pb_encode.c
+            pb_decode.h
+            pb_decode.c)
+        set_target_properties(protobuf-nanopb PROPERTIES
+            SOVERSION ${nanopb_SOVERSION})
+        install(TARGETS protobuf-nanopb EXPORT nanopb-targets
+            ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
+            LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
+            RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
+        target_include_directories(protobuf-nanopb INTERFACE
+            $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
+            $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
+        )
+    endif()
+
+    if(BUILD_STATIC_LIBS)
+        add_library(protobuf-nanopb-static STATIC
+            pb.h
+            pb_common.h
+            pb_common.c
+            pb_encode.h
+            pb_encode.c
+            pb_decode.h
+            pb_decode.c)
+        set_target_properties(protobuf-nanopb-static PROPERTIES
+            OUTPUT_NAME protobuf-nanopb)
+        install(TARGETS protobuf-nanopb-static EXPORT nanopb-targets
+            ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
+        target_include_directories(protobuf-nanopb-static INTERFACE
+            $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
+	        $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
+        )
+    endif()
+
+    configure_file(extra/nanopb-config-version.cmake.in
+        nanopb-config-version.cmake @ONLY)
+
+    install(EXPORT nanopb-targets
+        DESTINATION ${CMAKE_INSTALL_CMAKEDIR}
+        NAMESPACE nanopb::)
+
+    install(FILES extra/nanopb-config.cmake
+        ${CMAKE_CURRENT_BINARY_DIR}/nanopb-config-version.cmake
+        DESTINATION ${CMAKE_INSTALL_CMAKEDIR})
+
+    install(FILES pb.h pb_common.h pb_encode.h pb_decode.h
+        DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
+endif()

+ 32 - 0
components/spotify/cspot/bell/nanopb/CONTRIBUTING.md

@@ -0,0 +1,32 @@
+Contributing to Nanopb development
+==================================
+
+Reporting issues and requesting features
+----------------------------------------
+
+Feel free to report any issues you see or features you would like
+to see in the future to the Github issue tracker. Using the templates
+below is preferred:
+
+* [Report a bug](https://github.com/nanopb/nanopb/issues/new?body=**Steps%20to%20reproduce%20the%20issue**%0a%0a1.%0a2.%0a3.%0a%0a**What%20happens?**%0A%0A**What%20should%20happen?**&labels=Type-Defect)
+* [Request a feature](https://github.com/nanopb/nanopb/issues/new?body=**What%20should%20the%20feature%20do?**%0A%0A**In%20what%20situation%20would%20the%20feature%20be%20useful?**&labels=Type-Enhancement)
+
+Requesting help
+---------------
+
+If there is something strange going on, but you do not know if
+it is actually a bug in nanopb, try asking first on the
+[discussion forum](https://groups.google.com/forum/#!forum/nanopb).
+
+Pull requests
+-------------
+
+Pull requests are welcome!
+
+If it is not obvious from the commit message, please indicate the
+same information as you would for an issue report:
+
+* What functionality it fixes/adds.
+* How can the problem be reproduced / when would the feature be useful.
+
+

+ 20 - 0
components/spotify/cspot/bell/nanopb/LICENSE.txt

@@ -0,0 +1,20 @@
+Copyright (c) 2011 Petteri Aimonen <jpa at nanopb.mail.kapsi.fi>
+
+This software is provided 'as-is', without any express or 
+implied warranty. In no event will the authors be held liable 
+for any damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any 
+purpose, including commercial applications, and to alter it and 
+redistribute it freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you 
+   must not claim that you wrote the original software. If you use 
+   this software in a product, an acknowledgment in the product 
+   documentation would be appreciated but is not required.
+
+2. Altered source versions must be plainly marked as such, and 
+   must not be misrepresented as being the original software.
+
+3. This notice may not be removed or altered from any source 
+   distribution.

+ 63 - 0
components/spotify/cspot/bell/nanopb/Package.swift

@@ -0,0 +1,63 @@
+// swift-tools-version:5.0
+// The swift-tools-version declares the minimum version of Swift required to build this package.
+
+import PackageDescription
+
+let package = Package(
+  name: "nanopb",
+  products: [
+    .library(
+      name: "nanopb",
+      targets: ["nanopb"]
+    )
+  ],
+
+  targets: [
+    .target(
+      name: "nanopb",
+      path: ".",
+      sources: [
+        "pb.h",
+        "pb_common.h",
+        "pb_common.c",
+        "pb_decode.h",
+        "pb_decode.c",
+        "pb_encode.h",
+        "pb_encode.c"
+      ],
+      publicHeadersPath: "spm_headers",
+      cSettings: [
+        .define("PB_FIELD_32BIT", to: "1"),
+        .define("PB_NO_PACKED_STRUCTS", to: "1"),
+        .define("PB_ENABLE_MALLOC", to: "1"),
+      ]
+    ),
+    .testTarget(
+      name: "swift-test",
+      dependencies: [
+        "nanopb",
+      ],
+      path: "spm-test/swift",
+      cSettings: [
+        .headerSearchPath("../"),
+        .define("PB_FIELD_32BIT", to: "1"),
+        .define("PB_NO_PACKED_STRUCTS", to: "1"),
+        .define("PB_ENABLE_MALLOC", to: "1"),
+      ]
+    ),
+    .testTarget(
+      name: "objc-test",
+      dependencies: [
+        "nanopb",
+      ],
+      path: "spm-test/objc",
+      cSettings: [
+        .headerSearchPath("../"),
+        .define("PB_FIELD_32BIT", to: "1"),
+        .define("PB_NO_PACKED_STRUCTS", to: "1"),
+        .define("PB_ENABLE_MALLOC", to: "1"),
+      ]
+    )
+  ]
+)
+

+ 108 - 0
components/spotify/cspot/bell/nanopb/README.md

@@ -0,0 +1,108 @@
+Nanopb - Protocol Buffers for Embedded Systems
+==============================================
+
+[![Build Status](https://travis-ci.com/nanopb/nanopb.svg?branch=master)](https://travis-ci.com/nanopb/nanopb)
+
+Nanopb is a small code-size Protocol Buffers implementation in ansi C. It is
+especially suitable for use in microcontrollers, but fits any memory
+restricted system.
+
+* **Homepage:** https://jpa.kapsi.fi/nanopb/
+* **Documentation:** https://jpa.kapsi.fi/nanopb/docs/
+* **Downloads:** https://jpa.kapsi.fi/nanopb/download/
+* **Forum:** https://groups.google.com/forum/#!forum/nanopb
+* **Nightly builds:** https://jpa.kapsi.fi/jenkins/job/nanopb/
+
+
+Using the nanopb library
+------------------------
+To use the nanopb library, you need to do two things:
+
+1. Compile your .proto files for nanopb, using `protoc`.
+2. Include *pb_encode.c*, *pb_decode.c* and *pb_common.c* in your project.
+
+The easiest way to get started is to study the project in "examples/simple".
+It contains a Makefile, which should work directly under most Linux systems.
+However, for any other kind of build system, see the manual steps in
+README.txt in that folder.
+
+
+Generating the headers
+----------------------
+Protocol Buffers messages are defined in a `.proto` file, which follows a standard
+format that is compatible with all Protocol Buffers libraries. To use it with nanopb,
+you need to generate `.pb.c` and `.pb.h` files from it:
+
+    python generator/nanopb_generator.py myprotocol.proto  # For source checkout
+    generator-bin/nanopb_generator myprotocol.proto        # For binary package
+
+(Note: For instructions for nanopb-0.3.9.x and older, see the documentation
+of that particular version [here](https://github.com/nanopb/nanopb/blob/maintenance_0.3/README.md))
+
+The binary packages for Windows, Linux and Mac OS X should contain all necessary
+dependencies, including Python, python-protobuf library and protoc. If you are
+using a git checkout or a plain source distribution, you will need to install
+Python separately. Once you have Python, you can install the other dependencies
+with `pip install protobuf grpcio-tools`.
+
+You can further customize the header generation by creating an `.options` file.
+See [documentation](https://jpa.kapsi.fi/nanopb/docs/concepts.html#modifying-generator-behaviour) for details.
+
+
+Running the tests
+-----------------
+If you want to perform further development of the nanopb core, or to verify
+its functionality using your compiler and platform, you'll want to run the
+test suite. The build rules for the test suite are implemented using Scons,
+so you need to have that installed (ex: `sudo apt install scons` or `pip install scons`).
+To run the tests:
+
+    cd tests
+    scons
+
+This will show the progress of various test cases. If the output does not
+end in an error, the test cases were successful.
+
+Note: Mac OS X by default aliases 'clang' as 'gcc', while not actually
+supporting the same command line options as gcc does. To run tests on
+Mac OS X, use: `scons CC=clang CXX=clang`. Same way can be used to run
+tests with different compilers on any platform.
+
+For embedded platforms, there is currently support for running the tests
+on STM32 discovery board and [simavr](https://github.com/buserror/simavr)
+AVR simulator. Use `scons PLATFORM=STM32` and `scons PLATFORM=AVR` to run
+these tests.
+
+
+Build systems and integration
+-----------------------------
+Nanopb C code itself is designed to be portable and easy to build
+on any platform. Often the bigger hurdle is running the generator which
+takes in the `.proto` files and outputs `.pb.c` definitions.
+
+There exist build rules for several systems:
+
+* **Makefiles**: `extra/nanopb.mk`, see `examples/simple`
+* **CMake**: `extra/FindNanopb.cmake`, see `examples/cmake`
+* **SCons**: `tests/site_scons` (generator only)
+* **Bazel**: `BUILD` in source root
+* **Conan**: `conanfile.py` in source root
+* **PlatformIO**: https://platformio.org/lib/show/431/Nanopb
+* **PyPI/pip**: https://pypi.org/project/nanopb/
+
+And also integration to platform interfaces:
+
+* **Arduino**: http://platformio.org/lib/show/1385/nanopb-arduino
+
+Building nanopb - Using vcpkg
+-----------------------------
+
+You can download and install nanopb using the [vcpkg](https://github.com/Microsoft/vcpkg) dependency manager:
+
+    git clone https://github.com/Microsoft/vcpkg.git
+    cd vcpkg
+    ./bootstrap-vcpkg.sh
+    ./vcpkg integrate install
+    ./vcpkg install nanopb
+
+The nanopb port in vcpkg is kept up to date by Microsoft team members and community contributors. If the version is out of date, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository.

+ 1 - 0
components/spotify/cspot/bell/nanopb/WORKSPACE

@@ -0,0 +1 @@
+workspace(name = "com_github_nanopb_nanopb")

+ 6 - 0
components/spotify/cspot/bell/nanopb/build.py

@@ -0,0 +1,6 @@
+from conan.packager import ConanMultiPackager
+
+if __name__ == "__main__":
+    builder = ConanMultiPackager(build_policy="outdated")
+    builder.add_common_builds(shared_option_name=None)
+    builder.run()

+ 7 - 0
components/spotify/cspot/bell/nanopb/conan-wrapper/CMakeLists.txt

@@ -0,0 +1,7 @@
+cmake_minimum_required(VERSION 2.8.12)
+project(cmake_wrapper)
+
+include(${CMAKE_CURRENT_BINARY_DIR}/conanbuildinfo.cmake)
+conan_basic_setup()
+
+add_subdirectory(".." "nanopb")

+ 33 - 0
components/spotify/cspot/bell/nanopb/conanfile.py

@@ -0,0 +1,33 @@
+from conans import ConanFile, CMake, tools
+from os import path
+
+class NanoPbConan(ConanFile):
+    name = "nanopb"
+    version = "0.4.6-dev"
+    license = "zlib"
+    url = "https://jpa.kapsi.fi/nanopb/"
+    description = "Protocol Buffers with small code size"
+    settings = "os_build", "compiler", "build_type", "arch"
+    generators = "cmake"
+    exports = '*'
+    options = {
+        "fPIC": [True, False],
+    }
+    default_options = {
+        "fPIC": True,
+    }
+
+    def configure(self):
+        if self.settings.os_build == "Windows" and self.settings.compiler == "Visual Studio":
+            del self.options.fPIC
+
+    def build(self):
+        cmake = CMake(self)
+        cmake.configure(source_folder=path.join(self.source_folder, "conan-wrapper"))
+        cmake.build()
+        cmake.install()
+
+    def package_info(self):
+        self.cpp_info.includedirs = ["include"]
+        self.cpp_info.libdirs = ["lib"]
+        self.cpp_info.libs = ["protobuf-nanopb"]

+ 23 - 0
components/spotify/cspot/bell/nanopb/docs/Makefile

@@ -0,0 +1,23 @@
+INPUTS = index.md concepts.md reference.md security.md migration.md whats_new.md
+
+all: $(INPUTS:.md=.html)
+
+tmp_menu.html: $(INPUTS)
+	echo '<div id="index">' > $@
+	(echo '<h2>Documentation index</h2>'; \
+	 for file in $^; do echo -n '1. ['; sed -n '1 s!^# Nanopb: !! p' $$file; \
+	 echo -n "]("; echo $$file | sed 's/.md/.html)/' ; done;) | \
+	 pandoc -f markdown -t html5 >> $@
+	echo '</div>' >> $@
+
+%.html: %.md tmp_menu.html
+	sed '1 s!#!%!' $< | \
+	pandoc -s -f markdown -t html5 -c lsr.css --toc --toc-depth=4 \
+	 --variable 'header-includes=<link href="favicon.ico" type="image/x-icon" rel="shortcut icon" />' \
+	 --indented-code-classes=c \
+	 -o $@
+	sed -i '/<nav/e cat feedback.html' $@
+	sed -i 's/doc_page_name_placeholder/$</' $@
+	sed -i 's!<nav[^>]*>!\0<b>Contents:</b>!' $@
+	sed -i '/<nav/e cat tmp_menu.html' $@
+

+ 579 - 0
components/spotify/cspot/bell/nanopb/docs/concepts.md

@@ -0,0 +1,579 @@
+# Nanopb: Basic concepts
+
+The things outlined here are the underlying concepts of the nanopb
+design.
+
+## Proto files
+
+All Protocol Buffers implementations use .proto files to describe the
+message format. The point of these files is to be a portable interface
+description language.
+
+### Compiling .proto files for nanopb
+
+Nanopb comes with a Python script to generate `.pb.c` and
+`.pb.h` files from the `.proto` definition:
+
+    user@host:~$ nanopb/generator/nanopb_generator.py message.proto
+    Writing to message.pb.h and message.pb.c
+
+Internally this script uses Google `protoc` to parse the
+input file. If you do not have it available, you may receive an error
+message. You can install either `grpcio-tools` Python
+package using `pip`, or the `protoc` compiler
+itself from `protobuf-compiler` distribution package.
+Generally the Python package is recommended, because nanopb requires
+protoc version 3.6 or newer to support all features, and some distributions come with an older
+version.
+
+### Modifying generator behaviour
+
+Using generator options, you can set maximum sizes for fields in order
+to allocate them statically. The preferred way to do this is to create
+an .options file with the same name as your .proto file:
+
+    # Foo.proto
+    message Foo {
+       required string name = 1;
+    }
+
+    # Foo.options
+    Foo.name max_size:16
+
+For more information on this, see the [Proto file
+options](reference.html#proto-file-options) section in the reference
+manual.
+
+## Streams
+
+Nanopb uses streams for accessing the data in encoded format. The stream
+abstraction is very lightweight, and consists of a structure
+(`pb_ostream_t` or `pb_istream_t`) which contains a pointer to a
+callback function.
+
+There are a few generic rules for callback functions:
+
+1)  Return false on IO errors. The encoding or decoding process will
+    abort immediately.
+2)  Use state to store your own data, such as a file descriptor.
+3)  `bytes_written` and `bytes_left` are updated by pb_write and
+    pb_read.
+4)  Your callback may be used with substreams. In this case
+    `bytes_left`, `bytes_written` and `max_size` have smaller values
+    than the original stream. Don't use these values to calculate
+    pointers.
+5)  Always read or write the full requested length of data. For example,
+    POSIX `recv()` needs the `MSG_WAITALL` parameter to accomplish
+    this.
+
+### Output streams
+
+    struct _pb_ostream_t
+    {
+       bool (*callback)(pb_ostream_t *stream, const uint8_t *buf, size_t count);
+       void *state;
+       size_t max_size;
+       size_t bytes_written;
+    };
+
+The `callback` for output stream may be NULL, in which case the stream
+simply counts the number of bytes written. In this case, `max_size` is
+ignored.
+
+Otherwise, if `bytes_written` + bytes_to_be_written is larger than
+`max_size`, pb_write returns false before doing anything else. If you
+don\'t want to limit the size of the stream, pass SIZE_MAX.
+
+**Example 1:**
+
+This is the way to get the size of the message without storing it
+anywhere:
+
+    Person myperson = ...;
+    pb_ostream_t sizestream = {0};
+    pb_encode(&sizestream, Person_fields, &myperson);
+    printf("Encoded size is %d\n", sizestream.bytes_written);
+
+**Example 2:**
+
+Writing to stdout:
+
+    bool callback(pb_ostream_t `stream, const uint8_t `buf, size_t count)
+    {
+       FILE *file = (FILE*) stream->state;
+       return fwrite(buf, 1, count, file) == count;
+    }
+
+    pb_ostream_t stdoutstream = {&callback, stdout, SIZE_MAX, 0};
+
+### Input streams
+
+For input streams, there is one extra rule:
+
+6)  You don't need to know the length of the message in advance. After
+    getting EOF error when reading, set `bytes_left` to 0 and return
+    `false`. `pb_decode()` will detect this and if the EOF was in a proper
+    position, it will return true.
+
+Here is the structure:
+
+    struct _pb_istream_t
+    {
+       bool (*callback)(pb_istream_t *stream, uint8_t *buf, size_t count);
+       void *state;
+       size_t bytes_left;
+    };
+
+The `callback` must always be a function pointer. `Bytes_left` is an
+upper limit on the number of bytes that will be read. You can use
+SIZE_MAX if your callback handles EOF as described above.
+
+**Example:**
+
+This function binds an input stream to stdin:
+
+    bool callback(pb_istream_t *stream, uint8_t *buf, size_t count)
+    {
+       FILE *file = (FILE*)stream->state;
+       bool status;
+
+       if (buf == NULL)
+       {
+           while (count-- && fgetc(file) != EOF);
+           return count == 0;
+       }
+
+       status = (fread(buf, 1, count, file) == count);
+
+       if (feof(file))
+           stream->bytes_left = 0;
+
+       return status;
+    }
+
+    pb_istream_t stdinstream = {&callback, stdin, SIZE_MAX};
+
+## Data types
+
+Most Protocol Buffers datatypes have directly corresponding C datatypes,
+such as `int32` is `int32_t`, `float` is `float` and `bool` is `bool`. However, the
+variable-length datatypes are more complex:
+
+1)  Strings, bytes and repeated fields of any type map to callback
+    functions by default.
+2)  If there is a special option `(nanopb).max_size` specified in the
+    .proto file, string maps to null-terminated char array and bytes map
+    to a structure containing a char array and a size field.
+3)  If `(nanopb).fixed_length` is set to `true` and
+    `(nanopb).max_size` is also set, then bytes map to an inline byte
+    array of fixed size.
+4)  If there is a special option `(nanopb).max_count` specified on a
+    repeated field, it maps to an array of whatever type is being
+    repeated. Another field will be created for the actual number of
+    entries stored.
+5)  If `(nanopb).fixed_count` is set to `true` and
+    `(nanopb).max_count` is also set, the field for the actual number
+    of entries will not by created as the count is always assumed to be
+    max count.
+
+### Examples of .proto specifications vs. generated structure
+
+**Simple integer field:**\
+.proto: `int32 age = 1;`\
+.pb.h: `int32_t age;`
+
+**String with unknown length:**\
+.proto: `string name = 1;`\
+.pb.h: `pb_callback_t name;`
+
+**String with known maximum length:**\
+.proto: `string name = 1 [(nanopb).max_length = 40];`\
+.pb.h: `char name[41];`
+
+**Repeated string with unknown count:**\
+.proto: `repeated string names = 1;`\
+.pb.h: `pb_callback_t names;`
+
+**Repeated string with known maximum count and size:**\
+.proto: `repeated string names = 1 [(nanopb).max_length = 40, (nanopb).max_count = 5];`\
+.pb.h: `size_t names_count;` `char names[5][41];`
+
+**Bytes field with known maximum size:**\
+.proto: `bytes data = 1 [(nanopb).max_size = 16];`\
+.pb.h: `PB_BYTES_ARRAY_T(16) data;`, where the struct contains `{pb_size_t size; pb_byte_t bytes[n];}`
+
+**Bytes field with fixed length:**\
+.proto: `bytes data = 1 [(nanopb).max_size = 16, (nanopb).fixed_length = true];`\
+.pb.h: `pb_byte_t data[16];`
+
+**Repeated integer array with known maximum size:**\
+.proto: `repeated int32 numbers = 1 [(nanopb).max_count = 5];`\
+.pb.h: `pb_size_t numbers_count;` `int32_t numbers[5];`
+
+**Repeated integer array with fixed count:**\
+.proto: `repeated int32 numbers = 1 [(nanopb).max_count = 5, (nanopb).fixed_count = true];`\
+.pb.h: `int32_t numbers[5];`
+
+The maximum lengths are checked in runtime. If string/bytes/array
+exceeds the allocated length, `pb_decode()` will return false.
+
+> **Note:** For the `bytes` datatype, the field length checking may not be
+exact. The compiler may add some padding to the `pb_bytes_t`
+structure, and the nanopb runtime doesn't know how much of the
+structure size is padding. Therefore it uses the whole length of the
+structure for storing data, which is not very smart but shouldn't cause
+problems. In practise, this means that if you specify
+`(nanopb).max_size=5` on a `bytes` field, you may be able to store 6
+bytes there. For the `string` field type, the length limit is exact.
+
+> **Note:** The decoder only keeps track of one `fixed_count` repeated field at a time. Usually this it not an issue because all elements of a repeated field occur end-to-end. Interleaved array elements of several `fixed_count` repeated fields would be a valid protobuf message, but would get rejected by nanopb decoder with error `"wrong size for fixed count field"`.
+
+## Field callbacks
+
+When a field has dynamic length, nanopb cannot statically allocate
+storage for it. Instead, it allows you to handle the field in whatever
+way you want, using a callback function.
+
+The [pb_callback_t](reference.html#pb-callback-t) structure contains a
+function pointer and a `void` pointer called `arg` you can use for
+passing data to the callback. If the function pointer is NULL, the field
+will be skipped. A pointer to the `arg` is passed to the function, so
+that it can modify it and retrieve the value.
+
+The actual behavior of the callback function is different in encoding
+and decoding modes. In encoding mode, the callback is called once and
+should write out everything, including field tags. In decoding mode, the
+callback is called repeatedly for every data item.
+
+To write more complex field callbacks, it is recommended to read the
+[Google Protobuf Encoding Specification](https://developers.google.com/protocol-buffers/docs/encoding).
+
+### Encoding callbacks
+
+    bool (*encode)(pb_ostream_t *stream, const pb_field_iter_t *field, void * const *arg);
+
+|            |                                                                    |
+| ---------- | ------------------------------------------------------------------ |
+| `stream`   | Output stream to write to                                          |
+| `field`    | Iterator for the field currently being encoded or decoded.         |
+| `arg`      | Pointer to the `arg` field in the `pb_callback_t` structure.       |
+
+When encoding, the callback should write out complete fields, including
+the wire type and field number tag. It can write as many or as few
+fields as it likes. For example, if you want to write out an array as
+`repeated` field, you should do it all in a single call.
+
+Usually you can use [pb_encode_tag_for_field](reference.html#pb-encode-tag-for-field) to
+encode the wire type and tag number of the field. However, if you want
+to encode a repeated field as a packed array, you must call
+[pb_encode_tag](reference.html#pb-encode-tag) instead to specify a
+wire type of `PB_WT_STRING`.
+
+If the callback is used in a submessage, it will be called multiple
+times during a single call to [pb_encode](reference.html#pb-encode). In
+this case, it must produce the same amount of data every time. If the
+callback is directly in the main message, it is called only once.
+
+This callback writes out a dynamically sized string:
+
+    bool write_string(pb_ostream_t *stream, const pb_field_iter_t *field, void * const *arg)
+    {
+        char *str = get_string_from_somewhere();
+        if (!pb_encode_tag_for_field(stream, field))
+            return false;
+
+        return pb_encode_string(stream, (uint8_t*)str, strlen(str));
+    }
+
+### Decoding callbacks
+
+    bool (*decode)(pb_istream_t *stream, const pb_field_iter_t *field, void **arg);
+
+|            |                                                                    |
+| ---------- | ------------------------------------------------------------------ |
+| `stream`   | Input stream to read from                                          |
+| `field`    | Iterator for the field currently being encoded or decoded.         |
+| `arg`      | Pointer to the `arg` field in the `pb_callback_t` structure.       |
+
+When decoding, the callback receives a length-limited substring that
+reads the contents of a single field. The field tag has already been
+read. For `string` and `bytes`, the length value has already been
+parsed, and is available at `stream->bytes_left`.
+
+The callback will be called multiple times for repeated fields. For
+packed fields, you can either read multiple values until the stream
+ends, or leave it to [pb_decode](reference.html#pb-decode) to call your
+function over and over until all values have been read.
+
+This callback reads multiple integers and prints them:
+
+    bool read_ints(pb_istream_t *stream, const pb_field_iter_t *field, void **arg)
+    {
+        while (stream->bytes_left)
+        {
+            uint64_t value;
+            if (!pb_decode_varint(stream, &value))
+                return false;
+            printf("%lld\n", value);
+        }
+        return true;
+    }
+
+### Function name bound callbacks
+
+    bool MyMessage_callback(pb_istream_t *istream, pb_ostream_t *ostream, const pb_field_iter_t *field);
+
+|            |                                                                    |
+| ---------- | ------------------------------------------------------------------ |
+| `istream`  | Input stream to read from, or NULL if called in encoding context.  |
+| `ostream`  | Output stream to write to, or NULL if called in decoding context.  |
+| `field`    | Iterator for the field currently being encoded or decoded.         |
+
+Storing function pointer in `pb_callback_t` fields inside
+the message requires extra storage space and is often cumbersome. As an
+alternative, the generator options `callback_function` and
+`callback_datatype` can be used to bind a callback function
+based on its name.
+
+Typically this feature is used by setting
+`callback_datatype` to e.g. `void\*` or other
+data type used for callback state. Then the generator will automatically
+set `callback_function` to
+`MessageName_callback` and produce a prototype for it in
+generated `.pb.h`. By implementing this function in your own
+code, you will receive callbacks for fields without having to separately
+set function pointers.
+
+If you want to use function name bound callbacks for some fields and
+`pb_callback_t` for other fields, you can call
+`pb_default_field_callback` from the message-level
+callback. It will then read a function pointer from
+`pb_callback_t` and call it.
+
+## Message descriptor
+
+For using the `pb_encode()` and `pb_decode()` functions, you need a
+description of all the fields contained in a message. This description
+is usually autogenerated from .proto file.
+
+For example this submessage in the Person.proto file:
+
+~~~~ protobuf
+message Person {
+    message PhoneNumber {
+        required string number = 1 [(nanopb).max_size = 40];
+        optional PhoneType type = 2 [default = HOME];
+    }
+}
+~~~~
+
+This in turn generates a macro list in the `.pb.h` file:
+
+    #define Person_PhoneNumber_FIELDLIST(X, a) \
+    X(a, STATIC,   REQUIRED, STRING,   number,            1) \
+    X(a, STATIC,   OPTIONAL, UENUM,    type,              2)
+
+Inside the `.pb.c` file there is a macro call to
+`PB_BIND`:
+
+    PB_BIND(Person_PhoneNumber, Person_PhoneNumber, AUTO)
+
+These macros will in combination generate `pb_msgdesc_t`
+structure and associated lists:
+
+    const uint32_t Person_PhoneNumber_field_info[] = { ... };
+    const pb_msgdesc_t * const Person_PhoneNumber_submsg_info[] = { ... };
+    const pb_msgdesc_t Person_PhoneNumber_msg = {
+      2,
+      Person_PhoneNumber_field_info,
+      Person_PhoneNumber_submsg_info,
+      Person_PhoneNumber_DEFAULT,
+      NULL,
+    };
+
+The encoding and decoding functions take a pointer to this structure and
+use it to process each field in the message.
+
+## Oneof
+
+Protocol Buffers supports
+[oneof](https://developers.google.com/protocol-buffers/docs/reference/proto2-spec#oneof_and_oneof_field)
+sections, where only one of the fields contained within can be present. Here is an example of `oneof` usage:
+
+~~~~ protobuf
+message MsgType1 {
+    required int32 value = 1;
+}
+
+message MsgType2 {
+    required bool value = 1;
+}
+
+message MsgType3 {
+    required int32 value1 = 1;
+    required int32 value2 = 2;
+} 
+
+message MyMessage {
+    required uint32 uid = 1;
+    required uint32 pid = 2;
+    required uint32 utime = 3;
+
+    oneof payload {
+        MsgType1 msg1 = 4;
+        MsgType2 msg2 = 5;
+        MsgType3 msg3 = 6;
+    }
+}
+~~~~
+
+Nanopb will generate `payload` as a C union and add an additional field
+`which_payload`:
+
+    typedef struct _MyMessage {
+      uint32_t uid;
+      uint32_t pid;
+      uint32_t utime;
+      pb_size_t which_payload;
+      union {
+          MsgType1 msg1;
+          MsgType2 msg2;
+          MsgType3 msg3;
+      } payload;
+    } MyMessage;
+
+`which_payload` indicates which of the `oneof` fields is actually set.
+The user is expected to set the field manually using the correct field
+tag:
+
+    MyMessage msg = MyMessage_init_zero;
+    msg.payload.msg2.value = true;
+    msg.which_payload = MyMessage_msg2_tag;
+
+Notice that neither `which_payload` field nor the unused fields in
+`payload` will consume any space in the resulting encoded message.
+
+When a field inside `oneof` contains `pb_callback_t`
+fields, the callback values cannot be set before decoding. This is
+because the different fields share the same storage space in C
+`union`. Instead either function name bound callbacks or a
+separate message level callback can be used. See
+[tests/oneof_callback](https://github.com/nanopb/nanopb/tree/master/tests/oneof_callback)
+for an example on this.
+
+## Extension fields
+
+Protocol Buffers supports a concept of [extension
+fields](https://developers.google.com/protocol-buffers/docs/proto#extensions),
+which are additional fields to a message, but defined outside the actual
+message. The definition can even be in a completely separate .proto
+file.
+
+The base message is declared as extensible by keyword `extensions` in
+the .proto file:
+
+~~~~ protobuf
+message MyMessage {
+    .. fields ..
+    extensions 100 to 199;
+}
+~~~~
+
+For each extensible message, `nanopb_generator.py` declares an
+additional callback field called `extensions`. The field and associated
+datatype `pb_extension_t` forms a linked list of handlers. When an
+unknown field is encountered, the decoder calls each handler in turn
+until either one of them handles the field, or the list is exhausted.
+
+The actual extensions are declared using the `extend` keyword in the
+.proto, and are in the global namespace:
+
+~~~~ protobuf
+extend MyMessage {
+    optional int32 myextension = 100;
+}
+~~~~
+
+For each extension, `nanopb_generator.py` creates a constant of type
+`pb_extension_type_t`. To link together the base message and the
+extension, you have to:
+
+1.  Allocate storage for your field, matching the datatype in the
+    .proto. For example, for a `int32` field, you need a `int32_t`
+    variable to store the value.
+2.  Create a `pb_extension_t` constant, with pointers to your variable
+    and to the generated `pb_extension_type_t`.
+3.  Set the `message.extensions` pointer to point to the
+    `pb_extension_t`.
+
+An example of this is available in `tests/test_encode_extensions.c`
+and `tests/test_decode_extensions.c`.
+
+## Default values
+
+Protobuf has two syntax variants, proto2 and proto3. Of these proto2 has
+user definable default values that can be given in .proto file:
+
+~~~~ protobuf
+message MyMessage {
+    optional bytes foo = 1 [default = "ABC\x01\x02\x03"];
+    optional string bar = 2 [default = "åäö"];
+}
+~~~~
+
+Nanopb will generate both static and runtime initialization for the
+default values. In `myproto.pb.h` there will be a
+`#define MyMessage_init_default {...}` that can be used to initialize
+whole message into default values:
+
+    MyMessage msg = MyMessage_init_default;
+
+In addition to this, `pb_decode()` will initialize message
+fields to defaults at runtime. If this is not desired,
+`pb_decode_ex()` can be used instead.
+
+## Message framing
+
+Protocol Buffers does not specify a method of framing the messages for
+transmission. This is something that must be provided by the library
+user, as there is no one-size-fits-all solution. Typical needs for a
+framing format are to:
+
+1.  Encode the message length.
+2.  Encode the message type.
+3.  Perform any synchronization and error checking that may be needed
+    depending on application.
+
+For example UDP packets already fulfill all the requirements, and TCP
+streams typically only need a way to identify the message length and
+type. Lower level interfaces such as serial ports may need a more robust
+frame format, such as HDLC (high-level data link control).
+
+Nanopb provides a few helpers to facilitate implementing framing
+formats:
+
+1.  Functions `pb_encode_ex` and `pb_decode_ex` prefix the message
+    data with a varint-encoded length.
+2.  Union messages and oneofs are supported in order to implement
+    top-level container messages.
+3.  Message IDs can be specified using the `(nanopb_msgopt).msgid`
+    option and can then be accessed from the header.
+
+## Return values and error handling
+
+Most functions in nanopb return bool: `true` means success, `false`
+means failure. There is also support for error messages for
+debugging purposes: the error messages go in `stream->errmsg`.
+
+The error messages help in guessing what is the underlying cause of the
+error. The most common error conditions are:
+
+1)  Invalid protocol buffers binary message.
+2)  Mismatch between binary message and .proto message type.
+3)  Unterminated message (incorrect message length).
+4) Exceeding the max_size or bytes_left of a stream.
+5) Exceeding the max_size/max_count of a string or array field
+6) IO errors in your own stream callbacks.
+7) Errors that happen in your callback functions.
+8) Running out of memory, i.e. stack overflow.
+9) Invalid field descriptors (would usually mean a bug in the generator).

+ 2869 - 0
components/spotify/cspot/bell/nanopb/docs/generator_flow.svg

@@ -0,0 +1,2869 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="490"
+   height="220"
+   id="svg1901"
+   sodipodi:version="0.32"
+   inkscape:version="0.48.2 r9819"
+   sodipodi:docname="generator_flow.svg"
+   version="1.1">
+  <defs
+     id="defs1903">
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient15568">
+      <stop
+         style="stop-color:#729fcf;stop-opacity:1;"
+         offset="0"
+         id="stop15570" />
+      <stop
+         style="stop-color:#729fcf;stop-opacity:0;"
+         offset="1"
+         id="stop15572" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient15558">
+      <stop
+         style="stop-color:#fcaf3e;stop-opacity:1;"
+         offset="0"
+         id="stop15560" />
+      <stop
+         style="stop-color:#fcaf3e;stop-opacity:0;"
+         offset="1"
+         id="stop15562" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient13629">
+      <stop
+         style="stop-color:#fce94f;stop-opacity:1;"
+         offset="0"
+         id="stop13631" />
+      <stop
+         style="stop-color:#fce94f;stop-opacity:0;"
+         offset="1"
+         id="stop13633" />
+    </linearGradient>
+    <radialGradient
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1,0,0,0.284916,0,30.08928)"
+       r="15.821514"
+       fy="42.07798"
+       fx="24.306795"
+       cy="42.07798"
+       cx="24.306795"
+       id="radialGradient4548"
+       xlink:href="#linearGradient4542"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient259">
+      <stop
+         style="stop-color:#fafafa;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop260" />
+      <stop
+         style="stop-color:#bbbbbb;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop261" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient269">
+      <stop
+         style="stop-color:#a3a3a3;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop270" />
+      <stop
+         style="stop-color:#4c4c4c;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop271" />
+    </linearGradient>
+    <radialGradient
+       gradientUnits="userSpaceOnUse"
+       fy="114.5684"
+       fx="20.892099"
+       r="5.256"
+       cy="114.5684"
+       cx="20.892099"
+       id="aigrd2">
+      <stop
+         id="stop15566"
+         style="stop-color:#F0F0F0"
+         offset="0" />
+      <stop
+         id="stop15568"
+         style="stop-color:#9a9a9a;stop-opacity:1.0000000;"
+         offset="1.0000000" />
+    </radialGradient>
+    <radialGradient
+       gradientUnits="userSpaceOnUse"
+       fy="64.567902"
+       fx="20.892099"
+       r="5.257"
+       cy="64.567902"
+       cx="20.892099"
+       id="aigrd3">
+      <stop
+         id="stop15573"
+         style="stop-color:#F0F0F0"
+         offset="0" />
+      <stop
+         id="stop15575"
+         style="stop-color:#9a9a9a;stop-opacity:1.0000000;"
+         offset="1.0000000" />
+    </radialGradient>
+    <linearGradient
+       id="linearGradient15662">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop15664" />
+      <stop
+         style="stop-color:#f8f8f8;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop15666" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4542"
+       inkscape:collect="always">
+      <stop
+         id="stop4544"
+         offset="0"
+         style="stop-color:#000000;stop-opacity:1;" />
+      <stop
+         id="stop4546"
+         offset="1"
+         style="stop-color:#000000;stop-opacity:0;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient5048">
+      <stop
+         id="stop5050"
+         offset="0"
+         style="stop-color:black;stop-opacity:0;" />
+      <stop
+         style="stop-color:black;stop-opacity:1;"
+         offset="0.5"
+         id="stop5056" />
+      <stop
+         id="stop5052"
+         offset="1"
+         style="stop-color:black;stop-opacity:0;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient5060"
+       inkscape:collect="always">
+      <stop
+         id="stop5062"
+         offset="0"
+         style="stop-color:black;stop-opacity:1;" />
+      <stop
+         id="stop5064"
+         offset="1"
+         style="stop-color:black;stop-opacity:0;" />
+    </linearGradient>
+    <radialGradient
+       r="9.586297"
+       fy="9.8105707"
+       fx="21.578989"
+       cy="9.8105707"
+       cx="21.578989"
+       gradientTransform="matrix(0.74942,0,0,0.394055,6.226925,10.09253)"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient2908"
+       xlink:href="#linearGradient2869"
+       inkscape:collect="always" />
+    <radialGradient
+       r="6.4286141"
+       fy="20.800287"
+       fx="23.94367"
+       cy="20.800287"
+       cx="23.94367"
+       gradientTransform="matrix(1.353283,0,0,0.635968,-8.45889,3.41347)"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient2906"
+       xlink:href="#linearGradient2884"
+       inkscape:collect="always" />
+    <radialGradient
+       r="9.586297"
+       fy="9.0255041"
+       fx="21.578989"
+       cy="9.0255041"
+       cx="21.578989"
+       gradientTransform="matrix(0.74942,0,0,0.394055,6.226925,10.09253)"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient2898"
+       xlink:href="#linearGradient2869"
+       inkscape:collect="always" />
+    <radialGradient
+       r="6.4286141"
+       fy="20.800287"
+       fx="23.94367"
+       cy="20.800287"
+       cx="23.94367"
+       gradientTransform="matrix(1.353283,0,0,0.635968,-8.45889,3.41347)"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient2896"
+       xlink:href="#linearGradient2884"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="22.585211"
+       x2="24.990499"
+       y1="34.004856"
+       x1="24.990499"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient2288"
+       xlink:href="#linearGradient4210"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="47.388485"
+       x2="30.014812"
+       y1="19.912336"
+       x1="18.706615"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient2285"
+       xlink:href="#linearGradient4222"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="16.020695"
+       x2="22.071806"
+       y1="9.7577486"
+       x1="21.906841"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient2282"
+       xlink:href="#linearGradient4987"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="12.636667"
+       x2="34.193642"
+       y1="12.636667"
+       x1="16.148972"
+       gradientTransform="matrix(1,0,0,1.039184,0,-0.04057054)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient2280"
+       xlink:href="#linearGradient4182"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="16.17037"
+       x2="24.119167"
+       y1="24.720648"
+       x1="25.381256"
+       gradientTransform="matrix(1,0,0,0.986355,0,0.316638)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient2277"
+       xlink:href="#linearGradient4192"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="15.267649"
+       x2="47.065834"
+       y1="14.661557"
+       x1="36.288929"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient2274"
+       xlink:href="#linearGradient4995"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="12.333632"
+       x2="17.696169"
+       y1="13.444801"
+       x1="30.062469"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient2269"
+       xlink:href="#linearGradient4979"
+       inkscape:collect="always" />
+    <radialGradient
+       r="17.576654"
+       fy="35.373093"
+       fx="22.930462"
+       cy="35.373093"
+       cx="22.930462"
+       gradientTransform="matrix(1,0,0,0.333333,0,23.58206)"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient2252"
+       xlink:href="#linearGradient4946"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient4182">
+      <stop
+         style="stop-color:#a36d18;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop4184" />
+      <stop
+         style="stop-color:#d79020;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop4186" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4192">
+      <stop
+         style="stop-color:#e9b96e;stop-opacity:1;"
+         offset="0"
+         id="stop4194" />
+      <stop
+         style="stop-color:#f1d19e;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop4196" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4210">
+      <stop
+         style="stop-color:#eaba6f;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop4212" />
+      <stop
+         style="stop-color:#b97a1b;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop4214" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4222">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1;"
+         offset="0"
+         id="stop4224" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0.68639052;"
+         offset="1.0000000"
+         id="stop4226" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient4946">
+      <stop
+         style="stop-color:#000000;stop-opacity:1;"
+         offset="0"
+         id="stop4948" />
+      <stop
+         style="stop-color:#000000;stop-opacity:0;"
+         offset="1"
+         id="stop4950" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4979">
+      <stop
+         style="stop-color:#fbf0e0;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop4981" />
+      <stop
+         style="stop-color:#f0ce99;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop4983" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient4987">
+      <stop
+         style="stop-color:#a0670c;stop-opacity:1;"
+         offset="0"
+         id="stop4989" />
+      <stop
+         style="stop-color:#a0670c;stop-opacity:0;"
+         offset="1"
+         id="stop4991" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4995">
+      <stop
+         style="stop-color:#de9523;stop-opacity:1;"
+         offset="0"
+         id="stop4997" />
+      <stop
+         style="stop-color:#a36d18;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop4999" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient2869">
+      <stop
+         id="stop2871"
+         offset="0"
+         style="stop-color:#ffffff;stop-opacity:1;" />
+      <stop
+         id="stop2873"
+         offset="1.0000000"
+         style="stop-color:#cccccc;stop-opacity:1.0000000;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient2884"
+       inkscape:collect="always">
+      <stop
+         id="stop2886"
+         offset="0"
+         style="stop-color:#000000;stop-opacity:1;" />
+      <stop
+         id="stop2888"
+         offset="1"
+         style="stop-color:#000000;stop-opacity:0;" />
+    </linearGradient>
+    <linearGradient
+       y2="609.50507"
+       x2="302.85715"
+       y1="366.64789"
+       x1="302.85715"
+       gradientTransform="matrix(2.774389,0,0,1.969706,-1892.179,-872.8854)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient6715-6"
+       xlink:href="#linearGradient5048-7"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient5048-7">
+      <stop
+         id="stop5050-2"
+         offset="0"
+         style="stop-color:black;stop-opacity:0;" />
+      <stop
+         style="stop-color:black;stop-opacity:1;"
+         offset="0.5"
+         id="stop5056-4" />
+      <stop
+         id="stop5052-0"
+         offset="1"
+         style="stop-color:black;stop-opacity:0;" />
+    </linearGradient>
+    <radialGradient
+       r="117.14286"
+       fy="486.64789"
+       fx="605.71429"
+       cy="486.64789"
+       cx="605.71429"
+       gradientTransform="matrix(2.774389,0,0,1.969706,-1891.633,-872.8854)"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient6717-4"
+       xlink:href="#linearGradient5060-6"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient5060-6"
+       inkscape:collect="always">
+      <stop
+         id="stop5062-2"
+         offset="0"
+         style="stop-color:black;stop-opacity:1;" />
+      <stop
+         id="stop5064-8"
+         offset="1"
+         style="stop-color:black;stop-opacity:0;" />
+    </linearGradient>
+    <radialGradient
+       r="117.14286"
+       fy="486.64789"
+       fx="605.71429"
+       cy="486.64789"
+       cx="605.71429"
+       gradientTransform="matrix(-2.774389,0,0,1.969706,112.7623,-872.8854)"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient6719-8"
+       xlink:href="#linearGradient5060-6"
+       inkscape:collect="always" />
+    <linearGradient
+       gradientTransform="matrix(-0.901805,0.210818,-0.211618,-0.898788,63.54132,37.87423)"
+       y2="46.06208"
+       x2="29.477814"
+       y1="2.8703361"
+       x1="25.950134"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient5486"
+       xlink:href="#linearGradient5476"
+       inkscape:collect="always" />
+    <linearGradient
+       gradientTransform="matrix(1.106909,-0.258404,0.259748,1.101665,-19.66697,12.19788)"
+       gradientUnits="userSpaceOnUse"
+       y2="46.06208"
+       x2="29.477814"
+       y1="2.8703361"
+       x1="25.950134"
+       id="linearGradient5482"
+       xlink:href="#linearGradient5476"
+       inkscape:collect="always" />
+    <linearGradient
+       gradientTransform="matrix(1.106909,-0.258404,0.259748,1.101665,-19.66697,12.19788)"
+       y2="2.8163671"
+       x2="21.587093"
+       y1="23.499001"
+       x1="21.587093"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient5472"
+       xlink:href="#linearGradient5464"
+       inkscape:collect="always" />
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient4356">
+      <stop
+         style="stop-color:#000000;stop-opacity:1;"
+         offset="0"
+         id="stop4358" />
+      <stop
+         style="stop-color:#000000;stop-opacity:0;"
+         offset="1"
+         id="stop4360" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4344">
+      <stop
+         style="stop-color:#727e0a;stop-opacity:1;"
+         offset="0"
+         id="stop4346" />
+      <stop
+         style="stop-color:#5b6508;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop4348" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4338">
+      <stop
+         id="stop4340"
+         offset="0.0000000"
+         style="stop-color:#e9b15e;stop-opacity:1.0000000;" />
+      <stop
+         id="stop4342"
+         offset="1.0000000"
+         style="stop-color:#966416;stop-opacity:1.0000000;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4163">
+      <stop
+         style="stop-color:#3b74bc;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop4165" />
+      <stop
+         style="stop-color:#2d5990;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop4167" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3824">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1;"
+         offset="0"
+         id="stop3826" />
+      <stop
+         style="stop-color:#c9c9c9;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop3828" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient3816">
+      <stop
+         style="stop-color:#000000;stop-opacity:1;"
+         offset="0"
+         id="stop3818" />
+      <stop
+         style="stop-color:#000000;stop-opacity:0;"
+         offset="1"
+         id="stop3820" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3800">
+      <stop
+         style="stop-color:#f4d9b1;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop3802" />
+      <stop
+         style="stop-color:#df9725;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop3804" />
+    </linearGradient>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3800"
+       id="radialGradient3806"
+       cx="29.344931"
+       cy="17.064077"
+       fx="29.344931"
+       fy="17.064077"
+       r="9.1620579"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3816"
+       id="radialGradient3822"
+       cx="31.112698"
+       cy="19.008621"
+       fx="31.112698"
+       fy="19.008621"
+       r="8.6620579"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3824"
+       id="linearGradient3830"
+       x1="30.935921"
+       y1="29.553486"
+       x2="30.935921"
+       y2="35.803486"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4163"
+       id="radialGradient4169"
+       cx="28.089741"
+       cy="27.203083"
+       fx="28.089741"
+       fy="27.203083"
+       r="13.56536"
+       gradientTransform="matrix(1.297564,0,0,0.884831,-8.358505,4.940469)"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3800"
+       id="radialGradient4171"
+       gradientUnits="userSpaceOnUse"
+       cx="29.344931"
+       cy="17.064077"
+       fx="29.344931"
+       fy="17.064077"
+       r="9.1620579"
+       gradientTransform="matrix(0.787998,0,0,0.787998,6.221198,3.617627)" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3824"
+       id="linearGradient4175"
+       gradientUnits="userSpaceOnUse"
+       x1="30.935921"
+       y1="29.553486"
+       x2="30.935921"
+       y2="35.803486"
+       gradientTransform="translate(0.707108,0)" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3816"
+       id="radialGradient4179"
+       gradientUnits="userSpaceOnUse"
+       cx="31.112698"
+       cy="19.008621"
+       fx="31.112698"
+       fy="19.008621"
+       r="8.6620579" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3824"
+       id="linearGradient4326"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="translate(-12.41789,-7)"
+       x1="30.935921"
+       y1="29.553486"
+       x2="30.935921"
+       y2="35.803486" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4338"
+       id="radialGradient4328"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.787998,0,0,0.787998,6.221198,3.617627)"
+       cx="29.344931"
+       cy="17.064077"
+       fx="29.344931"
+       fy="17.064077"
+       r="9.1620579" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3816"
+       id="radialGradient4330"
+       gradientUnits="userSpaceOnUse"
+       cx="31.112698"
+       cy="19.008621"
+       fx="31.112698"
+       fy="19.008621"
+       r="8.6620579" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3824"
+       id="linearGradient4332"
+       gradientUnits="userSpaceOnUse"
+       x1="30.935921"
+       y1="29.553486"
+       x2="30.935921"
+       y2="35.803486"
+       gradientTransform="translate(-13.125,-7)" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3816"
+       id="radialGradient4336"
+       gradientUnits="userSpaceOnUse"
+       cx="31.112698"
+       cy="19.008621"
+       fx="31.112698"
+       fy="19.008621"
+       r="8.6620579" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4344"
+       id="radialGradient4350"
+       cx="16.214741"
+       cy="19.836468"
+       fx="16.214741"
+       fy="19.836468"
+       r="13.56536"
+       gradientTransform="matrix(1,0,0,0.681917,0,8.233773)"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4356"
+       id="linearGradient4362"
+       x1="20.661695"
+       y1="35.817974"
+       x2="22.626925"
+       y2="36.217758"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.983375,0.181588,-0.181588,0.983375,6.231716,-2.651466)" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4356"
+       id="linearGradient4366"
+       gradientUnits="userSpaceOnUse"
+       x1="22.686766"
+       y1="36.3904"
+       x2="21.408455"
+       y2="35.739632"
+       gradientTransform="matrix(-0.977685,0.210075,0.210075,0.977685,55.1096,-3.945209)" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4356"
+       id="linearGradient4372"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.983375,0.181588,-0.181588,0.983375,-7.07212,-9.82492)"
+       x1="20.661695"
+       y1="35.817974"
+       x2="22.626925"
+       y2="36.217758" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4356"
+       id="linearGradient4374"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(-0.977685,0.210075,0.210075,0.977685,41.80576,-11.11866)"
+       x1="22.686766"
+       y1="36.3904"
+       x2="21.408455"
+       y2="35.739632" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4356"
+       id="linearGradient1366"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(-0.977685,0.210075,0.210075,0.977685,41.80576,-11.11866)"
+       x1="22.686766"
+       y1="36.3904"
+       x2="21.408455"
+       y2="35.739632" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4356"
+       id="linearGradient1369"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.983375,0.181588,-0.181588,0.983375,-7.07212,-9.82492)"
+       x1="20.661695"
+       y1="35.817974"
+       x2="22.626925"
+       y2="36.217758" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3824"
+       id="linearGradient1372"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="translate(-12.41789,-7)"
+       x1="30.935921"
+       y1="29.553486"
+       x2="30.935921"
+       y2="35.803486" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4344"
+       id="radialGradient1381"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1,0,0,0.681917,0,8.233773)"
+       cx="16.214741"
+       cy="19.836468"
+       fx="16.214741"
+       fy="19.836468"
+       r="13.56536" />
+    <linearGradient
+       y2="11.981981"
+       x2="13.846983"
+       y1="11.48487"
+       x1="11.74217"
+       gradientTransform="matrix(1.276531,0,0,-1.406115,24.24763,33.3374)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient1493"
+       xlink:href="#linearGradient15107"
+       inkscape:collect="always" />
+    <radialGradient
+       r="7.228416"
+       fy="73.615715"
+       fx="6.702713"
+       cy="73.615715"
+       cx="6.702713"
+       gradientTransform="scale(1.902215,0.525703)"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient1481"
+       xlink:href="#linearGradient10691"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="12.765438"
+       x2="38.129341"
+       y1="7.7850504"
+       x1="26.577936"
+       gradientTransform="matrix(0,1,-1,0,37.07553,-5.879343)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient2365"
+       xlink:href="#linearGradient4274"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="29.698416"
+       x2="16.588747"
+       y1="16.612858"
+       x1="41.093174"
+       gradientTransform="matrix(0,0.914114,-0.914114,0,39.78243,-9.748047)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient2566"
+       xlink:href="#linearGradient2187"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="27.145725"
+       x2="10.112462"
+       y1="23.332331"
+       x1="10.791593"
+       gradientTransform="matrix(0,1,-1,0,37.07553,-5.879343)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient2564"
+       xlink:href="#linearGradient6925"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="30.55784"
+       x2="12.252101"
+       y1="15.028743"
+       x1="15.193591"
+       gradientTransform="matrix(0,1,-1,0,37.07553,-5.879343)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient2562"
+       xlink:href="#linearGradient6901"
+       inkscape:collect="always" />
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient6925">
+      <stop
+         style="stop-color:#204a87;stop-opacity:1;"
+         offset="0"
+         id="stop6927" />
+      <stop
+         style="stop-color:#204a87;stop-opacity:0;"
+         offset="1"
+         id="stop6929" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient6901">
+      <stop
+         style="stop-color:#3465a4;stop-opacity:1;"
+         offset="0"
+         id="stop6903" />
+      <stop
+         style="stop-color:#3465a4;stop-opacity:0;"
+         offset="1"
+         id="stop6905" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient2187"
+       inkscape:collect="always">
+      <stop
+         id="stop2189"
+         offset="0"
+         style="stop-color:#ffffff;stop-opacity:1;" />
+      <stop
+         id="stop2191"
+         offset="1"
+         style="stop-color:#ffffff;stop-opacity:0;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4274">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0.25490198;"
+         offset="0.0000000"
+         id="stop4276" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop4278" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient10691">
+      <stop
+         style="stop-color:#000000;stop-opacity:1;"
+         offset="0"
+         id="stop10693" />
+      <stop
+         style="stop-color:#000000;stop-opacity:0;"
+         offset="1"
+         id="stop10695" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient15107">
+      <stop
+         id="stop15109"
+         offset="0.0000000"
+         style="stop-color:#ffffff;stop-opacity:1.0000000;" />
+      <stop
+         id="stop15111"
+         offset="1.0000000"
+         style="stop-color:#e2e2e2;stop-opacity:1.0000000;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient9749">
+      <stop
+         id="stop9751"
+         offset="0"
+         style="stop-color:#ffffff;stop-opacity:1;" />
+      <stop
+         id="stop9753"
+         offset="1.0000000"
+         style="stop-color:#ededed;stop-opacity:1.0000000;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient2274-5">
+      <stop
+         id="stop2276"
+         offset="0.0000000"
+         style="stop-color:#000000;stop-opacity:0.12871288;" />
+      <stop
+         id="stop2278"
+         offset="1.0000000"
+         style="stop-color:#000000;stop-opacity:0.0000000;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient2624">
+      <stop
+         style="stop-color:#dfe0df;stop-opacity:1;"
+         offset="0"
+         id="stop2626" />
+      <stop
+         id="stop2630"
+         offset="0.23809524"
+         style="stop-color:#a6b0a6;stop-opacity:1;" />
+      <stop
+         style="stop-color:#b5beb5;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop2628" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient5464">
+      <stop
+         id="stop5466"
+         offset="0"
+         style="stop-color:#729fcf;stop-opacity:1;" />
+      <stop
+         id="stop5468"
+         offset="1"
+         style="stop-color:#afc9e4;stop-opacity:1;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient5476"
+       inkscape:collect="always">
+      <stop
+         id="stop5478"
+         offset="0"
+         style="stop-color:#ffffff;stop-opacity:1;" />
+      <stop
+         id="stop5480"
+         offset="1"
+         style="stop-color:#ffffff;stop-opacity:0;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient5048-5">
+      <stop
+         id="stop5050-4"
+         offset="0"
+         style="stop-color:black;stop-opacity:0;" />
+      <stop
+         style="stop-color:black;stop-opacity:1;"
+         offset="0.5"
+         id="stop5056-9" />
+      <stop
+         id="stop5052-2"
+         offset="1"
+         style="stop-color:black;stop-opacity:0;" />
+    </linearGradient>
+    <radialGradient
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1,0,0,0.177966,0,108.7434)"
+       r="29.036913"
+       fy="132.28575"
+       fx="61.518883"
+       cy="132.28575"
+       cx="61.518883"
+       id="radialGradient2801"
+       xlink:href="#linearGradient2795"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="76.313133"
+       x2="26.670298"
+       y1="76.176224"
+       x1="172.94208"
+       gradientTransform="matrix(0.562541,0,0,0.567972,-11.5974,-7.60954)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient2258"
+       xlink:href="#linearGradient4689"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="144.75717"
+       x2="-65.308502"
+       y1="144.75717"
+       x1="224.23996"
+       gradientTransform="matrix(0.562541,0,0,0.567972,-11.5974,-7.60954)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient2255"
+       xlink:href="#linearGradient4671"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="144.75717"
+       x2="-65.308502"
+       y1="144.75717"
+       x1="224.23996"
+       gradientTransform="translate(100.2702,99.61116)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient2250"
+       xlink:href="#linearGradient4671"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="76.313133"
+       x2="26.670298"
+       y1="77.475983"
+       x1="172.94208"
+       gradientTransform="translate(100.2702,99.61116)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient2248"
+       xlink:href="#linearGradient4689"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="144.75717"
+       x2="-65.308502"
+       y1="144.75717"
+       x1="224.23996"
+       gradientTransform="translate(100.2702,99.61116)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient2589"
+       xlink:href="#linearGradient4671"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="76.313133"
+       x2="26.670298"
+       y1="77.475983"
+       x1="172.94208"
+       gradientTransform="translate(100.2702,99.61116)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient2587"
+       xlink:href="#linearGradient4689"
+       inkscape:collect="always" />
+    <linearGradient
+       gradientTransform="translate(100.2702,99.61116)"
+       gradientUnits="userSpaceOnUse"
+       xlink:href="#linearGradient4689"
+       id="linearGradient2990"
+       y2="76.313133"
+       x2="26.670298"
+       y1="77.475983"
+       x1="172.94208" />
+    <linearGradient
+       gradientTransform="translate(100.2702,99.61116)"
+       gradientUnits="userSpaceOnUse"
+       xlink:href="#linearGradient4671"
+       id="linearGradient2987"
+       y2="144.75717"
+       x2="-65.308502"
+       y1="144.75717"
+       x1="224.23996" />
+    <linearGradient
+       id="linearGradient4689">
+      <stop
+         id="stop4691"
+         offset="0"
+         style="stop-color:#5a9fd4;stop-opacity:1;" />
+      <stop
+         id="stop4693"
+         offset="1"
+         style="stop-color:#306998;stop-opacity:1;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4671">
+      <stop
+         id="stop4673"
+         offset="0"
+         style="stop-color:#ffd43b;stop-opacity:1;" />
+      <stop
+         id="stop4675"
+         offset="1"
+         style="stop-color:#ffe873;stop-opacity:1" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3236">
+      <stop
+         id="stop3244"
+         offset="0"
+         style="stop-color:#f4f4f4;stop-opacity:1" />
+      <stop
+         id="stop3240"
+         offset="1"
+         style="stop-color:white;stop-opacity:1" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3676">
+      <stop
+         id="stop3678"
+         offset="0"
+         style="stop-color:#b2b2b2;stop-opacity:0.5;" />
+      <stop
+         id="stop3680"
+         offset="1"
+         style="stop-color:#b3b3b3;stop-opacity:0;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient2787">
+      <stop
+         id="stop2789"
+         offset="0"
+         style="stop-color:#7f7f7f;stop-opacity:0.5;" />
+      <stop
+         id="stop2791"
+         offset="1"
+         style="stop-color:#7f7f7f;stop-opacity:0;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient2795">
+      <stop
+         id="stop2797"
+         offset="0"
+         style="stop-color:#b8b8b8;stop-opacity:0.49803922;" />
+      <stop
+         id="stop2799"
+         offset="1"
+         style="stop-color:#7f7f7f;stop-opacity:0;" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4689"
+       id="linearGradient11109"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.562541,0,0,0.567972,-9.399749,-5.305317)"
+       x1="26.648937"
+       y1="20.603781"
+       x2="135.66525"
+       y2="114.39767" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4671"
+       id="linearGradient11111"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.562541,0,0,0.567972,-9.399749,-5.305317)"
+       x1="150.96111"
+       y1="192.35176"
+       x2="112.03144"
+       y2="137.27299" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2795"
+       id="radialGradient11113"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(2.382716e-8,-0.296405,1.43676,4.683673e-7,-128.544,150.5202)"
+       cx="61.518883"
+       cy="132.28575"
+       fx="61.518883"
+       fy="132.28575"
+       r="29.036913" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient5048"
+       id="linearGradient11177"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(2.774389,0,0,1.969706,-1892.179,-872.8854)"
+       x1="302.85715"
+       y1="366.64789"
+       x2="302.85715"
+       y2="609.50507" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient5060"
+       id="radialGradient11179"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(2.774389,0,0,1.969706,-1891.633,-872.8854)"
+       cx="605.71429"
+       cy="486.64789"
+       fx="605.71429"
+       fy="486.64789"
+       r="117.14286" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient5060"
+       id="radialGradient11181"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(-2.774389,0,0,1.969706,112.7623,-872.8854)"
+       cx="605.71429"
+       cy="486.64789"
+       fx="605.71429"
+       fy="486.64789"
+       r="117.14286" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient259"
+       id="radialGradient11183"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(0.960493,1.041132)"
+       cx="33.966679"
+       cy="35.736916"
+       fx="33.966679"
+       fy="35.736916"
+       r="86.70845" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient269"
+       id="radialGradient11185"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.968273,0,0,1.032767,3.353553,0.646447)"
+       cx="8.824419"
+       cy="3.7561285"
+       fx="8.824419"
+       fy="3.7561285"
+       r="37.751713" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient15662"
+       id="radialGradient11187"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.968273,0,0,1.032767,3.353553,0.646447)"
+       cx="8.1435566"
+       cy="7.2678967"
+       fx="8.1435566"
+       fy="7.2678967"
+       r="38.158695" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#aigrd2"
+       id="radialGradient11189"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.229703,0,0,0.229703,4.613529,3.979808)"
+       cx="20.892099"
+       cy="114.5684"
+       fx="20.892099"
+       fy="114.5684"
+       r="5.256" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#aigrd3"
+       id="radialGradient11191"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.229703,0,0,0.229703,4.613529,3.979808)"
+       cx="20.892099"
+       cy="64.567902"
+       fx="20.892099"
+       fy="64.567902"
+       r="5.257" />
+    <linearGradient
+       y2="31.026741"
+       x2="22.17771"
+       y1="33.357376"
+       x1="17.397203"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient1505"
+       xlink:href="#linearGradient2573-9"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="7.4121075"
+       x2="40.024059"
+       y1="4.2507305"
+       x1="11.841544"
+       gradientTransform="matrix(1.370928,0,0,-1.46456,2.525057,33.71269)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient1503"
+       xlink:href="#linearGradient9749-0"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="-7.5274644"
+       x2="17.178024"
+       y1="20.219761"
+       x1="10.027"
+       gradientTransform="matrix(1.570607,0,0,-1.231511,2.973436,33.33485)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient1501"
+       xlink:href="#linearGradient15107-6"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="11.981981"
+       x2="13.846983"
+       y1="11.48487"
+       x1="11.74217"
+       gradientTransform="matrix(1.296015,0,0,-1.43692,3.746576,33.20516)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient1497"
+       xlink:href="#linearGradient15107-6"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="11.981981"
+       x2="13.846983"
+       y1="11.48487"
+       x1="11.74217"
+       gradientTransform="matrix(1.276531,0,0,-1.406115,24.24763,33.3374)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient1493-0"
+       xlink:href="#linearGradient15107-6"
+       inkscape:collect="always" />
+    <radialGradient
+       r="17.977943"
+       fy="38.711506"
+       fx="27.741131"
+       cy="38.711506"
+       cx="27.741131"
+       gradientTransform="matrix(0.629929,0.459373,-0.147675,0.248512,16.51724,9.053737)"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient1491"
+       xlink:href="#linearGradient2274-9"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="52.090679"
+       x2="9.8855038"
+       y1="38.070892"
+       x1="9.1643066"
+       gradientTransform="matrix(2.454781,0,0,0.762004,2.88175,0.337386)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient1487"
+       xlink:href="#linearGradient2624-6"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="26.022909"
+       x2="18.475286"
+       y1="4.7461624"
+       x1="11.572842"
+       gradientTransform="matrix(1.343475,0,0,1.505846,2.879511,-2.266018)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient1483"
+       xlink:href="#linearGradient15107-6"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient4274-7">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0.25490198;"
+         offset="0.0000000"
+         id="stop4276-3" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop4278-5" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient15107-6">
+      <stop
+         id="stop15109-8"
+         offset="0.0000000"
+         style="stop-color:#ffffff;stop-opacity:1.0000000;" />
+      <stop
+         id="stop15111-9"
+         offset="1.0000000"
+         style="stop-color:#e2e2e2;stop-opacity:1.0000000;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient9749-0">
+      <stop
+         id="stop9751-2"
+         offset="0"
+         style="stop-color:#ffffff;stop-opacity:1;" />
+      <stop
+         id="stop9753-3"
+         offset="1.0000000"
+         style="stop-color:#ededed;stop-opacity:1.0000000;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient2274-9">
+      <stop
+         id="stop2276-4"
+         offset="0.0000000"
+         style="stop-color:#000000;stop-opacity:0.12871288;" />
+      <stop
+         id="stop2278-2"
+         offset="1.0000000"
+         style="stop-color:#000000;stop-opacity:0.0000000;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient2573-9"
+       inkscape:collect="always">
+      <stop
+         id="stop2575-9"
+         offset="0"
+         style="stop-color:#ffffff;stop-opacity:1;" />
+      <stop
+         id="stop2577-6"
+         offset="1"
+         style="stop-color:#ffffff;stop-opacity:0;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient2624-6">
+      <stop
+         style="stop-color:#dfe0df;stop-opacity:1;"
+         offset="0"
+         id="stop2626-1" />
+      <stop
+         id="stop2630-9"
+         offset="0.23809524"
+         style="stop-color:#a6b0a6;stop-opacity:1;" />
+      <stop
+         style="stop-color:#b5beb5;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop2628-4" />
+    </linearGradient>
+    <linearGradient
+       y2="609.50507"
+       x2="302.85715"
+       y1="366.64789"
+       x1="302.85715"
+       gradientTransform="matrix(2.774389,0,0,1.969706,-1892.179,-872.8854)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient5027"
+       xlink:href="#linearGradient5048-2"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient5048-2">
+      <stop
+         id="stop5050-7"
+         offset="0"
+         style="stop-color:black;stop-opacity:0;" />
+      <stop
+         style="stop-color:black;stop-opacity:1;"
+         offset="0.5"
+         id="stop5056-2" />
+      <stop
+         id="stop5052-01"
+         offset="1"
+         style="stop-color:black;stop-opacity:0;" />
+    </linearGradient>
+    <radialGradient
+       r="117.14286"
+       fy="486.64789"
+       fx="605.71429"
+       cy="486.64789"
+       cx="605.71429"
+       gradientTransform="matrix(2.774389,0,0,1.969706,-1891.633,-872.8854)"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient5029"
+       xlink:href="#linearGradient5060-4"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient5060-4"
+       inkscape:collect="always">
+      <stop
+         id="stop5062-24"
+         offset="0"
+         style="stop-color:black;stop-opacity:1;" />
+      <stop
+         id="stop5064-0"
+         offset="1"
+         style="stop-color:black;stop-opacity:0;" />
+    </linearGradient>
+    <radialGradient
+       r="117.14286"
+       fy="486.64789"
+       fx="605.71429"
+       cy="486.64789"
+       cx="605.71429"
+       gradientTransform="matrix(-2.774389,0,0,1.969706,112.7623,-872.8854)"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient5031"
+       xlink:href="#linearGradient5060-4"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient5048-3">
+      <stop
+         id="stop5050-23"
+         offset="0"
+         style="stop-color:black;stop-opacity:0;" />
+      <stop
+         style="stop-color:black;stop-opacity:1;"
+         offset="0.5"
+         id="stop5056-8" />
+      <stop
+         id="stop5052-05"
+         offset="1"
+         style="stop-color:black;stop-opacity:0;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient5060-5"
+       inkscape:collect="always">
+      <stop
+         id="stop5062-1"
+         offset="0"
+         style="stop-color:black;stop-opacity:1;" />
+      <stop
+         id="stop5064-5"
+         offset="1"
+         style="stop-color:black;stop-opacity:0;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient259-5">
+      <stop
+         style="stop-color:#fafafa;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop260-8" />
+      <stop
+         style="stop-color:#bbbbbb;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop261-9" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient269-3">
+      <stop
+         style="stop-color:#a3a3a3;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop270-6" />
+      <stop
+         style="stop-color:#4c4c4c;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop271-7" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient15662-6">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop15664-2" />
+      <stop
+         style="stop-color:#f8f8f8;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop15666-5" />
+    </linearGradient>
+    <radialGradient
+       gradientUnits="userSpaceOnUse"
+       fy="114.5684"
+       fx="20.892099"
+       r="5.256"
+       cy="114.5684"
+       cx="20.892099"
+       id="aigrd2-0">
+      <stop
+         id="stop15566-0"
+         style="stop-color:#F0F0F0"
+         offset="0" />
+      <stop
+         id="stop15568-0"
+         style="stop-color:#9a9a9a;stop-opacity:1.0000000;"
+         offset="1.0000000" />
+    </radialGradient>
+    <radialGradient
+       gradientUnits="userSpaceOnUse"
+       fy="64.567902"
+       fx="20.892099"
+       r="5.257"
+       cy="64.567902"
+       cx="20.892099"
+       id="aigrd3-2">
+      <stop
+         id="stop15573-8"
+         style="stop-color:#F0F0F0"
+         offset="0" />
+      <stop
+         id="stop15575-8"
+         style="stop-color:#9a9a9a;stop-opacity:1.0000000;"
+         offset="1.0000000" />
+    </radialGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient5048-3"
+       id="linearGradient13544"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(2.774389,0,0,1.969706,-1892.179,-872.8854)"
+       x1="302.85715"
+       y1="366.64789"
+       x2="302.85715"
+       y2="609.50507" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient5060-5"
+       id="radialGradient13546"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(2.774389,0,0,1.969706,-1891.633,-872.8854)"
+       cx="605.71429"
+       cy="486.64789"
+       fx="605.71429"
+       fy="486.64789"
+       r="117.14286" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient5060-5"
+       id="radialGradient13548"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(-2.774389,0,0,1.969706,112.7623,-872.8854)"
+       cx="605.71429"
+       cy="486.64789"
+       fx="605.71429"
+       fy="486.64789"
+       r="117.14286" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient259-5"
+       id="radialGradient13550"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(0.960493,1.041132)"
+       cx="33.966679"
+       cy="35.736916"
+       fx="33.966679"
+       fy="35.736916"
+       r="86.70845" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient269-3"
+       id="radialGradient13552"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.968273,0,0,1.032767,3.353553,0.646447)"
+       cx="8.824419"
+       cy="3.7561285"
+       fx="8.824419"
+       fy="3.7561285"
+       r="37.751713" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient15662-6"
+       id="radialGradient13554"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.968273,0,0,1.032767,3.353553,0.646447)"
+       cx="8.1435566"
+       cy="7.2678967"
+       fx="8.1435566"
+       fy="7.2678967"
+       r="38.158695" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#aigrd2-0"
+       id="radialGradient13556"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.229703,0,0,0.229703,4.613529,3.979808)"
+       cx="20.892099"
+       cy="114.5684"
+       fx="20.892099"
+       fy="114.5684"
+       r="5.256" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#aigrd3-2"
+       id="radialGradient13558"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.229703,0,0,0.229703,4.613529,3.979808)"
+       cx="20.892099"
+       cy="64.567902"
+       fx="20.892099"
+       fy="64.567902"
+       r="5.257" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient13629"
+       id="linearGradient13635"
+       x1="135"
+       y1="317.36218"
+       x2="105"
+       y2="237.36218"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       y2="248.6311"
+       x2="153.0005"
+       y1="15.4238"
+       x1="99.777298"
+       gradientUnits="userSpaceOnUse"
+       id="aigrd1">
+      <stop
+         id="stop53300"
+         style="stop-color:#184375"
+         offset="0" />
+      <stop
+         id="stop53302"
+         style="stop-color:#C8BDDC"
+         offset="1" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient2300">
+      <stop
+         style="stop-color:#000000;stop-opacity:0.32673267;"
+         offset="0.0000000"
+         id="stop2302" />
+      <stop
+         style="stop-color:#000000;stop-opacity:0;"
+         offset="1"
+         id="stop2304" />
+    </linearGradient>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2300"
+       id="radialGradient15544"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1.399258,-2.234445e-7,8.196178e-8,0.513264,4.365074,4.839285)"
+       cx="14.287618"
+       cy="68.872971"
+       fx="14.287618"
+       fy="72.568001"
+       r="11.68987" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#aigrd1"
+       id="linearGradient15546"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.200685,0,0,0.200685,-0.585758,-1.050787)"
+       x1="99.777298"
+       y1="15.4238"
+       x2="153.0005"
+       y2="248.6311" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient15558"
+       id="linearGradient15564"
+       x1="350"
+       y1="352.36218"
+       x2="350"
+       y2="272.36218"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient15568"
+       id="linearGradient15574"
+       x1="350"
+       y1="452.36218"
+       x2="340"
+       y2="342.36218"
+       gradientUnits="userSpaceOnUse" />
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="1.4"
+     inkscape:cx="249.31284"
+     inkscape:cy="117.69757"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     inkscape:window-width="1280"
+     inkscape:window-height="750"
+     inkscape:window-x="-1"
+     inkscape:window-y="26"
+     showgrid="true"
+     inkscape:window-maximized="1"
+     fit-margin-top="0"
+     fit-margin-left="0"
+     fit-margin-right="0"
+     fit-margin-bottom="0">
+    <inkscape:grid
+       type="xygrid"
+       id="grid10878"
+       empspacing="5"
+       visible="true"
+       enabled="true"
+       snapvisiblegridlinesonly="true"
+       color="#0000ff"
+       opacity="0.04705882" />
+  </sodipodi:namedview>
+  <metadata
+     id="metadata1906">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Taso 1"
+     inkscape:groupmode="layer"
+     id="layer1"
+     transform="translate(-60,-212.36218)">
+    <path
+       style="fill:url(#linearGradient15574);fill-opacity:1;stroke:none"
+       d="m 214,392.36218 25,-25 275,0 25,25 -25,25 -275,0 z"
+       id="path15566"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:url(#linearGradient15564);fill-opacity:1;stroke:none"
+       d="m 230,332.36218 0,-40 0,-10 290,0 0,50 -20,20 -90,0 0,5 -30,20 -30,-20 0,-5 -100,0 z"
+       id="path15548"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="ccccccccccccc" />
+    <path
+       style="fill:url(#linearGradient13635);fill-opacity:1;stroke:none"
+       d="m 70,287.36218 0,-60 230,0 20,20 0,45 -35,20 -35,-20 0,-5 z"
+       id="path13627"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="ccccccccc" />
+    <g
+       id="g10938"
+       transform="translate(0,0.21712644)">
+      <g
+         transform="matrix(0.69596564,0,0,0.69596564,116.34319,233.05094)"
+         id="g3694">
+        <g
+           id="layer6"
+           inkscape:label="Shadow">
+          <g
+             style="display:inline"
+             transform="matrix(0.02105461,0,0,0.02086758,42.85172,41.1536)"
+             id="g6707">
+            <rect
+               style="opacity:0.40206185;color:#000000;fill:url(#linearGradient11177);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible"
+               id="rect6709"
+               width="1339.6335"
+               height="478.35718"
+               x="-1559.2523"
+               y="-150.69685" />
+            <path
+               inkscape:connector-curvature="0"
+               style="opacity:0.40206185;color:#000000;fill:url(#radialGradient11179);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible"
+               d="m -219.61876,-150.68038 c 0,0 0,478.33079 0,478.33079 142.874166,0.90045 345.40022,-107.16966 345.40014,-239.196175 0,-132.026537 -159.436816,-239.134595 -345.40014,-239.134615 z"
+               id="path6711"
+               sodipodi:nodetypes="cccc" />
+            <path
+               inkscape:connector-curvature="0"
+               sodipodi:nodetypes="cccc"
+               id="path6713"
+               d="m -1559.2523,-150.68038 c 0,0 0,478.33079 0,478.33079 -142.8742,0.90045 -345.4002,-107.16966 -345.4002,-239.196175 0,-132.026537 159.4368,-239.134595 345.4002,-239.134615 z"
+               style="opacity:0.40206185;color:#000000;fill:url(#radialGradient11181);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible" />
+          </g>
+        </g>
+        <g
+           style="display:inline"
+           inkscape:label="Base"
+           id="layer1-8">
+          <rect
+             style="color:#000000;fill:url(#radialGradient11183);fill-opacity:1;fill-rule:nonzero;stroke:url(#radialGradient11185);stroke-width:1.43685257;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;marker:none;visibility:visible;display:block;overflow:visible"
+             id="rect15391"
+             width="34.875"
+             height="40.920494"
+             x="6.6035528"
+             y="3.6464462"
+             ry="1.1490486" />
+          <rect
+             style="color:#000000;fill:none;stroke:url(#radialGradient11187);stroke-width:1.43685257;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;marker:none;visibility:visible;display:block;overflow:visible"
+             id="rect15660"
+             width="32.775887"
+             height="38.946384"
+             x="7.6660538"
+             y="4.5839462"
+             ry="0.14904857"
+             rx="0.14904857" />
+          <g
+             transform="translate(0.646447,-0.03798933)"
+             id="g2270">
+            <g
+               id="g1440"
+               style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.43685257;stroke-miterlimit:4"
+               transform="matrix(0.229703,0,0,0.229703,4.967081,4.244972)">
+              <radialGradient
+                 id="radialGradient1442"
+                 cx="20.892099"
+                 cy="114.5684"
+                 r="5.256"
+                 fx="20.892099"
+                 fy="114.5684"
+                 gradientUnits="userSpaceOnUse">
+                <stop
+                   offset="0"
+                   style="stop-color:#F0F0F0"
+                   id="stop1444" />
+                <stop
+                   offset="1"
+                   style="stop-color:#474747"
+                   id="stop1446" />
+              </radialGradient>
+              <path
+                 inkscape:connector-curvature="0"
+                 style="stroke:none"
+                 d="m 23.428,113.07 c 0,1.973 -1.6,3.572 -3.573,3.572 -1.974,0 -3.573,-1.6 -3.573,-3.572 0,-1.974 1.6,-3.573 3.573,-3.573 1.973,0 3.573,1.6 3.573,3.573 z"
+                 id="path1448" />
+              <radialGradient
+                 id="radialGradient1450"
+                 cx="20.892099"
+                 cy="64.567902"
+                 r="5.257"
+                 fx="20.892099"
+                 fy="64.567902"
+                 gradientUnits="userSpaceOnUse">
+                <stop
+                   offset="0"
+                   style="stop-color:#F0F0F0"
+                   id="stop1452" />
+                <stop
+                   offset="1"
+                   style="stop-color:#474747"
+                   id="stop1454" />
+              </radialGradient>
+              <path
+                 inkscape:connector-curvature="0"
+                 style="stroke:none"
+                 d="m 23.428,63.07 c 0,1.973 -1.6,3.573 -3.573,3.573 -1.974,0 -3.573,-1.6 -3.573,-3.573 0,-1.974 1.6,-3.573 3.573,-3.573 1.973,0 3.573,1.6 3.573,3.573 z"
+                 id="path1456" />
+            </g>
+            <path
+               inkscape:connector-curvature="0"
+               style="fill:url(#radialGradient11189);fill-rule:nonzero;stroke:none"
+               d="m 9.9950109,29.952326 c 0,0.453204 -0.3675248,0.820499 -0.8207288,0.820499 -0.4534338,0 -0.8207289,-0.367524 -0.8207289,-0.820499 0,-0.453434 0.3675248,-0.820729 0.8207289,-0.820729 0.453204,0 0.8207288,0.367525 0.8207288,0.820729 z"
+               id="path15570" />
+            <path
+               inkscape:connector-curvature="0"
+               style="fill:url(#radialGradient11191);fill-rule:nonzero;stroke:none"
+               d="m 9.9950109,18.467176 c 0,0.453204 -0.3675248,0.820729 -0.8207288,0.820729 -0.4534338,0 -0.8207289,-0.367525 -0.8207289,-0.820729 0,-0.453434 0.3675248,-0.820729 0.8207289,-0.820729 0.453204,0 0.8207288,0.367525 0.8207288,0.820729 z"
+               id="path15577" />
+          </g>
+          <path
+             inkscape:connector-curvature="0"
+             style="fill:none;stroke:#000000;stroke-width:1.42040503;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0.01754384"
+             d="m 11.505723,5.4942766 0,37.9065924"
+             id="path15672"
+             sodipodi:nodetypes="cc" />
+          <path
+             inkscape:connector-curvature="0"
+             style="fill:none;stroke:#ffffff;stroke-width:1.43685257;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0.20467828"
+             d="m 12.5,5.0205154 0,38.0177126"
+             id="path15674"
+             sodipodi:nodetypes="cc" />
+        </g>
+        <g
+           id="layer5"
+           inkscape:label="Text"
+           style="display:inline">
+          <rect
+             ry="0.065390877"
+             rx="0.13778631"
+             y="9"
+             x="15.999994"
+             height="1"
+             width="20.000006"
+             id="rect15686"
+             style="color:#000000;fill:#9b9b9b;fill-opacity:0.54970757;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible" />
+          <rect
+             ry="0.065390877"
+             rx="0.13778631"
+             y="11"
+             x="15.999994"
+             height="1"
+             width="20.000006"
+             id="rect15688"
+             style="color:#000000;fill:#9b9b9b;fill-opacity:0.54970757;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible" />
+          <rect
+             ry="0.065390877"
+             rx="0.13778631"
+             y="13"
+             x="15.999994"
+             height="1"
+             width="20.000006"
+             id="rect15690"
+             style="color:#000000;fill:#9b9b9b;fill-opacity:0.54970757;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible" />
+          <rect
+             ry="0.065390877"
+             rx="0.13778631"
+             y="15"
+             x="15.999994"
+             height="1"
+             width="20.000006"
+             id="rect15692"
+             style="color:#000000;fill:#9b9b9b;fill-opacity:0.54970757;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible" />
+          <rect
+             ry="0.065390877"
+             rx="0.13778631"
+             y="17"
+             x="15.999994"
+             height="1"
+             width="20.000006"
+             id="rect15694"
+             style="color:#000000;fill:#9b9b9b;fill-opacity:0.54970757;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible" />
+          <rect
+             ry="0.065390877"
+             rx="0.13778631"
+             y="19"
+             x="15.999994"
+             height="1"
+             width="20.000006"
+             id="rect15696"
+             style="color:#000000;fill:#9b9b9b;fill-opacity:0.54970757;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible" />
+          <rect
+             ry="0.065390877"
+             rx="0.13778631"
+             y="21"
+             x="15.999994"
+             height="1"
+             width="20.000006"
+             id="rect15698"
+             style="color:#000000;fill:#9b9b9b;fill-opacity:0.54970757;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible" />
+          <rect
+             ry="0.065390877"
+             rx="0.13778631"
+             y="23"
+             x="15.999994"
+             height="1"
+             width="20.000006"
+             id="rect15700"
+             style="color:#000000;fill:#9b9b9b;fill-opacity:0.54970757;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible" />
+          <rect
+             ry="0.065390877"
+             rx="0.062003858"
+             y="25"
+             x="15.999986"
+             height="1"
+             width="9.0000057"
+             id="rect15732"
+             style="color:#000000;fill:#9b9b9b;fill-opacity:0.54970757;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible" />
+          <g
+             id="g4849">
+            <rect
+               style="color:#000000;fill:#9b9b9b;fill-opacity:0.54970757;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible"
+               id="rect15736"
+               width="20.000006"
+               height="1"
+               x="15.999986"
+               y="29"
+               rx="0.13778631"
+               ry="0.065390877" />
+            <rect
+               style="color:#000000;fill:#9b9b9b;fill-opacity:0.54970757;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible"
+               id="rect15738"
+               width="20.000006"
+               height="1"
+               x="15.999986"
+               y="31"
+               rx="0.13778631"
+               ry="0.065390877" />
+            <rect
+               style="color:#000000;fill:#9b9b9b;fill-opacity:0.54970757;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible"
+               id="rect15740"
+               width="20.000006"
+               height="1"
+               x="15.999986"
+               y="33"
+               rx="0.13778631"
+               ry="0.065390877" />
+            <rect
+               style="color:#000000;fill:#9b9b9b;fill-opacity:0.54970757;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible"
+               id="rect15742"
+               width="20.000006"
+               height="1"
+               x="15.999986"
+               y="35"
+               rx="0.13778631"
+               ry="0.065390877" />
+            <rect
+               style="color:#000000;fill:#9b9b9b;fill-opacity:0.54970757;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible"
+               id="rect15744"
+               width="14.000014"
+               height="1"
+               x="15.999986"
+               y="37"
+               rx="0.096450485"
+               ry="0.065390877" />
+          </g>
+        </g>
+      </g>
+      <text
+         sodipodi:linespacing="125%"
+         id="text7676"
+         y="279.34702"
+         x="85.84211"
+         style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:FreeSans;-inkscape-font-specification:FreeSans"
+         xml:space="preserve"><tspan
+           y="279.34702"
+           x="85.84211"
+           id="tspan7678"
+           sodipodi:role="line">MyMessage.proto</tspan></text>
+    </g>
+    <g
+       id="g11049"
+       transform="translate(74.824219,-16)">
+      <text
+         sodipodi:linespacing="125%"
+         id="text7692"
+         y="408.36218"
+         x="269.17578"
+         style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:FreeSans;-inkscape-font-specification:FreeSans"
+         xml:space="preserve"><tspan
+           y="408.36218"
+           x="269.17578"
+           id="tspan7694"
+           sodipodi:role="line">pb_encode( );</tspan></text>
+      <text
+         sodipodi:linespacing="125%"
+         id="text7696"
+         y="421.36218"
+         x="269"
+         style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:FreeSans;-inkscape-font-specification:FreeSans"
+         xml:space="preserve"><tspan
+           y="421.36218"
+           x="269"
+           id="tspan7698"
+           sodipodi:role="line">pb_decode( );</tspan></text>
+    </g>
+    <g
+       id="g10981"
+       transform="translate(40.612196,-41.994574)">
+      <text
+         sodipodi:linespacing="125%"
+         id="text7688"
+         y="321.55872"
+         x="161.02837"
+         style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:FreeSans;-inkscape-font-specification:FreeSans"
+         xml:space="preserve"><tspan
+           y="321.55872"
+           x="161.02837"
+           id="tspan7690"
+           sodipodi:role="line">nanopb_generator.py</tspan></text>
+      <g
+         transform="matrix(0.20866613,0,0,0.20866613,166.72161,281.75965)"
+         id="g10620">
+        <path
+           inkscape:connector-curvature="0"
+           id="path46"
+           style="fill:#646464;fill-opacity:1"
+           d="m 184.61344,61.929363 c 0,-14.56215 -4.15226,-22.03817 -12.45678,-22.44755 -3.30427,-0.15595 -6.53055,0.37039 -9.66912,1.58878 -2.505,0.89673 -4.19124,1.78372 -5.07823,2.68045 l 0,34.75812 c 5.31216,3.33351 10.02976,4.88329 14.14303,4.63962 8.70415,-0.57508 13.0611,-7.64172 13.0611,-21.21942 z m 10.24419,0.60432 c 0,7.39804 -1.73498,13.53871 -5.22444,18.422 -3.88909,5.5266 -9.27923,8.37275 -16.17042,8.52871 -5.1952,0.1657 -10.54635,-1.46207 -16.05346,-4.87355 l 0,31.590317 -8.90884,-3.17755 0,-70.120567 c 1.46206,-1.79346 3.34325,-3.3335 5.62407,-4.63961 5.30242,-3.08983 11.74524,-4.67861 19.32848,-4.75658 l 0.12671,0.12671 c 6.93018,-0.08773 12.27159,2.75843 16.02422,8.5287 3.4992,5.29267 5.25368,12.07665 5.25368,20.37142 z" />
+        <path
+           inkscape:connector-curvature="0"
+           id="path48"
+           style="fill:#646464;fill-opacity:1"
+           d="m 249.30487,83.265743 c 0,9.92254 -0.9942,16.794237 -2.9826,20.615097 -1.99816,3.82086 -5.79952,6.8717 -11.41385,9.14277 -4.55189,1.79346 -9.47417,2.76817 -14.75709,2.93387 l -1.47181,-5.61432 c 5.37064,-0.73103 9.15252,-1.46207 11.34561,-2.1931 4.31796,-1.46206 7.28108,-3.70389 8.90884,-6.706 1.30611,-2.446517 1.94942,-7.115367 1.94942,-14.026057 l 0,-2.3198 c -6.09193,2.76817 -12.47628,4.14251 -19.15303,4.14251 -4.38619,0 -8.25579,-1.37434 -11.58929,-4.14251 -3.74289,-3.01186 -5.61433,-6.83272 -5.61433,-11.46258 l 0,-37.07793 8.90884,-3.05084 0,37.3216 c 0,3.98656 1.28662,7.0569 3.85985,9.21101 2.57323,2.1541 5.90674,3.18729 9.99077,3.10932 4.08403,-0.08773 8.46047,-1.66676 13.10983,-4.75658 l 0,-43.54025 8.90884,0 0,48.41379 z" />
+        <path
+           inkscape:connector-curvature="0"
+           id="path50"
+           style="fill:#646464;fill-opacity:1"
+           d="m 284.08249,88.997033 c -1.06243,0.08772 -2.03714,0.12671 -2.93387,0.12671 -5.03925,0 -8.96733,-1.19889 -11.77449,-3.60642 -2.79742,-2.40753 -4.20099,-5.73129 -4.20099,-9.97127 l 0,-35.08953 -6.10168,0 0,-5.60457 6.10168,0 0,-14.88381 8.89909,-3.16781 0,18.05162 10.01026,0 0,5.60457 -10.01026,0 0,34.84585 c 0,3.34325 0.89673,5.71179 2.6902,7.09588 1.54004,1.14041 3.98656,1.79347 7.32006,1.95917 l 0,4.63961 z" />
+        <path
+           inkscape:connector-curvature="0"
+           id="path52"
+           style="fill:#646464;fill-opacity:1"
+           d="m 338.02288,88.266003 -8.90884,0 0,-34.38773 c 0,-3.49921 -0.81876,-6.51106 -2.44651,-9.02581 -1.88119,-2.84615 -4.49342,-4.26923 -7.84641,-4.26923 -4.08404,0 -9.19152,2.15411 -15.32242,6.46233 l 0,41.22044 -8.90885,0 0,-82.1972101 8.90885,-2.80716 0,37.4385701 c 5.6923,-4.14251 11.91093,-6.21864 18.66566,-6.21864 4.7176,0 8.53846,1.58877 11.46258,4.75658 2.93388,3.1678 4.39594,7.11537 4.39594,11.83296 l 0,37.1949 0,0 z" />
+        <path
+           inkscape:connector-curvature="0"
+           id="path54"
+           style="fill:#646464;fill-opacity:1"
+           d="m 385.37424,60.525783 c 0,-5.59483 -1.06242,-10.21495 -3.17755,-13.87011 -2.51474,-4.45442 -6.42332,-6.80347 -11.70625,-7.04715 -9.76658,0.56534 -14.64012,7.56375 -14.64012,20.97574 0,6.15042 1.01369,11.28713 3.06057,15.41015 2.61223,5.25368 6.53056,7.84641 11.755,7.75869 9.80557,-0.07798 14.70835,-7.81717 14.70835,-23.22732 z m 9.75685,0.05848 c 0,7.96338 -2.03714,14.5914 -6.10168,19.88407 -4.47391,5.92623 -10.65357,8.89909 -18.53897,8.89909 -7.81716,0 -13.90909,-2.97286 -18.30503,-8.89909 -3.98656,-5.29267 -5.97497,-11.92069 -5.97497,-19.88407 0,-7.48576 2.15411,-13.78238 6.46232,-18.90935 4.5519,-5.43888 10.53661,-8.16806 17.93464,-8.16806 7.39805,0 13.42174,2.72918 18.06137,8.16806 4.3082,5.12697 6.46232,11.42359 6.46232,18.90935 z" />
+        <path
+           inkscape:connector-curvature="0"
+           id="path56"
+           style="fill:#646464;fill-opacity:1"
+           d="m 446.20583,88.266003 -8.90884,0 0,-36.33715 c 0,-3.98656 -1.19889,-7.09588 -3.59667,-9.33772 -2.39779,-2.23208 -5.59483,-3.31401 -9.58139,-3.22628 -4.23023,0.07798 -8.25579,1.46206 -12.07664,4.14251 l 0,44.75864 -8.90884,0 0,-45.86006 c 5.12697,-3.73313 9.84456,-6.16991 14.15276,-7.31032 4.06455,-1.06243 7.65148,-1.58877 10.74131,-1.58877 2.11512,0 4.10352,0.20469 5.97496,0.61406 3.49921,0.80901 6.34535,2.31006 8.53845,4.51291 2.44651,2.43677 3.6649,5.3609 3.6649,8.78212 l 0,40.85006 z" />
+        <path
+           inkscape:connector-curvature="0"
+           style="fill:url(#linearGradient11109);fill-opacity:1"
+           d="m 60.510156,6.3979729 c -4.583653,0.021298 -8.960939,0.4122177 -12.8125,1.09375 C 36.35144,9.4962267 34.291407,13.691825 34.291406,21.429223 l 0,10.21875 26.8125,0 0,3.40625 -26.8125,0 -10.0625,0 c -7.792459,0 -14.6157592,4.683717 -16.7500002,13.59375 -2.46182,10.212966 -2.5710151,16.586023 0,27.25 1.9059283,7.937852 6.4575432,13.593748 14.2500002,13.59375 l 9.21875,0 0,-12.25 c 0,-8.849902 7.657144,-16.656248 16.75,-16.65625 l 26.78125,0 c 7.454951,0 13.406253,-6.138164 13.40625,-13.625 l 0,-25.53125 c 0,-7.266339 -6.12998,-12.7247775 -13.40625,-13.9375001 -4.605987,-0.7667253 -9.385097,-1.1150483 -13.96875,-1.09375 z m -14.5,8.2187501 c 2.769547,0 5.03125,2.298646 5.03125,5.125 -2e-6,2.816336 -2.261703,5.09375 -5.03125,5.09375 -2.779476,-1e-6 -5.03125,-2.277415 -5.03125,-5.09375 -1e-6,-2.826353 2.251774,-5.125 5.03125,-5.125 z"
+           id="path1948" />
+        <path
+           inkscape:connector-curvature="0"
+           style="fill:url(#linearGradient11111);fill-opacity:1"
+           d="m 91.228906,35.054223 0,11.90625 c 0,9.230755 -7.825895,16.999999 -16.75,17 l -26.78125,0 c -7.335833,0 -13.406249,6.278483 -13.40625,13.625 l 0,25.531247 c 0,7.26634 6.318588,11.54032 13.40625,13.625 8.487331,2.49561 16.626237,2.94663 26.78125,0 6.750155,-1.95439 13.406253,-5.88761 13.40625,-13.625 l 0,-10.218747 -26.78125,0 0,-3.40625 26.78125,0 13.406254,0 c 7.79246,0 10.69625,-5.435408 13.40624,-13.59375 2.79933,-8.398886 2.68022,-16.475776 0,-27.25 -1.92578,-7.757441 -5.60387,-13.59375 -13.40624,-13.59375 l -10.062504,0 z m -15.0625,64.65625 c 2.779478,3e-6 5.03125,2.277417 5.03125,5.093747 -2e-6,2.82635 -2.251775,5.125 -5.03125,5.125 -2.76955,0 -5.03125,-2.29865 -5.03125,-5.125 2e-6,-2.81633 2.261697,-5.093747 5.03125,-5.093747 z"
+           id="path1950" />
+        <path
+           inkscape:connector-curvature="0"
+           d="m 463.5544,26.909383 1.56195,0 0,-9.79624 3.70013,0 0,-1.16766 -8.96221,0 0,1.16766 3.70013,0 0,9.79624 m 6.64702,0 1.33447,0 0,-8.94703 2.89641,8.945906 1.48569,0 3.01816,-8.915576 0,8.9167 1.45579,0 0,-10.9639 -1.92589,0 -3.29831,9.392857 -2.81297,-9.392857 -2.15335,0 0,10.9639"
+           style="font-size:15.16445827px;font-style:normal;font-weight:normal;line-height:125%;fill:#646464;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
+           id="text3004"
+           sodipodi:nodetypes="ccccccccccccccccccccccc" />
+        <path
+           sodipodi:type="arc"
+           style="opacity:0.44382019;fill:url(#radialGradient11113);fill-opacity:1;fill-rule:nonzero;stroke:none"
+           id="path1894"
+           sodipodi:cx="61.518883"
+           sodipodi:cy="132.28575"
+           sodipodi:rx="48.948284"
+           sodipodi:ry="8.6066771"
+           d="m 110.46717,132.28575 c 0,4.75334 -21.914896,8.60668 -48.948287,8.60668 -27.033391,0 -48.948284,-3.85334 -48.948284,-8.60668 0,-4.75334 21.914893,-8.60668 48.948284,-8.60668 27.033391,0 48.948287,3.85334 48.948287,8.60668 z"
+           transform="matrix(0.73406,0,0,0.809524,16.24958,27.00935)" />
+      </g>
+    </g>
+    <g
+       transform="translate(221.34207,203.5191)"
+       id="g10632">
+      <g
+         id="g10678"
+         inkscape:label="Text"
+         style="display:inline" />
+    </g>
+    <g
+       id="g13491"
+       transform="translate(24.020135,-23.566724)">
+      <text
+         sodipodi:linespacing="125%"
+         id="text7680"
+         y="360.05713"
+         x="215.79094"
+         style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:FreeSans;-inkscape-font-specification:FreeSans"
+         xml:space="preserve"><tspan
+           y="360.05713"
+           x="215.79094"
+           id="tspan7682"
+           sodipodi:role="line">MyMessage.pb.c</tspan></text>
+      <text
+         sodipodi:linespacing="125%"
+         id="text7684"
+         y="346.05713"
+         x="215.73695"
+         style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:FreeSans;-inkscape-font-specification:FreeSans"
+         xml:space="preserve"><tspan
+           y="346.05713"
+           x="215.73695"
+           id="tspan7686"
+           sodipodi:role="line">MyMessage.pb.h</tspan></text>
+    </g>
+    <g
+       id="g13560"
+       transform="translate(1.7323942,-7.4432063)">
+      <g
+         transform="matrix(0.69596564,0,0,0.69596564,207.04204,157.31974)"
+         id="g10800-7">
+        <g
+           transform="translate(221.34207,203.5191)"
+           id="g10634-0"
+           inkscape:label="Shadow">
+          <g
+             style="display:inline"
+             transform="matrix(0.02105461,0,0,0.02086758,42.85172,41.1536)"
+             id="g10636-1">
+            <rect
+               style="opacity:0.40206185;color:#000000;fill:url(#linearGradient13544);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible"
+               id="rect10638-5"
+               width="1339.6335"
+               height="478.35718"
+               x="-1559.2523"
+               y="-150.69685" />
+            <path
+               inkscape:connector-curvature="0"
+               style="opacity:0.40206185;color:#000000;fill:url(#radialGradient13546);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible"
+               d="m -219.61876,-150.68038 c 0,0 0,478.33079 0,478.33079 142.874166,0.90045 345.40022,-107.16966 345.40014,-239.196175 0,-132.026537 -159.436816,-239.134595 -345.40014,-239.134615 z"
+               id="path10640-0"
+               sodipodi:nodetypes="cccc" />
+            <path
+               inkscape:connector-curvature="0"
+               sodipodi:nodetypes="cccc"
+               id="path10642-8"
+               d="m -1559.2523,-150.68038 c 0,0 0,478.33079 0,478.33079 -142.8742,0.90045 -345.4002,-107.16966 -345.4002,-239.196175 0,-132.026537 159.4368,-239.134595 345.4002,-239.134615 z"
+               style="opacity:0.40206185;color:#000000;fill:url(#radialGradient13548);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible" />
+          </g>
+        </g>
+        <g
+           transform="translate(221.34207,203.5191)"
+           style="display:inline"
+           inkscape:label="Base"
+           id="g10644-0">
+          <rect
+             style="color:#000000;fill:url(#radialGradient13550);fill-opacity:1;fill-rule:nonzero;stroke:url(#radialGradient13552);stroke-width:1.43685257;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;marker:none;visibility:visible;display:block;overflow:visible"
+             id="rect10646-7"
+             width="34.875"
+             height="40.920494"
+             x="6.6035528"
+             y="3.6464462"
+             ry="1.1490486" />
+          <rect
+             style="color:#000000;fill:none;stroke:url(#radialGradient13554);stroke-width:1.43685257;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;marker:none;visibility:visible;display:block;overflow:visible"
+             id="rect10648-1"
+             width="32.775887"
+             height="38.946384"
+             x="7.6660538"
+             y="4.5839462"
+             ry="0.14904857"
+             rx="0.14904857" />
+          <g
+             transform="translate(0.646447,-0.03798933)"
+             id="g10650-5">
+            <g
+               id="g10652-1"
+               style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.43685257;stroke-miterlimit:4"
+               transform="matrix(0.229703,0,0,0.229703,4.967081,4.244972)">
+              <radialGradient
+                 id="radialGradient10654-3"
+                 cx="20.892099"
+                 cy="114.5684"
+                 r="5.256"
+                 fx="20.892099"
+                 fy="114.5684"
+                 gradientUnits="userSpaceOnUse">
+                <stop
+                   offset="0"
+                   style="stop-color:#F0F0F0"
+                   id="stop10656-3" />
+                <stop
+                   offset="1"
+                   style="stop-color:#474747"
+                   id="stop10658-9" />
+              </radialGradient>
+              <path
+                 inkscape:connector-curvature="0"
+                 style="stroke:none"
+                 d="m 23.428,113.07 c 0,1.973 -1.6,3.572 -3.573,3.572 -1.974,0 -3.573,-1.6 -3.573,-3.572 0,-1.974 1.6,-3.573 3.573,-3.573 1.973,0 3.573,1.6 3.573,3.573 z"
+                 id="path10660-4" />
+              <radialGradient
+                 id="radialGradient10662-8"
+                 cx="20.892099"
+                 cy="64.567902"
+                 r="5.257"
+                 fx="20.892099"
+                 fy="64.567902"
+                 gradientUnits="userSpaceOnUse">
+                <stop
+                   offset="0"
+                   style="stop-color:#F0F0F0"
+                   id="stop10664-2" />
+                <stop
+                   offset="1"
+                   style="stop-color:#474747"
+                   id="stop10666-3" />
+              </radialGradient>
+              <path
+                 inkscape:connector-curvature="0"
+                 style="stroke:none"
+                 d="m 23.428,63.07 c 0,1.973 -1.6,3.573 -3.573,3.573 -1.974,0 -3.573,-1.6 -3.573,-3.573 0,-1.974 1.6,-3.573 3.573,-3.573 1.973,0 3.573,1.6 3.573,3.573 z"
+                 id="path10668-6" />
+            </g>
+            <path
+               inkscape:connector-curvature="0"
+               style="fill:url(#radialGradient13556);fill-rule:nonzero;stroke:none"
+               d="m 9.9950109,29.952326 c 0,0.453204 -0.3675248,0.820499 -0.8207288,0.820499 -0.4534338,0 -0.8207289,-0.367524 -0.8207289,-0.820499 0,-0.453434 0.3675248,-0.820729 0.8207289,-0.820729 0.453204,0 0.8207288,0.367525 0.8207288,0.820729 z"
+               id="path10670-0" />
+            <path
+               inkscape:connector-curvature="0"
+               style="fill:url(#radialGradient13558);fill-rule:nonzero;stroke:none"
+               d="m 9.9950109,18.467176 c 0,0.453204 -0.3675248,0.820729 -0.8207288,0.820729 -0.4534338,0 -0.8207289,-0.367525 -0.8207289,-0.820729 0,-0.453434 0.3675248,-0.820729 0.8207289,-0.820729 0.453204,0 0.8207288,0.367525 0.8207288,0.820729 z"
+               id="path10672-9" />
+          </g>
+          <path
+             inkscape:connector-curvature="0"
+             style="fill:none;stroke:#000000;stroke-width:1.42040503;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0.01754384"
+             d="m 11.505723,5.4942766 0,37.9065924"
+             id="path10674-0"
+             sodipodi:nodetypes="cc" />
+          <path
+             inkscape:connector-curvature="0"
+             style="fill:none;stroke:#ffffff;stroke-width:1.43685257;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0.20467828"
+             d="m 12.5,5.0205154 0,38.0177126"
+             id="path10676-7"
+             sodipodi:nodetypes="cc" />
+        </g>
+        <rect
+           transform="translate(221.34207,203.5191)"
+           ry="0.065390877"
+           rx="0.13778631"
+           y="9"
+           x="15.999994"
+           height="1"
+           width="20.000006"
+           id="rect10680-0"
+           style="color:#000000;fill:#9b9b9b;fill-opacity:0.54970757;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible" />
+        <rect
+           transform="translate(221.34207,203.5191)"
+           ry="0.065390877"
+           rx="0.010779859"
+           y="11"
+           x="15.999994"
+           height="1"
+           width="1.5647217"
+           id="rect10682-2"
+           style="color:#000000;fill:#9b9b9b;fill-opacity:0.54970757;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible" />
+        <rect
+           transform="translate(221.34207,203.5191)"
+           ry="0.065390877"
+           rx="0.071673371"
+           y="13"
+           x="18.272837"
+           height="1"
+           width="10.403558"
+           id="rect10684-0"
+           style="color:#000000;fill:#9b9b9b;fill-opacity:0.54970757;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible" />
+        <rect
+           transform="translate(221.34207,203.5191)"
+           ry="0.065390877"
+           rx="0.093421049"
+           y="15"
+           x="18.272837"
+           height="1"
+           width="13.560284"
+           id="rect10686-0"
+           style="color:#000000;fill:#9b9b9b;fill-opacity:0.54970757;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible" />
+        <rect
+           transform="translate(221.34207,203.5191)"
+           ry="0.065390877"
+           rx="0.074283093"
+           y="17"
+           x="18.272837"
+           height="1"
+           width="10.782365"
+           id="rect10688-0"
+           style="color:#000000;fill:#9b9b9b;fill-opacity:0.54970757;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible" />
+        <rect
+           transform="translate(221.34207,203.5191)"
+           ry="0.065390877"
+           rx="0.010779865"
+           y="19"
+           x="18.272837"
+           height="1"
+           width="1.5647227"
+           id="rect10690-4"
+           style="color:#000000;fill:#9b9b9b;fill-opacity:0.54970757;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible" />
+        <rect
+           transform="translate(221.34207,203.5191)"
+           ry="0.065390877"
+           rx="0.041226614"
+           y="21"
+           x="20.166874"
+           height="1"
+           width="5.984139"
+           id="rect10692-0"
+           style="color:#000000;fill:#9b9b9b;fill-opacity:0.54970757;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible" />
+        <rect
+           transform="translate(221.34207,203.5191)"
+           ry="0.065390877"
+           rx="0.031657632"
+           y="23"
+           x="18.146568"
+           height="1"
+           width="4.5951796"
+           id="rect10694-8"
+           style="color:#000000;fill:#9b9b9b;fill-opacity:0.54970757;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible" />
+        <rect
+           transform="translate(221.34207,203.5191)"
+           ry="0.065390877"
+           rx="0.064613581"
+           y="25"
+           x="20.040596"
+           height="1"
+           width="9.3788128"
+           id="rect10696-1"
+           style="color:#000000;fill:#9b9b9b;fill-opacity:0.54970757;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible" />
+        <rect
+           transform="translate(221.34207,203.5191)"
+           style="color:#000000;fill:#9b9b9b;fill-opacity:0.54970757;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible"
+           id="rect10730-1"
+           width="1.5501302"
+           height="1"
+           x="18.166864"
+           y="27"
+           rx="0.010679333"
+           ry="0.065390877" />
+        <rect
+           transform="translate(221.34207,203.5191)"
+           style="color:#000000;fill:#9b9b9b;fill-opacity:0.54970757;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible"
+           id="rect10732-9"
+           width="1.5647217"
+           height="1"
+           x="15.999994"
+           y="29"
+           rx="0.010779859"
+           ry="0.065390877" />
+        <rect
+           transform="translate(221.34207,203.5191)"
+           style="color:#000000;fill:#9b9b9b;fill-opacity:0.54970757;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible"
+           id="rect10734-9"
+           width="9.2671347"
+           height="1"
+           x="15.999994"
+           y="33"
+           rx="0.063844196"
+           ry="0.065390877" />
+        <rect
+           transform="translate(221.34207,203.5191)"
+           style="color:#000000;fill:#9b9b9b;fill-opacity:0.54970757;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible"
+           id="rect10736-3"
+           width="1.5647217"
+           height="1"
+           x="15.999994"
+           y="35"
+           rx="0.010779859"
+           ry="0.065390877" />
+        <rect
+           transform="translate(221.34207,203.5191)"
+           style="color:#000000;fill:#9b9b9b;fill-opacity:0.54970757;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible"
+           id="rect10738-9"
+           width="8.7620602"
+           height="1"
+           x="18.272837"
+           y="37"
+           rx="0.060364578"
+           ry="0.065390877" />
+        <rect
+           transform="translate(221.34207,203.5191)"
+           style="color:#000000;fill:#9b9b9b;fill-opacity:0.54970757;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible"
+           id="rect10740-9"
+           width="10.277287"
+           height="1"
+           x="18.272837"
+           y="39"
+           rx="0.070803463"
+           ry="0.065390877" />
+        <rect
+           transform="translate(221.34207,203.5191)"
+           style="color:#000000;fill:#555753;fill-opacity:0.54970757;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible"
+           id="rect10742-1"
+           width="1.5647227"
+           height="1"
+           x="19.43354"
+           y="23"
+           rx="0.010779865"
+           ry="0.065390877" />
+        <rect
+           transform="translate(221.34207,203.5191)"
+           ry="0.065390877"
+           rx="0.010779865"
+           y="16.928572"
+           x="18.272825"
+           height="1"
+           width="1.5647227"
+           id="rect10744-2"
+           style="color:#000000;fill:#555753;fill-opacity:0.54970757;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible" />
+        <rect
+           transform="translate(221.34207,203.5191)"
+           style="color:#000000;fill:#75507b;fill-opacity:0.54970757;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible"
+           id="rect10746-6"
+           width="3.9754369"
+           height="1"
+           x="15.951397"
+           y="8.9821434"
+           rx="0.027388033"
+           ry="0.065390877" />
+        <rect
+           transform="translate(221.34207,203.5191)"
+           ry="0.065390877"
+           rx="0.021236859"
+           y="13.000001"
+           x="18.272825"
+           height="1"
+           width="3.0825799"
+           id="rect10748-4"
+           style="color:#000000;fill:#75507b;fill-opacity:0.54970757;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible" />
+        <rect
+           transform="translate(221.34207,203.5191)"
+           style="color:#000000;fill:#75507b;fill-opacity:0.54970757;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible"
+           id="rect10750-7"
+           width="3.0825799"
+           height="1"
+           x="18.36211"
+           y="14.964287"
+           rx="0.021236859"
+           ry="0.065390877" />
+        <rect
+           transform="translate(221.34207,203.5191)"
+           ry="0.065390877"
+           rx="0.014470569"
+           y="33"
+           x="15.86211"
+           height="1"
+           width="2.1004369"
+           id="rect10752-9"
+           style="color:#000000;fill:#75507b;fill-opacity:0.54970757;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible" />
+        <rect
+           transform="translate(221.34207,203.5191)"
+           style="color:#000000;fill:#75507b;fill-opacity:0.54970757;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible"
+           id="rect10754-3"
+           width="2.1004369"
+           height="1"
+           x="18.272825"
+           y="36.92857"
+           rx="0.014470569"
+           ry="0.065390877" />
+        <text
+           xml:space="preserve"
+           style="font-size:22.49356079px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#2e3436;fill-opacity:1;stroke:none;font-family:FreeSans;-inkscape-font-specification:FreeSans"
+           x="247.85315"
+           y="242.62157"
+           id="text10726-2"
+           sodipodi:linespacing="125%"><tspan
+             sodipodi:role="line"
+             id="tspan10728-8"
+             x="247.85315"
+             y="242.62157">c</tspan></text>
+      </g>
+      <text
+         xml:space="preserve"
+         style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:FreeSans;-inkscape-font-specification:FreeSans"
+         x="339"
+         y="345.36218"
+         id="text13355"
+         sodipodi:linespacing="125%"><tspan
+           sodipodi:role="line"
+           id="tspan13357"
+           x="339"
+           y="345.36218">Nanopb library</tspan></text>
+    </g>
+    <g
+       id="g11071"
+       transform="translate(81.439632,-41.53157)">
+      <g
+         id="g12984">
+        <text
+           xml:space="preserve"
+           style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:FreeSans;-inkscape-font-specification:FreeSans"
+           x="193"
+           y="442.36218"
+           id="text10864"
+           sodipodi:linespacing="125%"><tspan
+             sodipodi:role="line"
+             id="tspan10866"
+             x="193"
+             y="442.36218">Protocol Buffers</tspan><tspan
+             sodipodi:role="line"
+             x="193"
+             y="457.36218"
+             id="tspan10868"
+             dy="-5">messages</tspan></text>
+        <g
+           transform="matrix(0.66229159,0,0,0.66229159,176.71024,408.41713)"
+           inkscape:label="Layer 1"
+           id="layer1-3">
+          <g
+             style="display:inline"
+             id="g5022"
+             transform="matrix(0.02312904,0,0,0.01485743,45.62082,30.57952)">
+            <rect
+               y="-150.69685"
+               x="-1559.2523"
+               height="478.35718"
+               width="1339.6335"
+               id="rect4173"
+               style="opacity:0.40206185;color:#000000;fill:url(#linearGradient5027);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible" />
+            <path
+               inkscape:connector-curvature="0"
+               sodipodi:nodetypes="cccc"
+               id="path5058"
+               d="m -219.61876,-150.68038 c 0,0 0,478.33079 0,478.33079 142.874166,0.90045 345.40022,-107.16966 345.40014,-239.196175 0,-132.026537 -159.436816,-239.134595 -345.40014,-239.134615 z"
+               style="opacity:0.40206185;color:#000000;fill:url(#radialGradient5029);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible" />
+            <path
+               inkscape:connector-curvature="0"
+               style="opacity:0.40206185;color:#000000;fill:url(#radialGradient5031);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible"
+               d="m -1559.2523,-150.68038 c 0,0 0,478.33079 0,478.33079 -142.8742,0.90045 -345.4002,-107.16966 -345.4002,-239.196175 0,-132.026537 159.4368,-239.134595 345.4002,-239.134615 z"
+               id="path5018"
+               sodipodi:nodetypes="cccc" />
+          </g>
+          <g
+             id="g2570"
+             transform="matrix(1.004727,0,0,1.006001,0.05456518,-9.119156)"
+             inkscape:r_cx="true"
+             inkscape:r_cy="true">
+            <path
+               inkscape:connector-curvature="0"
+               id="path12723"
+               d="m 6.34375,15.454879 0,25.987281 36.96875,0 L 43.25,15.554447 c -1.3e-5,-0.0057 3.74e-4,-0.02709 0,-0.03319 -7.31e-4,-0.0065 0.0011,-0.02633 0,-0.03319 -0.0014,-0.0072 -0.02946,-0.02558 -0.03125,-0.03319 l -36.875,0 z"
+               style="fill:url(#linearGradient1483);fill-opacity:1;fill-rule:evenodd;stroke:#888a85;stroke-width:1.50185335;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+               inkscape:r_cx="true"
+               inkscape:r_cy="true" />
+            <path
+               inkscape:connector-curvature="0"
+               sodipodi:nodetypes="ccccccc"
+               id="path1634"
+               d="M 20.490674,29.058712 7.09471,40.0307 l 13.908842,-9.604306 9.018158,0 12.419047,9.482193 -11.863425,-10.849875 -10.086658,0 z"
+               style="fill:url(#linearGradient1487);fill-opacity:1;fill-rule:evenodd;stroke:none"
+               inkscape:r_cx="true"
+               inkscape:r_cy="true" />
+            <path
+               inkscape:connector-curvature="0"
+               id="path15103"
+               d="m 7.34375,16.733862 c -0.0067,0.01334 0.00539,0.01964 0,0.03159 -0.00237,0.0056 -0.029214,0.02632 -0.03125,0.03159 -0.0017,0.0049 0.00137,0.02704 0,0.03159 -0.00103,0.0042 6.858e-4,0.02777 0,0.03159 l 0.03125,23.473418 34.9375,0 -0.0625,-23.347047 c -6.87e-4,-0.0037 10e-4,-0.02751 0,-0.03159 -0.01466,-0.04808 -0.04183,-0.132156 -0.09375,-0.221149 l -34.78125,0 z"
+               style="fill:none;stroke:#ffffff;stroke-width:1.50185323;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+               inkscape:r_cx="true"
+               inkscape:r_cy="true" />
+            <path
+               inkscape:connector-curvature="0"
+               id="path2563"
+               d="M 23.329298,32.996721 C 20.937189,32.550375 7.9003872,18.771125 6.5966059,16.372022 6.5816495,16.343448 6.5559705,16.288608 6.5446896,16.2636 l 34.5131134,0 c -0.277079,2.502804 -7.524227,16.505746 -9.561279,16.733121 -0.0082,4.68e-4 -0.02128,0 -0.02927,0 l -8.020859,0 c -0.03363,0 -0.07755,0.0074 -0.117094,0 z"
+               style="fill:url(#radialGradient1491);fill-opacity:1;fill-rule:evenodd;stroke:none"
+               inkscape:r_cx="true"
+               inkscape:r_cy="true" />
+            <path
+               inkscape:connector-curvature="0"
+               id="path1613"
+               d="M 20.77475,31.085394 C 18.407309,30.694257 7.945269,18.619435 7.1185841,16.517089 7.109327,16.49205 7.094677,16.443993 7.088438,16.422079 l 35.542207,0 c -0.823616,2.19322 -11.29845,14.464065 -13.445143,14.663315 -0.0085,4.09e-4 -0.02191,0 -0.03015,0 l -8.260021,0 c -0.03463,0 -0.08145,0.0065 -0.120584,0 z"
+               style="fill:url(#linearGradient1497);fill-opacity:1;fill-rule:evenodd;stroke:#989898;stroke-width:1.28649366;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1"
+               inkscape:r_cx="true"
+               inkscape:r_cy="true" />
+            <path
+               inkscape:connector-curvature="0"
+               id="path18153"
+               d="M 20.625174,30.490479 C 18.519211,29.999928 7.7224803,17.987711 7.0314243,16.466377 c -0.00254,-0.006 0.00218,-0.02669 0,-0.03231 -0.00545,-0.01576 -0.029096,-0.0523 -0.03125,-0.06463 2.87e-5,-0.0033 -4.061e-4,-0.02938 0,-0.03231 0.00117,-0.0021 0.029695,0.0017 0.03125,0 l 0.09375,-0.09694 35.4687497,0 c -0.0027,0.02433 -0.02268,0.06687 -0.03125,0.09694 -0.0075,0.0236 -0.02057,0.07023 -0.03125,0.09694 -0.922098,2.180937 -11.507988,13.766449 -13.34375,14.056416 -0.01493,0.0016 -0.04885,0 -0.0625,0 l -8.375,0 c -0.03029,-0.0017 -0.08975,0.0082 -0.125,0 z"
+               style="fill:url(#linearGradient1501);fill-opacity:1;fill-rule:evenodd;stroke:none"
+               inkscape:r_cx="true"
+               inkscape:r_cy="true" />
+            <path
+               inkscape:connector-curvature="0"
+               id="path1616"
+               d="M 20.875174,30.051141 C 18.427215,29.501671 8.7040003,18.433898 7.5314243,16.451725 l 34.5937497,0 c -1.490188,2.333171 -11.046672,13.411791 -13.15625,13.599416 -0.0087,4.02e-4 -0.02278,0 -0.03125,0 l -7.90625,0 c -0.02639,0 -0.06488,0.0036 -0.09375,0 -0.01979,-0.0031 -0.04165,0.0047 -0.0625,0 z"
+               style="fill:none;stroke:url(#linearGradient1503);stroke-width:1.2864933;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1"
+               inkscape:r_cx="true"
+               inkscape:r_cy="true" />
+            <path
+               inkscape:connector-curvature="0"
+               sodipodi:nodetypes="cccccc"
+               id="path1636"
+               d="m 20.959511,30.447113 -11.941499,8.270856 2.219433,0.0061 9.998125,-6.86894 8.821908,-1.422838 -9.097967,0.01482 z"
+               style="fill:url(#linearGradient1505);fill-opacity:1;fill-rule:evenodd;stroke:none"
+               inkscape:r_cx="true"
+               inkscape:r_cy="true" />
+          </g>
+        </g>
+      </g>
+    </g>
+    <g
+       id="g11055"
+       transform="translate(68.952442,-27.959635)">
+      <text
+         sodipodi:linespacing="125%"
+         id="text10870"
+         y="435.36218"
+         x="367.90341"
+         style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:FreeSans;-inkscape-font-specification:FreeSans"
+         xml:space="preserve"><tspan
+           y="435.36218"
+           x="367.90341"
+           id="tspan10872"
+           sodipodi:role="line">Data structures</tspan></text>
+      <g
+         transform="matrix(0.69596564,0,0,0.69596564,273.85443,81.742553)"
+         id="g10906">
+        <path
+           style="fill:none;stroke:#2e3436;stroke-width:1.43685257px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+           d="m 180,479.36218 0,-3 4,0 0,-3"
+           id="path10902"
+           inkscape:connector-curvature="0"
+           sodipodi:nodetypes="cccc" />
+        <path
+           style="fill:none;stroke:#2e3436;stroke-width:1.43685257px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+           d="m 206,479.36218 0,-3 -4,0 0,-3"
+           id="path10904"
+           inkscape:connector-curvature="0"
+           sodipodi:nodetypes="cccc" />
+        <g
+           id="g10880">
+          <rect
+             ry="0.040280778"
+             rx="0.010749566"
+             y="462.36218"
+             x="180"
+             height="11"
+             width="26"
+             id="rect10874"
+             style="color:#000000;fill:#729fcf;fill-opacity:1;fill-rule:nonzero;stroke:#204a87;stroke-width:1.43685257;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+          <rect
+             style="color:#000000;fill:#729fcf;fill-opacity:1;fill-rule:nonzero;stroke:#bdd2e9;stroke-width:1.43685257;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+             id="rect10876"
+             width="24"
+             height="9.0000305"
+             x="181"
+             y="463.36215"
+             rx="0.0099226767"
+             ry="0.032957111" />
+        </g>
+        <g
+           id="g10892"
+           transform="translate(8,-2)">
+          <rect
+             style="color:#000000;fill:#d3d7cf;fill-opacity:1;fill-rule:nonzero;stroke:#4e9a06;stroke-width:1.43685257;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+             id="rect10886"
+             width="13"
+             height="10.999969"
+             x="166"
+             y="481.36221"
+             rx="0.0053747827"
+             ry="0.040280666" />
+          <rect
+             ry="0.032956999"
+             rx="0.004547894"
+             y="482.36218"
+             x="167"
+             height="9"
+             width="11"
+             id="rect10888"
+             style="color:#000000;fill:#8ae234;fill-opacity:1;fill-rule:nonzero;stroke:#caf2a4;stroke-width:1.43685257;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+        </g>
+        <g
+           transform="translate(33,-2)"
+           id="g10896">
+          <rect
+             ry="0.040280666"
+             rx="0.0053747827"
+             y="481.36221"
+             x="166"
+             height="10.999969"
+             width="13"
+             id="rect10898"
+             style="color:#000000;fill:#d3d7cf;fill-opacity:1;fill-rule:nonzero;stroke:#4e9a06;stroke-width:1.43685257;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+          <rect
+             style="color:#000000;fill:#8ae234;fill-opacity:1;fill-rule:nonzero;stroke:#caf2a4;stroke-width:1.43685257;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+             id="rect10900"
+             width="11"
+             height="9"
+             x="167"
+             y="482.36218"
+             rx="0.004547894"
+             ry="0.032956999" />
+        </g>
+      </g>
+    </g>
+    <g
+       id="g15531"
+       transform="translate(-16,0.55679368)">
+      <g
+         transform="matrix(0.79106547,0,0,0.79106547,463.64438,289.26048)"
+         id="g15500">
+        <g
+           inkscape:label="shadow"
+           id="layer2">
+          <path
+             transform="matrix(1.18638,0,0,1.18638,-4.539687,-7.794678)"
+             d="m 44.285715,38.714287 c 0,5.43296 -8.922325,9.837245 -19.928572,9.837245 -11.006246,0 -19.9285713,-4.404285 -19.9285713,-9.837245 0,-5.432961 8.9223253,-9.837245 19.9285713,-9.837245 11.006247,0 19.928572,4.404284 19.928572,9.837245 z"
+             sodipodi:ry="9.837245"
+             sodipodi:rx="19.928572"
+             sodipodi:cy="38.714287"
+             sodipodi:cx="24.357143"
+             id="path1538"
+             style="color:#000000;fill:url(#radialGradient15544);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.50000042;marker:none;visibility:visible;display:inline;overflow:visible"
+             sodipodi:type="arc" />
+        </g>
+        <g
+           id="layer1-4"
+           inkscape:label="Layer 1">
+          <path
+             inkscape:connector-curvature="0"
+             style="fill:url(#linearGradient15546);fill-rule:nonzero;stroke:#3f4561;stroke-width:1.26411784;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1"
+             d="M 24.285801,43.196358 4.3751874,23.285744 24.285801,3.3751291 44.196415,23.285744 24.285801,43.196358 l 0,0 z"
+             id="path53304" />
+          <path
+             inkscape:connector-curvature="0"
+             sodipodi:nodetypes="ccccccc"
+             style="opacity:0.72000002;fill:#ffffff;fill-rule:nonzero;stroke:none"
+             d="M 43.505062,23.285744 24.285801,4.0664819 5.0665401,23.285744 5.8476076,23.910676 24.45724,5.4825431 43.505256,23.285744 l -1.94e-4,0 z"
+             id="path53359" />
+          <path
+             inkscape:connector-curvature="0"
+             style="opacity:0.5;fill:#ffffff;fill-rule:nonzero;stroke:none"
+             d="m 8.9257729,27.145172 0.7384498,-1.024184 c 0.6367493,0.268492 1.3006183,0.485069 1.9861833,0.644885 l -0.0058,1.576858 c 0.427728,0.08834 0.86301,0.156136 1.304105,0.204371 l 0.481774,-1.501889 c 0.344041,0.02848 0.691764,0.04417 1.043361,0.04417 0.351209,0 0.699124,-0.0155 1.043166,-0.04417 l 0.481775,1.501889 c 0.441288,-0.04823 0.876376,-0.116036 1.304104,-0.204371 l -0.006,-1.577051 c 0.685758,-0.159623 1.349433,-0.3762 1.986182,-0.644692 l 0.92248,1.279502 c 0.402351,-0.182094 0.794241,-0.382591 1.174895,-0.600522 l -0.492817,-1.498016 c 0.59723,-0.36225 1.161723,-0.773319 1.687471,-1.227972 l 1.272141,0.931779 c 0.325638,-0.296581 0.637329,-0.608272 0.933716,-0.93391 l -0.931585,-1.271947 c 0.454847,-0.525748 0.865916,-1.090047 1.228166,-1.687665 l 1.498015,0.493011 C 26.79347,21.2244 26.994161,20.832316 27.175867,20.43016 l -1.279308,-0.922287 c 0.268492,-0.636749 0.485068,-1.300618 0.645079,-1.986376 l 1.576663,0.0058 c 0.08834,-0.427727 0.156137,-0.86301 0.204178,-1.304298 l -1.501695,-0.481774 c 0.02886,-0.343848 0.04417,-0.691764 0.04417,-1.043167 0,-0.351403 -0.01569,-0.699125 -0.04417,-1.043361 l 1.501695,-0.481774 C 28.274632,12.73184 28.206442,12.296751 28.118495,11.86883 l -1.577051,0.006 C 26.381627,11.189076 26.165051,10.525208 25.896753,9.8886539 L 27.176061,8.9663652 C 26.994354,8.5640139 26.79347,8.1721237 26.575926,7.7912754 L 25.077717,8.2842867 C 24.715466,7.6868623 24.304398,7.1225635 23.849744,6.5970095 L 24.78133,5.3248686 C 24.502958,5.0189892 24.210252,4.7268638 23.905922,4.4467488 L 5.0669275,23.285938 6.0738693,24.29288 6.3725811,24.074174 c 0.5257484,0.454653 1.0900465,0.865722 1.6874698,1.227972 l -0.2419526,0.735157 1.1080622,1.108062 -3.876e-4,-1.93e-4 z"
+             id="path53361" />
+          <path
+             inkscape:connector-curvature="0"
+             style="opacity:0.5;fill:#ffffff;fill-rule:nonzero;stroke:none"
+             d="m 28.448976,32.191116 c 0,-6.484682 4.233883,-11.979469 10.08724,-13.874023 l -2.226972,-2.227167 c -0.01685,0.007 -0.0339,0.01298 -0.05056,0.02015 L 36.077171,15.858244 34.665167,14.44624 c -0.463178,0.2189 -0.91667,0.45446 -1.359314,0.707648 l 0.694089,2.109193 c -0.841314,0.509669 -1.635748,1.08869 -2.375747,1.728732 l -1.79111,-1.311659 c -0.458721,0.41746 -0.897297,0.856036 -1.314564,1.314565 l 1.311465,1.790914 c -0.640041,0.740195 -1.218868,1.534628 -1.728731,2.375748 l -2.109387,-0.694089 c -0.306654,0.536403 -0.589093,1.088304 -0.844994,1.654732 l 1.801182,1.298293 c -0.377942,0.896329 -0.682852,1.831014 -0.907758,2.796501 l -2.219999,-0.0085 c -0.124172,0.602266 -0.219869,1.215188 -0.287476,1.836051 l 2.114423,0.678398 c -0.04029,0.484293 -0.06199,0.97401 -0.06199,1.46857 0,0.494753 0.0217,0.98447 0.06199,1.468763 l -2.114423,0.677816 c 0.06761,0.621251 0.163304,1.233979 0.28767,1.836245 l 2.219805,-0.0083 c 0.224906,0.965487 0.529816,1.900172 0.907758,2.796502 l -1.801182,1.298486 c 0.142382,0.31479 0.293869,0.624931 0.452136,0.930423 l 3.804023,-3.803636 c -0.61602,-1.614245 -0.95425,-3.365836 -0.95425,-5.196269 l 1.93e-4,-1.94e-4 z"
+             id="path53363" />
+          <path
+             inkscape:connector-curvature="0"
+             sodipodi:nodetypes="ccccccc"
+             style="opacity:0.35;fill:#000000;fill-rule:nonzero;stroke:none"
+             d="M 5.2050478,23.424252 24.285801,42.505005 43.505062,23.285744 42.789963,22.603525 24.310314,41.041677 5.2050478,23.424059 l 0,1.93e-4 z"
+             id="path53365" />
+        </g>
+      </g>
+      <text
+         sodipodi:linespacing="125%"
+         id="text13355-1"
+         y="337.36218"
+         x="440"
+         style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:FreeSans;-inkscape-font-specification:FreeSans"
+         xml:space="preserve"><tspan
+           y="337.36218"
+           x="440"
+           id="tspan13357-7"
+           sodipodi:role="line">User application</tspan></text>
+    </g>
+  </g>
+</svg>

+ 158 - 0
components/spotify/cspot/bell/nanopb/docs/index.md

@@ -0,0 +1,158 @@
+# Nanopb: Overview
+
+Nanopb is an ANSI-C library for encoding and decoding messages in
+Google's [Protocol Buffers](https://developers.google.com/protocol-buffers/docs/reference/overview)
+format with minimal requirements for RAM and code space. It is primarily
+suitable for 32-bit microcontrollers.
+
+Documentation version
+---------------------
+
+This documentation applies for nanopb 0.4.0 and later versions. For
+documentation of older releases,
+[see here](https://github.com/nanopb/nanopb/blob/maintenance_0.3/docs/index.rst).
+
+Overall structure
+-----------------
+
+For the runtime program, you always need `pb.h` for type declarations
+and `pb_common.h/c` for base functions. Depending on whether you want
+to encode, decode, or both, you also need `pb_encode.h/c` or
+`pb_decode.h/c`.
+
+The high-level encoding and decoding functions take a pointer to
+`pb_msgdesc_t` structure, which describes the fields of a message
+structure. Usually you want these autogenerated from a `.proto` file.
+The tool script `nanopb_generator.py` accomplishes this.
+
+![Image: Nanopb generator flow](generator_flow.svg)
+
+So a typical project might include these files:
+
+1. Nanopb runtime library:
+    -   pb.h
+    -   pb_common.h and pb_common.c (always needed)
+    -   pb_decode.h and pb_decode.c (needed for decoding messages)
+    -   pb_encode.h and pb_encode.c (needed for encoding messages)
+
+2. Protocol description (you can have many):
+    -   person.proto (just an example)
+    -   person.pb.c (autogenerated, contains message descriptors)
+    -   person.pb.h (autogenerated, contains type declarations and macros)
+
+Features and limitations
+------------------------
+
+**Features**
+
+1)  Pure C runtime
+2)  Small code size (5--10 kB depending on processor and compilation options, plus any message definitions)
+3)  Small ram usage (typically \~300 bytes stack, plus any message structs)
+4)  Allows specifying maximum size for strings and arrays, so that they can be allocated statically.
+5)  No malloc needed: everything can be allocated statically or on the stack. Optional malloc support available.
+6)  You can use either encoder or decoder alone to cut the code size in half.
+7)  Support for most protobuf features, including: all data types,
+    nested submessages, default values, repeated and optional fields,
+    oneofs, packed arrays, extension fields.
+8)  Callback mechanism for handling messages larger than can fit in available RAM.
+9)  Extensive set of tests.
+
+**Limitations**
+
+1)  Some speed has been sacrificed for code size.
+2)  Encoding is focused on writing to streams. For memory buffers only it could be made more efficient.
+3)  The deprecated Protocol Buffers feature called "groups" is not supported.
+4)  Fields in the generated structs are ordered by the tag number, instead of the natural ordering in .proto file.
+5)  Unknown fields are not preserved when decoding and re-encoding a message.
+6)  Reflection (runtime introspection) is not supported. E.g. you can't request a field by giving its name in a string.
+7)  Numeric arrays are always encoded as packed, even if not marked as packed in .proto.
+8)  Cyclic references between messages are supported only in callback and malloc mode.
+9)  Nanopb doesn't have a stable ABI (application binary interface)
+    between versions, so using it as a shared library (.so / .dll)
+    requires extra care.
+
+Getting started
+---------------
+
+For starters, consider this simple message:
+
+~~~~ protobuf
+message Example {
+    required int32 value = 1;
+}
+~~~~
+
+Save this in `message.proto` and compile it:
+
+    user@host:~$ python nanopb/generator/nanopb_generator.py message.proto
+
+You should now have in `message.pb.h`:
+
+    typedef struct {
+       int32_t value;
+    } Example;
+
+    extern const pb_msgdesc_t Example_msg;
+    #define Example_fields &Example_msg
+
+Then you have to include the nanopb headers and the generated header:
+
+    #include <pb_encode.h>
+    #include "message.pb.h"
+
+Now in your main program do this to encode a message:
+
+    Example mymessage = {42};
+    uint8_t buffer[10];
+    pb_ostream_t stream = pb_ostream_from_buffer(buffer, sizeof(buffer));
+    pb_encode(&stream, Example_fields, &mymessage);
+
+After that, buffer will contain the encoded message. The number of bytes
+in the message is stored in `stream.bytes_written`. You can feed the
+message to `protoc --decode=Example message.proto` to verify its
+validity.
+
+For a complete example of the simple case, see [examples/simple/simple.c](https://github.com/nanopb/nanopb/blob/master/examples/simple/simple.c).
+For a more complex example with network interface, see the [examples/network_server](https://github.com/nanopb/nanopb/tree/master/examples/network_server) subdirectory.
+
+Compiler requirements
+---------------------
+
+Nanopb should compile with most ansi-C compatible compilers. It however
+requires a few header files to be available:
+
+1)  `string.h`, with these functions: `strlen`, `memcpy`, `memset`
+2)  `stdint.h`, for definitions of `int32_t` etc.
+3)  `stddef.h`, for definition of `size_t`
+4)  `stdbool.h`, for definition of `bool`
+5)  `limits.h`, for definition of `CHAR_BIT`
+
+If these header files do not come with your compiler, you can use the
+file `extra/pb_syshdr.h` instead. It contains an example of how to
+provide the dependencies. You may have to edit it a bit to suit your
+custom platform.
+
+To use the pb_syshdr.h, define `PB_SYSTEM_HEADER` as
+`"pb_syshdr.h"` (including the quotes). Similarly, you can provide a
+custom include file, which should provide all the dependencies listed
+above.
+
+Running the test cases
+----------------------
+
+Extensive unittests and test cases are included under the `tests`
+folder.
+
+To build the tests, you will need the [scons](http://www.scons.org/)
+build system. The tests should be runnable on most platforms. Windows
+and Linux builds are regularly tested. The tests also support embedded
+targets: STM32 (ARM Cortex-M) and AVR builds are regularly tested.
+
+In addition to the build system, you will also need a working Google
+Protocol Buffers `protoc` compiler, and the Python bindings for Protocol
+Buffers.
+
+Easiest way to install dependencies is to use the Python package manager
+[pip](https://pypi.org/project/pip/), which works on all platforms supported by Python:
+
+    pip3 install scons protobuf grpcio-tools

BIN
components/spotify/cspot/bell/nanopb/docs/logo/logo.png


File diff suppressed because it is too large
+ 1464 - 0
components/spotify/cspot/bell/nanopb/docs/logo/logo.svg


BIN
components/spotify/cspot/bell/nanopb/docs/logo/logo16px.png


BIN
components/spotify/cspot/bell/nanopb/docs/logo/logo48px.png


+ 233 - 0
components/spotify/cspot/bell/nanopb/docs/lsr.css

@@ -0,0 +1,233 @@
+/*
+Original author: Peter Parente
+Date: 2008/01/22
+Version: 1.0 (modified)
+Copyright: This stylesheet has been placed in the public domain - free to edit and use for all uses.
+
+--
+
+Heavily modified for use in nanopb documentation.
+2011-2020 Petteri Aimonen
+*/
+
+body {
+  font: 100% sans-serif;
+  background: #ffffff;
+  color: black;
+  margin: 2em;
+  padding: 0em 2em;
+  max-width: 1200px;
+}
+
+p.topic-title {
+  font-weight: bold;
+}
+
+table.docinfo {
+  text-align: left;
+  margin: 2em 0em;
+}
+
+a[href] {
+  color: #436976;
+  background-color: transparent;
+}
+
+a.toc-backref {
+  text-decoration: none;
+}
+
+h1 a[href] {
+  color: #003a6b;
+  text-decoration: none;
+  background-color: transparent;
+}
+
+a.strong {
+  font-weight: bold;
+}
+
+img {
+  margin: 0;
+  border: 0;
+}
+
+blockquote {
+  border-left: 3px solid black;
+  background-color: #f6f6f6;
+  padding: 0.5em 1em 0.2em 1em;
+}
+
+li {
+  margin-bottom: 0.5em;
+}
+
+p {
+  margin: 0.5em 0 1em 0;
+  line-height: 1.5em;
+}
+
+p a:visited {
+  color: purple;
+  background-color: transparent;
+}
+
+p a:active {
+  color: red;
+  background-color: transparent;
+}
+
+a:hover {
+  text-decoration: none;
+}
+
+p img {
+  border: 0;
+  margin: 0;
+}
+
+p.rubric {
+  font-weight: bold;
+  font-style: italic;
+}
+
+em, cite {
+  font-style: normal;
+  font-family: monospace;
+  font-weight: bold;
+}
+
+pre {
+  border-left: 3px double #aaa;
+  padding: 5px 10px;
+  background-color: #f6f6f6;
+}
+
+code {
+  border: 1px solid rgba(128, 128, 128, 0.1);
+  padding: 1px 5px;
+  border-radius: 5px;
+  background-color: rgba(128, 128, 128, 0.05);
+  white-space: nowrap;
+}
+
+pre code {
+  border: none;
+  background-color: transparent;
+  padding: 0px;
+}
+
+h1, h2, h3, h4, h5, h6 {
+  color: #000;
+  background-color: transparent;
+  margin: 0em;
+  padding-top: 0.5em;
+}
+
+h1 {
+  color: #003a6b;
+  font-size: 180%;
+  margin-bottom: 0.5em;
+  border-bottom: 2px solid #aaa;
+}
+
+h2 {
+  color: #003a6b;
+  font-size: 130%;
+  margin-bottom: 0.5em;
+  border-bottom: 1px solid #aaa;
+  margin-top: 1.5em;
+}
+
+h3 {
+  font-size: 120%;
+  margin-bottom: 0.5em;
+  margin-top: 1.0em;
+}
+
+h4 {
+  font-size: 110%;
+  font-weight: bold;
+  margin-bottom: 0.5em;
+  margin-top: 0.5em;
+}
+
+h5 {
+  font-size: 105%;
+  font-weight: bold;
+  margin-bottom: 0.5em;
+}
+
+h6 {
+  font-size: 100%;
+  font-weight: bold;
+  margin-bottom: 0.5em;
+}
+
+dt {
+  font-style: italic;
+}
+
+dd {
+  margin-bottom: 1.5em;
+}
+
+
+
+table {
+  text-align: left;
+  border-collapse: collapse;
+  margin: 1.5em 0em;
+}
+
+table td, table th {
+  padding: 0.25em 1em;
+  border-top: 1px solid gray;
+  border-bottom: 1px solid gray;
+}
+
+#index {
+  margin: 2em 2em 2em 0em;
+  padding: 0em 1em;
+  border-top: 1px solid #aaa;
+  border-left: 1px solid #aaa;
+  border-bottom: 2px solid #555;
+  border-right: 2px solid #555;
+  max-width: 20em;
+}
+
+#index h2 {
+  margin-bottom: 0em;
+  margin-top: 0em;
+  color: #003a6b;
+  font-size: 100%;
+  border-bottom: 1px solid #aaa;
+  font-weight: bold;
+}
+
+#feedback_link {
+  float: right;
+}
+
+#feedback {
+  visibility: hidden;
+  padding: 1em;
+  border-radius: 5px;
+  position: fixed;
+  top: 10em;
+  right: 10em;
+  background: white;
+  border-top: 1px solid #aaa;
+  border-left: 1px solid #aaa;
+  border-bottom: 2px solid #555;
+  border-right: 2px solid #555;
+}
+
+#feedback:target {
+  visibility: visible;
+}
+
+#feedback .cancel {
+  color: #666;
+  padding-left: 2em;
+}

+ 618 - 0
components/spotify/cspot/bell/nanopb/docs/migration.md

@@ -0,0 +1,618 @@
+# Nanopb: Migration from older versions
+
+This document details all the breaking changes that have been made to
+nanopb since its initial release. For each change, the rationale and
+required modifications of user applications are explained. Also any
+error indications are included, in order to make it easier to find this
+document.
+
+Nanopb-0.4.6 (to come)
+-------------------------
+
+### `NANOPB_VERSION` define is now a string
+
+**Changes:** To ease `NANOPB_VERSION` macro usage, the value is directly a string.
+
+**Required actions:** Most nanopb users probably never used that macro. If so,
+you certainly use the `#` preprocessor to convert it as string. You, now,
+only have to call it directly, like this for example:
+`strcpy(myvar, NANOPB_VERSION);`
+
+Nanopb-0.4.4 (2020-11-25)
+-------------------------
+
+### Remove outdated generator/nanopb/options.proto
+
+**Changes:** Back in 2018, it was considered in pull request #241 to
+move nanopb generator options to a separate namespace. For this reason,
+a transitional file was added. It was later abandoned and is now removed
+to avoid confusion.
+
+**Required actions:** Most nanopb users probably never used that transitional
+file at all. If your `.proto` files import it, change to using `generator/proto/nanopb.proto`.
+
+**Error indications:** Errors about missing file `options.proto` when running
+the generator.
+
+Nanopb-0.4.3 (2020-09-21)
+-------------------------
+
+### pb_msgdesc_t struct has new fields
+
+**Changes:** New fields `required_field_count` and
+`largest_tag` were added to `pb_msgdesc_t`
+and existing fields were reordered.
+
+**Required actions:** All `.pb.c` files must be recompiled.
+Regeneration is not needed.
+
+**Error indications:** Messages may fail to encode or decode, or the
+code can crash inside `load_descriptor_values()` in
+`pb_common.c`.
+
+Nanopb-0.4.2 (2020-06-23)
+-------------------------
+
+### Generator now uses Python 3 by default
+
+**Rationale:** Previously `nanopb-generator.py` had hashbang
+of `#!/usr/bin/env python`, which would execute with Python
+2 on most systems. Python 2 is now deprecated and many libraries are
+dropping support for it, which makes installing dependencies difficult.
+While `nanopb_generator.py` has worked with Python 3 for
+years now, and overriding the python version was possible with
+virtualenv, that was an extra complication.
+
+**Changes:** Hashbang now uses `#!/usr/bin/env python3`.
+New file `nanopb_generator.py2` can be used to run with
+Python 2, if necessary.
+
+**Required actions:** If possible, just verify Python 3 is installed and
+necessary dependencies are installed for it. For example `pip3 install protobuf grpcio-tools`
+should take care of it. If this is not possible, call `nanopb_generator.py2` from your build
+scripts instead.
+
+**Error indications:** `python3: command not found` if
+Python 3 is not installed.
+`Could not import the Google protobuf Python libraries` if dependencies are only installed for Python 2.
+
+Nanopb-0.4.0 (2019-12-20)
+-------------------------
+
+### New field descriptor format
+
+**Rationale:** Previously information about struct fields was stored as
+an array of `pb_field_t` structures. This was a
+straightforward method, but required allocating space for e.g.
+submessage type and array size for all fields, even though most fields
+are not submessages nor arrays.
+
+**Changes:** Now field information is encoded more efficiently in
+`uint32_t` array in a variable-length format. Old
+`pb_field_t` structure has been removed and it is now a
+typedef for `pb_field_iter_t`. This retains compatibility
+with most old callback definitions. The field definitions in
+`.pb.h` files are now of type `pb_msgdesc_t`.
+
+**Required actions:** If your own code accesses the low-level field
+information in `pb_field_t`, it must be modified to do so
+only through the functions declared in `pb_common.h`.
+
+**Error indications:** `incompatible pointer type` errors
+relating to `pb_field_t`
+
+### Changes to generator default options
+
+**Rationale:** Previously nanopb_generator added a timestamp header to
+generated files and used only basename of files in
+`#include` directives. This is different than what the
+`protoc` C++ backend does.
+
+**Changes:** Now default options are `--no-timestamp` and
+`--no-strip-path`.
+
+**Required actions:** If old behaviour is desired, add
+`--timestamp` and `--strip-path` options to
+`nanopb_generator.py` or on `protoc` command
+line as `--nanopb_out=--timestamp,--strip-path:outdir`.
+
+**Error indications:** Compiler error: cannot find include file
+`mymessage.pb.h` when compiling
+`mymessage.pb.c`.
+
+### Removal of bundled plugin.proto
+
+**Rationale:** Google's Python protobuf library, which is used in
+nanopb generator, has included `plugin_pb2` with it since
+version 3.1.0. It is not necessary to bundle it with nanopb anymore.
+
+**Required actions:** Update `python-protobuf` to version
+3.1.0 or newer.
+
+**Error indications:** `ImportError: No module named compiler.plugin_pb2`
+
+### .options file is now always case-sensitive
+
+**Rationale:** Previously field names in `.options` file
+were case-sensitive on Linux and case-insensitive on Windows. This was
+by accident. Because `.proto` files are case-sensitive,
+`.options` files should be too.
+
+**Changes:** Now field names in `.options` are always
+case-sensitive, and matched by `fnmatchcase()` instead of
+`fnmatch()`.
+
+**Required actions:** If field names in `.options` are not
+capitalized the same as in `.proto`, they must be updated.
+
+### `CHAR_BIT` define is now needed
+
+**Rationale:** To check whether the platform has 8-bit or larger chars,
+the C standard `CHAR_BIT` macro is needed.
+
+**Changes:** `pb.h` now includes `limits.h` for this macro.
+
+**Required actions:** If your platform doesn't have `limits.h`
+available, you can define the macro in `pb_syshdr.h`. There is an
+example in `extra` directory.
+
+**Error indications:** `"Cannot find include file <limits.h>."` or
+`"Undefined identifier: CHAR_BIT."`
+
+### Strings must now always be null-terminated
+
+**Rationale:** Previously `pb_encode()` would accept non-terminated
+strings and assume that they are the full length of the defined array.
+However, `pb_decode()` would reject such messages because null
+terminator wouldn't fit in the array.
+
+**Changes:** `pb_encode()` will now return an error if null terminator
+is missing. Maximum encoded message size calculation is changed
+accordingly so that at most `max_size-1` strings are assumed. New field
+option `max_length` can be used to define the maximum string length,
+instead of the array size.
+
+**Required actions:** If your strings were previously filling the whole
+allocated array, increase the size of the field by 1.
+
+**Error indications:** `pb_encode()` returns error `unterminated string`.
+
+### Removal of per-field default value constants
+
+**Rationale:** Previously nanopb declared a
+`fieldname_default` constant variable for each field with a
+default value, and used these internally to initialize messages. This
+however used unnecessarily large amount of storage for the values. The
+variables were mostly for internal usage, but were available in the
+header file.
+
+**Changes:** Default values are now stored as an encoded protobuf
+message.
+
+**Required actions:** If your code previously used default constants, it
+will have to be adapted to take the default value in some other way,
+such as by defining
+`static const MyMessage msg_default = MyMessage_init_default;` and accessing
+`msg_default.fieldname`.
+
+**Error indications:** Compiler error about `fieldname_default` being undeclared.
+
+### Zero tag in message now raises error by default
+
+**Rationale:** Previously nanopb has allowed messages to be terminated
+by a null byte, which is read as zero tag value. Most other protobuf
+implementations don't support this, so it is not very useful feature.
+It has also been noted that this can complicate debugging issues with
+corrupted messages.
+
+**Changes:** `pb_decode()` now gives error when it
+encounters zero tag value. A new function `pb_decode_ex()`
+supports flag `PB_DECODE_NULLTERMINATED` that supports
+decoding null terminated messages.
+
+**Required actions:** If application uses null termination for messages,
+switch it to use `pb_decode_ex()` and
+`pb_encode_ex()`. If compatibility with 0.3.9.x is needed,
+there are also `pb_decode_nullterminated()` and
+`pb_encode_nullterminated()` macros, which work both in
+0.4.0 and 0.3.9.
+
+**Error indications:** Error message from `pb_decode()`: `zero_tag`.
+
+### Submessages now have has_field in proto3 mode
+
+**Rationale:** Previously nanopb considered proto3 submessages as
+present only when their contents was non-zero. Most other protobuf
+libraries allow explicit null state for submessages.
+
+**Changes:** Submessages now have separate `has_field` in
+proto3 mode also.
+
+**Required actions:** When using submessages in proto3 mode, user code
+must now set `mymsg.has_submsg = true` for each submessage
+that is present. Alternatively, the field option
+`proto3_singular_msgs` can be used to restore the old
+behavior.
+
+**Error indications:** Submessages do not get encoded.
+
+### PB_OLD_CALLBACK_STYLE option has been removed
+
+**Rationale:** Back in 2013, function signature for callbacks was
+changed. The `PB_OLD_CALLBACK_STYLE` option allowed
+compatibility with old code, but complicated code and testing because of
+the different options.
+
+**Changes:** `PB_OLD_CALLBACK_STYLE` option no-longer has
+any effect.
+
+**Required actions:** If `PB_OLD_CALLBACK_STYLE` option
+was in use previously, function signatures must be updated to use double
+pointers (`void**` and `void * const *`).
+
+**Error indications:** Assignment from incompatible pointer type.
+
+### protoc insertion points are no longer included by default
+
+**Rationale:** Protoc allows including comments in form
+`@@protoc_insertion_point` to identify locations for
+other plugins to insert their own extra content. Previously these were
+included by default, but they clutter the generated files and are rarely
+used.
+
+**Changes:** Insertion points are now included only when
+`--protoc-insertion-points` option is passed to the
+generator.
+
+Nanopb-0.3.9.4, 0.4.0 (2019-10-13)
+----------------------------------
+
+### Fix generation of min/max defines for enum types
+
+**Rationale:** Nanopb generator makes \#defines for enum minimum and
+maximum value. Previously these defines incorrectly had the first and
+last enum value, instead of the actual minimum and maximum. (issue
+#405)
+
+**Changes:** Minimum define now always has the smallest value, and
+maximum define always has the largest value.
+
+**Required actions:** If these defines are used and enum values in
+.proto file are not defined in ascending order, user code behaviour may
+change. Check that user code doesn\'t expect the old, incorrect
+first/last behaviour.
+
+### Fix undefined behavior related to bool fields
+
+**Rationale:** In C99, `bool` variables are not allowed to
+have other values than `true` and `false`.
+Compilers use this fact in optimization, and constructs like
+`int foo = msg.has_field ? 100 : 0;` will give unexpected results
+otherwise. Previously nanopb didn\'t enforce that decoded bool fields
+had valid values.
+
+**Changes:** Bool fields are now handled separately as
+`PB_LTYPE_BOOL`. The `LTYPE` descriptor
+numbers for other field types were renumbered.
+
+**Required actions:** Source code files must be recompiled, but
+regenerating `.pb.h`/`.pb.c` files from
+`.proto` is not required. If user code directly uses the
+nanopb internal field representation (search for
+`PB_LTYPE_VARINT` in source), it may need updating.
+
+Nanopb-0.3.9.1, 0.4.0 (2018-04-14)
+----------------------------------
+
+### Fix handling of string and bytes default values
+
+**Rationale:** Previously nanopb didn't properly decode special
+character escapes like `\200` emitted by protoc. This caused these
+escapes to end up verbatim in the default values in .pb.c file.
+
+**Changes:** Escapes are now decoded, and e.g. `\200` or `\x80`
+results in {0x80} for bytes field and `"\x80"` for string field.
+
+**Required actions:** If code has previously relied on `\` in default
+value being passed through verbatim, it must now be changed to `\\`.
+
+Nanopb-0.3.8 (2017-03-05)
+-------------------------
+
+### Fully drain substreams before closing
+
+**Rationale:** If the substream functions were called directly and the
+caller did not completely empty the substring before closing it, the
+parent stream would be put into an incorrect state.
+
+**Changes:** `pb_close_string_substream` can now error and returns a
+boolean.
+
+**Required actions:** Add error checking onto any call to
+`pb_close_string_substream`.
+
+### Change oneof format in .pb.c files
+
+**Rationale:** Previously two oneofs in a single message would be
+erroneously handled as part of the same union.
+
+**Changes:** Oneofs fields now use special `PB_DATAOFFSET_UNION`
+offset type in generated .pb.c files to distinguish whether they are the
+first or following field inside an union.
+
+**Required actions:** Regenerate `.pb.c/.pb.h` files with new nanopb
+version if oneofs are used.
+
+Nanopb-0.3.5 (2016-02-13)
+-------------------------
+
+### Add support for platforms without uint8_t
+
+**Rationale:** Some platforms cannot access 8-bit sized values directly,
+and do not define `uint8_t`. Nanopb previously didn\'t support these
+platforms.
+
+**Changes:** References to `uint8_t` were replaced with several
+alternatives, one of them being a new `pb_byte_t` typedef. This in
+turn uses `uint_least8_t` which means the smallest available type.
+
+**Required actions:** If your platform does not have a
+standards-compliant `stdint.h`, it may lack the definition for
+`[u]int_least8_t`. This must be added manually, example can be found
+in `extra/pb_syshdr.h`.
+
+**Error indications:** Compiler error: `"unknown type name 'uint_least8_t'"`.
+
+Nanopb-0.3.2 (2015-01-24)
+-------------------------
+
+### Add support for OneOfs
+
+**Rationale:** Previously nanopb did not support the `oneof` construct
+in `.proto` files. Those fields were generated as regular `optional`
+fields.
+
+**Changes:** OneOfs are now generated as C unions. Callback fields are
+not supported inside oneof and generator gives an error.
+
+**Required actions:** The generator option `no_unions` can be used to
+restore old behaviour and to allow callbacks to be used. To use unions,
+one change is needed: use `which_xxxx` field to detect which field is
+present, instead of `has_xxxx`. Compare the value against
+`MyStruct_myfield_tag`.
+
+**Error indications:** Generator error: `"Callback fields inside of
+oneof are not supported"`. Compiler error: `"Message"` has no member
+named `"has_xxxx"`.
+
+Nanopb-0.3.0 (2014-08-26)
+-------------------------
+
+### Separate field iterator logic to pb_common.c
+
+**Rationale:** Originally, the field iteration logic was simple enough
+to be duplicated in `pb_decode.c` and `pb_encode.c`. New field types
+have made the logic more complex, which required the creation of a new
+file to contain the common functionality.
+
+**Changes:** There is a new file, `pb_common.c`, which must be included
+in builds.
+
+**Required actions:** Add `pb_common.c` to build rules. This file is
+always required. Either `pb_decode.c` or `pb_encode.c` can still be
+left out if some functionality is not needed.
+
+**Error indications:** Linker error: undefined reference to
+`pb_field_iter_begin`, `pb_field_iter_next` or similar.
+
+### Change data type of field counts to pb_size_t
+
+**Rationale:** Often nanopb is used with small arrays, such as 255 items
+or less. Using a full `size_t` field to store the array count wastes
+memory if there are many arrays. There already exists parameters
+`PB_FIELD_16BIT` and `PB_FIELD_32BIT` which tell nanopb what is the
+maximum size of arrays in use.
+
+**Changes:** Generator will now use `pb_size_t` for the array
+`_count` fields. The size of the type will be controlled by the
+`PB_FIELD_16BIT` and `PB_FIELD_32BIT` compilation time options.
+
+**Required actions:** Regenerate all `.pb.h` files. In some cases casts
+to the `pb_size_t` type may need to be added in the user code when
+accessing the `_count` fields.
+
+**Error indications:** Incorrect data at runtime, crashes. But note that
+other changes in the same version already require regenerating the files
+and have better indications of errors, so this is only an issue for
+development versions.
+
+### Renamed some macros and identifiers
+
+**Rationale:** Some names in nanopb core were badly chosen and
+conflicted with ISO C99 reserved names or lacked a prefix. While they
+haven\'t caused trouble so far, it is reasonable to switch to
+non-conflicting names as these are rarely used from user code.
+
+**Changes:** The following identifier names have changed:
+
+ -   Macros:
+     -   STATIC_ASSERT(x) -> PB_STATIC_ASSERT(x)
+     -   UNUSED(x) -> PB_UNUSED(x)
+ -   Include guards:
+     -   PB_filename -> PB_filename_INCLUDED
+ -   Structure forward declaration tags:
+     -   _pb_field_t -> pb_field_s
+     -   _pb_bytes_array_t -> pb_bytes_array_s
+     -   _pb_callback_t -> pb_callback_s
+     -   _pb_extension_type_t -> pb_extension_type_s
+     -   _pb_extension_t -> pb_extension_s
+     -   _pb_istream_t -> pb_istream_s
+     -   _pb_ostream_t -> pb_ostream_s
+
+**Required actions:** Regenerate all `.pb.c` files. If you use any of
+the above identifiers in your application code, perform search-replace
+to the new name.
+
+**Error indications:** Compiler errors on lines with the macro/type
+names.
+
+Nanopb-0.2.9 (2014-08-09)
+-------------------------
+
+### Change semantics of generator -e option
+
+**Rationale:** Some compilers do not accept filenames with two dots
+(like in default extension .pb.c). The `-e` option to the generator
+allowed changing the extension, but not skipping the extra dot.
+
+**Changes:** The `-e` option in generator will no longer add the
+prepending dot. The default value has been adjusted accordingly to
+`.pb.c` to keep the default behaviour the same as before.
+
+**Required actions:** Only if using the generator -e option. Add dot
+before the parameter value on the command line.
+
+**Error indications:** File not found when trying to compile generated
+files.
+
+Nanopb-0.2.7 (2014-04-07)
+-------------------------
+
+### Changed pointer-type bytes field datatype
+
+**Rationale:** In the initial pointer encoding support since
+nanopb-0.2.5, the bytes type used a separate `pb_bytes_ptr_t` type to
+represent `bytes` fields. This made it easy to encode data from a
+separate, user-allocated buffer. However, it made the internal logic
+more complex and was inconsistent with the other types.
+
+**Changes:** Dynamically allocated bytes fields now have the
+`pb_bytes_array_t` type, just like statically allocated ones.
+
+**Required actions:** Only if using pointer-type fields with the bytes
+datatype. Change any access to `msg->field.size` to
+`msg->field->size`. Change any allocation to reserve space of amount
+`PB_BYTES_ARRAY_T_ALLOCSIZE(n)`. If the data pointer was begin
+assigned from external source, implement the field using a callback
+function instead.
+
+**Error indications:** Compiler error: unknown type name
+`pb_bytes_ptr_t`.
+
+Nanopb-0.2.4 (2013-11-07)
+-------------------------
+
+### Remove the NANOPB_INTERNALS compilation option
+
+**Rationale:** Having the option in the headers required the functions
+to be non-static, even if the option is not used. This caused errors on
+some static analysis tools.
+
+**Changes:** The `\#ifdef` and associated functions were removed from
+the header.
+
+**Required actions:** Only if the `NANOPB_INTERNALS` option was
+previously used. Actions are as listed under nanopb-0.1.3 and
+nanopb-0.1.6.
+
+**Error indications:** Compiler warning: implicit declaration of
+function `pb_dec_string`, `pb_enc_string`, or similar.
+
+Nanopb-0.2.1 (2013-04-14)
+-------------------------
+
+### Callback function signature
+
+**Rationale:** Previously the auxiliary data to field callbacks was
+passed as `void*`. This allowed passing of any data, but made it
+unnecessarily complex to return a pointer from callback.
+
+**Changes:** The callback function parameter was changed to `void**`.
+
+**Required actions:** You can continue using the old callback style by
+defining `PB_OLD_CALLBACK_STYLE`. Recommended action is to:
+
+-   Change the callback signatures to contain `void**` for decoders and `void * const *` for encoders.
+-   Change the callback function body to use **arg` instead of `arg`.
+
+**Error indications:** Compiler warning: assignment from incompatible
+pointer type, when initializing `funcs.encode` or `funcs.decode`.
+
+Nanopb-0.2.0 (2013-03-02)
+-------------------------
+
+### Reformatted generated .pb.c file using macros
+
+**Rationale:** Previously the generator made a list of C `pb_field_t`
+initializers in the .pb.c file. This led to a need to regenerate all
+.pb.c files after even small changes to the `pb_field_t` definition.
+
+**Changes:** Macros were added to pb.h which allow for cleaner
+definition of the .pb.c contents. By changing the macro definitions,
+changes to the field structure are possible without breaking
+compatibility with old .pb.c files.
+
+**Required actions:** Regenerate all .pb.c files from the .proto
+sources.
+
+**Error indications:** Compiler warning: implicit declaration of
+function `pb_delta_end`.
+
+### Changed pb_type_t definitions
+
+**Rationale:** The `pb_type_t` was previously an enumeration type.
+This caused warnings on some compilers when using bitwise operations to
+set flags inside the values.
+
+**Changes:** The `pb_type_t` was changed to *typedef uint8_t*. The
+values were changed to `#define`. Some value names were changed for
+consistency.
+
+**Required actions:** Only if you directly access the
+`pb_field_t` contents in your own code, something which is
+not usually done. Needed changes:
+
+-   Change `PB_HTYPE_ARRAY` to `PB_HTYPE_REPEATED`.
+-   Change `PB_HTYPE_CALLBACK` to `PB_ATYPE()` and `PB_ATYPE_CALLBACK`.
+
+**Error indications:** Compiler error: `PB_HTYPE_ARRAY` or
+`PB_HTYPE_CALLBACK` undeclared.
+
+Nanopb-0.1.6 (2012-09-02)
+-------------------------
+
+### Refactored field decoder interface
+
+**Rationale:** Similarly to field encoders in nanopb-0.1.3.
+
+**Changes:** New functions with names `pb_decode_*` were added.
+
+**Required actions:** By defining NANOPB_INTERNALS, you can still keep
+using the old functions. Recommended action is to replace any calls with
+the newer `pb_decode_*` equivalents.
+
+**Error indications:** Compiler warning: implicit declaration of
+function `pb_dec_string`, `pb_dec_varint`, `pb_dec_submessage` or
+similar.
+
+Nanopb-0.1.3 (2012-06-12)
+-------------------------
+
+### Refactored field encoder interface
+
+**Rationale:** The old `pb_enc_*` functions were designed mostly for
+the internal use by the core. Because they are internally accessed
+through function pointers, their signatures had to be common. This led
+to a confusing interface for external users.
+
+**Changes:** New functions with names `pb_encode_*` were added. These
+have easier to use interfaces. The old functions are now only thin
+wrappers for the new interface.
+
+**Required actions:** By defining NANOPB_INTERNALS, you can still keep
+using the old functions. Recommended action is to replace any calls with
+the newer `pb_encode_*` equivalents.
+
+**Error indications:** Compiler warning: implicit declaration of
+function `pb_enc_string`, *pb_enc_varint,`pb_enc_submessage\` or
+similar.

+ 1034 - 0
components/spotify/cspot/bell/nanopb/docs/reference.md

@@ -0,0 +1,1034 @@
+# Nanopb: API reference
+
+## Compilation options
+
+The following options can be specified in one of two ways:
+
+1.  Using the -D switch on the C compiler command line.
+2.  Using a `#define` at the top of pb.h.
+
+> **NOTE:** You must have the same settings for the nanopb library and all code that
+includes nanopb headers.
+
+* `PB_ENABLE_MALLOC`: Enable dynamic allocation support in the decoder.
+* `PB_MAX_REQUIRED_FIELDS`: Maximum number of proto2 `required` fields to check for presence. Default value is 64. Compiler warning will tell if you need this.
+* `PB_FIELD_32BIT`: Add support for field tag numbers over 65535, fields larger than 64 kiB and arrays larger than 65535 entries. Compiler warning will tell if you need this.
+* `PB_NO_ERRMSG`: Disable error message support to save code size. Only error information is the `true`/`false` return value.
+* `PB_BUFFER_ONLY`: Disable support for custom streams. Only supports encoding and decoding with memory buffers. Speeds up execution and slightly decreases code size.
+* `PB_SYSTEM_HEADER`: Replace the standards header files with a single system-specific header file. Value must include quotes, for example `#define PB_SYSTEM_HEADER "foo.h"`. See [extra/pb_syshdr.h](https://github.com/nanopb/nanopb/blob/master/extra/pb_syshdr.h) for an example.
+* `PB_WITHOUT_64BIT`: Disable support of 64-bit integer fields, for old compilers or for a slight speedup on 8-bit platforms.
+* `PB_ENCODE_ARRAYS_UNPACKED`: Encode scalar arrays in the unpacked format, which takes up more space. Only to be used when the decoder on the receiving side cannot process packed arrays, such as [protobuf.js versions before 2020](https://github.com/protocolbuffers/protobuf/issues/1701).
+* `PB_CONVERT_DOUBLE_FLOAT`: Convert doubles to floats for platforms that do not support 64-bit `double` datatype. Mainly `AVR` processors.
+* `PB_VALIDATE_UTF8`: Check whether incoming strings are valid UTF-8 sequences. Adds a small performance and code size penalty.
+
+The `PB_MAX_REQUIRED_FIELDS` and `PB_FIELD_32BIT` settings allow
+raising some datatype limits to suit larger messages. Their need is
+recognized automatically by C-preprocessor `#if`-directives in the
+generated `.pb.c` files. The default setting is to use the smallest
+datatypes (least resources used).
+
+## Proto file options
+
+The generator behaviour can be adjusted using several options, defined
+in the [nanopb.proto](https://github.com/nanopb/nanopb/blob/master/generator/proto/nanopb.proto) file in the generator folder. Here is a list of the most common options, but see the file for a full list:
+
+* `max_size`: Allocated maximum size for `bytes` and `string` fields. For strings, this includes the terminating zero.
+* `max_length`: Maximum length for `string` fields. Setting this is equivalent to setting `max_size` to a value of length + 1.
+* `max_count`: Allocated maximum number of entries in arrays (`repeated` fields).
+* `type`: Select how memory is allocated for the generated field. Default value is `FT_DEFAULT`, which defaults to `FT_STATIC` when possible and `FT_CALLBACK` if not possible. You can use `FT_CALLBACK`, `FT_POINTER`, `FT_STATIC` or `FT_IGNORE` to select a callback field, a dynamically allocate dfield, a statically allocated field or to completely ignore the field.
+* `long_names`: Prefix the enum name to the enum value in definitions, i.e. `EnumName_EnumValue`. Enabled by default.
+* `packed_struct`: Make the generated structures packed, which saves some RAM space but slows down execution. This can only be used if the CPU supports unaligned access to variables.
+* `skip_message`: Skip a whole message from generation. Can be used to remove message types that are not needed in an application.
+* `no_unions`: Generate `oneof` fields as multiple optional fields instead of a C `union {}`.
+* `anonymous_oneof`: Generate `oneof` fields as an anonymous union.
+* `msgid`: Specifies a unique id for this message type. Can be used by user code as an identifier.
+* `fixed_length`: Generate `bytes` fields with a constant length defined by `max_size`. A separate `.size` field will then not be generated.
+* `fixed_count`: Generate arrays with constant length defined by `max_count`.
+* `package`: Package name that applies only for nanopb generator. Defaults to name defined by `package` keyword in .proto file, which applies for all languages.
+* `int_size`: Override the integer type of a field. For example, specify `int_size = IS_8` to convert `int32` from protocol definition into `int8_t` in the structure.
+
+These options can be defined for the .proto files before they are
+converted using the nanopb-generatory.py. There are three ways to define
+the options:
+
+1.  Using a separate .options file. This allows using wildcards for
+    applying same options to multiple fields.
+2.  Defining the options on the command line of nanopb_generator.py.
+    This only makes sense for settings that apply to a whole file.
+3.  Defining the options in the .proto file using the nanopb extensions.
+    This keeps the options close to the fields they apply to, but can be
+    problematic if the same .proto file is shared with many projects.
+
+The effect of the options is the same no matter how they are given. The
+most common purpose is to define maximum size for string fields in order
+to statically allocate them.
+
+### Defining the options in a .options file
+
+The preferred way to define options is to have a separate file
+'myproto.options' in the same directory as the 'myproto.proto'. :
+
+    # myproto.proto
+    message MyMessage {
+        required string name = 1;
+        repeated int32 ids = 4;
+    }
+
+    # myproto.options
+    MyMessage.name         max_size:40
+    MyMessage.ids          max_count:5
+
+The generator will automatically search for this file and read the
+options from it. The file format is as follows:
+
+-   Lines starting with `#` or `//` are regarded as comments.
+-   Blank lines are ignored.
+-   All other lines should start with a field name pattern, followed by
+    one or more options. For example: `MyMessage.myfield max_size:5 max_count:10`.
+-   The field name pattern is matched against a string of form
+    `Message.field`. For nested messages, the string is
+    `Message.SubMessage.field`. A whole file can be matched by its
+    filename `dir/file.proto`.
+-   The field name pattern may use the notation recognized by Python
+    fnmatch():
+    -   `*` matches any part of string, like `Message.*` for all
+        fields
+    -   `?` matches any single character
+    -   `[seq]` matches any of characters `s`, `e` and `q`
+    -   `[!seq]` matches any other character
+-   The options are written as `option_name:option_value` and
+    several options can be defined on same line, separated by
+    whitespace.
+-   Options defined later in the file override the ones specified
+    earlier, so it makes sense to define wildcard options first in the
+    file and more specific ones later.
+
+To debug problems in applying the options, you can use the `-v` option
+for the nanopb generator. With protoc, plugin options are specified with
+`--nanopb_opt`:
+
+    nanopb_generator -v message.proto           # When invoked directly
+    protoc ... --nanopb_opt=-v --nanopb_out=. message.proto  # When invoked through protoc
+
+Protoc doesn't currently pass include path into plugins. Therefore if
+your `.proto` is in a subdirectory, nanopb may have trouble finding the
+associated `.options` file. A workaround is to specify include path
+separately to the nanopb plugin, like:
+
+    protoc -Isubdir --nanopb_opt=-Isubdir --nanopb_out=. message.proto
+
+If preferred, the name of the options file can be set using generator
+argument `-f`.
+
+### Defining the options on command line
+
+The nanopb_generator.py has a simple command line option `-s OPTION:VALUE`.
+The setting applies to the whole file that is being processed.
+
+### Defining the options in the .proto file
+
+The .proto file format allows defining custom options for the fields.
+The nanopb library comes with *nanopb.proto* which does exactly that,
+allowing you do define the options directly in the .proto file:
+
+~~~~ protobuf
+import "nanopb.proto";
+
+message MyMessage {
+    required string name = 1 [(nanopb).max_size = 40];
+    repeated int32 ids = 4   [(nanopb).max_count = 5];
+}
+~~~~
+
+A small complication is that you have to set the include path of protoc
+so that nanopb.proto can be found. Therefore, to compile a .proto file
+which uses options, use a protoc command similar to:
+
+    protoc -Inanopb/generator/proto -I. --nanopb_out=. message.proto
+
+The options can be defined in file, message and field scopes:
+
+~~~~ protobuf
+option (nanopb_fileopt).max_size = 20; // File scope
+message Message
+{
+    option (nanopb_msgopt).max_size = 30; // Message scope
+    required string fieldsize = 1 [(nanopb).max_size = 40]; // Field scope
+}
+~~~~
+
+## pb.h
+
+### pb_byte_t
+
+Type used for storing byte-sized data, such as raw binary input and
+bytes-type fields.
+
+    typedef uint_least8_t pb_byte_t;
+
+For most platforms this is equivalent to `uint8_t`. Some platforms
+however do not support 8-bit variables, and on those platforms 16 or 32
+bits need to be used for each byte.
+
+### pb_size_t
+
+Type used for storing tag numbers and sizes of message fields. By
+default the type is 16-bit:
+
+    typedef uint_least16_t pb_size_t;
+
+If tag numbers or fields larger than 65535 are needed, `PB_FIELD_32BIT`
+option can be used to change the type to 32-bit value.
+
+### pb_type_t
+
+Type used to store the type of each field, to control the
+encoder/decoder behaviour.
+
+    typedef uint_least8_t pb_type_t;
+
+The low-order nibble of the enumeration values defines the function that
+can be used for encoding and decoding the field data:
+
+| LTYPE identifier                 |Value  |Storage format
+| ---------------------------------|-------|------------------------------------------------
+| `PB_LTYPE_BOOL`                  |0x00   |Boolean.
+| `PB_LTYPE_VARINT`                |0x01   |Integer.
+| `PB_LTYPE_UVARINT`               |0x02   |Unsigned integer.
+| `PB_LTYPE_SVARINT`               |0x03   |Integer, zigzag encoded.
+| `PB_LTYPE_FIXED32`               |0x04   |32-bit integer or floating point.
+| `PB_LTYPE_FIXED64`               |0x05   |64-bit integer or floating point.
+| `PB_LTYPE_BYTES`                 |0x06   |Structure with `size_t` field and byte array.
+| `PB_LTYPE_STRING`                |0x07   |Null-terminated string.
+| `PB_LTYPE_SUBMESSAGE`            |0x08   |Submessage structure.
+| `PB_LTYPE_SUBMSG_W_CB`           |0x09   |Submessage with pre-decoding callback.
+| `PB_LTYPE_EXTENSION`             |0x0A   |Pointer to `pb_extension_t`.
+| `PB_LTYPE_FIXED_LENGTH_BYTES`    |0x0B   |Inline `pb_byte_t` array of fixed size.
+
+The bits 4-5 define whether the field is required, optional or repeated.
+There are separate definitions for semantically different modes, even
+though some of them share values and are distinguished based on values
+of other fields:
+
+ |HTYPE identifier     |Value  |Field handling
+ |---------------------|-------|--------------------------------------------------------------------------------------------
+ |`PB_HTYPE_REQUIRED`  |0x00   |Verify that field exists in decoded message.
+ |`PB_HTYPE_OPTIONAL`  |0x10   |Use separate `has_<field>` boolean to specify whether the field is present.
+ |`PB_HTYPE_SINGULAR`  |0x10   |Proto3 field, which is present when its value is non-zero.
+ |`PB_HTYPE_REPEATED`  |0x20   |A repeated field with preallocated array. Separate `<field>_count` for number of items.
+ |`PB_HTYPE_FIXARRAY`  |0x20   |A repeated field that has constant length.
+ |`PB_HTYPE_ONEOF`     |0x30   |Oneof-field, only one of each group can be present.
+
+The bits 6-7 define the how the storage for the field is allocated:
+
+|ATYPE identifier     |Value  |Allocation method
+|---------------------|-------|--------------------------------------------------------------------------------------------
+|`PB_ATYPE_STATIC`    |0x00   |Statically allocated storage in the structure.
+|`PB_ATYPE_POINTER`   |0x80   |Dynamically allocated storage. Struct field contains a pointer to the storage.
+|`PB_ATYPE_CALLBACK`  |0x40   |A field with dynamic storage size. Struct field contains a pointer to a callback function.
+
+### pb_msgdesc_t
+
+Autogenerated structure that contains information about a message and
+pointers to the field descriptors. Use functions defined in
+`pb_common.h` to process the field information.
+
+    typedef struct pb_msgdesc_s pb_msgdesc_t;
+    struct pb_msgdesc_s {
+        pb_size_t field_count;
+        const uint32_t *field_info;
+        const pb_msgdesc_t * const * submsg_info;
+        const pb_byte_t *default_value;
+
+        bool (*field_callback)(pb_istream_t *istream, pb_ostream_t *ostream, const pb_field_iter_t *field);
+    };
+
+|                 |                                                        |
+|-----------------|--------------------------------------------------------|
+|`field_count`    | Total number of fields in the message.
+|`field_info`     | Pointer to compact representation of the field information.
+|`submsg_info`    | Pointer to array of pointers to descriptors for submessages.
+|`default_value`  | Default values for this message as an encoded protobuf message.
+|`field_callback` | Function used to handle all callback fields in this message. By default `pb_default_field_callback()`  which loads per-field callbacks from a `pb_callback_t` structure.
+
+### pb_field_iter_t
+
+Describes a single structure field with memory position in relation to
+others. The field information is stored in a compact format and loaded
+into `pb_field_iter_t` by the functions defined in `pb_common.h`.
+
+    typedef struct pb_field_iter_s pb_field_iter_t;
+    struct pb_field_iter_s {
+        const pb_msgdesc_t *descriptor;
+        void *message;
+
+        pb_size_t index;
+        pb_size_t field_info_index;
+        pb_size_t required_field_index;
+        pb_size_t submessage_index;
+
+        pb_size_t tag;
+        pb_size_t data_size;
+        pb_size_t array_size;
+        pb_type_t type;
+
+        void *pField;
+        void *pData;
+        void *pSize;
+
+        const pb_msgdesc_t *submsg_desc;
+    };
+
+|                      |                                                        |
+|----------------------|--------------------------------------------------------|
+| descriptor           | Pointer to `pb_msgdesc_t` for the message that contains this field.
+| message              | Pointer to the start of the message structure.
+| index                | Index of the field inside the message
+| field_info_index     | Index to the internal `field_info` array
+| required_field_index | Index that counts only the required fields
+| submessage_index     | Index that counts only submessages
+| tag                  | Tag number defined in `.proto` file for this field.
+| data_size            | `sizeof()` of the field in the structure. For repeated fields this is for a single array entry.
+| array_size           | Maximum number of items in a statically allocated array.
+| type                 | Type ([pb_type_t](#pb_type_t)) of the field.
+| pField               | Pointer to the field storage in the structure.
+| pData                | Pointer to data contents. For arrays and pointers this can be different than `pField`.
+| pSize                | Pointer to count or has field, or NULL if this field doesn't have such.
+| submsg_desc          | For submessage fields, points to the descriptor for the submessage.
+
+By default [pb_size_t](#pb_size_t) is 16-bit, limiting the sizes and
+tags to 65535. The limit can be raised by defining `PB_FIELD_32BIT`.
+
+### pb_bytes_array_t
+
+An byte array with a field for storing the length:
+
+    typedef struct {
+        pb_size_t size;
+        pb_byte_t bytes[1];
+    } pb_bytes_array_t;
+
+In an actual array, the length of `bytes` may be different. The macros
+`PB_BYTES_ARRAY_T()` and `PB_BYTES_ARRAY_T_ALLOCSIZE()`
+are used to allocate variable length storage for bytes fields.
+
+### pb_callback_t
+
+Part of a message structure, for fields with type PB_HTYPE_CALLBACK:
+
+    typedef struct _pb_callback_t pb_callback_t;
+    struct _pb_callback_t {
+        union {
+            bool (*decode)(pb_istream_t *stream, const pb_field_iter_t *field, void **arg);
+            bool (*encode)(pb_ostream_t *stream, const pb_field_iter_t *field, void * const *arg);
+        } funcs;
+
+        void *arg;
+    };
+
+A pointer to the *arg* is passed to the callback when calling. It can be
+used to store any information that the callback might need. Note that
+this is a double pointer. If you set `field.arg` to point to
+`&data` in your main code, in the callback you can access it like this:
+
+    myfunction(*arg);           /* Gives pointer to data as argument */
+    myfunction(*(data_t*)*arg); /* Gives value of data as argument */
+    *arg = newdata;             /* Alters value of field.arg in structure */
+
+When calling [pb_encode](#pb_encode), `funcs.encode` is used, and
+similarly when calling [pb_decode](#pb_decode), `funcs.decode` is used.
+The function pointers are stored in the same memory location but are of
+incompatible types. You can set the function pointer to NULL to skip the
+field.
+
+### pb_wire_type_t
+
+Protocol Buffers wire types. These are used with
+[pb_encode_tag](#pb_encode_tag). :
+
+    typedef enum {
+        PB_WT_VARINT = 0,
+        PB_WT_64BIT  = 1,
+        PB_WT_STRING = 2,
+        PB_WT_32BIT  = 5
+    } pb_wire_type_t;
+
+### pb_extension_type_t
+
+Defines the handler functions and auxiliary data for a field that
+extends another message. Usually autogenerated by
+`nanopb_generator.py`.
+
+    typedef struct {
+        bool (*decode)(pb_istream_t *stream, pb_extension_t *extension,
+                   uint32_t tag, pb_wire_type_t wire_type);
+        bool (*encode)(pb_ostream_t *stream, const pb_extension_t *extension);
+        const void *arg;
+    } pb_extension_type_t;
+
+In the normal case, the function pointers are `NULL` and the decoder and
+encoder use their internal implementations. The internal implementations
+assume that `arg` points to a [pb_field_iter_t](#pb_field_iter_t)
+that describes the field in question.
+
+To implement custom processing of unknown fields, you can provide
+pointers to your own functions. Their functionality is mostly the same
+as for normal callback fields, except that they get called for any
+unknown field when decoding.
+
+### pb_extension_t
+
+Ties together the extension field type and the storage for the field
+value. For message structs that have extensions, the generator will
+add a `pb_extension_t*` field. It should point to a linked list of
+extensions.
+
+    typedef struct {
+        const pb_extension_type_t *type;
+        void *dest;
+        pb_extension_t *next;
+        bool found;
+    } pb_extension_t;
+
+|                      |                                                        |
+|----------------------|--------------------------------------------------------|
+| type                 | Pointer to the structure that defines the callback functions.
+| dest                 | Pointer to the variable that stores the field value (as used by the default extension callback functions.)
+| next                 | Pointer to the next extension handler, or `NULL` for last handler.
+| found                | Decoder sets this to true if the extension was found.
+
+### PB_GET_ERROR
+
+Get the current error message from a stream, or a placeholder string if
+there is no error message:
+
+    #define PB_GET_ERROR(stream) (string expression)
+
+This should be used for printing errors, for example:
+
+    if (!pb_decode(...))
+    {
+        printf("Decode failed: %s\n", PB_GET_ERROR(stream));
+    }
+
+The macro only returns pointers to constant strings (in code memory), so
+that there is no need to release the returned pointer.
+
+### PB_RETURN_ERROR
+
+Set the error message and return false:
+
+    #define PB_RETURN_ERROR(stream,msg) (sets error and returns false)
+
+This should be used to handle error conditions inside nanopb functions
+and user callback functions:
+
+    if (error_condition)
+    {
+        PB_RETURN_ERROR(stream, "something went wrong");
+    }
+
+The *msg* parameter must be a constant string.
+
+### PB_BIND
+
+This macro generates the [pb_msgdesc_t](#pb_msgdesc_t) and associated
+arrays, based on a list of fields in [X-macro](https://en.wikipedia.org/wiki/X_Macro) format. :
+
+    #define PB_BIND(msgname, structname, width) ...
+
+|                      |                                                        |
+|----------------------|--------------------------------------------------------|
+| msgname              | Name of the message type. Expects `msgname_FIELDLIST` macro to exist.
+| structname           | Name of the C structure to bind to.
+| width                | Number of words per field descriptor, or `AUTO` to use minimum size possible.
+
+This macro is automatically invoked inside the autogenerated `.pb.c`
+files. User code can also call it to bind message types with custom
+structures or class types.
+
+## pb_encode.h
+
+### pb_ostream_from_buffer
+
+Constructs an output stream for writing into a memory buffer. It uses an internal callback that
+stores the pointer in stream `state` field. :
+
+    pb_ostream_t pb_ostream_from_buffer(pb_byte_t *buf, size_t bufsize);
+
+|                      |                                                        |
+|----------------------|--------------------------------------------------------|
+| buf                  | Memory buffer to write into.
+| bufsize              | Maximum number of bytes to write.
+| returns              | An output stream.
+
+After writing, you can check `stream.bytes_written` to find out how
+much valid data there is in the buffer. This should be passed as the
+message length on decoding side.
+
+### pb_write
+
+Writes data to an output stream. Always use this function, instead of
+trying to call stream callback manually. :
+
+    bool pb_write(pb_ostream_t *stream, const pb_byte_t *buf, size_t count);
+
+|                      |                                                        |
+|----------------------|--------------------------------------------------------|
+| stream               | Output stream to write to.
+| buf                  | Pointer to buffer with the data to be written.
+| count                | Number of bytes to write.
+| returns              | True on success, false if maximum length is exceeded or an IO error happens.
+
+> **NOTE:** If an error happens, *bytes_written* is not incremented. Depending on
+the callback used, calling pb_write again after it has failed once may
+cause undefined behavior. Nanopb itself never does this, instead it
+returns the error to user application. The builtin
+`pb_ostream_from_buffer` is safe to call again after failed write.
+
+### pb_encode
+
+Encodes the contents of a structure as a protocol buffers message and
+writes it to output stream. :
+
+    bool pb_encode(pb_ostream_t *stream, const pb_msgdesc_t *fields, const void *src_struct);
+
+|                      |                                                        |
+|----------------------|--------------------------------------------------------|
+| stream               | Output stream to write to.
+| fields               | Message descriptor, usually autogenerated.
+| src_struct           | Pointer to the message structure. Must match `fields` descriptor.
+| returns              | True on success, false on any error condition. Error message is set to `stream->errmsg`.
+
+Normally pb_encode simply walks through the fields description array
+and serializes each field in turn. However, submessages must be
+serialized twice: first to calculate their size and then to actually
+write them to output. This causes some constraints for callback fields,
+which must return the same data on every call.
+
+### pb_encode_ex
+
+Encodes the message, with extended behavior set by flags:
+
+    bool pb_encode_ex(pb_ostream_t *stream, const pb_msgdesc_t *fields, const void *src_struct, unsigned int flags);
+
+|                      |                                                        |
+|----------------------|--------------------------------------------------------|
+| stream               | Output stream to write to.
+| fields               | Message descriptor, usually autogenerated.
+| src_struct           | Pointer to the message structure. Must match `fields` descriptor.
+| flags                | Extended options, see below.
+| returns              | True on success, false on any error condition. Error message is set to `stream->errmsg`.
+
+The options that can be defined are:
+
+* `PB_ENCODE_DELIMITED`: Indicate the length of the message by prefixing with a varint-encoded length. Compatible with `parseDelimitedFrom` in Google's protobuf library.
+* `PB_ENCODE_NULLTERMINATED`: Indicate the length of the message by appending a zero tag value after it. Supported by nanopb decoder, but not by most other protobuf libraries.
+
+### pb_get_encoded_size
+
+Calculates the length of the encoded message.
+
+    bool pb_get_encoded_size(size_t *size, const pb_msgdesc_t *fields, const void *src_struct);
+
+|                      |                                                        |
+|----------------------|--------------------------------------------------------|
+| size                 | Calculated size of the encoded message.
+| fields               | Message descriptor, usually autogenerated.
+| src_struct           | Pointer to the data that will be serialized.
+| returns              | True on success, false on detectable errors in field description or if a field encoder returns false.
+
+### Callback field encoders
+The functions with names `pb_encode_<datatype>` are used when dealing with
+callback fields. The typical reason for using callbacks is to have an
+array of unlimited size. In that case, [pb_encode](#pb_encode) will
+call your callback function, which in turn will call `pb_encode_<datatype>`
+functions repeatedly to write out values.
+
+The tag of a field must be encoded first with
+[pb_encode_tag_for_field](#pb_encode_tag_for_field). After that, you
+can call exactly one of the content-writing functions to encode the
+payload of the field. For repeated fields, you can repeat this process
+multiple times.
+
+Writing packed arrays is a little bit more involved: you need to use
+`pb_encode_tag` and specify `PB_WT_STRING` as the wire
+type. Then you need to know exactly how much data you are going to
+write, and use [pb_encode_varint](#pb_encode_varint) to write out the
+number of bytes before writing the actual data. Substreams can be used
+to determine the number of bytes beforehand; see
+[pb_encode_submessage](#pb_encode_submessage) source code for an
+example.
+
+See [Google Protobuf Encoding Format Documentation](https://developers.google.com/protocol-buffers/docs/encoding)
+for background information on the Protobuf wire format.
+
+#### pb_encode_tag
+
+Starts a field in the Protocol Buffers binary format: encodes the field
+number and the wire type of the data.
+
+    bool pb_encode_tag(pb_ostream_t *stream, pb_wire_type_t wiretype, uint32_t field_number);
+
+|                      |                                                        |
+|----------------------|--------------------------------------------------------|
+| stream               | Output stream to write to. 1-5 bytes will be written.
+| wiretype             | `PB_WT_VARINT`, `PB_WT_64BIT`, `PB_WT_STRING` or `PB_WT_32BIT`
+| field_number         | Identifier for the field, defined in the .proto file. You can get it from `field->tag`.
+| returns              | True on success, false on IO error.
+
+#### pb_encode_tag_for_field
+
+Same as [pb_encode_tag](#pb_encode_tag), except takes the parameters
+from a `pb_field_iter_t` structure.
+
+    bool pb_encode_tag_for_field(pb_ostream_t *stream, const pb_field_iter_t *field);
+
+|                      |                                                        |
+|----------------------|--------------------------------------------------------|
+| stream               | Output stream to write to. 1-5 bytes will be written.
+| field                | Field iterator for this field.
+| returns              | True on success, false on IO error or unknown field type.
+
+This function only considers the `PB_LTYPE` of the field. You can use it from
+your field callbacks, because the source generator writes correct `LTYPE`
+also for callback type fields.
+
+Wire type mapping is as follows:
+
+| LTYPEs                                           | Wire type
+|--------------------------------------------------|-----------------
+| BOOL, VARINT, UVARINT, SVARINT                   | PB_WT_VARINT
+| FIXED64                                          | PB_WT_64BIT
+| STRING, BYTES, SUBMESSAGE, FIXED_LENGTH_BYTES    | PB_WT_STRING
+| FIXED32                                          | PB_WT_32BIT
+
+#### pb_encode_varint
+
+Encodes a signed or unsigned integer in the
+[varint](http://code.google.com/apis/protocolbuffers/docs/encoding.html#varints)
+format. Works for fields of type `bool`, `enum`, `int32`, `int64`, `uint32` and `uint64`:
+
+    bool pb_encode_varint(pb_ostream_t *stream, uint64_t value);
+
+|                      |                                                        |
+|----------------------|--------------------------------------------------------|
+| stream               | Output stream to write to. 1-10 bytes will be written.
+| value                | Value to encode, cast to `uint64_t`.
+| returns              | True on success, false on IO error.
+
+> **NOTE:** Value will be converted to `uint64_t` in the argument.
+> To encode signed values, the argument should be cast to `int64_t` first for correct sign extension.
+
+#### pb_encode_svarint
+
+Encodes a signed integer in the [zig-zagged](https://developers.google.com/protocol-buffers/docs/encoding#signed_integers) format.
+Works for fields of type `sint32` and `sint64`:
+
+    bool pb_encode_svarint(pb_ostream_t *stream, int64_t value);
+
+(parameters are the same as for [pb_encode_varint](#pb_encode_varint)
+
+#### pb_encode_string
+
+Writes the length of a string as varint and then contents of the string.
+Works for fields of type `bytes` and `string`:
+
+    bool pb_encode_string(pb_ostream_t *stream, const pb_byte_t *buffer, size_t size);
+
+|                      |                                                        |
+|----------------------|--------------------------------------------------------|
+| stream               | Output stream to write to.
+| buffer               | Pointer to string data.
+| size                 | Number of bytes in the string. Pass `strlen(s)` for strings.
+| returns              | True on success, false on IO error.
+
+#### pb_encode_fixed32
+
+Writes 4 bytes to stream and swaps bytes on big-endian architectures.
+Works for fields of type `fixed32`, `sfixed32` and `float`:
+
+    bool pb_encode_fixed32(pb_ostream_t *stream, const void *value);
+
+|                      |                                                        |
+|----------------------|--------------------------------------------------------|
+| stream               | Output stream to write to. 4 bytes will be written.
+| value                | Pointer to a 4-bytes large C variable, for example `uint32_t foo;`.
+| returns              | True on success, false on IO error.
+
+#### pb_encode_fixed64
+
+Writes 8 bytes to stream and swaps bytes on big-endian architecture.
+Works for fields of type `fixed64`, `sfixed64` and `double`:
+
+    bool pb_encode_fixed64(pb_ostream_t *stream, const void *value);
+
+|                      |                                                        |
+|----------------------|--------------------------------------------------------|
+| stream               | Output stream to write to. 8 bytes will be written.
+| value                | Pointer to a 8-bytes large C variable, for example `uint64_t foo;`.
+| returns              | True on success, false on IO error.
+
+#### pb_encode_float_as_double
+
+Encodes a 32-bit `float` value so that it appears like a 64-bit `double` in the encoded message.
+This is sometimes needed when platforms like AVR that do not support 64-bit `double` need to communicate using a
+message type that contains `double` fields.
+
+    bool pb_encode_float_as_double(pb_ostream_t *stream, float value);
+
+|                      |                                                        |
+|----------------------|--------------------------------------------------------|
+| stream               | Output stream to write to. 8 bytes will be written.
+| value                | Float value to encode.
+| returns              | True on success, false on IO error.
+
+#### pb_encode_submessage
+
+Encodes a submessage field, including the size header for it. Works for
+fields of any message type.
+
+    bool pb_encode_submessage(pb_ostream_t *stream, const pb_msgdesc_t *fields, const void *src_struct);
+
+|                      |                                                        |
+|----------------------|--------------------------------------------------------|
+| stream               | Output stream to write to.
+| fields               | Pointer to the autogenerated message descriptor for the submessage type, e.g. `MyMessage_fields`.
+| src                  | Pointer to the structure where submessage data is.
+| returns              | True on success, false on IO errors, pb_encode errors or if submessage size changes between calls.
+
+In Protocol Buffers format, the submessage size must be written before
+the submessage contents. Therefore, this function has to encode the
+submessage twice in order to know the size beforehand.
+
+If the submessage contains callback fields, the callback function might
+misbehave and write out a different amount of data on the second call.
+This situation is recognized and `false` is returned, but garbage will
+be written to the output before the problem is detected.
+
+## pb_decode.h
+
+### pb_istream_from_buffer
+
+Helper function for creating an input stream that reads data from a
+memory buffer.
+
+    pb_istream_t pb_istream_from_buffer(const pb_byte_t *buf, size_t bufsize);
+
+|                      |                                                        |
+|----------------------|--------------------------------------------------------|
+| buf                  | Pointer to byte array to read from.
+| bufsize              | Size of the byte array.
+| returns              | An input stream ready to use.
+
+### pb_read
+
+Read data from input stream. Always use this function, don't try to
+call the stream callback directly.
+
+    bool pb_read(pb_istream_t *stream, pb_byte_t *buf, size_t count);
+
+|                      |                                                        |
+|----------------------|--------------------------------------------------------|
+| stream               | Input stream to read from.
+| buf                  | Buffer to store the data to, or `NULL` to just read data without storing it anywhere.
+| count                | Number of bytes to read.
+| returns              | True on success, false if `stream->bytes_left` is less than `count` or if an IO error occurs.
+
+End of file is signalled by `stream->bytes_left` being zero after pb_read returns false.
+
+### pb_decode
+
+Read and decode all fields of a structure. Reads until EOF on input
+stream.
+
+    bool pb_decode(pb_istream_t *stream, const pb_msgdesc_t *fields, void *dest_struct);
+
+|                      |                                                        |
+|----------------------|--------------------------------------------------------|
+| stream               | Input stream to read from.
+| fields               | Message descriptor, usually autogenerated.
+| dest_struct          | Pointer to message structure where data will be stored.
+| returns              | True on success, false on any error condition. Error message will be in `stream->errmsg`.
+
+In Protocol Buffers binary format, end-of-file is only allowed between fields.
+If it happens anywhere else, pb_decode will return `false`. If
+pb_decode returns `false`, you cannot trust any of the data in the
+structure.
+
+For optional fields, this function applies the default value and sets
+`has_<field>` to false if the field is not present.
+
+If `PB_ENABLE_MALLOC` is defined, this function may allocate storage
+for any pointer type fields. In this case, you have to call
+[pb_release](#pb_release) to release the memory after you are done with
+the message. On error return `pb_decode` will release the memory itself.
+
+### pb_decode_ex
+
+Same as [pb_decode](#pb_decode), but allows extended options.
+
+    bool pb_decode_ex(pb_istream_t *stream, const pb_msgdesc_t *fields, void *dest_struct, unsigned int flags);
+
+|                      |                                                        |
+|----------------------|--------------------------------------------------------|
+| stream               | Input stream to read from.
+| fields               | Message descriptor, usually autogenerated.
+| dest_struct          | Pointer to message structure where data will be stored.
+| flags                | Extended options, see below
+| returns              | True on success, false on any error condition. Error message will be in `stream->errmsg`.
+
+The following options can be defined and combined with bitwise `|` operator:
+
+* `PB_DECODE_NOINIT`: Do not initialize structure before decoding. This can be used to combine multiple messages, or if you have already initialized the message structure yourself.
+
+* `PB_DECODE_DELIMITED`: Expect a length prefix in varint format before message. The counterpart of `PB_ENCODE_DELIMITED`.
+
+* `PB_DECODE_NULLTERMINATED`: Expect the message to be terminated with zero tag. The counterpart of `PB_ENCODE_NULLTERMINATED`.
+
+If `PB_ENABLE_MALLOC` is defined, this function may allocate storage
+for any pointer type fields. In this case, you have to call
+[pb_release](#pb_release) to release the memory after you are done with
+the message. On error return `pb_decode_ex` will release the memory
+itself.
+
+### pb_release
+
+Releases any dynamically allocated fields:
+
+    void pb_release(const pb_msgdesc_t *fields, void *dest_struct);
+
+|                      |                                                        |
+|----------------------|--------------------------------------------------------|
+| fields               | Message descriptor, usually autogenerated.
+| dest_struct          | Pointer to structure where data is stored. If `NULL`, function does nothing.
+
+This function is only available if `PB_ENABLE_MALLOC` is defined. It
+will release any pointer type fields in the structure and set the
+pointers to `NULL`.
+
+This function is safe to call multiple times, calling it again does nothing.
+
+### pb_decode_tag
+
+Decode the tag that comes before field in the protobuf encoding:
+
+    bool pb_decode_tag(pb_istream_t *stream, pb_wire_type_t *wire_type, uint32_t *tag, bool *eof);
+
+|                      |                                                        |
+|----------------------|--------------------------------------------------------|
+| stream               | Input stream to read from.
+| wire_type            | Pointer to variable where to store the wire type of the field.
+| tag                  | Pointer to variable where to store the tag of the field.
+| eof                  | Pointer to variable where to store end-of-file status.
+| returns              | True on success, false on error or EOF.
+
+When the message (stream) ends, this function will return `false` and set
+`eof` to true. On other errors, `eof` will be set to false.
+
+### pb_skip_field
+
+Remove the data for a field from the stream, without actually decoding it:
+
+    bool pb_skip_field(pb_istream_t *stream, pb_wire_type_t wire_type);
+
+|                      |                                                        |
+|----------------------|--------------------------------------------------------|
+| stream               | Input stream to read from.
+| wire_type            | Type of field to skip.
+| returns              | True on success, false on IO error.
+
+This function determines the amount of bytes to read based on the wire type.
+For `PB_WT_STRING`, it will read the length prefix of a string or submessage
+to determine its length.
+
+### Callback field decoders
+The functions with names `pb_decode_<datatype>` are used when dealing with callback fields.
+The typical reason for using callbacks is to have an array of unlimited size.
+In that case, [pb_decode](#pb_decode) will call your callback function repeatedly,
+which can then store the values into e.g. filesystem in the order received in.
+
+For decoding numeric (including enumerated and boolean) values, use
+[pb_decode_varint](#pb_decode_varint), [pb_decode_svarint](#pb_decode_svarint),
+[pb_decode_fixed32](#pb_decode_fixed32) and [pb_decode_fixed64](#pb_decode_fixed64).
+They take a pointer to a 32- or 64-bit C variable, which you may then cast to smaller datatype for storage.
+
+For decoding strings and bytes fields, the length has already been decoded and the callback function is given a length-limited substream.
+You can therefore check the total length in `stream->bytes_left` and read the data using [pb_read](#pb_read).
+
+Finally, for decoding submessages in a callback, use [pb_decode](#pb_decode) and pass it the `SubMessage_fields` descriptor array.
+
+#### pb_decode_varint
+
+Read and decode a [varint](http://code.google.com/apis/protocolbuffers/docs/encoding.html#varints)
+encoded integer.
+
+    bool pb_decode_varint(pb_istream_t *stream, uint64_t *dest);
+
+|                      |                                                        |
+|----------------------|--------------------------------------------------------|
+| stream               | Input stream to read from. 1-10 bytes will be read.
+| dest                 | Storage for the decoded integer. Value is undefined on error.
+| returns              | True on success, false if value exceeds uint64_t range or an IO error happens.
+
+#### pb_decode_varint32
+
+Same as `pb_decode_varint`, but limits the value to 32 bits:
+
+    bool pb_decode_varint32(pb_istream_t *stream, uint32_t *dest);
+
+Parameters are the same as `pb_decode_varint`. This function can be used
+for decoding lengths and other commonly occurring elements that you know
+shouldn't be larger than 32 bit. It will return an error if the value
+exceeds the `uint32_t` datatype.
+
+#### pb_decode_svarint
+
+Similar to [pb_decode_varint](#pb_decode_varint), except that it
+performs zigzag-decoding on the value. This corresponds to the Protocol
+Buffers `sint32` and `sint64` datatypes. :
+
+    bool pb_decode_svarint(pb_istream_t *stream, int64_t *dest);
+
+(parameters are the same as [pb_decode_varint](#pb_decode_varint))
+
+#### pb_decode_fixed32
+
+Decode a `fixed32`, `sfixed32` or `float` value.
+
+    bool pb_decode_fixed32(pb_istream_t *stream, void *dest);
+
+|                      |                                                        |
+|----------------------|--------------------------------------------------------|
+| stream               | Input stream to read from. 4 bytes will be read.
+| dest                 | Pointer to destination `int32_t`, `uint32_t` or `float`.
+| returns              | True on success, false on IO errors.
+
+This function reads 4 bytes from the input stream. On big endian
+architectures, it then reverses the order of the bytes. Finally, it
+writes the bytes to `dest`.
+
+#### pb_decode_fixed64
+
+Decode a `fixed64`, `sfixed64` or `double` value. :
+
+    bool pb_decode_fixed64(pb_istream_t *stream, void *dest);
+
+|                      |                                                        |
+|----------------------|--------------------------------------------------------|
+| stream               | Input stream to read from. 8 bytes will be read.
+| dest                 | Pointer to destination `int64_t`, `uint64_t` or `double`.
+| returns              | True on success, false on IO errors.
+
+Same as [pb_decode_fixed32](#pb_decode_fixed32), except this reads 8
+bytes.
+
+#### pb_decode_double_as_float
+
+Decodes a 64-bit `double` value into a 32-bit `float`
+variable. Counterpart of [pb_encode_float_as_double](#pb_encode_float_as_double). :
+
+    bool pb_decode_double_as_float(pb_istream_t *stream, float *dest);
+
+|                      |                                                        |
+|----------------------|--------------------------------------------------------|
+| stream               | Input stream to read from. 8 bytes will be read.
+| dest                 | Pointer to destination *float*.
+| returns              | True on success, false on IO errors.
+
+#### pb_make_string_substream
+
+Decode the length for a field with wire type `PB_WT_STRING` and create
+a substream for reading the data.
+
+    bool pb_make_string_substream(pb_istream_t *stream, pb_istream_t *substream);
+
+|                      |                                                        |
+|----------------------|--------------------------------------------------------|
+| stream               | Original input stream to read the length and data from.
+| substream            | Storage for a new substream that has limited length. Filled in by the function.
+| returns              | True on success, false if reading the length fails.
+
+This function uses `pb_decode_varint` to read an integer from the stream.
+This is interpreted as a number of bytes, and the substream is set up so that its `bytes_left` is initially the same as the
+length, and its callback function and state the same as the parent stream.
+
+#### pb_close_string_substream
+
+Close the substream created with
+[pb_make_string_substream](#pb_make_string_substream).
+
+    void pb_close_string_substream(pb_istream_t *stream, pb_istream_t *substream);
+
+|                      |                                                        |
+|----------------------|--------------------------------------------------------|
+| stream               | Original input stream to read data from.
+| substream            | Substream to close
+
+This function copies back the state from the substream to the parent stream,
+and throws away any unread data from the substream.
+It must be called after done with the substream.
+
+## pb_common.h
+
+### pb_field_iter_begin
+
+Begins iterating over the fields in a message type:
+
+    bool pb_field_iter_begin(pb_field_iter_t *iter, const pb_msgdesc_t *desc, void *message);
+
+|                      |                                                        |
+|----------------------|--------------------------------------------------------|
+| iter                 | Pointer to destination [pb_field_iter_t](#pb_field_iter_t) variable.
+| desc                 | Autogenerated message descriptor.
+| message              | Pointer to message structure.
+| returns              | True on success, false if the message type has no fields.
+
+### pb_field_iter_next
+
+Advance to the next field in the message:
+
+    bool pb_field_iter_next(pb_field_iter_t *iter);
+
+|                      |                                                        |
+|----------------------|--------------------------------------------------------|
+| iter                 | Pointer to `pb_field_iter_t` previously initialized by [pb_field_iter_begin](#pb_field_iter_begin).
+| returns              | True on success, false after last field in the message.
+
+When the last field in the message has been processed, this function
+will return false and initialize `iter` back to the first field in the
+message.
+
+### pb_field_iter_find
+
+Find a field specified by tag number in the message:
+
+    bool pb_field_iter_find(pb_field_iter_t *iter, uint32_t tag);
+
+|                      |                                                        |
+|----------------------|--------------------------------------------------------|
+| iter                 | Pointer to `pb_field_iter_t` previously initialized by [pb_field_iter_begin](#pb_field_iter_begin).
+| tag                  | Tag number to search for.
+| returns              | True if field was found, false otherwise.
+
+This function is functionally identical to calling `pb_field_iter_next()` until `iter.tag` equals the searched value.
+Internally this function avoids fully processing the descriptor for intermediate fields.
+
+### pb_validate_utf8
+
+Validates an UTF8 encoded string:
+
+    bool pb_validate_utf8(const char *s);
+
+|                      |                                                        |
+|----------------------|--------------------------------------------------------|
+| s                    | Pointer to beginning of a string.
+| returns              | True, if string is valid UTF-8, false otherwise.
+
+The protobuf standard requires that `string` fields only contain valid
+UTF-8 encoded text, while `bytes` fields can contain arbitrary data.
+When the compilation option `PB_VALIDATE_UTF8` is defined, nanopb will
+automatically validate strings on both encoding and decoding.
+
+User code can call this function to validate strings in e.g. custom
+callbacks.

+ 92 - 0
components/spotify/cspot/bell/nanopb/docs/security.md

@@ -0,0 +1,92 @@
+# Nanopb: Security model
+
+Importance of security in a Protocol Buffers library
+----------------------------------------------------
+
+In the context of protocol buffers, security comes into play when
+decoding untrusted data. Naturally, if the attacker can modify the
+contents of a protocol buffers message, he can feed the application any
+values possible. Therefore the application itself must be prepared to
+receive untrusted values.
+
+Where nanopb plays a part is preventing the attacker from running
+arbitrary code on the target system. Mostly this means that there must
+not be any possibility to cause buffer overruns, memory corruption or
+invalid pointers by the means of crafting a malicious message.
+
+Division of trusted and untrusted data
+--------------------------------------
+
+The following data is regarded as **trusted**. It must be under the
+control of the application writer. Malicious data in these structures
+could cause security issues, such as execution of arbitrary code:
+
+1.  Callback, pointer and extension fields in message structures given
+    to pb_encode() and pb_decode(). These fields are memory pointers,
+    and are generated depending on the message definition in the .proto
+    file.
+2.  The automatically generated field definitions, i.e.
+    `pb_msgdesc_t`.
+3.  Contents of the `pb_istream_t` and `pb_ostream_t` structures
+    (this does not mean the contents of the stream itself, just the
+    stream definition).
+
+The following data is regarded as **untrusted**. Invalid/malicious data
+in these will cause "garbage in, garbage out" behaviour. It will not
+cause buffer overflows, information disclosure or other security
+problems:
+
+1.  All data read from `pb_istream_t`.
+2.  All fields in message structures, except:
+    -   callbacks (`pb_callback_t` structures)
+    -   pointer fields and `_count` fields for pointers
+    -   extensions (`pb_extension_t` structures)
+
+Invariants
+----------
+
+The following invariants are maintained during operation, even if the
+untrusted data has been maliciously crafted:
+
+1.  Nanopb will never read more than `bytes_left` bytes from
+    `pb_istream_t`.
+2.  Nanopb will never write more than `max_size` bytes to
+    `pb_ostream_t`.
+3.  Nanopb will never access memory out of bounds of the message
+    structure.
+4.  After `pb_decode()` returns successfully, the message structure will
+    be internally consistent:
+    -   The `count` fields of arrays will not exceed the array size.
+    -   The `size` field of bytes will not exceed the allocated size.
+    -   All string fields will have null terminator.
+    -   bool fields will have valid true/false values (since
+        nanopb-0.3.9.4)
+    -   pointer fields will be either `NULL` or point to valid data
+5.  After `pb_encode()` returns successfully, the resulting message is a
+    valid protocol buffers message. (Except if user-defined callbacks
+    write incorrect data.)
+6.  All memory allocated by `pb_decode()` will be released by a subsequent
+    call to `pb_release()` on the same message.
+
+Further considerations
+----------------------
+
+Even if the nanopb library is free of any security issues, there are
+still several possible attack vectors that the application author must
+consider. The following list is not comprehensive:
+
+1.  Stack usage may depend on the contents of the message. The message
+    definition places an upper bound on how much stack will be used.
+    Tests should be run with all fields present, to record the maximum
+    possible stack usage.
+2.  Callbacks can do anything. The code for the callbacks must be
+    carefully checked if they are used with untrusted data.
+3.  If using stream input, a maximum size should be set in
+    `pb_istream_t` to stop a denial of service attack from using an
+    infinite message.
+4.  If using network sockets as streams, a timeout should be set to stop
+    denial of service attacks.
+5.  If using `malloc()` support, some method of limiting memory use
+    should be employed. This can be done by defining custom
+    `pb_realloc()` function. Nanopb will properly detect and handle
+    failed memory allocations.

+ 173 - 0
components/spotify/cspot/bell/nanopb/docs/whats_new.md

@@ -0,0 +1,173 @@
+# Nanopb: New features in nanopb 0.4
+
+## What's new in nanopb 0.4
+
+Long in the making, nanopb 0.4 has seen some wide reaching improvements
+in reaction to the development of the rest of the protobuf ecosystem.
+This document showcases features that are not immediately visible, but
+that you may want to take advantage of.
+
+A lot of effort has been spent in retaining backwards and forwards
+compatibility with previous nanopb versions. For a list of breaking
+changes, see [migration document](migration.html)
+
+### New field descriptor format
+
+The basic design of nanopb has always been that the information about
+messages is stored in a compact descriptor format, which is iterated in
+runtime. Initially it was very tightly tied with encoder and decoder
+logic.
+
+In nanopb-0.3.0 the field iteration logic was separated to
+`pb_common.c`. Already at that point it was clear that the old format
+was getting too limited, but it wasn't extended at that time.
+
+Now in 0.4, the descriptor format was completely decoupled from the
+encoder and decoder logic, and redesigned to meet new demands.
+Previously each field was stored as `pb_field_t` struct, which was
+between 8 and 32 bytes in size, depending on compilation options and
+platform. Now information about fields is stored as a variable length
+sequence of `uint32_t` data words. There are 1, 2, 4 and 8 word formats,
+with the 8 word format containing plenty of space for future
+extensibility.
+
+One benefit of the variable length format is that most messages now take
+less storage space. Most fields use 2 words, while simple fields in
+small messages require only 1 word. Benefit is larger if code previously
+required `PB_FIELD_16BIT` or `PB_FIELD_32BIT` options. In
+the `AllTypes` test case, 0.3 had data size of 1008 bytes in
+8-bit configuration and 1408 bytes in 16-bit configuration. New format
+in 0.4 takes 896 bytes for either of these.
+
+In addition, the new decoupling has allowed moving most of the field
+descriptor data into FLASH on Harvard architectures, such as AVR.
+Previously nanopb was quite RAM-heavy on AVR, which cannot put normal
+constants in flash like most other platforms do.
+
+### Python packaging for generator
+
+Nanopb generator is now available as a Python package, installable using
+`pip` package manager. This will reduce the need for binary
+packages, as if you have Python already installed you can just
+`pip install nanopb` and have the generator available on path as
+`nanopb_generator`.
+
+The generator can also take advantage of the Python-based `protoc`
+available in `grpcio-tools` Python package. If you also install that,
+there is no longer a need to have binary `protoc` available.
+
+### Generator now automatically calls protoc
+
+Initially, nanopb generator was used in two steps: first calling
+`protoc` to parse the `.proto` file into `.pb` binary
+format, and then calling `nanopb_generator.py` to output the
+`.pb.h` and `.pb.c` files.
+
+Nanopb 0.2.3 added support for running as a `protoc` plugin, which
+allowed single-step generation using `--nanopb_out` parameter. However,
+the plugin mode has two complications: passing options to nanopb
+generator itself becomes more difficult, and the generator does not know
+the actual path of input files. The second limitation has been
+particularly problematic for locating `.options` files.
+
+Both of these older methods still work and will remain supported.
+However, now `nanopb_generator` can also take `.proto` files
+directly and it will transparently call `protoc` in the background.
+
+### Callbacks bound by function name
+
+Since its very beginnings, nanopb has supported field callbacks to allow
+processing structures that are larger than what could fit in memory at
+once. So far the callback functions have been stored in the message
+structure in a `pb_callback_t` struct.
+
+Storing pointers along with user data is somewhat risky from a security
+point of view. In addition it has caused problems with `oneof` fields,
+which reuse the same storage space for multiple submessages. Because
+there is no separate area for each submessage, there is no space to
+store the callback pointers either.
+
+Nanopb-0.4.0 introduces callbacks that are referenced by the function
+name instead of setting the pointers separately. This should work well
+for most applications that have a single callback function for each
+message type. For more complex needs, `pb_callback_t` will also remain
+supported.
+
+Function name callbacks also allow specifying custom data types for
+inclusion in the message structure. For example, you could have
+`MyObject*` pointer along with other message fields, and then process
+that object in custom way in your callback.
+
+This feature is demonstrated in
+[tests/oneof_callback](https://github.com/nanopb/nanopb/tree/master/tests/oneof_callback) test case and
+[examples/network_server](https://github.com/nanopb/nanopb/tree/master/examples/network_server) example.
+
+### Message level callback for oneofs
+
+As mentioned above, callbacks inside submessages inside oneofs have been
+problematic to use. To make using `pb_callback_t`-style callbacks there
+possible, a new generator option `submsg_callback` was added.
+
+Setting this option to true will cause a new message level callback to
+be added before the `which_field` of the oneof. This callback will be
+called when the submessage tag number is known, but before the actual
+message is decoded. The callback can either choose to set callback
+pointers inside the submessage, or just completely decode the submessage
+there and then. If any unread data remains after the callback returns,
+normal submessage decoding will continue.
+
+There is an example of this in [tests/oneof_callback](https://github.com/nanopb/nanopb/tree/master/tests/oneof_callback) test case.
+
+### Binding message types to custom structures
+
+It is often said that good C code is chock full of macros. Or maybe I
+got it wrong. But since nanopb 0.2, the field descriptor generation has
+heavily relied on macros. This allows it to automatically adapt to
+differences in type alignment on different platforms, and to decouple
+the Python generation logic from how the message descriptors are
+implemented on the C side.
+
+Now in 0.4.0, I've made the macros even more abstract. Time will tell
+whether this was such a great idea that I think it is, but now the
+complete list of fields in each message is available in `.pb.h` file.
+This allows a kind of metaprogramming using [X-macros]()
+
+One feature that this can be used for is binding the message descriptor
+to a custom structure or C++ class type. You could have a bunch of other
+fields in the structure and even the datatypes can be different to an
+extent, and nanopb will automatically detect the size and position of
+each field. The generated `.pb.c` files now just have calls of
+`PB_BIND(msgname, structname, width)`. Adding a similar
+call to your own code will bind the message to your own structure.
+
+### UTF-8 validation
+
+Protobuf format defines that strings should consist of valid UTF-8
+codepoints. Previously nanopb has not enforced this, requiring extra
+care in the user code. Now optional UTF-8 validation is available with
+compilation option `PB_VALIDATE_UTF8`.
+
+### Double to float conversion
+
+Some platforms such as `AVR` do not support the `double`
+datatype, instead making it an alias for `float`. This has resulted in
+problems when trying to process message types containing `double` fields
+generated on other machines. There has been an example on how to
+manually perform the conversion between `double` and
+`float`.
+
+Now that example is integrated as an optional feature in nanopb core. By
+defining `PB_CONVERT_DOUBLE_FLOAT`, the required conversion between 32-
+and 64-bit floating point formats happens automatically on decoding and
+encoding.
+
+### Improved testing
+
+Testing on embedded platforms has been integrated in the continuous
+testing environment. Now all of the 80+ test cases are automatically run
+on STM32 and AVR targets. Previously only a few specialized test cases
+were manually tested on embedded systems.
+
+Nanopb fuzzer has also been integrated in Google's [OSSFuzz](https://google.github.io/oss-fuzz/)
+platform, giving a huge boost in the CPU power available for randomized
+testing.

+ 18 - 0
components/spotify/cspot/bell/nanopb/examples/cmake_relpath/CMakeLists.txt

@@ -0,0 +1,18 @@
+cmake_minimum_required(VERSION 2.8)
+project(NANOPB_CMAKE_SIMPLE C)
+
+set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../../extra)
+find_package(Nanopb REQUIRED)
+include_directories(${NANOPB_INCLUDE_DIRS})
+
+nanopb_generate_cpp(PROTO_SRCS PROTO_HDRS RELPATH proto
+	proto/simple.proto proto/sub/unlucky.proto)
+
+include_directories(${CMAKE_CURRENT_BINARY_DIR})
+#add_custom_target(generate_proto_sources DEPENDS ${PROTO_SRCS} ${PROTO_HDRS})
+set_source_files_properties(${PROTO_SRCS} ${PROTO_HDRS}
+    PROPERTIES GENERATED TRUE)
+
+set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Werror -g -O0")
+
+add_executable(simple simple.c ${PROTO_SRCS} ${PROTO_HDRS})

+ 18 - 0
components/spotify/cspot/bell/nanopb/examples/cmake_relpath/README.txt

@@ -0,0 +1,18 @@
+Nanopb example "simple" using CMake
+=======================
+
+This example is the same as the simple nanopb example but built using CMake.
+
+Example usage
+-------------
+
+On Linux, create a build directory and then call cmake:
+
+    nanopb/examples/cmake_simple$ mkdir build
+    nanopb/examples/cmake_simple$ cd build/
+    nanopb/examples/cmake_simple/build$ cmake ..
+    nanopb/examples/cmake_simple/build$ make
+
+After that, you can run it with the command: ./simple
+
+On other platforms supported by CMake, refer to CMake instructions.

+ 11 - 0
components/spotify/cspot/bell/nanopb/examples/cmake_relpath/proto/simple.proto

@@ -0,0 +1,11 @@
+// A very simple protocol definition, consisting of only
+// one message.
+syntax = "proto2";
+
+import "sub/unlucky.proto";
+
+message SimpleMessage {
+    required int32 lucky_number = 1;
+    required UnluckyNumber unlucky = 2;
+}
+

+ 5 - 0
components/spotify/cspot/bell/nanopb/examples/cmake_relpath/proto/sub/unlucky.proto

@@ -0,0 +1,5 @@
+syntax = "proto2";
+
+message UnluckyNumber {
+	required uint32 number = 1;
+}

+ 73 - 0
components/spotify/cspot/bell/nanopb/examples/cmake_relpath/simple.c

@@ -0,0 +1,73 @@
+#include <stdio.h>
+#include <pb_encode.h>
+#include <pb_decode.h>
+#include "simple.pb.h"
+
+int main()
+{
+    /* This is the buffer where we will store our message. */
+    uint8_t buffer[128];
+    size_t message_length;
+    bool status;
+    
+    /* Encode our message */
+    {
+        /* Allocate space on the stack to store the message data.
+         *
+         * Nanopb generates simple struct definitions for all the messages.
+         * - check out the contents of simple.pb.h!
+         * It is a good idea to always initialize your structures
+         * so that you do not have garbage data from RAM in there.
+         */
+        SimpleMessage message = SimpleMessage_init_zero;
+        
+        /* Create a stream that will write to our buffer. */
+        pb_ostream_t stream = pb_ostream_from_buffer(buffer, sizeof(buffer));
+        
+        /* Fill in the lucky number */
+        message.lucky_number = 13;
+        message.unlucky.number = 42;
+        
+        /* Now we are ready to encode the message! */
+        status = pb_encode(&stream, SimpleMessage_fields, &message);
+        message_length = stream.bytes_written;
+        
+        /* Then just check for any errors.. */
+        if (!status)
+        {
+            printf("Encoding failed: %s\n", PB_GET_ERROR(&stream));
+            return 1;
+        }
+    }
+    
+    /* Now we could transmit the message over network, store it in a file or
+     * wrap it to a pigeon's leg.
+     */
+
+    /* But because we are lazy, we will just decode it immediately. */
+    
+    {
+        /* Allocate space for the decoded message. */
+        SimpleMessage message = SimpleMessage_init_zero;
+        
+        /* Create a stream that reads from the buffer. */
+        pb_istream_t stream = pb_istream_from_buffer(buffer, message_length);
+        
+        /* Now we are ready to decode the message. */
+        status = pb_decode(&stream, SimpleMessage_fields, &message);
+        
+        /* Check for errors... */
+        if (!status)
+        {
+            printf("Decoding failed: %s\n", PB_GET_ERROR(&stream));
+            return 1;
+        }
+        
+        /* Print the data contained in the message. */
+        printf("Your lucky number was %d!\n", message.lucky_number);
+        printf("Your unlucky number was %u!\n", message.unlucky.number);
+    }
+    
+    return 0;
+}
+

+ 16 - 0
components/spotify/cspot/bell/nanopb/examples/cmake_simple/CMakeLists.txt

@@ -0,0 +1,16 @@
+cmake_minimum_required(VERSION 2.8)
+project(NANOPB_CMAKE_SIMPLE C)
+
+set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../../extra)
+find_package(Nanopb REQUIRED)
+include_directories(${NANOPB_INCLUDE_DIRS})
+
+nanopb_generate_cpp(PROTO_SRCS PROTO_HDRS simple.proto)
+include_directories(${CMAKE_CURRENT_BINARY_DIR})
+#add_custom_target(generate_proto_sources DEPENDS ${PROTO_SRCS} ${PROTO_HDRS})
+set_source_files_properties(${PROTO_SRCS} ${PROTO_HDRS}
+    PROPERTIES GENERATED TRUE)
+
+set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Werror -g -O0")
+
+add_executable(simple simple.c ${PROTO_SRCS} ${PROTO_HDRS})

+ 18 - 0
components/spotify/cspot/bell/nanopb/examples/cmake_simple/README.txt

@@ -0,0 +1,18 @@
+Nanopb example "simple" using CMake
+=======================
+
+This example is the same as the simple nanopb example but built using CMake.
+
+Example usage
+-------------
+
+On Linux, create a build directory and then call cmake:
+
+    nanopb/examples/cmake_simple$ mkdir build
+    nanopb/examples/cmake_simple$ cd build/
+    nanopb/examples/cmake_simple/build$ cmake ..
+    nanopb/examples/cmake_simple/build$ make
+
+After that, you can run it with the command: ./simple
+
+On other platforms supported by CMake, refer to CMake instructions.

+ 71 - 0
components/spotify/cspot/bell/nanopb/examples/cmake_simple/simple.c

@@ -0,0 +1,71 @@
+#include <stdio.h>
+#include <pb_encode.h>
+#include <pb_decode.h>
+#include "simple.pb.h"
+
+int main()
+{
+    /* This is the buffer where we will store our message. */
+    uint8_t buffer[128];
+    size_t message_length;
+    bool status;
+    
+    /* Encode our message */
+    {
+        /* Allocate space on the stack to store the message data.
+         *
+         * Nanopb generates simple struct definitions for all the messages.
+         * - check out the contents of simple.pb.h!
+         * It is a good idea to always initialize your structures
+         * so that you do not have garbage data from RAM in there.
+         */
+        SimpleMessage message = SimpleMessage_init_zero;
+        
+        /* Create a stream that will write to our buffer. */
+        pb_ostream_t stream = pb_ostream_from_buffer(buffer, sizeof(buffer));
+        
+        /* Fill in the lucky number */
+        message.lucky_number = 13;
+        
+        /* Now we are ready to encode the message! */
+        status = pb_encode(&stream, SimpleMessage_fields, &message);
+        message_length = stream.bytes_written;
+        
+        /* Then just check for any errors.. */
+        if (!status)
+        {
+            printf("Encoding failed: %s\n", PB_GET_ERROR(&stream));
+            return 1;
+        }
+    }
+    
+    /* Now we could transmit the message over network, store it in a file or
+     * wrap it to a pigeon's leg.
+     */
+
+    /* But because we are lazy, we will just decode it immediately. */
+    
+    {
+        /* Allocate space for the decoded message. */
+        SimpleMessage message = SimpleMessage_init_zero;
+        
+        /* Create a stream that reads from the buffer. */
+        pb_istream_t stream = pb_istream_from_buffer(buffer, message_length);
+        
+        /* Now we are ready to decode the message. */
+        status = pb_decode(&stream, SimpleMessage_fields, &message);
+        
+        /* Check for errors... */
+        if (!status)
+        {
+            printf("Decoding failed: %s\n", PB_GET_ERROR(&stream));
+            return 1;
+        }
+        
+        /* Print the data contained in the message. */
+        printf("Your lucky number was %d!\n", message.lucky_number);
+    }
+    
+    return 0;
+}
+

+ 9 - 0
components/spotify/cspot/bell/nanopb/examples/cmake_simple/simple.proto

@@ -0,0 +1,9 @@
+// A very simple protocol definition, consisting of only
+// one message.
+
+syntax = "proto2";
+
+message SimpleMessage {
+    required int32 lucky_number = 1;
+}
+

+ 17 - 0
components/spotify/cspot/bell/nanopb/examples/network_server/Makefile

@@ -0,0 +1,17 @@
+# Include the nanopb provided Makefile rules
+include ../../extra/nanopb.mk
+
+# Compiler flags to enable all warnings & debug info
+CFLAGS = -ansi -Wall -Werror -g -O0
+CFLAGS += -I$(NANOPB_DIR)
+
+all: server client
+
+.SUFFIXES:
+
+clean:
+	rm -f server client fileproto.pb.c fileproto.pb.h
+
+%: %.c common.c fileproto.pb.c
+	$(CC) $(CFLAGS) -o $@ $^ $(NANOPB_CORE)
+

+ 60 - 0
components/spotify/cspot/bell/nanopb/examples/network_server/README.txt

@@ -0,0 +1,60 @@
+Nanopb example "network_server"
+===============================
+
+This example demonstrates the use of nanopb to communicate over network
+connections. It consists of a server that sends file listings, and of
+a client that requests the file list from the server.
+
+Example usage
+-------------
+
+user@host:~/nanopb/examples/network_server$ make        # Build the example
+protoc -ofileproto.pb fileproto.proto
+python ../../generator/nanopb_generator.py fileproto.pb
+Writing to fileproto.pb.h and fileproto.pb.c
+cc -ansi -Wall -Werror -I .. -g -O0 -I../.. -o server server.c
+    ../../pb_decode.c ../../pb_encode.c fileproto.pb.c common.c
+cc -ansi -Wall -Werror -I .. -g -O0 -I../.. -o client client.c
+    ../../pb_decode.c ../../pb_encode.c fileproto.pb.c common.c
+
+user@host:~/nanopb/examples/network_server$ ./server &  # Start the server on background
+[1] 24462
+
+petteri@oddish:~/nanopb/examples/network_server$ ./client /bin  # Request the server to list /bin
+Got connection.
+Listing directory: /bin
+1327119    bzdiff
+1327126    bzless
+1327147    ps
+1327178    ntfsmove
+1327271    mv
+1327187    mount
+1327259    false
+1327266    tempfile
+1327285    zfgrep
+1327165    gzexe
+1327204    nc.openbsd
+1327260    uname
+
+
+Details of implementation
+-------------------------
+fileproto.proto contains the portable Google Protocol Buffers protocol definition.
+It could be used as-is to implement a server or a client in any other language, for
+example Python or Java.
+
+fileproto.options contains the nanopb-specific options for the protocol file. This
+sets the amount of space allocated for file names when decoding messages.
+
+common.c/h contains functions that allow nanopb to read and write directly from
+network socket. This way there is no need to allocate a separate buffer to store
+the message.
+
+server.c contains the code to open a listening socket, to respond to clients and
+to list directory contents.
+
+client.c contains the code to connect to a server, to send a request and to print
+the response message.
+
+The code is implemented using the POSIX socket api, but it should be easy enough
+to port into any other socket api, such as lwip.

+ 138 - 0
components/spotify/cspot/bell/nanopb/examples/network_server/client.c

@@ -0,0 +1,138 @@
+/* This is a simple TCP client that connects to port 1234 and prints a list
+ * of files in a given directory.
+ *
+ * It directly deserializes and serializes messages from network, minimizing
+ * memory use.
+ * 
+ * For flexibility, this example is implemented using posix api.
+ * In a real embedded system you would typically use some other kind of
+ * a communication and filesystem layer.
+ */
+
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <pb_encode.h>
+#include <pb_decode.h>
+
+#include "fileproto.pb.h"
+#include "common.h"
+
+/* This callback function will be called once for each filename received
+ * from the server. The filenames will be printed out immediately, so that
+ * no memory has to be allocated for them.
+ */
+bool ListFilesResponse_callback(pb_istream_t *istream, pb_ostream_t *ostream, const pb_field_iter_t *field)
+{
+    PB_UNUSED(ostream);
+    if (istream != NULL && field->tag == ListFilesResponse_file_tag)
+    {
+        FileInfo fileinfo = {};
+
+        if (!pb_decode(istream, FileInfo_fields, &fileinfo))
+            return false;
+
+        printf("%-10lld %s\n", (long long)fileinfo.inode, fileinfo.name);
+    }
+    
+    return true;
+}
+
+/* This function sends a request to socket 'fd' to list the files in
+ * directory given in 'path'. The results received from server will
+ * be printed to stdout.
+ */
+bool listdir(int fd, char *path)
+{
+    /* Construct and send the request to server */
+    {
+        ListFilesRequest request = {};
+        pb_ostream_t output = pb_ostream_from_socket(fd);
+        
+        /* In our protocol, path is optional. If it is not given,
+         * the server will list the root directory. */
+        if (path == NULL)
+        {
+            request.has_path = false;
+        }
+        else
+        {
+            request.has_path = true;
+            if (strlen(path) + 1 > sizeof(request.path))
+            {
+                fprintf(stderr, "Too long path.\n");
+                return false;
+            }
+            
+            strcpy(request.path, path);
+        }
+        
+        /* Encode the request. It is written to the socket immediately
+         * through our custom stream. */
+        if (!pb_encode_delimited(&output, ListFilesRequest_fields, &request))
+        {
+            fprintf(stderr, "Encoding failed: %s\n", PB_GET_ERROR(&output));
+            return false;
+        }
+    }
+    
+    /* Read back the response from server */
+    {
+        ListFilesResponse response = {};
+        pb_istream_t input = pb_istream_from_socket(fd);
+        
+        if (!pb_decode_delimited(&input, ListFilesResponse_fields, &response))
+        {
+            fprintf(stderr, "Decode failed: %s\n", PB_GET_ERROR(&input));
+            return false;
+        }
+        
+        /* If the message from server decodes properly, but directory was
+         * not found on server side, we get path_error == true. */
+        if (response.path_error)
+        {
+            fprintf(stderr, "Server reported error.\n");
+            return false;
+        }
+    }
+    
+    return true;
+}
+
+int main(int argc, char **argv)
+{
+    int sockfd;
+    struct sockaddr_in servaddr;
+    char *path = NULL;
+    
+    if (argc > 1)
+        path = argv[1];
+    
+    sockfd = socket(AF_INET, SOCK_STREAM, 0);
+    
+    /* Connect to server running on localhost:1234 */
+    memset(&servaddr, 0, sizeof(servaddr));
+    servaddr.sin_family = AF_INET;
+    servaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+    servaddr.sin_port = htons(1234);
+    
+    if (connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) != 0)
+    {
+        perror("connect");
+        return 1;
+    }
+    
+    /* Send the directory listing request */
+    if (!listdir(sockfd, path))
+        return 2;
+    
+    /* Close connection */
+    close(sockfd);
+    
+    return 0;
+}

+ 43 - 0
components/spotify/cspot/bell/nanopb/examples/network_server/common.c

@@ -0,0 +1,43 @@
+/* Simple binding of nanopb streams to TCP sockets.
+ */
+
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <pb_encode.h>
+#include <pb_decode.h>
+
+#include "common.h"
+
+static bool write_callback(pb_ostream_t *stream, const uint8_t *buf, size_t count)
+{
+    int fd = (intptr_t)stream->state;
+    return send(fd, buf, count, 0) == count;
+}
+
+static bool read_callback(pb_istream_t *stream, uint8_t *buf, size_t count)
+{
+    int fd = (intptr_t)stream->state;
+    int result;
+    
+    if (count == 0)
+        return true;
+
+    result = recv(fd, buf, count, MSG_WAITALL);
+    
+    if (result == 0)
+        stream->bytes_left = 0; /* EOF */
+    
+    return result == count;
+}
+
+pb_ostream_t pb_ostream_from_socket(int fd)
+{
+    pb_ostream_t stream = {&write_callback, (void*)(intptr_t)fd, SIZE_MAX, 0};
+    return stream;
+}
+
+pb_istream_t pb_istream_from_socket(int fd)
+{
+    pb_istream_t stream = {&read_callback, (void*)(intptr_t)fd, SIZE_MAX};
+    return stream;
+}

+ 9 - 0
components/spotify/cspot/bell/nanopb/examples/network_server/common.h

@@ -0,0 +1,9 @@
+#ifndef _PB_EXAMPLE_COMMON_H_
+#define _PB_EXAMPLE_COMMON_H_
+
+#include <pb.h>
+
+pb_ostream_t pb_ostream_from_socket(int fd);
+pb_istream_t pb_istream_from_socket(int fd);
+
+#endif

+ 16 - 0
components/spotify/cspot/bell/nanopb/examples/network_server/fileproto.options

@@ -0,0 +1,16 @@
+# This file defines the nanopb-specific options for the messages defined
+# in fileproto.proto.
+#
+# If you come from high-level programming background, the hardcoded
+# maximum lengths may disgust you. However, if your microcontroller only
+# has a few kB of ram to begin with, setting reasonable limits for
+# filenames is ok.
+#
+# On the other hand, using the callback interface, it is not necessary
+# to set a limit on the number of files in the response.
+
+* include:"sys/types.h"
+* include:"dirent.h"
+ListFilesResponse.file  type:FT_CALLBACK, callback_datatype:"DIR*"
+ListFilesRequest.path 	max_size:128
+FileInfo.name 		max_size:128

+ 20 - 0
components/spotify/cspot/bell/nanopb/examples/network_server/fileproto.proto

@@ -0,0 +1,20 @@
+// This defines protocol for a simple server that lists files.
+//
+// See also the nanopb-specific options in fileproto.options.
+
+syntax = "proto2";
+
+message ListFilesRequest {
+    optional string path = 1 [default = "/"];
+}
+
+message FileInfo {
+    required uint64 inode = 1;
+    required string name = 2;
+}
+
+message ListFilesResponse {
+    optional bool path_error = 1 [default = false];
+    repeated FileInfo file = 2;
+}
+

+ 164 - 0
components/spotify/cspot/bell/nanopb/examples/network_server/server.c

@@ -0,0 +1,164 @@
+/* This is a simple TCP server that listens on port 1234 and provides lists
+ * of files to clients, using a protocol defined in file_server.proto.
+ *
+ * It directly deserializes and serializes messages from network, minimizing
+ * memory use.
+ * 
+ * For flexibility, this example is implemented using posix api.
+ * In a real embedded system you would typically use some other kind of
+ * a communication and filesystem layer.
+ */
+
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <pb_encode.h>
+#include <pb_decode.h>
+
+#include "fileproto.pb.h"
+#include "common.h"
+
+/* This callback function will be called during the encoding.
+ * It will write out any number of FileInfo entries, without consuming unnecessary memory.
+ * This is accomplished by fetching the filenames one at a time and encoding them
+ * immediately.
+ */
+bool ListFilesResponse_callback(pb_istream_t *istream, pb_ostream_t *ostream, const pb_field_iter_t *field)
+{
+    PB_UNUSED(istream);
+    if (ostream != NULL && field->tag == ListFilesResponse_file_tag)
+    {
+        DIR *dir = *(DIR**)field->pData;
+        struct dirent *file;
+        FileInfo fileinfo = {};
+
+        while ((file = readdir(dir)) != NULL)
+        {
+            fileinfo.inode = file->d_ino;
+            strncpy(fileinfo.name, file->d_name, sizeof(fileinfo.name));
+            fileinfo.name[sizeof(fileinfo.name) - 1] = '\0';
+
+            /* This encodes the header for the field, based on the constant info
+            * from pb_field_t. */
+            if (!pb_encode_tag_for_field(ostream, field))
+                return false;
+
+            /* This encodes the data for the field, based on our FileInfo structure. */
+            if (!pb_encode_submessage(ostream, FileInfo_fields, &fileinfo))
+                return false;
+        }
+
+        /* Because the main program uses pb_encode_delimited(), this callback will be
+        * called twice. Rewind the directory for the next call. */
+        rewinddir(dir);
+    }
+
+    return true;
+}
+
+/* Handle one arriving client connection.
+ * Clients are expected to send a ListFilesRequest, terminated by a '0'.
+ * Server will respond with a ListFilesResponse message.
+ */
+void handle_connection(int connfd)
+{
+    DIR *directory = NULL;
+    
+    /* Decode the message from the client and open the requested directory. */
+    {
+        ListFilesRequest request = {};
+        pb_istream_t input = pb_istream_from_socket(connfd);
+        
+        if (!pb_decode_delimited(&input, ListFilesRequest_fields, &request))
+        {
+            printf("Decode failed: %s\n", PB_GET_ERROR(&input));
+            return;
+        }
+        
+        directory = opendir(request.path);
+        printf("Listing directory: %s\n", request.path);
+    }
+    
+    /* List the files in the directory and transmit the response to client */
+    {
+        ListFilesResponse response = {};
+        pb_ostream_t output = pb_ostream_from_socket(connfd);
+        
+        if (directory == NULL)
+        {
+            perror("opendir");
+            
+            /* Directory was not found, transmit error status */
+            response.has_path_error = true;
+            response.path_error = true;
+        }
+        else
+        {
+            /* Directory was found, transmit filenames */
+            response.has_path_error = false;
+            response.file = directory;
+        }
+        
+        if (!pb_encode_delimited(&output, ListFilesResponse_fields, &response))
+        {
+            printf("Encoding failed: %s\n", PB_GET_ERROR(&output));
+        }
+    }
+    
+    if (directory != NULL)
+        closedir(directory);
+}
+
+int main(int argc, char **argv)
+{
+    int listenfd, connfd;
+    struct sockaddr_in servaddr;
+    int reuse = 1;
+    
+    /* Listen on localhost:1234 for TCP connections */
+    listenfd = socket(AF_INET, SOCK_STREAM, 0);
+    setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse));
+    
+    memset(&servaddr, 0, sizeof(servaddr));
+    servaddr.sin_family = AF_INET;
+    servaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+    servaddr.sin_port = htons(1234);
+    if (bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) != 0)
+    {
+        perror("bind");
+        return 1;
+    }
+    
+    if (listen(listenfd, 5) != 0)
+    {
+        perror("listen");
+        return 1;
+    }
+    
+    for(;;)
+    {
+        /* Wait for a client */
+        connfd = accept(listenfd, NULL, NULL);
+        
+        if (connfd < 0)
+        {
+            perror("accept");
+            return 1;
+        }
+        
+        printf("Got connection.\n");
+        
+        handle_connection(connfd);
+        
+        printf("Closing connection.\n");
+        
+        close(connfd);
+    }
+    
+    return 0;
+}

+ 5 - 0
components/spotify/cspot/bell/nanopb/examples/platformio/.gitignore

@@ -0,0 +1,5 @@
+.pio/
+.idea/
+cmake-build-*/
+CMakeLists.txt
+CMakeListsPrivate.txt

+ 35 - 0
components/spotify/cspot/bell/nanopb/examples/platformio/platformio.ini

@@ -0,0 +1,35 @@
+;
+; You can setup `custom_nanopb_protos` `nanopb_options` vars to generate code from proto files
+;
+; Generator will use next folders:
+;
+;   `$BUILD_DIR/nanopb/generated-src` - `*.pb.h` and `*.pb.c` files
+;   `$BUILD_DIR/nanopb/md5` - MD5 files to track changes in source .proto/.options
+;
+; Compiled `.pb.o` files will be located under `$BUILD_DIR/nanopb/generated-build`
+;
+; Example:
+
+[env:pio_with_options]
+platform = native
+lib_deps = Nanopb
+
+src_filter =
+    +<pio_with_options.c>
+
+; All path are relative to the `$PROJECT_DIR`
+custom_nanopb_protos =
+    +<proto/pio_with_options.proto>
+custom_nanopb_options =
+    --error-on-unmatched
+
+[env:pio_without_options]
+platform = native
+lib_deps = Nanopb
+
+src_filter =
+    +<pio_without_options.c>
+
+; All path are relative to the `$PROJECT_DIR`
+custom_nanopb_protos =
+    +<proto/pio_without_options.proto>

+ 1 - 0
components/spotify/cspot/bell/nanopb/examples/platformio/proto/pio_with_options.options

@@ -0,0 +1 @@
+TestMessageWithOptions.str max_size:16

+ 5 - 0
components/spotify/cspot/bell/nanopb/examples/platformio/proto/pio_with_options.proto

@@ -0,0 +1,5 @@
+syntax = "proto3";
+
+message TestMessageWithOptions {
+  string str = 1;
+}

+ 5 - 0
components/spotify/cspot/bell/nanopb/examples/platformio/proto/pio_without_options.proto

@@ -0,0 +1,5 @@
+syntax = "proto3";
+
+message TestMessageWithoutOptions {
+  int32 number = 1;
+}

+ 35 - 0
components/spotify/cspot/bell/nanopb/examples/platformio/src/pio_with_options.c

@@ -0,0 +1,35 @@
+#include "pb_encode.h"
+#include "pb_decode.h"
+
+#include "test.h"
+
+#include "pio_with_options.pb.h"
+
+int main(int argc, char *argv[]) {
+
+    int status = 0;
+
+    uint8_t buffer[256];
+    pb_ostream_t ostream;
+    pb_istream_t istream;
+    size_t written;
+
+    TestMessageWithOptions original = TestMessageWithOptions_init_zero;
+    strcpy(original.str,"Hello");
+
+    ostream = pb_ostream_from_buffer(buffer, sizeof(buffer));
+
+    TEST(pb_encode(&ostream, &TestMessageWithOptions_msg, &original));
+
+    written = ostream.bytes_written;
+
+    istream = pb_istream_from_buffer(buffer, written);
+
+    TestMessageWithOptions decoded = TestMessageWithOptions_init_zero;
+
+    TEST(pb_decode(&istream, &TestMessageWithOptions_msg, &decoded));
+
+    TEST(strcmp(decoded.str,"Hello") == 0);
+
+    return status;
+}

+ 35 - 0
components/spotify/cspot/bell/nanopb/examples/platformio/src/pio_without_options.c

@@ -0,0 +1,35 @@
+#include "pb_encode.h"
+#include "pb_decode.h"
+
+#include "test.h"
+
+#include "pio_without_options.pb.h"
+
+int main(int argc, char *argv[]) {
+
+    int status = 0;
+
+    uint8_t buffer[256];
+    pb_ostream_t ostream;
+    pb_istream_t istream;
+    size_t written;
+
+    TestMessageWithoutOptions original = TestMessageWithoutOptions_init_zero;
+    original.number = 45;
+
+    ostream = pb_ostream_from_buffer(buffer, sizeof(buffer));
+
+    TEST(pb_encode(&ostream, &TestMessageWithoutOptions_msg, &original));
+
+    written = ostream.bytes_written;
+
+    istream = pb_istream_from_buffer(buffer, written);
+
+    TestMessageWithoutOptions decoded = TestMessageWithoutOptions_init_zero;
+
+    TEST(pb_decode(&istream, &TestMessageWithoutOptions_msg, &decoded));
+
+    TEST(decoded.number == 45);
+
+    return status;
+}

+ 9 - 0
components/spotify/cspot/bell/nanopb/examples/platformio/src/test.h

@@ -0,0 +1,9 @@
+#include <stdio.h>
+
+#define TEST(x) \
+    if (!(x)) { \
+        fprintf(stderr, "\033[31;1mFAILED:\033[22;39m %s:%d %s\n", __FILE__, __LINE__, #x); \
+        status = 1; \
+    } else { \
+        printf("\033[32;1mOK:\033[22;39m %s\n", #x); \
+    }

+ 22 - 0
components/spotify/cspot/bell/nanopb/examples/simple/Makefile

@@ -0,0 +1,22 @@
+# Include the nanopb provided Makefile rules
+include ../../extra/nanopb.mk
+
+# Compiler flags to enable all warnings & debug info
+CFLAGS = -Wall -Werror -g -O0
+CFLAGS += "-I$(NANOPB_DIR)"
+
+# C source code files that are required
+CSRC  = simple.c                   # The main program
+CSRC += simple.pb.c                # The compiled protocol definition
+CSRC += $(NANOPB_DIR)/pb_encode.c  # The nanopb encoder
+CSRC += $(NANOPB_DIR)/pb_decode.c  # The nanopb decoder
+CSRC += $(NANOPB_DIR)/pb_common.c  # The nanopb common parts
+
+# Build rule for the main program
+simple: $(CSRC)
+	$(CC) $(CFLAGS) -osimple $(CSRC)
+
+# Build rule for the protocol
+simple.pb.c: simple.proto
+	$(PROTOC) $(PROTOC_OPTS) --nanopb_out=. simple.proto
+

+ 29 - 0
components/spotify/cspot/bell/nanopb/examples/simple/README.txt

@@ -0,0 +1,29 @@
+Nanopb example "simple"
+=======================
+
+This example demonstrates the very basic use of nanopb. It encodes and
+decodes a simple message.
+
+The code uses four different API functions:
+
+  * pb_ostream_from_buffer() to declare the output buffer that is to be used
+  * pb_encode() to encode a message
+  * pb_istream_from_buffer() to declare the input buffer that is to be used
+  * pb_decode() to decode a message
+
+Example usage
+-------------
+
+On Linux, simply type "make" to build the example. After that, you can
+run it with the command: ./simple
+
+On other platforms, you first have to compile the protocol definition using
+the following command::
+
+  ../../generator-bin/protoc --nanopb_out=. simple.proto
+
+After that, add the following five files to your project and compile:
+
+  simple.c  simple.pb.c  pb_encode.c  pb_decode.c  pb_common.c
+
+

+ 71 - 0
components/spotify/cspot/bell/nanopb/examples/simple/simple.c

@@ -0,0 +1,71 @@
+#include <stdio.h>
+#include <pb_encode.h>
+#include <pb_decode.h>
+#include "simple.pb.h"
+
+int main()
+{
+    /* This is the buffer where we will store our message. */
+    uint8_t buffer[128];
+    size_t message_length;
+    bool status;
+    
+    /* Encode our message */
+    {
+        /* Allocate space on the stack to store the message data.
+         *
+         * Nanopb generates simple struct definitions for all the messages.
+         * - check out the contents of simple.pb.h!
+         * It is a good idea to always initialize your structures
+         * so that you do not have garbage data from RAM in there.
+         */
+        SimpleMessage message = SimpleMessage_init_zero;
+        
+        /* Create a stream that will write to our buffer. */
+        pb_ostream_t stream = pb_ostream_from_buffer(buffer, sizeof(buffer));
+        
+        /* Fill in the lucky number */
+        message.lucky_number = 13;
+        
+        /* Now we are ready to encode the message! */
+        status = pb_encode(&stream, SimpleMessage_fields, &message);
+        message_length = stream.bytes_written;
+        
+        /* Then just check for any errors.. */
+        if (!status)
+        {
+            printf("Encoding failed: %s\n", PB_GET_ERROR(&stream));
+            return 1;
+        }
+    }
+    
+    /* Now we could transmit the message over network, store it in a file or
+     * wrap it to a pigeon's leg.
+     */
+
+    /* But because we are lazy, we will just decode it immediately. */
+    
+    {
+        /* Allocate space for the decoded message. */
+        SimpleMessage message = SimpleMessage_init_zero;
+        
+        /* Create a stream that reads from the buffer. */
+        pb_istream_t stream = pb_istream_from_buffer(buffer, message_length);
+        
+        /* Now we are ready to decode the message. */
+        status = pb_decode(&stream, SimpleMessage_fields, &message);
+        
+        /* Check for errors... */
+        if (!status)
+        {
+            printf("Decoding failed: %s\n", PB_GET_ERROR(&stream));
+            return 1;
+        }
+        
+        /* Print the data contained in the message. */
+        printf("Your lucky number was %d!\n", (int)message.lucky_number);
+    }
+    
+    return 0;
+}
+

+ 9 - 0
components/spotify/cspot/bell/nanopb/examples/simple/simple.proto

@@ -0,0 +1,9 @@
+// A very simple protocol definition, consisting of only
+// one message.
+
+syntax = "proto2";
+
+message SimpleMessage {
+    required int32 lucky_number = 1;
+}
+

+ 20 - 0
components/spotify/cspot/bell/nanopb/examples/using_union_messages/Makefile

@@ -0,0 +1,20 @@
+# Include the nanopb provided Makefile rules
+include ../../extra/nanopb.mk
+
+# Compiler flags to enable all warnings & debug info
+CFLAGS = -ansi -Wall -Werror -g -O0
+CFLAGS += -I$(NANOPB_DIR)
+
+all: encode decode
+	./encode 1 | ./decode
+	./encode 2 | ./decode
+	./encode 3 | ./decode
+
+.SUFFIXES:
+
+clean:
+	rm -f encode unionproto.pb.h unionproto.pb.c
+
+%: %.c unionproto.pb.c
+	$(CC) $(CFLAGS) -o $@ $^ $(NANOPB_CORE)
+

+ 55 - 0
components/spotify/cspot/bell/nanopb/examples/using_union_messages/README.txt

@@ -0,0 +1,55 @@
+Nanopb example "using_union_messages"
+=====================================
+
+Union messages is a common technique in Google Protocol Buffers used to
+represent a group of messages, only one of which is passed at a time.
+It is described in Google's documentation:
+https://developers.google.com/protocol-buffers/docs/techniques#union
+
+This directory contains an example on how to encode and decode union messages
+with minimal memory usage. Usually, nanopb would allocate space to store
+all of the possible messages at the same time, even though at most one of
+them will be used at a time.
+
+By using some of the lower level nanopb APIs, we can manually generate the
+top level message, so that we only need to allocate the one submessage that
+we actually want. Similarly when decoding, we can manually read the tag of
+the top level message, and only then allocate the memory for the submessage
+after we already know its type.
+
+NOTE: There is a newer protobuf feature called `oneof` that is also supported
+by nanopb. It might be a better option for new code.
+
+
+Example usage
+-------------
+
+Type `make` to run the example. It will build it and run commands like
+following:
+
+./encode 1 | ./decode
+Got MsgType1: 42
+./encode 2 | ./decode
+Got MsgType2: true
+./encode 3 | ./decode
+Got MsgType3: 3 1415
+
+This simply demonstrates that the "decode" program has correctly identified
+the type of the received message, and managed to decode it.
+
+
+Details of implementation
+-------------------------
+
+unionproto.proto contains the protocol used in the example. It consists of
+three messages: MsgType1, MsgType2 and MsgType3, which are collected together
+into UnionMessage.
+
+encode.c takes one command line argument, which should be a number 1-3. It
+then fills in and encodes the corresponding message, and writes it to stdout.
+
+decode.c reads a UnionMessage from stdin. Then it calls the function
+decode_unionmessage_type() to determine the type of the message. After that,
+the corresponding message is decoded and the contents of it printed to the
+screen.
+

+ 95 - 0
components/spotify/cspot/bell/nanopb/examples/using_union_messages/decode.c

@@ -0,0 +1,95 @@
+/* This program reads a message from stdin, detects its type and decodes it.
+ */
+ 
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <pb_decode.h>
+#include <pb_common.h>
+#include "unionproto.pb.h"
+
+/* This function reads manually the first tag from the stream and finds the
+ * corresponding message type. It doesn't yet decode the actual message.
+ *
+ * Returns a pointer to the MsgType_fields array, as an identifier for the
+ * message type. Returns null if the tag is of unknown type or an error occurs.
+ */
+const pb_msgdesc_t* decode_unionmessage_type(pb_istream_t *stream)
+{
+    pb_wire_type_t wire_type;
+    uint32_t tag;
+    bool eof;
+
+    while (pb_decode_tag(stream, &wire_type, &tag, &eof))
+    {
+        if (wire_type == PB_WT_STRING)
+        {
+            pb_field_iter_t iter;
+            if (pb_field_iter_begin(&iter, UnionMessage_fields, NULL) &&
+                pb_field_iter_find(&iter, tag))
+            {
+                /* Found our field. */
+                return iter.submsg_desc;
+            }
+        }
+        
+        /* Wasn't our field.. */
+        pb_skip_field(stream, wire_type);
+    }
+    
+    return NULL;
+}
+
+bool decode_unionmessage_contents(pb_istream_t *stream, const pb_msgdesc_t *messagetype, void *dest_struct)
+{
+    pb_istream_t substream;
+    bool status;
+    if (!pb_make_string_substream(stream, &substream))
+        return false;
+    
+    status = pb_decode(&substream, messagetype, dest_struct);
+    pb_close_string_substream(stream, &substream);
+    return status;
+}
+
+int main()
+{
+    /* Read the data into buffer */
+    uint8_t buffer[512];
+    size_t count = fread(buffer, 1, sizeof(buffer), stdin);
+    pb_istream_t stream = pb_istream_from_buffer(buffer, count);
+    
+    const pb_msgdesc_t *type = decode_unionmessage_type(&stream);
+    bool status = false;
+    
+    if (type == MsgType1_fields)
+    {
+        MsgType1 msg = {};
+        status = decode_unionmessage_contents(&stream, MsgType1_fields, &msg);
+        printf("Got MsgType1: %d\n", msg.value);
+    }
+    else if (type == MsgType2_fields)
+    {
+        MsgType2 msg = {};
+        status = decode_unionmessage_contents(&stream, MsgType2_fields, &msg);
+        printf("Got MsgType2: %s\n", msg.value ? "true" : "false");
+    }
+    else if (type == MsgType3_fields)
+    {
+        MsgType3 msg = {};
+        status = decode_unionmessage_contents(&stream, MsgType3_fields, &msg);
+        printf("Got MsgType3: %d %d\n", msg.value1, msg.value2);    
+    }
+    
+    if (!status)
+    {
+        printf("Decode failed: %s\n", PB_GET_ERROR(&stream));
+        return 1;
+    }
+    
+    return 0;
+}
+
+
+

+ 90 - 0
components/spotify/cspot/bell/nanopb/examples/using_union_messages/encode.c

@@ -0,0 +1,90 @@
+/* This program takes a command line argument and encodes a message in
+ * one of MsgType1, MsgType2 or MsgType3.
+ */
+ 
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <pb_encode.h>
+#include <pb_common.h>
+#include "unionproto.pb.h"
+
+/* This function is the core of the union encoding process. It handles
+ * the top-level pb_field_t array manually, in order to encode a correct
+ * field tag before the message. The pointer to MsgType_fields array is
+ * used as an unique identifier for the message type.
+ */
+bool encode_unionmessage(pb_ostream_t *stream, const pb_msgdesc_t *messagetype, void *message)
+{
+    pb_field_iter_t iter;
+
+    if (!pb_field_iter_begin(&iter, UnionMessage_fields, message))
+        return false;
+
+    do
+    {
+        if (iter.submsg_desc == messagetype)
+        {
+            /* This is our field, encode the message using it. */
+            if (!pb_encode_tag_for_field(stream, &iter))
+                return false;
+            
+            return pb_encode_submessage(stream, messagetype, message);
+        }
+    } while (pb_field_iter_next(&iter));
+    
+    /* Didn't find the field for messagetype */
+    return false;
+}
+
+int main(int argc, char **argv)
+{
+    if (argc != 2)
+    {
+        fprintf(stderr, "Usage: %s (1|2|3)\n", argv[0]);
+        return 1;
+    }
+    
+    uint8_t buffer[512];
+    pb_ostream_t stream = pb_ostream_from_buffer(buffer, sizeof(buffer));
+    
+    bool status = false;
+    int msgtype = atoi(argv[1]);
+    if (msgtype == 1)
+    {
+        /* Send message of type 1 */
+        MsgType1 msg = {42};
+        status = encode_unionmessage(&stream, MsgType1_fields, &msg);
+    }
+    else if (msgtype == 2)
+    {
+        /* Send message of type 2 */
+        MsgType2 msg = {true};
+        status = encode_unionmessage(&stream, MsgType2_fields, &msg);
+    }
+    else if (msgtype == 3)
+    {
+        /* Send message of type 3 */
+        MsgType3 msg = {3, 1415};
+        status = encode_unionmessage(&stream, MsgType3_fields, &msg);
+    }
+    else
+    {
+        fprintf(stderr, "Unknown message type: %d\n", msgtype);
+        return 2;
+    }
+    
+    if (!status)
+    {
+        fprintf(stderr, "Encoding failed!\n");
+        return 3;
+    }
+    else
+    {
+        fwrite(buffer, 1, stream.bytes_written, stdout);
+        return 0; /* Success */
+    }
+}
+
+

+ 32 - 0
components/spotify/cspot/bell/nanopb/examples/using_union_messages/unionproto.proto

@@ -0,0 +1,32 @@
+// This is an example of how to handle 'union' style messages
+// with nanopb, without allocating memory for all the message types.
+//
+// There is no official type in Protocol Buffers for describing unions,
+// but they are commonly implemented by filling out exactly one of
+// several optional fields.
+
+syntax = "proto2";
+
+message MsgType1
+{
+    required int32 value = 1;
+}
+
+message MsgType2
+{
+    required bool value = 1;
+}
+
+message MsgType3
+{
+    required int32 value1 = 1;
+    required int32 value2 = 2;
+}
+
+message UnionMessage
+{
+    optional MsgType1 msg1 = 1;
+    optional MsgType2 msg2 = 2;
+    optional MsgType3 msg3 = 3;
+}
+

+ 371 - 0
components/spotify/cspot/bell/nanopb/extra/FindNanopb.cmake

@@ -0,0 +1,371 @@
+# This is an example script for use with CMake projects for locating and configuring
+# the nanopb library.
+#
+# The following variables can be set and are optional:
+#
+#
+#   PROTOBUF_SRC_ROOT_FOLDER - When compiling with MSVC, if this cache variable is set
+#                              the protobuf-default VS project build locations
+#                              (vsprojects/Debug & vsprojects/Release) will be searched
+#                              for libraries and binaries.
+#
+#   NANOPB_IMPORT_DIRS       - List of additional directories to be searched for
+#                              imported .proto files.
+#
+#   NANOPB_OPTIONS           - List of options passed to nanopb.
+#
+#   NANOPB_DEPENDS           - List of files to be used as dependencies
+#                              for the generated source and header files. These
+#                              files are not directly passed as options to
+#                              nanopb but rather their directories.
+#
+#   NANOPB_GENERATE_CPP_APPEND_PATH - By default -I will be passed to protoc
+#                                     for each directory where a proto file is referenced.
+#                                     This causes all output files to go directly
+#                                     under build directory, instead of mirroring
+#                                     relative paths of source directories.
+#                                     Set to FALSE if you want to disable this behaviour.
+#
+# Defines the following variables:
+#
+#   NANOPB_FOUND - Found the nanopb library (source&header files, generator tool, protoc compiler tool)
+#   NANOPB_INCLUDE_DIRS - Include directories for Google Protocol Buffers
+#
+# The following cache variables are also available to set or use:
+#   PROTOBUF_PROTOC_EXECUTABLE - The protoc compiler
+#   NANOPB_GENERATOR_SOURCE_DIR - The nanopb generator source
+#
+#  ====================================================================
+#
+# NANOPB_GENERATE_CPP (public function)
+# NANOPB_GENERATE_CPP(SRCS HDRS [RELPATH <root-path-of-proto-files>]
+#                     <proto-files>...)
+#   SRCS = Variable to define with autogenerated source files
+#   HDRS = Variable to define with autogenerated header files
+#   If you want to use relative paths in your import statements use the RELPATH
+#   option. The argument to RELPATH should be the directory that all the
+#   imports will be relative to.
+#   When RELPATH is not specified then all proto files can be imported without
+#   a path.
+#
+#
+#  ====================================================================
+#  Example:
+#
+#   set(NANOPB_SRC_ROOT_FOLDER "/path/to/nanopb")
+#   set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${NANOPB_SRC_ROOT_FOLDER}/extra)
+#   find_package( Nanopb REQUIRED )
+#   include_directories(${NANOPB_INCLUDE_DIRS})
+#
+#   NANOPB_GENERATE_CPP(PROTO_SRCS PROTO_HDRS foo.proto)
+#
+#   include_directories(${CMAKE_CURRENT_BINARY_DIR})
+#   add_executable(bar bar.cc ${PROTO_SRCS} ${PROTO_HDRS})
+#
+#  Example with RELPATH:
+#   Assume we have a layout like:
+#    .../CMakeLists.txt
+#    .../bar.cc
+#    .../proto/
+#    .../proto/foo.proto  (Which contains: import "sub/bar.proto"; )
+#    .../proto/sub/bar.proto
+#   Everything would be the same as the previous example, but the call to
+#   NANOPB_GENERATE_CPP would change to:
+#
+#   NANOPB_GENERATE_CPP(PROTO_SRCS PROTO_HDRS RELPATH proto
+#                       proto/foo.proto proto/sub/bar.proto)
+#
+#  ====================================================================
+
+#=============================================================================
+# Copyright 2009 Kitware, Inc.
+# Copyright 2009-2011 Philip Lowman <philip@yhbt.com>
+# Copyright 2008 Esben Mose Hansen, Ange Optimization ApS
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+#   notice, this list of conditions and the following disclaimer.
+#
+# * Redistributions in binary form must reproduce the above copyright
+#   notice, this list of conditions and the following disclaimer in the
+#   documentation and/or other materials provided with the distribution.
+#
+# * Neither the names of Kitware, Inc., the Insight Software Consortium,
+#   nor the names of their contributors may be used to endorse or promote
+#   products derived from this software without specific prior written
+#   permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#=============================================================================
+#
+# Changes
+# 2013.01.31 - Pavlo Ilin - used Modules/FindProtobuf.cmake from cmake 2.8.10 to
+#                           write FindNanopb.cmake
+#
+#=============================================================================
+
+
+function(NANOPB_GENERATE_CPP SRCS HDRS)
+  cmake_parse_arguments(NANOPB_GENERATE_CPP "" "RELPATH" "" ${ARGN})
+  if(NOT NANOPB_GENERATE_CPP_UNPARSED_ARGUMENTS)
+    return()
+  endif()
+
+  if(NANOPB_GENERATE_CPP_APPEND_PATH)
+    # Create an include path for each file specified
+    foreach(FIL ${NANOPB_GENERATE_CPP_UNPARSED_ARGUMENTS})
+      get_filename_component(ABS_FIL ${FIL} ABSOLUTE)
+      get_filename_component(ABS_PATH ${ABS_FIL} PATH)
+      list(APPEND _nanopb_include_path "-I${ABS_PATH}")
+    endforeach()
+  else()
+    set(_nanopb_include_path "-I${CMAKE_CURRENT_SOURCE_DIR}")
+  endif()
+
+  if(NANOPB_GENERATE_CPP_RELPATH)
+    list(APPEND _nanopb_include_path "-I${NANOPB_GENERATE_CPP_RELPATH}")
+  endif()
+
+  if(DEFINED NANOPB_IMPORT_DIRS)
+    foreach(DIR ${NANOPB_IMPORT_DIRS})
+      get_filename_component(ABS_PATH ${DIR} ABSOLUTE)
+      list(APPEND _nanopb_include_path "-I${ABS_PATH}")
+    endforeach()
+  endif()
+
+  list(REMOVE_DUPLICATES _nanopb_include_path)
+
+  set(GENERATOR_PATH ${CMAKE_CURRENT_BINARY_DIR}/nanopb/generator)
+
+  set(NANOPB_GENERATOR_EXECUTABLE ${GENERATOR_PATH}/nanopb_generator.py)
+  if (CMAKE_HOST_WIN32)
+    set(NANOPB_GENERATOR_PLUGIN ${GENERATOR_PATH}/protoc-gen-nanopb.bat)
+  else()
+    set(NANOPB_GENERATOR_PLUGIN ${GENERATOR_PATH}/protoc-gen-nanopb)
+  endif()
+
+  set(GENERATOR_CORE_DIR ${GENERATOR_PATH}/proto)
+  set(GENERATOR_CORE_SRC
+      ${GENERATOR_CORE_DIR}/nanopb.proto)
+
+  # Treat the source directory as immutable.
+  #
+  # Copy the generator directory to the build directory before
+  # compiling python and proto files.  Fixes issues when using the
+  # same build directory with different python/protobuf versions
+  # as the binary build directory is discarded across builds.
+  #
+  add_custom_command(
+      OUTPUT ${NANOPB_GENERATOR_EXECUTABLE} ${GENERATOR_CORE_SRC}
+      COMMAND ${CMAKE_COMMAND} -E copy_directory
+      ARGS ${NANOPB_GENERATOR_SOURCE_DIR} ${GENERATOR_PATH}
+      VERBATIM)
+
+  set(GENERATOR_CORE_PYTHON_SRC)
+  foreach(FIL ${GENERATOR_CORE_SRC})
+      get_filename_component(ABS_FIL ${FIL} ABSOLUTE)
+      get_filename_component(FIL_WE ${FIL} NAME_WE)
+
+      set(output "${GENERATOR_CORE_DIR}/${FIL_WE}_pb2.py")
+      set(GENERATOR_CORE_PYTHON_SRC ${GENERATOR_CORE_PYTHON_SRC} ${output})
+      add_custom_command(
+        OUTPUT ${output}
+        COMMAND ${PROTOBUF_PROTOC_EXECUTABLE}
+        ARGS -I${GENERATOR_PATH}/proto
+          --python_out=${GENERATOR_CORE_DIR} ${ABS_FIL}
+        DEPENDS ${ABS_FIL}
+        VERBATIM)
+  endforeach()
+
+  if(NANOPB_GENERATE_CPP_RELPATH)
+      get_filename_component(ABS_ROOT ${NANOPB_GENERATE_CPP_RELPATH} ABSOLUTE)
+  endif()
+  foreach(FIL ${NANOPB_GENERATE_CPP_UNPARSED_ARGUMENTS})
+    get_filename_component(ABS_FIL ${FIL} ABSOLUTE)
+    get_filename_component(FIL_WE ${FIL} NAME_WE)
+    get_filename_component(FIL_DIR ${FIL} PATH)
+    set(FIL_PATH_REL)
+    if(ABS_ROOT)
+      # Check that the file is under the given "RELPATH"
+      string(FIND ${ABS_FIL} ${ABS_ROOT} LOC)
+      if (${LOC} EQUAL 0)
+        string(REPLACE "${ABS_ROOT}/" "" FIL_REL ${ABS_FIL})
+        get_filename_component(FIL_PATH_REL ${FIL_REL} PATH)
+        file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${FIL_PATH_REL})
+      endif()
+    endif()
+    if(NOT FIL_PATH_REL)
+      set(FIL_PATH_REL ".")
+    endif()
+
+    list(APPEND ${SRCS} "${CMAKE_CURRENT_BINARY_DIR}/${FIL_PATH_REL}/${FIL_WE}.pb.c")
+    list(APPEND ${HDRS} "${CMAKE_CURRENT_BINARY_DIR}/${FIL_PATH_REL}/${FIL_WE}.pb.h")
+
+    set(NANOPB_PLUGIN_OPTIONS)
+    set(NANOPB_OPTIONS_DIRS)
+
+    # If there an options file in the same working directory, set it as a dependency
+    get_filename_component(ABS_OPT_FIL ${FIL_DIR}/${FIL_WE}.options ABSOLUTE)
+    if(EXISTS ${ABS_OPT_FIL})
+        # Get directory as lookups for dependency options fail if an options
+        # file is used. The options is still set as a dependency of the
+        # generated source and header.
+        get_filename_component(options_dir ${ABS_OPT_FIL} DIRECTORY)
+        list(APPEND NANOPB_OPTIONS_DIRS ${options_dir})
+    else()
+        set(ABS_OPT_FIL)
+    endif()
+
+    # If the dependencies are options files, we need to pass the directories
+    # as arguments to nanopb
+    foreach(depends_file ${NANOPB_DEPENDS})
+        get_filename_component(ext ${depends_file} EXT)
+        if(ext STREQUAL ".options")
+            get_filename_component(depends_dir ${depends_file} DIRECTORY)
+            list(APPEND NANOPB_OPTIONS_DIRS ${depends_dir})
+        endif()
+    endforeach()
+
+    if(NANOPB_OPTIONS_DIRS)
+        list(REMOVE_DUPLICATES NANOPB_OPTIONS_DIRS)
+    endif()
+
+    foreach(options_path ${NANOPB_OPTIONS_DIRS})
+        set(NANOPB_PLUGIN_OPTIONS "${NANOPB_PLUGIN_OPTIONS} -I${options_path}")
+    endforeach()
+
+    if(NANOPB_OPTIONS)
+        set(NANOPB_PLUGIN_OPTIONS "${NANOPB_PLUGIN_OPTIONS} ${NANOPB_OPTIONS}")
+    endif()
+
+    # based on the version of protoc it might be necessary to add "/${FIL_PATH_REL}" currently dealt with in #516
+    set(NANOPB_OUT "${CMAKE_CURRENT_BINARY_DIR}")
+
+    # We need to pass the path to the option files to the nanopb plugin. There are two ways to do it.
+    # - An older hacky one using ':' as option separator in protoc args preventing the ':' to be used in path.
+    # - Or a newer one, using --nanopb_opt which requires a version of protoc >= 3.6
+    # So we will determine which version of protoc we have available and choose accordingly.
+    execute_process(COMMAND ${PROTOBUF_PROTOC_EXECUTABLE} --version OUTPUT_VARIABLE PROTOC_VERSION_STRING OUTPUT_STRIP_TRAILING_WHITESPACE)
+    string(REGEX MATCH "[(0-9)].*.[(0-9)].*.[(0-9)].*$" PROTOC_VERSION "${PROTOC_VERSION_STRING}")
+
+    #if(PROTOC_VERSION VERSION_LESS "3.6.0")
+	if(0)
+        #try to use the older way
+        string(REGEX MATCH ":" HAS_COLON_IN_PATH ${NANOPB_PLUGIN_OPTIONS} ${NANOPB_OUT})
+        if(HAS_COLON_IN_PATH)
+          message(FATAL_ERROR "Your path includes a ':' character used as an option separator for nanopb. Upgrade to protoc version >= 3.6.0 or use a different path.")
+        endif()
+        set(NANOPB_OPT_STRING "--nanopb_out=${NANOPB_PLUGIN_OPTIONS}:${NANOPB_OUT}")
+    else()
+      set(NANOPB_OPT_STRING "--nanopb_opt=${NANOPB_PLUGIN_OPTIONS}" "--nanopb_out=${NANOPB_OUT}")
+    endif()
+
+    add_custom_command(
+      OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${FIL_PATH_REL}/${FIL_WE}.pb.c"
+             "${CMAKE_CURRENT_BINARY_DIR}/${FIL_PATH_REL}/${FIL_WE}.pb.h"
+      COMMAND  ${PROTOBUF_PROTOC_EXECUTABLE}
+      ARGS -I${GENERATOR_PATH} -I${GENERATOR_CORE_DIR}
+           -I${CMAKE_CURRENT_BINARY_DIR} ${_nanopb_include_path}
+           --plugin=protoc-gen-nanopb=${NANOPB_GENERATOR_PLUGIN}
+           ${NANOPB_OPT_STRING}
+           ${ABS_FIL}
+      DEPENDS ${ABS_FIL} ${GENERATOR_CORE_PYTHON_SRC}
+           ${ABS_OPT_FIL} ${NANOPB_DEPENDS}
+      COMMENT "Running C++ protocol buffer compiler using nanopb plugin on ${FIL}"
+      VERBATIM )
+
+  endforeach()
+
+  set_source_files_properties(${${SRCS}} ${${HDRS}} PROPERTIES GENERATED TRUE)
+  set(${SRCS} ${${SRCS}} ${NANOPB_SRCS} PARENT_SCOPE)
+  set(${HDRS} ${${HDRS}} ${NANOPB_HDRS} PARENT_SCOPE)
+
+endfunction()
+
+
+
+#
+# Main.
+#
+
+# By default have NANOPB_GENERATE_CPP macro pass -I to protoc
+# for each directory where a proto file is referenced.
+if(NOT DEFINED NANOPB_GENERATE_CPP_APPEND_PATH)
+  set(NANOPB_GENERATE_CPP_APPEND_PATH TRUE)
+endif()
+
+# Make a really good guess regarding location of NANOPB_SRC_ROOT_FOLDER
+if(NOT DEFINED NANOPB_SRC_ROOT_FOLDER)
+  get_filename_component(NANOPB_SRC_ROOT_FOLDER
+                         ${CMAKE_CURRENT_LIST_DIR}/.. ABSOLUTE)
+endif()
+
+# Find the include directory
+find_path(NANOPB_INCLUDE_DIRS
+    pb.h
+    PATHS ${NANOPB_SRC_ROOT_FOLDER}
+    NO_CMAKE_FIND_ROOT_PATH
+)
+mark_as_advanced(NANOPB_INCLUDE_DIRS)
+
+# Find nanopb source files
+set(NANOPB_SRCS)
+set(NANOPB_HDRS)
+list(APPEND _nanopb_srcs pb_decode.c pb_encode.c pb_common.c)
+list(APPEND _nanopb_hdrs pb_decode.h pb_encode.h pb_common.h pb.h)
+
+foreach(FIL ${_nanopb_srcs})
+  find_file(${FIL}__nano_pb_file NAMES ${FIL} PATHS ${NANOPB_SRC_ROOT_FOLDER} ${NANOPB_INCLUDE_DIRS} NO_CMAKE_FIND_ROOT_PATH)
+  list(APPEND NANOPB_SRCS "${${FIL}__nano_pb_file}")
+  mark_as_advanced(${FIL}__nano_pb_file)
+endforeach()
+
+foreach(FIL ${_nanopb_hdrs})
+  find_file(${FIL}__nano_pb_file NAMES ${FIL} PATHS ${NANOPB_INCLUDE_DIRS} NO_CMAKE_FIND_ROOT_PATH)
+  mark_as_advanced(${FIL}__nano_pb_file)
+  list(APPEND NANOPB_HDRS "${${FIL}__nano_pb_file}")
+endforeach()
+
+# Find the protoc Executable
+find_program(PROTOBUF_PROTOC_EXECUTABLE
+    NAMES protoc
+    DOC "The Google Protocol Buffers Compiler"
+    PATHS
+    ${PROTOBUF_SRC_ROOT_FOLDER}/vsprojects/Release
+    ${PROTOBUF_SRC_ROOT_FOLDER}/vsprojects/Debug
+    ${NANOPB_SRC_ROOT_FOLDER}/generator-bin
+    ${NANOPB_SRC_ROOT_FOLDER}/generator
+)
+mark_as_advanced(PROTOBUF_PROTOC_EXECUTABLE)
+
+# Find nanopb generator source dir
+find_path(NANOPB_GENERATOR_SOURCE_DIR
+    NAMES nanopb_generator.py
+    DOC "nanopb generator source"
+    PATHS
+    ${NANOPB_SRC_ROOT_FOLDER}/generator
+    NO_CMAKE_FIND_ROOT_PATH
+)
+mark_as_advanced(NANOPB_GENERATOR_SOURCE_DIR)
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(Nanopb DEFAULT_MSG
+  NANOPB_INCLUDE_DIRS
+  NANOPB_SRCS NANOPB_HDRS
+  NANOPB_GENERATOR_SOURCE_DIR
+  PROTOBUF_PROTOC_EXECUTABLE
+  )

+ 11 - 0
components/spotify/cspot/bell/nanopb/extra/nanopb-config-version.cmake.in

@@ -0,0 +1,11 @@
+set(PACKAGE_VERSION "@nanopb_VERSION@")
+
+# Check whether the requested PACKAGE_FIND_VERSION is compatible
+if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}")
+    set(PACKAGE_VERSION_COMPATIBLE FALSE)
+else()
+    set(PACKAGE_VERSION_COMPATIBLE TRUE)
+    if ("${PACKAGE_VERSION}" VERSION_EQUAL "${PACKAGE_FIND_VERSION}")
+        set(PACKAGE_VERSION_EXACT TRUE)
+    endif()
+endif()

+ 1 - 0
components/spotify/cspot/bell/nanopb/extra/nanopb-config.cmake

@@ -0,0 +1 @@
+include(${CMAKE_CURRENT_LIST_DIR}/nanopb-targets.cmake)

+ 37 - 0
components/spotify/cspot/bell/nanopb/extra/nanopb.mk

@@ -0,0 +1,37 @@
+# This is an include file for Makefiles. It provides rules for building
+# .pb.c and .pb.h files out of .proto, as well the path to nanopb core.
+
+# Path to the nanopb root directory
+NANOPB_DIR := $(patsubst %/,%,$(dir $(patsubst %/,%,$(dir $(lastword $(MAKEFILE_LIST))))))
+
+# Files for the nanopb core
+NANOPB_CORE = $(NANOPB_DIR)/pb_encode.c $(NANOPB_DIR)/pb_decode.c $(NANOPB_DIR)/pb_common.c
+
+# Check if we are running on Windows
+ifdef windir
+WINDOWS = 1
+endif
+ifdef WINDIR
+WINDOWS = 1
+endif
+
+# Check whether to use binary version of nanopb_generator or the
+# system-supplied python interpreter.
+ifneq "$(wildcard $(NANOPB_DIR)/generator-bin)" ""
+	# Binary package
+	PROTOC = $(NANOPB_DIR)/generator-bin/protoc
+	PROTOC_OPTS =
+else
+	# Source only or git checkout
+	PROTOC_OPTS =
+	ifdef WINDOWS
+	    PROTOC = python $(NANOPB_DIR)/generator/protoc
+	else
+	    PROTOC = $(NANOPB_DIR)/generator/protoc
+	endif
+endif
+
+# Rule for building .pb.c and .pb.h
+%.pb.c %.pb.h: %.proto $(wildcard %.options)
+	$(PROTOC) $(PROTOC_OPTS) --nanopb_out=. $<
+

+ 120 - 0
components/spotify/cspot/bell/nanopb/extra/pb_syshdr.h

@@ -0,0 +1,120 @@
+/* This is an example of a header file for platforms/compilers that do
+ * not come with stdint.h/stddef.h/stdbool.h/string.h. To use it, define
+ * PB_SYSTEM_HEADER as "pb_syshdr.h", including the quotes, and add the
+ * extra folder to your include path.
+ *
+ * It is very likely that you will need to customize this file to suit
+ * your platform. For any compiler that supports C99, this file should
+ * not be necessary.
+ */
+
+#ifndef _PB_SYSHDR_H_
+#define _PB_SYSHDR_H_
+
+/* stdint.h subset */
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#else
+/* You will need to modify these to match the word size of your platform. */
+typedef signed char int8_t;
+typedef unsigned char uint8_t;
+typedef signed short int16_t;
+typedef unsigned short uint16_t;
+typedef signed int int32_t;
+typedef unsigned int uint32_t;
+typedef signed long long int64_t;
+typedef unsigned long long uint64_t;
+
+/* These are ok for most platforms, unless uint8_t is actually not available,
+ * in which case you should give the smallest available type. */
+typedef int8_t int_least8_t;
+typedef uint8_t uint_least8_t;
+typedef uint8_t uint_fast8_t;
+typedef int16_t int_least16_t;
+typedef uint16_t uint_least16_t;
+#endif
+
+/* stddef.h subset */
+#ifdef HAVE_STDDEF_H
+#include <stddef.h>
+#else
+
+typedef uint32_t size_t;
+#define offsetof(st, m) ((size_t)(&((st *)0)->m))
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+#endif
+
+/* stdbool.h subset */
+#ifdef HAVE_STDBOOL_H
+#include <stdbool.h>
+#else
+
+#ifndef __cplusplus
+typedef int bool;
+#define false 0
+#define true 1
+#endif
+
+#endif
+
+/* stdlib.h subset */
+#ifdef PB_ENABLE_MALLOC
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#else
+void *realloc(void *ptr, size_t size);
+void free(void *ptr);
+#endif
+#endif
+
+/* string.h subset */
+#ifdef HAVE_STRING_H
+#include <string.h>
+#else
+
+/* Implementations are from the Public Domain C Library (PDCLib). */
+static size_t strlen( const char * s )
+{
+    size_t rc = 0;
+    while ( s[rc] )
+    {
+        ++rc;
+    }
+    return rc;
+}
+
+static void * memcpy( void *s1, const void *s2, size_t n )
+{
+    char * dest = (char *) s1;
+    const char * src = (const char *) s2;
+    while ( n-- )
+    {
+        *dest++ = *src++;
+    }
+    return s1;
+}
+
+static void * memset( void * s, int c, size_t n )
+{
+    unsigned char * p = (unsigned char *) s;
+    while ( n-- )
+    {
+        *p++ = (unsigned char) c;
+    }
+    return s;
+}
+#endif
+
+
+/* limits.h subset */
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#else
+#define CHAR_BIT 8
+#endif
+
+#endif

+ 20 - 0
components/spotify/cspot/bell/nanopb/extra/poetry/poetry_build.sh

@@ -0,0 +1,20 @@
+#!/bin/bash
+
+set -ex
+
+rm -rf build
+mkdir build
+mkdir -p dist
+
+(cd "$(git rev-parse --show-toplevel)"; git archive HEAD) > build/tmp.tar
+cd build
+ln -s ../dist .
+
+mkdir nanopb
+tar xf tmp.tar README.md generator
+mv generator nanopb/
+touch nanopb/__init__.py nanopb/generator/__init__.py
+make -C nanopb/generator/proto
+cp ../pyproject.toml .
+sed -i -e 's/\(version =.*\)-dev.*/\1-dev'$(git rev-list HEAD --count)'"/' pyproject.toml
+poetry build

+ 31 - 0
components/spotify/cspot/bell/nanopb/extra/poetry/pyproject.toml

@@ -0,0 +1,31 @@
+[tool.poetry]
+name = "nanopb"
+version = "0.4.6-dev"
+description = "Nanopb is a small code-size Protocol Buffers implementation in ansi C. It is especially suitable for use in microcontrollers, but fits any memory restricted system."
+authors = ["Petteri Aimonen <jpa@npb.mail.kapsi.fi>"]
+license = "Zlib"
+repository = "https://github.com/nanopb/nanopb/"
+readme = "README.md"
+homepage = "https://jpa.kapsi.fi/nanopb/"
+documentation = "https://jpa.kapsi.fi/nanopb/docs/index.html"
+keywords = ["protobuf", "protoc"]
+classifiers = ["Topic :: Software Development :: Build Tools"]
+include = ["nanopb/**/*", "nanopb/__init__.py"]
+
+[tool.poetry.scripts]
+nanopb_generator = "nanopb.generator.nanopb_generator:main_cli"
+protoc-gen-nanopb = "nanopb.generator.nanopb_generator:main_plugin"
+
+[tool.poetry.dependencies]
+python = ">=2.7"
+protobuf = ">=3.6"
+grpcio-tools = {version = ">=1.26.0rc1", allow-prereleases = true, optional=true}
+
+[tool.poetry.dev-dependencies]
+
+[tool.poetry.extras]
+grpcio-tools = ["grpcio-tools"]
+
+[build-system]
+requires = ["poetry>=0.12"]
+build-backend = "poetry.masonry.api"

+ 2361 - 0
components/spotify/cspot/bell/nanopb/generator/nanopb_generator.py

@@ -0,0 +1,2361 @@
+#!/usr/bin/env python3
+# kate: replace-tabs on; indent-width 4;
+
+from __future__ import unicode_literals
+
+'''Generate header file for nanopb from a ProtoBuf FileDescriptorSet.'''
+nanopb_version = "nanopb-0.4.6-dev"
+
+import sys
+import re
+import codecs
+import copy
+import itertools
+import tempfile
+import shutil
+import os
+from functools import reduce
+
+try:
+    # Add some dummy imports to keep packaging tools happy.
+    import google # bbfreeze seems to need these
+    import pkg_resources # pyinstaller / protobuf 2.5 seem to need these
+    import proto.nanopb_pb2 as nanopb_pb2 # pyinstaller seems to need this
+    import pkg_resources.py2_warn
+except:
+    # Don't care, we will error out later if it is actually important.
+    pass
+
+try:
+    # Make sure grpc_tools gets included in binary package if it is available
+    import grpc_tools.protoc
+except:
+    pass
+
+try:
+    import google.protobuf.text_format as text_format
+    import google.protobuf.descriptor_pb2 as descriptor
+    import google.protobuf.compiler.plugin_pb2 as plugin_pb2
+    import google.protobuf.reflection as reflection
+    import google.protobuf.descriptor
+except:
+    sys.stderr.write('''
+         *************************************************************
+         *** Could not import the Google protobuf Python libraries ***
+         *** Try installing package 'python3-protobuf' or similar.  ***
+         *************************************************************
+    ''' + '\n')
+    raise
+
+try:
+    from .proto import nanopb_pb2
+    from .proto._utils import invoke_protoc
+except TypeError:
+    sys.stderr.write('''
+         ****************************************************************************
+         *** Got TypeError when importing the protocol definitions for generator. ***
+         *** This usually means that the protoc in your path doesn't match the    ***
+         *** Python protobuf library version.                                     ***
+         ***                                                                      ***
+         *** Please check the output of the following commands:                   ***
+         *** which protoc                                                         ***
+         *** protoc --version                                                     ***
+         *** python3 -c 'import google.protobuf; print(google.protobuf.__file__)'  ***
+         *** If you are not able to find the python protobuf version using the    ***
+         *** above command, use this command.                                     ***
+         *** pip freeze | grep -i protobuf                                        ***
+         ****************************************************************************
+    ''' + '\n')
+    raise
+except (ValueError, SystemError, ImportError):
+    # Probably invoked directly instead of via installed scripts.
+    import proto.nanopb_pb2 as nanopb_pb2
+    from proto._utils import invoke_protoc
+except:
+    sys.stderr.write('''
+         ********************************************************************
+         *** Failed to import the protocol definitions for generator.     ***
+         *** You have to run 'make' in the nanopb/generator/proto folder. ***
+         ********************************************************************
+    ''' + '\n')
+    raise
+
+try:
+    from tempfile import TemporaryDirectory
+except ImportError:
+    class TemporaryDirectory:
+        '''TemporaryDirectory fallback for Python 2'''
+        def __enter__(self):
+            self.dir = tempfile.mkdtemp()
+            return self.dir
+
+        def __exit__(self, *args):
+            shutil.rmtree(self.dir)
+
+# ---------------------------------------------------------------------------
+#                     Generation of single fields
+# ---------------------------------------------------------------------------
+
+import time
+import os.path
+
+# Values are tuple (c type, pb type, encoded size, data_size)
+FieldD = descriptor.FieldDescriptorProto
+datatypes = {
+    FieldD.TYPE_BOOL:       ('bool',     'BOOL',        1,  4),
+    FieldD.TYPE_DOUBLE:     ('double',   'DOUBLE',      8,  8),
+    FieldD.TYPE_FIXED32:    ('uint32_t', 'FIXED32',     4,  4),
+    FieldD.TYPE_FIXED64:    ('uint64_t', 'FIXED64',     8,  8),
+    FieldD.TYPE_FLOAT:      ('float',    'FLOAT',       4,  4),
+    FieldD.TYPE_INT32:      ('int32_t',  'INT32',      10,  4),
+    FieldD.TYPE_INT64:      ('int64_t',  'INT64',      10,  8),
+    FieldD.TYPE_SFIXED32:   ('int32_t',  'SFIXED32',    4,  4),
+    FieldD.TYPE_SFIXED64:   ('int64_t',  'SFIXED64',    8,  8),
+    FieldD.TYPE_SINT32:     ('int32_t',  'SINT32',      5,  4),
+    FieldD.TYPE_SINT64:     ('int64_t',  'SINT64',     10,  8),
+    FieldD.TYPE_UINT32:     ('uint32_t', 'UINT32',      5,  4),
+    FieldD.TYPE_UINT64:     ('uint64_t', 'UINT64',     10,  8),
+
+    # Integer size override options
+    (FieldD.TYPE_INT32,   nanopb_pb2.IS_8):   ('int8_t',   'INT32', 10,  1),
+    (FieldD.TYPE_INT32,  nanopb_pb2.IS_16):   ('int16_t',  'INT32', 10,  2),
+    (FieldD.TYPE_INT32,  nanopb_pb2.IS_32):   ('int32_t',  'INT32', 10,  4),
+    (FieldD.TYPE_INT32,  nanopb_pb2.IS_64):   ('int64_t',  'INT32', 10,  8),
+    (FieldD.TYPE_SINT32,  nanopb_pb2.IS_8):   ('int8_t',  'SINT32',  2,  1),
+    (FieldD.TYPE_SINT32, nanopb_pb2.IS_16):   ('int16_t', 'SINT32',  3,  2),
+    (FieldD.TYPE_SINT32, nanopb_pb2.IS_32):   ('int32_t', 'SINT32',  5,  4),
+    (FieldD.TYPE_SINT32, nanopb_pb2.IS_64):   ('int64_t', 'SINT32', 10,  8),
+    (FieldD.TYPE_UINT32,  nanopb_pb2.IS_8):   ('uint8_t', 'UINT32',  2,  1),
+    (FieldD.TYPE_UINT32, nanopb_pb2.IS_16):   ('uint16_t','UINT32',  3,  2),
+    (FieldD.TYPE_UINT32, nanopb_pb2.IS_32):   ('uint32_t','UINT32',  5,  4),
+    (FieldD.TYPE_UINT32, nanopb_pb2.IS_64):   ('uint64_t','UINT32', 10,  8),
+    (FieldD.TYPE_INT64,   nanopb_pb2.IS_8):   ('int8_t',   'INT64', 10,  1),
+    (FieldD.TYPE_INT64,  nanopb_pb2.IS_16):   ('int16_t',  'INT64', 10,  2),
+    (FieldD.TYPE_INT64,  nanopb_pb2.IS_32):   ('int32_t',  'INT64', 10,  4),
+    (FieldD.TYPE_INT64,  nanopb_pb2.IS_64):   ('int64_t',  'INT64', 10,  8),
+    (FieldD.TYPE_SINT64,  nanopb_pb2.IS_8):   ('int8_t',  'SINT64',  2,  1),
+    (FieldD.TYPE_SINT64, nanopb_pb2.IS_16):   ('int16_t', 'SINT64',  3,  2),
+    (FieldD.TYPE_SINT64, nanopb_pb2.IS_32):   ('int32_t', 'SINT64',  5,  4),
+    (FieldD.TYPE_SINT64, nanopb_pb2.IS_64):   ('int64_t', 'SINT64', 10,  8),
+    (FieldD.TYPE_UINT64,  nanopb_pb2.IS_8):   ('uint8_t', 'UINT64',  2,  1),
+    (FieldD.TYPE_UINT64, nanopb_pb2.IS_16):   ('uint16_t','UINT64',  3,  2),
+    (FieldD.TYPE_UINT64, nanopb_pb2.IS_32):   ('uint32_t','UINT64',  5,  4),
+    (FieldD.TYPE_UINT64, nanopb_pb2.IS_64):   ('uint64_t','UINT64', 10,  8),
+}
+
+class Globals:
+    '''Ugly global variables, should find a good way to pass these.'''
+    verbose_options = False
+    separate_options = []
+    matched_namemasks = set()
+    protoc_insertion_points = False
+
+# String types (for python 2 / python 3 compatibility)
+try:
+    strtypes = (unicode, str)
+    openmode_unicode = 'rU'
+except NameError:
+    strtypes = (str, )
+    openmode_unicode = 'r'
+
+
+class Names:
+    '''Keeps a set of nested names and formats them to C identifier.'''
+    def __init__(self, parts = ()):
+        if isinstance(parts, Names):
+            parts = parts.parts
+        elif isinstance(parts, strtypes):
+            parts = (parts,)
+        self.parts = tuple(parts)
+
+    def __str__(self):
+        return '_'.join(self.parts)
+
+    def __add__(self, other):
+        if isinstance(other, strtypes):
+            return Names(self.parts + (other,))
+        elif isinstance(other, Names):
+            return Names(self.parts + other.parts)
+        elif isinstance(other, tuple):
+            return Names(self.parts + other)
+        else:
+            raise ValueError("Name parts should be of type str")
+
+    def __eq__(self, other):
+        return isinstance(other, Names) and self.parts == other.parts
+
+    def __lt__(self, other):
+        if not isinstance(other, Names):
+            return NotImplemented
+        return str(self) < str(other)
+
+def names_from_type_name(type_name):
+    '''Parse Names() from FieldDescriptorProto type_name'''
+    if type_name[0] != '.':
+        raise NotImplementedError("Lookup of non-absolute type names is not supported")
+    return Names(type_name[1:].split('.'))
+
+def varint_max_size(max_value):
+    '''Returns the maximum number of bytes a varint can take when encoded.'''
+    if max_value < 0:
+        max_value = 2**64 - max_value
+    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(-1) == 10
+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 = [], declarations = [], required_defines = []):
+        if isinstance(value, EncodedSize):
+            self.value = value.value
+            self.symbols = value.symbols
+            self.declarations = value.declarations
+            self.required_defines = value.required_defines
+        elif isinstance(value, strtypes + (Names,)):
+            self.symbols = [str(value)]
+            self.value = 0
+            self.declarations = []
+            self.required_defines = [str(value)]
+        else:
+            self.value = value
+            self.symbols = symbols
+            self.declarations = declarations
+            self.required_defines = required_defines
+
+    def __add__(self, other):
+        if isinstance(other, int):
+            return EncodedSize(self.value + other, self.symbols, self.declarations, self.required_defines)
+        elif isinstance(other, strtypes + (Names,)):
+            return EncodedSize(self.value, self.symbols + [str(other)], self.declarations, self.required_defines + [str(other)])
+        elif isinstance(other, EncodedSize):
+            return EncodedSize(self.value + other.value, self.symbols + other.symbols,
+                               self.declarations + other.declarations, self.required_defines + other.required_defines)
+        else:
+            raise ValueError("Cannot add size: " + repr(other))
+
+    def __mul__(self, other):
+        if isinstance(other, int):
+            return EncodedSize(self.value * other, [str(other) + '*' + s for s in self.symbols],
+                               self.declarations, self.required_defines)
+        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 get_declarations(self):
+        '''Get any declarations that must appear alongside this encoded size definition,
+        such as helper union {} types.'''
+        return '\n'.join(self.declarations)
+
+    def get_cpp_guard(self, local_defines):
+        '''Get an #if preprocessor statement listing all defines that are required for this definition.'''
+        needed = [x for x in self.required_defines if x not in local_defines]
+        if needed:
+            return '#if ' + ' && '.join(['defined(%s)' % x for x in needed]) + "\n"
+        else:
+            return ''
+
+    def upperlimit(self):
+        if not self.symbols:
+            return self.value
+        else:
+            return 2**32 - 1
+
+
+'''
+Constants regarding path of proto elements in file descriptor.
+They are used to connect proto elements with source code information (comments)
+These values come from:
+    https://github.com/google/protobuf/blob/master/src/google/protobuf/descriptor.proto
+'''
+MESSAGE_PATH = 4
+ENUM_PATH = 5
+FIELD_PATH = 2
+
+
+class ProtoElement(object):
+    def __init__(self, path, index, comments):
+        '''
+        path is a predefined value for each element type in proto file.
+            For example, message == 4, enum == 5, service == 6
+        index is the N-th occurrence of the `path` in the proto file.
+            For example, 4-th message in the proto file or 2-nd enum etc ...
+        comments is a dictionary mapping between element path & SourceCodeInfo.Location
+            (contains information about source comments).
+        '''
+        self.path = path
+        self.index = index
+        self.comments = comments
+
+    def element_path(self):
+        '''Get path to proto element.'''
+        return [self.path, self.index]
+
+    def member_path(self, member_index):
+        '''Get path to member of proto element.
+        Example paths:
+        [4, m] - message comments, m: msgIdx in proto from 0
+        [4, m, 2, f] - field comments in message, f: fieldIdx in message from 0
+        [6, s] - service comments, s: svcIdx in proto from 0
+        [6, s, 2, r] - rpc comments in service, r: rpc method def in service from 0
+        '''
+        return self.element_path() + [FIELD_PATH, member_index]
+
+    def get_comments(self, path, leading_indent=True):
+        '''Get leading & trailing comments for enum member based on path.
+
+        path is the proto path of an element or member (ex. [5 0] or [4 1 2 0])
+        leading_indent is a flag that indicates if leading comments should be indented
+        '''
+
+        # Obtain SourceCodeInfo.Location object containing comment
+        # information (based on the member path)
+        comment = self.comments.get(str(path))
+
+        leading_comment = ""
+        trailing_comment = ""
+
+        if not comment:
+            return leading_comment, trailing_comment
+
+        if comment.leading_comments:
+            leading_comment = "    " if leading_indent else ""
+            leading_comment += "/* %s */" % comment.leading_comments.strip()
+
+        if comment.trailing_comments:
+            trailing_comment = "/* %s */" % comment.trailing_comments.strip()
+
+        return leading_comment, trailing_comment
+
+
+class Enum(ProtoElement):
+    def __init__(self, names, desc, enum_options, index, comments):
+        '''
+        desc is EnumDescriptorProto
+        index is the index of this enum element inside the file
+        comments is a dictionary mapping between element path & SourceCodeInfo.Location
+            (contains information about source comments)
+        '''
+        super(Enum, self).__init__(ENUM_PATH, index, comments)
+
+        self.options = enum_options
+        self.names = names
+
+        # by definition, `names` include this enum's name
+        base_name = Names(names.parts[:-1])
+
+        if enum_options.long_names:
+            self.values = [(names + x.name, x.number) for x in desc.value]
+        else:
+            self.values = [(base_name + x.name, x.number) for x in desc.value]
+
+        self.value_longnames = [self.names + x.name for x in desc.value]
+        self.packed = enum_options.packed_enum
+
+    def has_negative(self):
+        for n, v in self.values:
+            if v < 0:
+                return True
+        return False
+
+    def encoded_size(self):
+        return max([varint_max_size(v) for n,v in self.values])
+
+    def __str__(self):
+        enum_path = self.element_path()
+        leading_comment, trailing_comment = self.get_comments(enum_path, leading_indent=False)
+
+        result = ''
+        if leading_comment:
+            result = '%s\n' % leading_comment
+
+        result += 'typedef enum _%s { %s\n' % (self.names, trailing_comment)
+
+        enum_length = len(self.values)
+        enum_values = []
+        for index, (name, value) in enumerate(self.values):
+            member_path = self.member_path(index)
+            leading_comment, trailing_comment = self.get_comments(member_path)
+
+            if leading_comment:
+                enum_values.append(leading_comment)
+
+            comma = ","
+            if index == enum_length - 1:
+                # last enum member should not end with a comma
+                comma = ""
+
+            enum_values.append("    %s = %d%s %s" % (name, value, comma, trailing_comment))
+
+        result += '\n'.join(enum_values)
+        result += '\n}'
+
+        if self.packed:
+            result += ' pb_packed'
+
+        result += ' %s;' % self.names
+        return result
+
+    def auxiliary_defines(self):
+        # sort the enum by value
+        sorted_values = sorted(self.values, key = lambda x: (x[1], x[0]))
+        result  = '#define _%s_MIN %s\n' % (self.names, sorted_values[0][0])
+        result += '#define _%s_MAX %s\n' % (self.names, sorted_values[-1][0])
+        result += '#define _%s_ARRAYSIZE ((%s)(%s+1))\n' % (self.names, self.names, sorted_values[-1][0])
+
+        if not self.options.long_names:
+            # Define the long names always so that enum value references
+            # from other files work properly.
+            for i, x in enumerate(self.values):
+                result += '#define %s %s\n' % (self.value_longnames[i], x[0])
+
+        if self.options.enum_to_string:
+            result += 'const char *%s_name(%s v);\n' % (self.names, self.names)
+
+        return result
+
+    def enum_to_string_definition(self):
+        if not self.options.enum_to_string:
+            return ""
+
+        result = 'const char *%s_name(%s v) {\n' % (self.names, self.names)
+        result += '    switch (v) {\n'
+
+        for ((enumname, _), strname) in zip(self.values, self.value_longnames):
+            # Strip off the leading type name from the string value.
+            strval = str(strname)[len(str(self.names)) + 1:]
+            result += '        case %s: return "%s";\n' % (enumname, strval)
+
+        result += '    }\n'
+        result += '    return "unknown";\n'
+        result += '}\n'
+
+        return result
+
+class FieldMaxSize:
+    def __init__(self, worst = 0, checks = [], field_name = 'undefined'):
+        if isinstance(worst, list):
+            self.worst = max(i for i in worst if i is not None)
+        else:
+            self.worst = worst
+
+        self.worst_field = field_name
+        self.checks = list(checks)
+
+    def extend(self, extend, field_name = None):
+        self.worst = max(self.worst, extend.worst)
+
+        if self.worst == extend.worst:
+            self.worst_field = extend.worst_field
+
+        self.checks.extend(extend.checks)
+
+class Field:
+    macro_x_param = 'X'
+    macro_a_param = 'a'
+
+    def __init__(self, struct_name, desc, field_options):
+        '''desc is FieldDescriptorProto'''
+        self.tag = desc.number
+        self.struct_name = struct_name
+        self.union_name = None
+        self.name = desc.name
+        self.default = None
+        self.max_size = None
+        self.max_count = None
+        self.array_decl = ""
+        self.enc_size = None
+        self.data_item_size = None
+        self.ctype = None
+        self.fixed_count = False
+        self.callback_datatype = field_options.callback_datatype
+        self.math_include_required = False
+        self.sort_by_tag = field_options.sort_by_tag
+
+        if field_options.type == nanopb_pb2.FT_INLINE:
+            # Before nanopb-0.3.8, fixed length bytes arrays were specified
+            # by setting type to FT_INLINE. But to handle pointer typed fields,
+            # it makes sense to have it as a separate option.
+            field_options.type = nanopb_pb2.FT_STATIC
+            field_options.fixed_length = True
+
+        # Parse field options
+        if field_options.HasField("max_size"):
+            self.max_size = field_options.max_size
+
+        self.default_has = field_options.default_has
+
+        if desc.type == FieldD.TYPE_STRING and field_options.HasField("max_length"):
+            # max_length overrides max_size for strings
+            self.max_size = field_options.max_length + 1
+
+        if field_options.HasField("max_count"):
+            self.max_count = field_options.max_count
+
+        if desc.HasField('default_value'):
+            self.default = desc.default_value
+
+        # Check field rules, i.e. required/optional/repeated.
+        can_be_static = True
+        if desc.label == FieldD.LABEL_REPEATED:
+            self.rules = 'REPEATED'
+            if self.max_count is None:
+                can_be_static = False
+            else:
+                self.array_decl = '[%d]' % self.max_count
+                if field_options.fixed_count:
+                  self.rules = 'FIXARRAY'
+
+        elif field_options.proto3:
+            if desc.type == FieldD.TYPE_MESSAGE and not field_options.proto3_singular_msgs:
+                # In most other protobuf libraries proto3 submessages have
+                # "null" status. For nanopb, that is implemented as has_ field.
+                self.rules = 'OPTIONAL'
+            elif hasattr(desc, "proto3_optional") and desc.proto3_optional:
+                # Protobuf 3.12 introduced optional fields for proto3 syntax
+                self.rules = 'OPTIONAL'
+            else:
+                # Proto3 singular fields (without has_field)
+                self.rules = 'SINGULAR'
+        elif desc.label == FieldD.LABEL_REQUIRED:
+            self.rules = 'REQUIRED'
+        elif desc.label == FieldD.LABEL_OPTIONAL:
+            self.rules = 'OPTIONAL'
+        else:
+            raise NotImplementedError(desc.label)
+
+        # Check if the field can be implemented with static allocation
+        # i.e. whether the data size is known.
+        if desc.type == FieldD.TYPE_STRING and self.max_size is None:
+            can_be_static = False
+
+        if desc.type == FieldD.TYPE_BYTES and self.max_size is None:
+            can_be_static = False
+
+        # Decide how the field data will be allocated
+        if field_options.type == nanopb_pb2.FT_DEFAULT:
+            if can_be_static:
+                field_options.type = nanopb_pb2.FT_STATIC
+            else:
+                field_options.type = nanopb_pb2.FT_CALLBACK
+
+        if field_options.type == nanopb_pb2.FT_STATIC and not can_be_static:
+            raise Exception("Field '%s' is defined as static, but max_size or "
+                            "max_count is not given." % self.name)
+
+        if field_options.fixed_count and self.max_count is None:
+            raise Exception("Field '%s' is defined as fixed count, "
+                            "but max_count is not given." % self.name)
+
+        if field_options.type == nanopb_pb2.FT_STATIC:
+            self.allocation = 'STATIC'
+        elif field_options.type == nanopb_pb2.FT_POINTER:
+            self.allocation = 'POINTER'
+        elif field_options.type == nanopb_pb2.FT_CALLBACK:
+            self.allocation = 'CALLBACK'
+        else:
+            raise NotImplementedError(field_options.type)
+
+        if field_options.HasField("type_override"):
+            desc.type = field_options.type_override
+
+        # Decide the C data type to use in the struct.
+        if desc.type in datatypes:
+            self.ctype, self.pbtype, self.enc_size, self.data_item_size = datatypes[desc.type]
+
+            # Override the field size if user wants to use smaller integers
+            if (desc.type, field_options.int_size) in datatypes:
+                self.ctype, self.pbtype, self.enc_size, self.data_item_size = datatypes[(desc.type, field_options.int_size)]
+        elif desc.type == FieldD.TYPE_ENUM:
+            self.pbtype = 'ENUM'
+            self.data_item_size = 4
+            self.ctype = names_from_type_name(desc.type_name)
+            if self.default is not None:
+                self.default = self.ctype + self.default
+            self.enc_size = None # Needs to be filled in when enum values are known
+        elif desc.type == FieldD.TYPE_STRING:
+            self.pbtype = 'STRING'
+            self.ctype = 'char'
+            if self.allocation == 'STATIC':
+                self.ctype = 'char'
+                self.array_decl += '[%d]' % self.max_size
+                # -1 because of null terminator. Both pb_encode and pb_decode
+                # check the presence of it.
+                self.enc_size = varint_max_size(self.max_size) + self.max_size - 1
+        elif desc.type == FieldD.TYPE_BYTES:
+            if field_options.fixed_length:
+                self.pbtype = 'FIXED_LENGTH_BYTES'
+
+                if self.max_size is None:
+                    raise Exception("Field '%s' is defined as fixed length, "
+                                    "but max_size is not given." % self.name)
+
+                self.enc_size = varint_max_size(self.max_size) + self.max_size
+                self.ctype = 'pb_byte_t'
+                self.array_decl += '[%d]' % self.max_size
+            else:
+                self.pbtype = 'BYTES'
+                self.ctype = 'pb_bytes_array_t'
+                if self.allocation == 'STATIC':
+                    self.ctype = self.struct_name + self.name + 't'
+                    self.enc_size = varint_max_size(self.max_size) + self.max_size
+        elif desc.type == FieldD.TYPE_MESSAGE:
+            self.pbtype = 'MESSAGE'
+            self.ctype = self.submsgname = names_from_type_name(desc.type_name)
+            self.enc_size = None # Needs to be filled in after the message type is available
+            if field_options.submsg_callback and self.allocation == 'STATIC':
+                self.pbtype = 'MSG_W_CB'
+        else:
+            raise NotImplementedError(desc.type)
+
+        if self.default and self.pbtype in ['FLOAT', 'DOUBLE']:
+            if 'inf' in self.default or 'nan' in self.default:
+                self.math_include_required = True
+
+    def __lt__(self, other):
+        return self.tag < other.tag
+
+    def __str__(self):
+        result = ''
+        if self.allocation == 'POINTER':
+            if self.rules == 'REPEATED':
+                if self.pbtype == 'MSG_W_CB':
+                    result += '    pb_callback_t cb_' + self.name + ';\n'
+                result += '    pb_size_t ' + self.name + '_count;\n'
+
+            if self.pbtype in ['MESSAGE', 'MSG_W_CB']:
+                # Use struct definition, so recursive submessages are possible
+                result += '    struct _%s *%s;' % (self.ctype, self.name)
+            elif self.pbtype == 'FIXED_LENGTH_BYTES' or self.rules == 'FIXARRAY':
+                # Pointer to fixed size array
+                result += '    %s (*%s)%s;' % (self.ctype, self.name, self.array_decl)
+            elif self.rules in ['REPEATED', 'FIXARRAY'] and self.pbtype in ['STRING', 'BYTES']:
+                # String/bytes arrays need to be defined as pointers to pointers
+                result += '    %s **%s;' % (self.ctype, self.name)
+            else:
+                result += '    %s *%s;' % (self.ctype, self.name)
+        elif self.allocation == 'CALLBACK':
+            result += '    %s %s;' % (self.callback_datatype, self.name)
+        else:
+            if self.pbtype == 'MSG_W_CB' and self.rules in ['OPTIONAL', 'REPEATED']:
+                result += '    pb_callback_t cb_' + self.name + ';\n'
+
+            if self.rules == 'OPTIONAL':
+                result += '    bool has_' + self.name + ';\n'
+            elif self.rules == 'REPEATED':
+                result += '    pb_size_t ' + self.name + '_count;\n'
+            result += '    %s %s%s;' % (self.ctype, self.name, self.array_decl)
+        return result
+
+    def types(self):
+        '''Return definitions for any special types this field might need.'''
+        if self.pbtype == 'BYTES' and self.allocation == 'STATIC':
+            result = 'typedef PB_BYTES_ARRAY_T(%d) %s;\n' % (self.max_size, self.ctype)
+        else:
+            result = ''
+        return result
+
+    def get_dependencies(self):
+        '''Get list of type names used by this field.'''
+        if self.allocation == 'STATIC':
+            return [str(self.ctype)]
+        else:
+            return []
+
+    def get_initializer(self, null_init, inner_init_only = False):
+        '''Return literal expression for this field's default value.
+        null_init: If True, initialize to a 0 value instead of default from .proto
+        inner_init_only: If True, exclude initialization for any count/has fields
+        '''
+
+        inner_init = None
+        if self.pbtype in ['MESSAGE', 'MSG_W_CB']:
+            if null_init:
+                inner_init = '%s_init_zero' % self.ctype
+            else:
+                inner_init = '%s_init_default' % self.ctype
+        elif self.default is None or null_init:
+            if self.pbtype == 'STRING':
+                inner_init = '""'
+            elif self.pbtype == 'BYTES':
+                inner_init = '{0, {0}}'
+            elif self.pbtype == 'FIXED_LENGTH_BYTES':
+                inner_init = '{0}'
+            elif self.pbtype in ('ENUM', 'UENUM'):
+                inner_init = '_%s_MIN' % self.ctype
+            else:
+                inner_init = '0'
+        else:
+            if self.pbtype == 'STRING':
+                data = codecs.escape_encode(self.default.encode('utf-8'))[0]
+                inner_init = '"' + data.decode('ascii') + '"'
+            elif self.pbtype == 'BYTES':
+                data = codecs.escape_decode(self.default)[0]
+                data = ["0x%02x" % c for c in bytearray(data)]
+                if len(data) == 0:
+                    inner_init = '{0, {0}}'
+                else:
+                    inner_init = '{%d, {%s}}' % (len(data), ','.join(data))
+            elif self.pbtype == 'FIXED_LENGTH_BYTES':
+                data = codecs.escape_decode(self.default)[0]
+                data = ["0x%02x" % c for c in bytearray(data)]
+                if len(data) == 0:
+                    inner_init = '{0}'
+                else:
+                    inner_init = '{%s}' % ','.join(data)
+            elif self.pbtype in ['FIXED32', 'UINT32']:
+                inner_init = str(self.default) + 'u'
+            elif self.pbtype in ['FIXED64', 'UINT64']:
+                inner_init = str(self.default) + 'ull'
+            elif self.pbtype in ['SFIXED64', 'INT64']:
+                inner_init = str(self.default) + 'll'
+            elif self.pbtype in ['FLOAT', 'DOUBLE']:
+                inner_init = str(self.default)
+                if 'inf' in inner_init:
+                    inner_init = inner_init.replace('inf', 'INFINITY')
+                elif 'nan' in inner_init:
+                    inner_init = inner_init.replace('nan', 'NAN')
+                elif (not '.' in inner_init) and self.pbtype == 'FLOAT':
+                    inner_init += '.0f'
+                elif self.pbtype == 'FLOAT':
+                    inner_init += 'f'
+            else:
+                inner_init = str(self.default)
+
+        if inner_init_only:
+            return inner_init
+
+        outer_init = None
+        if self.allocation == 'STATIC':
+            if self.rules == 'REPEATED':
+                outer_init = '0, {' + ', '.join([inner_init] * self.max_count) + '}'
+            elif self.rules == 'FIXARRAY':
+                outer_init = '{' + ', '.join([inner_init] * self.max_count) + '}'
+            elif self.rules == 'OPTIONAL':
+                if null_init or not self.default_has:
+                    outer_init = 'false, ' + inner_init
+                else:
+                    outer_init = 'true, ' + inner_init
+            else:
+                outer_init = inner_init
+        elif self.allocation == 'POINTER':
+            if self.rules == 'REPEATED':
+                outer_init = '0, NULL'
+            else:
+                outer_init = 'NULL'
+        elif self.allocation == 'CALLBACK':
+            if self.pbtype == 'EXTENSION':
+                outer_init = 'NULL'
+            else:
+                outer_init = '{{NULL}, NULL}'
+
+        if self.pbtype == 'MSG_W_CB' and self.rules in ['REPEATED', 'OPTIONAL']:
+            outer_init = '{{NULL}, NULL}, ' + outer_init
+
+        return outer_init
+
+    def tags(self):
+        '''Return the #define for the tag number of this field.'''
+        identifier = '%s_%s_tag' % (self.struct_name, self.name)
+        return '#define %-40s %d\n' % (identifier, self.tag)
+
+    def fieldlist(self):
+        '''Return the FIELDLIST macro entry for this field.
+        Format is: X(a, ATYPE, HTYPE, LTYPE, field_name, tag)
+        '''
+        name = self.name
+
+        if self.rules == "ONEOF":
+          # For oneofs, make a tuple of the union name, union member name,
+          # and the name inside the parent struct.
+          if not self.anonymous:
+            name = '(%s,%s,%s)' % (self.union_name, self.name, self.union_name + '.' + self.name)
+          else:
+            name = '(%s,%s,%s)' % (self.union_name, self.name, self.name)
+
+        return '%s(%s, %-9s %-9s %-9s %-16s %3d)' % (self.macro_x_param,
+                                                     self.macro_a_param,
+                                                     self.allocation + ',',
+                                                     self.rules + ',',
+                                                     self.pbtype + ',',
+                                                     name + ',',
+                                                     self.tag)
+
+    def data_size(self, dependencies):
+        '''Return estimated size of this field in the C struct.
+        This is used to try to automatically pick right descriptor size.
+        If the estimate is wrong, it will result in compile time error and
+        user having to specify descriptor_width option.
+        '''
+        if self.allocation == 'POINTER' or self.pbtype == 'EXTENSION':
+            size = 8
+            alignment = 8
+        elif self.allocation == 'CALLBACK':
+            size = 16
+            alignment = 8
+        elif self.pbtype in ['MESSAGE', 'MSG_W_CB']:
+            alignment = 8
+            if str(self.submsgname) in dependencies:
+                other_dependencies = dict(x for x in dependencies.items() if x[0] != str(self.struct_name))
+                size = dependencies[str(self.submsgname)].data_size(other_dependencies)
+            else:
+                size = 256 # Message is in other file, this is reasonable guess for most cases
+
+            if self.pbtype == 'MSG_W_CB':
+                size += 16
+        elif self.pbtype in ['STRING', 'FIXED_LENGTH_BYTES']:
+            size = self.max_size
+            alignment = 4
+        elif self.pbtype == 'BYTES':
+            size = self.max_size + 4
+            alignment = 4
+        elif self.data_item_size is not None:
+            size = self.data_item_size
+            alignment = 4
+            if self.data_item_size >= 8:
+                alignment = 8
+        else:
+            raise Exception("Unhandled field type: %s" % self.pbtype)
+
+        if self.rules in ['REPEATED', 'FIXARRAY'] and self.allocation == 'STATIC':
+            size *= self.max_count
+
+        if self.rules not in ('REQUIRED', 'SINGULAR'):
+            size += 4
+
+        if size % alignment != 0:
+            # Estimate how much alignment requirements will increase the size.
+            size += alignment - (size % alignment)
+
+        return size
+
+    def encoded_size(self, dependencies):
+        '''Return the maximum size that this field can take when encoded,
+        including the field tag. If the size cannot be determined, returns
+        None.'''
+
+        if self.allocation != 'STATIC':
+            return None
+
+        if self.pbtype in ['MESSAGE', 'MSG_W_CB']:
+            encsize = None
+            if str(self.submsgname) in dependencies:
+                submsg = dependencies[str(self.submsgname)]
+                other_dependencies = dict(x for x in dependencies.items() if x[0] != str(self.struct_name))
+                encsize = submsg.encoded_size(other_dependencies)
+
+                my_msg = dependencies.get(str(self.struct_name))
+                external = (not my_msg or submsg.protofile != my_msg.protofile)
+
+                if encsize and encsize.symbols and external:
+                    # Couldn't fully resolve the size of a dependency from
+                    # another file. Instead of including the symbols directly,
+                    # just use the #define SubMessage_size from the header.
+                    encsize = None
+
+                if encsize is not None:
+                    # Include submessage length prefix
+                    encsize += varint_max_size(encsize.upperlimit())
+                elif not external:
+                    # The dependency is from the same file and size cannot be
+                    # determined for it, thus we know it will not be possible
+                    # in runtime either.
+                    return None
+
+            if encsize is None:
+                # Submessage or its size cannot be found.
+                # This can occur if submessage is defined in different
+                # file, and it or its .options could not be found.
+                # Instead of direct numeric value, reference the size that
+                # has been #defined in the other file.
+                encsize = EncodedSize(self.submsgname + 'size')
+
+                # We will have to make a conservative assumption on the length
+                # prefix size, though.
+                encsize += 5
+
+        elif self.pbtype in ['ENUM', 'UENUM']:
+            if str(self.ctype) in dependencies:
+                enumtype = dependencies[str(self.ctype)]
+                encsize = enumtype.encoded_size()
+            else:
+                # Conservative assumption
+                encsize = 10
+
+        elif self.enc_size is None:
+            raise RuntimeError("Could not determine encoded size for %s.%s"
+                               % (self.struct_name, self.name))
+        else:
+            encsize = EncodedSize(self.enc_size)
+
+        encsize += varint_max_size(self.tag << 3) # Tag + wire type
+
+        if self.rules in ['REPEATED', 'FIXARRAY']:
+            # Decoders must be always able to handle unpacked arrays.
+            # Therefore we have to reserve space for it, even though
+            # we emit packed arrays ourselves. For length of 1, packed
+            # arrays are larger however so we need to add allowance
+            # for the length byte.
+            encsize *= self.max_count
+
+            if self.max_count == 1:
+                encsize += 1
+
+        return encsize
+
+    def has_callbacks(self):
+        return self.allocation == 'CALLBACK'
+
+    def requires_custom_field_callback(self):
+        return self.allocation == 'CALLBACK' and self.callback_datatype != 'pb_callback_t'
+
+class ExtensionRange(Field):
+    def __init__(self, struct_name, range_start, field_options):
+        '''Implements a special pb_extension_t* field in an extensible message
+        structure. The range_start signifies the index at which the extensions
+        start. Not necessarily all tags above this are extensions, it is merely
+        a speed optimization.
+        '''
+        self.tag = range_start
+        self.struct_name = struct_name
+        self.name = 'extensions'
+        self.pbtype = 'EXTENSION'
+        self.rules = 'OPTIONAL'
+        self.allocation = 'CALLBACK'
+        self.ctype = 'pb_extension_t'
+        self.array_decl = ''
+        self.default = None
+        self.max_size = 0
+        self.max_count = 0
+        self.data_item_size = 0
+        self.fixed_count = False
+        self.callback_datatype = 'pb_extension_t*'
+
+    def requires_custom_field_callback(self):
+        return False
+
+    def __str__(self):
+        return '    pb_extension_t *extensions;'
+
+    def types(self):
+        return ''
+
+    def tags(self):
+        return ''
+
+    def encoded_size(self, dependencies):
+        # We exclude extensions from the count, because they cannot be known
+        # until runtime. Other option would be to return None here, but this
+        # way the value remains useful if extensions are not used.
+        return EncodedSize(0)
+
+class ExtensionField(Field):
+    def __init__(self, fullname, desc, field_options):
+        self.fullname = fullname
+        self.extendee_name = names_from_type_name(desc.extendee)
+        Field.__init__(self, self.fullname + "extmsg", desc, field_options)
+
+        if self.rules != 'OPTIONAL':
+            self.skip = True
+        else:
+            self.skip = False
+            self.rules = 'REQUIRED' # We don't really want the has_field for extensions
+            # currently no support for comments for extension fields => provide 0, {}
+            self.msg = Message(self.fullname + "extmsg", None, field_options, 0, {})
+            self.msg.fields.append(self)
+
+    def tags(self):
+        '''Return the #define for the tag number of this field.'''
+        identifier = '%s_tag' % self.fullname
+        return '#define %-40s %d\n' % (identifier, self.tag)
+
+    def extension_decl(self):
+        '''Declaration of the extension type in the .pb.h file'''
+        if self.skip:
+            msg = '/* Extension field %s was skipped because only "optional"\n' % self.fullname
+            msg +='   type of extension fields is currently supported. */\n'
+            return msg
+
+        return ('extern const pb_extension_type_t %s; /* field type: %s */\n' %
+            (self.fullname, str(self).strip()))
+
+    def extension_def(self, dependencies):
+        '''Definition of the extension type in the .pb.c file'''
+
+        if self.skip:
+            return ''
+
+        result = "/* Definition for extension field %s */\n" % self.fullname
+        result += str(self.msg)
+        result += self.msg.fields_declaration(dependencies)
+        result += 'pb_byte_t %s_default[] = {0x00};\n' % self.msg.name
+        result += self.msg.fields_definition(dependencies)
+        result += 'const pb_extension_type_t %s = {\n' % self.fullname
+        result += '    NULL,\n'
+        result += '    NULL,\n'
+        result += '    &%s_msg\n' % self.msg.name
+        result += '};\n'
+        return result
+
+
+# ---------------------------------------------------------------------------
+#                   Generation of oneofs (unions)
+# ---------------------------------------------------------------------------
+
+class OneOf(Field):
+    def __init__(self, struct_name, oneof_desc, oneof_options):
+        self.struct_name = struct_name
+        self.name = oneof_desc.name
+        self.ctype = 'union'
+        self.pbtype = 'oneof'
+        self.fields = []
+        self.allocation = 'ONEOF'
+        self.default = None
+        self.rules = 'ONEOF'
+        self.anonymous = oneof_options.anonymous_oneof
+        self.sort_by_tag = oneof_options.sort_by_tag
+        self.has_msg_cb = False
+
+    def add_field(self, field):
+        field.union_name = self.name
+        field.rules = 'ONEOF'
+        field.anonymous = self.anonymous
+        self.fields.append(field)
+
+        if self.sort_by_tag:
+            self.fields.sort()
+
+        if field.pbtype == 'MSG_W_CB':
+            self.has_msg_cb = True
+
+        # Sort by the lowest tag number inside union
+        self.tag = min([f.tag for f in self.fields])
+
+    def __str__(self):
+        result = ''
+        if self.fields:
+            if self.has_msg_cb:
+                result += '    pb_callback_t cb_' + self.name + ';\n'
+
+            result += '    pb_size_t which_' + self.name + ";\n"
+            result += '    union {\n'
+            for f in self.fields:
+                result += '    ' + str(f).replace('\n', '\n    ') + '\n'
+            if self.anonymous:
+                result += '    };'
+            else:
+                result += '    } ' + self.name + ';'
+        return result
+
+    def types(self):
+        return ''.join([f.types() for f in self.fields])
+
+    def get_dependencies(self):
+        deps = []
+        for f in self.fields:
+            deps += f.get_dependencies()
+        return deps
+
+    def get_initializer(self, null_init):
+        if self.has_msg_cb:
+            return '{{NULL}, NULL}, 0, {' + self.fields[0].get_initializer(null_init) + '}'
+        else:
+            return '0, {' + self.fields[0].get_initializer(null_init) + '}'
+
+    def tags(self):
+        return ''.join([f.tags() for f in self.fields])
+
+    def data_size(self, dependencies):
+        return max(f.data_size(dependencies) for f in self.fields)
+
+    def encoded_size(self, dependencies):
+        '''Returns the size of the largest oneof field.'''
+        largest = 0
+        dynamic_sizes = {}
+        for f in self.fields:
+            size = EncodedSize(f.encoded_size(dependencies))
+            if size is None or size.value is None:
+                return None
+            elif size.symbols:
+                dynamic_sizes[f.tag] = size
+            elif size.value > largest:
+                largest = size.value
+
+        if not dynamic_sizes:
+            # Simple case, all sizes were known at generator time
+            return EncodedSize(largest)
+
+        if largest > 0:
+            # Some sizes were known, some were not
+            dynamic_sizes[0] = EncodedSize(largest)
+
+        # Couldn't find size for submessage at generation time,
+        # have to rely on macro resolution at compile time.
+        if len(dynamic_sizes) == 1:
+            # Only one symbol was needed
+            return list(dynamic_sizes.values())[0]
+        else:
+            # Use sizeof(union{}) construct to find the maximum size of
+            # submessages.
+            union_name = "%s_%s_size_union" % (self.struct_name, self.name)
+            union_def = 'union %s {%s};\n' % (union_name, ' '.join('char f%d[%s];' % (k, s) for k,s in dynamic_sizes.items()))
+            required_defs = list(itertools.chain.from_iterable(s.required_defines for k,s in dynamic_sizes.items()))
+            return EncodedSize(0, ['sizeof(union %s)' % union_name], [union_def], required_defs)
+
+    def has_callbacks(self):
+        return bool([f for f in self.fields if f.has_callbacks()])
+
+    def requires_custom_field_callback(self):
+        return bool([f for f in self.fields if f.requires_custom_field_callback()])
+
+# ---------------------------------------------------------------------------
+#                   Generation of messages (structures)
+# ---------------------------------------------------------------------------
+
+
+class Message(ProtoElement):
+    def __init__(self, names, desc, message_options, index, comments):
+        super(Message, self).__init__(MESSAGE_PATH, index, comments)
+        self.name = names
+        self.fields = []
+        self.oneofs = {}
+        self.desc = desc
+        self.math_include_required = False
+        self.packed = message_options.packed_struct
+        self.descriptorsize = message_options.descriptorsize
+
+        if message_options.msgid:
+            self.msgid = message_options.msgid
+
+        if desc is not None:
+            self.load_fields(desc, message_options)
+
+        self.callback_function = message_options.callback_function
+        if not message_options.HasField('callback_function'):
+            # Automatically assign a per-message callback if any field has
+            # a special callback_datatype.
+            for field in self.fields:
+                if field.requires_custom_field_callback():
+                    self.callback_function = "%s_callback" % self.name
+                    break
+
+    def load_fields(self, desc, message_options):
+        '''Load field list from DescriptorProto'''
+
+        no_unions = []
+
+        if hasattr(desc, 'oneof_decl'):
+            for i, f in enumerate(desc.oneof_decl):
+                oneof_options = get_nanopb_suboptions(desc, message_options, self.name + f.name)
+                if oneof_options.no_unions:
+                    no_unions.append(i) # No union, but add fields normally
+                elif oneof_options.type == nanopb_pb2.FT_IGNORE:
+                    pass # No union and skip fields also
+                else:
+                    oneof = OneOf(self.name, f, oneof_options)
+                    self.oneofs[i] = oneof
+        else:
+            sys.stderr.write('Note: This Python protobuf library has no OneOf support\n')
+
+        for f in desc.field:
+            field_options = get_nanopb_suboptions(f, message_options, self.name + f.name)
+            if field_options.type == nanopb_pb2.FT_IGNORE:
+                continue
+
+            if field_options.descriptorsize > self.descriptorsize:
+                self.descriptorsize = field_options.descriptorsize
+
+            field = Field(self.name, f, field_options)
+            if hasattr(f, 'oneof_index') and f.HasField('oneof_index'):
+                if hasattr(f, 'proto3_optional') and f.proto3_optional:
+                    no_unions.append(f.oneof_index)
+
+                if f.oneof_index in no_unions:
+                    self.fields.append(field)
+                elif f.oneof_index in self.oneofs:
+                    self.oneofs[f.oneof_index].add_field(field)
+
+                    if self.oneofs[f.oneof_index] not in self.fields:
+                        self.fields.append(self.oneofs[f.oneof_index])
+            else:
+                self.fields.append(field)
+
+            if field.math_include_required:
+                self.math_include_required = True
+
+        if len(desc.extension_range) > 0:
+            field_options = get_nanopb_suboptions(desc, message_options, self.name + 'extensions')
+            range_start = min([r.start for r in desc.extension_range])
+            if field_options.type != nanopb_pb2.FT_IGNORE:
+                self.fields.append(ExtensionRange(self.name, range_start, field_options))
+
+        if message_options.sort_by_tag:
+            self.fields.sort()
+
+    def get_dependencies(self):
+        '''Get list of type names that this structure refers to.'''
+        deps = []
+        for f in self.fields:
+            deps += f.get_dependencies()
+        return deps
+
+    def __str__(self):
+        message_path = self.element_path()
+        leading_comment, trailing_comment = self.get_comments(message_path, leading_indent=False)
+
+        result = ''
+        if leading_comment:
+            result = '%s\n' % leading_comment
+
+        result += 'typedef struct _%s { %s\n' % (self.name, trailing_comment)
+
+        if not self.fields:
+            # Empty structs are not allowed in C standard.
+            # Therefore add a dummy field if an empty message occurs.
+            result += '    char dummy_field;'
+
+        msg_fields = []
+        for index, field in enumerate(self.fields):
+            member_path = self.member_path(index)
+            leading_comment, trailing_comment = self.get_comments(member_path)
+
+            if leading_comment:
+                msg_fields.append(leading_comment)
+
+            msg_fields.append("%s %s" % (str(field), trailing_comment))
+
+        result += '\n'.join(msg_fields)
+
+        if Globals.protoc_insertion_points:
+            result += '\n/* @@protoc_insertion_point(struct:%s) */' % self.name
+
+        result += '\n}'
+
+        if self.packed:
+            result += ' pb_packed'
+
+        result += ' %s;' % self.name
+
+        if self.packed:
+            result = 'PB_PACKED_STRUCT_START\n' + result
+            result += '\nPB_PACKED_STRUCT_END'
+
+        return result + '\n'
+
+    def types(self):
+        return ''.join([f.types() for f in self.fields])
+
+    def get_initializer(self, null_init):
+        if not self.fields:
+            return '{0}'
+
+        parts = []
+        for field in self.fields:
+            parts.append(field.get_initializer(null_init))
+        return '{' + ', '.join(parts) + '}'
+
+    def count_required_fields(self):
+        '''Returns number of required fields inside this message'''
+        count = 0
+        for f in self.fields:
+            if not isinstance(f, OneOf):
+                if f.rules == 'REQUIRED':
+                    count += 1
+        return count
+
+    def all_fields(self):
+        '''Iterate over all fields in this message, including nested OneOfs.'''
+        for f in self.fields:
+            if isinstance(f, OneOf):
+                for f2 in f.fields:
+                    yield f2
+            else:
+                yield f
+
+
+    def field_for_tag(self, tag):
+        '''Given a tag number, return the Field instance.'''
+        for field in self.all_fields():
+            if field.tag == tag:
+                return field
+        return None
+
+    def count_all_fields(self):
+        '''Count the total number of fields in this message.'''
+        count = 0
+        for f in self.fields:
+            if isinstance(f, OneOf):
+                count += len(f.fields)
+            else:
+                count += 1
+        return count
+
+    def fields_declaration(self, dependencies):
+        '''Return X-macro declaration of all fields in this message.'''
+        Field.macro_x_param = 'X'
+        Field.macro_a_param = 'a'
+        while any(field.name == Field.macro_x_param for field in self.all_fields()):
+            Field.macro_x_param += '_'
+        while any(field.name == Field.macro_a_param for field in self.all_fields()):
+            Field.macro_a_param += '_'
+
+        # Field descriptor array must be sorted by tag number, pb_common.c relies on it.
+        sorted_fields = list(self.all_fields())
+        sorted_fields.sort(key = lambda x: x.tag)
+
+        result = '#define %s_FIELDLIST(%s, %s) \\\n' % (self.name,
+                                                        Field.macro_x_param,
+                                                        Field.macro_a_param)
+        result += ' \\\n'.join(x.fieldlist() for x in sorted_fields)
+        result += '\n'
+
+        has_callbacks = bool([f for f in self.fields if f.has_callbacks()])
+        if has_callbacks:
+            if self.callback_function != 'pb_default_field_callback':
+                result += "extern bool %s(pb_istream_t *istream, pb_ostream_t *ostream, const pb_field_t *field);\n" % self.callback_function
+            result += "#define %s_CALLBACK %s\n" % (self.name, self.callback_function)
+        else:
+            result += "#define %s_CALLBACK NULL\n" % self.name
+
+        defval = self.default_value(dependencies)
+        if defval:
+            hexcoded = ''.join("\\x%02x" % ord(defval[i:i+1]) for i in range(len(defval)))
+            result += '#define %s_DEFAULT (const pb_byte_t*)"%s\\x00"\n' % (self.name, hexcoded)
+        else:
+            result += '#define %s_DEFAULT NULL\n' % self.name
+
+        for field in sorted_fields:
+            if field.pbtype in ['MESSAGE', 'MSG_W_CB']:
+                if field.rules == 'ONEOF':
+                    result += "#define %s_%s_%s_MSGTYPE %s\n" % (self.name, field.union_name, field.name, field.ctype)
+                else:
+                    result += "#define %s_%s_MSGTYPE %s\n" % (self.name, field.name, field.ctype)
+
+        return result
+
+    def fields_declaration_cpp_lookup(self):
+        result = 'template <>\n'
+        result += 'struct MessageDescriptor<%s> {\n' % (self.name)
+        result += '    static PB_INLINE_CONSTEXPR const pb_size_t fields_array_length = %d;\n' % (self.count_all_fields())
+        result += '    static inline const pb_msgdesc_t* fields() {\n'
+        result += '        return &%s_msg;\n' % (self.name)
+        result += '    }\n'
+        result += '};'
+        return result
+
+    def fields_definition(self, dependencies):
+        '''Return the field descriptor definition that goes in .pb.c file.'''
+        width = self.required_descriptor_width(dependencies)
+        if width == 1:
+          width = 'AUTO'
+
+        result = 'PB_BIND(%s, %s, %s)\n' % (self.name, self.name, width)
+        return result
+
+    def required_descriptor_width(self, dependencies):
+        '''Estimate how many words are necessary for each field descriptor.'''
+        if self.descriptorsize != nanopb_pb2.DS_AUTO:
+            return int(self.descriptorsize)
+
+        if not self.fields:
+          return 1
+
+        max_tag = max(field.tag for field in self.all_fields())
+        max_offset = self.data_size(dependencies)
+        max_arraysize = max((field.max_count or 0) for field in self.all_fields())
+        max_datasize = max(field.data_size(dependencies) for field in self.all_fields())
+
+        if max_arraysize > 0xFFFF:
+            return 8
+        elif (max_tag > 0x3FF or max_offset > 0xFFFF or
+              max_arraysize > 0x0FFF or max_datasize > 0x0FFF):
+            return 4
+        elif max_tag > 0x3F or max_offset > 0xFF:
+            return 2
+        else:
+            # NOTE: Macro logic in pb.h ensures that width 1 will
+            # be raised to 2 automatically for string/submsg fields
+            # and repeated fields. Thus only tag and offset need to
+            # be checked.
+            return 1
+
+    def data_size(self, dependencies):
+        '''Return approximate sizeof(struct) in the compiled code.'''
+        return sum(f.data_size(dependencies) for f in self.fields)
+
+    def encoded_size(self, dependencies):
+        '''Return the maximum size that this message can take when encoded.
+        If the size cannot be determined, returns None.
+        '''
+        size = EncodedSize(0)
+        for field in self.fields:
+            fsize = field.encoded_size(dependencies)
+            if fsize is None:
+                return None
+            size += fsize
+
+        return size
+
+    def default_value(self, dependencies):
+        '''Generate serialized protobuf message that contains the
+        default values for optional fields.'''
+
+        if not self.desc:
+            return b''
+
+        if self.desc.options.map_entry:
+            return b''
+
+        optional_only = copy.deepcopy(self.desc)
+
+        # Remove fields without default values
+        # The iteration is done in reverse order to avoid remove() messing up iteration.
+        for field in reversed(list(optional_only.field)):
+            field.ClearField(str('extendee'))
+            parsed_field = self.field_for_tag(field.number)
+            if parsed_field is None or parsed_field.allocation != 'STATIC':
+                optional_only.field.remove(field)
+            elif (field.label == FieldD.LABEL_REPEATED or
+                  field.type == FieldD.TYPE_MESSAGE):
+                optional_only.field.remove(field)
+            elif hasattr(field, 'oneof_index') and field.HasField('oneof_index'):
+                optional_only.field.remove(field)
+            elif field.type == FieldD.TYPE_ENUM:
+                # The partial descriptor doesn't include the enum type
+                # so we fake it with int64.
+                enumname = names_from_type_name(field.type_name)
+                try:
+                    enumtype = dependencies[str(enumname)]
+                except KeyError:
+                    raise Exception("Could not find enum type %s while generating default values for %s.\n" % (enumname, self.name)
+                                    + "Try passing all source files to generator at once, or use -I option.")
+
+                if field.HasField('default_value'):
+                    defvals = [v for n,v in enumtype.values if n.parts[-1] == field.default_value]
+                else:
+                    # If no default is specified, the default is the first value.
+                    defvals = [v for n,v in enumtype.values]
+                if defvals and defvals[0] != 0:
+                    field.type = FieldD.TYPE_INT64
+                    field.default_value = str(defvals[0])
+                    field.ClearField(str('type_name'))
+                else:
+                    optional_only.field.remove(field)
+            elif not field.HasField('default_value'):
+                optional_only.field.remove(field)
+
+        if len(optional_only.field) == 0:
+            return b''
+
+        optional_only.ClearField(str('oneof_decl'))
+        optional_only.ClearField(str('nested_type'))
+        optional_only.ClearField(str('extension'))
+        optional_only.ClearField(str('enum_type'))
+        desc = google.protobuf.descriptor.MakeDescriptor(optional_only)
+        msg = reflection.MakeClass(desc)()
+
+        for field in optional_only.field:
+            if field.type == FieldD.TYPE_STRING:
+                setattr(msg, field.name, field.default_value)
+            elif field.type == FieldD.TYPE_BYTES:
+                setattr(msg, field.name, codecs.escape_decode(field.default_value)[0])
+            elif field.type in [FieldD.TYPE_FLOAT, FieldD.TYPE_DOUBLE]:
+                setattr(msg, field.name, float(field.default_value))
+            elif field.type == FieldD.TYPE_BOOL:
+                setattr(msg, field.name, field.default_value == 'true')
+            else:
+                setattr(msg, field.name, int(field.default_value))
+
+        return msg.SerializeToString()
+
+
+# ---------------------------------------------------------------------------
+#                    Processing of entire .proto files
+# ---------------------------------------------------------------------------
+
+def iterate_messages(desc, flatten = False, names = Names()):
+    '''Recursively find all messages. For each, yield name, DescriptorProto.'''
+    if hasattr(desc, 'message_type'):
+        submsgs = desc.message_type
+    else:
+        submsgs = desc.nested_type
+
+    for submsg in submsgs:
+        sub_names = names + submsg.name
+        if flatten:
+            yield Names(submsg.name), submsg
+        else:
+            yield sub_names, submsg
+
+        for x in iterate_messages(submsg, flatten, sub_names):
+            yield x
+
+def iterate_extensions(desc, flatten = False, names = Names()):
+    '''Recursively find all extensions.
+    For each, yield name, FieldDescriptorProto.
+    '''
+    for extension in desc.extension:
+        yield names, extension
+
+    for subname, subdesc in iterate_messages(desc, flatten, names):
+        for extension in subdesc.extension:
+            yield subname, extension
+
+def toposort2(data):
+    '''Topological sort.
+    From http://code.activestate.com/recipes/577413-topological-sort/
+    This function is under the MIT license.
+    '''
+    for k, v in list(data.items()):
+        v.discard(k) # Ignore self dependencies
+    extra_items_in_deps = reduce(set.union, list(data.values()), set()) - set(data.keys())
+    data.update(dict([(item, set()) for item in extra_items_in_deps]))
+    while True:
+        ordered = set(item for item,dep in list(data.items()) if not dep)
+        if not ordered:
+            break
+        for item in sorted(ordered):
+            yield item
+        data = dict([(item, (dep - ordered)) for item,dep in list(data.items())
+                if item not in ordered])
+    assert not data, "A cyclic dependency exists amongst %r" % data
+
+def sort_dependencies(messages):
+    '''Sort a list of Messages based on dependencies.'''
+    dependencies = {}
+    message_by_name = {}
+    for message in messages:
+        dependencies[str(message.name)] = set(message.get_dependencies())
+        message_by_name[str(message.name)] = message
+
+    for msgname in toposort2(dependencies):
+        if msgname in message_by_name:
+            yield message_by_name[msgname]
+
+def make_identifier(headername):
+    '''Make #ifndef identifier that contains uppercase A-Z and digits 0-9'''
+    result = ""
+    for c in headername.upper():
+        if c.isalnum():
+            result += c
+        else:
+            result += '_'
+    return result
+
+class ProtoFile:
+    def __init__(self, fdesc, file_options):
+        '''Takes a FileDescriptorProto and parses it.'''
+        self.fdesc = fdesc
+        self.file_options = file_options
+        self.dependencies = {}
+        self.math_include_required = False
+        self.parse()
+        for message in self.messages:
+            if message.math_include_required:
+                self.math_include_required = True
+                break
+
+        # Some of types used in this file probably come from the file itself.
+        # Thus it has implicit dependency on itself.
+        self.add_dependency(self)
+
+    def parse(self):
+        self.enums = []
+        self.messages = []
+        self.extensions = []
+
+        mangle_names = self.file_options.mangle_names
+        flatten = mangle_names == nanopb_pb2.M_FLATTEN
+        strip_prefix = None
+        replacement_prefix = None
+        if mangle_names == nanopb_pb2.M_STRIP_PACKAGE:
+            strip_prefix = "." + self.fdesc.package
+        elif mangle_names == nanopb_pb2.M_PACKAGE_INITIALS:
+            strip_prefix = "." + self.fdesc.package
+            replacement_prefix = ""
+            for part in self.fdesc.package.split("."):
+                replacement_prefix += part[0]
+        elif self.file_options.package:
+            strip_prefix = "." + self.fdesc.package
+            replacement_prefix = self.file_options.package
+
+
+        def create_name(names):
+            if mangle_names in (nanopb_pb2.M_NONE, nanopb_pb2.M_PACKAGE_INITIALS):
+                return base_name + names
+            if mangle_names == nanopb_pb2.M_STRIP_PACKAGE:
+                return Names(names)
+            single_name = names
+            if isinstance(names, Names):
+                single_name = names.parts[-1]
+            return Names(single_name)
+
+        def mangle_field_typename(typename):
+            if mangle_names == nanopb_pb2.M_FLATTEN:
+                return "." + typename.split(".")[-1]
+            if strip_prefix is not None and typename.startswith(strip_prefix):
+                if replacement_prefix is not None:
+                    return "." + replacement_prefix + typename[len(strip_prefix):]
+                else:
+                    return typename[len(strip_prefix):]
+            if self.file_options.package:
+                return "." + replacement_prefix + typename
+            return typename
+
+        if replacement_prefix is not None:
+            base_name = Names(replacement_prefix.split('.'))
+        elif self.fdesc.package:
+            base_name = Names(self.fdesc.package.split('.'))
+        else:
+            base_name = Names()
+
+        # process source code comment locations
+        # ignores any locations that do not contain any comment information
+        self.comment_locations = {
+            str(list(location.path)): location
+            for location in self.fdesc.source_code_info.location
+            if location.leading_comments or location.leading_detached_comments or location.trailing_comments
+        }
+
+        for index, enum in enumerate(self.fdesc.enum_type):
+            name = create_name(enum.name)
+            enum_options = get_nanopb_suboptions(enum, self.file_options, name)
+            self.enums.append(Enum(name, enum, enum_options, index, self.comment_locations))
+
+        for index, (names, message) in enumerate(iterate_messages(self.fdesc, flatten)):
+            name = create_name(names)
+            message_options = get_nanopb_suboptions(message, self.file_options, name)
+
+            if message_options.skip_message:
+                continue
+
+            message = copy.deepcopy(message)
+            for field in message.field:
+                if field.type in (FieldD.TYPE_MESSAGE, FieldD.TYPE_ENUM):
+                    field.type_name = mangle_field_typename(field.type_name)
+
+            self.messages.append(Message(name, message, message_options, index, self.comment_locations))
+            for index, enum in enumerate(message.enum_type):
+                name = create_name(names + enum.name)
+                enum_options = get_nanopb_suboptions(enum, message_options, name)
+                self.enums.append(Enum(name, enum, enum_options, index, self.comment_locations))
+
+        for names, extension in iterate_extensions(self.fdesc, flatten):
+            name = create_name(names + extension.name)
+            field_options = get_nanopb_suboptions(extension, self.file_options, name)
+
+            extension = copy.deepcopy(extension)
+            if extension.type in (FieldD.TYPE_MESSAGE, FieldD.TYPE_ENUM):
+                extension.type_name = mangle_field_typename(extension.type_name)
+
+            if field_options.type != nanopb_pb2.FT_IGNORE:
+                self.extensions.append(ExtensionField(name, extension, field_options))
+
+    def add_dependency(self, other):
+        for enum in other.enums:
+            self.dependencies[str(enum.names)] = enum
+            enum.protofile = other
+
+        for msg in other.messages:
+            self.dependencies[str(msg.name)] = msg
+            msg.protofile = other
+
+        # Fix field default values where enum short names are used.
+        for enum in other.enums:
+            if not enum.options.long_names:
+                for message in self.messages:
+                    for field in message.all_fields():
+                        if field.default in enum.value_longnames:
+                            idx = enum.value_longnames.index(field.default)
+                            field.default = enum.values[idx][0]
+
+        # Fix field data types where enums have negative values.
+        for enum in other.enums:
+            if not enum.has_negative():
+                for message in self.messages:
+                    for field in message.all_fields():
+                        if field.pbtype == 'ENUM' and field.ctype == enum.names:
+                            field.pbtype = 'UENUM'
+
+    def generate_header(self, includes, headername, options):
+        '''Generate content for a header file.
+        Generates strings, which should be concatenated and stored to file.
+        '''
+
+        yield '/* Automatically generated nanopb header */\n'
+        if options.notimestamp:
+            yield '/* Generated by %s */\n\n' % (nanopb_version)
+        else:
+            yield '/* Generated by %s at %s. */\n\n' % (nanopb_version, time.asctime())
+
+        if self.fdesc.package:
+            symbol = make_identifier(self.fdesc.package + '_' + headername)
+        else:
+            symbol = make_identifier(headername)
+        yield '#ifndef PB_%s_INCLUDED\n' % symbol
+        yield '#define PB_%s_INCLUDED\n' % symbol
+        if self.math_include_required:
+            yield '#include <math.h>\n'
+        try:
+            yield options.libformat % ('pb.h')
+        except TypeError:
+            # no %s specified - use whatever was passed in as options.libformat
+            yield options.libformat
+        yield '\n'
+
+        for incfile in self.file_options.include:
+            # allow including system headers
+            if (incfile.startswith('<')):
+                yield '#include %s\n' % incfile
+            else:
+                yield options.genformat % incfile
+                yield '\n'
+
+        for incfile in includes:
+            noext = os.path.splitext(incfile)[0]
+            yield options.genformat % (noext + options.extension + options.header_extension)
+            yield '\n'
+
+        if Globals.protoc_insertion_points:
+            yield '/* @@protoc_insertion_point(includes) */\n'
+
+        yield '\n'
+
+        yield '#if PB_PROTO_HEADER_VERSION != 40\n'
+        yield '#error Regenerate this file with the current version of nanopb generator.\n'
+        yield '#endif\n'
+        yield '\n'
+
+        if self.enums:
+            yield '/* Enum definitions */\n'
+            for enum in self.enums:
+                yield str(enum) + '\n\n'
+
+        if self.messages:
+            yield '/* Struct definitions */\n'
+            for msg in sort_dependencies(self.messages):
+                yield msg.types()
+                yield str(msg) + '\n'
+            yield '\n'
+
+        if self.extensions:
+            yield '/* Extensions */\n'
+            for extension in self.extensions:
+                yield extension.extension_decl()
+            yield '\n'
+
+        if self.enums:
+                yield '/* Helper constants for enums */\n'
+                for enum in self.enums:
+                    yield enum.auxiliary_defines() + '\n'
+                yield '\n'
+
+        yield '#ifdef __cplusplus\n'
+        yield 'extern "C" {\n'
+        yield '#endif\n\n'
+
+        if self.messages:
+            yield '/* Initializer values for message structs */\n'
+            for msg in self.messages:
+                identifier = '%s_init_default' % msg.name
+                yield '#define %-40s %s\n' % (identifier, msg.get_initializer(False))
+            for msg in self.messages:
+                identifier = '%s_init_zero' % msg.name
+                yield '#define %-40s %s\n' % (identifier, msg.get_initializer(True))
+            yield '\n'
+
+            yield '/* Field tags (for use in manual encoding/decoding) */\n'
+            for msg in sort_dependencies(self.messages):
+                for field in msg.fields:
+                    yield field.tags()
+            for extension in self.extensions:
+                yield extension.tags()
+            yield '\n'
+
+            yield '/* Struct field encoding specification for nanopb */\n'
+            for msg in self.messages:
+                yield msg.fields_declaration(self.dependencies) + '\n'
+            for msg in self.messages:
+                yield 'extern const pb_msgdesc_t %s_msg;\n' % msg.name
+            yield '\n'
+
+            yield '/* Defines for backwards compatibility with code written before nanopb-0.4.0 */\n'
+            for msg in self.messages:
+              yield '#define %s_fields &%s_msg\n' % (msg.name, msg.name)
+            yield '\n'
+
+            yield '/* Maximum encoded size of messages (where known) */\n'
+            messagesizes = []
+            for msg in self.messages:
+                identifier = '%s_size' % msg.name
+                messagesizes.append((identifier, msg.encoded_size(self.dependencies)))
+
+            # If we require a symbol from another file, put a preprocessor if statement
+            # around it to prevent compilation errors if the symbol is not actually available.
+            local_defines = [identifier for identifier, msize in messagesizes if msize is not None]
+
+            # emit size_unions, if any
+            oneof_sizes = []
+            for msg in self.messages:
+                for f in msg.fields:
+                    if isinstance(f, OneOf):
+                        msize = f.encoded_size(self.dependencies)
+                        if msize is not None:
+                            oneof_sizes.append(msize)
+            for msize in oneof_sizes:
+                guard = msize.get_cpp_guard(local_defines)
+                if guard:
+                    yield guard
+                yield msize.get_declarations()
+                if guard:
+                    yield '#endif\n'
+
+            guards = {}
+            for identifier, msize in messagesizes:
+                if msize is not None:
+                    cpp_guard = msize.get_cpp_guard(local_defines)
+                    if cpp_guard not in guards:
+                        guards[cpp_guard] = set()
+                    guards[cpp_guard].add('#define %-40s %s' % (identifier, msize))
+                else:
+                    yield '/* %s depends on runtime parameters */\n' % identifier
+            for guard, values in guards.items():
+                if guard:
+                    yield guard
+                for v in sorted(values):
+                    yield v
+                    yield '\n'
+                if guard:
+                    yield '#endif\n'
+            yield '\n'
+
+            if [msg for msg in self.messages if hasattr(msg,'msgid')]:
+              yield '/* Message IDs (where set with "msgid" option) */\n'
+              for msg in self.messages:
+                  if hasattr(msg,'msgid'):
+                      yield '#define PB_MSG_%d %s\n' % (msg.msgid, msg.name)
+              yield '\n'
+
+              symbol = make_identifier(headername.split('.')[0])
+              yield '#define %s_MESSAGES \\\n' % symbol
+
+              for msg in self.messages:
+                  m = "-1"
+                  msize = msg.encoded_size(self.dependencies)
+                  if msize is not None:
+                      m = msize
+                  if hasattr(msg,'msgid'):
+                      yield '\tPB_MSG(%d,%s,%s) \\\n' % (msg.msgid, m, msg.name)
+              yield '\n'
+
+              for msg in self.messages:
+                  if hasattr(msg,'msgid'):
+                      yield '#define %s_msgid %d\n' % (msg.name, msg.msgid)
+              yield '\n'
+
+        yield '#ifdef __cplusplus\n'
+        yield '} /* extern "C" */\n'
+        yield '#endif\n'
+
+        if options.cpp_descriptors:
+            yield '\n'
+            yield '#ifdef __cplusplus\n'
+            yield '/* Message descriptors for nanopb */\n'
+            yield 'namespace nanopb {\n'
+            for msg in self.messages:
+                yield msg.fields_declaration_cpp_lookup() + '\n'
+            yield '}  // namespace nanopb\n'
+            yield '\n'
+            yield '#endif  /* __cplusplus */\n'
+            yield '\n'
+
+        if Globals.protoc_insertion_points:
+            yield '/* @@protoc_insertion_point(eof) */\n'
+
+        # End of header
+        yield '\n#endif\n'
+
+    def generate_source(self, headername, options):
+        '''Generate content for a source file.'''
+
+        yield '/* Automatically generated nanopb constant definitions */\n'
+        if options.notimestamp:
+            yield '/* Generated by %s */\n\n' % (nanopb_version)
+        else:
+            yield '/* Generated by %s at %s. */\n\n' % (nanopb_version, time.asctime())
+        yield options.genformat % (headername)
+        yield '\n'
+
+        if Globals.protoc_insertion_points:
+            yield '/* @@protoc_insertion_point(includes) */\n'
+
+        yield '#if PB_PROTO_HEADER_VERSION != 40\n'
+        yield '#error Regenerate this file with the current version of nanopb generator.\n'
+        yield '#endif\n'
+        yield '\n'
+
+        for msg in self.messages:
+            yield msg.fields_definition(self.dependencies) + '\n\n'
+
+        for ext in self.extensions:
+            yield ext.extension_def(self.dependencies) + '\n'
+
+        for enum in self.enums:
+            yield enum.enum_to_string_definition() + '\n'
+
+        # Add checks for numeric limits
+        if self.messages:
+            largest_msg = max(self.messages, key = lambda m: m.count_required_fields())
+            largest_count = largest_msg.count_required_fields()
+            if largest_count > 64:
+                yield '\n/* Check that missing required fields will be properly detected */\n'
+                yield '#if PB_MAX_REQUIRED_FIELDS < %d\n' % largest_count
+                yield '#error Properly detecting missing required fields in %s requires \\\n' % largest_msg.name
+                yield '       setting PB_MAX_REQUIRED_FIELDS to %d or more.\n' % largest_count
+                yield '#endif\n'
+
+        # Add check for sizeof(double)
+        has_double = False
+        for msg in self.messages:
+            for field in msg.all_fields():
+                if field.ctype == 'double':
+                    has_double = True
+
+        if has_double:
+            yield '\n'
+            yield '#ifndef PB_CONVERT_DOUBLE_FLOAT\n'
+            yield '/* On some platforms (such as AVR), double is really float.\n'
+            yield ' * To be able to encode/decode double on these platforms, you need.\n'
+            yield ' * to define PB_CONVERT_DOUBLE_FLOAT in pb.h or compiler command line.\n'
+            yield ' */\n'
+            yield 'PB_STATIC_ASSERT(sizeof(double) == 8, DOUBLE_MUST_BE_8_BYTES)\n'
+            yield '#endif\n'
+
+        yield '\n'
+
+        if Globals.protoc_insertion_points:
+            yield '/* @@protoc_insertion_point(eof) */\n'
+
+# ---------------------------------------------------------------------------
+#                    Options parsing for the .proto files
+# ---------------------------------------------------------------------------
+
+from fnmatch import fnmatchcase
+
+def read_options_file(infile):
+    '''Parse a separate options file to list:
+        [(namemask, options), ...]
+    '''
+    results = []
+    data = infile.read()
+    data = re.sub(r'/\*.*?\*/', '', data, flags = re.MULTILINE)
+    data = re.sub(r'//.*?$', '', data, flags = re.MULTILINE)
+    data = re.sub(r'#.*?$', '', data, flags = re.MULTILINE)
+    for i, line in enumerate(data.split('\n')):
+        line = line.strip()
+        if not line:
+            continue
+
+        parts = line.split(None, 1)
+
+        if len(parts) < 2:
+            sys.stderr.write("%s:%d: " % (infile.name, i + 1) +
+                             "Option lines should have space between field name and options. " +
+                             "Skipping line: '%s'\n" % line)
+            sys.exit(1)
+
+        opts = nanopb_pb2.NanoPBOptions()
+
+        try:
+            text_format.Merge(parts[1], opts)
+        except Exception as e:
+            sys.stderr.write("%s:%d: " % (infile.name, i + 1) +
+                             "Unparsable option line: '%s'. " % line +
+                             "Error: %s\n" % str(e))
+            sys.exit(1)
+        results.append((parts[0], opts))
+
+    return results
+
+def get_nanopb_suboptions(subdesc, options, name):
+    '''Get copy of options, and merge information from subdesc.'''
+    new_options = nanopb_pb2.NanoPBOptions()
+    new_options.CopyFrom(options)
+
+    if hasattr(subdesc, 'syntax') and subdesc.syntax == "proto3":
+        new_options.proto3 = True
+
+    # Handle options defined in a separate file
+    dotname = '.'.join(name.parts)
+    for namemask, options in Globals.separate_options:
+        if fnmatchcase(dotname, namemask):
+            Globals.matched_namemasks.add(namemask)
+            new_options.MergeFrom(options)
+
+    # Handle options defined in .proto
+    if isinstance(subdesc.options, descriptor.FieldOptions):
+        ext_type = nanopb_pb2.nanopb
+    elif isinstance(subdesc.options, descriptor.FileOptions):
+        ext_type = nanopb_pb2.nanopb_fileopt
+    elif isinstance(subdesc.options, descriptor.MessageOptions):
+        ext_type = nanopb_pb2.nanopb_msgopt
+    elif isinstance(subdesc.options, descriptor.EnumOptions):
+        ext_type = nanopb_pb2.nanopb_enumopt
+    else:
+        raise Exception("Unknown options type")
+
+    if subdesc.options.HasExtension(ext_type):
+        ext = subdesc.options.Extensions[ext_type]
+        new_options.MergeFrom(ext)
+
+    if Globals.verbose_options:
+        sys.stderr.write("Options for " + dotname + ": ")
+        sys.stderr.write(text_format.MessageToString(new_options) + "\n")
+
+    return new_options
+
+
+# ---------------------------------------------------------------------------
+#                         Command line interface
+# ---------------------------------------------------------------------------
+
+import sys
+import os.path
+from optparse import OptionParser
+
+optparser = OptionParser(
+    usage = "Usage: nanopb_generator.py [options] file.pb ...",
+    epilog = "Compile file.pb from file.proto by: 'protoc -ofile.pb file.proto'. " +
+             "Output will be written to file.pb.h and file.pb.c.")
+optparser.add_option("--version", dest="version", action="store_true",
+    help="Show version info and exit")
+optparser.add_option("-x", dest="exclude", metavar="FILE", action="append", default=[],
+    help="Exclude file from generated #include list.")
+optparser.add_option("-e", "--extension", dest="extension", metavar="EXTENSION", default=".pb",
+    help="Set extension to use instead of '.pb' for generated files. [default: %default]")
+optparser.add_option("-H", "--header-extension", dest="header_extension", metavar="EXTENSION", default=".h",
+    help="Set extension to use for generated header files. [default: %default]")
+optparser.add_option("-S", "--source-extension", dest="source_extension", metavar="EXTENSION", default=".c",
+    help="Set extension to use for generated source files. [default: %default]")
+optparser.add_option("-f", "--options-file", dest="options_file", metavar="FILE", default="%s.options",
+    help="Set name of a separate generator options file.")
+optparser.add_option("-I", "--options-path", dest="options_path", metavar="DIR",
+    action="append", default = [],
+    help="Search for .options files additionally in this path")
+optparser.add_option("--error-on-unmatched", dest="error_on_unmatched", action="store_true", default=False,
+                     help ="Stop generation if there are unmatched fields in options file")
+optparser.add_option("--no-error-on-unmatched", dest="error_on_unmatched", action="store_false", default=False,
+                     help ="Continue generation if there are unmatched fields in options file (default)")
+optparser.add_option("-D", "--output-dir", dest="output_dir",
+                     metavar="OUTPUTDIR", default=None,
+                     help="Output directory of .pb.h and .pb.c files")
+optparser.add_option("-Q", "--generated-include-format", dest="genformat",
+    metavar="FORMAT", default='#include "%s"',
+    help="Set format string to use for including other .pb.h files. [default: %default]")
+optparser.add_option("-L", "--library-include-format", dest="libformat",
+    metavar="FORMAT", default='#include <%s>',
+    help="Set format string to use for including the nanopb pb.h header. [default: %default]")
+optparser.add_option("--strip-path", dest="strip_path", action="store_true", default=False,
+    help="Strip directory path from #included .pb.h file name")
+optparser.add_option("--no-strip-path", dest="strip_path", action="store_false",
+    help="Opposite of --strip-path (default since 0.4.0)")
+optparser.add_option("--cpp-descriptors", action="store_true",
+    help="Generate C++ descriptors to lookup by type (e.g. pb_field_t for a message)")
+optparser.add_option("-T", "--no-timestamp", dest="notimestamp", action="store_true", default=True,
+    help="Don't add timestamp to .pb.h and .pb.c preambles (default since 0.4.0)")
+optparser.add_option("-t", "--timestamp", dest="notimestamp", action="store_false", default=True,
+    help="Add timestamp to .pb.h and .pb.c preambles")
+optparser.add_option("-q", "--quiet", dest="quiet", action="store_true", default=False,
+    help="Don't print anything except errors.")
+optparser.add_option("-v", "--verbose", dest="verbose", action="store_true", default=False,
+    help="Print more information.")
+optparser.add_option("-s", dest="settings", metavar="OPTION:VALUE", action="append", default=[],
+    help="Set generator option (max_size, max_count etc.).")
+optparser.add_option("--protoc-insertion-points", dest="protoc_insertion_points", action="store_true", default=False,
+                     help="Include insertion point comments in output for use by custom protoc plugins")
+
+def parse_file(filename, fdesc, options):
+    '''Parse a single file. Returns a ProtoFile instance.'''
+    toplevel_options = nanopb_pb2.NanoPBOptions()
+    for s in options.settings:
+        text_format.Merge(s, toplevel_options)
+
+    if not fdesc:
+        data = open(filename, 'rb').read()
+        fdesc = descriptor.FileDescriptorSet.FromString(data).file[0]
+
+    # Check if there is a separate .options file
+    had_abspath = False
+    try:
+        optfilename = options.options_file % os.path.splitext(filename)[0]
+    except TypeError:
+        # No %s specified, use the filename as-is
+        optfilename = options.options_file
+        had_abspath = True
+
+    paths = ['.'] + options.options_path
+    for p in paths:
+        if os.path.isfile(os.path.join(p, optfilename)):
+            optfilename = os.path.join(p, optfilename)
+            if options.verbose:
+                sys.stderr.write('Reading options from ' + optfilename + '\n')
+            Globals.separate_options = read_options_file(open(optfilename, openmode_unicode))
+            break
+    else:
+        # If we are given a full filename and it does not exist, give an error.
+        # However, don't give error when we automatically look for .options file
+        # with the same name as .proto.
+        if options.verbose or had_abspath:
+            sys.stderr.write('Options file not found: ' + optfilename + '\n')
+        Globals.separate_options = []
+
+    Globals.matched_namemasks = set()
+    Globals.protoc_insertion_points = options.protoc_insertion_points
+
+    # Parse the file
+    file_options = get_nanopb_suboptions(fdesc, toplevel_options, Names([filename]))
+    f = ProtoFile(fdesc, file_options)
+    f.optfilename = optfilename
+
+    return f
+
+def process_file(filename, fdesc, options, other_files = {}):
+    '''Process a single file.
+    filename: The full path to the .proto or .pb source file, as string.
+    fdesc: The loaded FileDescriptorSet, or None to read from the input file.
+    options: Command line options as they come from OptionsParser.
+
+    Returns a dict:
+        {'headername': Name of header file,
+         'headerdata': Data for the .h header file,
+         'sourcename': Name of the source code file,
+         'sourcedata': Data for the .c source code file
+        }
+    '''
+    f = parse_file(filename, fdesc, options)
+
+    # Check the list of dependencies, and if they are available in other_files,
+    # add them to be considered for import resolving. Recursively add any files
+    # imported by the dependencies.
+    deps = list(f.fdesc.dependency)
+    while deps:
+        dep = deps.pop(0)
+        if dep in other_files:
+            f.add_dependency(other_files[dep])
+            deps += list(other_files[dep].fdesc.dependency)
+
+    # Decide the file names
+    noext = os.path.splitext(filename)[0]
+    headername = noext + options.extension + options.header_extension
+    sourcename = noext + options.extension + options.source_extension
+
+    if options.strip_path:
+        headerbasename = os.path.basename(headername)
+    else:
+        headerbasename = headername
+
+    # List of .proto files that should not be included in the C header file
+    # even if they are mentioned in the source .proto.
+    excludes = ['nanopb.proto', 'google/protobuf/descriptor.proto'] + options.exclude + list(f.file_options.exclude)
+    includes = [d for d in f.fdesc.dependency if d not in excludes]
+
+    headerdata = ''.join(f.generate_header(includes, headerbasename, options))
+    sourcedata = ''.join(f.generate_source(headerbasename, options))
+
+    # Check if there were any lines in .options that did not match a member
+    unmatched = [n for n,o in Globals.separate_options if n not in Globals.matched_namemasks]
+    if unmatched:
+        if options.error_on_unmatched:
+            raise Exception("Following patterns in " + f.optfilename + " did not match any fields: "
+                            + ', '.join(unmatched));
+        elif not options.quiet:
+            sys.stderr.write("Following patterns in " + f.optfilename + " did not match any fields: "
+                            + ', '.join(unmatched) + "\n")
+
+        if not Globals.verbose_options:
+            sys.stderr.write("Use  protoc --nanopb-out=-v:.   to see a list of the field names.\n")
+
+    return {'headername': headername, 'headerdata': headerdata,
+            'sourcename': sourcename, 'sourcedata': sourcedata}
+
+def main_cli():
+    '''Main function when invoked directly from the command line.'''
+
+    options, filenames = optparser.parse_args()
+
+    if options.version:
+        print(nanopb_version)
+        sys.exit(0)
+
+    if not filenames:
+        optparser.print_help()
+        sys.exit(1)
+
+    if options.quiet:
+        options.verbose = False
+
+    if options.output_dir and not os.path.exists(options.output_dir):
+        optparser.print_help()
+        sys.stderr.write("\noutput_dir does not exist: %s\n" % options.output_dir)
+        sys.exit(1)
+
+    if options.verbose:
+        sys.stderr.write("Nanopb version %s\n" % nanopb_version)
+        sys.stderr.write('Google Python protobuf library imported from %s, version %s\n'
+                         % (google.protobuf.__file__, google.protobuf.__version__))
+
+    # Load .pb files into memory and compile any .proto files.
+    include_path = ['-I%s' % p for p in options.options_path]
+    all_fdescs = {}
+    out_fdescs = {}
+    for filename in filenames:
+        if filename.endswith(".proto"):
+            with TemporaryDirectory() as tmpdir:
+                tmpname = os.path.join(tmpdir, os.path.basename(filename) + ".pb")
+                status = invoke_protoc(["protoc"] + include_path + ['--include_imports', '--include_source_info', '-o' + tmpname, filename])
+                if status != 0: sys.exit(status)
+                data = open(tmpname, 'rb').read()
+        else:
+            data = open(filename, 'rb').read()
+
+        fdescs = descriptor.FileDescriptorSet.FromString(data).file
+        last_fdesc = fdescs[-1]
+
+        for fdesc in fdescs:
+          all_fdescs[fdesc.name] = fdesc
+
+        out_fdescs[last_fdesc.name] = last_fdesc
+
+    # Process any include files first, in order to have them
+    # available as dependencies
+    other_files = {}
+    for fdesc in all_fdescs.values():
+        other_files[fdesc.name] = parse_file(fdesc.name, fdesc, options)
+
+    # Then generate the headers / sources
+    Globals.verbose_options = options.verbose
+    for fdesc in out_fdescs.values():
+        results = process_file(fdesc.name, fdesc, options, other_files)
+
+        base_dir = options.output_dir or ''
+        to_write = [
+            (os.path.join(base_dir, results['headername']), results['headerdata']),
+            (os.path.join(base_dir, results['sourcename']), results['sourcedata']),
+        ]
+
+        if not options.quiet:
+            paths = " and ".join([x[0] for x in to_write])
+            sys.stderr.write("Writing to %s\n" % paths)
+
+        for path, data in to_write:
+            dirname = os.path.dirname(path)
+            if dirname and not os.path.exists(dirname):
+                os.makedirs(dirname)
+
+            with open(path, 'w') as f:
+                f.write(data)
+
+def main_plugin():
+    '''Main function when invoked as a protoc plugin.'''
+
+    import io, sys
+    if sys.platform == "win32":
+        import os, msvcrt
+        # Set stdin and stdout to binary mode
+        msvcrt.setmode(sys.stdin.fileno(), os.O_BINARY)
+        msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
+
+    data = io.open(sys.stdin.fileno(), "rb").read()
+
+    request = plugin_pb2.CodeGeneratorRequest.FromString(data)
+
+    try:
+        # Versions of Python prior to 2.7.3 do not support unicode
+        # input to shlex.split(). Try to convert to str if possible.
+        params = str(request.parameter)
+    except UnicodeEncodeError:
+        params = request.parameter
+
+    import shlex
+    args = shlex.split(params)
+
+    if len(args) == 1 and ',' in args[0]:
+        # For compatibility with other protoc plugins, support options
+        # separated by comma.
+        lex = shlex.shlex(params)
+        lex.whitespace_split = True
+        lex.whitespace = ','
+        lex.commenters = ''
+        args = list(lex)
+
+    optparser.usage = "Usage: protoc --nanopb_out=[options][,more_options]:outdir file.proto"
+    optparser.epilog = "Output will be written to file.pb.h and file.pb.c."
+
+    if '-h' in args or '--help' in args:
+        # By default optparser prints help to stdout, which doesn't work for
+        # protoc plugins.
+        optparser.print_help(sys.stderr)
+        sys.exit(1)
+
+    options, dummy = optparser.parse_args(args)
+
+    if options.version:
+        sys.stderr.write('%s\n' % (nanopb_version))
+        sys.exit(0)
+
+    Globals.verbose_options = options.verbose
+
+    if options.verbose:
+        sys.stderr.write("Nanopb version %s\n" % nanopb_version)
+        sys.stderr.write('Google Python protobuf library imported from %s, version %s\n'
+                         % (google.protobuf.__file__, google.protobuf.__version__))
+
+    response = plugin_pb2.CodeGeneratorResponse()
+
+    # Google's protoc does not currently indicate the full path of proto files.
+    # Instead always add the main file path to the search dirs, that works for
+    # the common case.
+    import os.path
+    options.options_path.append(os.path.dirname(request.file_to_generate[0]))
+
+    # Process any include files first, in order to have them
+    # available as dependencies
+    other_files = {}
+    for fdesc in request.proto_file:
+        other_files[fdesc.name] = parse_file(fdesc.name, fdesc, options)
+
+    for filename in request.file_to_generate:
+        for fdesc in request.proto_file:
+            if fdesc.name == filename:
+                results = process_file(filename, fdesc, options, other_files)
+
+                f = response.file.add()
+                f.name = results['headername']
+                f.content = results['headerdata']
+
+                f = response.file.add()
+                f.name = results['sourcename']
+                f.content = results['sourcedata']
+
+    if hasattr(plugin_pb2.CodeGeneratorResponse, "FEATURE_PROTO3_OPTIONAL"):
+        response.supported_features = plugin_pb2.CodeGeneratorResponse.FEATURE_PROTO3_OPTIONAL
+
+    io.open(sys.stdout.fileno(), "wb").write(response.SerializeToString())
+
+if __name__ == '__main__':
+    # Check if we are running as a plugin under protoc
+    if 'protoc-gen-' in sys.argv[0] or '--protoc-plugin' in sys.argv:
+        main_plugin()
+    else:
+        main_cli()

+ 13 - 0
components/spotify/cspot/bell/nanopb/generator/nanopb_generator.py2

@@ -0,0 +1,13 @@
+#!/usr/bin/env python2
+# This file is a wrapper around nanopb_generator.py in case you want to run
+# it with Python 2 instead of default Python 3. This only exists for backwards
+# compatibility, do not use for new projects.
+
+from nanopb_generator import *
+
+if __name__ == '__main__':
+    # Check if we are running as a plugin under protoc
+    if 'protoc-gen-' in sys.argv[0] or '--protoc-plugin' in sys.argv:
+        main_plugin()
+    else:
+        main_cli()

+ 148 - 0
components/spotify/cspot/bell/nanopb/generator/platformio_generator.py

@@ -0,0 +1,148 @@
+import os
+import hashlib
+import pathlib
+from platformio import fs
+
+Import("env")
+
+try:
+    import protobuf
+except ImportError:
+    env.Execute(
+        env.VerboseAction(
+            # We need to speicify protobuf version. In other case got next (on Ubuntu 20.04):
+            # Requirement already satisfied: protobuf in /usr/lib/python3/dist-packages (3.6.1)
+            '$PYTHONEXE -m pip install "protobuf>=3.19.1"',
+            "Installing Protocol Buffers dependencies",
+        )
+    )
+
+try:
+    import grpc_tools.protoc
+except ImportError:
+    env.Execute(
+        env.VerboseAction(
+            '$PYTHONEXE -m pip install "grpcio-tools>=1.43.0"',
+            "Installing GRPC dependencies",
+        )
+    )
+
+nanopb_root = os.path.join(os.getcwd(), '..')
+
+project_dir = env.subst("$PROJECT_DIR")
+build_dir = env.subst("$BUILD_DIR")
+
+generated_src_dir = os.path.join(build_dir, 'nanopb', 'generated-src')
+generated_build_dir = os.path.join(build_dir, 'nanopb', 'generated-build')
+md5_dir = os.path.join(build_dir, 'nanopb', 'md5')
+
+nanopb_protos = env.GetProjectOption("custom_nanopb_protos", "")
+nanopb_plugin_options = env.GetProjectOption("custom_nanopb_options", "")
+
+if not nanopb_protos:
+    print("[nanopb] No generation needed.")
+else:
+    if isinstance(nanopb_plugin_options, (list, tuple)):
+        nanopb_plugin_options = " ".join(nanopb_plugin_options)
+
+    nanopb_plugin_options = nanopb_plugin_options.split()
+
+    protos_files = fs.match_src_files(project_dir, nanopb_protos)
+    if not len(protos_files):
+        print("[nanopb] ERROR: No files matched pattern:")
+        print(f"custom_nanopb_protos: {nanopb_protos}")
+        exit(1)
+
+    protoc_generator = os.path.join(nanopb_root, 'generator', 'protoc')
+
+    nanopb_options = ""
+    nanopb_options += f" --nanopb_out={generated_src_dir}"
+    for opt in nanopb_plugin_options:
+        nanopb_options += (" --nanopb_opt=" + opt)
+
+    try:
+        os.makedirs(generated_src_dir)
+    except FileExistsError:
+        pass
+
+    try:
+        os.makedirs(md5_dir)
+    except FileExistsError:
+        pass
+
+    # Collect include dirs based on
+    proto_include_dirs = set()
+    for proto_file in protos_files:
+        proto_file_abs = os.path.join(project_dir, proto_file)
+        proto_dir = os.path.dirname(proto_file_abs)
+        proto_include_dirs.add(proto_dir)
+
+    for proto_include_dir in proto_include_dirs:
+        nanopb_options += (" --proto_path=" + proto_include_dir)
+        nanopb_options += (" --nanopb_opt=-I" + proto_include_dir)
+
+    for proto_file in protos_files:
+        proto_file_abs = os.path.join(project_dir, proto_file)
+
+        proto_file_path_abs = os.path.dirname(proto_file_abs)
+        proto_file_basename = os.path.basename(proto_file_abs)
+        proto_file_without_ext = os.path.splitext(proto_file_basename)[0]
+
+        proto_file_md5_abs = os.path.join(md5_dir, proto_file_basename + '.md5')
+        proto_file_current_md5 = hashlib.md5(pathlib.Path(proto_file_abs).read_bytes()).hexdigest()
+
+        options_file = proto_file_without_ext + ".options"
+        options_file_abs = os.path.join(proto_file_path_abs, options_file)
+        options_file_md5_abs = None
+        options_file_current_md5 = None
+        if pathlib.Path(options_file_abs).exists():
+            options_file_md5_abs = os.path.join(md5_dir, options_file + '.md5')
+            options_file_current_md5 = hashlib.md5(pathlib.Path(options_file_abs).read_bytes()).hexdigest()
+        else:
+            options_file = None
+
+        header_file = proto_file_without_ext + ".pb.h"
+        source_file = proto_file_without_ext + ".pb.c"
+
+        header_file_abs = os.path.join(generated_src_dir, source_file)
+        source_file_abs = os.path.join(generated_src_dir, header_file)
+
+        need_generate = False
+
+        # Check proto file md5
+        try:
+            last_md5 = pathlib.Path(proto_file_md5_abs).read_text()
+            if last_md5 != proto_file_current_md5:
+                need_generate = True
+        except FileNotFoundError:
+            need_generate = True
+
+        if options_file:
+            # Check options file md5
+            try:
+                last_md5 = pathlib.Path(options_file_md5_abs).read_text()
+                if last_md5 != options_file_current_md5:
+                    need_generate = True
+            except FileNotFoundError:
+                need_generate = True
+
+        options_info = f"{options_file}" if options_file else "no options"
+
+        if not need_generate:
+            print(f"[nanopb] Skipping '{proto_file}' ({options_info})")
+        else:
+            print(f"[nanopb] Processing '{proto_file}' ({options_info})")
+            cmd = protoc_generator + " " + nanopb_options + " " + proto_file_basename
+            result = env.Execute(cmd)
+            if result != 0:
+                print(f"[nanopb] ERROR: ({result}) processing cmd: '{cmd}'")
+                exit(1)
+            pathlib.Path(proto_file_md5_abs).write_text(proto_file_current_md5)
+            if options_file:
+                pathlib.Path(options_file_md5_abs).write_text(options_file_current_md5)
+
+    #
+    # Add generated includes and sources to build environment
+    #
+    env.Append(CPPPATH=[generated_src_dir])
+    env.BuildSources(generated_build_dir, generated_src_dir)

+ 10 - 0
components/spotify/cspot/bell/nanopb/generator/proto/Makefile

@@ -0,0 +1,10 @@
+PROTOC?=protoc
+
+all: nanopb_pb2.py
+
+%_pb2.py: %.proto
+	$(PROTOC) --python_out=. $<
+
+.PHONY: clean
+clean:
+	rm nanopb_pb2.py

+ 36 - 0
components/spotify/cspot/bell/nanopb/generator/proto/__init__.py

@@ -0,0 +1,36 @@
+'''This file automatically rebuilds the proto definitions for Python.'''
+from __future__ import absolute_import
+
+import os.path
+import sys
+
+import pkg_resources
+
+from ._utils import has_grpcio_protoc, invoke_protoc
+
+dirname = os.path.dirname(__file__)
+protosrc = os.path.join(dirname, "nanopb.proto")
+protodst = os.path.join(dirname, "nanopb_pb2.py")
+
+if os.path.isfile(protosrc):
+    src_date = os.path.getmtime(protosrc)
+    if not os.path.isfile(protodst) or os.path.getmtime(protodst) < src_date:
+
+        cmd = [
+            "protoc",
+            "--python_out={}".format(dirname),
+            protosrc,
+            "-I={}".format(dirname),
+        ]
+
+        if has_grpcio_protoc():
+            # grpcio-tools has an extra CLI argument
+            # from grpc.tools.protoc __main__ invocation.
+            _builtin_proto_include = pkg_resources.resource_filename('grpc_tools', '_proto')
+
+            cmd.append("-I={}".format(_builtin_proto_include))
+        try:
+            invoke_protoc(argv=cmd)
+        except:
+            sys.stderr.write("Failed to build nanopb_pb2.py: " + ' '.join(cmd) + "\n")
+            raise

+ 43 - 0
components/spotify/cspot/bell/nanopb/generator/proto/_utils.py

@@ -0,0 +1,43 @@
+import subprocess
+import os.path
+
+def has_grpcio_protoc():
+    # type: () -> bool
+    """ checks if grpcio-tools protoc is installed"""
+
+    try:
+        import grpc_tools.protoc
+    except ImportError:
+        return False
+    return True
+
+
+def invoke_protoc(argv):
+    # type: (list) -> typing.Any
+    """
+    Invoke protoc.
+
+    This routine will use grpcio-provided protoc if it exists,
+    using system-installed protoc as a fallback.
+
+    Args:
+        argv: protoc CLI invocation, first item must be 'protoc'
+    """
+
+    # Add current directory to include path if nothing else is specified
+    if not [x for x in argv if x.startswith('-I')]:
+        argv.append("-I.")
+
+    # Add default protoc include paths
+    nanopb_include = os.path.dirname(os.path.abspath(__file__))
+    argv.append('-I' + nanopb_include)
+
+    if has_grpcio_protoc():
+        import grpc_tools.protoc as protoc
+        import pkg_resources
+        proto_include = pkg_resources.resource_filename('grpc_tools', '_proto')
+        argv.append('-I' + proto_include)
+
+        return protoc.main(argv)
+    else:
+        return subprocess.call(argv)

+ 872 - 0
components/spotify/cspot/bell/nanopb/generator/proto/google/protobuf/descriptor.proto

@@ -0,0 +1,872 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+//
+// The messages in this file describe the definitions found in .proto files.
+// A valid .proto file can be translated directly to a FileDescriptorProto
+// without any other information (e.g. without reading its imports).
+
+
+syntax = "proto2";
+
+package google.protobuf;
+option go_package = "github.com/golang/protobuf/protoc-gen-go/descriptor;descriptor";
+option java_package = "com.google.protobuf";
+option java_outer_classname = "DescriptorProtos";
+option csharp_namespace = "Google.Protobuf.Reflection";
+option objc_class_prefix = "GPB";
+option cc_enable_arenas = true;
+
+// descriptor.proto must be optimized for speed because reflection-based
+// algorithms don't work during bootstrapping.
+option optimize_for = SPEED;
+
+// The protocol compiler can output a FileDescriptorSet containing the .proto
+// files it parses.
+message FileDescriptorSet {
+  repeated FileDescriptorProto file = 1;
+}
+
+// Describes a complete .proto file.
+message FileDescriptorProto {
+  optional string name = 1;       // file name, relative to root of source tree
+  optional string package = 2;    // e.g. "foo", "foo.bar", etc.
+
+  // Names of files imported by this file.
+  repeated string dependency = 3;
+  // Indexes of the public imported files in the dependency list above.
+  repeated int32 public_dependency = 10;
+  // Indexes of the weak imported files in the dependency list.
+  // For Google-internal migration only. Do not use.
+  repeated int32 weak_dependency = 11;
+
+  // All top-level definitions in this file.
+  repeated DescriptorProto message_type = 4;
+  repeated EnumDescriptorProto enum_type = 5;
+  repeated ServiceDescriptorProto service = 6;
+  repeated FieldDescriptorProto extension = 7;
+
+  optional FileOptions options = 8;
+
+  // This field contains optional information about the original source code.
+  // You may safely remove this entire field without harming runtime
+  // functionality of the descriptors -- the information is needed only by
+  // development tools.
+  optional SourceCodeInfo source_code_info = 9;
+
+  // The syntax of the proto file.
+  // The supported values are "proto2" and "proto3".
+  optional string syntax = 12;
+}
+
+// Describes a message type.
+message DescriptorProto {
+  optional string name = 1;
+
+  repeated FieldDescriptorProto field = 2;
+  repeated FieldDescriptorProto extension = 6;
+
+  repeated DescriptorProto nested_type = 3;
+  repeated EnumDescriptorProto enum_type = 4;
+
+  message ExtensionRange {
+    optional int32 start = 1;
+    optional int32 end = 2;
+
+    optional ExtensionRangeOptions options = 3;
+  }
+  repeated ExtensionRange extension_range = 5;
+
+  repeated OneofDescriptorProto oneof_decl = 8;
+
+  optional MessageOptions options = 7;
+
+  // Range of reserved tag numbers. Reserved tag numbers may not be used by
+  // fields or extension ranges in the same message. Reserved ranges may
+  // not overlap.
+  message ReservedRange {
+    optional int32 start = 1; // Inclusive.
+    optional int32 end = 2;   // Exclusive.
+  }
+  repeated ReservedRange reserved_range = 9;
+  // Reserved field names, which may not be used by fields in the same message.
+  // A given name may only be reserved once.
+  repeated string reserved_name = 10;
+}
+
+message ExtensionRangeOptions {
+  // The parser stores options it doesn't recognize here. See above.
+  repeated UninterpretedOption uninterpreted_option = 999;
+
+  // Clients can define custom options in extensions of this message. See above.
+  extensions 1000 to max;
+}
+
+// Describes a field within a message.
+message FieldDescriptorProto {
+  enum Type {
+    // 0 is reserved for errors.
+    // Order is weird for historical reasons.
+    TYPE_DOUBLE         = 1;
+    TYPE_FLOAT          = 2;
+    // Not ZigZag encoded.  Negative numbers take 10 bytes.  Use TYPE_SINT64 if
+    // negative values are likely.
+    TYPE_INT64          = 3;
+    TYPE_UINT64         = 4;
+    // Not ZigZag encoded.  Negative numbers take 10 bytes.  Use TYPE_SINT32 if
+    // negative values are likely.
+    TYPE_INT32          = 5;
+    TYPE_FIXED64        = 6;
+    TYPE_FIXED32        = 7;
+    TYPE_BOOL           = 8;
+    TYPE_STRING         = 9;
+    // Tag-delimited aggregate.
+    // Group type is deprecated and not supported in proto3. However, Proto3
+    // implementations should still be able to parse the group wire format and
+    // treat group fields as unknown fields.
+    TYPE_GROUP          = 10;
+    TYPE_MESSAGE        = 11;  // Length-delimited aggregate.
+
+    // New in version 2.
+    TYPE_BYTES          = 12;
+    TYPE_UINT32         = 13;
+    TYPE_ENUM           = 14;
+    TYPE_SFIXED32       = 15;
+    TYPE_SFIXED64       = 16;
+    TYPE_SINT32         = 17;  // Uses ZigZag encoding.
+    TYPE_SINT64         = 18;  // Uses ZigZag encoding.
+  };
+
+  enum Label {
+    // 0 is reserved for errors
+    LABEL_OPTIONAL      = 1;
+    LABEL_REQUIRED      = 2;
+    LABEL_REPEATED      = 3;
+  };
+
+  optional string name = 1;
+  optional int32 number = 3;
+  optional Label label = 4;
+
+  // If type_name is set, this need not be set.  If both this and type_name
+  // are set, this must be one of TYPE_ENUM, TYPE_MESSAGE or TYPE_GROUP.
+  optional Type type = 5;
+
+  // For message and enum types, this is the name of the type.  If the name
+  // starts with a '.', it is fully-qualified.  Otherwise, C++-like scoping
+  // rules are used to find the type (i.e. first the nested types within this
+  // message are searched, then within the parent, on up to the root
+  // namespace).
+  optional string type_name = 6;
+
+  // For extensions, this is the name of the type being extended.  It is
+  // resolved in the same manner as type_name.
+  optional string extendee = 2;
+
+  // For numeric types, contains the original text representation of the value.
+  // For booleans, "true" or "false".
+  // For strings, contains the default text contents (not escaped in any way).
+  // For bytes, contains the C escaped value.  All bytes >= 128 are escaped.
+  // TODO(kenton):  Base-64 encode?
+  optional string default_value = 7;
+
+  // If set, gives the index of a oneof in the containing type's oneof_decl
+  // list.  This field is a member of that oneof.
+  optional int32 oneof_index = 9;
+
+  // JSON name of this field. The value is set by protocol compiler. If the
+  // user has set a "json_name" option on this field, that option's value
+  // will be used. Otherwise, it's deduced from the field's name by converting
+  // it to camelCase.
+  optional string json_name = 10;
+
+  optional FieldOptions options = 8;
+}
+
+// Describes a oneof.
+message OneofDescriptorProto {
+  optional string name = 1;
+  optional OneofOptions options = 2;
+}
+
+// Describes an enum type.
+message EnumDescriptorProto {
+  optional string name = 1;
+
+  repeated EnumValueDescriptorProto value = 2;
+
+  optional EnumOptions options = 3;
+
+  // Range of reserved numeric values. Reserved values may not be used by
+  // entries in the same enum. Reserved ranges may not overlap.
+  //
+  // Note that this is distinct from DescriptorProto.ReservedRange in that it
+  // is inclusive such that it can appropriately represent the entire int32
+  // domain.
+  message EnumReservedRange {
+    optional int32 start = 1; // Inclusive.
+    optional int32 end = 2;   // Inclusive.
+  }
+
+  // Range of reserved numeric values. Reserved numeric values may not be used
+  // by enum values in the same enum declaration. Reserved ranges may not
+  // overlap.
+  repeated EnumReservedRange reserved_range = 4;
+
+  // Reserved enum value names, which may not be reused. A given name may only
+  // be reserved once.
+  repeated string reserved_name = 5;
+}
+
+// Describes a value within an enum.
+message EnumValueDescriptorProto {
+  optional string name = 1;
+  optional int32 number = 2;
+
+  optional EnumValueOptions options = 3;
+}
+
+// Describes a service.
+message ServiceDescriptorProto {
+  optional string name = 1;
+  repeated MethodDescriptorProto method = 2;
+
+  optional ServiceOptions options = 3;
+}
+
+// Describes a method of a service.
+message MethodDescriptorProto {
+  optional string name = 1;
+
+  // Input and output type names.  These are resolved in the same way as
+  // FieldDescriptorProto.type_name, but must refer to a message type.
+  optional string input_type = 2;
+  optional string output_type = 3;
+
+  optional MethodOptions options = 4;
+
+  // Identifies if client streams multiple client messages
+  optional bool client_streaming = 5 [default=false];
+  // Identifies if server streams multiple server messages
+  optional bool server_streaming = 6 [default=false];
+}
+
+
+// ===================================================================
+// Options
+
+// Each of the definitions above may have "options" attached.  These are
+// just annotations which may cause code to be generated slightly differently
+// or may contain hints for code that manipulates protocol messages.
+//
+// Clients may define custom options as extensions of the *Options messages.
+// These extensions may not yet be known at parsing time, so the parser cannot
+// store the values in them.  Instead it stores them in a field in the *Options
+// message called uninterpreted_option. This field must have the same name
+// across all *Options messages. We then use this field to populate the
+// extensions when we build a descriptor, at which point all protos have been
+// parsed and so all extensions are known.
+//
+// Extension numbers for custom options may be chosen as follows:
+// * For options which will only be used within a single application or
+//   organization, or for experimental options, use field numbers 50000
+//   through 99999.  It is up to you to ensure that you do not use the
+//   same number for multiple options.
+// * For options which will be published and used publicly by multiple
+//   independent entities, e-mail protobuf-global-extension-registry@google.com
+//   to reserve extension numbers. Simply provide your project name (e.g.
+//   Objective-C plugin) and your project website (if available) -- there's no
+//   need to explain how you intend to use them. Usually you only need one
+//   extension number. You can declare multiple options with only one extension
+//   number by putting them in a sub-message. See the Custom Options section of
+//   the docs for examples:
+//   https://developers.google.com/protocol-buffers/docs/proto#options
+//   If this turns out to be popular, a web service will be set up
+//   to automatically assign option numbers.
+
+
+message FileOptions {
+
+  // Sets the Java package where classes generated from this .proto will be
+  // placed.  By default, the proto package is used, but this is often
+  // inappropriate because proto packages do not normally start with backwards
+  // domain names.
+  optional string java_package = 1;
+
+
+  // If set, all the classes from the .proto file are wrapped in a single
+  // outer class with the given name.  This applies to both Proto1
+  // (equivalent to the old "--one_java_file" option) and Proto2 (where
+  // a .proto always translates to a single class, but you may want to
+  // explicitly choose the class name).
+  optional string java_outer_classname = 8;
+
+  // If set true, then the Java code generator will generate a separate .java
+  // file for each top-level message, enum, and service defined in the .proto
+  // file.  Thus, these types will *not* be nested inside the outer class
+  // named by java_outer_classname.  However, the outer class will still be
+  // generated to contain the file's getDescriptor() method as well as any
+  // top-level extensions defined in the file.
+  optional bool java_multiple_files = 10 [default=false];
+
+  // This option does nothing.
+  optional bool java_generate_equals_and_hash = 20 [deprecated=true];
+
+  // If set true, then the Java2 code generator will generate code that
+  // throws an exception whenever an attempt is made to assign a non-UTF-8
+  // byte sequence to a string field.
+  // Message reflection will do the same.
+  // However, an extension field still accepts non-UTF-8 byte sequences.
+  // This option has no effect on when used with the lite runtime.
+  optional bool java_string_check_utf8 = 27 [default=false];
+
+
+  // Generated classes can be optimized for speed or code size.
+  enum OptimizeMode {
+    SPEED = 1;        // Generate complete code for parsing, serialization,
+                      // etc.
+    CODE_SIZE = 2;    // Use ReflectionOps to implement these methods.
+    LITE_RUNTIME = 3; // Generate code using MessageLite and the lite runtime.
+  }
+  optional OptimizeMode optimize_for = 9 [default=SPEED];
+
+  // Sets the Go package where structs generated from this .proto will be
+  // placed. If omitted, the Go package will be derived from the following:
+  //   - The basename of the package import path, if provided.
+  //   - Otherwise, the package statement in the .proto file, if present.
+  //   - Otherwise, the basename of the .proto file, without extension.
+  optional string go_package = 11;
+
+
+
+  // Should generic services be generated in each language?  "Generic" services
+  // are not specific to any particular RPC system.  They are generated by the
+  // main code generators in each language (without additional plugins).
+  // Generic services were the only kind of service generation supported by
+  // early versions of google.protobuf.
+  //
+  // Generic services are now considered deprecated in favor of using plugins
+  // that generate code specific to your particular RPC system.  Therefore,
+  // these default to false.  Old code which depends on generic services should
+  // explicitly set them to true.
+  optional bool cc_generic_services = 16 [default=false];
+  optional bool java_generic_services = 17 [default=false];
+  optional bool py_generic_services = 18 [default=false];
+  optional bool php_generic_services = 42 [default=false];
+
+  // Is this file deprecated?
+  // Depending on the target platform, this can emit Deprecated annotations
+  // for everything in the file, or it will be completely ignored; in the very
+  // least, this is a formalization for deprecating files.
+  optional bool deprecated = 23 [default=false];
+
+  // Enables the use of arenas for the proto messages in this file. This applies
+  // only to generated classes for C++.
+  optional bool cc_enable_arenas = 31 [default=false];
+
+
+  // Sets the objective c class prefix which is prepended to all objective c
+  // generated classes from this .proto. There is no default.
+  optional string objc_class_prefix = 36;
+
+  // Namespace for generated classes; defaults to the package.
+  optional string csharp_namespace = 37;
+
+  // By default Swift generators will take the proto package and CamelCase it
+  // replacing '.' with underscore and use that to prefix the types/symbols
+  // defined. When this options is provided, they will use this value instead
+  // to prefix the types/symbols defined.
+  optional string swift_prefix = 39;
+
+  // Sets the php class prefix which is prepended to all php generated classes
+  // from this .proto. Default is empty.
+  optional string php_class_prefix = 40;
+
+  // Use this option to change the namespace of php generated classes. Default
+  // is empty. When this option is empty, the package name will be used for
+  // determining the namespace.
+  optional string php_namespace = 41;
+
+  // The parser stores options it doesn't recognize here.
+  // See the documentation for the "Options" section above.
+  repeated UninterpretedOption uninterpreted_option = 999;
+
+  // Clients can define custom options in extensions of this message.
+  // See the documentation for the "Options" section above.
+  extensions 1000 to max;
+
+  reserved 38;
+}
+
+message MessageOptions {
+  // Set true to use the old proto1 MessageSet wire format for extensions.
+  // This is provided for backwards-compatibility with the MessageSet wire
+  // format.  You should not use this for any other reason:  It's less
+  // efficient, has fewer features, and is more complicated.
+  //
+  // The message must be defined exactly as follows:
+  //   message Foo {
+  //     option message_set_wire_format = true;
+  //     extensions 4 to max;
+  //   }
+  // Note that the message cannot have any defined fields; MessageSets only
+  // have extensions.
+  //
+  // All extensions of your type must be singular messages; e.g. they cannot
+  // be int32s, enums, or repeated messages.
+  //
+  // Because this is an option, the above two restrictions are not enforced by
+  // the protocol compiler.
+  optional bool message_set_wire_format = 1 [default=false];
+
+  // Disables the generation of the standard "descriptor()" accessor, which can
+  // conflict with a field of the same name.  This is meant to make migration
+  // from proto1 easier; new code should avoid fields named "descriptor".
+  optional bool no_standard_descriptor_accessor = 2 [default=false];
+
+  // Is this message deprecated?
+  // Depending on the target platform, this can emit Deprecated annotations
+  // for the message, or it will be completely ignored; in the very least,
+  // this is a formalization for deprecating messages.
+  optional bool deprecated = 3 [default=false];
+
+  // Whether the message is an automatically generated map entry type for the
+  // maps field.
+  //
+  // For maps fields:
+  //     map<KeyType, ValueType> map_field = 1;
+  // The parsed descriptor looks like:
+  //     message MapFieldEntry {
+  //         option map_entry = true;
+  //         optional KeyType key = 1;
+  //         optional ValueType value = 2;
+  //     }
+  //     repeated MapFieldEntry map_field = 1;
+  //
+  // Implementations may choose not to generate the map_entry=true message, but
+  // use a native map in the target language to hold the keys and values.
+  // The reflection APIs in such implementions still need to work as
+  // if the field is a repeated message field.
+  //
+  // NOTE: Do not set the option in .proto files. Always use the maps syntax
+  // instead. The option should only be implicitly set by the proto compiler
+  // parser.
+  optional bool map_entry = 7;
+
+  reserved 8;  // javalite_serializable
+  reserved 9;  // javanano_as_lite
+
+  // The parser stores options it doesn't recognize here. See above.
+  repeated UninterpretedOption uninterpreted_option = 999;
+
+  // Clients can define custom options in extensions of this message. See above.
+  extensions 1000 to max;
+}
+
+message FieldOptions {
+  // The ctype option instructs the C++ code generator to use a different
+  // representation of the field than it normally would.  See the specific
+  // options below.  This option is not yet implemented in the open source
+  // release -- sorry, we'll try to include it in a future version!
+  optional CType ctype = 1 [default = STRING];
+  enum CType {
+    // Default mode.
+    STRING = 0;
+
+    CORD = 1;
+
+    STRING_PIECE = 2;
+  }
+  // The packed option can be enabled for repeated primitive fields to enable
+  // a more efficient representation on the wire. Rather than repeatedly
+  // writing the tag and type for each element, the entire array is encoded as
+  // a single length-delimited blob. In proto3, only explicit setting it to
+  // false will avoid using packed encoding.
+  optional bool packed = 2;
+
+  // The jstype option determines the JavaScript type used for values of the
+  // field.  The option is permitted only for 64 bit integral and fixed types
+  // (int64, uint64, sint64, fixed64, sfixed64).  A field with jstype JS_STRING
+  // is represented as JavaScript string, which avoids loss of precision that
+  // can happen when a large value is converted to a floating point JavaScript.
+  // Specifying JS_NUMBER for the jstype causes the generated JavaScript code to
+  // use the JavaScript "number" type.  The behavior of the default option
+  // JS_NORMAL is implementation dependent.
+  //
+  // This option is an enum to permit additional types to be added, e.g.
+  // goog.math.Integer.
+  optional JSType jstype = 6 [default = JS_NORMAL];
+  enum JSType {
+    // Use the default type.
+    JS_NORMAL = 0;
+
+    // Use JavaScript strings.
+    JS_STRING = 1;
+
+    // Use JavaScript numbers.
+    JS_NUMBER = 2;
+  }
+
+  // Should this field be parsed lazily?  Lazy applies only to message-type
+  // fields.  It means that when the outer message is initially parsed, the
+  // inner message's contents will not be parsed but instead stored in encoded
+  // form.  The inner message will actually be parsed when it is first accessed.
+  //
+  // This is only a hint.  Implementations are free to choose whether to use
+  // eager or lazy parsing regardless of the value of this option.  However,
+  // setting this option true suggests that the protocol author believes that
+  // using lazy parsing on this field is worth the additional bookkeeping
+  // overhead typically needed to implement it.
+  //
+  // This option does not affect the public interface of any generated code;
+  // all method signatures remain the same.  Furthermore, thread-safety of the
+  // interface is not affected by this option; const methods remain safe to
+  // call from multiple threads concurrently, while non-const methods continue
+  // to require exclusive access.
+  //
+  //
+  // Note that implementations may choose not to check required fields within
+  // a lazy sub-message.  That is, calling IsInitialized() on the outer message
+  // may return true even if the inner message has missing required fields.
+  // This is necessary because otherwise the inner message would have to be
+  // parsed in order to perform the check, defeating the purpose of lazy
+  // parsing.  An implementation which chooses not to check required fields
+  // must be consistent about it.  That is, for any particular sub-message, the
+  // implementation must either *always* check its required fields, or *never*
+  // check its required fields, regardless of whether or not the message has
+  // been parsed.
+  optional bool lazy = 5 [default=false];
+
+  // Is this field deprecated?
+  // Depending on the target platform, this can emit Deprecated annotations
+  // for accessors, or it will be completely ignored; in the very least, this
+  // is a formalization for deprecating fields.
+  optional bool deprecated = 3 [default=false];
+
+  // For Google-internal migration only. Do not use.
+  optional bool weak = 10 [default=false];
+
+
+  // The parser stores options it doesn't recognize here. See above.
+  repeated UninterpretedOption uninterpreted_option = 999;
+
+  // Clients can define custom options in extensions of this message. See above.
+  extensions 1000 to max;
+
+  reserved 4;  // removed jtype
+}
+
+message OneofOptions {
+  // The parser stores options it doesn't recognize here. See above.
+  repeated UninterpretedOption uninterpreted_option = 999;
+
+  // Clients can define custom options in extensions of this message. See above.
+  extensions 1000 to max;
+}
+
+message EnumOptions {
+
+  // Set this option to true to allow mapping different tag names to the same
+  // value.
+  optional bool allow_alias = 2;
+
+  // Is this enum deprecated?
+  // Depending on the target platform, this can emit Deprecated annotations
+  // for the enum, or it will be completely ignored; in the very least, this
+  // is a formalization for deprecating enums.
+  optional bool deprecated = 3 [default=false];
+
+  reserved 5;  // javanano_as_lite
+
+  // The parser stores options it doesn't recognize here. See above.
+  repeated UninterpretedOption uninterpreted_option = 999;
+
+  // Clients can define custom options in extensions of this message. See above.
+  extensions 1000 to max;
+}
+
+message EnumValueOptions {
+  // Is this enum value deprecated?
+  // Depending on the target platform, this can emit Deprecated annotations
+  // for the enum value, or it will be completely ignored; in the very least,
+  // this is a formalization for deprecating enum values.
+  optional bool deprecated = 1 [default=false];
+
+  // The parser stores options it doesn't recognize here. See above.
+  repeated UninterpretedOption uninterpreted_option = 999;
+
+  // Clients can define custom options in extensions of this message. See above.
+  extensions 1000 to max;
+}
+
+message ServiceOptions {
+
+  // Note:  Field numbers 1 through 32 are reserved for Google's internal RPC
+  //   framework.  We apologize for hoarding these numbers to ourselves, but
+  //   we were already using them long before we decided to release Protocol
+  //   Buffers.
+
+  // Is this service deprecated?
+  // Depending on the target platform, this can emit Deprecated annotations
+  // for the service, or it will be completely ignored; in the very least,
+  // this is a formalization for deprecating services.
+  optional bool deprecated = 33 [default=false];
+
+  // The parser stores options it doesn't recognize here. See above.
+  repeated UninterpretedOption uninterpreted_option = 999;
+
+  // Clients can define custom options in extensions of this message. See above.
+  extensions 1000 to max;
+}
+
+message MethodOptions {
+
+  // Note:  Field numbers 1 through 32 are reserved for Google's internal RPC
+  //   framework.  We apologize for hoarding these numbers to ourselves, but
+  //   we were already using them long before we decided to release Protocol
+  //   Buffers.
+
+  // Is this method deprecated?
+  // Depending on the target platform, this can emit Deprecated annotations
+  // for the method, or it will be completely ignored; in the very least,
+  // this is a formalization for deprecating methods.
+  optional bool deprecated = 33 [default=false];
+
+  // Is this method side-effect-free (or safe in HTTP parlance), or idempotent,
+  // or neither? HTTP based RPC implementation may choose GET verb for safe
+  // methods, and PUT verb for idempotent methods instead of the default POST.
+  enum IdempotencyLevel {
+    IDEMPOTENCY_UNKNOWN = 0;
+    NO_SIDE_EFFECTS     = 1; // implies idempotent
+    IDEMPOTENT          = 2; // idempotent, but may have side effects
+  }
+  optional IdempotencyLevel idempotency_level =
+      34 [default=IDEMPOTENCY_UNKNOWN];
+
+  // The parser stores options it doesn't recognize here. See above.
+  repeated UninterpretedOption uninterpreted_option = 999;
+
+  // Clients can define custom options in extensions of this message. See above.
+  extensions 1000 to max;
+}
+
+
+// A message representing a option the parser does not recognize. This only
+// appears in options protos created by the compiler::Parser class.
+// DescriptorPool resolves these when building Descriptor objects. Therefore,
+// options protos in descriptor objects (e.g. returned by Descriptor::options(),
+// or produced by Descriptor::CopyTo()) will never have UninterpretedOptions
+// in them.
+message UninterpretedOption {
+  // The name of the uninterpreted option.  Each string represents a segment in
+  // a dot-separated name.  is_extension is true iff a segment represents an
+  // extension (denoted with parentheses in options specs in .proto files).
+  // E.g.,{ ["foo", false], ["bar.baz", true], ["qux", false] } represents
+  // "foo.(bar.baz).qux".
+  message NamePart {
+    required string name_part = 1;
+    required bool is_extension = 2;
+  }
+  repeated NamePart name = 2;
+
+  // The value of the uninterpreted option, in whatever type the tokenizer
+  // identified it as during parsing. Exactly one of these should be set.
+  optional string identifier_value = 3;
+  optional uint64 positive_int_value = 4;
+  optional int64 negative_int_value = 5;
+  optional double double_value = 6;
+  optional bytes string_value = 7;
+  optional string aggregate_value = 8;
+}
+
+// ===================================================================
+// Optional source code info
+
+// Encapsulates information about the original source file from which a
+// FileDescriptorProto was generated.
+message SourceCodeInfo {
+  // A Location identifies a piece of source code in a .proto file which
+  // corresponds to a particular definition.  This information is intended
+  // to be useful to IDEs, code indexers, documentation generators, and similar
+  // tools.
+  //
+  // For example, say we have a file like:
+  //   message Foo {
+  //     optional string foo = 1;
+  //   }
+  // Let's look at just the field definition:
+  //   optional string foo = 1;
+  //   ^       ^^     ^^  ^  ^^^
+  //   a       bc     de  f  ghi
+  // We have the following locations:
+  //   span   path               represents
+  //   [a,i)  [ 4, 0, 2, 0 ]     The whole field definition.
+  //   [a,b)  [ 4, 0, 2, 0, 4 ]  The label (optional).
+  //   [c,d)  [ 4, 0, 2, 0, 5 ]  The type (string).
+  //   [e,f)  [ 4, 0, 2, 0, 1 ]  The name (foo).
+  //   [g,h)  [ 4, 0, 2, 0, 3 ]  The number (1).
+  //
+  // Notes:
+  // - A location may refer to a repeated field itself (i.e. not to any
+  //   particular index within it).  This is used whenever a set of elements are
+  //   logically enclosed in a single code segment.  For example, an entire
+  //   extend block (possibly containing multiple extension definitions) will
+  //   have an outer location whose path refers to the "extensions" repeated
+  //   field without an index.
+  // - Multiple locations may have the same path.  This happens when a single
+  //   logical declaration is spread out across multiple places.  The most
+  //   obvious example is the "extend" block again -- there may be multiple
+  //   extend blocks in the same scope, each of which will have the same path.
+  // - A location's span is not always a subset of its parent's span.  For
+  //   example, the "extendee" of an extension declaration appears at the
+  //   beginning of the "extend" block and is shared by all extensions within
+  //   the block.
+  // - Just because a location's span is a subset of some other location's span
+  //   does not mean that it is a descendent.  For example, a "group" defines
+  //   both a type and a field in a single declaration.  Thus, the locations
+  //   corresponding to the type and field and their components will overlap.
+  // - Code which tries to interpret locations should probably be designed to
+  //   ignore those that it doesn't understand, as more types of locations could
+  //   be recorded in the future.
+  repeated Location location = 1;
+  message Location {
+    // Identifies which part of the FileDescriptorProto was defined at this
+    // location.
+    //
+    // Each element is a field number or an index.  They form a path from
+    // the root FileDescriptorProto to the place where the definition.  For
+    // example, this path:
+    //   [ 4, 3, 2, 7, 1 ]
+    // refers to:
+    //   file.message_type(3)  // 4, 3
+    //       .field(7)         // 2, 7
+    //       .name()           // 1
+    // This is because FileDescriptorProto.message_type has field number 4:
+    //   repeated DescriptorProto message_type = 4;
+    // and DescriptorProto.field has field number 2:
+    //   repeated FieldDescriptorProto field = 2;
+    // and FieldDescriptorProto.name has field number 1:
+    //   optional string name = 1;
+    //
+    // Thus, the above path gives the location of a field name.  If we removed
+    // the last element:
+    //   [ 4, 3, 2, 7 ]
+    // this path refers to the whole field declaration (from the beginning
+    // of the label to the terminating semicolon).
+    repeated int32 path = 1 [packed=true];
+
+    // Always has exactly three or four elements: start line, start column,
+    // end line (optional, otherwise assumed same as start line), end column.
+    // These are packed into a single field for efficiency.  Note that line
+    // and column numbers are zero-based -- typically you will want to add
+    // 1 to each before displaying to a user.
+    repeated int32 span = 2 [packed=true];
+
+    // If this SourceCodeInfo represents a complete declaration, these are any
+    // comments appearing before and after the declaration which appear to be
+    // attached to the declaration.
+    //
+    // A series of line comments appearing on consecutive lines, with no other
+    // tokens appearing on those lines, will be treated as a single comment.
+    //
+    // leading_detached_comments will keep paragraphs of comments that appear
+    // before (but not connected to) the current element. Each paragraph,
+    // separated by empty lines, will be one comment element in the repeated
+    // field.
+    //
+    // Only the comment content is provided; comment markers (e.g. //) are
+    // stripped out.  For block comments, leading whitespace and an asterisk
+    // will be stripped from the beginning of each line other than the first.
+    // Newlines are included in the output.
+    //
+    // Examples:
+    //
+    //   optional int32 foo = 1;  // Comment attached to foo.
+    //   // Comment attached to bar.
+    //   optional int32 bar = 2;
+    //
+    //   optional string baz = 3;
+    //   // Comment attached to baz.
+    //   // Another line attached to baz.
+    //
+    //   // Comment attached to qux.
+    //   //
+    //   // Another line attached to qux.
+    //   optional double qux = 4;
+    //
+    //   // Detached comment for corge. This is not leading or trailing comments
+    //   // to qux or corge because there are blank lines separating it from
+    //   // both.
+    //
+    //   // Detached comment for corge paragraph 2.
+    //
+    //   optional string corge = 5;
+    //   /* Block comment attached
+    //    * to corge.  Leading asterisks
+    //    * will be removed. */
+    //   /* Block comment attached to
+    //    * grault. */
+    //   optional int32 grault = 6;
+    //
+    //   // ignored detached comments.
+    optional string leading_comments = 3;
+    optional string trailing_comments = 4;
+    repeated string leading_detached_comments = 6;
+  }
+}
+
+// Describes the relationship between generated code and its original source
+// file. A GeneratedCodeInfo message is associated with only one generated
+// source file, but may contain references to different source .proto files.
+message GeneratedCodeInfo {
+  // An Annotation connects some span of text in generated code to an element
+  // of its generating .proto file.
+  repeated Annotation annotation = 1;
+  message Annotation {
+    // Identifies the element in the original source .proto file. This field
+    // is formatted the same as SourceCodeInfo.Location.path.
+    repeated int32 path = 1 [packed=true];
+
+    // Identifies the filesystem path to the original source .proto.
+    optional string source_file = 2;
+
+    // Identifies the starting offset in bytes in the generated code
+    // that relates to the identified object.
+    optional int32 begin = 3;
+
+    // Identifies the ending offset in bytes in the generated code that
+    // relates to the identified offset. The end offset should be one past
+    // the last relevant byte (so the length of the text = end - begin).
+    optional int32 end = 4;
+  }
+}

+ 179 - 0
components/spotify/cspot/bell/nanopb/generator/proto/nanopb.proto

@@ -0,0 +1,179 @@
+// Custom options for defining:
+// - Maximum size of string/bytes
+// - Maximum number of elements in array
+//
+// These are used by nanopb to generate statically allocable structures
+// for memory-limited environments.
+
+syntax = "proto2";
+import "google/protobuf/descriptor.proto";
+
+option java_package = "fi.kapsi.koti.jpa.nanopb";
+
+enum FieldType {
+    FT_DEFAULT = 0; // Automatically decide field type, generate static field if possible.
+    FT_CALLBACK = 1; // Always generate a callback field.
+    FT_POINTER = 4; // Always generate a dynamically allocated field.
+    FT_STATIC = 2; // Generate a static field or raise an exception if not possible.
+    FT_IGNORE = 3; // Ignore the field completely.
+    FT_INLINE = 5; // Legacy option, use the separate 'fixed_length' option instead
+}
+
+enum IntSize {
+    IS_DEFAULT = 0; // Default, 32/64bit based on type in .proto
+    IS_8 = 8;
+    IS_16 = 16;
+    IS_32 = 32;
+    IS_64 = 64;
+}
+
+enum TypenameMangling {
+    M_NONE = 0; // Default, no typename mangling
+    M_STRIP_PACKAGE = 1; // Strip current package name
+    M_FLATTEN = 2; // Only use last path component
+    M_PACKAGE_INITIALS = 3; // Replace the package name by the initials
+}
+
+enum DescriptorSize {
+    DS_AUTO = 0; // Select minimal size based on field type
+    DS_1 = 1;    // 1 word; up to 15 byte fields, no arrays
+    DS_2 = 2;    // 2 words; up to 4095 byte fields, 4095 entry arrays
+    DS_4 = 4;    // 4 words; up to 2^32-1 byte fields, 2^16-1 entry arrays
+    DS_8 = 8;    // 8 words; up to 2^32-1 entry arrays
+}
+
+// This is the inner options message, which basically defines options for
+// a field. When it is used in message or file scope, it applies to all
+// fields.
+message NanoPBOptions {
+  // Allocated size for 'bytes' and 'string' fields.
+  // For string fields, this should include the space for null terminator.
+  optional int32 max_size = 1;
+  
+  // Maximum length for 'string' fields. Setting this is equivalent
+  // to setting max_size to a value of length+1.
+  optional int32 max_length = 14;
+  
+  // Allocated number of entries in arrays ('repeated' fields)
+  optional int32 max_count = 2;
+  
+  // Size of integer fields. Can save some memory if you don't need
+  // full 32 bits for the value.
+  optional IntSize int_size = 7 [default = IS_DEFAULT];
+
+  // Force type of field (callback or static allocation)
+  optional FieldType type = 3 [default = FT_DEFAULT];
+  
+  // Use long names for enums, i.e. EnumName_EnumValue.
+  optional bool long_names = 4 [default = true];
+  
+  // Add 'packed' attribute to generated structs.
+  // Note: this cannot be used on CPUs that break on unaligned
+  // accesses to variables.
+  optional bool packed_struct = 5 [default = false];
+  
+  // Add 'packed' attribute to generated enums.
+  optional bool packed_enum = 10 [default = false];
+  
+  // Skip this message
+  optional bool skip_message = 6 [default = false];
+
+  // Generate oneof fields as normal optional fields instead of union.
+  optional bool no_unions = 8 [default = false];
+
+  // integer type tag for a message
+  optional uint32 msgid = 9;
+
+  // decode oneof as anonymous union
+  optional bool anonymous_oneof = 11 [default = false];
+
+  // Proto3 singular field does not generate a "has_" flag
+  optional bool proto3 = 12 [default = false];
+  
+  // Force proto3 messages to have no "has_" flag.
+  // This was default behavior until nanopb-0.4.0.
+  optional bool proto3_singular_msgs = 21 [default = false];
+
+  // Generate an enum->string mapping function (can take up lots of space).
+  optional bool enum_to_string = 13 [default = false];
+
+  // Generate bytes arrays with fixed length
+  optional bool fixed_length = 15 [default = false];
+
+  // Generate repeated field with fixed count
+  optional bool fixed_count = 16 [default = false];
+
+  // Generate message-level callback that is called before decoding submessages.
+  // This can be used to set callback fields for submsgs inside oneofs.
+  optional bool submsg_callback = 22 [default = false];
+
+  // Shorten or remove package names from type names.
+  // This option applies only on the file level.
+  optional TypenameMangling mangle_names = 17 [default = M_NONE];
+
+  // Data type for storage associated with callback fields.
+  optional string callback_datatype = 18 [default = "pb_callback_t"];
+
+  // Callback function used for encoding and decoding.
+  // Prior to nanopb-0.4.0, the callback was specified in per-field pb_callback_t
+  // structure. This is still supported, but does not work inside e.g. oneof or pointer
+  // fields. Instead, a new method allows specifying a per-message callback that
+  // will be called for all callback fields in a message type.
+  optional string callback_function = 19 [default = "pb_default_field_callback"];
+
+  // Select the size of field descriptors. This option has to be defined
+  // for the whole message, not per-field. Usually automatic selection is
+  // ok, but if it results in compilation errors you can increase the field
+  // size here.
+  optional DescriptorSize descriptorsize = 20 [default = DS_AUTO];
+
+  // Set default value for has_ fields.
+  optional bool default_has = 23 [default = false];
+
+  // Extra files to include in generated `.pb.h`
+  repeated string include = 24;
+
+  // Automatic includes to exclude from generated `.pb.h`
+  // Same as nanopb_generator.py command line flag -x.
+  repeated string exclude = 26;
+
+  // Package name that applies only for nanopb.
+  optional string package = 25;
+  
+  // Override type of the field in generated C code. Only to be used with related field types
+  optional google.protobuf.FieldDescriptorProto.Type type_override = 27;
+
+  // Due to historical reasons, nanopb orders fields in structs by their tag number
+  // instead of the order in .proto. Set this to false to keep the .proto order.
+  // The default value will probably change to false in nanopb-0.5.0.
+  optional bool sort_by_tag = 28 [default = true];
+}
+
+// Extensions to protoc 'Descriptor' type in order to define options
+// inside a .proto file.
+//
+// Protocol Buffers extension number registry
+// --------------------------------
+// Project:  Nanopb
+// Contact:  Petteri Aimonen <jpa@kapsi.fi>
+// Web site: http://kapsi.fi/~jpa/nanopb
+// Extensions: 1010 (all types)
+// --------------------------------
+
+extend google.protobuf.FileOptions {
+    optional NanoPBOptions nanopb_fileopt = 1010;
+}
+
+extend google.protobuf.MessageOptions {
+    optional NanoPBOptions nanopb_msgopt = 1010;
+}
+
+extend google.protobuf.EnumOptions {
+    optional NanoPBOptions nanopb_enumopt = 1010;
+}
+
+extend google.protobuf.FieldOptions {
+    optional NanoPBOptions nanopb = 1010;
+}
+
+

+ 28 - 0
components/spotify/cspot/bell/nanopb/generator/protoc

@@ -0,0 +1,28 @@
+#!/usr/bin/env python3
+
+import sys
+import os
+import os.path
+from nanopb_generator import invoke_protoc
+
+if __name__ == '__main__':
+    # Add argument so that protoc-gen-nanopb gets found
+    if getattr(sys, 'frozen', False):
+        mypath = os.path.dirname(sys.executable) # For pyInstaller
+    else:
+        mypath = os.path.dirname(__file__)
+
+    if os.path.isfile(os.path.join(mypath, "protoc-gen-nanopb.exe")):
+        protoc_gen_nanopb = os.path.join(mypath, "protoc-gen-nanopb.exe")
+    elif os.name == 'nt':
+        protoc_gen_nanopb = os.path.join(mypath, "protoc-gen-nanopb.bat")
+    else:
+        protoc_gen_nanopb = os.path.join(mypath, "protoc-gen-nanopb")
+
+    args = sys.argv[1:]
+
+    if os.path.isfile(protoc_gen_nanopb):
+         args = ['--plugin=protoc-gen-nanopb=%s' % protoc_gen_nanopb] + args
+
+    status = invoke_protoc(['protoc'] + args)
+    sys.exit(status)

+ 13 - 0
components/spotify/cspot/bell/nanopb/generator/protoc-gen-nanopb

@@ -0,0 +1,13 @@
+#!/bin/sh
+
+# This file is used to invoke nanopb_generator.py as a plugin
+# to protoc on Linux and other *nix-style systems.
+# Use it like this:
+# protoc --plugin=protoc-gen-nanopb=..../protoc-gen-nanopb --nanopb_out=dir foo.proto
+#
+# Note that if you use the binary package of nanopb, the protoc
+# path is already set up properly and there is no need to give
+# --plugin= on the command line.
+
+MYPATH=$(dirname "$0")
+exec "$MYPATH/nanopb_generator.py" --protoc-plugin

+ 16 - 0
components/spotify/cspot/bell/nanopb/generator/protoc-gen-nanopb-py2

@@ -0,0 +1,16 @@
+#!/bin/sh
+
+# This file is used to invoke nanopb_generator.py2 as a plugin
+# to protoc on Linux and other *nix-style systems.
+#
+# The difference from protoc-gen-nanopb is that this executes with Python 2.
+#
+# Use it like this:
+# protoc --plugin=protoc-gen-nanopb=..../protoc-gen-nanopb-py2 --nanopb_out=dir foo.proto
+#
+# Note that if you use the binary package of nanopb, the protoc
+# path is already set up properly and there is no need to give
+# --plugin= on the command line.
+
+MYPATH=$(dirname "$0")
+exec "$MYPATH/nanopb_generator.py2" --protoc-plugin

+ 12 - 0
components/spotify/cspot/bell/nanopb/generator/protoc-gen-nanopb.bat

@@ -0,0 +1,12 @@
+@echo off
+:: This file is used to invoke nanopb_generator.py as a plugin
+:: to protoc on Windows.
+:: Use it like this:
+:: protoc --plugin=protoc-gen-nanopb=..../protoc-gen-nanopb.bat --nanopb_out=dir foo.proto
+::
+:: Note that if you use the binary package of nanopb, the protoc
+:: path is already set up properly and there is no need to give
+:: --plugin= on the command line.
+
+set mydir=%~dp0
+python "%mydir%\nanopb_generator.py" --protoc-plugin %*

+ 9 - 0
components/spotify/cspot/bell/nanopb/generator/protoc.bat

@@ -0,0 +1,9 @@
+@echo off
+:: This file acts as a drop-in replacement of binary protoc.exe.
+:: It will use either Python-based protoc from grpcio-tools package,
+:: or if it is not available, protoc.exe from path if found.
+
+setLocal enableDelayedExpansion
+set mydir=%~dp0
+python "%mydir%\protoc" %*
+exit /b %ERRORLEVEL%

+ 42 - 0
components/spotify/cspot/bell/nanopb/library.json

@@ -0,0 +1,42 @@
+{
+  "name": "Nanopb",
+  "version": "0.4.6.3",
+  "keywords": "protocol buffers, protobuf, google",
+  "description": "Nanopb is a plain-C implementation of Google's Protocol Buffers data format. It is targeted at 32 bit microcontrollers, but is also fit for other embedded systems with tight (<10 kB ROM, <1 kB RAM) memory constraints.",
+  "repository": {
+    "type": "git",
+    "url": "https://github.com/nanopb/nanopb.git"
+  },
+  "authors": [{
+    "name": "Petteri Aimonen",
+    "email": "jpa@nanopb.mail.kapsi.fi",
+    "url": "http://koti.kapsi.fi/jpa/nanopb/"
+  }],
+  "export": {
+    "include": [
+      "*.c",
+      "*.cpp",
+      "*.h",
+      "examples",
+      "generator"
+    ],
+    "exclude": [
+      "generator/**/__pycache__",
+      "examples/platformio/.gitignore"
+    ]
+  },
+  "build": {
+    "extraScript": "generator/platformio_generator.py",
+    "srcDir": "",
+    "srcFilter": [
+      "+<*.c>"
+    ]
+  },
+  "examples": [
+    "examples/platformio/platformio.ini",
+    "examples/platformio/src/*.c",
+    "examples/*/*.c"
+  ],
+  "frameworks": "*",
+  "platforms": "*"
+}

+ 895 - 0
components/spotify/cspot/bell/nanopb/pb.h

@@ -0,0 +1,895 @@
+/* Common parts of the nanopb library. Most of these are quite low-level
+ * stuff. For the high-level interface, see pb_encode.h and pb_decode.h.
+ */
+
+#ifndef PB_H_INCLUDED
+#define PB_H_INCLUDED
+
+/*****************************************************************
+ * Nanopb compilation time options. You can change these here by *
+ * uncommenting the lines, or on the compiler command line.      *
+ *****************************************************************/
+
+/* Enable support for dynamically allocated fields */
+/* #define PB_ENABLE_MALLOC 1 */
+
+/* Define this if your CPU / compiler combination does not support
+ * unaligned memory access to packed structures. Note that packed
+ * structures are only used when requested in .proto options. */
+/* #define PB_NO_PACKED_STRUCTS 1 */
+
+/* Increase the number of required fields that are tracked.
+ * A compiler warning will tell if you need this. */
+/* #define PB_MAX_REQUIRED_FIELDS 256 */
+
+/* Add support for tag numbers > 65536 and fields larger than 65536 bytes. */
+/* #define PB_FIELD_32BIT 1 */
+
+/* Disable support for error messages in order to save some code space. */
+/* #define PB_NO_ERRMSG 1 */
+
+/* Disable support for custom streams (support only memory buffers). */
+/* #define PB_BUFFER_ONLY 1 */
+
+/* Disable support for 64-bit datatypes, for compilers without int64_t
+   or to save some code space. */
+/* #define PB_WITHOUT_64BIT 1 */
+
+/* Don't encode scalar arrays as packed. This is only to be used when
+ * the decoder on the receiving side cannot process packed scalar arrays.
+ * Such example is older protobuf.js. */
+/* #define PB_ENCODE_ARRAYS_UNPACKED 1 */
+
+/* Enable conversion of doubles to floats for platforms that do not
+ * support 64-bit doubles. Most commonly AVR. */
+/* #define PB_CONVERT_DOUBLE_FLOAT 1 */
+
+/* Check whether incoming strings are valid UTF-8 sequences. Slows down
+ * the string processing slightly and slightly increases code size. */
+/* #define PB_VALIDATE_UTF8 1 */
+
+/* This can be defined if the platform is little-endian and has 8-bit bytes.
+ * Normally it is automatically detected based on __BYTE_ORDER__ macro. */
+/* #define PB_LITTLE_ENDIAN_8BIT 1 */
+
+/******************************************************************
+ * You usually don't need to change anything below this line.     *
+ * Feel free to look around and use the defined macros, though.   *
+ ******************************************************************/
+
+
+/* Version of the nanopb library. Just in case you want to check it in
+ * your own program. */
+#define NANOPB_VERSION "nanopb-0.4.6-dev"
+
+/* Include all the system headers needed by nanopb. You will need the
+ * definitions of the following:
+ * - strlen, memcpy, memset functions
+ * - [u]int_least8_t, uint_fast8_t, [u]int_least16_t, [u]int32_t, [u]int64_t
+ * - size_t
+ * - bool
+ *
+ * If you don't have the standard header files, you can instead provide
+ * a custom header that defines or includes all this. In that case,
+ * define PB_SYSTEM_HEADER to the path of this file.
+ */
+#ifdef PB_SYSTEM_HEADER
+#include PB_SYSTEM_HEADER
+#else
+#include <stdint.h>
+#include <stddef.h>
+#include <stdbool.h>
+#include <string.h>
+#include <limits.h>
+
+#ifdef PB_ENABLE_MALLOC
+#include <stdlib.h>
+#endif
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Macro for defining packed structures (compiler dependent).
+ * This just reduces memory requirements, but is not required.
+ */
+#if defined(PB_NO_PACKED_STRUCTS)
+    /* Disable struct packing */
+#   define PB_PACKED_STRUCT_START
+#   define PB_PACKED_STRUCT_END
+#   define pb_packed
+#elif defined(__GNUC__) || defined(__clang__)
+    /* For GCC and clang */
+#   define PB_PACKED_STRUCT_START
+#   define PB_PACKED_STRUCT_END
+#   define pb_packed __attribute__((packed))
+#elif defined(__ICCARM__) || defined(__CC_ARM)
+    /* For IAR ARM and Keil MDK-ARM compilers */
+#   define PB_PACKED_STRUCT_START _Pragma("pack(push, 1)")
+#   define PB_PACKED_STRUCT_END _Pragma("pack(pop)")
+#   define pb_packed
+#elif defined(_MSC_VER) && (_MSC_VER >= 1500)
+    /* For Microsoft Visual C++ */
+#   define PB_PACKED_STRUCT_START __pragma(pack(push, 1))
+#   define PB_PACKED_STRUCT_END __pragma(pack(pop))
+#   define pb_packed
+#else
+    /* Unknown compiler */
+#   define PB_PACKED_STRUCT_START
+#   define PB_PACKED_STRUCT_END
+#   define pb_packed
+#endif
+
+/* Detect endianness */
+#ifndef PB_LITTLE_ENDIAN_8BIT
+#if ((defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN) || \
+     (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) || \
+      defined(__LITTLE_ENDIAN__) || defined(__ARMEL__) || \
+      defined(__THUMBEL__) || defined(__AARCH64EL__) || defined(_MIPSEL) || \
+      defined(_M_IX86) || defined(_M_X64) || defined(_M_ARM)) \
+     && CHAR_BIT == 8
+#define PB_LITTLE_ENDIAN_8BIT 1
+#endif
+#endif
+
+/* Handly macro for suppressing unreferenced-parameter compiler warnings. */
+#ifndef PB_UNUSED
+#define PB_UNUSED(x) (void)(x)
+#endif
+
+/* Harvard-architecture processors may need special attributes for storing
+ * field information in program memory. */
+#ifndef PB_PROGMEM
+#ifdef __AVR__
+#include <avr/pgmspace.h>
+#define PB_PROGMEM             PROGMEM
+#define PB_PROGMEM_READU32(x)  pgm_read_dword(&x)
+#else
+#define PB_PROGMEM
+#define PB_PROGMEM_READU32(x)  (x)
+#endif
+#endif
+
+/* Compile-time assertion, used for checking compatible compilation options.
+ * If this does not work properly on your compiler, use
+ * #define PB_NO_STATIC_ASSERT to disable it.
+ *
+ * But before doing that, check carefully the error message / place where it
+ * comes from to see if the error has a real cause. Unfortunately the error
+ * message is not always very clear to read, but you can see the reason better
+ * in the place where the PB_STATIC_ASSERT macro was called.
+ */
+#ifndef PB_NO_STATIC_ASSERT
+#  ifndef PB_STATIC_ASSERT
+#    if defined(__ICCARM__)
+       /* IAR has static_assert keyword but no _Static_assert */
+#      define PB_STATIC_ASSERT(COND,MSG) static_assert(COND,#MSG);
+#    elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
+       /* C11 standard _Static_assert mechanism */
+#      define PB_STATIC_ASSERT(COND,MSG) _Static_assert(COND,#MSG);
+#    else
+       /* Classic negative-size-array static assert mechanism */
+#      define PB_STATIC_ASSERT(COND,MSG) typedef char PB_STATIC_ASSERT_MSG(MSG, __LINE__, __COUNTER__)[(COND)?1:-1];
+#      define PB_STATIC_ASSERT_MSG(MSG, LINE, COUNTER) PB_STATIC_ASSERT_MSG_(MSG, LINE, COUNTER)
+#      define PB_STATIC_ASSERT_MSG_(MSG, LINE, COUNTER) pb_static_assertion_##MSG##_##LINE##_##COUNTER
+#    endif
+#  endif
+#else
+   /* Static asserts disabled by PB_NO_STATIC_ASSERT */
+#  define PB_STATIC_ASSERT(COND,MSG)
+#endif
+
+/* Number of required fields to keep track of. */
+#ifndef PB_MAX_REQUIRED_FIELDS
+#define PB_MAX_REQUIRED_FIELDS 64
+#endif
+
+#if PB_MAX_REQUIRED_FIELDS < 64
+#error You should not lower PB_MAX_REQUIRED_FIELDS from the default value (64).
+#endif
+
+#ifdef PB_WITHOUT_64BIT
+#ifdef PB_CONVERT_DOUBLE_FLOAT
+/* Cannot use doubles without 64-bit types */
+#undef PB_CONVERT_DOUBLE_FLOAT
+#endif
+#endif
+
+/* List of possible field types. These are used in the autogenerated code.
+ * Least-significant 4 bits tell the scalar type
+ * Most-significant 4 bits specify repeated/required/packed etc.
+ */
+
+typedef uint_least8_t pb_type_t;
+
+/**** Field data types ****/
+
+/* Numeric types */
+#define PB_LTYPE_BOOL    0x00U /* bool */
+#define PB_LTYPE_VARINT  0x01U /* int32, int64, enum, bool */
+#define PB_LTYPE_UVARINT 0x02U /* uint32, uint64 */
+#define PB_LTYPE_SVARINT 0x03U /* sint32, sint64 */
+#define PB_LTYPE_FIXED32 0x04U /* fixed32, sfixed32, float */
+#define PB_LTYPE_FIXED64 0x05U /* fixed64, sfixed64, double */
+
+/* Marker for last packable field type. */
+#define PB_LTYPE_LAST_PACKABLE 0x05U
+
+/* Byte array with pre-allocated buffer.
+ * data_size is the length of the allocated PB_BYTES_ARRAY structure. */
+#define PB_LTYPE_BYTES 0x06U
+
+/* String with pre-allocated buffer.
+ * data_size is the maximum length. */
+#define PB_LTYPE_STRING 0x07U
+
+/* Submessage
+ * submsg_fields is pointer to field descriptions */
+#define PB_LTYPE_SUBMESSAGE 0x08U
+
+/* Submessage with pre-decoding callback
+ * The pre-decoding callback is stored as pb_callback_t right before pSize.
+ * submsg_fields is pointer to field descriptions */
+#define PB_LTYPE_SUBMSG_W_CB 0x09U
+
+/* Extension pseudo-field
+ * The field contains a pointer to pb_extension_t */
+#define PB_LTYPE_EXTENSION 0x0AU
+
+/* Byte array with inline, pre-allocated byffer.
+ * data_size is the length of the inline, allocated buffer.
+ * This differs from PB_LTYPE_BYTES by defining the element as
+ * pb_byte_t[data_size] rather than pb_bytes_array_t. */
+#define PB_LTYPE_FIXED_LENGTH_BYTES 0x0BU
+
+/* Number of declared LTYPES */
+#define PB_LTYPES_COUNT 0x0CU
+#define PB_LTYPE_MASK 0x0FU
+
+/**** Field repetition rules ****/
+
+#define PB_HTYPE_REQUIRED 0x00U
+#define PB_HTYPE_OPTIONAL 0x10U
+#define PB_HTYPE_SINGULAR 0x10U
+#define PB_HTYPE_REPEATED 0x20U
+#define PB_HTYPE_FIXARRAY 0x20U
+#define PB_HTYPE_ONEOF    0x30U
+#define PB_HTYPE_MASK     0x30U
+
+/**** Field allocation types ****/
+
+#define PB_ATYPE_STATIC   0x00U
+#define PB_ATYPE_POINTER  0x80U
+#define PB_ATYPE_CALLBACK 0x40U
+#define PB_ATYPE_MASK     0xC0U
+
+#define PB_ATYPE(x) ((x) & PB_ATYPE_MASK)
+#define PB_HTYPE(x) ((x) & PB_HTYPE_MASK)
+#define PB_LTYPE(x) ((x) & PB_LTYPE_MASK)
+#define PB_LTYPE_IS_SUBMSG(x) (PB_LTYPE(x) == PB_LTYPE_SUBMESSAGE || \
+                               PB_LTYPE(x) == PB_LTYPE_SUBMSG_W_CB)
+
+/* Data type used for storing sizes of struct fields
+ * and array counts.
+ */
+#if defined(PB_FIELD_32BIT)
+    typedef uint32_t pb_size_t;
+    typedef int32_t pb_ssize_t;
+#else
+    typedef uint_least16_t pb_size_t;
+    typedef int_least16_t pb_ssize_t;
+#endif
+#define PB_SIZE_MAX ((pb_size_t)-1)
+
+/* Data type for storing encoded data and other byte streams.
+ * This typedef exists to support platforms where uint8_t does not exist.
+ * You can regard it as equivalent on uint8_t on other platforms.
+ */
+typedef uint_least8_t pb_byte_t;
+
+/* Forward declaration of struct types */
+typedef struct pb_istream_s pb_istream_t;
+typedef struct pb_ostream_s pb_ostream_t;
+typedef struct pb_field_iter_s pb_field_iter_t;
+
+/* This structure is used in auto-generated constants
+ * to specify struct fields.
+ */
+typedef struct pb_msgdesc_s pb_msgdesc_t;
+struct pb_msgdesc_s {
+    const uint32_t *field_info;
+    const pb_msgdesc_t * const * submsg_info;
+    const pb_byte_t *default_value;
+
+    bool (*field_callback)(pb_istream_t *istream, pb_ostream_t *ostream, const pb_field_iter_t *field);
+
+    pb_size_t field_count;
+    pb_size_t required_field_count;
+    pb_size_t largest_tag;
+};
+
+/* Iterator for message descriptor */
+struct pb_field_iter_s {
+    const pb_msgdesc_t *descriptor;  /* Pointer to message descriptor constant */
+    void *message;                   /* Pointer to start of the structure */
+
+    pb_size_t index;                 /* Index of the field */
+    pb_size_t field_info_index;      /* Index to descriptor->field_info array */
+    pb_size_t required_field_index;  /* Index that counts only the required fields */
+    pb_size_t submessage_index;      /* Index that counts only submessages */
+
+    pb_size_t tag;                   /* Tag of current field */
+    pb_size_t data_size;             /* sizeof() of a single item */
+    pb_size_t array_size;            /* Number of array entries */
+    pb_type_t type;                  /* Type of current field */
+
+    void *pField;                    /* Pointer to current field in struct */
+    void *pData;                     /* Pointer to current data contents. Different than pField for arrays and pointers. */
+    void *pSize;                     /* Pointer to count/has field */
+
+    const pb_msgdesc_t *submsg_desc; /* For submessage fields, pointer to field descriptor for the submessage. */
+};
+
+/* For compatibility with legacy code */
+typedef pb_field_iter_t pb_field_t;
+
+/* Make sure that the standard integer types are of the expected sizes.
+ * Otherwise fixed32/fixed64 fields can break.
+ *
+ * If you get errors here, it probably means that your stdint.h is not
+ * correct for your platform.
+ */
+#ifndef PB_WITHOUT_64BIT
+PB_STATIC_ASSERT(sizeof(int64_t) == 2 * sizeof(int32_t), INT64_T_WRONG_SIZE)
+PB_STATIC_ASSERT(sizeof(uint64_t) == 2 * sizeof(uint32_t), UINT64_T_WRONG_SIZE)
+#endif
+
+/* This structure is used for 'bytes' arrays.
+ * It has the number of bytes in the beginning, and after that an array.
+ * Note that actual structs used will have a different length of bytes array.
+ */
+#define PB_BYTES_ARRAY_T(n) struct { pb_size_t size; pb_byte_t bytes[n]; }
+#define PB_BYTES_ARRAY_T_ALLOCSIZE(n) ((size_t)n + offsetof(pb_bytes_array_t, bytes))
+
+struct pb_bytes_array_s {
+    pb_size_t size;
+    pb_byte_t bytes[1];
+};
+typedef struct pb_bytes_array_s pb_bytes_array_t;
+
+/* This structure is used for giving the callback function.
+ * It is stored in the message structure and filled in by the method that
+ * calls pb_decode.
+ *
+ * The decoding callback will be given a limited-length stream
+ * If the wire type was string, the length is the length of the string.
+ * If the wire type was a varint/fixed32/fixed64, the length is the length
+ * of the actual value.
+ * The function may be called multiple times (especially for repeated types,
+ * but also otherwise if the message happens to contain the field multiple
+ * times.)
+ *
+ * The encoding callback will receive the actual output stream.
+ * It should write all the data in one call, including the field tag and
+ * wire type. It can write multiple fields.
+ *
+ * The callback can be null if you want to skip a field.
+ */
+typedef struct pb_callback_s pb_callback_t;
+struct pb_callback_s {
+    /* Callback functions receive a pointer to the arg field.
+     * You can access the value of the field as *arg, and modify it if needed.
+     */
+    union {
+        bool (*decode)(pb_istream_t *stream, const pb_field_t *field, void **arg);
+        bool (*encode)(pb_ostream_t *stream, const pb_field_t *field, void * const *arg);
+    } funcs;
+
+    /* Free arg for use by callback */
+    void *arg;
+};
+
+extern bool pb_default_field_callback(pb_istream_t *istream, pb_ostream_t *ostream, const pb_field_t *field);
+
+/* Wire types. Library user needs these only in encoder callbacks. */
+typedef enum {
+    PB_WT_VARINT = 0,
+    PB_WT_64BIT  = 1,
+    PB_WT_STRING = 2,
+    PB_WT_32BIT  = 5,
+    PB_WT_PACKED = 255 /* PB_WT_PACKED is internal marker for packed arrays. */
+} pb_wire_type_t;
+
+/* Structure for defining the handling of unknown/extension fields.
+ * Usually the pb_extension_type_t structure is automatically generated,
+ * while the pb_extension_t structure is created by the user. However,
+ * if you want to catch all unknown fields, you can also create a custom
+ * pb_extension_type_t with your own callback.
+ */
+typedef struct pb_extension_type_s pb_extension_type_t;
+typedef struct pb_extension_s pb_extension_t;
+struct pb_extension_type_s {
+    /* Called for each unknown field in the message.
+     * If you handle the field, read off all of its data and return true.
+     * If you do not handle the field, do not read anything and return true.
+     * If you run into an error, return false.
+     * Set to NULL for default handler.
+     */
+    bool (*decode)(pb_istream_t *stream, pb_extension_t *extension,
+                   uint32_t tag, pb_wire_type_t wire_type);
+
+    /* Called once after all regular fields have been encoded.
+     * If you have something to write, do so and return true.
+     * If you do not have anything to write, just return true.
+     * If you run into an error, return false.
+     * Set to NULL for default handler.
+     */
+    bool (*encode)(pb_ostream_t *stream, const pb_extension_t *extension);
+
+    /* Free field for use by the callback. */
+    const void *arg;
+};
+
+struct pb_extension_s {
+    /* Type describing the extension field. Usually you'll initialize
+     * this to a pointer to the automatically generated structure. */
+    const pb_extension_type_t *type;
+
+    /* Destination for the decoded data. This must match the datatype
+     * of the extension field. */
+    void *dest;
+
+    /* Pointer to the next extension handler, or NULL.
+     * If this extension does not match a field, the next handler is
+     * automatically called. */
+    pb_extension_t *next;
+
+    /* The decoder sets this to true if the extension was found.
+     * Ignored for encoding. */
+    bool found;
+};
+
+#define pb_extension_init_zero {NULL,NULL,NULL,false}
+
+/* Memory allocation functions to use. You can define pb_realloc and
+ * pb_free to custom functions if you want. */
+#ifdef PB_ENABLE_MALLOC
+#   ifndef pb_realloc
+#       define pb_realloc(ptr, size) realloc(ptr, size)
+#   endif
+#   ifndef pb_free
+#       define pb_free(ptr) free(ptr)
+#   endif
+#endif
+
+/* This is used to inform about need to regenerate .pb.h/.pb.c files. */
+#define PB_PROTO_HEADER_VERSION 40
+
+/* These macros are used to declare pb_field_t's in the constant array. */
+/* Size of a structure member, in bytes. */
+#define pb_membersize(st, m) (sizeof ((st*)0)->m)
+/* Number of entries in an array. */
+#define pb_arraysize(st, m) (pb_membersize(st, m) / pb_membersize(st, m[0]))
+/* Delta from start of one member to the start of another member. */
+#define pb_delta(st, m1, m2) ((int)offsetof(st, m1) - (int)offsetof(st, m2))
+
+/* Force expansion of macro value */
+#define PB_EXPAND(x) x
+
+/* Binding of a message field set into a specific structure */
+#define PB_BIND(msgname, structname, width) \
+    const uint32_t structname ## _field_info[] PB_PROGMEM = \
+    { \
+        msgname ## _FIELDLIST(PB_GEN_FIELD_INFO_ ## width, structname) \
+        0 \
+    }; \
+    const pb_msgdesc_t* const structname ## _submsg_info[] = \
+    { \
+        msgname ## _FIELDLIST(PB_GEN_SUBMSG_INFO, structname) \
+        NULL \
+    }; \
+    const pb_msgdesc_t structname ## _msg = \
+    { \
+       structname ## _field_info, \
+       structname ## _submsg_info, \
+       msgname ## _DEFAULT, \
+       msgname ## _CALLBACK, \
+       0 msgname ## _FIELDLIST(PB_GEN_FIELD_COUNT, structname), \
+       0 msgname ## _FIELDLIST(PB_GEN_REQ_FIELD_COUNT, structname), \
+       0 msgname ## _FIELDLIST(PB_GEN_LARGEST_TAG, structname), \
+    }; \
+    msgname ## _FIELDLIST(PB_GEN_FIELD_INFO_ASSERT_ ## width, structname)
+
+#define PB_GEN_FIELD_COUNT(structname, atype, htype, ltype, fieldname, tag) +1
+#define PB_GEN_REQ_FIELD_COUNT(structname, atype, htype, ltype, fieldname, tag) \
+    + (PB_HTYPE_ ## htype == PB_HTYPE_REQUIRED)
+#define PB_GEN_LARGEST_TAG(structname, atype, htype, ltype, fieldname, tag) \
+    * 0 + tag
+
+/* X-macro for generating the entries in struct_field_info[] array. */
+#define PB_GEN_FIELD_INFO_1(structname, atype, htype, ltype, fieldname, tag) \
+    PB_FIELDINFO_1(tag, PB_ATYPE_ ## atype | PB_HTYPE_ ## htype | PB_LTYPE_MAP_ ## ltype, \
+                   PB_DATA_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
+                   PB_DATA_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
+                   PB_SIZE_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
+                   PB_ARRAY_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname))
+
+#define PB_GEN_FIELD_INFO_2(structname, atype, htype, ltype, fieldname, tag) \
+    PB_FIELDINFO_2(tag, PB_ATYPE_ ## atype | PB_HTYPE_ ## htype | PB_LTYPE_MAP_ ## ltype, \
+                   PB_DATA_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
+                   PB_DATA_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
+                   PB_SIZE_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
+                   PB_ARRAY_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname))
+
+#define PB_GEN_FIELD_INFO_4(structname, atype, htype, ltype, fieldname, tag) \
+    PB_FIELDINFO_4(tag, PB_ATYPE_ ## atype | PB_HTYPE_ ## htype | PB_LTYPE_MAP_ ## ltype, \
+                   PB_DATA_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
+                   PB_DATA_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
+                   PB_SIZE_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
+                   PB_ARRAY_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname))
+
+#define PB_GEN_FIELD_INFO_8(structname, atype, htype, ltype, fieldname, tag) \
+    PB_FIELDINFO_8(tag, PB_ATYPE_ ## atype | PB_HTYPE_ ## htype | PB_LTYPE_MAP_ ## ltype, \
+                   PB_DATA_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
+                   PB_DATA_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
+                   PB_SIZE_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
+                   PB_ARRAY_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname))
+
+#define PB_GEN_FIELD_INFO_AUTO(structname, atype, htype, ltype, fieldname, tag) \
+    PB_FIELDINFO_AUTO2(PB_FIELDINFO_WIDTH_AUTO(_PB_ATYPE_ ## atype, _PB_HTYPE_ ## htype, _PB_LTYPE_ ## ltype), \
+                   tag, PB_ATYPE_ ## atype | PB_HTYPE_ ## htype | PB_LTYPE_MAP_ ## ltype, \
+                   PB_DATA_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
+                   PB_DATA_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
+                   PB_SIZE_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
+                   PB_ARRAY_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname))
+
+#define PB_FIELDINFO_AUTO2(width, tag, type, data_offset, data_size, size_offset, array_size) \
+    PB_FIELDINFO_AUTO3(width, tag, type, data_offset, data_size, size_offset, array_size)
+
+#define PB_FIELDINFO_AUTO3(width, tag, type, data_offset, data_size, size_offset, array_size) \
+    PB_FIELDINFO_ ## width(tag, type, data_offset, data_size, size_offset, array_size)
+
+/* X-macro for generating asserts that entries fit in struct_field_info[] array.
+ * The structure of macros here must match the structure above in PB_GEN_FIELD_INFO_x(),
+ * but it is not easily reused because of how macro substitutions work. */
+#define PB_GEN_FIELD_INFO_ASSERT_1(structname, atype, htype, ltype, fieldname, tag) \
+    PB_FIELDINFO_ASSERT_1(tag, PB_ATYPE_ ## atype | PB_HTYPE_ ## htype | PB_LTYPE_MAP_ ## ltype, \
+                   PB_DATA_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
+                   PB_DATA_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
+                   PB_SIZE_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
+                   PB_ARRAY_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname))
+
+#define PB_GEN_FIELD_INFO_ASSERT_2(structname, atype, htype, ltype, fieldname, tag) \
+    PB_FIELDINFO_ASSERT_2(tag, PB_ATYPE_ ## atype | PB_HTYPE_ ## htype | PB_LTYPE_MAP_ ## ltype, \
+                   PB_DATA_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
+                   PB_DATA_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
+                   PB_SIZE_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
+                   PB_ARRAY_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname))
+
+#define PB_GEN_FIELD_INFO_ASSERT_4(structname, atype, htype, ltype, fieldname, tag) \
+    PB_FIELDINFO_ASSERT_4(tag, PB_ATYPE_ ## atype | PB_HTYPE_ ## htype | PB_LTYPE_MAP_ ## ltype, \
+                   PB_DATA_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
+                   PB_DATA_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
+                   PB_SIZE_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
+                   PB_ARRAY_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname))
+
+#define PB_GEN_FIELD_INFO_ASSERT_8(structname, atype, htype, ltype, fieldname, tag) \
+    PB_FIELDINFO_ASSERT_8(tag, PB_ATYPE_ ## atype | PB_HTYPE_ ## htype | PB_LTYPE_MAP_ ## ltype, \
+                   PB_DATA_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
+                   PB_DATA_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
+                   PB_SIZE_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
+                   PB_ARRAY_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname))
+
+#define PB_GEN_FIELD_INFO_ASSERT_AUTO(structname, atype, htype, ltype, fieldname, tag) \
+    PB_FIELDINFO_ASSERT_AUTO2(PB_FIELDINFO_WIDTH_AUTO(_PB_ATYPE_ ## atype, _PB_HTYPE_ ## htype, _PB_LTYPE_ ## ltype), \
+                   tag, PB_ATYPE_ ## atype | PB_HTYPE_ ## htype | PB_LTYPE_MAP_ ## ltype, \
+                   PB_DATA_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
+                   PB_DATA_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
+                   PB_SIZE_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
+                   PB_ARRAY_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname))
+
+#define PB_FIELDINFO_ASSERT_AUTO2(width, tag, type, data_offset, data_size, size_offset, array_size) \
+    PB_FIELDINFO_ASSERT_AUTO3(width, tag, type, data_offset, data_size, size_offset, array_size)
+
+#define PB_FIELDINFO_ASSERT_AUTO3(width, tag, type, data_offset, data_size, size_offset, array_size) \
+    PB_FIELDINFO_ASSERT_ ## width(tag, type, data_offset, data_size, size_offset, array_size)
+
+#define PB_DATA_OFFSET_STATIC(htype, structname, fieldname) PB_DO ## htype(structname, fieldname)
+#define PB_DATA_OFFSET_POINTER(htype, structname, fieldname) PB_DO ## htype(structname, fieldname)
+#define PB_DATA_OFFSET_CALLBACK(htype, structname, fieldname) PB_DO ## htype(structname, fieldname)
+#define PB_DO_PB_HTYPE_REQUIRED(structname, fieldname) offsetof(structname, fieldname)
+#define PB_DO_PB_HTYPE_SINGULAR(structname, fieldname) offsetof(structname, fieldname)
+#define PB_DO_PB_HTYPE_ONEOF(structname, fieldname) offsetof(structname, PB_ONEOF_NAME(FULL, fieldname))
+#define PB_DO_PB_HTYPE_OPTIONAL(structname, fieldname) offsetof(structname, fieldname)
+#define PB_DO_PB_HTYPE_REPEATED(structname, fieldname) offsetof(structname, fieldname)
+#define PB_DO_PB_HTYPE_FIXARRAY(structname, fieldname) offsetof(structname, fieldname)
+
+#define PB_SIZE_OFFSET_STATIC(htype, structname, fieldname) PB_SO ## htype(structname, fieldname)
+#define PB_SIZE_OFFSET_POINTER(htype, structname, fieldname) PB_SO_PTR ## htype(structname, fieldname)
+#define PB_SIZE_OFFSET_CALLBACK(htype, structname, fieldname) PB_SO_CB ## htype(structname, fieldname)
+#define PB_SO_PB_HTYPE_REQUIRED(structname, fieldname) 0
+#define PB_SO_PB_HTYPE_SINGULAR(structname, fieldname) 0
+#define PB_SO_PB_HTYPE_ONEOF(structname, fieldname) PB_SO_PB_HTYPE_ONEOF2(structname, PB_ONEOF_NAME(FULL, fieldname), PB_ONEOF_NAME(UNION, fieldname))
+#define PB_SO_PB_HTYPE_ONEOF2(structname, fullname, unionname) PB_SO_PB_HTYPE_ONEOF3(structname, fullname, unionname)
+#define PB_SO_PB_HTYPE_ONEOF3(structname, fullname, unionname) pb_delta(structname, fullname, which_ ## unionname)
+#define PB_SO_PB_HTYPE_OPTIONAL(structname, fieldname) pb_delta(structname, fieldname, has_ ## fieldname)
+#define PB_SO_PB_HTYPE_REPEATED(structname, fieldname) pb_delta(structname, fieldname, fieldname ## _count)
+#define PB_SO_PB_HTYPE_FIXARRAY(structname, fieldname) 0
+#define PB_SO_PTR_PB_HTYPE_REQUIRED(structname, fieldname) 0
+#define PB_SO_PTR_PB_HTYPE_SINGULAR(structname, fieldname) 0
+#define PB_SO_PTR_PB_HTYPE_ONEOF(structname, fieldname) PB_SO_PB_HTYPE_ONEOF(structname, fieldname)
+#define PB_SO_PTR_PB_HTYPE_OPTIONAL(structname, fieldname) 0
+#define PB_SO_PTR_PB_HTYPE_REPEATED(structname, fieldname) PB_SO_PB_HTYPE_REPEATED(structname, fieldname)
+#define PB_SO_PTR_PB_HTYPE_FIXARRAY(structname, fieldname) 0
+#define PB_SO_CB_PB_HTYPE_REQUIRED(structname, fieldname) 0
+#define PB_SO_CB_PB_HTYPE_SINGULAR(structname, fieldname) 0
+#define PB_SO_CB_PB_HTYPE_ONEOF(structname, fieldname) PB_SO_PB_HTYPE_ONEOF(structname, fieldname)
+#define PB_SO_CB_PB_HTYPE_OPTIONAL(structname, fieldname) 0
+#define PB_SO_CB_PB_HTYPE_REPEATED(structname, fieldname) 0
+#define PB_SO_CB_PB_HTYPE_FIXARRAY(structname, fieldname) 0
+
+#define PB_ARRAY_SIZE_STATIC(htype, structname, fieldname) PB_AS ## htype(structname, fieldname)
+#define PB_ARRAY_SIZE_POINTER(htype, structname, fieldname) PB_AS_PTR ## htype(structname, fieldname)
+#define PB_ARRAY_SIZE_CALLBACK(htype, structname, fieldname) 1
+#define PB_AS_PB_HTYPE_REQUIRED(structname, fieldname) 1
+#define PB_AS_PB_HTYPE_SINGULAR(structname, fieldname) 1
+#define PB_AS_PB_HTYPE_OPTIONAL(structname, fieldname) 1
+#define PB_AS_PB_HTYPE_ONEOF(structname, fieldname) 1
+#define PB_AS_PB_HTYPE_REPEATED(structname, fieldname) pb_arraysize(structname, fieldname)
+#define PB_AS_PB_HTYPE_FIXARRAY(structname, fieldname) pb_arraysize(structname, fieldname)
+#define PB_AS_PTR_PB_HTYPE_REQUIRED(structname, fieldname) 1
+#define PB_AS_PTR_PB_HTYPE_SINGULAR(structname, fieldname) 1
+#define PB_AS_PTR_PB_HTYPE_OPTIONAL(structname, fieldname) 1
+#define PB_AS_PTR_PB_HTYPE_ONEOF(structname, fieldname) 1
+#define PB_AS_PTR_PB_HTYPE_REPEATED(structname, fieldname) 1
+#define PB_AS_PTR_PB_HTYPE_FIXARRAY(structname, fieldname) pb_arraysize(structname, fieldname[0])
+
+#define PB_DATA_SIZE_STATIC(htype, structname, fieldname) PB_DS ## htype(structname, fieldname)
+#define PB_DATA_SIZE_POINTER(htype, structname, fieldname) PB_DS_PTR ## htype(structname, fieldname)
+#define PB_DATA_SIZE_CALLBACK(htype, structname, fieldname) PB_DS_CB ## htype(structname, fieldname)
+#define PB_DS_PB_HTYPE_REQUIRED(structname, fieldname) pb_membersize(structname, fieldname)
+#define PB_DS_PB_HTYPE_SINGULAR(structname, fieldname) pb_membersize(structname, fieldname)
+#define PB_DS_PB_HTYPE_OPTIONAL(structname, fieldname) pb_membersize(structname, fieldname)
+#define PB_DS_PB_HTYPE_ONEOF(structname, fieldname) pb_membersize(structname, PB_ONEOF_NAME(FULL, fieldname))
+#define PB_DS_PB_HTYPE_REPEATED(structname, fieldname) pb_membersize(structname, fieldname[0])
+#define PB_DS_PB_HTYPE_FIXARRAY(structname, fieldname) pb_membersize(structname, fieldname[0])
+#define PB_DS_PTR_PB_HTYPE_REQUIRED(structname, fieldname) pb_membersize(structname, fieldname[0])
+#define PB_DS_PTR_PB_HTYPE_SINGULAR(structname, fieldname) pb_membersize(structname, fieldname[0])
+#define PB_DS_PTR_PB_HTYPE_OPTIONAL(structname, fieldname) pb_membersize(structname, fieldname[0])
+#define PB_DS_PTR_PB_HTYPE_ONEOF(structname, fieldname) pb_membersize(structname, PB_ONEOF_NAME(FULL, fieldname)[0])
+#define PB_DS_PTR_PB_HTYPE_REPEATED(structname, fieldname) pb_membersize(structname, fieldname[0])
+#define PB_DS_PTR_PB_HTYPE_FIXARRAY(structname, fieldname) pb_membersize(structname, fieldname[0][0])
+#define PB_DS_CB_PB_HTYPE_REQUIRED(structname, fieldname) pb_membersize(structname, fieldname)
+#define PB_DS_CB_PB_HTYPE_SINGULAR(structname, fieldname) pb_membersize(structname, fieldname)
+#define PB_DS_CB_PB_HTYPE_OPTIONAL(structname, fieldname) pb_membersize(structname, fieldname)
+#define PB_DS_CB_PB_HTYPE_ONEOF(structname, fieldname) pb_membersize(structname, PB_ONEOF_NAME(FULL, fieldname))
+#define PB_DS_CB_PB_HTYPE_REPEATED(structname, fieldname) pb_membersize(structname, fieldname)
+#define PB_DS_CB_PB_HTYPE_FIXARRAY(structname, fieldname) pb_membersize(structname, fieldname)
+
+#define PB_ONEOF_NAME(type, tuple) PB_EXPAND(PB_ONEOF_NAME_ ## type tuple)
+#define PB_ONEOF_NAME_UNION(unionname,membername,fullname) unionname
+#define PB_ONEOF_NAME_MEMBER(unionname,membername,fullname) membername
+#define PB_ONEOF_NAME_FULL(unionname,membername,fullname) fullname
+
+#define PB_GEN_SUBMSG_INFO(structname, atype, htype, ltype, fieldname, tag) \
+    PB_SUBMSG_INFO_ ## htype(_PB_LTYPE_ ## ltype, structname, fieldname)
+
+#define PB_SUBMSG_INFO_REQUIRED(ltype, structname, fieldname) PB_SI ## ltype(structname ## _ ## fieldname ## _MSGTYPE)
+#define PB_SUBMSG_INFO_SINGULAR(ltype, structname, fieldname) PB_SI ## ltype(structname ## _ ## fieldname ## _MSGTYPE)
+#define PB_SUBMSG_INFO_OPTIONAL(ltype, structname, fieldname) PB_SI ## ltype(structname ## _ ## fieldname ## _MSGTYPE)
+#define PB_SUBMSG_INFO_ONEOF(ltype, structname, fieldname) PB_SUBMSG_INFO_ONEOF2(ltype, structname, PB_ONEOF_NAME(UNION, fieldname), PB_ONEOF_NAME(MEMBER, fieldname))
+#define PB_SUBMSG_INFO_ONEOF2(ltype, structname, unionname, membername) PB_SUBMSG_INFO_ONEOF3(ltype, structname, unionname, membername)
+#define PB_SUBMSG_INFO_ONEOF3(ltype, structname, unionname, membername) PB_SI ## ltype(structname ## _ ## unionname ## _ ## membername ## _MSGTYPE)
+#define PB_SUBMSG_INFO_REPEATED(ltype, structname, fieldname) PB_SI ## ltype(structname ## _ ## fieldname ## _MSGTYPE)
+#define PB_SUBMSG_INFO_FIXARRAY(ltype, structname, fieldname) PB_SI ## ltype(structname ## _ ## fieldname ## _MSGTYPE)
+#define PB_SI_PB_LTYPE_BOOL(t)
+#define PB_SI_PB_LTYPE_BYTES(t)
+#define PB_SI_PB_LTYPE_DOUBLE(t)
+#define PB_SI_PB_LTYPE_ENUM(t)
+#define PB_SI_PB_LTYPE_UENUM(t)
+#define PB_SI_PB_LTYPE_FIXED32(t)
+#define PB_SI_PB_LTYPE_FIXED64(t)
+#define PB_SI_PB_LTYPE_FLOAT(t)
+#define PB_SI_PB_LTYPE_INT32(t)
+#define PB_SI_PB_LTYPE_INT64(t)
+#define PB_SI_PB_LTYPE_MESSAGE(t)  PB_SUBMSG_DESCRIPTOR(t)
+#define PB_SI_PB_LTYPE_MSG_W_CB(t) PB_SUBMSG_DESCRIPTOR(t)
+#define PB_SI_PB_LTYPE_SFIXED32(t)
+#define PB_SI_PB_LTYPE_SFIXED64(t)
+#define PB_SI_PB_LTYPE_SINT32(t)
+#define PB_SI_PB_LTYPE_SINT64(t)
+#define PB_SI_PB_LTYPE_STRING(t)
+#define PB_SI_PB_LTYPE_UINT32(t)
+#define PB_SI_PB_LTYPE_UINT64(t)
+#define PB_SI_PB_LTYPE_EXTENSION(t)
+#define PB_SI_PB_LTYPE_FIXED_LENGTH_BYTES(t)
+#define PB_SUBMSG_DESCRIPTOR(t)    &(t ## _msg),
+
+/* The field descriptors use a variable width format, with width of either
+ * 1, 2, 4 or 8 of 32-bit words. The two lowest bytes of the first byte always
+ * encode the descriptor size, 6 lowest bits of field tag number, and 8 bits
+ * of the field type.
+ *
+ * Descriptor size is encoded as 0 = 1 word, 1 = 2 words, 2 = 4 words, 3 = 8 words.
+ *
+ * Formats, listed starting with the least significant bit of the first word.
+ * 1 word:  [2-bit len] [6-bit tag] [8-bit type] [8-bit data_offset] [4-bit size_offset] [4-bit data_size]
+ *
+ * 2 words: [2-bit len] [6-bit tag] [8-bit type] [12-bit array_size] [4-bit size_offset]
+ *          [16-bit data_offset] [12-bit data_size] [4-bit tag>>6]
+ *
+ * 4 words: [2-bit len] [6-bit tag] [8-bit type] [16-bit array_size]
+ *          [8-bit size_offset] [24-bit tag>>6]
+ *          [32-bit data_offset]
+ *          [32-bit data_size]
+ *
+ * 8 words: [2-bit len] [6-bit tag] [8-bit type] [16-bit reserved]
+ *          [8-bit size_offset] [24-bit tag>>6]
+ *          [32-bit data_offset]
+ *          [32-bit data_size]
+ *          [32-bit array_size]
+ *          [32-bit reserved]
+ *          [32-bit reserved]
+ *          [32-bit reserved]
+ */
+
+#define PB_FIELDINFO_1(tag, type, data_offset, data_size, size_offset, array_size) \
+    (0 | (((tag) << 2) & 0xFF) | ((type) << 8) | (((uint32_t)(data_offset) & 0xFF) << 16) | \
+     (((uint32_t)(size_offset) & 0x0F) << 24) | (((uint32_t)(data_size) & 0x0F) << 28)),
+
+#define PB_FIELDINFO_2(tag, type, data_offset, data_size, size_offset, array_size) \
+    (1 | (((tag) << 2) & 0xFF) | ((type) << 8) | (((uint32_t)(array_size) & 0xFFF) << 16) | (((uint32_t)(size_offset) & 0x0F) << 28)), \
+    (((uint32_t)(data_offset) & 0xFFFF) | (((uint32_t)(data_size) & 0xFFF) << 16) | (((uint32_t)(tag) & 0x3c0) << 22)),
+
+#define PB_FIELDINFO_4(tag, type, data_offset, data_size, size_offset, array_size) \
+    (2 | (((tag) << 2) & 0xFF) | ((type) << 8) | (((uint32_t)(array_size) & 0xFFFF) << 16)), \
+    ((uint32_t)(int_least8_t)(size_offset) | (((uint32_t)(tag) << 2) & 0xFFFFFF00)), \
+    (data_offset), (data_size),
+
+#define PB_FIELDINFO_8(tag, type, data_offset, data_size, size_offset, array_size) \
+    (3 | (((tag) << 2) & 0xFF) | ((type) << 8)), \
+    ((uint32_t)(int_least8_t)(size_offset) | (((uint32_t)(tag) << 2) & 0xFFFFFF00)), \
+    (data_offset), (data_size), (array_size), 0, 0, 0,
+
+/* These assertions verify that the field information fits in the allocated space.
+ * The generator tries to automatically determine the correct width that can fit all
+ * data associated with a message. These asserts will fail only if there has been a
+ * problem in the automatic logic - this may be worth reporting as a bug. As a workaround,
+ * you can increase the descriptor width by defining PB_FIELDINFO_WIDTH or by setting
+ * descriptorsize option in .options file.
+ */
+#define PB_FITS(value,bits) ((uint32_t)(value) < ((uint32_t)1<<bits))
+#define PB_FIELDINFO_ASSERT_1(tag, type, data_offset, data_size, size_offset, array_size) \
+    PB_STATIC_ASSERT(PB_FITS(tag,6) && PB_FITS(data_offset,8) && PB_FITS(size_offset,4) && PB_FITS(data_size,4) && PB_FITS(array_size,1), FIELDINFO_DOES_NOT_FIT_width1_field ## tag)
+
+#define PB_FIELDINFO_ASSERT_2(tag, type, data_offset, data_size, size_offset, array_size) \
+    PB_STATIC_ASSERT(PB_FITS(tag,10) && PB_FITS(data_offset,16) && PB_FITS(size_offset,4) && PB_FITS(data_size,12) && PB_FITS(array_size,12), FIELDINFO_DOES_NOT_FIT_width2_field ## tag)
+
+#ifndef PB_FIELD_32BIT
+/* Maximum field sizes are still 16-bit if pb_size_t is 16-bit */
+#define PB_FIELDINFO_ASSERT_4(tag, type, data_offset, data_size, size_offset, array_size) \
+    PB_STATIC_ASSERT(PB_FITS(tag,16) && PB_FITS(data_offset,16) && PB_FITS((int_least8_t)size_offset,8) && PB_FITS(data_size,16) && PB_FITS(array_size,16), FIELDINFO_DOES_NOT_FIT_width4_field ## tag)
+
+#define PB_FIELDINFO_ASSERT_8(tag, type, data_offset, data_size, size_offset, array_size) \
+    PB_STATIC_ASSERT(PB_FITS(tag,16) && PB_FITS(data_offset,16) && PB_FITS((int_least8_t)size_offset,8) && PB_FITS(data_size,16) && PB_FITS(array_size,16), FIELDINFO_DOES_NOT_FIT_width8_field ## tag)
+#else
+/* Up to 32-bit fields supported.
+ * Note that the checks are against 31 bits to avoid compiler warnings about shift wider than type in the test.
+ * I expect that there is no reasonable use for >2GB messages with nanopb anyway.
+ */
+#define PB_FIELDINFO_ASSERT_4(tag, type, data_offset, data_size, size_offset, array_size) \
+    PB_STATIC_ASSERT(PB_FITS(tag,30) && PB_FITS(data_offset,31) && PB_FITS(size_offset,8) && PB_FITS(data_size,31) && PB_FITS(array_size,16), FIELDINFO_DOES_NOT_FIT_width4_field ## tag)
+
+#define PB_FIELDINFO_ASSERT_8(tag, type, data_offset, data_size, size_offset, array_size) \
+    PB_STATIC_ASSERT(PB_FITS(tag,30) && PB_FITS(data_offset,31) && PB_FITS(size_offset,8) && PB_FITS(data_size,31) && PB_FITS(array_size,31), FIELDINFO_DOES_NOT_FIT_width8_field ## tag)
+#endif
+
+
+/* Automatic picking of FIELDINFO width:
+ * Uses width 1 when possible, otherwise resorts to width 2.
+ * This is used when PB_BIND() is called with "AUTO" as the argument.
+ * The generator will give explicit size argument when it knows that a message
+ * structure grows beyond 1-word format limits.
+ */
+#define PB_FIELDINFO_WIDTH_AUTO(atype, htype, ltype) PB_FI_WIDTH ## atype(htype, ltype)
+#define PB_FI_WIDTH_PB_ATYPE_STATIC(htype, ltype) PB_FI_WIDTH ## htype(ltype)
+#define PB_FI_WIDTH_PB_ATYPE_POINTER(htype, ltype) PB_FI_WIDTH ## htype(ltype)
+#define PB_FI_WIDTH_PB_ATYPE_CALLBACK(htype, ltype) 2
+#define PB_FI_WIDTH_PB_HTYPE_REQUIRED(ltype) PB_FI_WIDTH ## ltype
+#define PB_FI_WIDTH_PB_HTYPE_SINGULAR(ltype) PB_FI_WIDTH ## ltype
+#define PB_FI_WIDTH_PB_HTYPE_OPTIONAL(ltype) PB_FI_WIDTH ## ltype
+#define PB_FI_WIDTH_PB_HTYPE_ONEOF(ltype) PB_FI_WIDTH ## ltype
+#define PB_FI_WIDTH_PB_HTYPE_REPEATED(ltype) 2
+#define PB_FI_WIDTH_PB_HTYPE_FIXARRAY(ltype) 2
+#define PB_FI_WIDTH_PB_LTYPE_BOOL      1
+#define PB_FI_WIDTH_PB_LTYPE_BYTES     2
+#define PB_FI_WIDTH_PB_LTYPE_DOUBLE    1
+#define PB_FI_WIDTH_PB_LTYPE_ENUM      1
+#define PB_FI_WIDTH_PB_LTYPE_UENUM     1
+#define PB_FI_WIDTH_PB_LTYPE_FIXED32   1
+#define PB_FI_WIDTH_PB_LTYPE_FIXED64   1
+#define PB_FI_WIDTH_PB_LTYPE_FLOAT     1
+#define PB_FI_WIDTH_PB_LTYPE_INT32     1
+#define PB_FI_WIDTH_PB_LTYPE_INT64     1
+#define PB_FI_WIDTH_PB_LTYPE_MESSAGE   2
+#define PB_FI_WIDTH_PB_LTYPE_MSG_W_CB  2
+#define PB_FI_WIDTH_PB_LTYPE_SFIXED32  1
+#define PB_FI_WIDTH_PB_LTYPE_SFIXED64  1
+#define PB_FI_WIDTH_PB_LTYPE_SINT32    1
+#define PB_FI_WIDTH_PB_LTYPE_SINT64    1
+#define PB_FI_WIDTH_PB_LTYPE_STRING    2
+#define PB_FI_WIDTH_PB_LTYPE_UINT32    1
+#define PB_FI_WIDTH_PB_LTYPE_UINT64    1
+#define PB_FI_WIDTH_PB_LTYPE_EXTENSION 1
+#define PB_FI_WIDTH_PB_LTYPE_FIXED_LENGTH_BYTES 2
+
+/* The mapping from protobuf types to LTYPEs is done using these macros. */
+#define PB_LTYPE_MAP_BOOL               PB_LTYPE_BOOL
+#define PB_LTYPE_MAP_BYTES              PB_LTYPE_BYTES
+#define PB_LTYPE_MAP_DOUBLE             PB_LTYPE_FIXED64
+#define PB_LTYPE_MAP_ENUM               PB_LTYPE_VARINT
+#define PB_LTYPE_MAP_UENUM              PB_LTYPE_UVARINT
+#define PB_LTYPE_MAP_FIXED32            PB_LTYPE_FIXED32
+#define PB_LTYPE_MAP_FIXED64            PB_LTYPE_FIXED64
+#define PB_LTYPE_MAP_FLOAT              PB_LTYPE_FIXED32
+#define PB_LTYPE_MAP_INT32              PB_LTYPE_VARINT
+#define PB_LTYPE_MAP_INT64              PB_LTYPE_VARINT
+#define PB_LTYPE_MAP_MESSAGE            PB_LTYPE_SUBMESSAGE
+#define PB_LTYPE_MAP_MSG_W_CB           PB_LTYPE_SUBMSG_W_CB
+#define PB_LTYPE_MAP_SFIXED32           PB_LTYPE_FIXED32
+#define PB_LTYPE_MAP_SFIXED64           PB_LTYPE_FIXED64
+#define PB_LTYPE_MAP_SINT32             PB_LTYPE_SVARINT
+#define PB_LTYPE_MAP_SINT64             PB_LTYPE_SVARINT
+#define PB_LTYPE_MAP_STRING             PB_LTYPE_STRING
+#define PB_LTYPE_MAP_UINT32             PB_LTYPE_UVARINT
+#define PB_LTYPE_MAP_UINT64             PB_LTYPE_UVARINT
+#define PB_LTYPE_MAP_EXTENSION          PB_LTYPE_EXTENSION
+#define PB_LTYPE_MAP_FIXED_LENGTH_BYTES PB_LTYPE_FIXED_LENGTH_BYTES
+
+/* These macros are used for giving out error messages.
+ * They are mostly a debugging aid; the main error information
+ * is the true/false return value from functions.
+ * Some code space can be saved by disabling the error
+ * messages if not used.
+ *
+ * PB_SET_ERROR() sets the error message if none has been set yet.
+ *                msg must be a constant string literal.
+ * PB_GET_ERROR() always returns a pointer to a string.
+ * PB_RETURN_ERROR() sets the error and returns false from current
+ *                   function.
+ */
+#ifdef PB_NO_ERRMSG
+#define PB_SET_ERROR(stream, msg) PB_UNUSED(stream)
+#define PB_GET_ERROR(stream) "(errmsg disabled)"
+#else
+#define PB_SET_ERROR(stream, msg) (stream->errmsg = (stream)->errmsg ? (stream)->errmsg : (msg))
+#define PB_GET_ERROR(stream) ((stream)->errmsg ? (stream)->errmsg : "(none)")
+#endif
+
+#define PB_RETURN_ERROR(stream, msg) return PB_SET_ERROR(stream, msg), false
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#ifdef __cplusplus
+#if __cplusplus >= 201103L
+#define PB_CONSTEXPR constexpr
+#else  // __cplusplus >= 201103L
+#define PB_CONSTEXPR
+#endif  // __cplusplus >= 201103L
+
+#if __cplusplus >= 201703L
+#define PB_INLINE_CONSTEXPR inline constexpr
+#else  // __cplusplus >= 201703L
+#define PB_INLINE_CONSTEXPR PB_CONSTEXPR
+#endif  // __cplusplus >= 201703L
+
+namespace nanopb {
+// Each type will be partially specialized by the generator.
+template <typename GenMessageT> struct MessageDescriptor;
+}  // namespace nanopb
+#endif  /* __cplusplus */
+
+#endif

+ 388 - 0
components/spotify/cspot/bell/nanopb/pb_common.c

@@ -0,0 +1,388 @@
+/* pb_common.c: Common support functions for pb_encode.c and pb_decode.c.
+ *
+ * 2014 Petteri Aimonen <jpa@kapsi.fi>
+ */
+
+#include "pb_common.h"
+
+static bool load_descriptor_values(pb_field_iter_t *iter)
+{
+    uint32_t word0;
+    uint32_t data_offset;
+    int_least8_t size_offset;
+
+    if (iter->index >= iter->descriptor->field_count)
+        return false;
+
+    word0 = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index]);
+    iter->type = (pb_type_t)((word0 >> 8) & 0xFF);
+
+    switch(word0 & 3)
+    {
+        case 0: {
+            /* 1-word format */
+            iter->array_size = 1;
+            iter->tag = (pb_size_t)((word0 >> 2) & 0x3F);
+            size_offset = (int_least8_t)((word0 >> 24) & 0x0F);
+            data_offset = (word0 >> 16) & 0xFF;
+            iter->data_size = (pb_size_t)((word0 >> 28) & 0x0F);
+            break;
+        }
+
+        case 1: {
+            /* 2-word format */
+            uint32_t word1 = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index + 1]);
+
+            iter->array_size = (pb_size_t)((word0 >> 16) & 0x0FFF);
+            iter->tag = (pb_size_t)(((word0 >> 2) & 0x3F) | ((word1 >> 28) << 6));
+            size_offset = (int_least8_t)((word0 >> 28) & 0x0F);
+            data_offset = word1 & 0xFFFF;
+            iter->data_size = (pb_size_t)((word1 >> 16) & 0x0FFF);
+            break;
+        }
+
+        case 2: {
+            /* 4-word format */
+            uint32_t word1 = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index + 1]);
+            uint32_t word2 = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index + 2]);
+            uint32_t word3 = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index + 3]);
+
+            iter->array_size = (pb_size_t)(word0 >> 16);
+            iter->tag = (pb_size_t)(((word0 >> 2) & 0x3F) | ((word1 >> 8) << 6));
+            size_offset = (int_least8_t)(word1 & 0xFF);
+            data_offset = word2;
+            iter->data_size = (pb_size_t)word3;
+            break;
+        }
+
+        default: {
+            /* 8-word format */
+            uint32_t word1 = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index + 1]);
+            uint32_t word2 = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index + 2]);
+            uint32_t word3 = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index + 3]);
+            uint32_t word4 = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index + 4]);
+
+            iter->array_size = (pb_size_t)word4;
+            iter->tag = (pb_size_t)(((word0 >> 2) & 0x3F) | ((word1 >> 8) << 6));
+            size_offset = (int_least8_t)(word1 & 0xFF);
+            data_offset = word2;
+            iter->data_size = (pb_size_t)word3;
+            break;
+        }
+    }
+
+    if (!iter->message)
+    {
+        /* Avoid doing arithmetic on null pointers, it is undefined */
+        iter->pField = NULL;
+        iter->pSize = NULL;
+    }
+    else
+    {
+        iter->pField = (char*)iter->message + data_offset;
+
+        if (size_offset)
+        {
+            iter->pSize = (char*)iter->pField - size_offset;
+        }
+        else if (PB_HTYPE(iter->type) == PB_HTYPE_REPEATED &&
+                 (PB_ATYPE(iter->type) == PB_ATYPE_STATIC ||
+                  PB_ATYPE(iter->type) == PB_ATYPE_POINTER))
+        {
+            /* Fixed count array */
+            iter->pSize = &iter->array_size;
+        }
+        else
+        {
+            iter->pSize = NULL;
+        }
+
+        if (PB_ATYPE(iter->type) == PB_ATYPE_POINTER && iter->pField != NULL)
+        {
+            iter->pData = *(void**)iter->pField;
+        }
+        else
+        {
+            iter->pData = iter->pField;
+        }
+    }
+
+    if (PB_LTYPE_IS_SUBMSG(iter->type))
+    {
+        iter->submsg_desc = iter->descriptor->submsg_info[iter->submessage_index];
+    }
+    else
+    {
+        iter->submsg_desc = NULL;
+    }
+
+    return true;
+}
+
+static void advance_iterator(pb_field_iter_t *iter)
+{
+    iter->index++;
+
+    if (iter->index >= iter->descriptor->field_count)
+    {
+        /* Restart */
+        iter->index = 0;
+        iter->field_info_index = 0;
+        iter->submessage_index = 0;
+        iter->required_field_index = 0;
+    }
+    else
+    {
+        /* Increment indexes based on previous field type.
+         * All field info formats have the following fields:
+         * - lowest 2 bits tell the amount of words in the descriptor (2^n words)
+         * - bits 2..7 give the lowest bits of tag number.
+         * - bits 8..15 give the field type.
+         */
+        uint32_t prev_descriptor = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index]);
+        pb_type_t prev_type = (prev_descriptor >> 8) & 0xFF;
+        pb_size_t descriptor_len = (pb_size_t)(1 << (prev_descriptor & 3));
+
+        /* Add to fields.
+         * The cast to pb_size_t is needed to avoid -Wconversion warning.
+         * Because the data is is constants from generator, there is no danger of overflow.
+         */
+        iter->field_info_index = (pb_size_t)(iter->field_info_index + descriptor_len);
+        iter->required_field_index = (pb_size_t)(iter->required_field_index + (PB_HTYPE(prev_type) == PB_HTYPE_REQUIRED));
+        iter->submessage_index = (pb_size_t)(iter->submessage_index + PB_LTYPE_IS_SUBMSG(prev_type));
+    }
+}
+
+bool pb_field_iter_begin(pb_field_iter_t *iter, const pb_msgdesc_t *desc, void *message)
+{
+    memset(iter, 0, sizeof(*iter));
+
+    iter->descriptor = desc;
+    iter->message = message;
+
+    return load_descriptor_values(iter);
+}
+
+bool pb_field_iter_begin_extension(pb_field_iter_t *iter, pb_extension_t *extension)
+{
+    const pb_msgdesc_t *msg = (const pb_msgdesc_t*)extension->type->arg;
+    bool status;
+
+    uint32_t word0 = PB_PROGMEM_READU32(msg->field_info[0]);
+    if (PB_ATYPE(word0 >> 8) == PB_ATYPE_POINTER)
+    {
+        /* For pointer extensions, the pointer is stored directly
+         * in the extension structure. This avoids having an extra
+         * indirection. */
+        status = pb_field_iter_begin(iter, msg, &extension->dest);
+    }
+    else
+    {
+        status = pb_field_iter_begin(iter, msg, extension->dest);
+    }
+
+    iter->pSize = &extension->found;
+    return status;
+}
+
+bool pb_field_iter_next(pb_field_iter_t *iter)
+{
+    advance_iterator(iter);
+    (void)load_descriptor_values(iter);
+    return iter->index != 0;
+}
+
+bool pb_field_iter_find(pb_field_iter_t *iter, uint32_t tag)
+{
+    if (iter->tag == tag)
+    {
+        return true; /* Nothing to do, correct field already. */
+    }
+    else if (tag > iter->descriptor->largest_tag)
+    {
+        return false;
+    }
+    else
+    {
+        pb_size_t start = iter->index;
+        uint32_t fieldinfo;
+
+        if (tag < iter->tag)
+        {
+            /* Fields are in tag number order, so we know that tag is between
+             * 0 and our start position. Setting index to end forces
+             * advance_iterator() call below to restart from beginning. */
+            iter->index = iter->descriptor->field_count;
+        }
+
+        do
+        {
+            /* Advance iterator but don't load values yet */
+            advance_iterator(iter);
+
+            /* Do fast check for tag number match */
+            fieldinfo = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index]);
+
+            if (((fieldinfo >> 2) & 0x3F) == (tag & 0x3F))
+            {
+                /* Good candidate, check further */
+                (void)load_descriptor_values(iter);
+
+                if (iter->tag == tag &&
+                    PB_LTYPE(iter->type) != PB_LTYPE_EXTENSION)
+                {
+                    /* Found it */
+                    return true;
+                }
+            }
+        } while (iter->index != start);
+
+        /* Searched all the way back to start, and found nothing. */
+        (void)load_descriptor_values(iter);
+        return false;
+    }
+}
+
+bool pb_field_iter_find_extension(pb_field_iter_t *iter)
+{
+    if (PB_LTYPE(iter->type) == PB_LTYPE_EXTENSION)
+    {
+        return true;
+    }
+    else
+    {
+        pb_size_t start = iter->index;
+        uint32_t fieldinfo;
+
+        do
+        {
+            /* Advance iterator but don't load values yet */
+            advance_iterator(iter);
+
+            /* Do fast check for field type */
+            fieldinfo = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index]);
+
+            if (PB_LTYPE((fieldinfo >> 8) & 0xFF) == PB_LTYPE_EXTENSION)
+            {
+                return load_descriptor_values(iter);
+            }
+        } while (iter->index != start);
+
+        /* Searched all the way back to start, and found nothing. */
+        (void)load_descriptor_values(iter);
+        return false;
+    }
+}
+
+static void *pb_const_cast(const void *p)
+{
+    /* Note: this casts away const, in order to use the common field iterator
+     * logic for both encoding and decoding. The cast is done using union
+     * to avoid spurious compiler warnings. */
+    union {
+        void *p1;
+        const void *p2;
+    } t;
+    t.p2 = p;
+    return t.p1;
+}
+
+bool pb_field_iter_begin_const(pb_field_iter_t *iter, const pb_msgdesc_t *desc, const void *message)
+{
+    return pb_field_iter_begin(iter, desc, pb_const_cast(message));
+}
+
+bool pb_field_iter_begin_extension_const(pb_field_iter_t *iter, const pb_extension_t *extension)
+{
+    return pb_field_iter_begin_extension(iter, (pb_extension_t*)pb_const_cast(extension));
+}
+
+bool pb_default_field_callback(pb_istream_t *istream, pb_ostream_t *ostream, const pb_field_t *field)
+{
+    if (field->data_size == sizeof(pb_callback_t))
+    {
+        pb_callback_t *pCallback = (pb_callback_t*)field->pData;
+
+        if (pCallback != NULL)
+        {
+            if (istream != NULL && pCallback->funcs.decode != NULL)
+            {
+                return pCallback->funcs.decode(istream, field, &pCallback->arg);
+            }
+
+            if (ostream != NULL && pCallback->funcs.encode != NULL)
+            {
+                return pCallback->funcs.encode(ostream, field, &pCallback->arg);
+            }
+        }
+    }
+
+    return true; /* Success, but didn't do anything */
+
+}
+
+#ifdef PB_VALIDATE_UTF8
+
+/* This function checks whether a string is valid UTF-8 text.
+ *
+ * Algorithm is adapted from https://www.cl.cam.ac.uk/~mgk25/ucs/utf8_check.c
+ * Original copyright: Markus Kuhn <http://www.cl.cam.ac.uk/~mgk25/> 2005-03-30
+ * Licensed under "Short code license", which allows use under MIT license or
+ * any compatible with it.
+ */
+
+bool pb_validate_utf8(const char *str)
+{
+    const pb_byte_t *s = (const pb_byte_t*)str;
+    while (*s)
+    {
+        if (*s < 0x80)
+        {
+            /* 0xxxxxxx */
+            s++;
+        }
+        else if ((s[0] & 0xe0) == 0xc0)
+        {
+            /* 110XXXXx 10xxxxxx */
+            if ((s[1] & 0xc0) != 0x80 ||
+                (s[0] & 0xfe) == 0xc0)                        /* overlong? */
+                return false;
+            else
+                s += 2;
+        }
+        else if ((s[0] & 0xf0) == 0xe0)
+        {
+            /* 1110XXXX 10Xxxxxx 10xxxxxx */
+            if ((s[1] & 0xc0) != 0x80 ||
+                (s[2] & 0xc0) != 0x80 ||
+                (s[0] == 0xe0 && (s[1] & 0xe0) == 0x80) ||    /* overlong? */
+                (s[0] == 0xed && (s[1] & 0xe0) == 0xa0) ||    /* surrogate? */
+                (s[0] == 0xef && s[1] == 0xbf &&
+                (s[2] & 0xfe) == 0xbe))                 /* U+FFFE or U+FFFF? */
+                return false;
+            else
+                s += 3;
+        }
+        else if ((s[0] & 0xf8) == 0xf0)
+        {
+            /* 11110XXX 10XXxxxx 10xxxxxx 10xxxxxx */
+            if ((s[1] & 0xc0) != 0x80 ||
+                (s[2] & 0xc0) != 0x80 ||
+                (s[3] & 0xc0) != 0x80 ||
+                (s[0] == 0xf0 && (s[1] & 0xf0) == 0x80) ||    /* overlong? */
+                (s[0] == 0xf4 && s[1] > 0x8f) || s[0] > 0xf4) /* > U+10FFFF? */
+                return false;
+            else
+                s += 4;
+        }
+        else
+        {
+            return false;
+        }
+    }
+
+    return true;
+}
+
+#endif
+

+ 49 - 0
components/spotify/cspot/bell/nanopb/pb_common.h

@@ -0,0 +1,49 @@
+/* pb_common.h: Common support functions for pb_encode.c and pb_decode.c.
+ * These functions are rarely needed by applications directly.
+ */
+
+#ifndef PB_COMMON_H_INCLUDED
+#define PB_COMMON_H_INCLUDED
+
+#include "pb.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Initialize the field iterator structure to beginning.
+ * Returns false if the message type is empty. */
+bool pb_field_iter_begin(pb_field_iter_t *iter, const pb_msgdesc_t *desc, void *message);
+
+/* Get a field iterator for extension field. */
+bool pb_field_iter_begin_extension(pb_field_iter_t *iter, pb_extension_t *extension);
+
+/* Same as pb_field_iter_begin(), but for const message pointer.
+ * Note that the pointers in pb_field_iter_t will be non-const but shouldn't
+ * be written to when using these functions. */
+bool pb_field_iter_begin_const(pb_field_iter_t *iter, const pb_msgdesc_t *desc, const void *message);
+bool pb_field_iter_begin_extension_const(pb_field_iter_t *iter, const pb_extension_t *extension);
+
+/* Advance the iterator to the next field.
+ * Returns false when the iterator wraps back to the first field. */
+bool pb_field_iter_next(pb_field_iter_t *iter);
+
+/* Advance the iterator until it points at a field with the given tag.
+ * Returns false if no such field exists. */
+bool pb_field_iter_find(pb_field_iter_t *iter, uint32_t tag);
+
+/* Find a field with type PB_LTYPE_EXTENSION, or return false if not found.
+ * There can be only one extension range field per message. */
+bool pb_field_iter_find_extension(pb_field_iter_t *iter);
+
+#ifdef PB_VALIDATE_UTF8
+/* Validate UTF-8 text string */
+bool pb_validate_utf8(const char *s);
+#endif
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif
+

+ 1713 - 0
components/spotify/cspot/bell/nanopb/pb_decode.c

@@ -0,0 +1,1713 @@
+/* pb_decode.c -- decode a protobuf using minimal resources
+ *
+ * 2011 Petteri Aimonen <jpa@kapsi.fi>
+ */
+
+/* Use the GCC warn_unused_result attribute to check that all return values
+ * are propagated correctly. On other compilers and gcc before 3.4.0 just
+ * ignore the annotation.
+ */
+#if !defined(__GNUC__) || ( __GNUC__ < 3) || (__GNUC__ == 3 && __GNUC_MINOR__ < 4)
+    #define checkreturn
+#else
+    #define checkreturn __attribute__((warn_unused_result))
+#endif
+
+#include "pb.h"
+#include "pb_decode.h"
+#include "pb_common.h"
+
+/**************************************
+ * Declarations internal to this file *
+ **************************************/
+
+static bool checkreturn buf_read(pb_istream_t *stream, pb_byte_t *buf, size_t count);
+static bool checkreturn pb_decode_varint32_eof(pb_istream_t *stream, uint32_t *dest, bool *eof);
+static bool checkreturn read_raw_value(pb_istream_t *stream, pb_wire_type_t wire_type, pb_byte_t *buf, size_t *size);
+static bool checkreturn decode_basic_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *field);
+static bool checkreturn decode_static_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *field);
+static bool checkreturn decode_pointer_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *field);
+static bool checkreturn decode_callback_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *field);
+static bool checkreturn decode_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *field);
+static bool checkreturn default_extension_decoder(pb_istream_t *stream, pb_extension_t *extension, uint32_t tag, pb_wire_type_t wire_type);
+static bool checkreturn decode_extension(pb_istream_t *stream, uint32_t tag, pb_wire_type_t wire_type, pb_extension_t *extension);
+static bool pb_field_set_to_default(pb_field_iter_t *field);
+static bool pb_message_set_to_defaults(pb_field_iter_t *iter);
+static bool checkreturn pb_dec_bool(pb_istream_t *stream, const pb_field_iter_t *field);
+static bool checkreturn pb_dec_varint(pb_istream_t *stream, const pb_field_iter_t *field);
+static bool checkreturn pb_dec_bytes(pb_istream_t *stream, const pb_field_iter_t *field);
+static bool checkreturn pb_dec_string(pb_istream_t *stream, const pb_field_iter_t *field);
+static bool checkreturn pb_dec_submessage(pb_istream_t *stream, const pb_field_iter_t *field);
+static bool checkreturn pb_dec_fixed_length_bytes(pb_istream_t *stream, const pb_field_iter_t *field);
+static bool checkreturn pb_skip_varint(pb_istream_t *stream);
+static bool checkreturn pb_skip_string(pb_istream_t *stream);
+
+#ifdef PB_ENABLE_MALLOC
+static bool checkreturn allocate_field(pb_istream_t *stream, void *pData, size_t data_size, size_t array_size);
+static void initialize_pointer_field(void *pItem, pb_field_iter_t *field);
+static bool checkreturn pb_release_union_field(pb_istream_t *stream, pb_field_iter_t *field);
+static void pb_release_single_field(pb_field_iter_t *field);
+#endif
+
+#ifdef PB_WITHOUT_64BIT
+#define pb_int64_t int32_t
+#define pb_uint64_t uint32_t
+#else
+#define pb_int64_t int64_t
+#define pb_uint64_t uint64_t
+#endif
+
+typedef struct {
+    uint32_t bitfield[(PB_MAX_REQUIRED_FIELDS + 31) / 32];
+} pb_fields_seen_t;
+
+/*******************************
+ * pb_istream_t implementation *
+ *******************************/
+
+static bool checkreturn buf_read(pb_istream_t *stream, pb_byte_t *buf, size_t count)
+{
+    size_t i;
+    const pb_byte_t *source = (const pb_byte_t*)stream->state;
+    stream->state = (pb_byte_t*)stream->state + count;
+    
+    if (buf != NULL)
+    {
+        for (i = 0; i < count; i++)
+            buf[i] = source[i];
+    }
+    
+    return true;
+}
+
+bool checkreturn pb_read(pb_istream_t *stream, pb_byte_t *buf, size_t count)
+{
+    if (count == 0)
+        return true;
+
+#ifndef PB_BUFFER_ONLY
+	if (buf == NULL && stream->callback != buf_read)
+	{
+		/* Skip input bytes */
+		pb_byte_t tmp[16];
+		while (count > 16)
+		{
+			if (!pb_read(stream, tmp, 16))
+				return false;
+			
+			count -= 16;
+		}
+		
+		return pb_read(stream, tmp, count);
+	}
+#endif
+
+    if (stream->bytes_left < count)
+        PB_RETURN_ERROR(stream, "end-of-stream");
+    
+#ifndef PB_BUFFER_ONLY
+    if (!stream->callback(stream, buf, count))
+        PB_RETURN_ERROR(stream, "io error");
+#else
+    if (!buf_read(stream, buf, count))
+        return false;
+#endif
+    
+    stream->bytes_left -= count;
+    return true;
+}
+
+/* Read a single byte from input stream. buf may not be NULL.
+ * This is an optimization for the varint decoding. */
+static bool checkreturn pb_readbyte(pb_istream_t *stream, pb_byte_t *buf)
+{
+    if (stream->bytes_left == 0)
+        PB_RETURN_ERROR(stream, "end-of-stream");
+
+#ifndef PB_BUFFER_ONLY
+    if (!stream->callback(stream, buf, 1))
+        PB_RETURN_ERROR(stream, "io error");
+#else
+    *buf = *(const pb_byte_t*)stream->state;
+    stream->state = (pb_byte_t*)stream->state + 1;
+#endif
+
+    stream->bytes_left--;
+    
+    return true;    
+}
+
+pb_istream_t pb_istream_from_buffer(const pb_byte_t *buf, size_t msglen)
+{
+    pb_istream_t stream;
+    /* Cast away the const from buf without a compiler error.  We are
+     * careful to use it only in a const manner in the callbacks.
+     */
+    union {
+        void *state;
+        const void *c_state;
+    } state;
+#ifdef PB_BUFFER_ONLY
+    stream.callback = NULL;
+#else
+    stream.callback = &buf_read;
+#endif
+    state.c_state = buf;
+    stream.state = state.state;
+    stream.bytes_left = msglen;
+#ifndef PB_NO_ERRMSG
+    stream.errmsg = NULL;
+#endif
+    return stream;
+}
+
+/********************
+ * Helper functions *
+ ********************/
+
+static bool checkreturn pb_decode_varint32_eof(pb_istream_t *stream, uint32_t *dest, bool *eof)
+{
+    pb_byte_t byte;
+    uint32_t result;
+    
+    if (!pb_readbyte(stream, &byte))
+    {
+        if (stream->bytes_left == 0)
+        {
+            if (eof)
+            {
+                *eof = true;
+            }
+        }
+
+        return false;
+    }
+    
+    if ((byte & 0x80) == 0)
+    {
+        /* Quick case, 1 byte value */
+        result = byte;
+    }
+    else
+    {
+        /* Multibyte case */
+        uint_fast8_t bitpos = 7;
+        result = byte & 0x7F;
+        
+        do
+        {
+            if (!pb_readbyte(stream, &byte))
+                return false;
+            
+            if (bitpos >= 32)
+            {
+                /* Note: The varint could have trailing 0x80 bytes, or 0xFF for negative. */
+                pb_byte_t sign_extension = (bitpos < 63) ? 0xFF : 0x01;
+                bool valid_extension = ((byte & 0x7F) == 0x00 ||
+                         ((result >> 31) != 0 && byte == sign_extension));
+
+                if (bitpos >= 64 || !valid_extension)
+                {
+                    PB_RETURN_ERROR(stream, "varint overflow");
+                }
+            }
+            else
+            {
+                result |= (uint32_t)(byte & 0x7F) << bitpos;
+            }
+            bitpos = (uint_fast8_t)(bitpos + 7);
+        } while (byte & 0x80);
+        
+        if (bitpos == 35 && (byte & 0x70) != 0)
+        {
+            /* The last byte was at bitpos=28, so only bottom 4 bits fit. */
+            PB_RETURN_ERROR(stream, "varint overflow");
+        }
+   }
+   
+   *dest = result;
+   return true;
+}
+
+bool checkreturn pb_decode_varint32(pb_istream_t *stream, uint32_t *dest)
+{
+    return pb_decode_varint32_eof(stream, dest, NULL);
+}
+
+#ifndef PB_WITHOUT_64BIT
+bool checkreturn pb_decode_varint(pb_istream_t *stream, uint64_t *dest)
+{
+    pb_byte_t byte;
+    uint_fast8_t bitpos = 0;
+    uint64_t result = 0;
+    
+    do
+    {
+        if (bitpos >= 64)
+            PB_RETURN_ERROR(stream, "varint overflow");
+        
+        if (!pb_readbyte(stream, &byte))
+            return false;
+
+        result |= (uint64_t)(byte & 0x7F) << bitpos;
+        bitpos = (uint_fast8_t)(bitpos + 7);
+    } while (byte & 0x80);
+    
+    *dest = result;
+    return true;
+}
+#endif
+
+bool checkreturn pb_skip_varint(pb_istream_t *stream)
+{
+    pb_byte_t byte;
+    do
+    {
+        if (!pb_read(stream, &byte, 1))
+            return false;
+    } while (byte & 0x80);
+    return true;
+}
+
+bool checkreturn pb_skip_string(pb_istream_t *stream)
+{
+    uint32_t length;
+    if (!pb_decode_varint32(stream, &length))
+        return false;
+    
+    if ((size_t)length != length)
+    {
+        PB_RETURN_ERROR(stream, "size too large");
+    }
+
+    return pb_read(stream, NULL, (size_t)length);
+}
+
+bool checkreturn pb_decode_tag(pb_istream_t *stream, pb_wire_type_t *wire_type, uint32_t *tag, bool *eof)
+{
+    uint32_t temp;
+    *eof = false;
+    *wire_type = (pb_wire_type_t) 0;
+    *tag = 0;
+    
+    if (!pb_decode_varint32_eof(stream, &temp, eof))
+    {
+        return false;
+    }
+    
+    *tag = temp >> 3;
+    *wire_type = (pb_wire_type_t)(temp & 7);
+    return true;
+}
+
+bool checkreturn pb_skip_field(pb_istream_t *stream, pb_wire_type_t wire_type)
+{
+    switch (wire_type)
+    {
+        case PB_WT_VARINT: return pb_skip_varint(stream);
+        case PB_WT_64BIT: return pb_read(stream, NULL, 8);
+        case PB_WT_STRING: return pb_skip_string(stream);
+        case PB_WT_32BIT: return pb_read(stream, NULL, 4);
+        default: PB_RETURN_ERROR(stream, "invalid wire_type");
+    }
+}
+
+/* Read a raw value to buffer, for the purpose of passing it to callback as
+ * a substream. Size is maximum size on call, and actual size on return.
+ */
+static bool checkreturn read_raw_value(pb_istream_t *stream, pb_wire_type_t wire_type, pb_byte_t *buf, size_t *size)
+{
+    size_t max_size = *size;
+    switch (wire_type)
+    {
+        case PB_WT_VARINT:
+            *size = 0;
+            do
+            {
+                (*size)++;
+                if (*size > max_size)
+                    PB_RETURN_ERROR(stream, "varint overflow");
+
+                if (!pb_read(stream, buf, 1))
+                    return false;
+            } while (*buf++ & 0x80);
+            return true;
+            
+        case PB_WT_64BIT:
+            *size = 8;
+            return pb_read(stream, buf, 8);
+        
+        case PB_WT_32BIT:
+            *size = 4;
+            return pb_read(stream, buf, 4);
+        
+        case PB_WT_STRING:
+            /* Calling read_raw_value with a PB_WT_STRING is an error.
+             * Explicitly handle this case and fallthrough to default to avoid
+             * compiler warnings.
+             */
+
+        default: PB_RETURN_ERROR(stream, "invalid wire_type");
+    }
+}
+
+/* Decode string length from stream and return a substream with limited length.
+ * Remember to close the substream using pb_close_string_substream().
+ */
+bool checkreturn pb_make_string_substream(pb_istream_t *stream, pb_istream_t *substream)
+{
+    uint32_t size;
+    if (!pb_decode_varint32(stream, &size))
+        return false;
+    
+    *substream = *stream;
+    if (substream->bytes_left < size)
+        PB_RETURN_ERROR(stream, "parent stream too short");
+    
+    substream->bytes_left = (size_t)size;
+    stream->bytes_left -= (size_t)size;
+    return true;
+}
+
+bool checkreturn pb_close_string_substream(pb_istream_t *stream, pb_istream_t *substream)
+{
+    if (substream->bytes_left) {
+        if (!pb_read(substream, NULL, substream->bytes_left))
+            return false;
+    }
+
+    stream->state = substream->state;
+
+#ifndef PB_NO_ERRMSG
+    stream->errmsg = substream->errmsg;
+#endif
+    return true;
+}
+
+/*************************
+ * Decode a single field *
+ *************************/
+
+static bool checkreturn decode_basic_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *field)
+{
+    switch (PB_LTYPE(field->type))
+    {
+        case PB_LTYPE_BOOL:
+            if (wire_type != PB_WT_VARINT && wire_type != PB_WT_PACKED)
+                PB_RETURN_ERROR(stream, "wrong wire type");
+
+            return pb_dec_bool(stream, field);
+
+        case PB_LTYPE_VARINT:
+        case PB_LTYPE_UVARINT:
+        case PB_LTYPE_SVARINT:
+            if (wire_type != PB_WT_VARINT && wire_type != PB_WT_PACKED)
+                PB_RETURN_ERROR(stream, "wrong wire type");
+
+            return pb_dec_varint(stream, field);
+
+        case PB_LTYPE_FIXED32:
+            if (wire_type != PB_WT_32BIT && wire_type != PB_WT_PACKED)
+                PB_RETURN_ERROR(stream, "wrong wire type");
+
+            return pb_decode_fixed32(stream, field->pData);
+
+        case PB_LTYPE_FIXED64:
+            if (wire_type != PB_WT_64BIT && wire_type != PB_WT_PACKED)
+                PB_RETURN_ERROR(stream, "wrong wire type");
+
+#ifdef PB_CONVERT_DOUBLE_FLOAT
+            if (field->data_size == sizeof(float))
+            {
+                return pb_decode_double_as_float(stream, (float*)field->pData);
+            }
+#endif
+
+#ifdef PB_WITHOUT_64BIT
+            PB_RETURN_ERROR(stream, "invalid data_size");
+#else
+            return pb_decode_fixed64(stream, field->pData);
+#endif
+
+        case PB_LTYPE_BYTES:
+            if (wire_type != PB_WT_STRING)
+                PB_RETURN_ERROR(stream, "wrong wire type");
+
+            return pb_dec_bytes(stream, field);
+
+        case PB_LTYPE_STRING:
+            if (wire_type != PB_WT_STRING)
+                PB_RETURN_ERROR(stream, "wrong wire type");
+
+            return pb_dec_string(stream, field);
+
+        case PB_LTYPE_SUBMESSAGE:
+        case PB_LTYPE_SUBMSG_W_CB:
+            if (wire_type != PB_WT_STRING)
+                PB_RETURN_ERROR(stream, "wrong wire type");
+
+            return pb_dec_submessage(stream, field);
+
+        case PB_LTYPE_FIXED_LENGTH_BYTES:
+            if (wire_type != PB_WT_STRING)
+                PB_RETURN_ERROR(stream, "wrong wire type");
+
+            return pb_dec_fixed_length_bytes(stream, field);
+
+        default:
+            PB_RETURN_ERROR(stream, "invalid field type");
+    }
+}
+
+static bool checkreturn decode_static_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *field)
+{
+    switch (PB_HTYPE(field->type))
+    {
+        case PB_HTYPE_REQUIRED:
+            return decode_basic_field(stream, wire_type, field);
+            
+        case PB_HTYPE_OPTIONAL:
+            if (field->pSize != NULL)
+                *(bool*)field->pSize = true;
+            return decode_basic_field(stream, wire_type, field);
+    
+        case PB_HTYPE_REPEATED:
+            if (wire_type == PB_WT_STRING
+                && PB_LTYPE(field->type) <= PB_LTYPE_LAST_PACKABLE)
+            {
+                /* Packed array */
+                bool status = true;
+                pb_istream_t substream;
+                pb_size_t *size = (pb_size_t*)field->pSize;
+                field->pData = (char*)field->pField + field->data_size * (*size);
+
+                if (!pb_make_string_substream(stream, &substream))
+                    return false;
+
+                while (substream.bytes_left > 0 && *size < field->array_size)
+                {
+                    if (!decode_basic_field(&substream, PB_WT_PACKED, field))
+                    {
+                        status = false;
+                        break;
+                    }
+                    (*size)++;
+                    field->pData = (char*)field->pData + field->data_size;
+                }
+
+                if (substream.bytes_left != 0)
+                    PB_RETURN_ERROR(stream, "array overflow");
+                if (!pb_close_string_substream(stream, &substream))
+                    return false;
+
+                return status;
+            }
+            else
+            {
+                /* Repeated field */
+                pb_size_t *size = (pb_size_t*)field->pSize;
+                field->pData = (char*)field->pField + field->data_size * (*size);
+
+                if ((*size)++ >= field->array_size)
+                    PB_RETURN_ERROR(stream, "array overflow");
+
+                return decode_basic_field(stream, wire_type, field);
+            }
+
+        case PB_HTYPE_ONEOF:
+            if (PB_LTYPE_IS_SUBMSG(field->type) &&
+                *(pb_size_t*)field->pSize != field->tag)
+            {
+                /* We memset to zero so that any callbacks are set to NULL.
+                 * This is because the callbacks might otherwise have values
+                 * from some other union field.
+                 * If callbacks are needed inside oneof field, use .proto
+                 * option submsg_callback to have a separate callback function
+                 * that can set the fields before submessage is decoded.
+                 * pb_dec_submessage() will set any default values. */
+                memset(field->pData, 0, (size_t)field->data_size);
+
+                /* Set default values for the submessage fields. */
+                if (field->submsg_desc->default_value != NULL ||
+                    field->submsg_desc->field_callback != NULL ||
+                    field->submsg_desc->submsg_info[0] != NULL)
+                {
+                    pb_field_iter_t submsg_iter;
+                    if (pb_field_iter_begin(&submsg_iter, field->submsg_desc, field->pData))
+                    {
+                        if (!pb_message_set_to_defaults(&submsg_iter))
+                            PB_RETURN_ERROR(stream, "failed to set defaults");
+                    }
+                }
+            }
+            *(pb_size_t*)field->pSize = field->tag;
+
+            return decode_basic_field(stream, wire_type, field);
+
+        default:
+            PB_RETURN_ERROR(stream, "invalid field type");
+    }
+}
+
+#ifdef PB_ENABLE_MALLOC
+/* Allocate storage for the field and store the pointer at iter->pData.
+ * array_size is the number of entries to reserve in an array.
+ * Zero size is not allowed, use pb_free() for releasing.
+ */
+static bool checkreturn allocate_field(pb_istream_t *stream, void *pData, size_t data_size, size_t array_size)
+{    
+    void *ptr = *(void**)pData;
+    
+    if (data_size == 0 || array_size == 0)
+        PB_RETURN_ERROR(stream, "invalid size");
+    
+#ifdef __AVR__
+    /* Workaround for AVR libc bug 53284: http://savannah.nongnu.org/bugs/?53284
+     * Realloc to size of 1 byte can cause corruption of the malloc structures.
+     */
+    if (data_size == 1 && array_size == 1)
+    {
+        data_size = 2;
+    }
+#endif
+
+    /* Check for multiplication overflows.
+     * This code avoids the costly division if the sizes are small enough.
+     * Multiplication is safe as long as only half of bits are set
+     * in either multiplicand.
+     */
+    {
+        const size_t check_limit = (size_t)1 << (sizeof(size_t) * 4);
+        if (data_size >= check_limit || array_size >= check_limit)
+        {
+            const size_t size_max = (size_t)-1;
+            if (size_max / array_size < data_size)
+            {
+                PB_RETURN_ERROR(stream, "size too large");
+            }
+        }
+    }
+    
+    /* Allocate new or expand previous allocation */
+    /* Note: on failure the old pointer will remain in the structure,
+     * the message must be freed by caller also on error return. */
+    ptr = pb_realloc(ptr, array_size * data_size);
+    if (ptr == NULL)
+        PB_RETURN_ERROR(stream, "realloc failed");
+    
+    *(void**)pData = ptr;
+    return true;
+}
+
+/* Clear a newly allocated item in case it contains a pointer, or is a submessage. */
+static void initialize_pointer_field(void *pItem, pb_field_iter_t *field)
+{
+    if (PB_LTYPE(field->type) == PB_LTYPE_STRING ||
+        PB_LTYPE(field->type) == PB_LTYPE_BYTES)
+    {
+        *(void**)pItem = NULL;
+    }
+    else if (PB_LTYPE_IS_SUBMSG(field->type))
+    {
+        /* We memset to zero so that any callbacks are set to NULL.
+         * Default values will be set by pb_dec_submessage(). */
+        memset(pItem, 0, field->data_size);
+    }
+}
+#endif
+
+static bool checkreturn decode_pointer_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *field)
+{
+#ifndef PB_ENABLE_MALLOC
+    PB_UNUSED(wire_type);
+    PB_UNUSED(field);
+    PB_RETURN_ERROR(stream, "no malloc support");
+#else
+    switch (PB_HTYPE(field->type))
+    {
+        case PB_HTYPE_REQUIRED:
+        case PB_HTYPE_OPTIONAL:
+        case PB_HTYPE_ONEOF:
+            if (PB_LTYPE_IS_SUBMSG(field->type) && *(void**)field->pField != NULL)
+            {
+                /* Duplicate field, have to release the old allocation first. */
+                /* FIXME: Does this work correctly for oneofs? */
+                pb_release_single_field(field);
+            }
+        
+            if (PB_HTYPE(field->type) == PB_HTYPE_ONEOF)
+            {
+                *(pb_size_t*)field->pSize = field->tag;
+            }
+
+            if (PB_LTYPE(field->type) == PB_LTYPE_STRING ||
+                PB_LTYPE(field->type) == PB_LTYPE_BYTES)
+            {
+                /* pb_dec_string and pb_dec_bytes handle allocation themselves */
+                field->pData = field->pField;
+                return decode_basic_field(stream, wire_type, field);
+            }
+            else
+            {
+                if (!allocate_field(stream, field->pField, field->data_size, 1))
+                    return false;
+                
+                field->pData = *(void**)field->pField;
+                initialize_pointer_field(field->pData, field);
+                return decode_basic_field(stream, wire_type, field);
+            }
+    
+        case PB_HTYPE_REPEATED:
+            if (wire_type == PB_WT_STRING
+                && PB_LTYPE(field->type) <= PB_LTYPE_LAST_PACKABLE)
+            {
+                /* Packed array, multiple items come in at once. */
+                bool status = true;
+                pb_size_t *size = (pb_size_t*)field->pSize;
+                size_t allocated_size = *size;
+                pb_istream_t substream;
+                
+                if (!pb_make_string_substream(stream, &substream))
+                    return false;
+                
+                while (substream.bytes_left)
+                {
+                    if (*size == PB_SIZE_MAX)
+                    {
+#ifndef PB_NO_ERRMSG
+                        stream->errmsg = "too many array entries";
+#endif
+                        status = false;
+                        break;
+                    }
+
+                    if ((size_t)*size + 1 > allocated_size)
+                    {
+                        /* Allocate more storage. This tries to guess the
+                         * number of remaining entries. Round the division
+                         * upwards. */
+                        size_t remain = (substream.bytes_left - 1) / field->data_size + 1;
+                        if (remain < PB_SIZE_MAX - allocated_size)
+                            allocated_size += remain;
+                        else
+                            allocated_size += 1;
+                        
+                        if (!allocate_field(&substream, field->pField, field->data_size, allocated_size))
+                        {
+                            status = false;
+                            break;
+                        }
+                    }
+
+                    /* Decode the array entry */
+                    field->pData = *(char**)field->pField + field->data_size * (*size);
+                    if (field->pData == NULL)
+                    {
+                        /* Shouldn't happen, but satisfies static analyzers */
+                        status = false;
+                        break;
+                    }
+                    initialize_pointer_field(field->pData, field);
+                    if (!decode_basic_field(&substream, PB_WT_PACKED, field))
+                    {
+                        status = false;
+                        break;
+                    }
+                    
+                    (*size)++;
+                }
+                if (!pb_close_string_substream(stream, &substream))
+                    return false;
+                
+                return status;
+            }
+            else
+            {
+                /* Normal repeated field, i.e. only one item at a time. */
+                pb_size_t *size = (pb_size_t*)field->pSize;
+
+                if (*size == PB_SIZE_MAX)
+                    PB_RETURN_ERROR(stream, "too many array entries");
+                
+                if (!allocate_field(stream, field->pField, field->data_size, (size_t)(*size + 1)))
+                    return false;
+            
+                field->pData = *(char**)field->pField + field->data_size * (*size);
+                (*size)++;
+                initialize_pointer_field(field->pData, field);
+                return decode_basic_field(stream, wire_type, field);
+            }
+
+        default:
+            PB_RETURN_ERROR(stream, "invalid field type");
+    }
+#endif
+}
+
+static bool checkreturn decode_callback_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *field)
+{
+    if (!field->descriptor->field_callback)
+        return pb_skip_field(stream, wire_type);
+
+    if (wire_type == PB_WT_STRING)
+    {
+        pb_istream_t substream;
+        size_t prev_bytes_left;
+        
+        if (!pb_make_string_substream(stream, &substream))
+            return false;
+        
+        do
+        {
+            prev_bytes_left = substream.bytes_left;
+            if (!field->descriptor->field_callback(&substream, NULL, field))
+                PB_RETURN_ERROR(stream, "callback failed");
+        } while (substream.bytes_left > 0 && substream.bytes_left < prev_bytes_left);
+        
+        if (!pb_close_string_substream(stream, &substream))
+            return false;
+
+        return true;
+    }
+    else
+    {
+        /* Copy the single scalar value to stack.
+         * This is required so that we can limit the stream length,
+         * which in turn allows to use same callback for packed and
+         * not-packed fields. */
+        pb_istream_t substream;
+        pb_byte_t buffer[10];
+        size_t size = sizeof(buffer);
+        
+        if (!read_raw_value(stream, wire_type, buffer, &size))
+            return false;
+        substream = pb_istream_from_buffer(buffer, size);
+        
+        return field->descriptor->field_callback(&substream, NULL, field);
+    }
+}
+
+static bool checkreturn decode_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *field)
+{
+#ifdef PB_ENABLE_MALLOC
+    /* When decoding an oneof field, check if there is old data that must be
+     * released first. */
+    if (PB_HTYPE(field->type) == PB_HTYPE_ONEOF)
+    {
+        if (!pb_release_union_field(stream, field))
+            return false;
+    }
+#endif
+
+    switch (PB_ATYPE(field->type))
+    {
+        case PB_ATYPE_STATIC:
+            return decode_static_field(stream, wire_type, field);
+        
+        case PB_ATYPE_POINTER:
+            return decode_pointer_field(stream, wire_type, field);
+        
+        case PB_ATYPE_CALLBACK:
+            return decode_callback_field(stream, wire_type, field);
+        
+        default:
+            PB_RETURN_ERROR(stream, "invalid field type");
+    }
+}
+
+/* Default handler for extension fields. Expects to have a pb_msgdesc_t
+ * pointer in the extension->type->arg field, pointing to a message with
+ * only one field in it.  */
+static bool checkreturn default_extension_decoder(pb_istream_t *stream,
+    pb_extension_t *extension, uint32_t tag, pb_wire_type_t wire_type)
+{
+    pb_field_iter_t iter;
+
+    if (!pb_field_iter_begin_extension(&iter, extension))
+        PB_RETURN_ERROR(stream, "invalid extension");
+
+    if (iter.tag != tag || !iter.message)
+        return true;
+
+    extension->found = true;
+    return decode_field(stream, wire_type, &iter);
+}
+
+/* Try to decode an unknown field as an extension field. Tries each extension
+ * decoder in turn, until one of them handles the field or loop ends. */
+static bool checkreturn decode_extension(pb_istream_t *stream,
+    uint32_t tag, pb_wire_type_t wire_type, pb_extension_t *extension)
+{
+    size_t pos = stream->bytes_left;
+    
+    while (extension != NULL && pos == stream->bytes_left)
+    {
+        bool status;
+        if (extension->type->decode)
+            status = extension->type->decode(stream, extension, tag, wire_type);
+        else
+            status = default_extension_decoder(stream, extension, tag, wire_type);
+
+        if (!status)
+            return false;
+        
+        extension = extension->next;
+    }
+    
+    return true;
+}
+
+/* Initialize message fields to default values, recursively */
+static bool pb_field_set_to_default(pb_field_iter_t *field)
+{
+    pb_type_t type;
+    type = field->type;
+
+    if (PB_LTYPE(type) == PB_LTYPE_EXTENSION)
+    {
+        pb_extension_t *ext = *(pb_extension_t* const *)field->pData;
+        while (ext != NULL)
+        {
+            pb_field_iter_t ext_iter;
+            if (pb_field_iter_begin_extension(&ext_iter, ext))
+            {
+                ext->found = false;
+                if (!pb_message_set_to_defaults(&ext_iter))
+                    return false;
+            }
+            ext = ext->next;
+        }
+    }
+    else if (PB_ATYPE(type) == PB_ATYPE_STATIC)
+    {
+        bool init_data = true;
+        if (PB_HTYPE(type) == PB_HTYPE_OPTIONAL && field->pSize != NULL)
+        {
+            /* Set has_field to false. Still initialize the optional field
+             * itself also. */
+            *(bool*)field->pSize = false;
+        }
+        else if (PB_HTYPE(type) == PB_HTYPE_REPEATED ||
+                 PB_HTYPE(type) == PB_HTYPE_ONEOF)
+        {
+            /* REPEATED: Set array count to 0, no need to initialize contents.
+               ONEOF: Set which_field to 0. */
+            *(pb_size_t*)field->pSize = 0;
+            init_data = false;
+        }
+
+        if (init_data)
+        {
+            if (PB_LTYPE_IS_SUBMSG(field->type) &&
+                (field->submsg_desc->default_value != NULL ||
+                 field->submsg_desc->field_callback != NULL ||
+                 field->submsg_desc->submsg_info[0] != NULL))
+            {
+                /* Initialize submessage to defaults.
+                 * Only needed if it has default values
+                 * or callback/submessage fields. */
+                pb_field_iter_t submsg_iter;
+                if (pb_field_iter_begin(&submsg_iter, field->submsg_desc, field->pData))
+                {
+                    if (!pb_message_set_to_defaults(&submsg_iter))
+                        return false;
+                }
+            }
+            else
+            {
+                /* Initialize to zeros */
+                memset(field->pData, 0, (size_t)field->data_size);
+            }
+        }
+    }
+    else if (PB_ATYPE(type) == PB_ATYPE_POINTER)
+    {
+        /* Initialize the pointer to NULL. */
+        *(void**)field->pField = NULL;
+
+        /* Initialize array count to 0. */
+        if (PB_HTYPE(type) == PB_HTYPE_REPEATED ||
+            PB_HTYPE(type) == PB_HTYPE_ONEOF)
+        {
+            *(pb_size_t*)field->pSize = 0;
+        }
+    }
+    else if (PB_ATYPE(type) == PB_ATYPE_CALLBACK)
+    {
+        /* Don't overwrite callback */
+    }
+
+    return true;
+}
+
+static bool pb_message_set_to_defaults(pb_field_iter_t *iter)
+{
+    pb_istream_t defstream = PB_ISTREAM_EMPTY;
+    uint32_t tag = 0;
+    pb_wire_type_t wire_type = PB_WT_VARINT;
+    bool eof;
+
+    if (iter->descriptor->default_value)
+    {
+        defstream = pb_istream_from_buffer(iter->descriptor->default_value, (size_t)-1);
+        if (!pb_decode_tag(&defstream, &wire_type, &tag, &eof))
+            return false;
+    }
+
+    do
+    {
+        if (!pb_field_set_to_default(iter))
+            return false;
+
+        if (tag != 0 && iter->tag == tag)
+        {
+            /* We have a default value for this field in the defstream */
+            if (!decode_field(&defstream, wire_type, iter))
+                return false;
+            if (!pb_decode_tag(&defstream, &wire_type, &tag, &eof))
+                return false;
+
+            if (iter->pSize)
+                *(bool*)iter->pSize = false;
+        }
+    } while (pb_field_iter_next(iter));
+
+    return true;
+}
+
+/*********************
+ * Decode all fields *
+ *********************/
+
+static bool checkreturn pb_decode_inner(pb_istream_t *stream, const pb_msgdesc_t *fields, void *dest_struct, unsigned int flags)
+{
+    uint32_t extension_range_start = 0;
+    pb_extension_t *extensions = NULL;
+
+    /* 'fixed_count_field' and 'fixed_count_size' track position of a repeated fixed
+     * count field. This can only handle _one_ repeated fixed count field that
+     * is unpacked and unordered among other (non repeated fixed count) fields.
+     */
+    pb_size_t fixed_count_field = PB_SIZE_MAX;
+    pb_size_t fixed_count_size = 0;
+    pb_size_t fixed_count_total_size = 0;
+
+    pb_fields_seen_t fields_seen = {{0, 0}};
+    const uint32_t allbits = ~(uint32_t)0;
+    pb_field_iter_t iter;
+
+    if (pb_field_iter_begin(&iter, fields, dest_struct))
+    {
+        if ((flags & PB_DECODE_NOINIT) == 0)
+        {
+            if (!pb_message_set_to_defaults(&iter))
+                PB_RETURN_ERROR(stream, "failed to set defaults");
+        }
+    }
+
+    while (stream->bytes_left)
+    {
+        uint32_t tag;
+        pb_wire_type_t wire_type;
+        bool eof;
+
+        if (!pb_decode_tag(stream, &wire_type, &tag, &eof))
+        {
+            if (eof)
+                break;
+            else
+                return false;
+        }
+
+        if (tag == 0)
+        {
+          if (flags & PB_DECODE_NULLTERMINATED)
+          {
+            break;
+          }
+          else
+          {
+            PB_RETURN_ERROR(stream, "zero tag");
+          }
+        }
+
+        if (!pb_field_iter_find(&iter, tag) || PB_LTYPE(iter.type) == PB_LTYPE_EXTENSION)
+        {
+            /* No match found, check if it matches an extension. */
+            if (extension_range_start == 0)
+            {
+                if (pb_field_iter_find_extension(&iter))
+                {
+                    extensions = *(pb_extension_t* const *)iter.pData;
+                    extension_range_start = iter.tag;
+                }
+
+                if (!extensions)
+                {
+                    extension_range_start = (uint32_t)-1;
+                }
+            }
+
+            if (tag >= extension_range_start)
+            {
+                size_t pos = stream->bytes_left;
+
+                if (!decode_extension(stream, tag, wire_type, extensions))
+                    return false;
+
+                if (pos != stream->bytes_left)
+                {
+                    /* The field was handled */
+                    continue;
+                }
+            }
+
+            /* No match found, skip data */
+            if (!pb_skip_field(stream, wire_type))
+                return false;
+            continue;
+        }
+
+        /* If a repeated fixed count field was found, get size from
+         * 'fixed_count_field' as there is no counter contained in the struct.
+         */
+        if (PB_HTYPE(iter.type) == PB_HTYPE_REPEATED && iter.pSize == &iter.array_size)
+        {
+            if (fixed_count_field != iter.index) {
+                /* If the new fixed count field does not match the previous one,
+                 * check that the previous one is NULL or that it finished
+                 * receiving all the expected data.
+                 */
+                if (fixed_count_field != PB_SIZE_MAX &&
+                    fixed_count_size != fixed_count_total_size)
+                {
+                    PB_RETURN_ERROR(stream, "wrong size for fixed count field");
+                }
+
+                fixed_count_field = iter.index;
+                fixed_count_size = 0;
+                fixed_count_total_size = iter.array_size;
+            }
+
+            iter.pSize = &fixed_count_size;
+        }
+
+        if (PB_HTYPE(iter.type) == PB_HTYPE_REQUIRED
+            && iter.required_field_index < PB_MAX_REQUIRED_FIELDS)
+        {
+            uint32_t tmp = ((uint32_t)1 << (iter.required_field_index & 31));
+            fields_seen.bitfield[iter.required_field_index >> 5] |= tmp;
+        }
+
+        if (!decode_field(stream, wire_type, &iter))
+            return false;
+    }
+
+    /* Check that all elements of the last decoded fixed count field were present. */
+    if (fixed_count_field != PB_SIZE_MAX &&
+        fixed_count_size != fixed_count_total_size)
+    {
+        PB_RETURN_ERROR(stream, "wrong size for fixed count field");
+    }
+
+    /* Check that all required fields were present. */
+    {
+        pb_size_t req_field_count = iter.descriptor->required_field_count;
+
+        if (req_field_count > 0)
+        {
+            pb_size_t i;
+
+            if (req_field_count > PB_MAX_REQUIRED_FIELDS)
+                req_field_count = PB_MAX_REQUIRED_FIELDS;
+
+            /* Check the whole words */
+            for (i = 0; i < (req_field_count >> 5); i++)
+            {
+                if (fields_seen.bitfield[i] != allbits)
+                    PB_RETURN_ERROR(stream, "missing required field");
+            }
+
+            /* Check the remaining bits (if any) */
+            if ((req_field_count & 31) != 0)
+            {
+                if (fields_seen.bitfield[req_field_count >> 5] !=
+                    (allbits >> (uint_least8_t)(32 - (req_field_count & 31))))
+                {
+                    PB_RETURN_ERROR(stream, "missing required field");
+                }
+            }
+        }
+    }
+
+    return true;
+}
+
+bool checkreturn pb_decode_ex(pb_istream_t *stream, const pb_msgdesc_t *fields, void *dest_struct, unsigned int flags)
+{
+    bool status;
+
+    if ((flags & PB_DECODE_DELIMITED) == 0)
+    {
+      status = pb_decode_inner(stream, fields, dest_struct, flags);
+    }
+    else
+    {
+      pb_istream_t substream;
+      if (!pb_make_string_substream(stream, &substream))
+        return false;
+
+      status = pb_decode_inner(&substream, fields, dest_struct, flags);
+
+      if (!pb_close_string_substream(stream, &substream))
+        return false;
+    }
+    
+#ifdef PB_ENABLE_MALLOC
+    if (!status)
+        pb_release(fields, dest_struct);
+#endif
+    
+    return status;
+}
+
+bool checkreturn pb_decode(pb_istream_t *stream, const pb_msgdesc_t *fields, void *dest_struct)
+{
+    bool status;
+
+    status = pb_decode_inner(stream, fields, dest_struct, 0);
+
+#ifdef PB_ENABLE_MALLOC
+    if (!status)
+        pb_release(fields, dest_struct);
+#endif
+
+    return status;
+}
+
+#ifdef PB_ENABLE_MALLOC
+/* Given an oneof field, if there has already been a field inside this oneof,
+ * release it before overwriting with a different one. */
+static bool pb_release_union_field(pb_istream_t *stream, pb_field_iter_t *field)
+{
+    pb_field_iter_t old_field = *field;
+    pb_size_t old_tag = *(pb_size_t*)field->pSize; /* Previous which_ value */
+    pb_size_t new_tag = field->tag; /* New which_ value */
+
+    if (old_tag == 0)
+        return true; /* Ok, no old data in union */
+
+    if (old_tag == new_tag)
+        return true; /* Ok, old data is of same type => merge */
+
+    /* Release old data. The find can fail if the message struct contains
+     * invalid data. */
+    if (!pb_field_iter_find(&old_field, old_tag))
+        PB_RETURN_ERROR(stream, "invalid union tag");
+
+    pb_release_single_field(&old_field);
+
+    if (PB_ATYPE(field->type) == PB_ATYPE_POINTER)
+    {
+        /* Initialize the pointer to NULL to make sure it is valid
+         * even in case of error return. */
+        *(void**)field->pField = NULL;
+        field->pData = NULL;
+    }
+
+    return true;
+}
+
+static void pb_release_single_field(pb_field_iter_t *field)
+{
+    pb_type_t type;
+    type = field->type;
+
+    if (PB_HTYPE(type) == PB_HTYPE_ONEOF)
+    {
+        if (*(pb_size_t*)field->pSize != field->tag)
+            return; /* This is not the current field in the union */
+    }
+
+    /* Release anything contained inside an extension or submsg.
+     * This has to be done even if the submsg itself is statically
+     * allocated. */
+    if (PB_LTYPE(type) == PB_LTYPE_EXTENSION)
+    {
+        /* Release fields from all extensions in the linked list */
+        pb_extension_t *ext = *(pb_extension_t**)field->pData;
+        while (ext != NULL)
+        {
+            pb_field_iter_t ext_iter;
+            if (pb_field_iter_begin_extension(&ext_iter, ext))
+            {
+                pb_release_single_field(&ext_iter);
+            }
+            ext = ext->next;
+        }
+    }
+    else if (PB_LTYPE_IS_SUBMSG(type) && PB_ATYPE(type) != PB_ATYPE_CALLBACK)
+    {
+        /* Release fields in submessage or submsg array */
+        pb_size_t count = 1;
+        
+        if (PB_ATYPE(type) == PB_ATYPE_POINTER)
+        {
+            field->pData = *(void**)field->pField;
+        }
+        else
+        {
+            field->pData = field->pField;
+        }
+        
+        if (PB_HTYPE(type) == PB_HTYPE_REPEATED)
+        {
+            count = *(pb_size_t*)field->pSize;
+
+            if (PB_ATYPE(type) == PB_ATYPE_STATIC && count > field->array_size)
+            {
+                /* Protect against corrupted _count fields */
+                count = field->array_size;
+            }
+        }
+        
+        if (field->pData)
+        {
+            for (; count > 0; count--)
+            {
+                pb_release(field->submsg_desc, field->pData);
+                field->pData = (char*)field->pData + field->data_size;
+            }
+        }
+    }
+    
+    if (PB_ATYPE(type) == PB_ATYPE_POINTER)
+    {
+        if (PB_HTYPE(type) == PB_HTYPE_REPEATED &&
+            (PB_LTYPE(type) == PB_LTYPE_STRING ||
+             PB_LTYPE(type) == PB_LTYPE_BYTES))
+        {
+            /* Release entries in repeated string or bytes array */
+            void **pItem = *(void***)field->pField;
+            pb_size_t count = *(pb_size_t*)field->pSize;
+            for (; count > 0; count--)
+            {
+                pb_free(*pItem);
+                *pItem++ = NULL;
+            }
+        }
+        
+        if (PB_HTYPE(type) == PB_HTYPE_REPEATED)
+        {
+            /* We are going to release the array, so set the size to 0 */
+            *(pb_size_t*)field->pSize = 0;
+        }
+        
+        /* Release main pointer */
+        pb_free(*(void**)field->pField);
+        *(void**)field->pField = NULL;
+    }
+}
+
+void pb_release(const pb_msgdesc_t *fields, void *dest_struct)
+{
+    pb_field_iter_t iter;
+    
+    if (!dest_struct)
+        return; /* Ignore NULL pointers, similar to free() */
+
+    if (!pb_field_iter_begin(&iter, fields, dest_struct))
+        return; /* Empty message type */
+    
+    do
+    {
+        pb_release_single_field(&iter);
+    } while (pb_field_iter_next(&iter));
+}
+#endif
+
+/* Field decoders */
+
+bool pb_decode_bool(pb_istream_t *stream, bool *dest)
+{
+    uint32_t value;
+    if (!pb_decode_varint32(stream, &value))
+        return false;
+
+    *(bool*)dest = (value != 0);
+    return true;
+}
+
+bool pb_decode_svarint(pb_istream_t *stream, pb_int64_t *dest)
+{
+    pb_uint64_t value;
+    if (!pb_decode_varint(stream, &value))
+        return false;
+    
+    if (value & 1)
+        *dest = (pb_int64_t)(~(value >> 1));
+    else
+        *dest = (pb_int64_t)(value >> 1);
+    
+    return true;
+}
+
+bool pb_decode_fixed32(pb_istream_t *stream, void *dest)
+{
+    union {
+        uint32_t fixed32;
+        pb_byte_t bytes[4];
+    } u;
+
+    if (!pb_read(stream, u.bytes, 4))
+        return false;
+
+#if defined(PB_LITTLE_ENDIAN_8BIT) && PB_LITTLE_ENDIAN_8BIT == 1
+    /* fast path - if we know that we're on little endian, assign directly */
+    *(uint32_t*)dest = u.fixed32;
+#else
+    *(uint32_t*)dest = ((uint32_t)u.bytes[0] << 0) |
+                       ((uint32_t)u.bytes[1] << 8) |
+                       ((uint32_t)u.bytes[2] << 16) |
+                       ((uint32_t)u.bytes[3] << 24);
+#endif
+    return true;
+}
+
+#ifndef PB_WITHOUT_64BIT
+bool pb_decode_fixed64(pb_istream_t *stream, void *dest)
+{
+    union {
+        uint64_t fixed64;
+        pb_byte_t bytes[8];
+    } u;
+
+    if (!pb_read(stream, u.bytes, 8))
+        return false;
+
+#if defined(PB_LITTLE_ENDIAN_8BIT) && PB_LITTLE_ENDIAN_8BIT == 1
+    /* fast path - if we know that we're on little endian, assign directly */
+    *(uint64_t*)dest = u.fixed64;
+#else
+    *(uint64_t*)dest = ((uint64_t)u.bytes[0] << 0) |
+                       ((uint64_t)u.bytes[1] << 8) |
+                       ((uint64_t)u.bytes[2] << 16) |
+                       ((uint64_t)u.bytes[3] << 24) |
+                       ((uint64_t)u.bytes[4] << 32) |
+                       ((uint64_t)u.bytes[5] << 40) |
+                       ((uint64_t)u.bytes[6] << 48) |
+                       ((uint64_t)u.bytes[7] << 56);
+#endif
+    return true;
+}
+#endif
+
+static bool checkreturn pb_dec_bool(pb_istream_t *stream, const pb_field_iter_t *field)
+{
+    return pb_decode_bool(stream, (bool*)field->pData);
+}
+
+static bool checkreturn pb_dec_varint(pb_istream_t *stream, const pb_field_iter_t *field)
+{
+    if (PB_LTYPE(field->type) == PB_LTYPE_UVARINT)
+    {
+        pb_uint64_t value, clamped;
+        if (!pb_decode_varint(stream, &value))
+            return false;
+
+        /* Cast to the proper field size, while checking for overflows */
+        if (field->data_size == sizeof(pb_uint64_t))
+            clamped = *(pb_uint64_t*)field->pData = value;
+        else if (field->data_size == sizeof(uint32_t))
+            clamped = *(uint32_t*)field->pData = (uint32_t)value;
+        else if (field->data_size == sizeof(uint_least16_t))
+            clamped = *(uint_least16_t*)field->pData = (uint_least16_t)value;
+        else if (field->data_size == sizeof(uint_least8_t))
+            clamped = *(uint_least8_t*)field->pData = (uint_least8_t)value;
+        else
+            PB_RETURN_ERROR(stream, "invalid data_size");
+
+        if (clamped != value)
+            PB_RETURN_ERROR(stream, "integer too large");
+
+        return true;
+    }
+    else
+    {
+        pb_uint64_t value;
+        pb_int64_t svalue;
+        pb_int64_t clamped;
+
+        if (PB_LTYPE(field->type) == PB_LTYPE_SVARINT)
+        {
+            if (!pb_decode_svarint(stream, &svalue))
+                return false;
+        }
+        else
+        {
+            if (!pb_decode_varint(stream, &value))
+                return false;
+
+            /* See issue 97: Google's C++ protobuf allows negative varint values to
+            * be cast as int32_t, instead of the int64_t that should be used when
+            * encoding. Nanopb versions before 0.2.5 had a bug in encoding. In order to
+            * not break decoding of such messages, we cast <=32 bit fields to
+            * int32_t first to get the sign correct.
+            */
+            if (field->data_size == sizeof(pb_int64_t))
+                svalue = (pb_int64_t)value;
+            else
+                svalue = (int32_t)value;
+        }
+
+        /* Cast to the proper field size, while checking for overflows */
+        if (field->data_size == sizeof(pb_int64_t))
+            clamped = *(pb_int64_t*)field->pData = svalue;
+        else if (field->data_size == sizeof(int32_t))
+            clamped = *(int32_t*)field->pData = (int32_t)svalue;
+        else if (field->data_size == sizeof(int_least16_t))
+            clamped = *(int_least16_t*)field->pData = (int_least16_t)svalue;
+        else if (field->data_size == sizeof(int_least8_t))
+            clamped = *(int_least8_t*)field->pData = (int_least8_t)svalue;
+        else
+            PB_RETURN_ERROR(stream, "invalid data_size");
+
+        if (clamped != svalue)
+            PB_RETURN_ERROR(stream, "integer too large");
+
+        return true;
+    }
+}
+
+static bool checkreturn pb_dec_bytes(pb_istream_t *stream, const pb_field_iter_t *field)
+{
+    uint32_t size;
+    size_t alloc_size;
+    pb_bytes_array_t *dest;
+    
+    if (!pb_decode_varint32(stream, &size))
+        return false;
+    
+    if (size > PB_SIZE_MAX)
+        PB_RETURN_ERROR(stream, "bytes overflow");
+    
+    alloc_size = PB_BYTES_ARRAY_T_ALLOCSIZE(size);
+    if (size > alloc_size)
+        PB_RETURN_ERROR(stream, "size too large");
+    
+    if (PB_ATYPE(field->type) == PB_ATYPE_POINTER)
+    {
+#ifndef PB_ENABLE_MALLOC
+        PB_RETURN_ERROR(stream, "no malloc support");
+#else
+        if (stream->bytes_left < size)
+            PB_RETURN_ERROR(stream, "end-of-stream");
+
+        if (!allocate_field(stream, field->pData, alloc_size, 1))
+            return false;
+        dest = *(pb_bytes_array_t**)field->pData;
+#endif
+    }
+    else
+    {
+        if (alloc_size > field->data_size)
+            PB_RETURN_ERROR(stream, "bytes overflow");
+        dest = (pb_bytes_array_t*)field->pData;
+    }
+
+    dest->size = (pb_size_t)size;
+    return pb_read(stream, dest->bytes, (size_t)size);
+}
+
+static bool checkreturn pb_dec_string(pb_istream_t *stream, const pb_field_iter_t *field)
+{
+    uint32_t size;
+    size_t alloc_size;
+    pb_byte_t *dest = (pb_byte_t*)field->pData;
+
+    if (!pb_decode_varint32(stream, &size))
+        return false;
+
+    if (size == (uint32_t)-1)
+        PB_RETURN_ERROR(stream, "size too large");
+
+    /* Space for null terminator */
+    alloc_size = (size_t)(size + 1);
+
+    if (alloc_size < size)
+        PB_RETURN_ERROR(stream, "size too large");
+
+    if (PB_ATYPE(field->type) == PB_ATYPE_POINTER)
+    {
+#ifndef PB_ENABLE_MALLOC
+        PB_RETURN_ERROR(stream, "no malloc support");
+#else
+        if (stream->bytes_left < size)
+            PB_RETURN_ERROR(stream, "end-of-stream");
+
+        if (!allocate_field(stream, field->pData, alloc_size, 1))
+            return false;
+        dest = *(pb_byte_t**)field->pData;
+#endif
+    }
+    else
+    {
+        if (alloc_size > field->data_size)
+            PB_RETURN_ERROR(stream, "string overflow");
+    }
+    
+    dest[size] = 0;
+
+    if (!pb_read(stream, dest, (size_t)size))
+        return false;
+
+#ifdef PB_VALIDATE_UTF8
+    if (!pb_validate_utf8((const char*)dest))
+        PB_RETURN_ERROR(stream, "invalid utf8");
+#endif
+
+    return true;
+}
+
+static bool checkreturn pb_dec_submessage(pb_istream_t *stream, const pb_field_iter_t *field)
+{
+    bool status = true;
+    bool submsg_consumed = false;
+    pb_istream_t substream;
+
+    if (!pb_make_string_substream(stream, &substream))
+        return false;
+    
+    if (field->submsg_desc == NULL)
+        PB_RETURN_ERROR(stream, "invalid field descriptor");
+    
+    /* Submessages can have a separate message-level callback that is called
+     * before decoding the message. Typically it is used to set callback fields
+     * inside oneofs. */
+    if (PB_LTYPE(field->type) == PB_LTYPE_SUBMSG_W_CB && field->pSize != NULL)
+    {
+        /* Message callback is stored right before pSize. */
+        pb_callback_t *callback = (pb_callback_t*)field->pSize - 1;
+        if (callback->funcs.decode)
+        {
+            status = callback->funcs.decode(&substream, field, &callback->arg);
+
+            if (substream.bytes_left == 0)
+            {
+                submsg_consumed = true;
+            }
+        }
+    }
+
+    /* Now decode the submessage contents */
+    if (status && !submsg_consumed)
+    {
+        unsigned int flags = 0;
+
+        /* Static required/optional fields are already initialized by top-level
+         * pb_decode(), no need to initialize them again. */
+        if (PB_ATYPE(field->type) == PB_ATYPE_STATIC &&
+            PB_HTYPE(field->type) != PB_HTYPE_REPEATED)
+        {
+            flags = PB_DECODE_NOINIT;
+        }
+
+        status = pb_decode_inner(&substream, field->submsg_desc, field->pData, flags);
+    }
+    
+    if (!pb_close_string_substream(stream, &substream))
+        return false;
+
+    return status;
+}
+
+static bool checkreturn pb_dec_fixed_length_bytes(pb_istream_t *stream, const pb_field_iter_t *field)
+{
+    uint32_t size;
+
+    if (!pb_decode_varint32(stream, &size))
+        return false;
+
+    if (size > PB_SIZE_MAX)
+        PB_RETURN_ERROR(stream, "bytes overflow");
+
+    if (size == 0)
+    {
+        /* As a special case, treat empty bytes string as all zeros for fixed_length_bytes. */
+        memset(field->pData, 0, (size_t)field->data_size);
+        return true;
+    }
+
+    if (size != field->data_size)
+        PB_RETURN_ERROR(stream, "incorrect fixed length bytes size");
+
+    return pb_read(stream, (pb_byte_t*)field->pData, (size_t)field->data_size);
+}
+
+#ifdef PB_CONVERT_DOUBLE_FLOAT
+bool pb_decode_double_as_float(pb_istream_t *stream, float *dest)
+{
+    uint_least8_t sign;
+    int exponent;
+    uint32_t mantissa;
+    uint64_t value;
+    union { float f; uint32_t i; } out;
+
+    if (!pb_decode_fixed64(stream, &value))
+        return false;
+
+    /* Decompose input value */
+    sign = (uint_least8_t)((value >> 63) & 1);
+    exponent = (int)((value >> 52) & 0x7FF) - 1023;
+    mantissa = (value >> 28) & 0xFFFFFF; /* Highest 24 bits */
+
+    /* Figure if value is in range representable by floats. */
+    if (exponent == 1024)
+    {
+        /* Special value */
+        exponent = 128;
+        mantissa >>= 1;
+    }
+    else
+    {
+        if (exponent > 127)
+        {
+            /* Too large, convert to infinity */
+            exponent = 128;
+            mantissa = 0;
+        }
+        else if (exponent < -150)
+        {
+            /* Too small, convert to zero */
+            exponent = -127;
+            mantissa = 0;
+        }
+        else if (exponent < -126)
+        {
+            /* Denormalized */
+            mantissa |= 0x1000000;
+            mantissa >>= (-126 - exponent);
+            exponent = -127;
+        }
+
+        /* Round off mantissa */
+        mantissa = (mantissa + 1) >> 1;
+
+        /* Check if mantissa went over 2.0 */
+        if (mantissa & 0x800000)
+        {
+            exponent += 1;
+            mantissa &= 0x7FFFFF;
+            mantissa >>= 1;
+        }
+    }
+
+    /* Combine fields */
+    out.i = mantissa;
+    out.i |= (uint32_t)(exponent + 127) << 23;
+    out.i |= (uint32_t)sign << 31;
+
+    *dest = out.f;
+    return true;
+}
+#endif

+ 199 - 0
components/spotify/cspot/bell/nanopb/pb_decode.h

@@ -0,0 +1,199 @@
+/* pb_decode.h: Functions to decode protocol buffers. Depends on pb_decode.c.
+ * The main function is pb_decode. You also need an input stream, and the
+ * field descriptions created by nanopb_generator.py.
+ */
+
+#ifndef PB_DECODE_H_INCLUDED
+#define PB_DECODE_H_INCLUDED
+
+#include "pb.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Structure for defining custom input streams. You will need to provide
+ * a callback function to read the bytes from your storage, which can be
+ * for example a file or a network socket.
+ * 
+ * The callback must conform to these rules:
+ *
+ * 1) Return false on IO errors. This will cause decoding to abort.
+ * 2) You can use state to store your own data (e.g. buffer pointer),
+ *    and rely on pb_read to verify that no-body reads past bytes_left.
+ * 3) Your callback may be used with substreams, in which case bytes_left
+ *    is different than from the main stream. Don't use bytes_left to compute
+ *    any pointers.
+ */
+struct pb_istream_s
+{
+#ifdef PB_BUFFER_ONLY
+    /* Callback pointer is not used in buffer-only configuration.
+     * Having an int pointer here allows binary compatibility but
+     * gives an error if someone tries to assign callback function.
+     */
+    int *callback;
+#else
+    bool (*callback)(pb_istream_t *stream, pb_byte_t *buf, size_t count);
+#endif
+
+    void *state; /* Free field for use by callback implementation */
+    size_t bytes_left;
+    
+#ifndef PB_NO_ERRMSG
+    const char *errmsg;
+#endif
+};
+
+#ifndef PB_NO_ERRMSG
+#define PB_ISTREAM_EMPTY {0,0,0,0}
+#else
+#define PB_ISTREAM_EMPTY {0,0,0}
+#endif
+
+/***************************
+ * Main decoding functions *
+ ***************************/
+ 
+/* Decode a single protocol buffers message from input stream into a C structure.
+ * Returns true on success, false on any failure.
+ * The actual struct pointed to by dest must match the description in fields.
+ * Callback fields of the destination structure must be initialized by caller.
+ * All other fields will be initialized by this function.
+ *
+ * Example usage:
+ *    MyMessage msg = {};
+ *    uint8_t buffer[64];
+ *    pb_istream_t stream;
+ *    
+ *    // ... read some data into buffer ...
+ *
+ *    stream = pb_istream_from_buffer(buffer, count);
+ *    pb_decode(&stream, MyMessage_fields, &msg);
+ */
+bool pb_decode(pb_istream_t *stream, const pb_msgdesc_t *fields, void *dest_struct);
+
+/* Extended version of pb_decode, with several options to control
+ * the decoding process:
+ *
+ * PB_DECODE_NOINIT:         Do not initialize the fields to default values.
+ *                           This is slightly faster if you do not need the default
+ *                           values and instead initialize the structure to 0 using
+ *                           e.g. memset(). This can also be used for merging two
+ *                           messages, i.e. combine already existing data with new
+ *                           values.
+ *
+ * PB_DECODE_DELIMITED:      Input message starts with the message size as varint.
+ *                           Corresponds to parseDelimitedFrom() in Google's
+ *                           protobuf API.
+ *
+ * PB_DECODE_NULLTERMINATED: Stop reading when field tag is read as 0. This allows
+ *                           reading null terminated messages.
+ *                           NOTE: Until nanopb-0.4.0, pb_decode() also allows
+ *                           null-termination. This behaviour is not supported in
+ *                           most other protobuf implementations, so PB_DECODE_DELIMITED
+ *                           is a better option for compatibility.
+ *
+ * Multiple flags can be combined with bitwise or (| operator)
+ */
+#define PB_DECODE_NOINIT          0x01U
+#define PB_DECODE_DELIMITED       0x02U
+#define PB_DECODE_NULLTERMINATED  0x04U
+bool pb_decode_ex(pb_istream_t *stream, const pb_msgdesc_t *fields, void *dest_struct, unsigned int flags);
+
+/* Defines for backwards compatibility with code written before nanopb-0.4.0 */
+#define pb_decode_noinit(s,f,d) pb_decode_ex(s,f,d, PB_DECODE_NOINIT)
+#define pb_decode_delimited(s,f,d) pb_decode_ex(s,f,d, PB_DECODE_DELIMITED)
+#define pb_decode_delimited_noinit(s,f,d) pb_decode_ex(s,f,d, PB_DECODE_DELIMITED | PB_DECODE_NOINIT)
+#define pb_decode_nullterminated(s,f,d) pb_decode_ex(s,f,d, PB_DECODE_NULLTERMINATED)
+
+#ifdef PB_ENABLE_MALLOC
+/* Release any allocated pointer fields. If you use dynamic allocation, you should
+ * call this for any successfully decoded message when you are done with it. If
+ * pb_decode() returns with an error, the message is already released.
+ */
+void pb_release(const pb_msgdesc_t *fields, void *dest_struct);
+#else
+/* Allocation is not supported, so release is no-op */
+#define pb_release(fields, dest_struct) PB_UNUSED(fields); PB_UNUSED(dest_struct);
+#endif
+
+
+/**************************************
+ * Functions for manipulating streams *
+ **************************************/
+
+/* Create an input stream for reading from a memory buffer.
+ *
+ * msglen should be the actual length of the message, not the full size of
+ * allocated buffer.
+ *
+ * Alternatively, you can use a custom stream that reads directly from e.g.
+ * a file or a network socket.
+ */
+pb_istream_t pb_istream_from_buffer(const pb_byte_t *buf, size_t msglen);
+
+/* Function to read from a pb_istream_t. You can use this if you need to
+ * read some custom header data, or to read data in field callbacks.
+ */
+bool pb_read(pb_istream_t *stream, pb_byte_t *buf, size_t count);
+
+
+/************************************************
+ * Helper functions for writing field callbacks *
+ ************************************************/
+
+/* Decode the tag for the next field in the stream. Gives the wire type and
+ * field tag. At end of the message, returns false and sets eof to true. */
+bool pb_decode_tag(pb_istream_t *stream, pb_wire_type_t *wire_type, uint32_t *tag, bool *eof);
+
+/* Skip the field payload data, given the wire type. */
+bool pb_skip_field(pb_istream_t *stream, pb_wire_type_t wire_type);
+
+/* Decode an integer in the varint format. This works for enum, int32,
+ * int64, uint32 and uint64 field types. */
+#ifndef PB_WITHOUT_64BIT
+bool pb_decode_varint(pb_istream_t *stream, uint64_t *dest);
+#else
+#define pb_decode_varint pb_decode_varint32
+#endif
+
+/* Decode an integer in the varint format. This works for enum, int32,
+ * and uint32 field types. */
+bool pb_decode_varint32(pb_istream_t *stream, uint32_t *dest);
+
+/* Decode a bool value in varint format. */
+bool pb_decode_bool(pb_istream_t *stream, bool *dest);
+
+/* Decode an integer in the zig-zagged svarint format. This works for sint32
+ * and sint64. */
+#ifndef PB_WITHOUT_64BIT
+bool pb_decode_svarint(pb_istream_t *stream, int64_t *dest);
+#else
+bool pb_decode_svarint(pb_istream_t *stream, int32_t *dest);
+#endif
+
+/* Decode a fixed32, sfixed32 or float value. You need to pass a pointer to
+ * a 4-byte wide C variable. */
+bool pb_decode_fixed32(pb_istream_t *stream, void *dest);
+
+#ifndef PB_WITHOUT_64BIT
+/* Decode a fixed64, sfixed64 or double value. You need to pass a pointer to
+ * a 8-byte wide C variable. */
+bool pb_decode_fixed64(pb_istream_t *stream, void *dest);
+#endif
+
+#ifdef PB_CONVERT_DOUBLE_FLOAT
+/* Decode a double value into float variable. */
+bool pb_decode_double_as_float(pb_istream_t *stream, float *dest);
+#endif
+
+/* Make a limited-length substream for reading a PB_WT_STRING field. */
+bool pb_make_string_substream(pb_istream_t *stream, pb_istream_t *substream);
+bool pb_close_string_substream(pb_istream_t *stream, pb_istream_t *substream);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif

+ 1001 - 0
components/spotify/cspot/bell/nanopb/pb_encode.c

@@ -0,0 +1,1001 @@
+/* pb_encode.c -- encode a protobuf using minimal resources
+ *
+ * 2011 Petteri Aimonen <jpa@kapsi.fi>
+ */
+
+#include "pb.h"
+#include "pb_encode.h"
+#include "pb_common.h"
+
+/* Use the GCC warn_unused_result attribute to check that all return values
+ * are propagated correctly. On other compilers and gcc before 3.4.0 just
+ * ignore the annotation.
+ */
+#if !defined(__GNUC__) || ( __GNUC__ < 3) || (__GNUC__ == 3 && __GNUC_MINOR__ < 4)
+    #define checkreturn
+#else
+    #define checkreturn __attribute__((warn_unused_result))
+#endif
+
+/**************************************
+ * Declarations internal to this file *
+ **************************************/
+static bool checkreturn buf_write(pb_ostream_t *stream, const pb_byte_t *buf, size_t count);
+static bool checkreturn encode_array(pb_ostream_t *stream, pb_field_iter_t *field);
+static bool checkreturn pb_check_proto3_default_value(const pb_field_iter_t *field);
+static bool checkreturn encode_basic_field(pb_ostream_t *stream, const pb_field_iter_t *field);
+static bool checkreturn encode_callback_field(pb_ostream_t *stream, const pb_field_iter_t *field);
+static bool checkreturn encode_field(pb_ostream_t *stream, pb_field_iter_t *field);
+static bool checkreturn encode_extension_field(pb_ostream_t *stream, const pb_field_iter_t *field);
+static bool checkreturn default_extension_encoder(pb_ostream_t *stream, const pb_extension_t *extension);
+static bool checkreturn pb_encode_varint_32(pb_ostream_t *stream, uint32_t low, uint32_t high);
+static bool checkreturn pb_enc_bool(pb_ostream_t *stream, const pb_field_iter_t *field);
+static bool checkreturn pb_enc_varint(pb_ostream_t *stream, const pb_field_iter_t *field);
+static bool checkreturn pb_enc_fixed(pb_ostream_t *stream, const pb_field_iter_t *field);
+static bool checkreturn pb_enc_bytes(pb_ostream_t *stream, const pb_field_iter_t *field);
+static bool checkreturn pb_enc_string(pb_ostream_t *stream, const pb_field_iter_t *field);
+static bool checkreturn pb_enc_submessage(pb_ostream_t *stream, const pb_field_iter_t *field);
+static bool checkreturn pb_enc_fixed_length_bytes(pb_ostream_t *stream, const pb_field_iter_t *field);
+
+#ifdef PB_WITHOUT_64BIT
+#define pb_int64_t int32_t
+#define pb_uint64_t uint32_t
+#else
+#define pb_int64_t int64_t
+#define pb_uint64_t uint64_t
+#endif
+
+/*******************************
+ * pb_ostream_t implementation *
+ *******************************/
+
+static bool checkreturn buf_write(pb_ostream_t *stream, const pb_byte_t *buf, size_t count)
+{
+    size_t i;
+    pb_byte_t *dest = (pb_byte_t*)stream->state;
+    stream->state = dest + count;
+    
+    for (i = 0; i < count; i++)
+        dest[i] = buf[i];
+    
+    return true;
+}
+
+pb_ostream_t pb_ostream_from_buffer(pb_byte_t *buf, size_t bufsize)
+{
+    pb_ostream_t stream;
+#ifdef PB_BUFFER_ONLY
+    /* In PB_BUFFER_ONLY configuration the callback pointer is just int*.
+     * NULL pointer marks a sizing field, so put a non-NULL value to mark a buffer stream.
+     */
+    static const int marker = 0;
+    stream.callback = &marker;
+#else
+    stream.callback = &buf_write;
+#endif
+    stream.state = buf;
+    stream.max_size = bufsize;
+    stream.bytes_written = 0;
+#ifndef PB_NO_ERRMSG
+    stream.errmsg = NULL;
+#endif
+    return stream;
+}
+
+bool checkreturn pb_write(pb_ostream_t *stream, const pb_byte_t *buf, size_t count)
+{
+    if (count > 0 && stream->callback != NULL)
+    {
+        if (stream->bytes_written + count < stream->bytes_written ||
+            stream->bytes_written + count > stream->max_size)
+        {
+            PB_RETURN_ERROR(stream, "stream full");
+        }
+
+#ifdef PB_BUFFER_ONLY
+        if (!buf_write(stream, buf, count))
+            PB_RETURN_ERROR(stream, "io error");
+#else        
+        if (!stream->callback(stream, buf, count))
+            PB_RETURN_ERROR(stream, "io error");
+#endif
+    }
+    
+    stream->bytes_written += count;
+    return true;
+}
+
+/*************************
+ * Encode a single field *
+ *************************/
+
+/* Read a bool value without causing undefined behavior even if the value
+ * is invalid. See issue #434 and
+ * https://stackoverflow.com/questions/27661768/weird-results-for-conditional
+ */
+static bool safe_read_bool(const void *pSize)
+{
+    const char *p = (const char *)pSize;
+    size_t i;
+    for (i = 0; i < sizeof(bool); i++)
+    {
+        if (p[i] != 0)
+            return true;
+    }
+    return false;
+}
+
+/* Encode a static array. Handles the size calculations and possible packing. */
+static bool checkreturn encode_array(pb_ostream_t *stream, pb_field_iter_t *field)
+{
+    pb_size_t i;
+    pb_size_t count;
+#ifndef PB_ENCODE_ARRAYS_UNPACKED
+    size_t size;
+#endif
+
+    count = *(pb_size_t*)field->pSize;
+
+    if (count == 0)
+        return true;
+
+    if (PB_ATYPE(field->type) != PB_ATYPE_POINTER && count > field->array_size)
+        PB_RETURN_ERROR(stream, "array max size exceeded");
+    
+#ifndef PB_ENCODE_ARRAYS_UNPACKED
+    /* We always pack arrays if the datatype allows it. */
+    if (PB_LTYPE(field->type) <= PB_LTYPE_LAST_PACKABLE)
+    {
+        if (!pb_encode_tag(stream, PB_WT_STRING, field->tag))
+            return false;
+        
+        /* Determine the total size of packed array. */
+        if (PB_LTYPE(field->type) == PB_LTYPE_FIXED32)
+        {
+            size = 4 * (size_t)count;
+        }
+        else if (PB_LTYPE(field->type) == PB_LTYPE_FIXED64)
+        {
+            size = 8 * (size_t)count;
+        }
+        else
+        { 
+            pb_ostream_t sizestream = PB_OSTREAM_SIZING;
+            void *pData_orig = field->pData;
+            for (i = 0; i < count; i++)
+            {
+                if (!pb_enc_varint(&sizestream, field))
+                    PB_RETURN_ERROR(stream, PB_GET_ERROR(&sizestream));
+                field->pData = (char*)field->pData + field->data_size;
+            }
+            field->pData = pData_orig;
+            size = sizestream.bytes_written;
+        }
+        
+        if (!pb_encode_varint(stream, (pb_uint64_t)size))
+            return false;
+        
+        if (stream->callback == NULL)
+            return pb_write(stream, NULL, size); /* Just sizing.. */
+        
+        /* Write the data */
+        for (i = 0; i < count; i++)
+        {
+            if (PB_LTYPE(field->type) == PB_LTYPE_FIXED32 || PB_LTYPE(field->type) == PB_LTYPE_FIXED64)
+            {
+                if (!pb_enc_fixed(stream, field))
+                    return false;
+            }
+            else
+            {
+                if (!pb_enc_varint(stream, field))
+                    return false;
+            }
+
+            field->pData = (char*)field->pData + field->data_size;
+        }
+    }
+    else /* Unpacked fields */
+#endif
+    {
+        for (i = 0; i < count; i++)
+        {
+            /* Normally the data is stored directly in the array entries, but
+             * for pointer-type string and bytes fields, the array entries are
+             * actually pointers themselves also. So we have to dereference once
+             * more to get to the actual data. */
+            if (PB_ATYPE(field->type) == PB_ATYPE_POINTER &&
+                (PB_LTYPE(field->type) == PB_LTYPE_STRING ||
+                 PB_LTYPE(field->type) == PB_LTYPE_BYTES))
+            {
+                bool status;
+                void *pData_orig = field->pData;
+                field->pData = *(void* const*)field->pData;
+
+                if (!field->pData)
+                {
+                    /* Null pointer in array is treated as empty string / bytes */
+                    status = pb_encode_tag_for_field(stream, field) &&
+                             pb_encode_varint(stream, 0);
+                }
+                else
+                {
+                    status = encode_basic_field(stream, field);
+                }
+
+                field->pData = pData_orig;
+
+                if (!status)
+                    return false;
+            }
+            else
+            {
+                if (!encode_basic_field(stream, field))
+                    return false;
+            }
+            field->pData = (char*)field->pData + field->data_size;
+        }
+    }
+    
+    return true;
+}
+
+/* In proto3, all fields are optional and are only encoded if their value is "non-zero".
+ * This function implements the check for the zero value. */
+static bool checkreturn pb_check_proto3_default_value(const pb_field_iter_t *field)
+{
+    pb_type_t type = field->type;
+
+    if (PB_ATYPE(type) == PB_ATYPE_STATIC)
+    {
+        if (PB_HTYPE(type) == PB_HTYPE_REQUIRED)
+        {
+            /* Required proto2 fields inside proto3 submessage, pretty rare case */
+            return false;
+        }
+        else if (PB_HTYPE(type) == PB_HTYPE_REPEATED)
+        {
+            /* Repeated fields inside proto3 submessage: present if count != 0 */
+            return *(const pb_size_t*)field->pSize == 0;
+        }
+        else if (PB_HTYPE(type) == PB_HTYPE_ONEOF)
+        {
+            /* Oneof fields */
+            return *(const pb_size_t*)field->pSize == 0;
+        }
+        else if (PB_HTYPE(type) == PB_HTYPE_OPTIONAL && field->pSize != NULL)
+        {
+            /* Proto2 optional fields inside proto3 message, or proto3
+             * submessage fields. */
+            return safe_read_bool(field->pSize) == false;
+        }
+        else if (field->descriptor->default_value)
+        {
+            /* Proto3 messages do not have default values, but proto2 messages
+             * can contain optional fields without has_fields (generator option 'proto3').
+             * In this case they must always be encoded, to make sure that the
+             * non-zero default value is overwritten.
+             */
+            return false;
+        }
+
+        /* Rest is proto3 singular fields */
+        if (PB_LTYPE(type) <= PB_LTYPE_LAST_PACKABLE)
+        {
+            /* Simple integer / float fields */
+            pb_size_t i;
+            const char *p = (const char*)field->pData;
+            for (i = 0; i < field->data_size; i++)
+            {
+                if (p[i] != 0)
+                {
+                    return false;
+                }
+            }
+
+            return true;
+        }
+        else if (PB_LTYPE(type) == PB_LTYPE_BYTES)
+        {
+            const pb_bytes_array_t *bytes = (const pb_bytes_array_t*)field->pData;
+            return bytes->size == 0;
+        }
+        else if (PB_LTYPE(type) == PB_LTYPE_STRING)
+        {
+            return *(const char*)field->pData == '\0';
+        }
+        else if (PB_LTYPE(type) == PB_LTYPE_FIXED_LENGTH_BYTES)
+        {
+            /* Fixed length bytes is only empty if its length is fixed
+             * as 0. Which would be pretty strange, but we can check
+             * it anyway. */
+            return field->data_size == 0;
+        }
+        else if (PB_LTYPE_IS_SUBMSG(type))
+        {
+            /* Check all fields in the submessage to find if any of them
+             * are non-zero. The comparison cannot be done byte-per-byte
+             * because the C struct may contain padding bytes that must
+             * be skipped. Note that usually proto3 submessages have
+             * a separate has_field that is checked earlier in this if.
+             */
+            pb_field_iter_t iter;
+            if (pb_field_iter_begin(&iter, field->submsg_desc, field->pData))
+            {
+                do
+                {
+                    if (!pb_check_proto3_default_value(&iter))
+                    {
+                        return false;
+                    }
+                } while (pb_field_iter_next(&iter));
+            }
+            return true;
+        }
+    }
+    else if (PB_ATYPE(type) == PB_ATYPE_POINTER)
+    {
+        return field->pData == NULL;
+    }
+    else if (PB_ATYPE(type) == PB_ATYPE_CALLBACK)
+    {
+        if (PB_LTYPE(type) == PB_LTYPE_EXTENSION)
+        {
+            const pb_extension_t *extension = *(const pb_extension_t* const *)field->pData;
+            return extension == NULL;
+        }
+        else if (field->descriptor->field_callback == pb_default_field_callback)
+        {
+            pb_callback_t *pCallback = (pb_callback_t*)field->pData;
+            return pCallback->funcs.encode == NULL;
+        }
+        else
+        {
+            return field->descriptor->field_callback == NULL;
+        }
+    }
+
+    return false; /* Not typically reached, safe default for weird special cases. */
+}
+
+/* Encode a field with static or pointer allocation, i.e. one whose data
+ * is available to the encoder directly. */
+static bool checkreturn encode_basic_field(pb_ostream_t *stream, const pb_field_iter_t *field)
+{
+    if (!field->pData)
+    {
+        /* Missing pointer field */
+        return true;
+    }
+
+    if (!pb_encode_tag_for_field(stream, field))
+        return false;
+
+    switch (PB_LTYPE(field->type))
+    {
+        case PB_LTYPE_BOOL:
+            return pb_enc_bool(stream, field);
+
+        case PB_LTYPE_VARINT:
+        case PB_LTYPE_UVARINT:
+        case PB_LTYPE_SVARINT:
+            return pb_enc_varint(stream, field);
+
+        case PB_LTYPE_FIXED32:
+        case PB_LTYPE_FIXED64:
+            return pb_enc_fixed(stream, field);
+
+        case PB_LTYPE_BYTES:
+            return pb_enc_bytes(stream, field);
+
+        case PB_LTYPE_STRING:
+            return pb_enc_string(stream, field);
+
+        case PB_LTYPE_SUBMESSAGE:
+        case PB_LTYPE_SUBMSG_W_CB:
+            return pb_enc_submessage(stream, field);
+
+        case PB_LTYPE_FIXED_LENGTH_BYTES:
+            return pb_enc_fixed_length_bytes(stream, field);
+
+        default:
+            PB_RETURN_ERROR(stream, "invalid field type");
+    }
+}
+
+/* Encode a field with callback semantics. This means that a user function is
+ * called to provide and encode the actual data. */
+static bool checkreturn encode_callback_field(pb_ostream_t *stream, const pb_field_iter_t *field)
+{
+    if (field->descriptor->field_callback != NULL)
+    {
+        if (!field->descriptor->field_callback(NULL, stream, field))
+            PB_RETURN_ERROR(stream, "callback error");
+    }
+    return true;
+}
+
+/* Encode a single field of any callback, pointer or static type. */
+static bool checkreturn encode_field(pb_ostream_t *stream, pb_field_iter_t *field)
+{
+    /* Check field presence */
+    if (PB_HTYPE(field->type) == PB_HTYPE_ONEOF)
+    {
+        if (*(const pb_size_t*)field->pSize != field->tag)
+        {
+            /* Different type oneof field */
+            return true;
+        }
+    }
+    else if (PB_HTYPE(field->type) == PB_HTYPE_OPTIONAL)
+    {
+        if (field->pSize)
+        {
+            if (safe_read_bool(field->pSize) == false)
+            {
+                /* Missing optional field */
+                return true;
+            }
+        }
+        else if (PB_ATYPE(field->type) == PB_ATYPE_STATIC)
+        {
+            /* Proto3 singular field */
+            if (pb_check_proto3_default_value(field))
+                return true;
+        }
+    }
+
+    if (!field->pData)
+    {
+        if (PB_HTYPE(field->type) == PB_HTYPE_REQUIRED)
+            PB_RETURN_ERROR(stream, "missing required field");
+
+        /* Pointer field set to NULL */
+        return true;
+    }
+
+    /* Then encode field contents */
+    if (PB_ATYPE(field->type) == PB_ATYPE_CALLBACK)
+    {
+        return encode_callback_field(stream, field);
+    }
+    else if (PB_HTYPE(field->type) == PB_HTYPE_REPEATED)
+    {
+        return encode_array(stream, field);
+    }
+    else
+    {
+        return encode_basic_field(stream, field);
+    }
+}
+
+/* Default handler for extension fields. Expects to have a pb_msgdesc_t
+ * pointer in the extension->type->arg field, pointing to a message with
+ * only one field in it.  */
+static bool checkreturn default_extension_encoder(pb_ostream_t *stream, const pb_extension_t *extension)
+{
+    pb_field_iter_t iter;
+
+    if (!pb_field_iter_begin_extension_const(&iter, extension))
+        PB_RETURN_ERROR(stream, "invalid extension");
+
+    return encode_field(stream, &iter);
+}
+
+
+/* Walk through all the registered extensions and give them a chance
+ * to encode themselves. */
+static bool checkreturn encode_extension_field(pb_ostream_t *stream, const pb_field_iter_t *field)
+{
+    const pb_extension_t *extension = *(const pb_extension_t* const *)field->pData;
+
+    while (extension)
+    {
+        bool status;
+        if (extension->type->encode)
+            status = extension->type->encode(stream, extension);
+        else
+            status = default_extension_encoder(stream, extension);
+
+        if (!status)
+            return false;
+        
+        extension = extension->next;
+    }
+    
+    return true;
+}
+
+/*********************
+ * Encode all fields *
+ *********************/
+
+bool checkreturn pb_encode(pb_ostream_t *stream, const pb_msgdesc_t *fields, const void *src_struct)
+{
+    pb_field_iter_t iter;
+    if (!pb_field_iter_begin_const(&iter, fields, src_struct))
+        return true; /* Empty message type */
+    
+    do {
+        if (PB_LTYPE(iter.type) == PB_LTYPE_EXTENSION)
+        {
+            /* Special case for the extension field placeholder */
+            if (!encode_extension_field(stream, &iter))
+                return false;
+        }
+        else
+        {
+            /* Regular field */
+            if (!encode_field(stream, &iter))
+                return false;
+        }
+    } while (pb_field_iter_next(&iter));
+    
+    return true;
+}
+
+bool checkreturn pb_encode_ex(pb_ostream_t *stream, const pb_msgdesc_t *fields, const void *src_struct, unsigned int flags)
+{
+  if ((flags & PB_ENCODE_DELIMITED) != 0)
+  {
+    return pb_encode_submessage(stream, fields, src_struct);
+  }
+  else if ((flags & PB_ENCODE_NULLTERMINATED) != 0)
+  {
+    const pb_byte_t zero = 0;
+
+    if (!pb_encode(stream, fields, src_struct))
+        return false;
+
+    return pb_write(stream, &zero, 1);
+  }
+  else
+  {
+    return pb_encode(stream, fields, src_struct);
+  }
+}
+
+bool pb_get_encoded_size(size_t *size, const pb_msgdesc_t *fields, const void *src_struct)
+{
+    pb_ostream_t stream = PB_OSTREAM_SIZING;
+    
+    if (!pb_encode(&stream, fields, src_struct))
+        return false;
+    
+    *size = stream.bytes_written;
+    return true;
+}
+
+/********************
+ * Helper functions *
+ ********************/
+
+/* This function avoids 64-bit shifts as they are quite slow on many platforms. */
+static bool checkreturn pb_encode_varint_32(pb_ostream_t *stream, uint32_t low, uint32_t high)
+{
+    size_t i = 0;
+    pb_byte_t buffer[10];
+    pb_byte_t byte = (pb_byte_t)(low & 0x7F);
+    low >>= 7;
+
+    while (i < 4 && (low != 0 || high != 0))
+    {
+        byte |= 0x80;
+        buffer[i++] = byte;
+        byte = (pb_byte_t)(low & 0x7F);
+        low >>= 7;
+    }
+
+    if (high)
+    {
+        byte = (pb_byte_t)(byte | ((high & 0x07) << 4));
+        high >>= 3;
+
+        while (high)
+        {
+            byte |= 0x80;
+            buffer[i++] = byte;
+            byte = (pb_byte_t)(high & 0x7F);
+            high >>= 7;
+        }
+    }
+
+    buffer[i++] = byte;
+
+    return pb_write(stream, buffer, i);
+}
+
+bool checkreturn pb_encode_varint(pb_ostream_t *stream, pb_uint64_t value)
+{
+    if (value <= 0x7F)
+    {
+        /* Fast path: single byte */
+        pb_byte_t byte = (pb_byte_t)value;
+        return pb_write(stream, &byte, 1);
+    }
+    else
+    {
+#ifdef PB_WITHOUT_64BIT
+        return pb_encode_varint_32(stream, value, 0);
+#else
+        return pb_encode_varint_32(stream, (uint32_t)value, (uint32_t)(value >> 32));
+#endif
+    }
+}
+
+bool checkreturn pb_encode_svarint(pb_ostream_t *stream, pb_int64_t value)
+{
+    pb_uint64_t zigzagged;
+    if (value < 0)
+        zigzagged = ~((pb_uint64_t)value << 1);
+    else
+        zigzagged = (pb_uint64_t)value << 1;
+    
+    return pb_encode_varint(stream, zigzagged);
+}
+
+bool checkreturn pb_encode_fixed32(pb_ostream_t *stream, const void *value)
+{
+#if defined(PB_LITTLE_ENDIAN_8BIT) && PB_LITTLE_ENDIAN_8BIT == 1
+    /* Fast path if we know that we're on little endian */
+    return pb_write(stream, (const pb_byte_t*)value, 4);
+#else
+    uint32_t val = *(const uint32_t*)value;
+    pb_byte_t bytes[4];
+    bytes[0] = (pb_byte_t)(val & 0xFF);
+    bytes[1] = (pb_byte_t)((val >> 8) & 0xFF);
+    bytes[2] = (pb_byte_t)((val >> 16) & 0xFF);
+    bytes[3] = (pb_byte_t)((val >> 24) & 0xFF);
+    return pb_write(stream, bytes, 4);
+#endif
+}
+
+#ifndef PB_WITHOUT_64BIT
+bool checkreturn pb_encode_fixed64(pb_ostream_t *stream, const void *value)
+{
+#if defined(PB_LITTLE_ENDIAN_8BIT) && PB_LITTLE_ENDIAN_8BIT == 1
+    /* Fast path if we know that we're on little endian */
+    return pb_write(stream, (const pb_byte_t*)value, 8);
+#else
+    uint64_t val = *(const uint64_t*)value;
+    pb_byte_t bytes[8];
+    bytes[0] = (pb_byte_t)(val & 0xFF);
+    bytes[1] = (pb_byte_t)((val >> 8) & 0xFF);
+    bytes[2] = (pb_byte_t)((val >> 16) & 0xFF);
+    bytes[3] = (pb_byte_t)((val >> 24) & 0xFF);
+    bytes[4] = (pb_byte_t)((val >> 32) & 0xFF);
+    bytes[5] = (pb_byte_t)((val >> 40) & 0xFF);
+    bytes[6] = (pb_byte_t)((val >> 48) & 0xFF);
+    bytes[7] = (pb_byte_t)((val >> 56) & 0xFF);
+    return pb_write(stream, bytes, 8);
+#endif
+}
+#endif
+
+bool checkreturn pb_encode_tag(pb_ostream_t *stream, pb_wire_type_t wiretype, uint32_t field_number)
+{
+    pb_uint64_t tag = ((pb_uint64_t)field_number << 3) | wiretype;
+    return pb_encode_varint(stream, tag);
+}
+
+bool pb_encode_tag_for_field ( pb_ostream_t* stream, const pb_field_iter_t* field )
+{
+    pb_wire_type_t wiretype;
+    switch (PB_LTYPE(field->type))
+    {
+        case PB_LTYPE_BOOL:
+        case PB_LTYPE_VARINT:
+        case PB_LTYPE_UVARINT:
+        case PB_LTYPE_SVARINT:
+            wiretype = PB_WT_VARINT;
+            break;
+        
+        case PB_LTYPE_FIXED32:
+            wiretype = PB_WT_32BIT;
+            break;
+        
+        case PB_LTYPE_FIXED64:
+            wiretype = PB_WT_64BIT;
+            break;
+        
+        case PB_LTYPE_BYTES:
+        case PB_LTYPE_STRING:
+        case PB_LTYPE_SUBMESSAGE:
+        case PB_LTYPE_SUBMSG_W_CB:
+        case PB_LTYPE_FIXED_LENGTH_BYTES:
+            wiretype = PB_WT_STRING;
+            break;
+        
+        default:
+            PB_RETURN_ERROR(stream, "invalid field type");
+    }
+    
+    return pb_encode_tag(stream, wiretype, field->tag);
+}
+
+bool checkreturn pb_encode_string(pb_ostream_t *stream, const pb_byte_t *buffer, size_t size)
+{
+    if (!pb_encode_varint(stream, (pb_uint64_t)size))
+        return false;
+    
+    return pb_write(stream, buffer, size);
+}
+
+bool checkreturn pb_encode_submessage(pb_ostream_t *stream, const pb_msgdesc_t *fields, const void *src_struct)
+{
+    /* First calculate the message size using a non-writing substream. */
+    pb_ostream_t substream = PB_OSTREAM_SIZING;
+    size_t size;
+    bool status;
+    
+    if (!pb_encode(&substream, fields, src_struct))
+    {
+#ifndef PB_NO_ERRMSG
+        stream->errmsg = substream.errmsg;
+#endif
+        return false;
+    }
+    
+    size = substream.bytes_written;
+    
+    if (!pb_encode_varint(stream, (pb_uint64_t)size))
+        return false;
+    
+    if (stream->callback == NULL)
+        return pb_write(stream, NULL, size); /* Just sizing */
+    
+    if (stream->bytes_written + size > stream->max_size)
+        PB_RETURN_ERROR(stream, "stream full");
+        
+    /* Use a substream to verify that a callback doesn't write more than
+     * what it did the first time. */
+    substream.callback = stream->callback;
+    substream.state = stream->state;
+    substream.max_size = size;
+    substream.bytes_written = 0;
+#ifndef PB_NO_ERRMSG
+    substream.errmsg = NULL;
+#endif
+    
+    status = pb_encode(&substream, fields, src_struct);
+    
+    stream->bytes_written += substream.bytes_written;
+    stream->state = substream.state;
+#ifndef PB_NO_ERRMSG
+    stream->errmsg = substream.errmsg;
+#endif
+    
+    if (substream.bytes_written != size)
+        PB_RETURN_ERROR(stream, "submsg size changed");
+    
+    return status;
+}
+
+/* Field encoders */
+
+static bool checkreturn pb_enc_bool(pb_ostream_t *stream, const pb_field_iter_t *field)
+{
+    uint32_t value = safe_read_bool(field->pData) ? 1 : 0;
+    PB_UNUSED(field);
+    return pb_encode_varint(stream, value);
+}
+
+static bool checkreturn pb_enc_varint(pb_ostream_t *stream, const pb_field_iter_t *field)
+{
+    if (PB_LTYPE(field->type) == PB_LTYPE_UVARINT)
+    {
+        /* Perform unsigned integer extension */
+        pb_uint64_t value = 0;
+
+        if (field->data_size == sizeof(uint_least8_t))
+            value = *(const uint_least8_t*)field->pData;
+        else if (field->data_size == sizeof(uint_least16_t))
+            value = *(const uint_least16_t*)field->pData;
+        else if (field->data_size == sizeof(uint32_t))
+            value = *(const uint32_t*)field->pData;
+        else if (field->data_size == sizeof(pb_uint64_t))
+            value = *(const pb_uint64_t*)field->pData;
+        else
+            PB_RETURN_ERROR(stream, "invalid data_size");
+
+        return pb_encode_varint(stream, value);
+    }
+    else
+    {
+        /* Perform signed integer extension */
+        pb_int64_t value = 0;
+
+        if (field->data_size == sizeof(int_least8_t))
+            value = *(const int_least8_t*)field->pData;
+        else if (field->data_size == sizeof(int_least16_t))
+            value = *(const int_least16_t*)field->pData;
+        else if (field->data_size == sizeof(int32_t))
+            value = *(const int32_t*)field->pData;
+        else if (field->data_size == sizeof(pb_int64_t))
+            value = *(const pb_int64_t*)field->pData;
+        else
+            PB_RETURN_ERROR(stream, "invalid data_size");
+
+        if (PB_LTYPE(field->type) == PB_LTYPE_SVARINT)
+            return pb_encode_svarint(stream, value);
+#ifdef PB_WITHOUT_64BIT
+        else if (value < 0)
+            return pb_encode_varint_32(stream, (uint32_t)value, (uint32_t)-1);
+#endif
+        else
+            return pb_encode_varint(stream, (pb_uint64_t)value);
+
+    }
+}
+
+static bool checkreturn pb_enc_fixed(pb_ostream_t *stream, const pb_field_iter_t *field)
+{
+#ifdef PB_CONVERT_DOUBLE_FLOAT
+    if (field->data_size == sizeof(float) && PB_LTYPE(field->type) == PB_LTYPE_FIXED64)
+    {
+        return pb_encode_float_as_double(stream, *(float*)field->pData);
+    }
+#endif
+
+    if (field->data_size == sizeof(uint32_t))
+    {
+        return pb_encode_fixed32(stream, field->pData);
+    }
+#ifndef PB_WITHOUT_64BIT
+    else if (field->data_size == sizeof(uint64_t))
+    {
+        return pb_encode_fixed64(stream, field->pData);
+    }
+#endif
+    else
+    {
+        PB_RETURN_ERROR(stream, "invalid data_size");
+    }
+}
+
+static bool checkreturn pb_enc_bytes(pb_ostream_t *stream, const pb_field_iter_t *field)
+{
+    const pb_bytes_array_t *bytes = NULL;
+
+    bytes = (const pb_bytes_array_t*)field->pData;
+    
+    if (bytes == NULL)
+    {
+        /* Treat null pointer as an empty bytes field */
+        return pb_encode_string(stream, NULL, 0);
+    }
+    
+    if (PB_ATYPE(field->type) == PB_ATYPE_STATIC &&
+        bytes->size > field->data_size - offsetof(pb_bytes_array_t, bytes))
+    {
+        PB_RETURN_ERROR(stream, "bytes size exceeded");
+    }
+    
+    return pb_encode_string(stream, bytes->bytes, (size_t)bytes->size);
+}
+
+static bool checkreturn pb_enc_string(pb_ostream_t *stream, const pb_field_iter_t *field)
+{
+    size_t size = 0;
+    size_t max_size = (size_t)field->data_size;
+    const char *str = (const char*)field->pData;
+    
+    if (PB_ATYPE(field->type) == PB_ATYPE_POINTER)
+    {
+        max_size = (size_t)-1;
+    }
+    else
+    {
+        /* pb_dec_string() assumes string fields end with a null
+         * terminator when the type isn't PB_ATYPE_POINTER, so we
+         * shouldn't allow more than max-1 bytes to be written to
+         * allow space for the null terminator.
+         */
+        if (max_size == 0)
+            PB_RETURN_ERROR(stream, "zero-length string");
+
+        max_size -= 1;
+    }
+
+
+    if (str == NULL)
+    {
+        size = 0; /* Treat null pointer as an empty string */
+    }
+    else
+    {
+        const char *p = str;
+
+        /* strnlen() is not always available, so just use a loop */
+        while (size < max_size && *p != '\0')
+        {
+            size++;
+            p++;
+        }
+
+        if (*p != '\0')
+        {
+            PB_RETURN_ERROR(stream, "unterminated string");
+        }
+    }
+
+#ifdef PB_VALIDATE_UTF8
+    if (!pb_validate_utf8(str))
+        PB_RETURN_ERROR(stream, "invalid utf8");
+#endif
+
+    return pb_encode_string(stream, (const pb_byte_t*)str, size);
+}
+
+static bool checkreturn pb_enc_submessage(pb_ostream_t *stream, const pb_field_iter_t *field)
+{
+    if (field->submsg_desc == NULL)
+        PB_RETURN_ERROR(stream, "invalid field descriptor");
+
+    if (PB_LTYPE(field->type) == PB_LTYPE_SUBMSG_W_CB && field->pSize != NULL)
+    {
+        /* Message callback is stored right before pSize. */
+        pb_callback_t *callback = (pb_callback_t*)field->pSize - 1;
+        if (callback->funcs.encode)
+        {
+            if (!callback->funcs.encode(stream, field, &callback->arg))
+                return false;
+        }
+    }
+    
+    return pb_encode_submessage(stream, field->submsg_desc, field->pData);
+}
+
+static bool checkreturn pb_enc_fixed_length_bytes(pb_ostream_t *stream, const pb_field_iter_t *field)
+{
+    return pb_encode_string(stream, (const pb_byte_t*)field->pData, (size_t)field->data_size);
+}
+
+#ifdef PB_CONVERT_DOUBLE_FLOAT
+bool pb_encode_float_as_double(pb_ostream_t *stream, float value)
+{
+    union { float f; uint32_t i; } in;
+    uint_least8_t sign;
+    int exponent;
+    uint64_t mantissa;
+
+    in.f = value;
+
+    /* Decompose input value */
+    sign = (uint_least8_t)((in.i >> 31) & 1);
+    exponent = (int)((in.i >> 23) & 0xFF) - 127;
+    mantissa = in.i & 0x7FFFFF;
+
+    if (exponent == 128)
+    {
+        /* Special value (NaN etc.) */
+        exponent = 1024;
+    }
+    else if (exponent == -127)
+    {
+        if (!mantissa)
+        {
+            /* Zero */
+            exponent = -1023;
+        }
+        else
+        {
+            /* Denormalized */
+            mantissa <<= 1;
+            while (!(mantissa & 0x800000))
+            {
+                mantissa <<= 1;
+                exponent--;
+            }
+            mantissa &= 0x7FFFFF;
+        }
+    }
+
+    /* Combine fields */
+    mantissa <<= 29;
+    mantissa |= (uint64_t)(exponent + 1023) << 52;
+    mantissa |= (uint64_t)sign << 63;
+
+    return pb_encode_fixed64(stream, &mantissa);
+}
+#endif

+ 185 - 0
components/spotify/cspot/bell/nanopb/pb_encode.h

@@ -0,0 +1,185 @@
+/* pb_encode.h: Functions to encode protocol buffers. Depends on pb_encode.c.
+ * The main function is pb_encode. You also need an output stream, and the
+ * field descriptions created by nanopb_generator.py.
+ */
+
+#ifndef PB_ENCODE_H_INCLUDED
+#define PB_ENCODE_H_INCLUDED
+
+#include "pb.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Structure for defining custom output streams. You will need to provide
+ * a callback function to write the bytes to your storage, which can be
+ * for example a file or a network socket.
+ *
+ * The callback must conform to these rules:
+ *
+ * 1) Return false on IO errors. This will cause encoding to abort.
+ * 2) You can use state to store your own data (e.g. buffer pointer).
+ * 3) pb_write will update bytes_written after your callback runs.
+ * 4) Substreams will modify max_size and bytes_written. Don't use them
+ *    to calculate any pointers.
+ */
+struct pb_ostream_s
+{
+#ifdef PB_BUFFER_ONLY
+    /* Callback pointer is not used in buffer-only configuration.
+     * Having an int pointer here allows binary compatibility but
+     * gives an error if someone tries to assign callback function.
+     * Also, NULL pointer marks a 'sizing stream' that does not
+     * write anything.
+     */
+    const int *callback;
+#else
+    bool (*callback)(pb_ostream_t *stream, const pb_byte_t *buf, size_t count);
+#endif
+    void *state;          /* Free field for use by callback implementation. */
+    size_t max_size;      /* Limit number of output bytes written (or use SIZE_MAX). */
+    size_t bytes_written; /* Number of bytes written so far. */
+    
+#ifndef PB_NO_ERRMSG
+    const char *errmsg;
+#endif
+};
+
+/***************************
+ * Main encoding functions *
+ ***************************/
+
+/* Encode a single protocol buffers message from C structure into a stream.
+ * Returns true on success, false on any failure.
+ * The actual struct pointed to by src_struct must match the description in fields.
+ * All required fields in the struct are assumed to have been filled in.
+ *
+ * Example usage:
+ *    MyMessage msg = {};
+ *    uint8_t buffer[64];
+ *    pb_ostream_t stream;
+ *
+ *    msg.field1 = 42;
+ *    stream = pb_ostream_from_buffer(buffer, sizeof(buffer));
+ *    pb_encode(&stream, MyMessage_fields, &msg);
+ */
+bool pb_encode(pb_ostream_t *stream, const pb_msgdesc_t *fields, const void *src_struct);
+
+/* Extended version of pb_encode, with several options to control the
+ * encoding process:
+ *
+ * PB_ENCODE_DELIMITED:      Prepend the length of message as a varint.
+ *                           Corresponds to writeDelimitedTo() in Google's
+ *                           protobuf API.
+ *
+ * PB_ENCODE_NULLTERMINATED: Append a null byte to the message for termination.
+ *                           NOTE: This behaviour is not supported in most other
+ *                           protobuf implementations, so PB_ENCODE_DELIMITED
+ *                           is a better option for compatibility.
+ */
+#define PB_ENCODE_DELIMITED       0x02U
+#define PB_ENCODE_NULLTERMINATED  0x04U
+bool pb_encode_ex(pb_ostream_t *stream, const pb_msgdesc_t *fields, const void *src_struct, unsigned int flags);
+
+/* Defines for backwards compatibility with code written before nanopb-0.4.0 */
+#define pb_encode_delimited(s,f,d) pb_encode_ex(s,f,d, PB_ENCODE_DELIMITED)
+#define pb_encode_nullterminated(s,f,d) pb_encode_ex(s,f,d, PB_ENCODE_NULLTERMINATED)
+
+/* Encode the message to get the size of the encoded data, but do not store
+ * the data. */
+bool pb_get_encoded_size(size_t *size, const pb_msgdesc_t *fields, const void *src_struct);
+
+/**************************************
+ * Functions for manipulating streams *
+ **************************************/
+
+/* Create an output stream for writing into a memory buffer.
+ * The number of bytes written can be found in stream.bytes_written after
+ * encoding the message.
+ *
+ * Alternatively, you can use a custom stream that writes directly to e.g.
+ * a file or a network socket.
+ */
+pb_ostream_t pb_ostream_from_buffer(pb_byte_t *buf, size_t bufsize);
+
+/* Pseudo-stream for measuring the size of a message without actually storing
+ * the encoded data.
+ * 
+ * Example usage:
+ *    MyMessage msg = {};
+ *    pb_ostream_t stream = PB_OSTREAM_SIZING;
+ *    pb_encode(&stream, MyMessage_fields, &msg);
+ *    printf("Message size is %d\n", stream.bytes_written);
+ */
+#ifndef PB_NO_ERRMSG
+#define PB_OSTREAM_SIZING {0,0,0,0,0}
+#else
+#define PB_OSTREAM_SIZING {0,0,0,0}
+#endif
+
+/* Function to write into a pb_ostream_t stream. You can use this if you need
+ * to append or prepend some custom headers to the message.
+ */
+bool pb_write(pb_ostream_t *stream, const pb_byte_t *buf, size_t count);
+
+
+/************************************************
+ * Helper functions for writing field callbacks *
+ ************************************************/
+
+/* Encode field header based on type and field number defined in the field
+ * structure. Call this from the callback before writing out field contents. */
+bool pb_encode_tag_for_field(pb_ostream_t *stream, const pb_field_iter_t *field);
+
+/* Encode field header by manually specifying wire type. You need to use this
+ * if you want to write out packed arrays from a callback field. */
+bool pb_encode_tag(pb_ostream_t *stream, pb_wire_type_t wiretype, uint32_t field_number);
+
+/* Encode an integer in the varint format.
+ * This works for bool, enum, int32, int64, uint32 and uint64 field types. */
+#ifndef PB_WITHOUT_64BIT
+bool pb_encode_varint(pb_ostream_t *stream, uint64_t value);
+#else
+bool pb_encode_varint(pb_ostream_t *stream, uint32_t value);
+#endif
+
+/* Encode an integer in the zig-zagged svarint format.
+ * This works for sint32 and sint64. */
+#ifndef PB_WITHOUT_64BIT
+bool pb_encode_svarint(pb_ostream_t *stream, int64_t value);
+#else
+bool pb_encode_svarint(pb_ostream_t *stream, int32_t value);
+#endif
+
+/* Encode a string or bytes type field. For strings, pass strlen(s) as size. */
+bool pb_encode_string(pb_ostream_t *stream, const pb_byte_t *buffer, size_t size);
+
+/* Encode a fixed32, sfixed32 or float value.
+ * You need to pass a pointer to a 4-byte wide C variable. */
+bool pb_encode_fixed32(pb_ostream_t *stream, const void *value);
+
+#ifndef PB_WITHOUT_64BIT
+/* Encode a fixed64, sfixed64 or double value.
+ * You need to pass a pointer to a 8-byte wide C variable. */
+bool pb_encode_fixed64(pb_ostream_t *stream, const void *value);
+#endif
+
+#ifdef PB_CONVERT_DOUBLE_FLOAT
+/* Encode a float value so that it appears like a double in the encoded
+ * message. */
+bool pb_encode_float_as_double(pb_ostream_t *stream, float value);
+#endif
+
+/* Encode a submessage field.
+ * You need to pass the pb_field_t array and pointer to struct, just like
+ * with pb_encode(). This internally encodes the submessage twice, first to
+ * calculate message size and then to actually write it out.
+ */
+bool pb_encode_submessage(pb_ostream_t *stream, const pb_msgdesc_t *fields, const void *src_struct);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif

+ 3 - 0
components/spotify/cspot/bell/nanopb/spm-test/objc/c-header.c

@@ -0,0 +1,3 @@
+#include "pb.h"
+#include "pb_common.h"
+#include "pb_decode.h"

+ 3 - 0
components/spotify/cspot/bell/nanopb/spm-test/objc/objc-header.m

@@ -0,0 +1,3 @@
+#import "pb.h"
+#import <pb_common.h>
+#include "pb_decode.h"

+ 1 - 0
components/spotify/cspot/bell/nanopb/spm-test/objc/objc-module.m

@@ -0,0 +1 @@
+@import nanopb;

+ 3 - 0
components/spotify/cspot/bell/nanopb/spm-test/objc/objc-qualified.m

@@ -0,0 +1,3 @@
+#import "nanopb/pb.h"
+#import <nanopb/pb_common.h>
+#include "nanopb/pb_decode.h"

+ 1 - 0
components/spotify/cspot/bell/nanopb/spm-test/swift/main.swift

@@ -0,0 +1 @@
+import nanopb

+ 1 - 0
components/spotify/cspot/bell/nanopb/spm_headers/nanopb/pb.h

@@ -0,0 +1 @@
+../../pb.h

+ 1 - 0
components/spotify/cspot/bell/nanopb/spm_headers/nanopb/pb_common.h

@@ -0,0 +1 @@
+../../pb_common.h

+ 1 - 0
components/spotify/cspot/bell/nanopb/spm_headers/nanopb/pb_decode.h

@@ -0,0 +1 @@
+../../pb_decode.h

+ 1 - 0
components/spotify/cspot/bell/nanopb/spm_headers/nanopb/pb_encode.h

@@ -0,0 +1 @@
+../../pb_encode.h

+ 1 - 0
components/spotify/cspot/bell/nanopb/spm_headers/pb.h

@@ -0,0 +1 @@
+#include "nanopb/pb.h"

+ 1 - 0
components/spotify/cspot/bell/nanopb/spm_headers/pb_common.h

@@ -0,0 +1 @@
+#include "nanopb/pb_common.h"

Some files were not shown because too many files changed in this diff