Преглед изворни кода

Merged in develop (pull request #20)

Release 1.1.0
Bart Hertog пре 5 година
родитељ
комит
32ca9279be
47 измењених фајлова са 2268 додато и 640 уклоњено
  1. 31 1
      CMakeLists.txt
  2. 3 4
      bitbucket-pipelines-dependencies.sh
  3. 5 3
      bitbucket-pipelines.yml
  4. 3 1
      build_test.sh
  5. 27 14
      code_coverage.sh
  6. 84 36
      generator/Header_Template.h
  7. 26 12
      generator/protoc-gen-eams.py
  8. 1 1
      protoc-gen-eams
  9. 1 1
      protoc-gen-eams.bat
  10. 39 0
      setup.sh
  11. 3 3
      sonar-project.properties
  12. 49 0
      src/Errors.h
  13. 265 0
      src/FieldStringBytes.h
  14. 120 54
      src/Fields.cpp
  15. 52 43
      src/Fields.h
  16. 16 9
      src/MessageInterface.cpp
  17. 6 4
      src/MessageInterface.h
  18. 6 8
      src/MessageSizeCalculator.h
  19. 5 2
      src/ReadBufferInterface.h
  20. 10 6
      src/ReadBufferSection.cpp
  21. 4 3
      src/ReadBufferSection.h
  22. 103 147
      src/RepeatedField.h
  23. 154 0
      src/RepeatedFieldFixedSize.h
  24. 180 103
      src/WireFormatter.h
  25. 4 1
      src/WriteBufferInterface.h
  26. 3 4
      test/mock/ReadBufferMock.h
  27. 1 1
      test/mock/WriteBufferMock.h
  28. 1 1
      test/proto/file_to_include.proto
  29. 1 1
      test/proto/include_other_files.proto
  30. 1 1
      test/proto/nested_message.proto
  31. 1 1
      test/proto/oneof_fields.proto
  32. 1 1
      test/proto/repeated_fields.proto
  33. 1 1
      test/proto/simple_types.proto
  34. 52 0
      test/proto/string_bytes.proto
  35. 1 1
      test/test_EmbeddedProto.cpp
  36. 40 5
      test/test_IncludeOtherFiles.cpp
  37. 74 0
      test/test_MessageSizeCalculator.cpp
  38. 35 22
      test/test_NestedMessage.cpp
  39. 147 0
      test/test_ReadBufferSection.cpp
  40. 0 87
      test/test_RepeatedField.cpp
  41. 159 0
      test/test_RepeatedFieldFixedSize.cpp
  42. 62 31
      test/test_RepeatedFieldMessage.cpp
  43. 71 11
      test/test_SimpleTypes.cpp
  44. 1 1
      test/test_getters_setters_fields.cpp
  45. 17 13
      test/test_oneof_fields.cpp
  46. 365 0
      test/test_string_bytes.cpp
  47. 37 2
      test_data.py

+ 31 - 1
CMakeLists.txt

@@ -1,3 +1,33 @@
+#
+#  Copyright (C) 2020 Embedded AMS B.V. - All Rights Reserved
+#
+#  This file is part of Embedded Proto.
+#
+#  Embedded Proto is open source software: you can redistribute it and/or 
+#  modify it under the terms of the GNU General Public License as published 
+#  by the Free Software Foundation, version 3 of the license.
+#
+#  Embedded Proto  is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+#  GNU General Public License for more details.
+#
+#  You should have received a copy of the GNU General Public License
+#  along with Embedded Proto. If not, see <https://www.gnu.org/licenses/>.
+#
+#  For commercial and closed source application please visit:
+#  <https://EmbeddedProto.com/license/>.
+#
+#  Embedded AMS B.V.
+#  Info:
+#    info at EmbeddedProto dot com
+#
+#  Postal address:
+#    Johan Huizingalaan 763a
+#    1066 VH, Amsterdam
+#    the Netherlands
+#
+
 cmake_minimum_required(VERSION 3.5)
 
 project(test_EmbeddedProto)
@@ -10,7 +40,7 @@ add_subdirectory(external/googletest)
 file(GLOB src_files
     "src/*.cpp"
     "test/*.cpp"
-    "build/EAMS/*cpp"
+    "build/EAMS/*.cpp"
 )
 
 include_directories(test test/mock src build/EAMS)

+ 3 - 4
bitbucket-pipelines-dependencies.sh

@@ -24,7 +24,7 @@
 # Info:
 #   info at EmbeddedProto dot com
 #
-# Postal adress:
+# Postal address:
 #   Johan Huizingalaan 763a
 #   1066 VH, Amsterdam
 #   the Netherlands
@@ -61,7 +61,6 @@ export PATH="$PATH:$PWD/sonar-scanner/bin"
 if [ -d "$PWD/venv" ]; then
   echo "found python virtualenv in cache"
 else
-  python3 -m venv venv
+  ./setup.sh
 fi
-source venv/bin/activate
-pip install -r requirements.txt
+

+ 5 - 3
bitbucket-pipelines.yml

@@ -1,4 +1,8 @@
 image: atlassian/default-image:2
+
+clone: 
+  depth: full
+
 pipelines:
   default:
     - step:    
@@ -13,8 +17,6 @@ pipelines:
           - source bitbucket-pipelines-dependencies.sh
 
           - ./build_test.sh
-          - ./build/test/test_EmbeddedProto --gtest_output="xml:build/test/test_details.xml"
-
           - ./code_coverage.sh
 
           - cd build/test
@@ -22,7 +24,7 @@ pipelines:
           
           - cd -
           - export SONAR_SCANNER_OPTS="-Xmx1024m"
-          - sonar-scanner -Dproject.settings=sonar-project.properties
+          - sonar-scanner -Dproject.settings=sonar-project.properties -Dsonar.login=$SONAR_LOGIN
                  
 definitions:
   caches:

+ 3 - 1
build_test.sh

@@ -24,7 +24,7 @@
 # Info:
 #   info at EmbeddedProto dot com
 #
-# Postal adress:
+# Postal address:
 #   Johan Huizingalaan 763a
 #   1066 VH, Amsterdam
 #   the Netherlands
@@ -37,6 +37,7 @@ protoc --plugin=protoc-gen-eams=protoc-gen-eams -I./test/proto --eams_out=./buil
 protoc --plugin=protoc-gen-eams=protoc-gen-eams -I./test/proto --eams_out=./build/EAMS ./test/proto/repeated_fields.proto
 protoc --plugin=protoc-gen-eams=protoc-gen-eams -I./test/proto --eams_out=./build/EAMS ./test/proto/oneof_fields.proto
 protoc --plugin=protoc-gen-eams=protoc-gen-eams -I./test/proto --eams_out=./build/EAMS ./test/proto/include_other_files.proto
+protoc --plugin=protoc-gen-eams=protoc-gen-eams -I./test/proto --eams_out=./build/EAMS ./test/proto/string_bytes.proto
 
 # For validation and testing generate the same message using python
 mkdir -p ./build/python
@@ -46,6 +47,7 @@ protoc -I./test/proto --python_out=./build/python ./test/proto/repeated_fields.p
 protoc -I./test/proto --python_out=./build/python ./test/proto/oneof_fields.proto
 protoc -I./test/proto --python_out=./build/python ./test/proto/include_other_files.proto
 protoc -I./test/proto --python_out=./build/python ./test/proto/file_to_include.proto
+protoc -I./test/proto --python_out=./build/python ./test/proto/string_bytes.proto
 
 # Build the tests
 mkdir -p build/test

+ 27 - 14
code_coverage.sh

@@ -1,4 +1,4 @@
-#! /bin/sh
+#! /bin/bash
 
 #
 # Copyright (C) 2020 Embedded AMS B.V. - All Rights Reserved
@@ -24,25 +24,38 @@
 # Info:
 #   info at EmbeddedProto dot com
 #
-# Postal adress:
+# Postal address:
 #   Johan Huizingalaan 763a
 #   1066 VH, Amsterdam
 #   the Netherlands
 #
 
-./build/test/test_EmbeddedProto
+./build/test/test_EmbeddedProto --gtest_output="xml:build/test/test_details.xml"
 
-# rm -rf ./code_coverage_report/*
-# lcov --directory ./build/test --capture --output-file ./code_coverage_report/total_code_coverage.info -rc lcov_branch_coverage=1
-# lcov --remove ./code_coverage_report/total_code_coverage.info $PWD'/external/googletest/*' '/usr/include/*' -o ./code_coverage_report/filtered_code_coverage.info
-# genhtml ./code_coverage_report/filtered_code_coverage.info --branch-coverage --output-directory ./code_coverage_report
 
-rm -rf ./code_coverage_report/*
-mkdir -p code_coverage_report
-cd code_coverage_report
+if [ $# -eq 0 ]; then
+  # No arguments provided, execte the analyisis for sonar qube.
+  rm -rf ./code_coverage_report/*
+  mkdir -p code_coverage_report
+  cd code_coverage_report
 
-# Run gcov on the static source files.
-gcov ../test/*.cpp --object-directory ../build/test/CMakeFiles/test_EmbeddedProto.dir/test/ 
-gcov ../src/*.cpp --object-directory ../build/test/CMakeFiles/test_EmbeddedProto.dir/src/
+  # Run gcov on the static source files.
+  gcov ../test/*.cpp --object-directory ../build/test/CMakeFiles/test_EmbeddedProto.dir/test/ 
+  gcov ../src/*.cpp --object-directory ../build/test/CMakeFiles/test_EmbeddedProto.dir/src/
 
-cd -
+  cd -
+
+else
+# Pass commands
+case "$1" in
+  -l|--local)
+    # Run the code coverage for local machine analysis
+    rm -rf ./code_coverage_report/*
+    lcov --directory ./build/test --capture --output-file ./code_coverage_report/total_code_coverage.info -rc lcov_branch_coverage=1
+    lcov --remove ./code_coverage_report/total_code_coverage.info $PWD'/external/googletest/*' '/usr/include/*' -o ./code_coverage_report/filtered_code_coverage.info
+    genhtml ./code_coverage_report/filtered_code_coverage.info --branch-coverage --output-directory ./code_coverage_report
+    ;;
+  *)
+    ;;
+esac
+fi

+ 84 - 36
generator/Header_Template.h

@@ -24,7 +24,7 @@ void init_{{_oneof.name}}(const id field_id)
   {
     {% for field in _oneof.fields() %}
     case id::{{field.variable_id_name}}:
-      {% if field.of_type_message or field.is_repeated_field%}
+      {% if field.of_type_message or field.is_repeated_field or field.is_string or field.is_bytes %}
       new(&{{field.variable_full_name}}) {{field.type}};
       {{_oneof.which_oneof}} = id::{{field.variable_id_name}};
       {% endif %}
@@ -44,7 +44,7 @@ void clear_{{_oneof.name}}()
   {
     {% for field in _oneof.fields() %}
     case id::{{field.variable_id_name}}:
-      {% if field.of_type_message or field.is_repeated_field%}
+      {% if field.of_type_message or field.is_repeated_field or field.is_string or field.is_bytes%}
       {{field.variable_full_name}}.~{{field.short_type}}();
       {% else %}
       {{field.variable_full_name}}.set(0);
@@ -61,7 +61,35 @@ void clear_{{_oneof.name}}()
 {# ------------------------------------------------------------------------------------------------------------------ #}
 {# #}
 {% macro field_get_set_macro(_field) %}
-{% if _field.is_repeated_field %}
+{% if _field.is_string or _field.is_bytes %}
+inline const {{_field.repeated_type}}& {{_field.name}}() const { return {{_field.variable_full_name}}; }
+{% if _field.which_oneof is defined %}
+inline void clear_{{_field.name}}()
+{
+  if(id::{{_field.variable_id_name}} == {{_field.which_oneof}})
+  {
+    {{_field.which_oneof}} = id::NOT_SET;
+    {{_field.variable_full_name}}.~{{_field.short_type}}();
+  }
+}
+inline {{_field.repeated_type}}& mutable_{{_field.name}}()
+{
+  if(id::{{_field.variable_id_name}} != {{_field.which_oneof}})
+  {
+    init_{{_field.oneof_name}}(id::{{_field.variable_id_name}});
+  }
+  return {{_field.variable_full_name}};
+}
+{% else %}
+inline void clear_{{_field.name}}() { {{_field.variable_full_name}}.clear(); }
+inline {{_field.repeated_type}}& mutable_{{_field.name}}() { return {{_field.variable_full_name}}; }
+{% endif %}
+{% if _field.is_string %}
+inline const char* get_{{_field.name}}() const { return {{_field.variable_full_name}}.get_const(); }
+{% else %}{# is bytes #}
+inline const uint8_t* get_{{_field.name}}() const { return {{_field.variable_full_name}}.get_const(); }
+{% endif %}
+{% elif _field.is_repeated_field %}
 inline const {{_field.type}}& {{_field.name}}(uint32_t index) const { return {{_field.variable_full_name}}[index]; }
 {% if _field.which_oneof is defined %}
 inline void clear_{{_field.name}}()
@@ -201,27 +229,27 @@ inline {{_field.type}}::FIELD_TYPE get_{{_field.name}}() const { return {{_field
 {# ------------------------------------------------------------------------------------------------------------------ #}
 {# #}
 {% macro field_serialize_macro(_field) %}
-{% if _field.is_repeated_field %}
-if(result)
+{% if _field.is_repeated_field or _field.is_string or _field.is_bytes %}
+if(::EmbeddedProto::Error::NO_ERRORS == return_value)
 {
-  result = {{_field.variable_full_name}}.serialize_with_id(static_cast<uint32_t>(id::{{_field.variable_id_name}}), buffer);
+  return_value = {{_field.variable_full_name}}.serialize_with_id(static_cast<uint32_t>(id::{{_field.variable_id_name}}), buffer);
 }
 {% elif _field.of_type_message %}
-if(result)
+if(::EmbeddedProto::Error::NO_ERRORS == return_value)
 {
-  result = {{_field.variable_full_name}}.serialize_with_id(static_cast<uint32_t>(id::{{_field.variable_id_name}}), buffer);
+  return_value = {{_field.variable_full_name}}.serialize_with_id(static_cast<uint32_t>(id::{{_field.variable_id_name}}), buffer);
 }
 {% elif _field.of_type_enum %}
-if(({{_field.default_value}} != {{_field.variable_full_name}}) && result)
+if(({{_field.default_value}} != {{_field.variable_full_name}}) && (::EmbeddedProto::Error::NO_ERRORS == return_value))
 {
   EmbeddedProto::uint32 value;
   value.set(static_cast<uint32_t>({{_field.variable_full_name}}));
-  result = value.serialize_with_id(static_cast<uint32_t>(id::{{_field.variable_id_name}}), buffer);
+  return_value = value.serialize_with_id(static_cast<uint32_t>(id::{{_field.variable_id_name}}), buffer);
 }
 {% else %}
-if(({{_field.default_value}} != {{_field.variable_full_name}}.get()) && result)
+if(({{_field.default_value}} != {{_field.variable_full_name}}.get()) && (::EmbeddedProto::Error::NO_ERRORS == return_value))
 {
-  result = {{_field.variable_full_name}}.serialize_with_id(static_cast<uint32_t>(id::{{_field.variable_id_name}}), buffer);
+  return_value = {{_field.variable_full_name}}.serialize_with_id(static_cast<uint32_t>(id::{{_field.variable_id_name}}), buffer);
 } {% endif %} {% endmacro %}
 {# #}
 {# ------------------------------------------------------------------------------------------------------------------ #}
@@ -230,31 +258,33 @@ if(({{_field.default_value}} != {{_field.variable_full_name}}.get()) && result)
 {% if _field.is_repeated_field %}
 if(::EmbeddedProto::WireFormatter::WireType::LENGTH_DELIMITED == wire_type)
 {
-  result = {{_field.variable_full_name}}.deserialize(buffer);
+  return_value = {{_field.variable_full_name}}.deserialize(buffer);
 }
 {% else %}
 if(::EmbeddedProto::WireFormatter::WireType::{{_field.wire_type}} == wire_type)
 {
   {% if _field.of_type_message %}
   uint32_t size;
-  result = ::EmbeddedProto::WireFormatter::DeserializeVarint(buffer, size);
+  return_value = ::EmbeddedProto::WireFormatter::DeserializeVarint(buffer, size);
   ::EmbeddedProto::ReadBufferSection bufferSection(buffer, size);
-  {% if _field.oneof_name is defined %}
-  init_{{_field.oneof_name}}(id::{{_field.variable_id_name}});
-  {% endif %}
-  result = result && {{_field.variable_full_name}}.deserialize(bufferSection);
+  if(::EmbeddedProto::Error::NO_ERRORS == return_value)
+  {
+    return_value = mutable_{{_field.name}}().deserialize(bufferSection);
+  }
+  {% elif _field.is_string or _field.is_bytes %}
+  return_value = mutable_{{_field.name}}().deserialize(buffer);
   {% elif _field.of_type_enum %}
   uint32_t value;
-  result = ::EmbeddedProto::WireFormatter::DeserializeVarint(buffer, value);
-  if(result)
+  return_value = ::EmbeddedProto::WireFormatter::DeserializeVarint(buffer, value);
+  if(::EmbeddedProto::Error::NO_ERRORS == return_value)
   {
     set_{{_field.name}}(static_cast<{{_field.type}}>(value));
   }
   {% else %}
-  result = {{_field.variable_full_name}}.deserialize(buffer);
+  return_value = {{_field.variable_full_name}}.deserialize(buffer);
   {% endif %}
-   {% if _field.which_oneof is defined %}
-  if(result)
+  {% if _field.which_oneof is defined %}
+  if(::EmbeddedProto::Error::NO_ERRORS == return_value)
   {
     {{_field.which_oneof}} = id::{{_field.variable_id_name}};
   }
@@ -263,8 +293,8 @@ if(::EmbeddedProto::WireFormatter::WireType::{{_field.wire_type}} == wire_type)
 {% endif %}
 else
 {
-  // TODO Error wire type does not match field.
-  result = false;
+  // Wire type does not match field.
+  return_value = ::EmbeddedProto::Error::INVALID_WIRETYPE;
 } {% endmacro %}
 {# #}
 {# ------------------------------------------------------------------------------------------------------------------ #}
@@ -316,9 +346,9 @@ class {{ msg.name }} final: public ::EmbeddedProto::MessageInterface
     {{ field_get_set_macro(field)|indent(4) }}
     {% endfor %}
     {% endfor %}
-    bool serialize(::EmbeddedProto::WriteBufferInterface& buffer) const final
+    ::EmbeddedProto::Error serialize(::EmbeddedProto::WriteBufferInterface& buffer) const final
     {
-      bool result = true;
+      ::EmbeddedProto::Error return_value = ::EmbeddedProto::Error::NO_ERRORS;
 
       {% for field in msg.fields() %}
       {{ field_serialize_macro(field)|indent(6) }}
@@ -338,16 +368,17 @@ class {{ msg.name }} final: public ::EmbeddedProto::MessageInterface
       }
 
       {% endfor %}
-      return result;
+      return return_value;
     };
 
-    bool deserialize(::EmbeddedProto::ReadBufferInterface& buffer) final
+    ::EmbeddedProto::Error deserialize(::EmbeddedProto::ReadBufferInterface& buffer) final
     {
-      bool result = true;
+      ::EmbeddedProto::Error return_value = ::EmbeddedProto::Error::NO_ERRORS;
       ::EmbeddedProto::WireFormatter::WireType wire_type;
       uint32_t id_number = 0;
 
-      while(result && ::EmbeddedProto::WireFormatter::DeserializeTag(buffer, wire_type, id_number))
+      ::EmbeddedProto::Error tag_value = ::EmbeddedProto::WireFormatter::DeserializeTag(buffer, wire_type, id_number);
+      while((::EmbeddedProto::Error::NO_ERRORS == return_value) && (::EmbeddedProto::Error::NO_ERRORS == tag_value))
       {
         switch(id_number)
         {
@@ -372,8 +403,23 @@ class {{ msg.name }} final: public ::EmbeddedProto::MessageInterface
           default:
             break;
         }
+        
+        if(::EmbeddedProto::Error::NO_ERRORS == return_value)
+        {
+            // Read the next tag.
+            tag_value = ::EmbeddedProto::WireFormatter::DeserializeTag(buffer, wire_type, id_number);
+        }
       }
-      return result;
+
+      // When an error was detect while reading the tag but no other errors where found, set it in the return value.
+      if((::EmbeddedProto::Error::NO_ERRORS == return_value)
+         && (::EmbeddedProto::Error::NO_ERRORS != tag_value)
+         && (::EmbeddedProto::Error::END_OF_BUFFER != tag_value)) // The end of the buffer is not an array in this case.
+      {
+        return_value = tag_value;
+      }
+
+      return return_value;
     };
 
     void clear() final
@@ -389,7 +435,7 @@ class {{ msg.name }} final: public ::EmbeddedProto::MessageInterface
   private:
 
     {% for field in msg.fields() %}
-    {% if field.is_repeated_field %}
+    {% if field.is_repeated_field or field.is_string or field.is_bytes %}
     {{field.repeated_type}} {{field.variable_name}};
     {% else %}
     {{field.type}} {{field.variable_name}};
@@ -403,7 +449,7 @@ class {{ msg.name }} final: public ::EmbeddedProto::MessageInterface
       {{oneof.name}}() {}
       ~{{oneof.name}}() {}
       {% for field in oneof.fields() %}
-      {% if field.is_repeated_field %}
+      {% if field.is_repeated_field or field.is_string or field.is_bytes %}
       {{field.repeated_type}} {{field.variable_name}};
       {% else %}
       {{field.type}} {{field.variable_name}};
@@ -444,7 +490,7 @@ class {{ msg.name }} final: public ::EmbeddedProto::MessageInterface
  *  Info:
  *    info at EmbeddedProto dot com
  *
- *  Postal adress:
+ *  Postal address:
  *    Johan Huizingalaan 763a
  *    1066 VH, Amsterdam
  *    the Netherlands
@@ -461,7 +507,9 @@ class {{ msg.name }} final: public ::EmbeddedProto::MessageInterface
 #include <Fields.h>
 #include <MessageSizeCalculator.h>
 #include <ReadBufferSection.h>
-#include <RepeatedField.h>
+#include <RepeatedFieldFixedSize.h>
+#include <FieldStringBytes.h>
+#include <Errors.h>
 {% endif %}
 {% if dependencies %}
 

+ 26 - 12
generator/protoc-gen-eams.py

@@ -22,7 +22,7 @@
 # Info:
 #   info at EmbeddedProto dot com
 #
-# Postal adress:
+# Postal address:
 #   Johan Huizingalaan 763a
 #   1066 VH, Amsterdam
 #   the Netherlands
@@ -66,9 +66,9 @@ class FieldTemplateParameters:
                              FieldDescriptorProto.TYPE_FIXED64:  "0U",
                              FieldDescriptorProto.TYPE_FIXED32:  "0U",
                              FieldDescriptorProto.TYPE_BOOL:     "false",
-                             FieldDescriptorProto.TYPE_STRING:   "TODO",    # TODO
+                             FieldDescriptorProto.TYPE_STRING:   "''",
                              FieldDescriptorProto.TYPE_MESSAGE:  "",
-                             FieldDescriptorProto.TYPE_BYTES:    "TODO",    # TODO
+                             FieldDescriptorProto.TYPE_BYTES:    "0U",
                              FieldDescriptorProto.TYPE_UINT32:   "0U",
                              FieldDescriptorProto.TYPE_ENUM:     "0",
                              FieldDescriptorProto.TYPE_SFIXED32: "0",
@@ -84,8 +84,8 @@ class FieldTemplateParameters:
                         FieldDescriptorProto.TYPE_FIXED64:  "EmbeddedProto::fixed64",
                         FieldDescriptorProto.TYPE_FIXED32:  "EmbeddedProto::fixed32",
                         FieldDescriptorProto.TYPE_BOOL:     "EmbeddedProto::boolean",
-                        FieldDescriptorProto.TYPE_STRING:   "TODO",     # TODO
-                        FieldDescriptorProto.TYPE_BYTES:    "TODO",     # TODO
+                        FieldDescriptorProto.TYPE_STRING:   "char",
+                        FieldDescriptorProto.TYPE_BYTES:    "uint8_t",
                         FieldDescriptorProto.TYPE_UINT32:   "EmbeddedProto::uint32",
                         FieldDescriptorProto.TYPE_SFIXED32: "EmbeddedProto::sfixed32",
                         FieldDescriptorProto.TYPE_SFIXED64: "EmbeddedProto::sfixed64",
@@ -127,17 +127,25 @@ class FieldTemplateParameters:
         self.of_type_message = FieldDescriptorProto.TYPE_MESSAGE == field_proto.type
         self.wire_type = self.type_to_wire_type[field_proto.type]
 
-        if FieldDescriptorProto.TYPE_MESSAGE == field_proto.type or FieldDescriptorProto.TYPE_ENUM == field_proto.type:
+        self.of_type_enum = FieldDescriptorProto.TYPE_ENUM == field_proto.type
+        self.is_repeated_field = FieldDescriptorProto.LABEL_REPEATED == field_proto.label
+        self.is_string = FieldDescriptorProto.TYPE_STRING == field_proto.type
+        self.is_bytes = FieldDescriptorProto.TYPE_BYTES == field_proto.type
+
+        if FieldDescriptorProto.TYPE_MESSAGE == field_proto.type or self.of_type_enum:
             self.type = field_proto.type_name if "." != field_proto.type_name[0] else field_proto.type_name[1:]
             self.type = self.type.replace(".", "::")
             # Store only the type without namespace or class scopes
             self.short_type = self.type.split("::")[-1]
+        elif self.is_string:
+            self.type = "::EmbeddedProto::FieldString"
+            self.short_type = "FieldString"
+        elif self.is_bytes:
+            self.type = "::EmbeddedProto::FieldBytes"
+            self.short_type = "FieldBytes"
         else:
             self.type = self.type_to_cpp_type[field_proto.type]
 
-        self.of_type_enum = FieldDescriptorProto.TYPE_ENUM == field_proto.type
-        self.is_repeated_field = field_proto.label == FieldDescriptorProto.LABEL_REPEATED
-
         self.default_value = None
         self.repeated_type = None
         self.templates = []
@@ -167,9 +175,15 @@ class FieldTemplateParameters:
             self.default_value = self.type_to_default_value[self.field_proto.type]
 
         if self.is_repeated_field:
-            self.repeated_type = "::EmbeddedProto::RepeatedFieldSize<" + self.type + ", " + self.variable_name \
-                                 + "SIZE>"
-            self.templates.append({"type": "uint32_t", "name": self.variable_name + "SIZE"})
+            self.repeated_type = "::EmbeddedProto::RepeatedFieldFixedSize<" + self.type + ", " + self.variable_name \
+                                 + "LENGTH>"
+
+        if self. is_string or self.is_bytes:
+            self.repeated_type = self.type + "<" + self.variable_name + "LENGTH>"
+            self.type = self.repeated_type
+
+        if self.is_repeated_field or self.is_string or self.is_bytes:
+            self.templates.append({"type": "uint32_t", "name": self.variable_name + "LENGTH"})
 
 
 # -----------------------------------------------------------------------------

+ 1 - 1
protoc-gen-eams

@@ -24,7 +24,7 @@
 # Info:
 #   info at EmbeddedProto dot com
 #
-# Postal adress:
+# Postal address:
 #   Johan Huizingalaan 763a
 #   1066 VH, Amsterdam
 #   the Netherlands

+ 1 - 1
protoc-gen-eams.bat

@@ -24,7 +24,7 @@
 :: Info:
 ::   info at EmbeddedProto dot com
 ::
-:: Postal adress:
+:: Postal address:
 ::   Johan Huizingalaan 763a
 ::   1066 VH, Amsterdam
 ::   the Netherlands

+ 39 - 0
setup.sh

@@ -0,0 +1,39 @@
+#! /bin/bash
+
+#
+# Copyright (C) 2020 Embedded AMS B.V. - All Rights Reserved
+#
+# This file is part of Embedded Proto.
+#
+# Embedded Proto is open source software: you can redistribute it and/or 
+# modify it under the terms of the GNU General Public License as published 
+# by the Free Software Foundation, version 3 of the license.
+#
+# Embedded Proto  is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Embedded Proto. If not, see <https://www.gnu.org/licenses/>.
+#
+# For commercial and closed source application please visit:
+# <https://EmbeddedProto.com/license/>.
+#
+# Embedded AMS B.V.
+# Info:
+#   info at EmbeddedProto dot com
+#
+# Postal address:
+#   Johan Huizingalaan 763a
+#   1066 VH, Amsterdam
+#   the Netherlands
+#
+
+# This script will setup the environment to generate source code in your project.
+
+# Setup the virtual envirounment for Python packages
+python3 -m venv venv
+source ./venv/bin/activate
+pip install -r requirements.txt
+

+ 3 - 3
sonar-project.properties

@@ -22,7 +22,7 @@
 # Info:
 #   info at EmbeddedProto dot com
 #
-# Postal adress:
+# Postal address:
 #   Johan Huizingalaan 763a
 #   1066 VH, Amsterdam
 #   the Netherlands
@@ -36,8 +36,6 @@ sonar.host.url=https://sonarcloud.io
 sonar.projectName=EmbeddedProto
 sonar.projectVersion=1.0
 sonar.organization=embeddedams
-# sonar authentication key
-sonar.login=492dba2b1a7da82eaea36308ce177f6033626bca
 
 # sonar-bitbucket-plugin
 sonar.bitbucket.minSeverity=INFO
@@ -58,3 +56,5 @@ sonar.sourceEncoding=UTF-8
 sonar.cfamily.build-wrapper-output=build/test/SonarQube-output
 sonar.cfamily.xunit.reportsPath=build/test/
 sonar.cfamily.gcov.reportsPath=code_coverage_report/
+sonar.cfamily.threads=1
+sonar.cfamily.cache.enabled=false

+ 49 - 0
src/Errors.h

@@ -0,0 +1,49 @@
+/*
+ *  Copyright (C) 2020 Embedded AMS B.V. - All Rights Reserved
+ *
+ *  This file is part of Embedded Proto.
+ *
+ *  Embedded Proto is open source software: you can redistribute it and/or 
+ *  modify it under the terms of the GNU General Public License as published 
+ *  by the Free Software Foundation, version 3 of the license.
+ *
+ *  Embedded Proto  is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Embedded Proto. If not, see <https://www.gnu.org/licenses/>.
+ *
+ *  For commercial and closed source application please visit:
+ *  <https://EmbeddedProto.com/license/>.
+ *
+ *  Embedded AMS B.V.
+ *  Info:
+ *    info at EmbeddedProto dot com
+ *
+ *  Postal address:
+ *    Johan Huizingalaan 763a
+ *    1066 VH, Amsterdam
+ *    the Netherlands
+ */
+
+#ifndef _ERRORS_H_
+#define _ERRORS_H_
+
+namespace EmbeddedProto 
+{
+
+  //! This enumeration defines errors which can occur during serialization and deserialization. 
+  enum class Error
+  {
+    NO_ERRORS        = 0, //!< No errors have occurred.
+    END_OF_BUFFER    = 1, //!< While trying to read from the buffer we ran out of bytes tor read.
+    BUFFER_FULL      = 2, //!< The write buffer is full, unable to push more bytes in to it.
+    INVALID_WIRETYPE = 3, //!< When reading a Wiretype from the tag we got an invalid value.
+    ARRAY_FULL       = 4, //!< The array is full, it is not possible to push more items in it.
+  };
+
+}; // End of namespace EmbeddedProto
+
+#endif // End of _ERRORS_H_

+ 265 - 0
src/FieldStringBytes.h

@@ -0,0 +1,265 @@
+/*
+ *  Copyright (C) 2020 Embedded AMS B.V. - All Rights Reserved
+ *
+ *  This file is part of Embedded Proto.
+ *
+ *  Embedded Proto is open source software: you can redistribute it and/or 
+ *  modify it under the terms of the GNU General Public License as published 
+ *  by the Free Software Foundation, version 3 of the license.
+ *
+ *  Embedded Proto  is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Embedded Proto. If not, see <https://www.gnu.org/licenses/>.
+ *
+ *  For commercial and closed source application please visit:
+ *  <https://EmbeddedProto.com/license/>.
+ *
+ *  Embedded AMS B.V.
+ *  Info:
+ *    info at EmbeddedProto dot com
+ *
+ *  Postal address:
+ *    Johan Huizingalaan 763a
+ *    1066 VH, Amsterdam
+ *    the Netherlands
+ */
+
+#ifndef _FIELD_STRING_BYTES_H_
+#define _FIELD_STRING_BYTES_H_
+
+#include "Fields.h"
+#include "Errors.h"
+
+#include <cstdint>
+#include <string.h>
+#include <type_traits>
+
+
+namespace EmbeddedProto
+{
+
+  namespace internal
+  {
+
+    template<uint32_t MAX_LENGTH, class DATA_TYPE>
+    class FieldStringBytes : public Field
+    {
+      static_assert(std::is_same<uint8_t, DATA_TYPE>::value || std::is_same<char, DATA_TYPE>::value, 
+                    "This class only supports unit8_t or chars.");
+
+      public:
+
+        FieldStringBytes()
+          : current_length_(0),
+            data_{0}
+        {
+
+        }
+
+        virtual ~FieldStringBytes()
+        {
+          clear();
+        }
+
+        //! Obtain the number of characters in the string right now.
+        uint32_t get_length() const { return current_length_; }
+
+        //! Obtain the maximum number characters in the string.
+        uint32_t get_max_length() const { return MAX_LENGTH; }
+
+        //! Get a constant pointer to the first element in the array.
+        const DATA_TYPE* get_const() const { return data_; }
+
+        //! Get a reference to the value at the given index. 
+        /*!
+          This function will update the number of elements used in the array/string.
+
+          \param[in] index The desired index to return.
+          \return The reference to the value at the given index. Will return the last element if the 
+                  index is out of bounds
+        */
+        DATA_TYPE& get(uint32_t index) 
+        { 
+          uint32_t limited_index = std::min(index, MAX_LENGTH-1);
+          // Check if we need to update the number of elements in the array.
+          if(limited_index >= current_length_) {
+            current_length_ = limited_index + 1;
+          }
+          return data_[limited_index]; 
+        }
+
+        //! Get a constant reference to the value at the given index. 
+        /*!
+          \param[in] index The desired index to return.
+          \return The reference to the value at the given index. Will return the last element if the 
+                  index is out of bounds
+        */
+        const DATA_TYPE& get_const(uint32_t index) const 
+        { 
+          uint32_t limited_index = std::min(index, MAX_LENGTH-1);
+          return data_[limited_index]; 
+        }
+
+        //! Get a reference to the value at the given index. 
+        /*!
+          This function will update the number of elements used in the array/string.
+
+          \param[in] index The desired index to return.
+          \return The reference to the value at the given index. Will return the last element if the 
+                  index is out of bounds
+        */
+        DATA_TYPE& operator[](uint32_t index) { return this->get(index); }
+
+        //! Get a constant reference to the value at the given index. 
+        /*!
+          \param[in] index The desired index to return.
+          \return The reference to the value at the given index. Will return the last element if the 
+                  index is out of bounds
+        */
+        const DATA_TYPE& operator[](uint32_t index) const { return this->get_const(index); }
+
+
+        Error set(const DATA_TYPE* data, const uint32_t length)
+        {
+          Error return_value = Error::NO_ERRORS;
+          if(MAX_LENGTH >= length)
+          {
+            current_length_ = length;
+            memcpy(data_, data, length);
+          }
+          else
+          {
+            return_value = Error::ARRAY_FULL;
+          }
+          return return_value;
+        }
+
+
+        Error serialize_with_id(uint32_t field_number, WriteBufferInterface& buffer) const override 
+        {
+          Error return_value = Error::NO_ERRORS;
+
+          if(0 < current_length_) 
+          {
+            if(current_length_ <= buffer.get_available_size())
+            {
+              uint32_t tag = WireFormatter::MakeTag(field_number, 
+                                                    WireFormatter::WireType::LENGTH_DELIMITED);
+              return_value = WireFormatter::SerializeVarint(tag, buffer);
+              if(Error::NO_ERRORS == return_value) 
+              {
+                return_value = serialize(buffer);
+              }
+            }
+            else 
+            {
+              return_value = Error::BUFFER_FULL;
+            }
+          }
+
+          return return_value;
+        }
+
+        Error serialize(WriteBufferInterface& buffer) const override 
+        { 
+          Error return_value = WireFormatter::SerializeVarint(current_length_, buffer);
+          if(Error::NO_ERRORS == return_value) 
+          {
+            const void* void_pointer = static_cast<const void*>(&(data_[0]));
+            const uint8_t* byte_pointer = static_cast<const uint8_t*>(void_pointer);
+            if(!buffer.push(byte_pointer, current_length_))
+            {
+              return_value = Error::BUFFER_FULL;
+            }
+          }
+          return return_value;
+        }
+
+        Error deserialize(ReadBufferInterface& buffer) override 
+        {
+          uint32_t availiable;
+          Error return_value = WireFormatter::DeserializeVarint(buffer, availiable);
+          if(Error::NO_ERRORS == return_value)
+          {
+            if(MAX_LENGTH >= availiable) 
+            {
+              clear();
+
+              uint8_t byte;
+              while((current_length_ < availiable) && buffer.pop(byte)) 
+              {
+                data_[current_length_] = static_cast<DATA_TYPE>(byte);
+                ++current_length_;
+              }
+
+              if(current_length_ != availiable)
+              {
+                // If at the end we did not read the same number of characters something went wrong.
+                return_value = Error::END_OF_BUFFER;
+              }
+            }
+            else 
+            {
+              return_value = Error::ARRAY_FULL;
+            }
+          }
+
+          return return_value;
+        }
+
+        //! Reset the field to it's initial value.
+        void clear() override 
+        { 
+          memset(data_, 0, current_length_);
+          current_length_ = 0; 
+        }
+    
+      protected:
+
+        //! Number of item in the data array.
+        uint32_t current_length_;
+
+        //! The text.
+        DATA_TYPE data_[MAX_LENGTH];
+
+    }; // End of class FieldStringBytes
+
+  } // End of namespace internal
+
+  template<uint32_t MAX_LENGTH>
+  class FieldString : public internal::FieldStringBytes<MAX_LENGTH, char>
+  {
+    public:
+      FieldString() = default;
+      virtual ~FieldString() = default;
+
+      void operator=(const char* const &&rhs)
+      {
+        const uint32_t rhs_MAX_LENGTH = strlen(rhs);
+        this->current_length_ = std::min(rhs_MAX_LENGTH, MAX_LENGTH);
+        strncpy(this->data_, rhs, this->current_length_);
+
+        // Make sure the string is null terminated.
+        if(MAX_LENGTH > this->current_length_)
+        {
+          this->data_[this->current_length_] = 0;
+        }
+      }
+  };
+
+  template<uint32_t MAX_LENGTH>
+  class FieldBytes : public internal::FieldStringBytes<MAX_LENGTH, uint8_t>
+  {
+    public:
+      FieldBytes() = default;
+      virtual ~FieldBytes() = default; 
+  };
+
+
+} // End of namespace EmbeddedProto
+
+#endif // End of _FIELD_STRING_BYTES_H_

+ 120 - 54
src/Fields.cpp

@@ -22,7 +22,7 @@
  *  Info:
  *    info at EmbeddedProto dot com
  *
- *  Postal adress:
+ *  Postal address:
  *    Johan Huizingalaan 763a
  *    1066 VH, Amsterdam
  *    the Netherlands
@@ -40,201 +40,267 @@ namespace EmbeddedProto
     return calcBuffer.get_size();
   }
 
