LCOV - code coverage report
Current view: top level - spb - pb.hpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 100.0 % 43 43
Test Date: 2026-05-30 19:41:37 Functions: 99.9 % 1939 1937

            Line data    Source code
       1              : /***************************************************************************\
       2              : * Name        : Public API for protobuf                                     *
       3              : * Description : all protobuf serialize and deserialize functions            *
       4              : * Author      : antonin.kriz@gmail.com                                      *
       5              : * ------------------------------------------------------------------------- *
       6              : * This is free software; you can redistribute it and/or modify it under the *
       7              : * terms of the MIT license. A copy of the license can be found in the file  *
       8              : * "LICENSE" at the root of this distribution.                               *
       9              : \***************************************************************************/
      10              : #pragma once
      11              : 
      12              : #include "concepts.h"
      13              : #include "pb/deserialize.hpp"
      14              : #include "pb/serialize.hpp"
      15              : #include "spb/io/io.hpp"
      16              : #include <cstdlib>
      17              : 
      18              : namespace spb::pb
      19              : {
      20              : 
      21              : struct serialize_options
      22              : {
      23              :     /**
      24              :      * @brief Writes the size of the message (as a varint) before the message itself.
      25              :      *        Compatible with Google's `writeDelimitedTo` and NanoPb's PB_ENCODE_DELIMITED.
      26              :      */
      27              :     bool delimited = false;
      28              : };
      29              : 
      30              : struct deserialize_options
      31              : {
      32              :     /**
      33              :      * @brief Expect the size of the message (encoded as a varint) to come before the message
      34              :      * itself. Compatible with Google's `parseDelimitedFrom` and NanoPb's PB_DECODE_DELIMITED. Will
      35              :      * return after having read the specified length; the spb::io::reader object can then be read
      36              :      * from again to get the next message (if any).
      37              :      */
      38              :     bool delimited = false;
      39              : };
      40              : 
      41              : /**
      42              :  * @brief serialize message via writer
      43              :  *
      44              :  * @param[in] message to be serialized
      45              :  * @param[in] on_write function for handling the writes
      46              :  * @param[in] options
      47              :  * @return serialized size in bytes
      48              :  * @throws exceptions only from `on_write`
      49              :  */
      50         1948 : static inline auto serialize(const auto &message, spb::io::writer on_write,
      51              :                              const serialize_options &options = {}) -> size_t
      52              : {
      53         1948 :     auto stream = detail::ostream{on_write};
      54         1948 :     if (options.delimited)
      55            4 :         detail::serialize_varint(stream, detail::serialize_size(message));
      56              : 
      57         1948 :     serialize(stream, message);
      58         3764 :     return stream.size();
      59              : }
      60              : 
      61              : /**
      62              :  * @brief return protobuf serialized size in bytes
      63              :  *
      64              :  * @param[in] message to be serialized
      65              :  * @param[in] options
      66              :  * @return serialized size in bytes
      67              :  */
      68         1192 : [[nodiscard]] static inline auto serialize_size(const auto &message, const serialize_options &options = {})
      69              :     -> size_t
      70              : {
      71         1192 :     return serialize(message, spb::io::writer(nullptr), options);
      72              : }
      73              : 
      74              : /**
      75              :  * @brief serialize message into protobuf
      76              :  *
      77              :  * @param[in] message to be serialized
      78              :  * @param[in] options
      79              :  * @param[out] result serialized protobuf
      80              :  * @return serialized size in bytes
      81              :  * @throws std::runtime_error on error
      82              :  * @example `auto serialized = std::vector< std::byte >();`
      83              :  *          `spb::pb::serialize( message, serialized );`
      84              :  */
      85              : template <typename Message, spb::resizable_container Container>
      86          822 : static inline auto serialize(const Message &message, Container &result, const serialize_options &options = {})
      87              :     -> size_t
      88              : {
      89          822 :     const auto size = serialize_size(message, options);
      90          756 :     result.resize(size);
      91         2848 :     auto writer = [ptr = result.data()](const void *data, size_t size) mutable
      92              :     {
      93         2092 :         memcpy(ptr, data, size);
      94         2092 :         ptr += size;
      95              :     };
      96              : 
      97          756 :     serialize(message, writer, options);
      98          756 :     return size;
      99              : }
     100              : 
     101              : /**
     102              :  * @brief serialize message into protobuf
     103              :  *
     104              :  * @param[in] message to be serialized
     105              :  * @param[in] options
     106              :  * @return serialized protobuf
     107              :  * @throws std::runtime_error on error
     108              :  * @example `auto serialized_message = spb::pb::serialize< std::vector< std::byte > >( message );`
     109              :  */
     110              : template <spb::resizable_container Container = std::string, typename Message>
     111          822 : [[nodiscard]] static inline auto serialize(const Message &message, const serialize_options &options = {})
     112              :     -> Container
     113              : {
     114          822 :     auto result = Container();
     115          822 :     serialize<Message, Container>(message, result, options);
     116          756 :     return result;
     117           66 : }
     118              : 
     119              : /**
     120              :  * @brief deserialize message from protobuf
     121              :  *
     122              :  * @param[in] reader function for handling reads
     123              :  * @param[in] options
     124              :  * @param[out] message deserialized message
     125              :  * @throws std::runtime_error on error
     126              :  */
     127         1180 : static inline void deserialize(auto &message, spb::io::reader reader, const deserialize_options &options = {})
     128              : {
     129         1180 :     detail::istream stream{reader};
     130         1180 :     if (!options.delimited)
     131         1178 :         return deserialize_main(stream, message);
     132              : 
     133            2 :     const auto substream_length = read_varint<uint32_t>(stream);
     134            2 :     auto substream = stream.sub_stream(substream_length);
     135            2 :     return deserialize_main(substream, message);
     136              : }
     137              : 
     138              : /**
     139              :  * @brief deserialize message from protobuf
     140              :  *
     141              :  * @param[in] protobuf string with protobuf
     142              :  * @param[in] options
     143              :  * @param[out] message deserialized message
     144              :  * @throws std::runtime_error on error
     145              :  * @example `auto serialized = std::vector< std::byte >( ... );`
     146              :  *          `auto message = Message();`
     147              :  *          `spb::pb::deserialize( message, serialized );`
     148              :  */
     149              : template <typename Message, spb::size_container Container>
     150         1180 : static inline void deserialize(Message &message, const Container &protobuf,
     151              :                                const deserialize_options &options = {})
     152              : {
     153         1180 :     auto ptr = protobuf.data();
     154         1180 :     const auto end = protobuf.data() + protobuf.size();
     155              : 
     156         5840 :     auto reader = [ptr, end](void *data, size_t size) mutable -> size_t
     157              :     {
     158         4660 :         const size_t bytes_left = end - ptr;
     159              : 
     160         4660 :         size = std::min(size, bytes_left);
     161         4660 :         memcpy(data, ptr, size);
     162         4660 :         ptr += size;
     163         4660 :         return size;
     164              :     };
     165         1997 :     return deserialize(message, reader, options);
     166              : }
     167              : 
     168              : /**
     169              :  * @brief deserialize message from protobuf
     170              :  *
     171              :  * @param[in] protobuf serialized protobuf
     172              :  * @param[in] options
     173              :  * @return deserialized message
     174              :  * @throws std::runtime_error on error
     175              :  * @example `auto serialized = std::vector< std::byte >( ... );`
     176              :  *          `auto message = spb::pb::deserialize< Message >( serialized );`
     177              :  */
     178              : template <typename Message, spb::size_container Container>
     179          810 : [[nodiscard]] static inline auto deserialize(const Container &protobuf,
     180              :                                              const deserialize_options &options = {}) -> Message
     181              : {
     182          776 :     auto message = Message{};
     183          810 :     deserialize(message, protobuf, options);
     184          450 :     return message;
     185          128 : }
     186              : 
     187              : /**
     188              :  * @brief deserialize message from reader
     189              :  *
     190              :  * @param[in] reader function for handling reads
     191              :  * @param[in] options
     192              :  * @return deserialized message
     193              :  * @throws std::runtime_error on error
     194              :  */
     195              : template <typename Message>
     196              : [[nodiscard]] static inline auto deserialize(spb::io::reader reader, const deserialize_options &options = {})
     197              :     -> Message
     198              : {
     199              :     auto message = Message{};
     200              :     deserialize(message, reader, options);
     201              :     return message;
     202              : }
     203              : 
     204              : } // namespace spb::pb
        

Generated by: LCOV version 2.0-1