-  bool int32::serialize_with_id(uint32_t field_number, WriteBufferInterface& buffer) const
+  Error int32::serialize_with_id(uint32_t field_number, WriteBufferInterface& buffer) const
   { 
-    return WireFormatter::SerializeVarint(WireFormatter::MakeTag(field_number, WireFormatter::WireType::VARINT), buffer) && serialize(buffer);
+    Error return_value = WireFormatter::SerializeVarint(WireFormatter::MakeTag(field_number, WireFormatter::WireType::VARINT), buffer);
+    if(Error::NO_ERRORS == return_value)
+    {
+      return_value = serialize(buffer);
+    }
+    return return_value;
   }
 
-  bool int64::serialize_with_id(uint32_t field_number, WriteBufferInterface& buffer) const
+  Error int64::serialize_with_id(uint32_t field_number, WriteBufferInterface& buffer) const
   { 
-    return WireFormatter::SerializeVarint(WireFormatter::MakeTag(field_number, WireFormatter::WireType::VARINT), buffer) && serialize(buffer);
+    Error return_value = WireFormatter::SerializeVarint(WireFormatter::MakeTag(field_number, WireFormatter::WireType::VARINT), buffer);
+    if(Error::NO_ERRORS == return_value)
+    {
+      return_value = serialize(buffer);
+    }
+    return return_value;
   }
 
-  bool uint32::serialize_with_id(uint32_t field_number, WriteBufferInterface& buffer) const
+  Error uint32::serialize_with_id(uint32_t field_number, WriteBufferInterface& buffer) const
   { 
-    return WireFormatter::SerializeVarint(WireFormatter::MakeTag(field_number, WireFormatter::WireType::VARINT), buffer) && serialize(buffer);
+    Error return_value = WireFormatter::SerializeVarint(WireFormatter::MakeTag(field_number, WireFormatter::WireType::VARINT), buffer);
+    if(Error::NO_ERRORS == return_value)
+    {
+      return_value = serialize(buffer);
+    }
+    return return_value;
   }
 
-  bool uint64::serialize_with_id(uint32_t field_number, WriteBufferInterface& buffer) const
+  Error uint64::serialize_with_id(uint32_t field_number, WriteBufferInterface& buffer) const
   { 
-    return WireFormatter::SerializeVarint(WireFormatter::MakeTag(field_number, WireFormatter::WireType::VARINT), buffer) && serialize(buffer);
+    Error return_value = WireFormatter::SerializeVarint(WireFormatter::MakeTag(field_number, WireFormatter::WireType::VARINT), buffer);
+    if(Error::NO_ERRORS == return_value)
+    {
+      return_value = serialize(buffer);
+    }
+    return return_value;
   }
 
-  bool sint32::serialize_with_id(uint32_t field_number, WriteBufferInterface& buffer) const
+  Error sint32::serialize_with_id(uint32_t field_number, WriteBufferInterface& buffer) const
   { 
-    return WireFormatter::SerializeVarint(WireFormatter::MakeTag(field_number, WireFormatter::WireType::VARINT), buffer) && serialize(buffer);
+    Error return_value = WireFormatter::SerializeVarint(WireFormatter::MakeTag(field_number, WireFormatter::WireType::VARINT), buffer);
+    if(Error::NO_ERRORS == return_value)
+    {
+      return_value = serialize(buffer);
+    }
+    return return_value;
   }
 
-  bool sint64::serialize_with_id(uint32_t field_number, WriteBufferInterface& buffer) const
+  Error sint64::serialize_with_id(uint32_t field_number, WriteBufferInterface& buffer) const
   { 
-    return WireFormatter::SerializeVarint(WireFormatter::MakeTag(field_number, WireFormatter::WireType::VARINT), buffer) && serialize(buffer);
+    Error return_value = WireFormatter::SerializeVarint(WireFormatter::MakeTag(field_number, WireFormatter::WireType::VARINT), buffer);
+    if(Error::NO_ERRORS == return_value)
+    {
+      return_value = serialize(buffer);
+    }
+    return return_value;
   }
 
-  bool boolean::serialize_with_id(uint32_t field_number, WriteBufferInterface& buffer) const
+  Error boolean::serialize_with_id(uint32_t field_number, WriteBufferInterface& buffer) const
   { 
-    return WireFormatter::SerializeVarint(WireFormatter::MakeTag(field_number, WireFormatter::WireType::VARINT), buffer) && serialize(buffer);
+    Error return_value = WireFormatter::SerializeVarint(WireFormatter::MakeTag(field_number, WireFormatter::WireType::VARINT), buffer);
+    if(Error::NO_ERRORS == return_value)
+    {
+      return_value = serialize(buffer);
+    }
+    return return_value;
   }
 
-  bool fixed32::serialize_with_id(uint32_t field_number, WriteBufferInterface& buffer) const
+  Error fixed32::serialize_with_id(uint32_t field_number, WriteBufferInterface& buffer) const
   { 
-    return WireFormatter::SerializeVarint(WireFormatter::MakeTag(field_number, WireFormatter::WireType::FIXED32), buffer) && serialize(buffer);
+    Error return_value = WireFormatter::SerializeVarint(WireFormatter::MakeTag(field_number, WireFormatter::WireType::FIXED32), buffer);
+    if(Error::NO_ERRORS == return_value)
+    {
+      return_value = serialize(buffer);
+    }
+    return return_value;
   }
 
-  bool fixed64::serialize_with_id(uint32_t field_number, WriteBufferInterface& buffer) const
+  Error fixed64::serialize_with_id(uint32_t field_number, WriteBufferInterface& buffer) const
   { 
-    return WireFormatter::SerializeVarint(WireFormatter::MakeTag(field_number, WireFormatter::WireType::FIXED64), buffer) && serialize(buffer);
+    Error return_value = WireFormatter::SerializeVarint(WireFormatter::MakeTag(field_number, WireFormatter::WireType::FIXED64), buffer);
+    if(Error::NO_ERRORS == return_value)
+    {
+      return_value = serialize(buffer);
+    }
+    return return_value;
   }
 
-  bool sfixed32::serialize_with_id(uint32_t field_number, WriteBufferInterface& buffer) const
+  Error sfixed32::serialize_with_id(uint32_t field_number, WriteBufferInterface& buffer) const
   { 
-    return WireFormatter::SerializeVarint(WireFormatter::MakeTag(field_number, WireFormatter::WireType::FIXED32), buffer) && serialize(buffer);
+    Error return_value = WireFormatter::SerializeVarint(WireFormatter::MakeTag(field_number, WireFormatter::WireType::FIXED32), buffer);
+    if(Error::NO_ERRORS == return_value)
+    {
+      return_value = serialize(buffer);
+    }
+    return return_value;
   }
 
-  bool sfixed64::serialize_with_id(uint32_t field_number, WriteBufferInterface& buffer) const
+  Error sfixed64::serialize_with_id(uint32_t field_number, WriteBufferInterface& buffer) const
   { 
-    return WireFormatter::SerializeVarint(WireFormatter::MakeTag(field_number, WireFormatter::WireType::FIXED64), buffer) && serialize(buffer);
+    Error return_value = WireFormatter::SerializeVarint(WireFormatter::MakeTag(field_number, WireFormatter::WireType::FIXED64), buffer);
+    if(Error::NO_ERRORS == return_value)
+    {
+      return_value = serialize(buffer);
+    }
+    return return_value;
   }
 
-  bool floatfixed::serialize_with_id(uint32_t field_number, WriteBufferInterface& buffer) const
+  Error floatfixed::serialize_with_id(uint32_t field_number, WriteBufferInterface& buffer) const
   { 
-    return WireFormatter::SerializeVarint(WireFormatter::MakeTag(field_number, WireFormatter::WireType::FIXED32), buffer) && serialize(buffer);
+    Error return_value = WireFormatter::SerializeVarint(WireFormatter::MakeTag(field_number, WireFormatter::WireType::FIXED32), buffer);
+    if(Error::NO_ERRORS == return_value)
+    {
+      return_value = serialize(buffer);
+    }
+    return return_value;
   }
 
-  bool doublefixed::serialize_with_id(uint32_t field_number, WriteBufferInterface& buffer) const
+  Error doublefixed::serialize_with_id(uint32_t field_number, WriteBufferInterface& buffer) const
   { 
-    return WireFormatter::SerializeVarint(WireFormatter::MakeTag(field_number, WireFormatter::WireType::FIXED64), buffer) && serialize(buffer);
+    Error return_value = WireFormatter::SerializeVarint(WireFormatter::MakeTag(field_number, WireFormatter::WireType::FIXED64), buffer);
+    if(Error::NO_ERRORS == return_value)
+    {
+      return_value = serialize(buffer);
+    }
+    return return_value;
   }
 
 
 
-  bool int32::serialize(WriteBufferInterface& buffer) const
+  Error int32::serialize(WriteBufferInterface& buffer) const
   {
     return WireFormatter::SerializeVarint(static_cast<uint32_t>(get()), buffer);
   }
 
-  bool int64::serialize(WriteBufferInterface& buffer) const
+  Error int64::serialize(WriteBufferInterface& buffer) const
   {
     return WireFormatter::SerializeVarint(static_cast<uint64_t>(get()), buffer);
   }
 
-  bool uint32::serialize(WriteBufferInterface& buffer) const
+  Error uint32::serialize(WriteBufferInterface& buffer) const
   {
     return WireFormatter::SerializeVarint(get(), buffer);
   }
 
-  bool uint64::serialize(WriteBufferInterface& buffer) const
+  Error uint64::serialize(WriteBufferInterface& buffer) const
   {
     return WireFormatter::SerializeVarint(get(), buffer);
   }
 
-  bool sint32::serialize(WriteBufferInterface& buffer) const
+  Error sint32::serialize(WriteBufferInterface& buffer) const
   {
     return WireFormatter::SerializeVarint(WireFormatter::ZigZagEncode(get()), buffer);
   }
 
-  bool sint64::serialize(WriteBufferInterface& buffer) const
+  Error sint64::serialize(WriteBufferInterface& buffer) const
   {
     return WireFormatter::SerializeVarint(WireFormatter::ZigZagEncode(get()), buffer);
   }
 
-  bool boolean::serialize(WriteBufferInterface& buffer) const
+  Error boolean::serialize(WriteBufferInterface& buffer) const
   {
-    return buffer.push(get() ? 0x01 : 0x00);
+    const uint8_t byte = get() ? 0x01 : 0x00;
+    return buffer.push(byte) ? Error::NO_ERRORS : Error::BUFFER_FULL;
   }
 
-  bool fixed32::serialize(WriteBufferInterface& buffer) const
+  Error fixed32::serialize(WriteBufferInterface& buffer) const
   {
     return WireFormatter::SerialzieFixedNoTag(get(), buffer);
   }
 
-  bool fixed64::serialize(WriteBufferInterface& buffer) const
+  Error fixed64::serialize(WriteBufferInterface& buffer) const
   {
     return WireFormatter::SerialzieFixedNoTag(get(), buffer);
   }
 
-  bool sfixed32::serialize(WriteBufferInterface& buffer) const
+  Error sfixed32::serialize(WriteBufferInterface& buffer) const
   {
     return WireFormatter::SerialzieSFixedNoTag(get(), buffer);
   }
 
-  bool sfixed64::serialize(WriteBufferInterface& buffer) const
+  Error sfixed64::serialize(WriteBufferInterface& buffer) const
   {
     return WireFormatter::SerialzieSFixedNoTag(get(), buffer);
   }
 
-  bool floatfixed::serialize(WriteBufferInterface& buffer) const
+  Error floatfixed::serialize(WriteBufferInterface& buffer) const
   {
     return WireFormatter::SerialzieFloatNoTag(get(), buffer);
   }
 
-  bool doublefixed::serialize(WriteBufferInterface& buffer) const
+  Error doublefixed::serialize(WriteBufferInterface& buffer) const
   {
     return WireFormatter::SerialzieDoubleNoTag(get(), buffer);
   }
 
 
 
-  bool int32::deserialize(ReadBufferInterface& buffer) 
+  Error int32::deserialize(ReadBufferInterface& buffer) 
   { 
     return WireFormatter::DeserializeInt(buffer, get());
   }
 
-  bool int64::deserialize(ReadBufferInterface& buffer) 
+  Error int64::deserialize(ReadBufferInterface& buffer) 
   { 
     return WireFormatter::DeserializeInt(buffer, get());
   }
 
-  bool uint32::deserialize(ReadBufferInterface& buffer) 
+  Error uint32::deserialize(ReadBufferInterface& buffer) 
   { 
     return WireFormatter::DeserializeUInt(buffer, get());
   }
 
-  bool uint64::deserialize(ReadBufferInterface& buffer) 
+  Error uint64::deserialize(ReadBufferInterface& buffer) 
   { 
     return WireFormatter::DeserializeUInt(buffer, get());
   }
 
-  bool sint32::deserialize(ReadBufferInterface& buffer) 
+  Error sint32::deserialize(ReadBufferInterface& buffer) 
   { 
     return WireFormatter::DeserializeSInt(buffer, get());
   }
 
-  bool sint64::deserialize(ReadBufferInterface& buffer) 
+  Error sint64::deserialize(ReadBufferInterface& buffer) 
   { 
     return WireFormatter::DeserializeSInt(buffer, get());
   }
 
-  bool boolean::deserialize(ReadBufferInterface& buffer) 
+  Error boolean::deserialize(ReadBufferInterface& buffer) 
   { 
     return WireFormatter::DeserializeBool(buffer, get());
   }
 
-  bool fixed32::deserialize(ReadBufferInterface& buffer) 
+  Error fixed32::deserialize(ReadBufferInterface& buffer) 
   { 
     return WireFormatter::DeserializeFixed(buffer, get());
   }
 
-  bool fixed64::deserialize(ReadBufferInterface& buffer) 
+  Error fixed64::deserialize(ReadBufferInterface& buffer) 
   { 
     return WireFormatter::DeserializeFixed(buffer, get());
   }
 
-  bool sfixed32::deserialize(ReadBufferInterface& buffer) 
+  Error sfixed32::deserialize(ReadBufferInterface& buffer) 
   { 
     return WireFormatter::DeserializeSFixed(buffer, get());
   }
 
-  bool sfixed64::deserialize(ReadBufferInterface& buffer) 
+  Error sfixed64::deserialize(ReadBufferInterface& buffer) 
   { 
     return WireFormatter::DeserializeSFixed(buffer, get());
   }
 
-  bool floatfixed::deserialize(ReadBufferInterface& buffer) 
+  Error floatfixed::deserialize(ReadBufferInterface& buffer) 
   { 
     return WireFormatter::DeserializeFloat(buffer, get());
   }
 
-  bool doublefixed::deserialize(ReadBufferInterface& buffer) 
+  Error doublefixed::deserialize(ReadBufferInterface& buffer) 
   { 
     return WireFormatter::DeserializeDouble(buffer, get());
   }

+ 52 - 43
src/Fields.h

@@ -22,7 +22,7 @@
  *  Info:
  *    info at EmbeddedProto dot com
  *
- *  Postal adress:
+ *  Postal address:
  *    Johan Huizingalaan 763a
  *    1066 VH, Amsterdam
  *    the Netherlands
@@ -31,10 +31,14 @@
 #ifndef _FIELDS_H_
 #define _FIELDS_H_
 
+#include "Errors.h"
 #include "WireFormatter.h"
 #include "WriteBufferInterface.h"
 #include "ReadBufferInterface.h"
 
+#include <cstdint>
+
+
 namespace EmbeddedProto 
 {
 
@@ -44,17 +48,20 @@ namespace EmbeddedProto
       Field() = default;
       virtual ~Field() = default;
 
-      virtual bool serialize_with_id(uint32_t field_number, WriteBufferInterface& buffer) const = 0;
+      virtual Error serialize_with_id(uint32_t field_number, WriteBufferInterface& buffer) const = 0;
 
-      virtual bool serialize(WriteBufferInterface& buffer) const = 0;
+      virtual Error serialize(WriteBufferInterface& buffer) const = 0;
 
-      virtual bool deserialize(ReadBufferInterface& buffer) = 0;
+      virtual Error deserialize(ReadBufferInterface& buffer) = 0;
 
       //! Calculate the size of this message when serialized.
       /*!
           \return The number of bytes this message will require once serialized.
       */
       uint32_t serialized_size() const;
+
+      //! Reset the field to it's initial value.
+      virtual void clear() = 0;
   };
 
   template<class TYPE>
@@ -98,6 +105,8 @@ namespace EmbeddedProto
       template<class TYPE_RHS>
       bool operator<=(const FieldTemplate<TYPE_RHS>& rhs) { return value_ <= rhs.get(); }
 
+      void clear() override { value_ = static_cast<TYPE>(0); }
+
     private:
 
       TYPE value_;
@@ -113,9 +122,9 @@ namespace EmbeddedProto
 
       ~int32() override = default;
 
-      bool serialize_with_id(uint32_t field_number, WriteBufferInterface& buffer) const final;
-      bool serialize(WriteBufferInterface& buffer) const final;
-      bool deserialize(ReadBufferInterface& buffer) final; 
+      Error serialize_with_id(uint32_t field_number, WriteBufferInterface& buffer) const final;
+      Error serialize(WriteBufferInterface& buffer) const final;
+      Error deserialize(ReadBufferInterface& buffer) final; 
   };
 
   class int64 : public FieldTemplate<int64_t> 
@@ -127,9 +136,9 @@ namespace EmbeddedProto
 
       ~int64() override = default;
       
-      bool serialize_with_id(uint32_t field_number, WriteBufferInterface& buffer) const final;
-      bool serialize(WriteBufferInterface& buffer) const final;
-      bool deserialize(ReadBufferInterface& buffer) final; 
+      Error serialize_with_id(uint32_t field_number, WriteBufferInterface& buffer) const final;
+      Error serialize(WriteBufferInterface& buffer) const final;
+      Error deserialize(ReadBufferInterface& buffer) final; 
   };
 
   class uint32 : public FieldTemplate<uint32_t> 
@@ -141,9 +150,9 @@ namespace EmbeddedProto
 
       ~uint32() override = default;
       
-      bool serialize_with_id(uint32_t field_number, WriteBufferInterface& buffer) const final;
-      bool serialize(WriteBufferInterface& buffer) const final;
-      bool deserialize(ReadBufferInterface& buffer) final; 
+      Error serialize_with_id(uint32_t field_number, WriteBufferInterface& buffer) const final;
+      Error serialize(WriteBufferInterface& buffer) const final;
+      Error deserialize(ReadBufferInterface& buffer) final; 
   };
 
   class uint64 : public FieldTemplate<uint64_t> 
@@ -155,9 +164,9 @@ namespace EmbeddedProto
 
       ~uint64() override = default;
       
-      bool serialize_with_id(uint32_t field_number, WriteBufferInterface& buffer) const final;
-      bool serialize(WriteBufferInterface& buffer) const final;
-      bool deserialize(ReadBufferInterface& buffe) final; 
+      Error serialize_with_id(uint32_t field_number, WriteBufferInterface& buffer) const final;
+      Error serialize(WriteBufferInterface& buffer) const final;
+      Error deserialize(ReadBufferInterface& buffe) final; 
   };
 
   class sint32 : public FieldTemplate<int32_t> 
@@ -169,9 +178,9 @@ namespace EmbeddedProto
 
       ~sint32() override = default;
       
-      bool serialize_with_id(uint32_t field_number, WriteBufferInterface& buffer) const final;
-      bool serialize(WriteBufferInterface& buffer) const final;
-      bool deserialize(ReadBufferInterface& buffer) final; 
+      Error serialize_with_id(uint32_t field_number, WriteBufferInterface& buffer) const final;
+      Error serialize(WriteBufferInterface& buffer) const final;
+      Error deserialize(ReadBufferInterface& buffer) final; 
   };
 
   class sint64 : public FieldTemplate<int64_t> 
@@ -183,9 +192,9 @@ namespace EmbeddedProto
 
       ~sint64() override = default;
       
-      bool serialize_with_id(uint32_t field_number, WriteBufferInterface& buffer) const final;
-      bool serialize(WriteBufferInterface& buffer) const final;
-      bool deserialize(ReadBufferInterface& buffer) final; 
+      Error serialize_with_id(uint32_t field_number, WriteBufferInterface& buffer) const final;
+      Error serialize(WriteBufferInterface& buffer) const final;
+      Error deserialize(ReadBufferInterface& buffer) final; 
   };
 
   class boolean : public FieldTemplate<bool> 
@@ -197,9 +206,9 @@ namespace EmbeddedProto
 
       ~boolean() override = default;
       
-      bool serialize_with_id(uint32_t field_number, WriteBufferInterface& buffer) const final;
-      bool serialize(WriteBufferInterface& buffer) const final;
-      bool deserialize(ReadBufferInterface& buffer) final; 
+      Error serialize_with_id(uint32_t field_number, WriteBufferInterface& buffer) const final;
+      Error serialize(WriteBufferInterface& buffer) const final;
+      Error deserialize(ReadBufferInterface& buffer) final; 
   };
 
   class fixed32 : public FieldTemplate<uint32_t> 
@@ -211,9 +220,9 @@ namespace EmbeddedProto
 
       ~fixed32() override = default;
       
-      bool serialize_with_id(uint32_t field_number, WriteBufferInterface& buffer) const final;
-      bool serialize(WriteBufferInterface& buffer) const final;
-      bool deserialize(ReadBufferInterface& buffer) final; 
+      Error serialize_with_id(uint32_t field_number, WriteBufferInterface& buffer) const final;
+      Error serialize(WriteBufferInterface& buffer) const final;
+      Error deserialize(ReadBufferInterface& buffer) final; 
   };
 
   class fixed64 : public FieldTemplate<uint64_t> 
@@ -225,9 +234,9 @@ namespace EmbeddedProto
 
       ~fixed64() override = default;
       
-      bool serialize_with_id(uint32_t field_number, WriteBufferInterface& buffer) const final;
-      bool serialize(WriteBufferInterface& buffer) const final;
-      bool deserialize(ReadBufferInterface& buffer) final; 
+      Error serialize_with_id(uint32_t field_number, WriteBufferInterface& buffer) const final;
+      Error serialize(WriteBufferInterface& buffer) const final;
+      Error deserialize(ReadBufferInterface& buffer) final; 
   };
 
   class sfixed32 : public FieldTemplate<int32_t> 
@@ -239,9 +248,9 @@ namespace EmbeddedProto
 
       ~sfixed32() override = default;
       
-      bool serialize_with_id(uint32_t field_number, WriteBufferInterface& buffer) const final;
-      bool serialize(WriteBufferInterface& buffer) const final;
-      bool deserialize(ReadBufferInterface& buffer) final; 
+      Error serialize_with_id(uint32_t field_number, WriteBufferInterface& buffer) const final;
+      Error serialize(WriteBufferInterface& buffer) const final;
+      Error deserialize(ReadBufferInterface& buffer) final; 
   };
 
   class sfixed64 : public FieldTemplate<int64_t> 
@@ -253,9 +262,9 @@ namespace EmbeddedProto
 
       ~sfixed64() override = default;
       
-      bool serialize_with_id(uint32_t field_number, WriteBufferInterface& buffer) const final;
-      bool serialize(WriteBufferInterface& buffer) const final;
-      bool deserialize(ReadBufferInterface& buffer) final; 
+      Error serialize_with_id(uint32_t field_number, WriteBufferInterface& buffer) const final;
+      Error serialize(WriteBufferInterface& buffer) const final;
+      Error deserialize(ReadBufferInterface& buffer) final; 
   };
 
   class floatfixed : public FieldTemplate<float> 
@@ -267,9 +276,9 @@ namespace EmbeddedProto
 
       ~floatfixed() override = default;
       
-      bool serialize_with_id(uint32_t field_number, WriteBufferInterface& buffer) const final;
-      bool serialize(WriteBufferInterface& buffer) const final;
-      bool deserialize(ReadBufferInterface& buffer) final; 
+      Error serialize_with_id(uint32_t field_number, WriteBufferInterface& buffer) const final;
+      Error serialize(WriteBufferInterface& buffer) const final;
+      Error deserialize(ReadBufferInterface& buffer) final; 
   };
 
   class doublefixed : public FieldTemplate<double> 
@@ -281,9 +290,9 @@ namespace EmbeddedProto
 
       ~doublefixed() override = default;
       
-      bool serialize_with_id(uint32_t field_number, WriteBufferInterface& buffer) const final;
-      bool serialize(WriteBufferInterface& buffer) const final;
-      bool deserialize(ReadBufferInterface& buffer) final; 
+      Error serialize_with_id(uint32_t field_number, WriteBufferInterface& buffer) const final;
+      Error serialize(WriteBufferInterface& buffer) const final;
+      Error deserialize(ReadBufferInterface& buffer) final; 
   };
 
 } // End of namespace EmbeddedProto.

+ 16 - 9
src/MessageInterface.cpp

@@ -22,7 +22,7 @@
  *  Info:
  *    info at EmbeddedProto dot com
  *
- *  Postal adress:
+ *  Postal address:
  *    Johan Huizingalaan 763a
  *    1066 VH, Amsterdam
  *    the Netherlands
@@ -34,20 +34,27 @@
 namespace EmbeddedProto
 {
 
-  bool MessageInterface::MessageInterface::serialize_with_id(uint32_t field_number, ::EmbeddedProto::WriteBufferInterface& buffer) const
+  Error MessageInterface::MessageInterface::serialize_with_id(uint32_t field_number, ::EmbeddedProto::WriteBufferInterface& buffer) const
   {
     const uint32_t size_x = this->serialized_size();
     bool result = (size_x < buffer.get_available_size());
+    Error return_value = result ? Error::NO_ERRORS : Error::BUFFER_FULL;
     if(result && (0 < size_x))
     {
-      uint32_t tag = ::EmbeddedProto::WireFormatter::MakeTag(field_number, 
-                              ::EmbeddedProto::WireFormatter::WireType::LENGTH_DELIMITED);
-      result = ::EmbeddedProto::WireFormatter::SerializeVarint(tag, buffer);
-      result = result && ::EmbeddedProto::WireFormatter::SerializeVarint(size_x, buffer);
-      const ::EmbeddedProto::Field* base = static_cast<const ::EmbeddedProto::Field*>(this);
-      result = result && base->serialize(buffer);
+      uint32_t tag = WireFormatter::MakeTag(field_number, 
+                              WireFormatter::WireType::LENGTH_DELIMITED);
+      return_value = WireFormatter::SerializeVarint(tag, buffer);
+      if(Error::NO_ERRORS == return_value)
+      {
+        return_value = WireFormatter::SerializeVarint(size_x, buffer);
+        if(Error::NO_ERRORS == return_value)
+        {
+          const ::EmbeddedProto::Field* base = static_cast<const ::EmbeddedProto::Field*>(this);  
+          return_value = base->serialize(buffer);
+        }
+      }
     }
-    return result;
+    return return_value;
   }
 
 } // End of namespace EmbeddedProto

+ 6 - 4
src/MessageInterface.h

@@ -22,7 +22,7 @@
  *  Info:
  *    info at EmbeddedProto dot com
  *
- *  Postal adress:
+ *  Postal address:
  *    Johan Huizingalaan 763a
  *    1066 VH, Amsterdam
  *    the Netherlands
@@ -31,10 +31,12 @@
 #ifndef _MESSAGE_INTERFACE_H_
 #define _MESSAGE_INTERFACE_H_
 
-#include <cstdint>
-
 #include "WireFormatter.h"
 #include "Fields.h"
+#include "Errors.h"
+
+#include <cstdint>
+
 
 namespace EmbeddedProto 
 {
@@ -48,7 +50,7 @@ class MessageInterface : public ::EmbeddedProto::Field
     virtual ~MessageInterface() = default;
 
     // TODO doc
-    bool serialize_with_id(uint32_t field_number, ::EmbeddedProto::WriteBufferInterface& buffer) const final;
+    Error serialize_with_id(uint32_t field_number, ::EmbeddedProto::WriteBufferInterface& buffer) const final;
 
     //! Clear the content of this message and set it to it's default state.
     /*!

+ 6 - 8
src/MessageSizeCalculator.h

@@ -22,7 +22,7 @@
  *  Info:
  *    info at EmbeddedProto dot com
  *
- *  Postal adress:
+ *  Postal address:
  *    Johan Huizingalaan 763a
  *    1066 VH, Amsterdam
  *    the Netherlands
@@ -31,9 +31,11 @@
 #ifndef _MESSAGE_SIZE_CALCULATOR_H_
 #define _MESSAGE_SIZE_CALCULATOR_H_
 
+#include "WriteBufferInterface.h"
+
+#include <cstdint>
 #include <limits> 
 
-#include "WriteBufferInterface.h"
 
 namespace EmbeddedProto 
 {
@@ -48,11 +50,7 @@ namespace EmbeddedProto
   class MessageSizeCalculator : public WriteBufferInterface
   {
     public:
-      MessageSizeCalculator()
-        : size_(0)
-      { 
-      };
-
+      MessageSizeCalculator() = default;
       ~MessageSizeCalculator() override = default;
       
       //! Reset the size count of the buffer.
@@ -101,7 +99,7 @@ namespace EmbeddedProto
     private:
 
       //! The calculated size of the buffer.
-      uint32_t size_;
+      uint32_t size_ = 0;
 
   }; // End of class MessageSizeCalculator
 

+ 5 - 2
src/ReadBufferInterface.h

@@ -22,7 +22,7 @@
  *  Info:
  *    info at EmbeddedProto dot com
  *
- *  Postal adress:
+ *  Postal address:
  *    Johan Huizingalaan 763a
  *    1066 VH, Amsterdam
  *    the Netherlands
@@ -31,6 +31,9 @@
 #ifndef _READ_BUFFER_INTERFACE_H_
 #define _READ_BUFFER_INTERFACE_H_
 
+#include <cstdint>
+
+
 namespace EmbeddedProto 
 {
   //! The pure virtual definition of a message buffer to read from.
@@ -59,7 +62,7 @@ namespace EmbeddedProto
           \param[out] byte When the buffer is not empty this variable will hold the oldest value.
           \return True when the buffer was not empty.
       */
-      virtual bool peak(uint8_t& byte) const = 0;
+      virtual bool peek(uint8_t& byte) const = 0;
 
       //! Advances the internal read index by one when the buffer is not empty.
       virtual void advance() = 0;

+ 10 - 6
src/ReadBufferSection.cpp

@@ -22,7 +22,7 @@
  *  Info:
  *    info at EmbeddedProto dot com
  *
- *  Postal adress:
+ *  Postal address:
  *    Johan Huizingalaan 763a
  *    1066 VH, Amsterdam
  *    the Netherlands
@@ -30,15 +30,18 @@
 
 #include "ReadBufferSection.h"
 
+#include <algorithm>
+
+
 namespace EmbeddedProto 
 {
 
   ReadBufferSection::ReadBufferSection(ReadBufferInterface& buffer, const uint32_t size)
     : buffer_(buffer),
-      size_(size),
-      max_size_(size)
+      size_(std::min(size, buffer.get_size())),
+      max_size_(std::min(size, buffer.get_size()))
   {
-
+    
   }
 
   uint32_t ReadBufferSection::get_size() const
@@ -51,12 +54,12 @@ namespace EmbeddedProto
     return max_size_;
   }
 
-  bool ReadBufferSection::peak(uint8_t& byte) const
+  bool ReadBufferSection::peek(uint8_t& byte) const
   {
     bool result = 0 < size_;
     if(result)
     {
-      result = buffer_.peak(byte);
+      result = buffer_.peek(byte);
     }
     return result;
   }
@@ -66,6 +69,7 @@ namespace EmbeddedProto
     if(0 < size_) 
     {
       buffer_.advance();
+      --size_;
     }
   }
 

+ 4 - 3
src/ReadBufferSection.h

@@ -22,7 +22,7 @@
  *  Info:
  *    info at EmbeddedProto dot com
  *
- *  Postal adress:
+ *  Postal address:
  *    Johan Huizingalaan 763a
  *    1066 VH, Amsterdam
  *    the Netherlands
@@ -31,9 +31,10 @@
 #ifndef _READ_BUFFER_SECTION_H_
 #define _READ_BUFFER_SECTION_H_
 
+#include "ReadBufferInterface.h"
+
 #include <cstdint>
 
-#include "ReadBufferInterface.h"
 
 namespace EmbeddedProto 
 {
@@ -75,7 +76,7 @@ namespace EmbeddedProto
       /*!
         This will not do anything if size zero is reached.
       */
-      bool peak(uint8_t& byte) const override;
+      bool peek(uint8_t& byte) const override;
 
       //! Decrement the size and call advance on the parent buffer.
       /*!

+ 103 - 147
src/RepeatedField.h

@@ -22,23 +22,24 @@
  *  Info:
  *    info at EmbeddedProto dot com
  *
- *  Postal adress:
+ *  Postal address:
  *    Johan Huizingalaan 763a
  *    1066 VH, Amsterdam
  *    the Netherlands
  */
 
-#ifndef _DYNAMIC_BUFFER_H_
-#define _DYNAMIC_BUFFER_H_
-
-#include <cstring>
-#include <algorithm>    // std::min
-#include <type_traits>
+#ifndef _REPEATED_FIELD_H_
+#define _REPEATED_FIELD_H_
 
 #include "Fields.h"
 #include "MessageInterface.h"
 #include "MessageSizeCalculator.h"
 #include "ReadBufferSection.h" 
+#include "Errors.h"
+
+#include <cstdint>
+#include <type_traits>
+
 
 namespace EmbeddedProto
 {
@@ -57,20 +58,17 @@ namespace EmbeddedProto
       RepeatedField() = default;
       virtual ~RepeatedField() = default;
 
-      //! Obtain the total number of bytes currently stored in the array.
-      virtual uint32_t get_size() const = 0;
-
-      //! Obtain the maximum number of bytes which can at most be stored in the array.
-      virtual uint32_t get_max_size() const = 0;
-
       //! Obtain the total number of DATA_TYPE items in the array.
       virtual uint32_t get_length() const = 0;
 
       //! Obtain the maximum number of DATA_TYPE items which can at most be stored in the array.
       virtual uint32_t get_max_length() const = 0;
+      
+      //! Obtain the total number of bytes currently stored in the array.
+      virtual uint32_t get_size() const = 0;
 
-      //! Get a pointer to the first element in the array.
-      virtual DATA_TYPE* get_data() = 0;
+      //! Obtain the maximum number of bytes which can at most be stored in the array.
+      virtual uint32_t get_max_size() const = 0;
 
       //! Get a reference to the value at the given index. 
       /*!
@@ -84,7 +82,7 @@ namespace EmbeddedProto
         \param[in] index The desired index to return.
         \return The constant reference to the value at the given index.
       */
-      virtual const DATA_TYPE& get(uint32_t index) const = 0;
+      virtual const DATA_TYPE& get_const(uint32_t index) const = 0;
 
       //! Get a reference to the value at the given index. 
       /*!
@@ -98,7 +96,7 @@ namespace EmbeddedProto
         \param[in] index The desired index to return.
         \return The constant reference to the value at the given index.
       */
-      const DATA_TYPE& operator[](uint32_t index) const { return this->get(index); }
+      const DATA_TYPE& operator[](uint32_t index) const { return this->get_const(index); }
 
       //! Set the value at the given index.
       /*!
@@ -111,91 +109,122 @@ namespace EmbeddedProto
       /*!
         \param[in] data A pointer the array to copy from.
         \param[in] length The number of value of DATA_TYPE in the array.
-        \return True when copying the data succedded. (Could be false if it does not fit.)
+        \return Error::NO_ERRORS when every was successful. Error::ARRAY_FULL when there is no space left.
       */
-      virtual bool set_data(const DATA_TYPE* data, const uint32_t length) = 0;
+      virtual Error set_data(const DATA_TYPE* data, const uint32_t length) = 0;
 
       //! Append a value to the end of the array.
       /*!
         \param[in] value The data to add.
-        \return False if there was no space to add the value.
+        \return Error::NO_ERRORS when every was successful. Error::ARRAY_FULL when there is no space left.
       */
-      virtual bool add(const DATA_TYPE& value) = 0;
+      virtual Error add(const DATA_TYPE& value) = 0;
 
       //! Remove all data in the array and set it to the default value.
       virtual void clear() = 0;
 
-      bool serialize(WriteBufferInterface& buffer) const final
+      Error serialize(WriteBufferInterface& buffer) const
       {
-        return false;
-      }
+        // This function should not be called on a repeated field.
+        return Error::BUFFER_FULL;
+      };
 
-      bool serialize_with_id(uint32_t field_number, WriteBufferInterface& buffer) const final
+      //! \see Field::serialize_with_id()
+      Error serialize_with_id(uint32_t field_number, WriteBufferInterface& buffer) const final
       {
-        bool result = true;
+        Error return_value = Error::NO_ERRORS;
 
         if(PACKED)
         {
           const uint32_t size_x = this->serialized_size_packed(field_number);
-          result = (size_x <= buffer.get_available_size());
 
           // Use the packed way of serialization for base fields.
-          if(result && (0 < size_x))
-          {          
-            uint32_t tag = ::EmbeddedProto::WireFormatter::MakeTag(field_number, 
-                                        ::EmbeddedProto::WireFormatter::WireType::LENGTH_DELIMITED);
-            result = ::EmbeddedProto::WireFormatter::SerializeVarint(tag, buffer);
-            result = result && ::EmbeddedProto::WireFormatter::SerializeVarint(size_x, buffer);
-            result = result && serialize_packed(buffer);
+          if(size_x <= buffer.get_available_size())
+          {
+            if(0 < size_x)
+            {          
+              uint32_t tag = WireFormatter::MakeTag(field_number, 
+                                          WireFormatter::WireType::LENGTH_DELIMITED);
+              return_value = WireFormatter::SerializeVarint(tag, buffer);
+              if(Error::NO_ERRORS == return_value) 
+              {
+                return_value = WireFormatter::SerializeVarint(size_x, buffer);
+                if(Error::NO_ERRORS == return_value) 
+                {
+                  return_value = serialize_packed(buffer);
+                }
+              }
+            }
+          }
+          else
+          {
+            return_value = Error::BUFFER_FULL;
           }
         }
         else 
         {
           const uint32_t size_x = this->serialized_size_unpacked(field_number);
-          result = (size_x <= buffer.get_available_size());
-          result = result && serialize_unpacked(field_number, buffer);
+          return_value = (size_x <= buffer.get_available_size()) ? serialize_unpacked(field_number, buffer) 
+                                                                 : Error::BUFFER_FULL;
         }
 
-        return result;
+        return return_value;
       }
 
       //! Function to deserialize this array.
       /*!
           From a buffer of data fill this array with data.
           \param buffer [in]  The memory from which the message is obtained.
-          \return True when every was successful. 
+          \return Error::NO_ERRORS when every was successful. 
       */
-      bool deserialize(::EmbeddedProto::ReadBufferInterface& buffer) final
+      Error deserialize(::EmbeddedProto::ReadBufferInterface& buffer) final
       {
-        bool result = true;
+        Error return_value = Error::NO_ERRORS;
         if(PACKED)
         {              
           uint32_t size;
-          result = ::EmbeddedProto::WireFormatter::DeserializeVarint(buffer, size);
-          ::EmbeddedProto::ReadBufferSection bufferSection(buffer, size);
+          return_value = WireFormatter::DeserializeVarint(buffer, size);
+          ReadBufferSection bufferSection(buffer, size);
           DATA_TYPE x;
-          while(result && x.deserialize(bufferSection)) 
+          
+          return_value = x.deserialize(bufferSection);
+          while(Error::NO_ERRORS == return_value)
+          {
+            return_value = this->add(x);
+            if(Error::NO_ERRORS == return_value)
+            {
+              return_value = x.deserialize(bufferSection);
+            }
+          }
+
+          // We expect the buffersection to be empty, in that case everything is fine..
+          if(Error::END_OF_BUFFER == return_value)
           {
-            result = this->add(x);
+            return_value = Error::NO_ERRORS;
           }
         }
         else 
         {
           uint32_t size;
-          result = ::EmbeddedProto::WireFormatter::DeserializeVarint(buffer, size);
-          ::EmbeddedProto::ReadBufferSection bufferSection(buffer, size);
-          DATA_TYPE x;
-          if(result && x.deserialize(bufferSection))
+          return_value = WireFormatter::DeserializeVarint(buffer, size);
+          if(Error::NO_ERRORS == return_value) 
           {
-            result = this->add(x);
+            ReadBufferSection bufferSection(buffer, size);
+            DATA_TYPE x;
+            return_value = x.deserialize(bufferSection);
+            if(Error::NO_ERRORS == return_value)
+            {
+              return_value = this->add(x);
+            }
           }
         }
-        return result;
+        return return_value;
       }
 
-      //! Calculate the size of this message when serialized.
+      //! Calculate the size of this field when serialized.
       /*!
-          \return The number of bytes this message will require once serialized.
+          The calculation only includes the data, not the size required by the tag and 
+          \return The number of bytes this field will require once serialized.
       */
       uint32_t serialized_size_packed(int32_t field_number) const 
       {
@@ -204,9 +233,9 @@ namespace EmbeddedProto
         return calcBuffer.get_size();
       }
 
-      //! Calculate the size of this message when serialized.
+      //! Calculate the size of this field when serialized.
       /*!
-          \return The number of bytes this message will require once serialized.
+          \return The number of bytes this field will require once serialized.
       */
       uint32_t serialized_size_unpacked(int32_t field_number) const 
       {
@@ -217,113 +246,40 @@ namespace EmbeddedProto
 
     private:
 
-      bool serialize_packed(WriteBufferInterface& buffer) const
+      Error serialize_packed(WriteBufferInterface& buffer) const
       {
-        bool result = true;
-        for(uint32_t i = 0; (i < this->get_length()) && result; ++i)
+        Error return_value = Error::NO_ERRORS;
+        for(uint32_t i = 0; (i < this->get_length()) && (Error::NO_ERRORS == return_value); ++i)
         {
-          result = this->get(i).serialize(buffer);
+          return_value = this->get_const(i).serialize(buffer);
         }
-        return result;
+        return return_value;
       }
 
-      bool serialize_unpacked(uint32_t field_number, WriteBufferInterface& buffer) const
+      Error serialize_unpacked(uint32_t field_number, WriteBufferInterface& buffer) const
       {
-        bool result = true;
-        for(uint32_t i = 0; (i < this->get_length()) && result; ++i)
+        Error return_value = Error::NO_ERRORS;
+        for(uint32_t i = 0; (i < this->get_length()) && (Error::NO_ERRORS == return_value); ++i)
         {
-          const uint32_t size_x = this->get(i).serialized_size();
-          uint32_t tag = ::EmbeddedProto::WireFormatter::MakeTag(field_number, 
-                                    ::EmbeddedProto::WireFormatter::WireType::LENGTH_DELIMITED);
-          result = ::EmbeddedProto::WireFormatter::SerializeVarint(tag, buffer);
-          result = result && ::EmbeddedProto::WireFormatter::SerializeVarint(size_x, buffer);
-          if(result && (0 < size_x)) 
+          const uint32_t size_x = this->get_const(i).serialized_size();
+          uint32_t tag = WireFormatter::MakeTag(field_number, 
+                                    WireFormatter::WireType::LENGTH_DELIMITED);
+          return_value = WireFormatter::SerializeVarint(tag, buffer);
+          if(Error::NO_ERRORS == return_value)
           {
-            result = this->get(i).serialize(buffer);
+            return_value = WireFormatter::SerializeVarint(size_x, buffer);
+            if((Error::NO_ERRORS == return_value) && (0 < size_x)) 
+            {
+              return_value = this->get_const(i).serialize(buffer);
+            }
           }
         }
-        return result;
+        return return_value;
       }
 
   };
 
-  //! A template class that actually holds some data.
-  /*!
-    This is a separate class to make it possible to not have the size defined in every function or 
-    class using this type of object.
-  */
-  template<class DATA_TYPE, uint32_t MAX_SIZE>
-  class RepeatedFieldSize : public RepeatedField<DATA_TYPE>
-  { 
-      static constexpr uint32_t BYTES_PER_ELEMENT = sizeof(DATA_TYPE);
-
-    public:
-
-      RepeatedFieldSize()
-        : current_size_(0),
-          data_{}
-      {
-
-      }  
-
-      ~RepeatedFieldSize() override = default;
-
-      uint32_t get_size() const override { return BYTES_PER_ELEMENT * current_size_; }
-
-      uint32_t get_max_size() const override { return BYTES_PER_ELEMENT * MAX_SIZE; }
-
-      uint32_t get_length() const override { return current_size_; }
-
-      uint32_t get_max_length() const override { return MAX_SIZE; }
-
-      DATA_TYPE* get_data() { return data_; }
-
-      DATA_TYPE& get(uint32_t index) override { return data_[index]; }
-      const DATA_TYPE& get(uint32_t index) const override { return data_[index]; }
-
-      void set(uint32_t index, const DATA_TYPE& value) override 
-      { 
-        data_[index] = value;
-        current_size_ = std::max(index+1, current_size_); 
-      }
-
-      bool set_data(const DATA_TYPE* data, const uint32_t length) override 
-      {
-        const uint32_t size = length * BYTES_PER_ELEMENT;
-        const bool result = MAX_SIZE >= size;
-        if(result) 
-        {
-          current_size_ = size;
-          memcpy(data_, data, size);
-        }
-        return result;
-      }
-
-      bool add(const DATA_TYPE& value) override 
-      {
-        const bool result = MAX_SIZE >= current_size_;
-        if(result) 
-        {
-          data_[current_size_] = value;
-          ++current_size_;
-        }
-        return result;
-      }
-
-      void clear() override 
-      {
-        current_size_ = 0;
-      }
-
-    private:
-
-      //! Number of item in the data array.
-      uint32_t current_size_;
-
-      //! The actual data 
-      DATA_TYPE data_[MAX_SIZE];
-  };
 
 } // End of namespace EmbeddedProto
 
-#endif // End of _DYNAMIC_BUFFER_H_
+#endif // End of _REPEATED_FIELD_H_

+ 154 - 0
src/RepeatedFieldFixedSize.h

@@ -0,0 +1,154 @@
+/*
+ *  Copyright (C) 2020 Embedded AMS B.V. - All Rights Reserved
+ *
+ *  This file is part of Embedded Proto.
+ *
+ *  Embedded Proto is open source software: you can redistribute it and/or 
+ *  modify it under the terms of the GNU General Public License as published 
+ *  by the Free Software Foundation, version 3 of the license.
+ *
+ *  Embedded Proto  is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Embedded Proto. If not, see <https://www.gnu.org/licenses/>.
+ *
+ *  For commercial and closed source application please visit:
+ *  <https://EmbeddedProto.com/license/>.
+ *
+ *  Embedded AMS B.V.
+ *  Info:
+ *    info at EmbeddedProto dot com
+ *
+ *  Postal address:
+ *    Johan Huizingalaan 763a
+ *    1066 VH, Amsterdam
+ *    the Netherlands
+ */
+
+#ifndef _REPEATED_FIELD_SIZE_H_
+#define _REPEATED_FIELD_SIZE_H_
+
+#include "RepeatedField.h"
+#include "Errors.h"
+
+#include <cstdint>
+#include <cstring>
+#include <algorithm>
+
+
+namespace EmbeddedProto
+{
+
+  //! A template class that actually holds some data.
+  /*!
+    This is a separate class to make it possible to not have the size defined in every function or 
+    class using this type of object.
+  */
+  template<class DATA_TYPE, uint32_t MAX_LENGTH>
+  class RepeatedFieldFixedSize : public RepeatedField<DATA_TYPE>
+  { 
+      static constexpr uint32_t BYTES_PER_ELEMENT = sizeof(DATA_TYPE);
+
+    public:
+
+      RepeatedFieldFixedSize()
+        : current_length_(0),
+          data_{}
+      {
+
+      }  
+
+      ~RepeatedFieldFixedSize() override = default;
+
+      //! Obtain the total number of DATA_TYPE items in the array.
+      uint32_t get_length() const override { return current_length_; }
+
+      //! Obtain the maximum number of DATA_TYPE items which can at most be stored in the array.
+      uint32_t get_max_length() const override { return MAX_LENGTH; }
+
+      //! Obtain the total number of bytes currently stored in the array.
+      uint32_t get_size() const override { return BYTES_PER_ELEMENT * current_length_; }
+
+      //! Obtain the maximum number of bytes which can at most be stored in the array.
+      uint32_t get_max_size() const override { return BYTES_PER_ELEMENT * MAX_LENGTH; }
+
+      DATA_TYPE& get(uint32_t index) override 
+      { 
+        uint32_t limited_index = std::min(index, MAX_LENGTH-1);
+        // Check if we need to update the number of elements in the array.
+        if(limited_index >= current_length_) {
+          current_length_ = limited_index + 1;
+        }
+        return data_[limited_index]; 
+      }
+
+      const DATA_TYPE& get_const(uint32_t index) const override 
+      { 
+        uint32_t limited_index = std::min(index, MAX_LENGTH-1);
+        return data_[limited_index]; 
+      }
+
+      void set(uint32_t index, const DATA_TYPE& value) override 
+      { 
+        uint32_t limited_index = std::min(index, MAX_LENGTH-1);
+        // Check if we need to update the number of elements in the array.
+        if(limited_index >= current_length_) {
+          current_length_ = limited_index + 1;
+        }
+        data_[limited_index] = value;  
+      }
+
+      Error set_data(const DATA_TYPE* data, const uint32_t length) override 
+      {
+        Error return_value = Error::NO_ERRORS;
+        if(MAX_LENGTH >= length) 
+        {
+          current_length_ = length;
+          memcpy(data_, data, length * BYTES_PER_ELEMENT);
+        }
+        else 
+        {
+          return_value = Error::ARRAY_FULL;
+        }
+        return return_value;
+      }
+
+      Error add(const DATA_TYPE& value) override 
+      {
+        Error return_value = Error::NO_ERRORS;
+        if(MAX_LENGTH > current_length_) 
+        {
+          data_[current_length_] = value;
+          ++current_length_;
+        }
+        else 
+        {
+          return_value = Error::ARRAY_FULL;
+        }
+        return return_value;
+      }
+
+      void clear() override 
+      {
+        for(uint32_t i = 0; i < current_length_; ++i)
+        {
+          data_[i].clear();
+        }
+        current_length_ = 0;
+      }
+
+    private:
+
+      //! Number of item in the data array.
+      uint32_t current_length_;
+
+      //! The actual data 
+      DATA_TYPE data_[MAX_LENGTH];
+  };
+
+} // End of namespace EmbeddedProto
+
+#endif // End of _REPEATED_FIELD_SIZE_H_

+ 180 - 103
src/WireFormatter.h

@@ -22,7 +22,7 @@
  *  Info:
  *    info at EmbeddedProto dot com
  *
- *  Postal adress:
+ *  Postal address:
  *    Johan Huizingalaan 763a
  *    1066 VH, Amsterdam
  *    the Netherlands
@@ -31,13 +31,15 @@
 #ifndef _WIRE_FORMATTER_H_
 #define _WIRE_FORMATTER_H_
 
+#include "WriteBufferInterface.h"
+#include "ReadBufferInterface.h"
+#include "Errors.h"
+
 #include <cstdint>
 #include <math.h> 
 #include <type_traits>
 #include <limits>
 
-#include "WriteBufferInterface.h"
-#include "ReadBufferInterface.h"
 
 namespace EmbeddedProto 
 {
@@ -69,73 +71,118 @@ namespace EmbeddedProto
          @{
       **/
       template<class INT_TYPE>
-      static bool SerializeInt(uint32_t field_number, INT_TYPE value, WriteBufferInterface& buffer)
+      static Error SerializeInt(uint32_t field_number, INT_TYPE value, WriteBufferInterface& buffer)
       {        
         typedef typename std::make_unsigned<INT_TYPE>::type UINT_TYPE;
-        return SerializeVarint(MakeTag(field_number, WireType::VARINT), buffer) 
-               && SerializeVarint(static_cast<UINT_TYPE>(value), buffer);
+        Error return_value = SerializeVarint(MakeTag(field_number, WireType::VARINT), buffer);
+        if(Error::NO_ERRORS == return_value)
+        {
+          return_value = SerializeVarint(static_cast<UINT_TYPE>(value), buffer);
+        }
+        return return_value;
       }
 
       template<class UINT_TYPE>
-      static bool SerializeUInt(uint32_t field_number, UINT_TYPE value, WriteBufferInterface& buffer)
+      static Error SerializeUInt(uint32_t field_number, UINT_TYPE value, WriteBufferInterface& buffer)
       {
-        return SerializeVarint(MakeTag(field_number, WireType::VARINT), buffer) 
-               && SerializeVarint(value, buffer);
+        Error return_value = SerializeVarint(MakeTag(field_number, WireType::VARINT), buffer);
+        if(Error::NO_ERRORS == return_value)
+        {
+          return_value = SerializeVarint(value, buffer);
+        }
+        return return_value;
       }
 
       template<class INT_TYPE>
-      static bool SerializeSInt(uint32_t field_number, INT_TYPE value, WriteBufferInterface& buffer)
+      static Error SerializeSInt(uint32_t field_number, INT_TYPE value, WriteBufferInterface& buffer)
       {
-        return SerializeVarint(MakeTag(field_number, WireType::VARINT), buffer) 
-               && SerializeVarint(ZigZagEncode(value), buffer);
+         Error return_value = SerializeVarint(MakeTag(field_number, WireType::VARINT), buffer);
+         if(Error::NO_ERRORS == return_value)
+        {
+          return_value = SerializeVarint(ZigZagEncode(value), buffer);
+        }
+        return return_value;
       }
       
-      static bool SerializeFixed(uint32_t field_number, uint32_t value, WriteBufferInterface& buffer)
+      static Error SerializeFixed(uint32_t field_number, uint32_t value, WriteBufferInterface& buffer)
       {
-        return SerializeVarint(MakeTag(field_number, WireType::FIXED32), buffer) 
-               && SerialzieFixedNoTag(value, buffer);
+        Error return_value = SerializeVarint(MakeTag(field_number, WireType::FIXED32), buffer);
+        if(Error::NO_ERRORS == return_value)
+        {
+          return_value = SerialzieFixedNoTag(value, buffer);
+        }
+        return return_value;
       }
 
-      static bool SerializeFixed(uint32_t field_number, uint64_t value, WriteBufferInterface& buffer)
+      static Error SerializeFixed(uint32_t field_number, uint64_t value, WriteBufferInterface& buffer)
       {
-        return SerializeVarint(MakeTag(field_number, WireType::FIXED64), buffer) 
-               && SerialzieFixedNoTag(value, buffer);
+        Error return_value = SerializeVarint(MakeTag(field_number, WireType::FIXED64), buffer);
+        if(Error::NO_ERRORS == return_value)
+        {
+          return_value = SerialzieFixedNoTag(value, buffer);
+        }
+        return return_value;
       }
 
-      static bool SerializeSFixed(uint32_t field_number, int32_t value, WriteBufferInterface& buffer)
+      static Error SerializeSFixed(uint32_t field_number, int32_t value, WriteBufferInterface& buffer)
       {
-        return SerializeVarint(MakeTag(field_number, WireType::FIXED32), buffer) 
-               && SerialzieSFixedNoTag(value, buffer);
+        Error return_value = SerializeVarint(MakeTag(field_number, WireType::FIXED32), buffer);
+        if(Error::NO_ERRORS == return_value)
+        {
+          return_value = SerialzieSFixedNoTag(value, buffer);
+        }
+        return return_value;
       }
 
-      static bool SerializeSFixed(uint32_t field_number, int64_t value, WriteBufferInterface& buffer)
+      static Error SerializeSFixed(uint32_t field_number, int64_t value, WriteBufferInterface& buffer)
       {
-        return SerializeVarint(MakeTag(field_number, WireType::FIXED64), buffer) 
-               && SerialzieSFixedNoTag(value, buffer);
+        Error return_value = SerializeVarint(MakeTag(field_number, WireType::FIXED64), buffer);
+        if(Error::NO_ERRORS == return_value)
+        {
+          return_value = SerialzieSFixedNoTag(value, buffer);
+        }
+        return return_value;
       }
 
-      static bool SerializeFloat(uint32_t field_number, float value, WriteBufferInterface& buffer)
+      static Error SerializeFloat(uint32_t field_number, float value, WriteBufferInterface& buffer)
       {
-        return SerializeVarint(MakeTag(field_number, WireType::FIXED32), buffer) 
-               && SerialzieFloatNoTag(value, buffer);
+        Error return_value = SerializeVarint(MakeTag(field_number, WireType::FIXED32), buffer);
+        if(Error::NO_ERRORS == return_value)
+        {
+          return_value = SerialzieFloatNoTag(value, buffer);
+        }
+        return return_value;
       }
 
-      static bool SerializeDouble(uint32_t field_number, double value, WriteBufferInterface& buffer)
+      static Error SerializeDouble(uint32_t field_number, double value, WriteBufferInterface& buffer)
       {
-        return SerializeVarint(MakeTag(field_number, WireType::FIXED64), buffer) 
-               && SerialzieDoubleNoTag(value, buffer);
+        Error return_value = SerializeVarint(MakeTag(field_number, WireType::FIXED64), buffer);
+        if(Error::NO_ERRORS == return_value)
+        {
+          return_value = SerialzieDoubleNoTag(value, buffer);
+        }
+        return return_value;
       }
 
-      static bool SerializeBool(uint32_t field_number, bool value, WriteBufferInterface& buffer)
+      static Error SerializeBool(uint32_t field_number, bool value, WriteBufferInterface& buffer)
       {
-        return SerializeVarint(MakeTag(field_number, WireType::VARINT), buffer)
-               && buffer.push(value ? 0x01 : 0x00);
+        Error return_value = SerializeVarint(MakeTag(field_number, WireType::VARINT), buffer);
+        if(Error::NO_ERRORS == return_value)
+        {
+          const uint8_t byte = value ? 0x01 : 0x00;
+          return_value = buffer.push(byte) ? Error::NO_ERRORS : Error::BUFFER_FULL;
+        }
+        return return_value;
       }
 
-      static bool SerializeEnum(uint32_t field_number, uint32_t value, WriteBufferInterface& buffer)
+      static Error SerializeEnum(uint32_t field_number, uint32_t value, WriteBufferInterface& buffer)
       {
-        return SerializeVarint(MakeTag(field_number, WireType::VARINT), buffer) 
-               && SerializeVarint(value, buffer);
+        Error return_value = SerializeVarint(MakeTag(field_number, WireType::VARINT), buffer);
+        if(Error::NO_ERRORS == return_value)
+        {
+          return_value = SerializeVarint(value, buffer);
+        }
+        return return_value;
       }
 
       /** @} **/
@@ -150,27 +197,33 @@ namespace EmbeddedProto
           \param[in] buffer The data source from which to read the type and id.
           \param[out] type This parameter returns the wiretype of the next field in the data buffer.
           \param[out] id This parameter returns the next field id.
-          \return True when deserializing the type and id succeeded.  
+          \return A value from the EmbeddedProto::Error enum indicating if the process succeeded.
       */
-      static bool DeserializeTag(ReadBufferInterface& buffer, WireType& type, uint32_t& id) 
+      static Error DeserializeTag(ReadBufferInterface& buffer, WireType& type, uint32_t& id) 
       {
         uint32_t temp_value;
+        // Read the next varint considered to be a tag.
+        Error return_value = DeserializeVarint(buffer, temp_value);
         
-        // Read the next varint considerted to be a tag. Next check the validity of the wire type.
-        bool result = DeserializeVarint(buffer, temp_value) && 
-                      ((temp_value &  0x07) <= static_cast<uint32_t>(WireType::FIXED32));
-        
-        // If reading the tag succedded and the wire type is a valid one
-        if(result) 
+        if(Error::NO_ERRORS == return_value) 
         {
-          type = static_cast<WireType>(temp_value &  0x07);
-          id = (temp_value >> 3);
+          // Next check the validity of the wire type.
+          if((temp_value &  0x07) <= static_cast<uint32_t>(WireType::FIXED32))
+          {
+            // If reading the tag succeeded and the wire type is a valid one.
+            type = static_cast<WireType>(temp_value &  0x07);
+            id = (temp_value >> 3);
+          }
+          else 
+          {
+            return_value = Error::INVALID_WIRETYPE;
+          }
         }
-        return result;
+        return return_value;
       }
 
       template<class UINT_TYPE>
-      static bool DeserializeUInt(ReadBufferInterface& buffer, UINT_TYPE& value) 
+      static Error DeserializeUInt(ReadBufferInterface& buffer, UINT_TYPE& value) 
       {
         static_assert(std::is_same<UINT_TYPE, uint32_t>::value || 
                       std::is_same<UINT_TYPE, uint64_t>::value, "Wrong type passed to DeserializeUInt.");
@@ -179,14 +232,14 @@ namespace EmbeddedProto
       }
 
       template<class INT_TYPE>
-      static bool DeserializeInt(ReadBufferInterface& buffer, INT_TYPE& value) 
+      static Error DeserializeInt(ReadBufferInterface& buffer, INT_TYPE& value) 
       {
         static_assert(std::is_same<INT_TYPE, int32_t>::value || 
                       std::is_same<INT_TYPE, int64_t>::value, "Wrong type passed to DeserializeInt.");
         
         uint64_t uint_value;
-        bool result = DeserializeVarint(buffer, uint_value);
-        if(result) 
+        Error result = DeserializeVarint(buffer, uint_value);
+        if(Error::NO_ERRORS == result) 
         {
           value = static_cast<INT_TYPE>(uint_value);
         }
@@ -194,14 +247,14 @@ namespace EmbeddedProto
       }
 
       template<class INT_TYPE>
-      static bool DeserializeSInt(ReadBufferInterface& buffer, INT_TYPE& value) 
+      static Error DeserializeSInt(ReadBufferInterface& buffer, INT_TYPE& value) 
       {
         static_assert(std::is_same<INT_TYPE, int32_t>::value || 
                       std::is_same<INT_TYPE, int64_t>::value, "Wrong type passed to DeserializeSInt.");
         
         uint64_t uint_value;
-        bool result = DeserializeVarint(buffer, uint_value);
-        if(result) 
+        Error result = DeserializeVarint(buffer, uint_value);
+        if(Error::NO_ERRORS == result) 
         {
           value = ZigZagDecode(uint_value);
         }
@@ -209,56 +262,63 @@ namespace EmbeddedProto
       }
 
       template<class TYPE>
-      static bool DeserializeFixed(ReadBufferInterface& buffer, TYPE& value) 
+      static Error DeserializeFixed(ReadBufferInterface& buffer, TYPE& value) 
       {
         static_assert(std::is_same<TYPE, uint32_t>::value || 
                       std::is_same<TYPE, uint64_t>::value, "Wrong type passed to DeserializeFixed.");
 
-          // Deserialize the data little endian to the buffer.
-          // TODO Define a little endian flag to support memcpy the data from the buffer.
-
-          TYPE temp_value = 0;
-          bool result(true);
-          uint8_t byte = 0;
-          for(uint8_t i = 0; (i < std::numeric_limits<TYPE>::digits) && result; 
-              i += std::numeric_limits<uint8_t>::digits)  
-          {
-            result = buffer.pop(byte);
-            if(result)
-            {
-              temp_value |= (static_cast<TYPE>(byte) << i);
-            }
-          }
+        // Deserialize the data little endian to the buffer.
+        // TODO Define a little endian flag to support memcpy the data from the buffer.
 
+        TYPE temp_value = 0;
+        bool result(true);
+        uint8_t byte = 0;
+        for(uint8_t i = 0; (i < std::numeric_limits<TYPE>::digits) && result; 
+            i += std::numeric_limits<uint8_t>::digits)  
+        {
+          result = buffer.pop(byte);
           if(result)
           {
-            value = temp_value;
+            temp_value |= (static_cast<TYPE>(byte) << i);
           }
+        }
+
+        Error return_value = Error::NO_ERRORS;
+        if(result)
+        {
+          value = temp_value;
+        }
+        else 
+        {
+          return_value = Error::END_OF_BUFFER;
+        }
 
-          return result;
+        return return_value;
       }
 
       template<class STYPE>
-      static bool DeserializeSFixed(ReadBufferInterface& buffer, STYPE& value) 
+      static Error DeserializeSFixed(ReadBufferInterface& buffer, STYPE& value) 
       {
         static_assert(std::is_same<STYPE, int32_t>::value || 
                       std::is_same<STYPE, int64_t>::value, "Wrong type passed to DeserializeSFixed.");
 
         typedef typename std::make_unsigned<STYPE>::type USTYPE;
         USTYPE temp_unsigned_value = 0;
-        bool result = DeserializeFixed(buffer, temp_unsigned_value);
-        if(result) {
+        Error result = DeserializeFixed(buffer, temp_unsigned_value);
+        if(Error::NO_ERRORS == result)
+        {
           value = static_cast<STYPE>(temp_unsigned_value);
         }
 
         return result;
       }
 
-      static bool DeserializeFloat(ReadBufferInterface& buffer, float& value) 
+      static Error DeserializeFloat(ReadBufferInterface& buffer, float& value) 
       {
         uint32_t temp_value = 0;
-        bool result = DeserializeFixed(buffer, temp_value);
-        if(result) {
+        Error result = DeserializeFixed(buffer, temp_value);
+        if(Error::NO_ERRORS == result) 
+        {
           // Cast from unsigned int to a float.
           const void* pVoid = static_cast<const void*>(&temp_value);
           const float* pFloat = static_cast<const float*>(pVoid);
@@ -267,11 +327,12 @@ namespace EmbeddedProto
         return result;
       }
 
-      static bool DeserializeDouble(ReadBufferInterface& buffer, double& value) 
+      static Error DeserializeDouble(ReadBufferInterface& buffer, double& value) 
       {
         uint64_t temp_value = 0;
-        bool result = DeserializeFixed(buffer, temp_value);
-        if(result) {
+        Error result = DeserializeFixed(buffer, temp_value);
+        if(Error::NO_ERRORS == result) 
+        {
           // Cast from unsigned int to a double.
           const void* pVoid = static_cast<const void*>(&temp_value);
           const double* pDouble = static_cast<const double*>(pVoid);
@@ -280,23 +341,29 @@ namespace EmbeddedProto
         return result;
       }
 
-      static bool DeserializeBool(ReadBufferInterface& buffer, bool& value) 
+      static Error DeserializeBool(ReadBufferInterface& buffer, bool& value) 
       {
         uint8_t byte;
-        bool result = buffer.pop(byte);
-        if(result) {
+        Error result = Error::NO_ERRORS;
+        if(buffer.pop(byte))
+        {
           value = static_cast<bool>(byte);
         }
+        else 
+        {
+          result = Error::END_OF_BUFFER;
+        }
         return result;
       }
 
       template<class ENUM_TYPE>
-      static bool DeserializeEnum(ReadBufferInterface& buffer, ENUM_TYPE& value) 
+      static Error DeserializeEnum(ReadBufferInterface& buffer, ENUM_TYPE& value) 
       {
         static_assert(std::is_enum<ENUM_TYPE>::value, "No enum given to DeserializeEnum parameter value.");
         uint64_t temp_value;
-        bool result = DeserializeVarint(buffer, temp_value);
-        if(result) {
+        Error result = DeserializeVarint(buffer, temp_value);
+        if(Error::NO_ERRORS == result)
+        {
           value = static_cast<ENUM_TYPE>(temp_value);
         }
         return result;
@@ -310,37 +377,42 @@ namespace EmbeddedProto
       /*!
         \param[in] value  The data to be serialized, uint32_t or uint64_t.
         \param[in] buffer A reference to a message buffer object in which to store the variable.
-        \return True when it was possible to store the variable in the buffer.
+        \return A value from the Error enum, NO_ERROR in case everything is fine.
       */
       template<class UINT_TYPE>
-      static bool SerializeVarint(UINT_TYPE value, WriteBufferInterface& buffer) 
+      static Error SerializeVarint(UINT_TYPE value, WriteBufferInterface& buffer) 
       {
         static_assert(std::is_same<UINT_TYPE, uint32_t>::value || 
                       std::is_same<UINT_TYPE, uint64_t>::value, 
                       "Wrong type passed to SerializeVarint.");
 
-        while (value >= VARINT_MSB_BYTE) {
-          buffer.push(static_cast<uint8_t>(value | VARINT_MSB_BYTE));
+        bool memory_free = true;
+        while((value >= VARINT_MSB_BYTE) && memory_free) 
+        {
+          memory_free = buffer.push(static_cast<uint8_t>(value | VARINT_MSB_BYTE));
           value >>= VARINT_SHIFT_N_BITS;
         }
-        return buffer.push(static_cast<uint8_t>(value));
+        memory_free = buffer.push(static_cast<uint8_t>(value));
+
+        const Error return_value = memory_free ? Error::NO_ERRORS : Error::BUFFER_FULL;
+        return return_value;
       }
 
-      //! This function de serializes the following N bytes into a varint.
+      //! This function deserializes the following N bytes into a varint.
       /*!
         \param[in] buffer The data buffer from which bytes are popped.
         \param[out] value The variable in which the varint is returned.
-        \return True when it was possible to deserialize a varint from the buffer.
+        \return A value from the Error enum, NO_ERROR in case everything is fine.
       */
       template<class UINT_TYPE>
-      static bool DeserializeVarint(ReadBufferInterface& buffer, UINT_TYPE& value) 
+      static Error DeserializeVarint(ReadBufferInterface& buffer, UINT_TYPE& value) 
       {
         static_assert(std::is_same<UINT_TYPE, uint32_t>::value || 
                       std::is_same<UINT_TYPE, uint64_t>::value, 
                       "Wrong type passed to DeserializeVarint.");
         
         // Calculate how many bytes there are in a varint 128 base encoded number. This should 
-        // yeild 5 for a 32bit number and 10 for a 64bit number.
+        // yield 5 for a 32bit number and 10 for a 64bit number.
         static constexpr uint8_t N_BYTES_IN_VARINT = static_cast<uint8_t>(std::ceil(
                                                           std::numeric_limits<UINT_TYPE>::digits 
                                                         / static_cast<float>(VARINT_SHIFT_N_BITS)));
@@ -364,12 +436,17 @@ namespace EmbeddedProto
           }
         }
 
+        Error return_value = Error::NO_ERRORS;
         if(result)
         {
           value = temp_value;
         }
+        else 
+        {
+          return_value = Error::END_OF_BUFFER;
+        }
 
-        return result;
+        return return_value;
       }
 
       //! Encode a signed integer using the zig zag method
@@ -430,7 +507,7 @@ namespace EmbeddedProto
 
       //! Serialize an unsigned fixed length field without the tag.
       template<class UINT_TYPE>
-      static bool SerialzieFixedNoTag(UINT_TYPE value, WriteBufferInterface& buffer) 
+      static Error SerialzieFixedNoTag(UINT_TYPE value, WriteBufferInterface& buffer) 
       {
         static_assert(std::is_same<UINT_TYPE, uint32_t>::value || 
                       std::is_same<UINT_TYPE, uint64_t>::value, "Wrong type passed to SerialzieFixedNoTag.");
@@ -445,12 +522,12 @@ namespace EmbeddedProto
           // Shift the value using the current value of i.
           result = buffer.push(static_cast<uint8_t>((value >> i) & 0x00FF));
         }
-        return result;
+        return result ? Error::NO_ERRORS : Error::BUFFER_FULL;
       }
 
-      //! Srialzie a signed fixed length field without the tag.
+      //! Serialize a signed fixed length field without the tag.
       template<class INT_TYPE>
-      static bool SerialzieSFixedNoTag(INT_TYPE value, WriteBufferInterface& buffer)
+      static Error SerialzieSFixedNoTag(INT_TYPE value, WriteBufferInterface& buffer)
       {
         static_assert(std::is_same<INT_TYPE, int32_t>::value || 
                       std::is_same<INT_TYPE, int64_t>::value, "Wrong type passed to SerialzieSFixedNoTag.");
@@ -461,7 +538,7 @@ namespace EmbeddedProto
       }
 
       //! Serialize a 32bit real value without tag.
-      static bool SerialzieFloatNoTag(float value, WriteBufferInterface& buffer)
+      static Error SerialzieFloatNoTag(float value, WriteBufferInterface& buffer)
       {
         // Cast the type to void and to a 32 fixed number
         void* pVoid = static_cast<void*>(&value);
@@ -470,7 +547,7 @@ namespace EmbeddedProto
       }
 
       //! Serialize a 64bit real value without tag.
-      static bool SerialzieDoubleNoTag(double value, WriteBufferInterface& buffer)
+      static Error SerialzieDoubleNoTag(double value, WriteBufferInterface& buffer)
       {
         // Cast the type to void and to a 64 fixed number
         void* pVoid = static_cast<void*>(&value);

+ 4 - 1
src/WriteBufferInterface.h

@@ -22,7 +22,7 @@
  *  Info:
  *    info at EmbeddedProto dot com
  *
- *  Postal adress:
+ *  Postal address:
  *    Johan Huizingalaan 763a
  *    1066 VH, Amsterdam
  *    the Netherlands
@@ -31,6 +31,9 @@
 #ifndef _WRITE_BUFFER_INTERFACE_H_
 #define _WRITE_BUFFER_INTERFACE_H_
 
+#include <cstdint>
+
+
 namespace EmbeddedProto 
 {
   //! The pure virtual definition of a message buffer used for writing .

+ 3 - 4
test/mock/ReadBufferMock.h

@@ -22,7 +22,7 @@
  *  Info:
  *    info at EmbeddedProto dot com
  *
- *  Postal adress:
+ *  Postal address:
  *    Johan Huizingalaan 763a
  *    1066 VH, Amsterdam
  *    the Netherlands
@@ -45,9 +45,8 @@ namespace Mocks
       MOCK_CONST_METHOD0(get_size, uint32_t());
       MOCK_CONST_METHOD0(get_max_size, uint32_t());
       
-      MOCK_CONST_METHOD1(peak, bool(uint8_t&));
-      MOCK_CONST_METHOD0(peak, uint8_t());
-
+      MOCK_CONST_METHOD1(peek, bool(uint8_t&));
+      
       MOCK_METHOD0(advance, void());
       MOCK_METHOD1(advance, void(uint32_t));
       

+ 1 - 1
test/mock/WriteBufferMock.h

@@ -22,7 +22,7 @@
  *  Info:
  *    info at EmbeddedProto dot com
  *
- *  Postal adress:
+ *  Postal address:
  *    Johan Huizingalaan 763a
  *    1066 VH, Amsterdam
  *    the Netherlands

+ 1 - 1
test/proto/file_to_include.proto

@@ -22,7 +22,7 @@
  *  Info:
  *    info at EmbeddedProto dot com
  *
- *  Postal adress:
+ *  Postal address:
  *    Johan Huizingalaan 763a
  *    1066 VH, Amsterdam
  *    the Netherlands

+ 1 - 1
test/proto/include_other_files.proto

@@ -22,7 +22,7 @@
  *  Info:
  *    info at EmbeddedProto dot com
  *
- *  Postal adress:
+ *  Postal address:
  *    Johan Huizingalaan 763a
  *    1066 VH, Amsterdam
  *    the Netherlands

+ 1 - 1
test/proto/nested_message.proto

@@ -22,7 +22,7 @@
  *  Info:
  *    info at EmbeddedProto dot com
  *
- *  Postal adress:
+ *  Postal address:
  *    Johan Huizingalaan 763a
  *    1066 VH, Amsterdam
  *    the Netherlands

+ 1 - 1
test/proto/oneof_fields.proto

@@ -22,7 +22,7 @@
  *  Info:
  *    info at EmbeddedProto dot com
  *
- *  Postal adress:
+ *  Postal address:
  *    Johan Huizingalaan 763a
  *    1066 VH, Amsterdam
  *    the Netherlands

+ 1 - 1
test/proto/repeated_fields.proto

@@ -22,7 +22,7 @@
  *  Info:
  *    info at EmbeddedProto dot com
  *
- *  Postal adress:
+ *  Postal address:
  *    Johan Huizingalaan 763a
  *    1066 VH, Amsterdam
  *    the Netherlands

+ 1 - 1
test/proto/simple_types.proto

@@ -22,7 +22,7 @@
  *  Info:
  *    info at EmbeddedProto dot com
  *
- *  Postal adress:
+ *  Postal address:
  *    Johan Huizingalaan 763a
  *    1066 VH, Amsterdam
  *    the Netherlands

+ 52 - 0
test/proto/string_bytes.proto

@@ -0,0 +1,52 @@
+/*
+ *  Copyright (C) 2020 Embedded AMS B.V. - All Rights Reserved
+ *
+ *  This file is part of Embedded Proto.
+ *
+ *  Embedded Proto is open source software: you can redistribute it and/or 
+ *  modify it under the terms of the GNU General Public License as published 
+ *  by the Free Software Foundation, version 3 of the license.
+ *
+ *  Embedded Proto  is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Embedded Proto. If not, see <https://www.gnu.org/licenses/>.
+ *
+ *  For commercial and closed source application please visit:
+ *  <https://EmbeddedProto.com/license/>.
+ *
+ *  Embedded AMS B.V.
+ *  Info:
+ *    info at EmbeddedProto dot com
+ *
+ *  Postal address:
+ *    Johan Huizingalaan 763a
+ *    1066 VH, Amsterdam
+ *    the Netherlands
+ */
+
+ // This file is used to test the string and bytes fields.
+
+syntax = "proto3";
+
+message text
+{
+  string txt = 1;
+}
+
+message raw_bytes
+{
+  bytes b = 1;
+}
+
+message string_or_bytes
+{
+  oneof s_or_b
+  {
+    string txt = 1;
+    bytes b = 2;
+  }
+}

+ 1 - 1
test/test_EmbeddedProto.cpp

@@ -22,7 +22,7 @@
  *  Info:
  *    info at EmbeddedProto dot com
  *
- *  Postal adress:
+ *  Postal address:
  *    Johan Huizingalaan 763a
  *    1066 VH, Amsterdam
  *    the Netherlands

+ 40 - 5
test/test_IncludeOtherFiles.cpp

@@ -22,7 +22,7 @@
  *  Info:
  *    info at EmbeddedProto dot com
  *
- *  Postal adress:
+ *  Postal address:
  *    Johan Huizingalaan 763a
  *    1066 VH, Amsterdam
  *    the Netherlands
@@ -46,10 +46,10 @@ using ::testing::InSequence;
 using ::testing::Return;
 using ::testing::SetArgReferee;
 
+
 namespace test_EmbeddedAMS_IncludeOtherFiles
 {
 
-
 static constexpr uint32_t RF_SIZE = 3;
 
 TEST(IncludeOtherFiles, zero) 
@@ -64,7 +64,7 @@ TEST(IncludeOtherFiles, zero)
   EXPECT_CALL(buffer, push(_,_)).Times(0);
   EXPECT_CALL(buffer, get_available_size()).WillRepeatedly(Return(99));
 
-  EXPECT_TRUE(msg.serialize(buffer));
+  EXPECT_EQ(::EmbeddedProto::Error::NO_ERRORS, msg.serialize(buffer));
 
   EXPECT_EQ(0, msg.serialized_size());
 }
@@ -73,7 +73,6 @@ TEST(IncludeOtherFiles, set)
 {
   InSequence s;
 
-  // See if an empty message results in no data been pushed.
   ::IncludedMessages<RF_SIZE> msg;
   Mocks::WriteBufferMock buffer;
 
@@ -109,8 +108,44 @@ TEST(IncludeOtherFiles, set)
     EXPECT_CALL(buffer, push(e)).Times(1).WillOnce(Return(true));
   }   
 
-  EXPECT_TRUE(msg.serialize(buffer));
+  EXPECT_EQ(::EmbeddedProto::Error::NO_ERRORS, msg.serialize(buffer));
+
+}
 
+TEST(IncludeOtherFiles, get) 
+{
+  InSequence s;
+
+  ::IncludedMessages<RF_SIZE> msg;
+  Mocks::ReadBufferMock buffer;
+  ON_CALL(buffer, get_size()).WillByDefault(Return(22));
+
+  uint8_t referee[] = { 0x08, 0x01, // state
+                       // cmsg
+                       0x12, 0x07, 
+                       0x08, 0x01, // msg.a
+                       0x15, 0x00, 0x00, 0x80, 0x3f, // msg.b
+                       // rf
+                       0x1a, 0x09, 
+                       0x08, 0x01, // rf.x
+                       0x12, 0x03, 0x01, 0x01, 0x01, // rf.y
+                       0x18, 0x01}; // rf.z
+
+  for(auto r: referee) {
+    EXPECT_CALL(buffer, pop(_)).Times(1).WillOnce(DoAll(SetArgReferee<0>(r), Return(true)));
+  }
+  EXPECT_CALL(buffer, pop(_)).Times(1).WillOnce(Return(false));    
+  
+  EXPECT_EQ(::EmbeddedProto::Error::NO_ERRORS, msg.deserialize(buffer));
+
+  EXPECT_EQ(1, msg.msg().a());
+  EXPECT_EQ(1.0F, msg.msg().b());
+
+  EXPECT_EQ(1, msg.rf().x());
+  EXPECT_EQ(1, msg.rf().y(0));
+  EXPECT_EQ(1, msg.rf().y(1));
+  EXPECT_EQ(1, msg.rf().y(2));
+  EXPECT_EQ(1, msg.rf().z());
 }
 
 

+ 74 - 0
test/test_MessageSizeCalculator.cpp

@@ -0,0 +1,74 @@
+/*
+ *  Copyright (C) 2020 Embedded AMS B.V. - All Rights Reserved
+ *
+ *  This file is part of Embedded Proto.
+ *
+ *  Embedded Proto is open source software: you can redistribute it and/or 
+ *  modify it under the terms of the GNU General Public License as published 
+ *  by the Free Software Foundation, version 3 of the license.
+ *
+ *  Embedded Proto  is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Embedded Proto. If not, see <https://www.gnu.org/licenses/>.
+ *
+ *  For commercial and closed source application please visit:
+ *  <https://EmbeddedProto.com/license/>.
+ *
+ *  Embedded AMS B.V.
+ *  Info:
+ *    info at EmbeddedProto dot com
+ *
+ *  Postal address:
+ *    Johan Huizingalaan 763a
+ *    1066 VH, Amsterdam
+ *    the Netherlands
+ */
+
+#include "gtest/gtest.h"
+
+#include <MessageSizeCalculator.h>
+
+#include <cstdint>
+#include <limits> 
+
+
+namespace test_EmbeddedAMS_MessageSizeCalculator
+{
+
+TEST(MessageSizeCalculator, push) 
+{
+  ::EmbeddedProto::MessageSizeCalculator msc;
+  uint8_t byte = 0;
+  EXPECT_EQ(0, msc.get_size());
+  EXPECT_TRUE(msc.push(byte));
+  EXPECT_EQ(1, msc.get_size());
+  EXPECT_TRUE(msc.push(byte));
+  EXPECT_EQ(2, msc.get_size());
+
+  // Clear the content
+  msc.clear();
+  EXPECT_EQ(0, msc.get_size());
+}
+
+TEST(MessageSizeCalculator, push_n) 
+{
+  ::EmbeddedProto::MessageSizeCalculator msc;
+
+  static constexpr uint8_t SIZE = 3;
+  uint8_t bytes[SIZE] = {1, 2, 3};
+  EXPECT_TRUE(msc.push(bytes, SIZE));
+  EXPECT_EQ(3, msc.get_size());
+}
+
+TEST(MessageSizeCalculator, unlimited_size) 
+{
+  ::EmbeddedProto::MessageSizeCalculator msc;
+  EXPECT_EQ(std::numeric_limits<uint32_t>::max(), msc.get_max_size());
+  EXPECT_EQ(std::numeric_limits<uint32_t>::max(), msc.get_available_size());
+}
+
+} // End of namespace test_EmbeddedAMS_MessageSizeCalculator

+ 35 - 22
test/test_NestedMessage.cpp

@@ -22,7 +22,7 @@
  *  Info:
  *    info at EmbeddedProto dot com
  *
- *  Postal adress:
+ *  Postal address:
  *    Johan Huizingalaan 763a
  *    1066 VH, Amsterdam
  *    the Netherlands
@@ -33,6 +33,7 @@
 #include <WireFormatter.h>
 #include <ReadBufferMock.h>
 #include <WriteBufferMock.h>
+#include <Errors.h>
 
 #include <cstdint>    
 #include <limits> 
@@ -58,7 +59,7 @@ TEST(NestedMessage, serialize_zero)
   EXPECT_CALL(buffer, push(_,_)).Times(0);
   EXPECT_CALL(buffer, get_available_size()).Times(1).WillOnce(Return(99));
 
-  EXPECT_TRUE(msg.serialize(buffer));
+  EXPECT_EQ(::EmbeddedProto::Error::NO_ERRORS, msg.serialize(buffer));
 
   EXPECT_EQ(0, msg.serialized_size());
 }
@@ -69,6 +70,8 @@ TEST(NestedMessage, serialize_one)
 
   ::message_b msg;
   Mocks::WriteBufferMock buffer;
+  ON_CALL(buffer, get_size()).WillByDefault(Return(9));
+
 
   // Test if a nested message can be serialized with values set to one.
   msg.set_u(1.0F);
@@ -97,7 +100,7 @@ TEST(NestedMessage, serialize_one)
   }
 
 
-  EXPECT_TRUE(msg.serialize(buffer));
+  EXPECT_EQ(::EmbeddedProto::Error::NO_ERRORS, msg.serialize(buffer));
 
   EXPECT_EQ(22, msg.serialized_size());
 }
@@ -136,7 +139,7 @@ TEST(NestedMessage, serialize_max)
     EXPECT_CALL(buffer, push(e)).Times(1).WillOnce(Return(true));
   }
 
-  EXPECT_TRUE(msg.serialize(buffer));
+  EXPECT_EQ(::EmbeddedProto::Error::NO_ERRORS, msg.serialize(buffer));
 
   EXPECT_EQ(39, msg.serialized_size());
 }
@@ -178,7 +181,7 @@ TEST(NestedMessage, serialize_nested_in_nested_max)
     EXPECT_CALL(buffer, push(e)).Times(1).WillOnce(Return(true));
   }
 
-  EXPECT_TRUE(msg.serialize(buffer));
+  EXPECT_EQ(::EmbeddedProto::Error::NO_ERRORS, msg.serialize(buffer));
 }
 
 TEST(NestedMessage, deserialize_one) 
@@ -188,22 +191,27 @@ TEST(NestedMessage, deserialize_one)
   ::message_b msg;
   Mocks::ReadBufferMock buffer;
 
+
+  static constexpr uint32_t SIZE = 22;
+
+  ON_CALL(buffer, get_size()).WillByDefault(Return(SIZE));
+
   // Test if a nested message can be deserialized with values set to one.
 
-  uint8_t referee[] = {0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F, // u
-                       0x12, 0x09, // tag and size of nested a
-                       0x08, 0x01, // x
-                       0x15, 0x00, 0x00, 0x80, 0x3F, // y
-                       0x18, 0x02, // z
-                       // And back to the parent message with field v.
-                       0x18, 0x01};
+  uint8_t referee[SIZE] = { 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F, // u
+                            0x12, 0x09, // tag and size of nested a
+                            0x08, 0x01, // x
+                            0x15, 0x00, 0x00, 0x80, 0x3F, // y
+                            0x18, 0x02, // z
+                            // And back to the parent message with field v.
+                            0x18, 0x01};
 
   for(auto r: referee) {
     EXPECT_CALL(buffer, pop(_)).Times(1).WillOnce(DoAll(SetArgReferee<0>(r), Return(true)));
   }
   EXPECT_CALL(buffer, pop(_)).Times(1).WillOnce(Return(false));
 
-  EXPECT_TRUE(msg.deserialize(buffer));
+  EXPECT_EQ(::EmbeddedProto::Error::NO_ERRORS, msg.deserialize(buffer));
 
   EXPECT_EQ(1.0F, msg.get_u());
   EXPECT_EQ(1, msg.get_nested_a().get_x());
@@ -219,23 +227,28 @@ TEST(NestedMessage, deserialize_nested_in_nested_max)
   ::message_c msg;
   Mocks::ReadBufferMock buffer;
 
+
+  static constexpr uint32_t SIZE = 41;
+
+  ON_CALL(buffer, get_size()).WillByDefault(Return(SIZE));
+
   // Test if a double nested message can be deserialized with values set to maximum.
 
-  uint8_t referee[] = { 0x0A, 0x27, // tag and size of nested b
-                        0x09, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0x7F, // u
-                        0x12, 0x16, // tag and size of nested a
-                        0x08, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, // x
-                        0x15, 0xFF, 0xFF, 0x7F, 0x7F, // y
-                        0x18, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, // z
-                        // And back to the parent message with field v.
-                        0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0x07};
+  uint8_t referee[SIZE] = { 0x0A, 0x27, // tag and size of nested b
+                            0x09, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0x7F, // u
+                            0x12, 0x16, // tag and size of nested a
+                            0x08, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, // x
+                            0x15, 0xFF, 0xFF, 0x7F, 0x7F, // y
+                            0x18, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, // z
+                            // And back to the parent message with field v.
+                            0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0x07};
 
   for(auto r: referee) {
     EXPECT_CALL(buffer, pop(_)).Times(1).WillOnce(DoAll(SetArgReferee<0>(r), Return(true)));
   }
   EXPECT_CALL(buffer, pop(_)).Times(1).WillOnce(Return(false));
 
-  EXPECT_TRUE(msg.deserialize(buffer));
+  EXPECT_EQ(::EmbeddedProto::Error::NO_ERRORS, msg.deserialize(buffer));
 
   EXPECT_EQ(std::numeric_limits<double>::max(), msg.get_nested_b().get_u());
   EXPECT_EQ(std::numeric_limits<int32_t>::max(), msg.get_nested_b().get_nested_a().get_x());

+ 147 - 0
test/test_ReadBufferSection.cpp

@@ -0,0 +1,147 @@
+/*
+ *  Copyright (C) 2020 Embedded AMS B.V. - All Rights Reserved
+ *
+ *  This file is part of Embedded Proto.
+ *
+ *  Embedded Proto is open source software: you can redistribute it and/or 
+ *  modify it under the terms of the GNU General Public License as published 
+ *  by the Free Software Foundation, version 3 of the license.
+ *
+ *  Embedded Proto  is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Embedded Proto. If not, see <https://www.gnu.org/licenses/>.
+ *
+ *  For commercial and closed source application please visit:
+ *  <https://EmbeddedProto.com/license/>.
+ *
+ *  Embedded AMS B.V.
+ *  Info:
+ *    info at EmbeddedProto dot com
+ *
+ *  Postal address:
+ *    Johan Huizingalaan 763a
+ *    1066 VH, Amsterdam
+ *    the Netherlands
+ */
+
+#include <gtest/gtest.h>
+
+#include <ReadBufferSection.h>
+
+#include "mock/ReadBufferMock.h"
+
+using ::testing::_;
+using ::testing::InSequence;
+using ::testing::Return;
+using ::testing::SetArgReferee;
+
+
+namespace test_EmbeddedAMS_ReadBufferSection
+{
+
+TEST(ReadBufferSection, construction) 
+{
+  Mocks::ReadBufferMock read_buffer_mock;
+  EXPECT_CALL(read_buffer_mock, get_size()).WillRepeatedly(Return(99));
+
+  EmbeddedProto::ReadBufferSection read_buffer_section(read_buffer_mock, 1);
+  EXPECT_EQ(1, read_buffer_section.get_max_size());
+  EXPECT_EQ(1, read_buffer_section.get_size());
+}
+
+TEST(ReadBufferSection, construction_limited) 
+{
+  Mocks::ReadBufferMock read_buffer_mock;
+  EXPECT_CALL(read_buffer_mock, get_size()).WillRepeatedly(Return(1));
+
+  EmbeddedProto::ReadBufferSection read_buffer_section(read_buffer_mock, 2);
+  EXPECT_EQ(1, read_buffer_section.get_max_size());
+  EXPECT_EQ(1, read_buffer_section.get_size());
+}
+
+TEST(ReadBufferSection, peek) 
+{
+  Mocks::ReadBufferMock read_buffer_mock;
+  EXPECT_CALL(read_buffer_mock, get_size()).WillRepeatedly(Return(1));
+  EXPECT_CALL(read_buffer_mock, peek(_)).WillOnce(DoAll(SetArgReferee<0>(1), Return(true)));
+
+  EmbeddedProto::ReadBufferSection read_buffer_section(read_buffer_mock, 1);
+  
+  uint8_t byte = 0;
+  EXPECT_TRUE(read_buffer_section.peek(byte));
+  EXPECT_EQ(1, byte);
+}
+
+TEST(ReadBufferSection, advance) 
+{
+  InSequence s;
+
+  Mocks::ReadBufferMock read_buffer_mock;
+  EXPECT_CALL(read_buffer_mock, get_size()).Times(2).WillRepeatedly(Return(3));
+  EXPECT_CALL(read_buffer_mock, advance());
+  EXPECT_CALL(read_buffer_mock, advance());
+
+  EmbeddedProto::ReadBufferSection read_buffer_section(read_buffer_mock, 2);
+  EXPECT_EQ(2, read_buffer_section.get_max_size());
+  EXPECT_EQ(2, read_buffer_section.get_size());
+
+  read_buffer_section.advance();
+  EXPECT_EQ(1, read_buffer_section.get_size());  
+
+  read_buffer_section.advance();
+  EXPECT_EQ(0, read_buffer_section.get_size());  
+
+  // One more advance should still be zero.
+  read_buffer_section.advance();
+  EXPECT_EQ(0, read_buffer_section.get_size());
+
+}
+
+TEST(ReadBufferSection, advance_n) 
+{
+  InSequence s;
+
+  Mocks::ReadBufferMock read_buffer_mock;
+  EXPECT_CALL(read_buffer_mock, get_size()).Times(2).WillRepeatedly(Return(3));
+  EXPECT_CALL(read_buffer_mock, advance(2));
+  EXPECT_CALL(read_buffer_mock, advance(1));
+
+  EmbeddedProto::ReadBufferSection read_buffer_section(read_buffer_mock, 3);
+  EXPECT_EQ(3, read_buffer_section.get_max_size());
+  EXPECT_EQ(3, read_buffer_section.get_size());
+
+  read_buffer_section.advance(2);
+  EXPECT_EQ(1, read_buffer_section.get_size());  
+
+  // We should not advance beond the max size.
+  read_buffer_section.advance(2);
+  EXPECT_EQ(0, read_buffer_section.get_size()); 
+}
+
+TEST(ReadBufferSection, pop) 
+{
+  Mocks::ReadBufferMock read_buffer_mock;
+  EXPECT_CALL(read_buffer_mock, get_size()).WillRepeatedly(Return(1));
+  EXPECT_CALL(read_buffer_mock, pop(_)).WillOnce(DoAll(SetArgReferee<0>(1), Return(true)));
+
+  EmbeddedProto::ReadBufferSection read_buffer_section(read_buffer_mock, 1);
+  
+  uint8_t byte = 0;
+  EXPECT_TRUE(read_buffer_section.pop(byte));
+  EXPECT_EQ(1, byte);
+  EXPECT_EQ(0, read_buffer_section.get_size());
+
+  // When attempting to read or peek at more we should not change byte and get a false.
+  byte = 0;
+  EXPECT_FALSE(read_buffer_section.pop(byte));
+  EXPECT_EQ(0, byte);
+  EXPECT_EQ(0, read_buffer_section.get_size());
+  EXPECT_FALSE(read_buffer_section.peek(byte));
+  EXPECT_EQ(0, byte);
+}
+
+} // End of namespace ReadBufferSection

+ 0 - 87
test/test_RepeatedField.cpp

@@ -1,87 +0,0 @@
-/*
- *  Copyright (C) 2020 Embedded AMS B.V. - All Rights Reserved
- *
- *  This file is part of Embedded Proto.
- *
- *  Embedded Proto is open source software: you can redistribute it and/or 
- *  modify it under the terms of the GNU General Public License as published 
- *  by the Free Software Foundation, version 3 of the license.
- *
- *  Embedded Proto  is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with Embedded Proto. If not, see <https://www.gnu.org/licenses/>.
- *
- *  For commercial and closed source application please visit:
- *  <https://EmbeddedProto.com/license/>.
- *
- *  Embedded AMS B.V.
- *  Info:
- *    info at EmbeddedProto dot com
- *
- *  Postal adress:
- *    Johan Huizingalaan 763a
- *    1066 VH, Amsterdam
- *    the Netherlands
- */
-
-#include <gtest/gtest.h>
-
-#include <Fields.h>
-#include <RepeatedField.h>
-
-namespace test_EmbeddedAMS_RepeatedField
-{
-
-TEST(RepeatedField, construction) 
-{
-  static constexpr uint32_t SIZE = 3;
-  EmbeddedProto::RepeatedFieldSize<::EmbeddedProto::uint32, SIZE> x;
-}
-
-TEST(RepeatedField, size_uint32_t) 
-{  
-  static constexpr uint32_t SIZE = 3;
-  EmbeddedProto::RepeatedFieldSize<::EmbeddedProto::uint32, SIZE> x;
-
-  static constexpr int32_t UINT32_SIZE = sizeof(::EmbeddedProto::uint32);
-
-  EXPECT_EQ(0, x.get_size());
-  EXPECT_EQ(SIZE*UINT32_SIZE, x.get_max_size());
-  EXPECT_EQ(0, x.get_length());
-  EXPECT_EQ(SIZE, x.get_max_length());
-
-  x.add(1);
-  x.add(2);
-  EXPECT_EQ(2*UINT32_SIZE, x.get_size());
-  EXPECT_EQ(2, x.get_length());
-
-  x.add(3);
-
-  EXPECT_EQ(SIZE*UINT32_SIZE, x.get_size());
-  EXPECT_EQ(SIZE*UINT32_SIZE, x.get_max_size());
-  EXPECT_EQ(SIZE, x.get_length());
-  EXPECT_EQ(SIZE, x.get_max_length());
-}
-
-TEST(RepeatedField, set) 
-{
-  static constexpr uint32_t SIZE = 3;
-  EmbeddedProto::RepeatedFieldSize<::EmbeddedProto::uint32, SIZE> x;
-
-  // First add a value in the middle and see if we have a size of two.
-  x.set(1, 2);
-  EXPECT_EQ(2, x.get(1));
-  EXPECT_EQ(2, x.get_length());
-
-  x.set(0, 1);
-  EXPECT_EQ(1, x.get(0));
-
-  x.set(2, 3);
-  EXPECT_EQ(3, x.get(2));
-}
-
-} // End namespace test_EmbeddedAMS_RepeatedField

+ 159 - 0
test/test_RepeatedFieldFixedSize.cpp

@@ -0,0 +1,159 @@
+/*
+ *  Copyright (C) 2020 Embedded AMS B.V. - All Rights Reserved
+ *
+ *  This file is part of Embedded Proto.
+ *
+ *  Embedded Proto is open source software: you can redistribute it and/or 
+ *  modify it under the terms of the GNU General Public License as published 
+ *  by the Free Software Foundation, version 3 of the license.
+ *
+ *  Embedded Proto  is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Embedded Proto. If not, see <https://www.gnu.org/licenses/>.
+ *
+ *  For commercial and closed source application please visit:
+ *  <https://EmbeddedProto.com/license/>.
+ *
+ *  Embedded AMS B.V.
+ *  Info:
+ *    info at EmbeddedProto dot com
+ *
+ *  Postal address:
+ *    Johan Huizingalaan 763a
+ *    1066 VH, Amsterdam
+ *    the Netherlands
+ */
+
+#include <gtest/gtest.h>
+
+#include <Fields.h>
+#include <RepeatedFieldFixedSize.h>
+
+namespace test_EmbeddedAMS_RepeatedFieldFixedSize
+{
+
+static constexpr int32_t UINT32_SIZE = sizeof(::EmbeddedProto::uint32);
+
+TEST(RepeatedFieldFixedSize, construction) 
+{
+  static constexpr uint32_t LENGTH = 3;
+  EmbeddedProto::RepeatedFieldFixedSize<::EmbeddedProto::uint32, LENGTH> x;
+}
+
+TEST(RepeatedFieldFixedSize, size_uint32_t) 
+{  
+  static constexpr uint32_t LENGTH = 3;
+  EmbeddedProto::RepeatedFieldFixedSize<::EmbeddedProto::uint32, LENGTH> x;
+
+  auto size = x.get_size();
+  EXPECT_EQ(0, size);
+
+  auto max_size = x.get_max_size();
+  EXPECT_EQ(LENGTH*UINT32_SIZE, max_size);
+
+  auto length = x.get_length();
+  EXPECT_EQ(0, length);
+
+  auto max_length = x.get_max_length();
+  EXPECT_EQ(LENGTH, max_length);
+}
+
+TEST(RepeatedFieldFixedSize, add_data) 
+{  
+  static constexpr uint32_t LENGTH = 3;
+  EmbeddedProto::RepeatedFieldFixedSize<::EmbeddedProto::uint32, LENGTH> x;
+
+  x.add(1);
+  x.add(2);
+  EXPECT_EQ(2*UINT32_SIZE, x.get_size());
+  EXPECT_EQ(2, x.get_length());
+
+  auto result = x.add(3);
+  EXPECT_EQ(EmbeddedProto::Error::NO_ERRORS, result);
+
+  EXPECT_EQ(LENGTH*UINT32_SIZE, x.get_size());
+  EXPECT_EQ(LENGTH*UINT32_SIZE, x.get_max_size());
+  EXPECT_EQ(LENGTH, x.get_length());
+  EXPECT_EQ(LENGTH, x.get_max_length());
+
+  // Check if we can add more than the limit.
+  result = x.add(4);
+  EXPECT_EQ(EmbeddedProto::Error::ARRAY_FULL, result);
+}
+
+TEST(RepeatedFieldFixedSize, get) 
+{  
+  static constexpr uint32_t LENGTH = 3;
+  EmbeddedProto::RepeatedFieldFixedSize<::EmbeddedProto::uint32, LENGTH> x;
+
+  // Get (non-const) should modify the number of items in the array.
+
+  // Set the second element
+  x.get(1) = 1;
+  EXPECT_EQ(2, x.get_length());
+  EXPECT_EQ(0, x.get_const(0));
+  EXPECT_EQ(1, x.get_const(1));
+
+  // When going out of bound the last element should be returned.
+  EXPECT_EQ(0, x.get_const(2));
+  x.get(3) = 3;
+  EXPECT_EQ(3, x.get_const(2));
+  EXPECT_EQ(3, x.get_const(3));
+}
+
+TEST(RepeatedFieldFixedSize, set_data_array) 
+{  
+  static constexpr uint32_t LENGTH = 3;
+  EmbeddedProto::RepeatedFieldFixedSize<::EmbeddedProto::uint32, LENGTH> x;
+
+  EmbeddedProto::uint32 data3[] = {1, 2, 3};
+
+  auto result = x.set_data(&(data3[0]), 3U);
+  EXPECT_EQ(EmbeddedProto::Error::NO_ERRORS, result);  
+
+  EXPECT_EQ(LENGTH*UINT32_SIZE, x.get_size());
+  EXPECT_EQ(LENGTH*UINT32_SIZE, x.get_max_size());
+  EXPECT_EQ(LENGTH, x.get_length());
+  EXPECT_EQ(LENGTH, x.get_max_length());
+
+  // Check if we can add more than the limit.
+  EmbeddedProto::uint32 data4[] = {1, 2, 3, 4};
+  result = x.set_data(&(data4[0]), 4U);
+  EXPECT_EQ(EmbeddedProto::Error::ARRAY_FULL, result);
+}
+
+TEST(RepeatedFieldFixedSize, set_element) 
+{
+  static constexpr uint32_t LENGTH = 3;
+  EmbeddedProto::RepeatedFieldFixedSize<::EmbeddedProto::uint32, LENGTH> x;
+
+  // First add a value in the middle and see if we have a size of two.
+  x.set(1, 2);
+  EXPECT_EQ(2, x.get_const(1));
+  EXPECT_EQ(2, x.get_length());
+
+  x.set(0, 1);
+  EXPECT_EQ(1, x.get_const(0));
+
+  x.set(2, 3);
+  EXPECT_EQ(3, x.get_const(2));
+}
+
+TEST(RepeatedFieldFixedSize, clear) 
+{
+  static constexpr uint32_t LENGTH = 3;
+  EmbeddedProto::RepeatedFieldFixedSize<::EmbeddedProto::uint32, LENGTH> x;
+  x.add(1);
+  x.add(2);
+  x.clear();
+  EXPECT_EQ(0U, x.get_const(0));
+  EXPECT_EQ(0U, x.get_const(1));
+  EXPECT_EQ(0U, x.get_length());
+}
+
+
+} // End namespace test_EmbeddedAMS_RepeatedField

+ 62 - 31
test/test_RepeatedFieldMessage.cpp

@@ -22,7 +22,7 @@
  *  Info:
  *    info at EmbeddedProto dot com
  *
- *  Postal adress:
+ *  Postal address:
  *    Johan Huizingalaan 763a
  *    1066 VH, Amsterdam
  *    the Netherlands
@@ -65,7 +65,7 @@ TEST(RepeatedFieldMessage, serialize_empty_fields)
   EXPECT_CALL(buffer, push(_,_)).Times(0);
   EXPECT_CALL(buffer, get_available_size()).WillRepeatedly(Return(99));
 
-  EXPECT_TRUE(msg.serialize(buffer));
+  EXPECT_EQ(::EmbeddedProto::Error::NO_ERRORS, msg.serialize(buffer));
 
   EXPECT_EQ(0, msg.serialized_size());
 }
@@ -79,7 +79,7 @@ TEST(RepeatedFieldMessage, serialize_empty_message)
   EXPECT_CALL(buffer, push(_,_)).Times(0);
   EXPECT_CALL(buffer, get_available_size()).WillRepeatedly(Return(99));
 
-  EXPECT_TRUE(msg.serialize(buffer));
+  EXPECT_EQ(::EmbeddedProto::Error::NO_ERRORS, msg.serialize(buffer));
 
   EXPECT_EQ(0, msg.serialized_size());
 }
@@ -104,7 +104,7 @@ TEST(RepeatedFieldMessage, serialize_array_zero_fields)
     EXPECT_CALL(buffer, push(e)).Times(1).WillOnce(Return(true));
   }
 
-  EXPECT_TRUE(msg.serialize(buffer));
+  EXPECT_EQ(::EmbeddedProto::Error::NO_ERRORS, msg.serialize(buffer));
 }
 
 TEST(RepeatedFieldMessage, serialize_array_zero_messages)
@@ -133,7 +133,7 @@ TEST(RepeatedFieldMessage, serialize_array_zero_messages)
   EXPECT_CALL(buffer, push(0x12)).Times(1).WillOnce(Return(true));
   EXPECT_CALL(buffer, push(0x00)).Times(1).WillOnce(Return(true));
 
-  EXPECT_TRUE(msg.serialize(buffer));
+  EXPECT_EQ(::EmbeddedProto::Error::NO_ERRORS, msg.serialize(buffer));
 }
 
 TEST(RepeatedFieldMessage, serialize_array_zero_one_zero)
@@ -155,7 +155,7 @@ TEST(RepeatedFieldMessage, serialize_array_zero_one_zero)
     EXPECT_CALL(buffer, push(e)).Times(1).WillOnce(Return(true));
   }
 
-  EXPECT_TRUE(msg.serialize(buffer));
+  EXPECT_EQ(::EmbeddedProto::Error::NO_ERRORS, msg.serialize(buffer));
 }
 
 TEST(RepeatedFieldMessage, serialize_array_zero_one_zero_messages)
@@ -194,7 +194,7 @@ TEST(RepeatedFieldMessage, serialize_array_zero_one_zero_messages)
   EXPECT_CALL(buffer, push(0x12)).Times(1).WillOnce(Return(true));
   EXPECT_CALL(buffer, push(0x00)).Times(1).WillOnce(Return(true));
 
-  EXPECT_TRUE(msg.serialize(buffer));
+  EXPECT_EQ(::EmbeddedProto::Error::NO_ERRORS, msg.serialize(buffer));
 }
 
 TEST(RepeatedFieldMessage, serialize_array_one)
@@ -216,7 +216,7 @@ TEST(RepeatedFieldMessage, serialize_array_one)
     EXPECT_CALL(buffer, push(e)).Times(1).WillOnce(Return(true));
   }
 
-  EXPECT_TRUE(msg.serialize(buffer));
+  EXPECT_EQ(::EmbeddedProto::Error::NO_ERRORS, msg.serialize(buffer));
 }
 
 
@@ -240,7 +240,7 @@ TEST(RepeatedFieldMessage, serialize_array_max)
     EXPECT_CALL(buffer, push(e)).Times(1).WillOnce(Return(true));
   }
 
-  EXPECT_TRUE(msg.serialize(buffer));
+  EXPECT_EQ(::EmbeddedProto::Error::NO_ERRORS, msg.serialize(buffer));
 }
 
 
@@ -273,7 +273,7 @@ TEST(RepeatedFieldMessage, serialize_one)
     EXPECT_CALL(buffer, push(e)).Times(1).WillOnce(Return(true));
   }
 
-  EXPECT_TRUE(msg.serialize(buffer));
+  EXPECT_EQ(::EmbeddedProto::Error::NO_ERRORS, msg.serialize(buffer));
 }
 
 
@@ -305,7 +305,22 @@ TEST(RepeatedFieldMessage, serialize_max)
     EXPECT_CALL(buffer, push(e)).Times(1).WillOnce(Return(true));
   }
 
-  EXPECT_TRUE(msg.serialize(buffer));
+  EXPECT_EQ(::EmbeddedProto::Error::NO_ERRORS, msg.serialize(buffer));
+}
+
+TEST(RepeatedFieldMessage, serialize_fault_buffer_full)
+{
+  Mocks::WriteBufferMock buffer;
+
+  repeated_fields<Y_SIZE> msg;
+  msg.add_y(1);
+  msg.add_y(1);
+  msg.add_y(1);                 
+  
+  // Need 3 bytes but got only 2.
+  EXPECT_CALL(buffer, get_available_size()).Times(1).WillOnce(Return(2));
+
+  EXPECT_EQ(::EmbeddedProto::Error::BUFFER_FULL, msg.serialize(buffer));
 }
 
 TEST(RepeatedFieldMessage, deserialize_empty_array) 
@@ -316,7 +331,7 @@ TEST(RepeatedFieldMessage, deserialize_empty_array)
   EXPECT_CALL(buffer, pop(_)).WillRepeatedly(Return(false));
   EXPECT_CALL(buffer, get_size()).WillRepeatedly(Return(0));
 
-  EXPECT_TRUE(msg.deserialize(buffer));
+  EXPECT_EQ(::EmbeddedProto::Error::NO_ERRORS, msg.deserialize(buffer));
 
 }
 
@@ -328,7 +343,7 @@ TEST(RepeatedFieldMessage, deserialize_empty_message_array)
   EXPECT_CALL(buffer, pop(_)).WillRepeatedly(Return(false));
   EXPECT_CALL(buffer, get_size()).WillRepeatedly(Return(0));
 
-  EXPECT_TRUE(msg.deserialize(buffer));
+  EXPECT_EQ(::EmbeddedProto::Error::NO_ERRORS, msg.deserialize(buffer));
 }
 
 TEST(RepeatedFieldMessage, deserialize_one) 
@@ -338,9 +353,13 @@ TEST(RepeatedFieldMessage, deserialize_one)
   repeated_fields<Y_SIZE> msg;
   Mocks::ReadBufferMock buffer;
 
-  uint8_t referee[] = {0x08, 0x01, // x
-                       0x12, 0x03, 0x01, 0x01, 0x01, // y
-                       0x18, 0x01}; // z 
+  static constexpr uint32_t SIZE = 9;
+
+  ON_CALL(buffer, get_size()).WillByDefault(Return(SIZE));
+
+  uint8_t referee[SIZE] = { 0x08, 0x01, // x
+                            0x12, 0x03, 0x01, 0x01, 0x01, // y
+                            0x18, 0x01}; // z 
 
   for(auto r: referee) 
   {
@@ -348,7 +367,7 @@ TEST(RepeatedFieldMessage, deserialize_one)
   }
   EXPECT_CALL(buffer, pop(_)).Times(1).WillOnce(Return(false));
 
-  EXPECT_TRUE(msg.deserialize(buffer));
+  EXPECT_EQ(::EmbeddedProto::Error::NO_ERRORS, msg.deserialize(buffer));
 
   EXPECT_EQ(1, msg.get_x());
   EXPECT_EQ(3, msg.get_y().get_length());
@@ -366,9 +385,13 @@ TEST(RepeatedFieldMessage, deserialize_one_message_array)
   repeated_message<Y_SIZE> msg;
   Mocks::ReadBufferMock buffer;
 
-  uint8_t referee[] = {0x08, 0x01, // x
-                       0x12, 0x00, 0x12, 0x04, 0x08, 0x01, 0x10, 0x01, 0x12, 0x00, // y
-                       0x18, 0x01}; // z 
+  static constexpr uint32_t SIZE = 15;
+
+  ON_CALL(buffer, get_size()).WillByDefault(Return(SIZE));
+
+  uint8_t referee[SIZE] = { 0x08, 0x01, // x
+                            0x12, 0x00, 0x12, 0x04, 0x08, 0x01, 0x10, 0x01, 0x12, 0x00, // y
+                            0x18, 0x01}; // z 
 
   for(auto r: referee) 
   {
@@ -376,7 +399,7 @@ TEST(RepeatedFieldMessage, deserialize_one_message_array)
   }
   EXPECT_CALL(buffer, pop(_)).Times(1).WillOnce(Return(false));
 
-  EXPECT_TRUE(msg.deserialize(buffer));
+  EXPECT_EQ(::EmbeddedProto::Error::NO_ERRORS, msg.deserialize(buffer));
 
   EXPECT_EQ(1, msg.get_a());
   EXPECT_EQ(3, msg.get_b().get_length());
@@ -399,11 +422,15 @@ TEST(RepeatedFieldMessage, deserialize_mixed_message_array)
   repeated_message<Y_SIZE> msg;
   Mocks::ReadBufferMock buffer;
 
-  uint8_t referee[] = {0x12, 0x00, // y[0]
-                       0x08, 0x01, // x
-                       0x12, 0x04, 0x08, 0x01, 0x10, 0x01, // y[1]
-                       0x18, 0x01, // z
-                       0x12, 0x00, }; // y[2] 
+  static constexpr uint32_t SIZE = 14;
+
+  ON_CALL(buffer, get_size()).WillByDefault(Return(SIZE));
+
+  uint8_t referee[SIZE] = { 0x12, 0x00, // y[0]
+                            0x08, 0x01, // x
+                            0x12, 0x04, 0x08, 0x01, 0x10, 0x01, // y[1]
+                            0x18, 0x01, // z
+                            0x12, 0x00, }; // y[2] 
 
   for(auto r: referee) 
   {
@@ -411,7 +438,7 @@ TEST(RepeatedFieldMessage, deserialize_mixed_message_array)
   }
   EXPECT_CALL(buffer, pop(_)).Times(1).WillOnce(Return(false));
 
-  EXPECT_TRUE(msg.deserialize(buffer));
+  EXPECT_EQ(::EmbeddedProto::Error::NO_ERRORS, msg.deserialize(buffer));
 
   EXPECT_EQ(1, msg.get_a());
   EXPECT_EQ(3, msg.get_b().get_length());
@@ -431,9 +458,13 @@ TEST(RepeatedFieldMessage, deserialize_max)
   repeated_fields<Y_SIZE> msg;
   Mocks::ReadBufferMock buffer;
 
-  uint8_t referee[] = {0x08, 0xff, 0xff, 0xff, 0xff, 0x0f,  // x
-                       0x12, 0x0f, 0xff, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0xff, 0x0f, // y
-                       0x18, 0xff, 0xff, 0xff, 0xff, 0x0f}; // z
+  static constexpr uint32_t SIZE = 29;
+
+  ON_CALL(buffer, get_size()).WillByDefault(Return(SIZE));
+
+  uint8_t referee[SIZE] = { 0x08, 0xff, 0xff, 0xff, 0xff, 0x0f,  // x
+                            0x12, 0x0f, 0xff, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0xff, 0x0f, // y
+                            0x18, 0xff, 0xff, 0xff, 0xff, 0x0f}; // z
 
   for(auto r: referee) 
   {
@@ -441,7 +472,7 @@ TEST(RepeatedFieldMessage, deserialize_max)
   }
   EXPECT_CALL(buffer, pop(_)).Times(1).WillOnce(Return(false));
 
-  EXPECT_TRUE(msg.deserialize(buffer));
+  EXPECT_EQ(::EmbeddedProto::Error::NO_ERRORS, msg.deserialize(buffer));
 
   EXPECT_EQ(std::numeric_limits<uint32_t>::max(), msg.get_x());
   EXPECT_EQ(3, msg.get_y().get_length());

+ 71 - 11
test/test_SimpleTypes.cpp

@@ -22,7 +22,7 @@
  *  Info:
  *    info at EmbeddedProto dot com
  *
- *  Postal adress:
+ *  Postal address:
  *    Johan Huizingalaan 763a
  *    1066 VH, Amsterdam
  *    the Netherlands
@@ -58,7 +58,7 @@ TEST(SimpleTypes, zero)
   EXPECT_CALL(buffer, push(_)).Times(0);
   EXPECT_CALL(buffer, push(_,_)).Times(0);
 
-  EXPECT_TRUE(msg.serialize(buffer));
+  EXPECT_EQ(::EmbeddedProto::Error::NO_ERRORS, msg.serialize(buffer));
 
   EXPECT_EQ(0, msg.serialized_size());
 }
@@ -107,7 +107,7 @@ TEST(SimpleTypes, serialize_one)
     EXPECT_CALL(buffer, push(e)).Times(1).WillOnce(Return(true));
   }
 
-  EXPECT_TRUE(msg.serialize(buffer));
+  EXPECT_EQ(::EmbeddedProto::Error::NO_ERRORS, msg.serialize(buffer));
 
   EXPECT_EQ(58, msg.serialized_size());
 }
@@ -156,7 +156,7 @@ TEST(SimpleTypes, serialize_max)
     EXPECT_CALL(buffer, push(e)).Times(1).WillOnce(Return(true));
   }
 
-  EXPECT_TRUE(msg.serialize(buffer));
+  EXPECT_EQ(::EmbeddedProto::Error::NO_ERRORS, msg.serialize(buffer));
   EXPECT_EQ(100, msg.serialized_size());
 }
 
@@ -197,7 +197,7 @@ TEST(SimpleTypes, serialize_min)
     EXPECT_CALL(buffer, push(e)).Times(1).WillOnce(Return(true));
   }
   
-  EXPECT_TRUE(msg.serialize(buffer));
+  EXPECT_EQ(::EmbeddedProto::Error::NO_ERRORS, msg.serialize(buffer));
   EXPECT_EQ(62, msg.serialized_size());
 }
 
@@ -221,10 +221,32 @@ TEST(SimpleTypes, serialize_smalest_real)
     EXPECT_CALL(buffer, push(e)).Times(1).WillOnce(Return(true));
   }
   
-  EXPECT_TRUE(msg.serialize(buffer));
+  EXPECT_EQ(::EmbeddedProto::Error::NO_ERRORS, msg.serialize(buffer));
   EXPECT_EQ(14, msg.serialized_size());
 }
 
+TEST(SimpleTypes, serialize_fault_buffer_full_varint)
+{
+    InSequence s;
+  
+  // Using a protobuf message and the google protobuf implementation test is serialization is 
+  // correct.
+  ::Test_Simple_Types msg;
+  Mocks::WriteBufferMock buffer;
+
+  // Just set some large value.
+  msg.set_a_uint32(std::numeric_limits<uint32_t>::max());
+
+  // Allow for some bytes to be serialized
+  EXPECT_CALL(buffer, push(_)).Times(1).WillOnce(Return(true));
+  EXPECT_CALL(buffer, push(_)).Times(1).WillOnce(Return(true));  
+  // And then fail
+  EXPECT_CALL(buffer, push(_)).Times(2).WillOnce(Return(false));
+
+  EXPECT_EQ(::EmbeddedProto::Error::BUFFER_FULL, msg.serialize(buffer));
+
+}
+
 TEST(SimpleTypes, deserialize_zero) 
 {
   InSequence s;
@@ -232,7 +254,7 @@ TEST(SimpleTypes, deserialize_zero)
   ::Test_Simple_Types msg;
 
   EXPECT_CALL(buffer, pop(_)).Times(1).WillOnce(Return(false));
-  EXPECT_TRUE(msg.deserialize(buffer));
+  EXPECT_EQ(::EmbeddedProto::Error::NO_ERRORS, msg.deserialize(buffer));
 
   EXPECT_EQ(0, msg.get_a_int32());   
   EXPECT_EQ(0, msg.get_a_int64());     
@@ -279,7 +301,7 @@ TEST(SimpleTypes, deserialize_one)
   }
   EXPECT_CALL(buffer, pop(_)).Times(1).WillOnce(Return(false));
 
-  EXPECT_TRUE(msg.deserialize(buffer));
+  EXPECT_EQ(::EmbeddedProto::Error::NO_ERRORS, msg.deserialize(buffer));
 
   EXPECT_EQ(1, msg.get_a_int32());   
   EXPECT_EQ(1, msg.get_a_int64());     
@@ -326,7 +348,7 @@ TEST(SimpleTypes, deserialize_max)
   }
   EXPECT_CALL(buffer, pop(_)).Times(1).WillOnce(Return(false));
 
-  EXPECT_TRUE(msg.deserialize(buffer));
+  EXPECT_EQ(::EmbeddedProto::Error::NO_ERRORS, msg.deserialize(buffer));
 
   EXPECT_EQ(std::numeric_limits<int32_t>::max(),  msg.get_a_int32());   
   EXPECT_EQ(std::numeric_limits<int64_t>::max(),  msg.get_a_int64());     
@@ -367,7 +389,7 @@ TEST(SimpleTypes, deserialize_min)
   }
   EXPECT_CALL(buffer, pop(_)).Times(1).WillOnce(Return(false));
 
-  EXPECT_TRUE(msg.deserialize(buffer));
+  EXPECT_EQ(::EmbeddedProto::Error::NO_ERRORS, msg.deserialize(buffer));
 
   EXPECT_EQ(std::numeric_limits<int32_t>::min(),  msg.get_a_int32());   
   EXPECT_EQ(std::numeric_limits<int64_t>::min(),  msg.get_a_int64());     
@@ -400,10 +422,48 @@ TEST(SimpleTypes, deserialize_smalest_real)
   }
   EXPECT_CALL(buffer, pop(_)).Times(1).WillOnce(Return(false));
   
-  EXPECT_TRUE(msg.deserialize(buffer));
+  EXPECT_EQ(::EmbeddedProto::Error::NO_ERRORS, msg.deserialize(buffer));
 
   EXPECT_EQ(std::numeric_limits<double>::min(), msg.get_a_double());
   EXPECT_EQ(std::numeric_limits<float>::min(),  msg.get_a_float());
 }
 
+TEST(SimpleTypes, deserialize_fault_end_of_buffer_fixed)
+{
+  InSequence s;
+  Mocks::ReadBufferMock buffer;
+  
+  ON_CALL(buffer, get_size()).WillByDefault(Return(58));
+
+  ::Test_Simple_Types msg;
+
+  uint8_t referee[] = {0x49, 0xFF, 0xFF}; // End half way through a fixed size value.
+
+  for(auto r: referee) {
+    EXPECT_CALL(buffer, pop(_)).Times(1).WillOnce(DoAll(SetArgReferee<0>(r), Return(true)));
+  }
+  EXPECT_CALL(buffer, pop(_)).Times(1).WillOnce(Return(false));
+
+  EXPECT_EQ(::EmbeddedProto::Error::END_OF_BUFFER, msg.deserialize(buffer));
+}
+
+TEST(SimpleTypes, deserialize_fault_end_of_buffer_bool)
+{
+  InSequence s;
+  Mocks::ReadBufferMock buffer;
+  
+  ON_CALL(buffer, get_size()).WillByDefault(Return(58));
+
+  ::Test_Simple_Types msg;
+
+  uint8_t referee[] = {0x38}; // Just the tag of a bool but no data
+
+  for(auto r: referee) {
+    EXPECT_CALL(buffer, pop(_)).Times(1).WillOnce(DoAll(SetArgReferee<0>(r), Return(true)));
+  }
+  EXPECT_CALL(buffer, pop(_)).Times(1).WillOnce(Return(false));
+
+  EXPECT_EQ(::EmbeddedProto::Error::END_OF_BUFFER, msg.deserialize(buffer));
+}
+
 } // End of namespace test_EmbeddedAMS_SimpleTypes

+ 1 - 1
test/test_getters_setters_fields.cpp

@@ -22,7 +22,7 @@
  *  Info:
  *    info at EmbeddedProto dot com
  *
- *  Postal adress:
+ *  Postal address:
  *    Johan Huizingalaan 763a
  *    1066 VH, Amsterdam
  *    the Netherlands

+ 17 - 13
test/test_oneof_fields.cpp

@@ -22,7 +22,7 @@
  *  Info:
  *    info at EmbeddedProto dot com
  *
- *  Postal adress:
+ *  Postal address:
  *    Johan Huizingalaan 763a
  *    1066 VH, Amsterdam
  *    the Netherlands
@@ -60,7 +60,7 @@ TEST(OneofField, serialize_zero)
   EXPECT_CALL(buffer, push(_,_)).Times(0);
   EXPECT_CALL(buffer, get_available_size()).Times(0);
 
-  EXPECT_TRUE(msg.serialize(buffer));
+  EXPECT_EQ(::EmbeddedProto::Error::NO_ERRORS, msg.serialize(buffer));
 }
 
 TEST(OneofField, set_get_clear)
@@ -125,7 +125,7 @@ TEST(OneofField, serialize_ones)
     EXPECT_CALL(buffer, push(e)).Times(1).WillOnce(Return(true));
   }
 
-  EXPECT_TRUE(msg.serialize(buffer));
+  EXPECT_EQ(::EmbeddedProto::Error::NO_ERRORS, msg.serialize(buffer));
 
   // Y
   msg.set_y(1);
@@ -137,7 +137,7 @@ TEST(OneofField, serialize_ones)
     EXPECT_CALL(buffer, push(e)).Times(1).WillOnce(Return(true));
   }
 
-  EXPECT_TRUE(msg.serialize(buffer));
+  EXPECT_EQ(::EmbeddedProto::Error::NO_ERRORS, msg.serialize(buffer));
 
   // z
   msg.set_z(1);
@@ -149,7 +149,7 @@ TEST(OneofField, serialize_ones)
     EXPECT_CALL(buffer, push(e)).Times(1).WillOnce(Return(true));
   }
 
-  EXPECT_TRUE(msg.serialize(buffer));
+  EXPECT_EQ(::EmbeddedProto::Error::NO_ERRORS, msg.serialize(buffer));
 }
 
 TEST(OneofField, serialize_second_oneof)
@@ -173,7 +173,7 @@ TEST(OneofField, serialize_second_oneof)
     EXPECT_CALL(buffer, push(e)).Times(1).WillOnce(Return(true));
   }
 
-  EXPECT_TRUE(msg.serialize(buffer));
+  EXPECT_EQ(::EmbeddedProto::Error::NO_ERRORS, msg.serialize(buffer));
 }
 
 TEST(OneofField, deserialize) 
@@ -192,7 +192,7 @@ TEST(OneofField, deserialize)
   }
   EXPECT_CALL(buffer, pop(_)).Times(1).WillOnce(Return(false));
 
-  EXPECT_TRUE(msg.deserialize(buffer));
+  EXPECT_EQ(::EmbeddedProto::Error::NO_ERRORS, msg.deserialize(buffer));
 
   EXPECT_EQ(1, msg.get_a());
   EXPECT_EQ(1, msg.get_b());
@@ -217,7 +217,7 @@ TEST(OneofField, deserialize_override)
   }
   EXPECT_CALL(buffer, pop(_)).Times(1).WillOnce(Return(false));
 
-  EXPECT_TRUE(msg.deserialize(buffer));
+  EXPECT_EQ(::EmbeddedProto::Error::NO_ERRORS, msg.deserialize(buffer));
 
   EXPECT_EQ(1, msg.get_a());
   EXPECT_EQ(1, msg.get_b());
@@ -235,7 +235,7 @@ TEST(OneofField, deserialize_failure)
   EXPECT_CALL(buffer, pop(_)).Times(1).WillOnce(DoAll(SetArgReferee<0>(0x30), Return(true)));  // y
   EXPECT_CALL(buffer, pop(_)).Times(1).WillOnce(DoAll(SetArgReferee<0>(0x01), Return(false))); // This simulates the fialure.
 
-  EXPECT_FALSE(msg.deserialize(buffer));
+  EXPECT_EQ(::EmbeddedProto::Error::END_OF_BUFFER, msg.deserialize(buffer));
   EXPECT_EQ(message_oneof::id::NOT_SET, msg.get_which_xyz());
 
 }
@@ -257,7 +257,7 @@ TEST(OneofField, deserialize_second_oneof)
   }
   EXPECT_CALL(buffer, pop(_)).Times(1).WillOnce(Return(false));
 
-  EXPECT_TRUE(msg.deserialize(buffer));
+  EXPECT_EQ(::EmbeddedProto::Error::NO_ERRORS, msg.deserialize(buffer));
 
   EXPECT_EQ(1, msg.get_a());
   EXPECT_EQ(1, msg.get_b());
@@ -290,7 +290,7 @@ TEST(OneofField, serialize_oneof_msg)
     EXPECT_CALL(buffer, push(e)).Times(1).WillOnce(Return(true));
   }
 
-  EXPECT_TRUE(msg.serialize(buffer));
+  EXPECT_EQ(::EmbeddedProto::Error::NO_ERRORS, msg.serialize(buffer));
 }
 
 TEST(OneofField, deserialize_oneof_msg) 
@@ -300,13 +300,17 @@ TEST(OneofField, deserialize_oneof_msg)
   message_oneof msg;
   Mocks::ReadBufferMock buffer;
 
-  uint8_t referee[] = {0xaa, 0x01, 0x07, 0x08, 0x01, 0x10, 0x16, 0x18, 0xcd, 0x02};
+  static constexpr uint32_t SIZE = 10;
+
+  ON_CALL(buffer, get_size()).WillByDefault(Return(SIZE));
+
+  uint8_t referee[SIZE] = {0xaa, 0x01, 0x07, 0x08, 0x01, 0x10, 0x16, 0x18, 0xcd, 0x02};
     for(auto r: referee) {
     EXPECT_CALL(buffer, pop(_)).Times(1).WillOnce(DoAll(SetArgReferee<0>(r), Return(true)));
   }
   EXPECT_CALL(buffer, pop(_)).Times(1).WillOnce(Return(false));
 
-  EXPECT_TRUE(msg.deserialize(buffer));
+  EXPECT_EQ(::EmbeddedProto::Error::NO_ERRORS, msg.deserialize(buffer));
 
   EXPECT_EQ(message_oneof::id::MSG_DEF, msg.get_which_message());
   EXPECT_EQ(1, msg.get_msg_DEF().get_varD());

+ 365 - 0
test/test_string_bytes.cpp

@@ -0,0 +1,365 @@
+/*
+ *  Copyright (C) 2020 Embedded AMS B.V. - All Rights Reserved
+ *
+ *  This file is part of Embedded Proto.
+ *
+ *  Embedded Proto is open source software: you can redistribute it and/or 
+ *  modify it under the terms of the GNU General Public License as published 
+ *  by the Free Software Foundation, version 3 of the license.
+ *
+ *  Embedded Proto  is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Embedded Proto. If not, see <https://www.gnu.org/licenses/>.
+ *
+ *  For commercial and closed source application please visit:
+ *  <https://EmbeddedProto.com/license/>.
+ *
+ *  Embedded AMS B.V.
+ *  Info:
+ *    info at EmbeddedProto dot com
+ *
+ *  Postal address:
+ *    Johan Huizingalaan 763a
+ *    1066 VH, Amsterdam
+ *    the Netherlands
+ */
+
+#include "gtest/gtest.h"
+#include "gmock/gmock.h"
+
+#include <WireFormatter.h>
+#include <ReadBufferMock.h>
+#include <WriteBufferMock.h>
+
+#include <cstdint>    
+#include <limits> 
+
+// EAMS message definitions
+#include <string_bytes.h>
+
+using ::testing::_;
+using ::testing::InSequence;
+using ::testing::Return;
+using ::testing::SetArgReferee;
+using ::testing::ElementsAre;
+
+namespace test_EmbeddedAMS_string_bytes
+{
+
+TEST(FieldString, clear)
+{
+  text<10> msg;  
+  
+  // Clear the field specific.
+  msg.mutable_txt() = "Foo Bar";
+  EXPECT_EQ(7, msg.txt().get_length());
+  msg.clear_txt();
+  EXPECT_EQ(0, msg.txt().get_length());
+
+  // Clear the whole message.
+  msg.mutable_txt() = "Foo Bar";
+  msg.clear();
+  EXPECT_EQ(0, msg.txt().get_length());
+}
+
+TEST(FieldString, serialize) 
+{
+  InSequence s;
+
+  text<10> msg;
+  Mocks::WriteBufferMock buffer;
+
+  msg.mutable_txt() = "Foo bar";
+
+  EXPECT_CALL(buffer, get_available_size()).Times(1).WillOnce(Return(17));
+
+  uint8_t expected[] = {0x0a, 0x07};
+  for(auto e : expected) 
+  {
+    EXPECT_CALL(buffer, push(e)).Times(1).WillOnce(Return(true));
+  }
+  EXPECT_CALL(buffer, push(_, 7)).Times(1).WillOnce(Return(true));
+
+
+  EXPECT_EQ(::EmbeddedProto::Error::NO_ERRORS, msg.serialize(buffer));
+  EXPECT_EQ(10, msg.txt().get_max_length());
+}
+
+TEST(FieldString, deserialize) 
+{
+  InSequence s;
+
+  text<10> msg;
+  Mocks::ReadBufferMock buffer;
+
+  uint8_t referee[] = {0x0a, 0x07, 0x46, 0x6f, 0x6f, 0x20, 0x62, 0x61, 0x72};
+
+  for(auto r: referee) 
+  {
+    EXPECT_CALL(buffer, pop(_)).Times(1).WillOnce(DoAll(SetArgReferee<0>(r), Return(true)));
+  }
+  EXPECT_CALL(buffer, pop(_)).Times(1).WillOnce(Return(false));
+
+
+  EXPECT_EQ(::EmbeddedProto::Error::NO_ERRORS, msg.deserialize(buffer));
+  EXPECT_EQ(7, msg.txt().get_length());
+  EXPECT_STREQ(msg.get_txt(), "Foo bar");
+}
+
+TEST(FieldString, deserialize_error_invalid_wiretype) 
+{
+  InSequence s;
+
+  text<10> msg;
+  Mocks::ReadBufferMock buffer;
+
+  // The first byte is an invalid wiretype
+  EXPECT_CALL(buffer, pop(_)).Times(1).WillOnce(DoAll(SetArgReferee<0>(0x09), Return(true)));
+  EXPECT_EQ(::EmbeddedProto::Error::INVALID_WIRETYPE, msg.deserialize(buffer));
+  EXPECT_EQ(0, msg.txt().get_length());
+}
+
+TEST(FieldString, oneof_serialize)
+{
+  InSequence s;
+
+  string_or_bytes<10, 10> msg;
+  Mocks::WriteBufferMock buffer;
+
+  msg.mutable_txt() = "Foo bar";
+
+  EXPECT_CALL(buffer, get_available_size()).Times(1).WillOnce(Return(99));
+
+  uint8_t expected[] = {0x0a, 0x07};
+  for(auto e : expected) 
+  {
+    EXPECT_CALL(buffer, push(e)).Times(1).WillOnce(Return(true));
+  }
+  EXPECT_CALL(buffer, push(_, 7)).Times(1).WillOnce(Return(true));
+
+
+  EXPECT_EQ(::EmbeddedProto::Error::NO_ERRORS, msg.serialize(buffer));
+  EXPECT_EQ(10, msg.txt().get_max_length());
+}
+
+TEST(FieldString, oneof_deserialize) 
+{
+  InSequence s;
+
+  string_or_bytes<10, 10> msg;
+  Mocks::ReadBufferMock buffer;
+
+  uint8_t referee[] = {0x0a, 0x07, 0x46, 0x6f, 0x6f, 0x20, 0x62, 0x61, 0x72};
+
+  for(auto r: referee) 
+  {
+    EXPECT_CALL(buffer, pop(_)).Times(1).WillOnce(DoAll(SetArgReferee<0>(r), Return(true)));
+  }
+  EXPECT_CALL(buffer, pop(_)).Times(1).WillOnce(Return(false));
+
+
+  EXPECT_EQ(::EmbeddedProto::Error::NO_ERRORS, msg.deserialize(buffer));
+  EXPECT_EQ(7, msg.txt().get_length());
+  EXPECT_STREQ(msg.get_txt(), "Foo bar");
+}
+
+TEST(FieldBytes, set_get)
+{
+  raw_bytes<10> msg;
+  msg.mutable_b()[0] = 1;
+  EXPECT_EQ(1, msg.b().get_length());
+  EXPECT_EQ(1, msg.b().get_const(0));
+
+  msg.clear();
+  EXPECT_EQ(0, msg.b().get_length());
+  EXPECT_EQ(0, msg.b().get_const(0));
+
+  msg.mutable_b()[1] = 2;
+  EXPECT_EQ(2, msg.b().get_length());
+  EXPECT_EQ(0, msg.b().get_const(0));
+  EXPECT_EQ(2, msg.b().get_const(1));
+
+  // Check index out of bound will return the last element.
+  msg.mutable_b()[10] = 11; // max index should be 9.
+  // The last element should be changed
+  EXPECT_EQ(10, msg.b().get_length());
+  EXPECT_EQ(11, msg.b().get_const(9));
+  // Check this function out of bound aswell.
+  EXPECT_EQ(11, msg.b().get_const(10));
+
+  // Try to set more bytes compared to what will fit.
+  uint8_t big_array[11] = {0};
+  big_array[10] = 11;
+  EXPECT_EQ(::EmbeddedProto::Error::ARRAY_FULL, msg.mutable_b().set(big_array, 11));
+}
+
+TEST(FieldBytes, clear)
+{
+  raw_bytes<10> msg;  
+  
+  const uint8_t array[2] = {1 ,2};
+
+  // Clear the field specific.
+  msg.mutable_b().set(array, 2);
+  EXPECT_EQ(2, msg.b().get_length());
+  msg.clear_b();
+  EXPECT_EQ(0, msg.b().get_length());
+
+  // Clear the whole message.
+  msg.mutable_b().set(array, 2);
+  msg.clear();
+  EXPECT_EQ(0, msg.b().get_length());
+}
+
+TEST(FieldBytes, serialize)
+{
+  InSequence s;
+
+  raw_bytes<10> msg;
+  Mocks::WriteBufferMock buffer;
+
+  uint8_t bytes[] = {1u, 2u, 3u, 0u};
+  msg.mutable_b().set(bytes, 4);
+
+  EXPECT_CALL(buffer, get_available_size()).Times(1).WillOnce(Return(17));
+
+  uint8_t expected[] = {0x0a, 0x04};
+  for(auto e : expected) 
+  {
+    EXPECT_CALL(buffer, push(e)).Times(1).WillOnce(Return(true));
+  }
+  EXPECT_CALL(buffer, push(_, 4)).Times(1).WillOnce(Return(true));
+
+  EXPECT_EQ(::EmbeddedProto::Error::NO_ERRORS, msg.serialize(buffer));
+  EXPECT_EQ(10, msg.b().get_max_length());
+}
+
+TEST(FieldBytes, deserialize) 
+{
+  InSequence s;
+
+  raw_bytes<10> msg;
+  Mocks::ReadBufferMock buffer;
+
+  uint8_t referee[] = {0x0a, 0x04, 0x01, 0x02, 0x03, 0x00};
+
+  for(auto r: referee) 
+  {
+    EXPECT_CALL(buffer, pop(_)).Times(1).WillOnce(DoAll(SetArgReferee<0>(r), Return(true)));
+  }
+  EXPECT_CALL(buffer, pop(_)).Times(1).WillOnce(Return(false));
+
+
+  EXPECT_EQ(::EmbeddedProto::Error::NO_ERRORS, msg.deserialize(buffer));
+  EXPECT_EQ(4, msg.b().get_length());
+  EXPECT_EQ(1, msg.b()[0]);
+  EXPECT_EQ(2, msg.b()[1]);
+  EXPECT_EQ(3, msg.b()[2]);
+  EXPECT_EQ(0, msg.b()[3]);
+}
+
+TEST(FieldBytes, deserialize_error_invalid_wiretype) 
+{
+  InSequence s;
+
+  raw_bytes<10> msg;
+  Mocks::ReadBufferMock buffer;
+
+  // The first byte is an invalid wiretype
+  EXPECT_CALL(buffer, pop(_)).Times(1).WillOnce(DoAll(SetArgReferee<0>(0x09), Return(true)));
+  EXPECT_EQ(::EmbeddedProto::Error::INVALID_WIRETYPE, msg.deserialize(buffer));
+  EXPECT_EQ(0, msg.b().get_length());
+}
+
+TEST(FieldBytes, oneof_set_get)
+{
+  string_or_bytes<10, 10> msg;  
+  msg.mutable_txt() = "Foo Bar";
+  
+  auto id = string_or_bytes<10, 10>::id::TXT;
+  EXPECT_EQ(id, msg.get_which_s_or_b());
+  EXPECT_STREQ(msg.get_txt(), "Foo Bar");
+
+  // Switch to the array
+  uint8_t array[] = {1, 2, 3, 4, 5};
+  msg.mutable_b().set(array, 5);
+
+  id = string_or_bytes<10, 10>::id::B;
+  EXPECT_EQ(id, msg.get_which_s_or_b());
+  for(uint8_t i = 0; i < 5; ++i)
+  {
+    EXPECT_EQ(i+1, msg.get_b()[i]);
+  }
+}
+
+TEST(FieldBytes, oneof_clear)
+{
+  raw_bytes<10> msg;  
+  
+  const uint8_t array[2] = {1 ,2};
+
+  // Clear the field specific.
+  msg.mutable_b().set(array, 2);
+  EXPECT_EQ(2, msg.b().get_length());
+  msg.clear_b();
+  EXPECT_EQ(0, msg.b().get_length());
+
+  // Clear the whole message.
+  msg.mutable_b().set(array, 2);
+  msg.clear();
+  EXPECT_EQ(0, msg.b().get_length());
+}
+
+TEST(FieldBytes, oneof_serialize)
+{
+  InSequence s;
+
+  string_or_bytes<10, 10> msg;
+  Mocks::WriteBufferMock buffer;
+
+  uint8_t bytes[] = {1u, 2u, 3u, 0u};
+  msg.mutable_b().set(bytes, 4);
+
+  EXPECT_CALL(buffer, get_available_size()).Times(1).WillOnce(Return(17));
+
+  uint8_t expected[] = {0x12, 0x04};
+  for(auto e : expected) 
+  {
+    EXPECT_CALL(buffer, push(e)).Times(1).WillOnce(Return(true));
+  }
+  EXPECT_CALL(buffer, push(_, 4)).Times(1).WillOnce(Return(true));
+
+
+  EXPECT_EQ(::EmbeddedProto::Error::NO_ERRORS, msg.serialize(buffer));
+  EXPECT_EQ(10, msg.txt().get_max_length());
+}
+
+TEST(FieldBytes, oneof_deserialize) 
+{
+  InSequence s;
+
+  string_or_bytes<10, 10> msg;
+  Mocks::ReadBufferMock buffer;
+
+  uint8_t referee[] = {0x12, 0x04, 0x01, 0x02, 0x03, 0x00};
+
+  for(auto r: referee) 
+  {
+    EXPECT_CALL(buffer, pop(_)).Times(1).WillOnce(DoAll(SetArgReferee<0>(r), Return(true)));
+  }
+  EXPECT_CALL(buffer, pop(_)).Times(1).WillOnce(Return(false));
+
+
+  EXPECT_EQ(::EmbeddedProto::Error::NO_ERRORS, msg.deserialize(buffer));
+  EXPECT_EQ(4, msg.b().get_length());
+  EXPECT_EQ(1, msg.b()[0]);
+  EXPECT_EQ(2, msg.b()[1]);
+  EXPECT_EQ(3, msg.b()[2]);
+  EXPECT_EQ(0, msg.b()[3]);
+}
+
+} // End of namespace test_EmbeddedAMS_string_bytes

+ 37 - 2
test_data.py

@@ -22,7 +22,7 @@
 # Info:
 #   info at EmbeddedProto dot com
 #
-# Postal adress:
+# Postal address:
 #   Johan Huizingalaan 763a
 #   1066 VH, Amsterdam
 #   the Netherlands
@@ -191,6 +191,38 @@ def test_repeated_message():
     print()
 
 
+def test_string():
+    msg = rf.text()
+
+    msg.txt = "Foo bar"
+
+    str = ""
+    msg_str = msg.SerializeToString()
+    print(len(msg_str))
+    print(msg_str)
+    for x in msg_str:
+        str += "0x{:02x}, ".format(x)
+
+    print(str)
+    print()
+
+
+def test_bytes():
+    msg = rf.raw_bytes()
+
+    msg.b = b'\x01\x02\x03\x00'
+
+    str = ""
+    msg_str = msg.SerializeToString()
+    print(len(msg_str))
+    print(msg_str)
+    for x in msg_str:
+        str += "0x{:02x}, ".format(x)
+
+    print(str)
+    print()
+
+
 def test_oneof_fields():
     msg = of.message_oneof()
 
@@ -236,6 +268,9 @@ def test_included_proto():
 
 #test_repeated_fields()
 #test_repeated_message()
+#test_string()
+test_bytes()
 #test_nested_message()
-test_oneof_fields()
+#test_oneof_fields()
 #test_included_proto()
+