From a2b0abea8313f689b5a459884e5c13c10a45c201 Mon Sep 17 00:00:00 2001
From: Asher Glick <asher.glick@gmail.com>
Date: Sat, 4 Nov 2023 13:48:12 -0500
Subject: [PATCH] Adding more dynamic Proto reading functions

This is the final of the four de/serializer function changes to allow for more dynamic interaction. It handles the proto read functions and allowing a single proto value to set multiple output values.
---
 xml_converter/doc/menu/display_name.md        |   7 +-
 xml_converter/doc/menu/name.md                |   7 +
 .../cpp_templates/attribute_template.hpp      |   3 +-
 .../attribute_template_compoundvalue.cpp      |   7 +-
 .../cpp_templates/attribute_template_enum.cpp |  12 +-
 .../attribute_template_multiflagvalue.cpp     |   7 +-
 .../cpp_templates/class_template.cpp          |   3 +-
 xml_converter/generators/generate_cpp.py      |  22 +--
 xml_converter/proto/waypoint.proto            |  15 +-
 xml_converter/src/attribute/bool.cpp          |  10 ++
 xml_converter/src/attribute/bool.hpp          |   5 +-
 xml_converter/src/attribute/color.cpp         |  11 +-
 xml_converter/src/attribute/color.hpp         |   2 +-
 .../src/attribute/cull_chirality_gen.cpp      |  20 ++-
 .../src/attribute/cull_chirality_gen.hpp      |   3 +-
 .../src/attribute/euler_rotation_gen.cpp      |  11 +-
 .../src/attribute/euler_rotation_gen.hpp      |   3 +-
 .../src/attribute/festival_filter_gen.cpp     |  19 +--
 .../src/attribute/festival_filter_gen.hpp     |   3 +-
 xml_converter/src/attribute/float.cpp         |  10 ++
 xml_converter/src/attribute/float.hpp         |   5 +-
 xml_converter/src/attribute/image.cpp         |  11 +-
 xml_converter/src/attribute/image.hpp         |   2 +-
 xml_converter/src/attribute/int.cpp           |  10 ++
 xml_converter/src/attribute/int.hpp           |   5 +-
 .../src/attribute/map_type_filter_gen.cpp     |  53 ++++---
 .../src/attribute/map_type_filter_gen.hpp     |   3 +-
 .../src/attribute/marker_category.cpp         |  13 +-
 .../src/attribute/marker_category.hpp         |   2 +-
 .../src/attribute/mount_filter_gen.cpp        |  25 +--
 .../src/attribute/mount_filter_gen.hpp        |   3 +-
 xml_converter/src/attribute/position_gen.cpp  |  11 +-
 xml_converter/src/attribute/position_gen.hpp  |   3 +-
 .../src/attribute/profession_filter_gen.cpp   |  23 +--
 .../src/attribute/profession_filter_gen.hpp   |   3 +-
 .../src/attribute/reset_behavior_gen.cpp      |  44 ++++--
 .../src/attribute/reset_behavior_gen.hpp      |   3 +-
 .../attribute/specialization_filter_gen.cpp   | 149 +++++++++---------
 .../attribute/specialization_filter_gen.hpp   |   3 +-
 .../src/attribute/species_filter_gen.cpp      |  15 +-
 .../src/attribute/species_filter_gen.hpp      |   3 +-
 xml_converter/src/attribute/string.cpp        |  23 +++
 xml_converter/src/attribute/string.hpp        |  11 +-
 xml_converter/src/attribute/trail_data.cpp    |  15 +-
 xml_converter/src/attribute/trail_data.hpp    |   2 +-
 xml_converter/src/attribute/unique_id.cpp     |  12 +-
 xml_converter/src/attribute/unique_id.hpp     |   2 +-
 xml_converter/src/category_gen.cpp            |  21 +--
 xml_converter/src/icon_gen.cpp                | 141 ++++++-----------
 xml_converter/src/trail_gen.cpp               |  81 ++++------
 50 files changed, 459 insertions(+), 418 deletions(-)

diff --git a/xml_converter/doc/menu/display_name.md b/xml_converter/doc/menu/display_name.md
index 6528b2cb..09675b3d 100644
--- a/xml_converter/doc/menu/display_name.md
+++ b/xml_converter/doc/menu/display_name.md
@@ -3,7 +3,12 @@ name: Display Name
 type: String
 applies_to: [Category]
 xml_fields: [DisplayName]
-protobuf_field: display_name
+protobuf_field: name
+custom_functions:
+  read.proto:
+    function: proto_display_name_to_display_name_and_name
+    side_effects: [Name]
+
 ---
 A human readable name of this category.
 
diff --git a/xml_converter/doc/menu/name.md b/xml_converter/doc/menu/name.md
index a6a514e6..f0c161be 100644
--- a/xml_converter/doc/menu/name.md
+++ b/xml_converter/doc/menu/name.md
@@ -4,6 +4,13 @@ type: String
 applies_to: [Category]
 xml_fields: [Name]
 protobuf_field: name
+custom_functions:
+  read.proto:
+    function: do_nothing
+    side_effects: []
+  write.proto:
+    function: do_nothing
+    side_effects: []
 ---
 
 Notes
diff --git a/xml_converter/generators/cpp_templates/attribute_template.hpp b/xml_converter/generators/cpp_templates/attribute_template.hpp
index def68312..3788bc5f 100644
--- a/xml_converter/generators/cpp_templates/attribute_template.hpp
+++ b/xml_converter/generators/cpp_templates/attribute_template.hpp
@@ -35,9 +35,10 @@ void xml_attribute_to_{{attribute_name}}(
     std::vector<XMLError*>* errors,
     {{class_name}}* value,
     bool* is_set);
+
 std::string {{attribute_name}}_to_xml_attribute(const std::string& attribute_name, const {{class_name}}* value);
 
-{{class_name}} from_proto_{{attribute_name}}({{proto_field_cpp_type}} proto_{{attribute_name}});
+void proto_to_{{attribute_name}}({{proto_field_cpp_type}} input, {{class_name}}* value, bool* is_set);
 
 {% if type == "Enum" %}
     void {{attribute_name}}_to_proto({{class_name}} value, std::function<void({{proto_field_cpp_type}})> setter);
diff --git a/xml_converter/generators/cpp_templates/attribute_template_compoundvalue.cpp b/xml_converter/generators/cpp_templates/attribute_template_compoundvalue.cpp
index 2be3578c..bcad298d 100644
--- a/xml_converter/generators/cpp_templates/attribute_template_compoundvalue.cpp
+++ b/xml_converter/generators/cpp_templates/attribute_template_compoundvalue.cpp
@@ -48,12 +48,13 @@ void xml_attribute_to_{{attribute_name}}(
     }
 {% endif %}
 
-{{class_name}} from_proto_{{attribute_name}}({{proto_field_cpp_type}} proto_{{attribute_name}}) {
+void proto_to_{{attribute_name}}({{proto_field_cpp_type}} input, {{class_name}}* value, bool* is_set) {
     {{class_name}} {{attribute_name}};
     {% for attribute_variable in attribute_variables: %}
-        {{attribute_name}}.{{attribute_variable.attribute_name}} = proto_{{attribute_name}}.{{attribute_variable.protobuf_field}}();
+        {{attribute_name}}.{{attribute_variable.attribute_name}} = input.{{attribute_variable.protobuf_field}}();
     {% endfor %}
-    return {{attribute_name}};
+    *value = {{attribute_name}};
+    *is_set = true;
 }
 
 void {{attribute_name}}_to_proto({{class_name}} value, std::function<void({{proto_field_cpp_type}}*)> setter) {
diff --git a/xml_converter/generators/cpp_templates/attribute_template_enum.cpp b/xml_converter/generators/cpp_templates/attribute_template_enum.cpp
index 41156ef2..339012f8 100644
--- a/xml_converter/generators/cpp_templates/attribute_template_enum.cpp
+++ b/xml_converter/generators/cpp_templates/attribute_template_enum.cpp
@@ -57,14 +57,18 @@ string {{attribute_name}}_to_xml_attribute(const std::string& attribute_name, co
     }
 }
 
-{{class_name}} from_proto_{{attribute_name}}({{proto_field_cpp_type}} proto_{{attribute_name}}) {
-    switch (proto_{{attribute_name}}) {
+void proto_to_{{attribute_name}}({{proto_field_cpp_type}} input, {{class_name}}* value, bool* is_set) {
+    switch (input) {
         {% for attribute_variable in attribute_variables %}
             case {{proto_field_cpp_type}}::{{attribute_variable.attribute_name}}:
-                return {{class_name}}::{{attribute_variable.attribute_name}};
+                *value = {{class_name}}::{{attribute_variable.attribute_name}};
+                *is_set = true;
+                break;
         {% endfor %}
         default:
-            return {{class_name}}::{{attribute_variables[0].attribute_name}};
+            *value = {{class_name}}::{{attribute_variables[0].attribute_name}};
+            *is_set = true;
+            break;
     }
 }
 
diff --git a/xml_converter/generators/cpp_templates/attribute_template_multiflagvalue.cpp b/xml_converter/generators/cpp_templates/attribute_template_multiflagvalue.cpp
index 3240ac8b..bacba5b5 100644
--- a/xml_converter/generators/cpp_templates/attribute_template_multiflagvalue.cpp
+++ b/xml_converter/generators/cpp_templates/attribute_template_multiflagvalue.cpp
@@ -59,12 +59,13 @@ string {{attribute_name}}_to_xml_attribute(const std::string& attribute_name, co
     return " " + attribute_name + "=\"" + output + "\"";
 }
 
-{{class_name}} from_proto_{{attribute_name}}({{proto_field_cpp_type}} proto_{{attribute_name}}) {
+void proto_to_{{attribute_name}}({{proto_field_cpp_type}} input, {{class_name}}* value, bool* is_set) {
     {{class_name}} {{attribute_name}};
     {% for n, attribute_variable in enumerate(attribute_variables)%}
-        {{attribute_name}}.{{attribute_variable.attribute_name}} = proto_{{attribute_name}}.{{attribute_variable.attribute_name}}();
+        {{attribute_name}}.{{attribute_variable.attribute_name}} = input.{{attribute_variable.attribute_name}}();
     {% endfor %}
-    return {{attribute_name}};
+    *value = {{attribute_name}};
+    *is_set = true;
 }
 
 void {{attribute_name}}_to_proto({{class_name}} value, std::function<void({{proto_field_cpp_type}}*)> setter) {
diff --git a/xml_converter/generators/cpp_templates/class_template.cpp b/xml_converter/generators/cpp_templates/class_template.cpp
index bcf713dc..45239935 100644
--- a/xml_converter/generators/cpp_templates/class_template.cpp
+++ b/xml_converter/generators/cpp_templates/class_template.cpp
@@ -115,8 +115,7 @@ void {{cpp_class}}::parse_protobuf(waypoint::{{cpp_class}} proto_{{cpp_class_hea
             {% else %}
                 if (proto_{{cpp_class_header}}{{attribute_variable.proto_drilldown_calls}}.{{attribute_variable.protobuf_field}}() != 0) {
             {% endif %}
-                this->{{attribute_variable.attribute_name}} = {{attribute_variable.deserialize_proto_function}}(proto_{{cpp_class_header}}{{attribute_variable.proto_drilldown_calls}}.{{attribute_variable.protobuf_field}}());
-                this->{{attribute_variable.attribute_flag_name}} = true;
+                {{attribute_variable.deserialize_proto_function}}(proto_{{cpp_class_header}}{{attribute_variable.proto_drilldown_calls}}.{{attribute_variable.protobuf_field}}(), &(this->{{attribute_variable.attribute_name}}), &(this->{{attribute_variable.attribute_flag_name}}){% for side_effect in attribute_variable.deserialize_proto_side_effects %}, &(this->{{side_effect}}){% endfor %});
             }
         {% endif %}
     {% endfor %}
diff --git a/xml_converter/generators/generate_cpp.py b/xml_converter/generators/generate_cpp.py
index b9b86c8d..2b2f959e 100644
--- a/xml_converter/generators/generate_cpp.py
+++ b/xml_converter/generators/generate_cpp.py
@@ -66,7 +66,7 @@ class AttributeVariable:
 
     # The function name and additional side effect pointers for proto deserialization.
     deserialize_proto_function: str
-    # deserialize_proto_side_effects: List[str]
+    deserialize_proto_side_effects: List[str]
 
     # The name of the field in the protobuf that this attribute corresponds to.
     protobuf_field: str
@@ -313,7 +313,7 @@ def generate_cpp_variable_data(
                         serialize_proto_function="to_proto_" + component_class_name,
                         # serialize_proto_side_effects=[],
                         deserialize_proto_function="from_proto_" + component_class_name,
-                        # deserialize_proto_side_effects=[],
+                        deserialize_proto_side_effects=[],
                     )
                     attribute_variables.append(component_attribute_variable)
                 # If there aren't any components to bundle, we don't want to render the attribute
@@ -326,7 +326,7 @@ def generate_cpp_variable_data(
             deserialize_xml_side_effects: List[str] = []
             serialize_proto_function: str = class_name + "_to_proto"
             serialize_proto_side_effects: List[str] = []
-            deserialize_proto_function: str = "from_proto_" + class_name
+            deserialize_proto_function: str = "proto_to_" + class_name
             deserialize_proto_side_effects: List[str] = []
             if "custom_functions" in fieldval:
                 # Overwrite defaults with xml/proto read/write functions
@@ -335,11 +335,11 @@ def generate_cpp_variable_data(
                         deserialize_xml_function, deserialize_xml_side_effects = build_custom_function_data(
                             fieldval["custom_functions"][custom_function]
                         )
-                    elif custom_function == "read.proto":
+                    elif custom_function == "write.xml":
                         serialize_xml_function, serialize_xml_side_effects = build_custom_function_data(
                             fieldval["custom_functions"][custom_function]
                         )
-                    elif custom_function == "write.xml":
+                    elif custom_function == "read.proto":
                         deserialize_proto_function, deserialize_proto_side_effects = build_custom_function_data(
                             fieldval["custom_functions"][custom_function]
                         )
@@ -353,11 +353,11 @@ def generate_cpp_variable_data(
                         deserialize_xml_function, deserialize_xml_side_effects = build_custom_function_data(
                             fieldval["custom_functions"][custom_function]
                         )
-                    elif custom_function == "read.proto." + doc_type:
+                    elif custom_function == "write.xml." + doc_type:
                         serialize_xml_function, serialize_xml_side_effects = build_custom_function_data(
                             fieldval["custom_functions"][custom_function]
                         )
-                    elif custom_function == "write.xml." + doc_type:
+                    elif custom_function == "read.proto." + doc_type:
                         deserialize_proto_function, deserialize_proto_side_effects = build_custom_function_data(
                             fieldval["custom_functions"][custom_function]
                         )
@@ -390,7 +390,7 @@ def generate_cpp_variable_data(
                 serialize_proto_function=serialize_proto_function,
                 # serialize_proto_side_effects=serialize_proto_side_effects,
                 deserialize_proto_function=deserialize_proto_function,
-                # deserialize_proto_side_effects=deserialize_proto_side_effects,
+                deserialize_proto_side_effects=deserialize_proto_side_effects,
 
                 uses_file_path=fieldval.get("uses_file_path", False)
             )
@@ -480,7 +480,7 @@ def write_attribute(output_directory: str, data: Dict[str, Document]) -> None:
                     # serialize_xml_side_effects=[],
                     deserialize_xml_side_effects=[],
                     # serialize_proto_side_effects=[],
-                    # deserialize_proto_side_effects=[],
+                    deserialize_proto_side_effects=[],
                 )
                 attribute_variables.append(attribute_variable)
 
@@ -515,7 +515,7 @@ def write_attribute(output_directory: str, data: Dict[str, Document]) -> None:
                     # serialize_xml_side_effects=[],
                     deserialize_xml_side_effects=[],
                     # serialize_proto_side_effects=[],
-                    # deserialize_proto_side_effects=[],
+                    deserialize_proto_side_effects=[],
                 )
                 attribute_variables.append(attribute_variable)
 
@@ -543,7 +543,7 @@ def write_attribute(output_directory: str, data: Dict[str, Document]) -> None:
                     # serialize_xml_side_effects=[],
                     deserialize_xml_side_effects=[],
                     # serialize_proto_side_effects=[],
-                    # deserialize_proto_side_effects=[],
+                    deserialize_proto_side_effects=[],
                 )
                 attribute_variables.append(attribute_variable)
 
diff --git a/xml_converter/proto/waypoint.proto b/xml_converter/proto/waypoint.proto
index bfc2f74f..8e5e1d26 100644
--- a/xml_converter/proto/waypoint.proto
+++ b/xml_converter/proto/waypoint.proto
@@ -7,14 +7,13 @@ message Waypoint {
 }
 
 message Category {
-    bool default_visibility = 1;
-    string display_name = 2;
-    bool is_separator = 3;
-    string name = 4;
-    string tip_description = 5;
-    repeated Category children = 6;
-    repeated Icon icon = 7;
-    repeated Trail trail = 8;
+    string name = 1;
+    repeated Category children = 2;
+    repeated Icon icon = 3;
+    repeated Trail trail = 4;
+    bool is_separator = 5;
+    bool default_visibility = 6;
+    string tip_description = 7;
 }
 
 message Icon {
diff --git a/xml_converter/src/attribute/bool.cpp b/xml_converter/src/attribute/bool.cpp
index 35a218e4..dd76c6b9 100644
--- a/xml_converter/src/attribute/bool.cpp
+++ b/xml_converter/src/attribute/bool.cpp
@@ -48,6 +48,16 @@ string bool_to_xml_attribute(const string& attribute_name, const bool* value) {
     }
 }
 
+////////////////////////////////////////////////////////////////////////////////
+// proto_to_bool
+//
+// Parses a bool from a proto field.
+////////////////////////////////////////////////////////////////////////////////
+void proto_to_bool(bool input, bool* value, bool* is_set) {
+    *value = input;
+    *is_set = true;
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // bool_to_proto
 //
diff --git a/xml_converter/src/attribute/bool.hpp b/xml_converter/src/attribute/bool.hpp
index 845be712..61d80300 100644
--- a/xml_converter/src/attribute/bool.hpp
+++ b/xml_converter/src/attribute/bool.hpp
@@ -16,9 +16,6 @@ void xml_attribute_to_bool(
 
 std::string bool_to_xml_attribute(const std::string& attribute_name, const bool* value);
 
-// Zero Cost Abstraction identity functions to make parsing and writing protobufs more uniform
-inline bool const& from_proto_bool(const bool& x) {
-    return x;
-}
+void proto_to_bool(bool input, bool* value, bool* is_set);
 
 void bool_to_proto(bool value, std::function<void(bool)> setter);
diff --git a/xml_converter/src/attribute/color.cpp b/xml_converter/src/attribute/color.cpp
index 6e1901dd..be6f7c13 100644
--- a/xml_converter/src/attribute/color.cpp
+++ b/xml_converter/src/attribute/color.cpp
@@ -114,21 +114,22 @@ string color_to_xml_attribute(const string& attribute_name, const Color* value)
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// from_proto_color
+// proto_to_color
 //
-// Converts a proto message into a Color
+// Parses a Color from a proto field.
 ////////////////////////////////////////////////////////////////////////////////
-Color from_proto_color(waypoint::RGBAColor attribute_value) {
+void proto_to_color(waypoint::RGBAColor input, Color* value, bool* is_set) {
     Color color;
     std::stringstream stream;
-    uint32_t rgba = attribute_value.rgba_color();
+    uint32_t rgba = input.rgba_color();
 
     color.red = convert_color_channel_int_to_float((rgba >> 24) & 0xff);
     color.green = convert_color_channel_int_to_float((rgba >> 16) & 0xff);
     color.blue = convert_color_channel_int_to_float((rgba >> 8) & 0xff);
     color.alpha = convert_color_channel_int_to_float(rgba & 0xff);
 
-    return color;
+    *value = color;
+    *is_set = true;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
diff --git a/xml_converter/src/attribute/color.hpp b/xml_converter/src/attribute/color.hpp
index 8f3c58b6..0747ce1d 100644
--- a/xml_converter/src/attribute/color.hpp
+++ b/xml_converter/src/attribute/color.hpp
@@ -27,6 +27,6 @@ void xml_attribute_to_color(
 
 std::string color_to_xml_attribute(const std::string& attribute_name, const Color* value);
 
-Color from_proto_color(waypoint::RGBAColor attribute_value);
+void proto_to_color(waypoint::RGBAColor input, Color* value, bool* is_set);
 
 void color_to_proto(Color value, std::function<void(waypoint::RGBAColor*)> setter);
diff --git a/xml_converter/src/attribute/cull_chirality_gen.cpp b/xml_converter/src/attribute/cull_chirality_gen.cpp
index 03933f55..12bbd883 100644
--- a/xml_converter/src/attribute/cull_chirality_gen.cpp
+++ b/xml_converter/src/attribute/cull_chirality_gen.cpp
@@ -51,16 +51,24 @@ string cull_chirality_to_xml_attribute(const std::string& attribute_name, const
     }
 }
 
-CullChirality from_proto_cull_chirality(waypoint::CullChirality proto_cull_chirality) {
-    switch (proto_cull_chirality) {
+void proto_to_cull_chirality(waypoint::CullChirality input, CullChirality* value, bool* is_set) {
+    switch (input) {
         case waypoint::CullChirality::none:
-            return CullChirality::none;
+            *value = CullChirality::none;
+            *is_set = true;
+            break;
         case waypoint::CullChirality::clockwise:
-            return CullChirality::clockwise;
+            *value = CullChirality::clockwise;
+            *is_set = true;
+            break;
         case waypoint::CullChirality::counter_clockwise:
-            return CullChirality::counter_clockwise;
+            *value = CullChirality::counter_clockwise;
+            *is_set = true;
+            break;
         default:
-            return CullChirality::none;
+            *value = CullChirality::none;
+            *is_set = true;
+            break;
     }
 }
 
diff --git a/xml_converter/src/attribute/cull_chirality_gen.hpp b/xml_converter/src/attribute/cull_chirality_gen.hpp
index c49c92f6..3f680d27 100644
--- a/xml_converter/src/attribute/cull_chirality_gen.hpp
+++ b/xml_converter/src/attribute/cull_chirality_gen.hpp
@@ -19,8 +19,9 @@ void xml_attribute_to_cull_chirality(
     std::vector<XMLError*>* errors,
     CullChirality* value,
     bool* is_set);
+
 std::string cull_chirality_to_xml_attribute(const std::string& attribute_name, const CullChirality* value);
 
-CullChirality from_proto_cull_chirality(waypoint::CullChirality proto_cull_chirality);
+void proto_to_cull_chirality(waypoint::CullChirality input, CullChirality* value, bool* is_set);
 
 void cull_chirality_to_proto(CullChirality value, std::function<void(waypoint::CullChirality)> setter);
diff --git a/xml_converter/src/attribute/euler_rotation_gen.cpp b/xml_converter/src/attribute/euler_rotation_gen.cpp
index ea1bb9c7..5cc44878 100644
--- a/xml_converter/src/attribute/euler_rotation_gen.cpp
+++ b/xml_converter/src/attribute/euler_rotation_gen.cpp
@@ -40,12 +40,13 @@ string euler_rotation_to_xml_attribute(const std::string& attribute_name, const
     return " " + attribute_name + "=\"" + output + "\"";
 }
 
-EulerRotation from_proto_euler_rotation(waypoint::EulerRotation proto_euler_rotation) {
+void proto_to_euler_rotation(waypoint::EulerRotation input, EulerRotation* value, bool* is_set) {
     EulerRotation euler_rotation;
-    euler_rotation.x_rotation = proto_euler_rotation.x();
-    euler_rotation.y_rotation = proto_euler_rotation.y();
-    euler_rotation.z_rotation = proto_euler_rotation.z();
-    return euler_rotation;
+    euler_rotation.x_rotation = input.x();
+    euler_rotation.y_rotation = input.y();
+    euler_rotation.z_rotation = input.z();
+    *value = euler_rotation;
+    *is_set = true;
 }
 
 void euler_rotation_to_proto(EulerRotation value, std::function<void(waypoint::EulerRotation*)> setter) {
diff --git a/xml_converter/src/attribute/euler_rotation_gen.hpp b/xml_converter/src/attribute/euler_rotation_gen.hpp
index 73052d39..a2c0c392 100644
--- a/xml_converter/src/attribute/euler_rotation_gen.hpp
+++ b/xml_converter/src/attribute/euler_rotation_gen.hpp
@@ -25,8 +25,9 @@ void xml_attribute_to_euler_rotation(
     std::vector<XMLError*>* errors,
     EulerRotation* value,
     bool* is_set);
+
 std::string euler_rotation_to_xml_attribute(const std::string& attribute_name, const EulerRotation* value);
 
-EulerRotation from_proto_euler_rotation(waypoint::EulerRotation proto_euler_rotation);
+void proto_to_euler_rotation(waypoint::EulerRotation input, EulerRotation* value, bool* is_set);
 
 void euler_rotation_to_proto(EulerRotation value, std::function<void(waypoint::EulerRotation*)> setter);
diff --git a/xml_converter/src/attribute/festival_filter_gen.cpp b/xml_converter/src/attribute/festival_filter_gen.cpp
index 002bd446..d83a6743 100644
--- a/xml_converter/src/attribute/festival_filter_gen.cpp
+++ b/xml_converter/src/attribute/festival_filter_gen.cpp
@@ -90,16 +90,17 @@ string festival_filter_to_xml_attribute(const std::string& attribute_name, const
     return " " + attribute_name + "=\"" + output + "\"";
 }
 
-FestivalFilter from_proto_festival_filter(waypoint::FestivalFilter proto_festival_filter) {
+void proto_to_festival_filter(waypoint::FestivalFilter input, FestivalFilter* value, bool* is_set) {
     FestivalFilter festival_filter;
-    festival_filter.dragonbash = proto_festival_filter.dragonbash();
-    festival_filter.festival_of_the_four_winds = proto_festival_filter.festival_of_the_four_winds();
-    festival_filter.halloween = proto_festival_filter.halloween();
-    festival_filter.lunar_new_year = proto_festival_filter.lunar_new_year();
-    festival_filter.super_adventure_festival = proto_festival_filter.super_adventure_festival();
-    festival_filter.wintersday = proto_festival_filter.wintersday();
-    festival_filter.none = proto_festival_filter.none();
-    return festival_filter;
+    festival_filter.dragonbash = input.dragonbash();
+    festival_filter.festival_of_the_four_winds = input.festival_of_the_four_winds();
+    festival_filter.halloween = input.halloween();
+    festival_filter.lunar_new_year = input.lunar_new_year();
+    festival_filter.super_adventure_festival = input.super_adventure_festival();
+    festival_filter.wintersday = input.wintersday();
+    festival_filter.none = input.none();
+    *value = festival_filter;
+    *is_set = true;
 }
 
 void festival_filter_to_proto(FestivalFilter value, std::function<void(waypoint::FestivalFilter*)> setter) {
diff --git a/xml_converter/src/attribute/festival_filter_gen.hpp b/xml_converter/src/attribute/festival_filter_gen.hpp
index 34a98c9d..217d9164 100644
--- a/xml_converter/src/attribute/festival_filter_gen.hpp
+++ b/xml_converter/src/attribute/festival_filter_gen.hpp
@@ -29,8 +29,9 @@ void xml_attribute_to_festival_filter(
     std::vector<XMLError*>* errors,
     FestivalFilter* value,
     bool* is_set);
+
 std::string festival_filter_to_xml_attribute(const std::string& attribute_name, const FestivalFilter* value);
 
-FestivalFilter from_proto_festival_filter(waypoint::FestivalFilter proto_festival_filter);
+void proto_to_festival_filter(waypoint::FestivalFilter input, FestivalFilter* value, bool* is_set);
 
 void festival_filter_to_proto(FestivalFilter value, std::function<void(waypoint::FestivalFilter*)> setter);
diff --git a/xml_converter/src/attribute/float.cpp b/xml_converter/src/attribute/float.cpp
index db030ac4..4508fc6c 100644
--- a/xml_converter/src/attribute/float.cpp
+++ b/xml_converter/src/attribute/float.cpp
@@ -30,6 +30,16 @@ string float_to_xml_attribute(const string& attribute_name, const float* value)
     return " " + attribute_name + "=\"" + to_string(*value) + "\"";
 }
 
+////////////////////////////////////////////////////////////////////////////////
+// proto_to_float
+//
+// Parses a float from a proto field.
+////////////////////////////////////////////////////////////////////////////////
+void proto_to_float(float input, float* value, bool* is_set) {
+    *value = input;
+    *is_set = true;
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // float_to_proto
 //
diff --git a/xml_converter/src/attribute/float.hpp b/xml_converter/src/attribute/float.hpp
index 176522ab..27b7b7a2 100644
--- a/xml_converter/src/attribute/float.hpp
+++ b/xml_converter/src/attribute/float.hpp
@@ -16,9 +16,6 @@ void xml_attribute_to_float(
 
 std::string float_to_xml_attribute(const std::string& attribute_name, const float* value);
 
-// Zero Cost Abstraction identity functions to make parsing and writing protobufs more uniform
-inline float const& from_proto_float(const float& x) {
-    return x;
-}
+void proto_to_float(float input, float* value, bool* is_set);
 
 void float_to_proto(float value, std::function<void(float&)> setter);
diff --git a/xml_converter/src/attribute/image.cpp b/xml_converter/src/attribute/image.cpp
index 1036e169..fd2688b5 100644
--- a/xml_converter/src/attribute/image.cpp
+++ b/xml_converter/src/attribute/image.cpp
@@ -34,14 +34,15 @@ string image_to_xml_attribute(const string& attribute_name, const Image* value)
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// from_proto_image
+// proto_to_image
 //
-// Parses a waypoint::Image from proto
+// Parses an Image from proto
 ////////////////////////////////////////////////////////////////////////////////
-Image from_proto_image(waypoint::TexturePath attribute_value) {
+void proto_to_image(waypoint::TexturePath input, Image* value, bool* is_set) {
     Image image;
-    image.path = attribute_value.path();
-    return image;
+    image.path = input.path();
+    *value = image;
+    *is_set = true;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
diff --git a/xml_converter/src/attribute/image.hpp b/xml_converter/src/attribute/image.hpp
index 0fa34df4..fb067108 100644
--- a/xml_converter/src/attribute/image.hpp
+++ b/xml_converter/src/attribute/image.hpp
@@ -24,6 +24,6 @@ void xml_attribute_to_image(
 
 std::string image_to_xml_attribute(const std::string& attribute_name, const Image* value);
 
-Image from_proto_image(waypoint::TexturePath attribute_value);
+void proto_to_image(waypoint::TexturePath input, Image* value, bool* is_set);
 
 void image_to_proto(Image value, std::function<void(waypoint::TexturePath*)> setter);
diff --git a/xml_converter/src/attribute/int.cpp b/xml_converter/src/attribute/int.cpp
index 2f97382f..fc095a50 100644
--- a/xml_converter/src/attribute/int.cpp
+++ b/xml_converter/src/attribute/int.cpp
@@ -45,6 +45,16 @@ string int_to_xml_attribute(const string& attribute_name, const int* value) {
     return " " + attribute_name + "=\"" + to_string(*value) + "\"";
 }
 
+////////////////////////////////////////////////////////////////////////////////
+// proto_to_int
+//
+// Parses an int from a proto field.
+////////////////////////////////////////////////////////////////////////////////
+void proto_to_int(int input, int* value, bool* is_set) {
+    *value = input;
+    *is_set = true;
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // int_to_proto
 //
diff --git a/xml_converter/src/attribute/int.hpp b/xml_converter/src/attribute/int.hpp
index 08e0bfb3..13c1abda 100644
--- a/xml_converter/src/attribute/int.hpp
+++ b/xml_converter/src/attribute/int.hpp
@@ -16,9 +16,6 @@ void xml_attribute_to_int(
 
 std::string int_to_xml_attribute(const std::string& attribute_name, const int* value);
 
-// Zero Cost Abstraction identity functions to make parsing and writing protobufs more uniform
-inline int const& from_proto_int(const int& x) {
-    return x;
-}
+void proto_to_int(int input, int* value, bool* is_set);
 
 void int_to_proto(int value, std::function<void(int&)> setter);
diff --git a/xml_converter/src/attribute/map_type_filter_gen.cpp b/xml_converter/src/attribute/map_type_filter_gen.cpp
index 0a402bd3..66b79add 100644
--- a/xml_converter/src/attribute/map_type_filter_gen.cpp
+++ b/xml_converter/src/attribute/map_type_filter_gen.cpp
@@ -206,33 +206,34 @@ string map_type_filter_to_xml_attribute(const std::string& attribute_name, const
     return " " + attribute_name + "=\"" + output + "\"";
 }
 
-MapTypeFilter from_proto_map_type_filter(waypoint::MapTypeFilter proto_map_type_filter) {
+void proto_to_map_type_filter(waypoint::MapTypeFilter input, MapTypeFilter* value, bool* is_set) {
     MapTypeFilter map_type_filter;
-    map_type_filter.unknown_map = proto_map_type_filter.unknown_map();
-    map_type_filter.redirect_map = proto_map_type_filter.redirect_map();
-    map_type_filter.character_create_map = proto_map_type_filter.character_create_map();
-    map_type_filter.pvp_map = proto_map_type_filter.pvp_map();
-    map_type_filter.gvg_map = proto_map_type_filter.gvg_map();
-    map_type_filter.instance_map = proto_map_type_filter.instance_map();
-    map_type_filter.public_map = proto_map_type_filter.public_map();
-    map_type_filter.tournament_map = proto_map_type_filter.tournament_map();
-    map_type_filter.tutorial_map = proto_map_type_filter.tutorial_map();
-    map_type_filter.user_tournament_map = proto_map_type_filter.user_tournament_map();
-    map_type_filter.center_map = proto_map_type_filter.center_map();
-    map_type_filter.eternal_battlegrounds_map = proto_map_type_filter.eternal_battlegrounds_map();
-    map_type_filter.bluehome_map = proto_map_type_filter.bluehome_map();
-    map_type_filter.blue_borderlands_map = proto_map_type_filter.blue_borderlands_map();
-    map_type_filter.green_home_map = proto_map_type_filter.green_home_map();
-    map_type_filter.green_borderlands_map = proto_map_type_filter.green_borderlands_map();
-    map_type_filter.red_home_map = proto_map_type_filter.red_home_map();
-    map_type_filter.red_borderlands_map = proto_map_type_filter.red_borderlands_map();
-    map_type_filter.fortunes_vale_map = proto_map_type_filter.fortunes_vale_map();
-    map_type_filter.jump_puzzle_map = proto_map_type_filter.jump_puzzle_map();
-    map_type_filter.obsidian_sanctum_map = proto_map_type_filter.obsidian_sanctum_map();
-    map_type_filter.edge_of_the_mists_map = proto_map_type_filter.edge_of_the_mists_map();
-    map_type_filter.public_mini_map = proto_map_type_filter.public_mini_map();
-    map_type_filter.wvw_lounge_map = proto_map_type_filter.wvw_lounge_map();
-    return map_type_filter;
+    map_type_filter.unknown_map = input.unknown_map();
+    map_type_filter.redirect_map = input.redirect_map();
+    map_type_filter.character_create_map = input.character_create_map();
+    map_type_filter.pvp_map = input.pvp_map();
+    map_type_filter.gvg_map = input.gvg_map();
+    map_type_filter.instance_map = input.instance_map();
+    map_type_filter.public_map = input.public_map();
+    map_type_filter.tournament_map = input.tournament_map();
+    map_type_filter.tutorial_map = input.tutorial_map();
+    map_type_filter.user_tournament_map = input.user_tournament_map();
+    map_type_filter.center_map = input.center_map();
+    map_type_filter.eternal_battlegrounds_map = input.eternal_battlegrounds_map();
+    map_type_filter.bluehome_map = input.bluehome_map();
+    map_type_filter.blue_borderlands_map = input.blue_borderlands_map();
+    map_type_filter.green_home_map = input.green_home_map();
+    map_type_filter.green_borderlands_map = input.green_borderlands_map();
+    map_type_filter.red_home_map = input.red_home_map();
+    map_type_filter.red_borderlands_map = input.red_borderlands_map();
+    map_type_filter.fortunes_vale_map = input.fortunes_vale_map();
+    map_type_filter.jump_puzzle_map = input.jump_puzzle_map();
+    map_type_filter.obsidian_sanctum_map = input.obsidian_sanctum_map();
+    map_type_filter.edge_of_the_mists_map = input.edge_of_the_mists_map();
+    map_type_filter.public_mini_map = input.public_mini_map();
+    map_type_filter.wvw_lounge_map = input.wvw_lounge_map();
+    *value = map_type_filter;
+    *is_set = true;
 }
 
 void map_type_filter_to_proto(MapTypeFilter value, std::function<void(waypoint::MapTypeFilter*)> setter) {
diff --git a/xml_converter/src/attribute/map_type_filter_gen.hpp b/xml_converter/src/attribute/map_type_filter_gen.hpp
index 42248660..13bd7dd4 100644
--- a/xml_converter/src/attribute/map_type_filter_gen.hpp
+++ b/xml_converter/src/attribute/map_type_filter_gen.hpp
@@ -46,8 +46,9 @@ void xml_attribute_to_map_type_filter(
     std::vector<XMLError*>* errors,
     MapTypeFilter* value,
     bool* is_set);
+
 std::string map_type_filter_to_xml_attribute(const std::string& attribute_name, const MapTypeFilter* value);
 
-MapTypeFilter from_proto_map_type_filter(waypoint::MapTypeFilter proto_map_type_filter);
+void proto_to_map_type_filter(waypoint::MapTypeFilter input, MapTypeFilter* value, bool* is_set);
 
 void map_type_filter_to_proto(MapTypeFilter value, std::function<void(waypoint::MapTypeFilter*)> setter);
diff --git a/xml_converter/src/attribute/marker_category.cpp b/xml_converter/src/attribute/marker_category.cpp
index 70e2fc64..3b70c60f 100644
--- a/xml_converter/src/attribute/marker_category.cpp
+++ b/xml_converter/src/attribute/marker_category.cpp
@@ -31,14 +31,15 @@ std::string marker_category_to_xml_attribute(const std::string& attribute_name,
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// from_proto_marker_category
+// proto_to_marker_category
 //
-// Parses a waypoint::Category and returns a MarkerCategory
-///////////////////////////////////////////////////////////////////////////////
-MarkerCategory from_proto_marker_category(waypoint::Category attribute_value) {
+// Parses a marker category from a proto field.
+////////////////////////////////////////////////////////////////////////////////
+void proto_to_marker_category(waypoint::Category input, MarkerCategory* value, bool* is_set) {
     MarkerCategory marker_category;
-    marker_category.category = attribute_value.name();
-    return marker_category;
+    marker_category.category = input.name();
+    *value = marker_category;
+    *is_set = true;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
diff --git a/xml_converter/src/attribute/marker_category.hpp b/xml_converter/src/attribute/marker_category.hpp
index 7bd6d53d..cf9903cc 100644
--- a/xml_converter/src/attribute/marker_category.hpp
+++ b/xml_converter/src/attribute/marker_category.hpp
@@ -24,6 +24,6 @@ void xml_attribute_to_marker_category(
 
 std::string marker_category_to_xml_attribute(const std::string& attribute_name, const MarkerCategory* value);
 
-MarkerCategory from_proto_marker_category(waypoint::Category attribute_value);
+void proto_to_marker_category(waypoint::Category input, MarkerCategory* value, bool* is_set);
 
 void marker_category_to_proto(MarkerCategory value, std::function<void(waypoint::Category*)> setter);
diff --git a/xml_converter/src/attribute/mount_filter_gen.cpp b/xml_converter/src/attribute/mount_filter_gen.cpp
index 56c87a3a..41124c08 100644
--- a/xml_converter/src/attribute/mount_filter_gen.cpp
+++ b/xml_converter/src/attribute/mount_filter_gen.cpp
@@ -108,19 +108,20 @@ string mount_filter_to_xml_attribute(const std::string& attribute_name, const Mo
     return " " + attribute_name + "=\"" + output + "\"";
 }
 
-MountFilter from_proto_mount_filter(waypoint::MountFilter proto_mount_filter) {
+void proto_to_mount_filter(waypoint::MountFilter input, MountFilter* value, bool* is_set) {
     MountFilter mount_filter;
-    mount_filter.raptor = proto_mount_filter.raptor();
-    mount_filter.springer = proto_mount_filter.springer();
-    mount_filter.skimmer = proto_mount_filter.skimmer();
-    mount_filter.jackal = proto_mount_filter.jackal();
-    mount_filter.griffon = proto_mount_filter.griffon();
-    mount_filter.roller_beetle = proto_mount_filter.roller_beetle();
-    mount_filter.warclaw = proto_mount_filter.warclaw();
-    mount_filter.skyscale = proto_mount_filter.skyscale();
-    mount_filter.skiff = proto_mount_filter.skiff();
-    mount_filter.seige_turtle = proto_mount_filter.seige_turtle();
-    return mount_filter;
+    mount_filter.raptor = input.raptor();
+    mount_filter.springer = input.springer();
+    mount_filter.skimmer = input.skimmer();
+    mount_filter.jackal = input.jackal();
+    mount_filter.griffon = input.griffon();
+    mount_filter.roller_beetle = input.roller_beetle();
+    mount_filter.warclaw = input.warclaw();
+    mount_filter.skyscale = input.skyscale();
+    mount_filter.skiff = input.skiff();
+    mount_filter.seige_turtle = input.seige_turtle();
+    *value = mount_filter;
+    *is_set = true;
 }
 
 void mount_filter_to_proto(MountFilter value, std::function<void(waypoint::MountFilter*)> setter) {
diff --git a/xml_converter/src/attribute/mount_filter_gen.hpp b/xml_converter/src/attribute/mount_filter_gen.hpp
index ec3a3d37..b9f5d9da 100644
--- a/xml_converter/src/attribute/mount_filter_gen.hpp
+++ b/xml_converter/src/attribute/mount_filter_gen.hpp
@@ -32,8 +32,9 @@ void xml_attribute_to_mount_filter(
     std::vector<XMLError*>* errors,
     MountFilter* value,
     bool* is_set);
+
 std::string mount_filter_to_xml_attribute(const std::string& attribute_name, const MountFilter* value);
 
-MountFilter from_proto_mount_filter(waypoint::MountFilter proto_mount_filter);
+void proto_to_mount_filter(waypoint::MountFilter input, MountFilter* value, bool* is_set);
 
 void mount_filter_to_proto(MountFilter value, std::function<void(waypoint::MountFilter*)> setter);
diff --git a/xml_converter/src/attribute/position_gen.cpp b/xml_converter/src/attribute/position_gen.cpp
index d594c8e8..275bf9e0 100644
--- a/xml_converter/src/attribute/position_gen.cpp
+++ b/xml_converter/src/attribute/position_gen.cpp
@@ -33,12 +33,13 @@ void xml_attribute_to_position(
     *is_set = true;
 }
 
-Position from_proto_position(waypoint::Position proto_position) {
+void proto_to_position(waypoint::Position input, Position* value, bool* is_set) {
     Position position;
-    position.x_position = proto_position.x();
-    position.y_position = proto_position.y();
-    position.z_position = proto_position.z();
-    return position;
+    position.x_position = input.x();
+    position.y_position = input.y();
+    position.z_position = input.z();
+    *value = position;
+    *is_set = true;
 }
 
 void position_to_proto(Position value, std::function<void(waypoint::Position*)> setter) {
diff --git a/xml_converter/src/attribute/position_gen.hpp b/xml_converter/src/attribute/position_gen.hpp
index 1d4f0aec..9033cb32 100644
--- a/xml_converter/src/attribute/position_gen.hpp
+++ b/xml_converter/src/attribute/position_gen.hpp
@@ -25,8 +25,9 @@ void xml_attribute_to_position(
     std::vector<XMLError*>* errors,
     Position* value,
     bool* is_set);
+
 std::string position_to_xml_attribute(const std::string& attribute_name, const Position* value);
 
-Position from_proto_position(waypoint::Position proto_position);
+void proto_to_position(waypoint::Position input, Position* value, bool* is_set);
 
 void position_to_proto(Position value, std::function<void(waypoint::Position*)> setter);
diff --git a/xml_converter/src/attribute/profession_filter_gen.cpp b/xml_converter/src/attribute/profession_filter_gen.cpp
index 43174d31..86729dcb 100644
--- a/xml_converter/src/attribute/profession_filter_gen.cpp
+++ b/xml_converter/src/attribute/profession_filter_gen.cpp
@@ -101,18 +101,19 @@ string profession_filter_to_xml_attribute(const std::string& attribute_name, con
     return " " + attribute_name + "=\"" + output + "\"";
 }
 
-ProfessionFilter from_proto_profession_filter(waypoint::ProfessionFilter proto_profession_filter) {
+void proto_to_profession_filter(waypoint::ProfessionFilter input, ProfessionFilter* value, bool* is_set) {
     ProfessionFilter profession_filter;
-    profession_filter.guardian = proto_profession_filter.guardian();
-    profession_filter.warrior = proto_profession_filter.warrior();
-    profession_filter.engineer = proto_profession_filter.engineer();
-    profession_filter.ranger = proto_profession_filter.ranger();
-    profession_filter.thief = proto_profession_filter.thief();
-    profession_filter.elementalist = proto_profession_filter.elementalist();
-    profession_filter.mesmer = proto_profession_filter.mesmer();
-    profession_filter.necromancer = proto_profession_filter.necromancer();
-    profession_filter.revenant = proto_profession_filter.revenant();
-    return profession_filter;
+    profession_filter.guardian = input.guardian();
+    profession_filter.warrior = input.warrior();
+    profession_filter.engineer = input.engineer();
+    profession_filter.ranger = input.ranger();
+    profession_filter.thief = input.thief();
+    profession_filter.elementalist = input.elementalist();
+    profession_filter.mesmer = input.mesmer();
+    profession_filter.necromancer = input.necromancer();
+    profession_filter.revenant = input.revenant();
+    *value = profession_filter;
+    *is_set = true;
 }
 
 void profession_filter_to_proto(ProfessionFilter value, std::function<void(waypoint::ProfessionFilter*)> setter) {
diff --git a/xml_converter/src/attribute/profession_filter_gen.hpp b/xml_converter/src/attribute/profession_filter_gen.hpp
index 0d0cbf8a..3c11493c 100644
--- a/xml_converter/src/attribute/profession_filter_gen.hpp
+++ b/xml_converter/src/attribute/profession_filter_gen.hpp
@@ -31,8 +31,9 @@ void xml_attribute_to_profession_filter(
     std::vector<XMLError*>* errors,
     ProfessionFilter* value,
     bool* is_set);
+
 std::string profession_filter_to_xml_attribute(const std::string& attribute_name, const ProfessionFilter* value);
 
-ProfessionFilter from_proto_profession_filter(waypoint::ProfessionFilter proto_profession_filter);
+void proto_to_profession_filter(waypoint::ProfessionFilter input, ProfessionFilter* value, bool* is_set);
 
 void profession_filter_to_proto(ProfessionFilter value, std::function<void(waypoint::ProfessionFilter*)> setter);
diff --git a/xml_converter/src/attribute/reset_behavior_gen.cpp b/xml_converter/src/attribute/reset_behavior_gen.cpp
index 40d1e184..3fdbb3ec 100644
--- a/xml_converter/src/attribute/reset_behavior_gen.cpp
+++ b/xml_converter/src/attribute/reset_behavior_gen.cpp
@@ -141,28 +141,48 @@ string reset_behavior_to_xml_attribute(const std::string& attribute_name, const
     }
 }
 
-ResetBehavior from_proto_reset_behavior(waypoint::ResetBehavior proto_reset_behavior) {
-    switch (proto_reset_behavior) {
+void proto_to_reset_behavior(waypoint::ResetBehavior input, ResetBehavior* value, bool* is_set) {
+    switch (input) {
         case waypoint::ResetBehavior::always_visible:
-            return ResetBehavior::always_visible;
+            *value = ResetBehavior::always_visible;
+            *is_set = true;
+            break;
         case waypoint::ResetBehavior::map_change:
-            return ResetBehavior::map_change;
+            *value = ResetBehavior::map_change;
+            *is_set = true;
+            break;
         case waypoint::ResetBehavior::daily_reset:
-            return ResetBehavior::daily_reset;
+            *value = ResetBehavior::daily_reset;
+            *is_set = true;
+            break;
         case waypoint::ResetBehavior::never:
-            return ResetBehavior::never;
+            *value = ResetBehavior::never;
+            *is_set = true;
+            break;
         case waypoint::ResetBehavior::timer:
-            return ResetBehavior::timer;
+            *value = ResetBehavior::timer;
+            *is_set = true;
+            break;
         case waypoint::ResetBehavior::map_reset:
-            return ResetBehavior::map_reset;
+            *value = ResetBehavior::map_reset;
+            *is_set = true;
+            break;
         case waypoint::ResetBehavior::instance_change:
-            return ResetBehavior::instance_change;
+            *value = ResetBehavior::instance_change;
+            *is_set = true;
+            break;
         case waypoint::ResetBehavior::daily_reset_per_character:
-            return ResetBehavior::daily_reset_per_character;
+            *value = ResetBehavior::daily_reset_per_character;
+            *is_set = true;
+            break;
         case waypoint::ResetBehavior::weekly_reset:
-            return ResetBehavior::weekly_reset;
+            *value = ResetBehavior::weekly_reset;
+            *is_set = true;
+            break;
         default:
-            return ResetBehavior::always_visible;
+            *value = ResetBehavior::always_visible;
+            *is_set = true;
+            break;
     }
 }
 
diff --git a/xml_converter/src/attribute/reset_behavior_gen.hpp b/xml_converter/src/attribute/reset_behavior_gen.hpp
index 7902ca24..d9bfeede 100644
--- a/xml_converter/src/attribute/reset_behavior_gen.hpp
+++ b/xml_converter/src/attribute/reset_behavior_gen.hpp
@@ -25,8 +25,9 @@ void xml_attribute_to_reset_behavior(
     std::vector<XMLError*>* errors,
     ResetBehavior* value,
     bool* is_set);
+
 std::string reset_behavior_to_xml_attribute(const std::string& attribute_name, const ResetBehavior* value);
 
-ResetBehavior from_proto_reset_behavior(waypoint::ResetBehavior proto_reset_behavior);
+void proto_to_reset_behavior(waypoint::ResetBehavior input, ResetBehavior* value, bool* is_set);
 
 void reset_behavior_to_proto(ResetBehavior value, std::function<void(waypoint::ResetBehavior)> setter);
diff --git a/xml_converter/src/attribute/specialization_filter_gen.cpp b/xml_converter/src/attribute/specialization_filter_gen.cpp
index 1d93dec9..c06f3958 100644
--- a/xml_converter/src/attribute/specialization_filter_gen.cpp
+++ b/xml_converter/src/attribute/specialization_filter_gen.cpp
@@ -623,81 +623,82 @@ string specialization_filter_to_xml_attribute(const std::string& attribute_name,
     return " " + attribute_name + "=\"" + output + "\"";
 }
 
-SpecializationFilter from_proto_specialization_filter(waypoint::SpecializationFilter proto_specialization_filter) {
+void proto_to_specialization_filter(waypoint::SpecializationFilter input, SpecializationFilter* value, bool* is_set) {
     SpecializationFilter specialization_filter;
-    specialization_filter.elementalist_tempest = proto_specialization_filter.elementalist_tempest();
-    specialization_filter.engineer_scrapper = proto_specialization_filter.engineer_scrapper();
-    specialization_filter.guardian_dragonhunter = proto_specialization_filter.guardian_dragonhunter();
-    specialization_filter.mesmer_chronomancer = proto_specialization_filter.mesmer_chronomancer();
-    specialization_filter.necromancer_reaper = proto_specialization_filter.necromancer_reaper();
-    specialization_filter.ranger_druid = proto_specialization_filter.ranger_druid();
-    specialization_filter.revenant_herald = proto_specialization_filter.revenant_herald();
-    specialization_filter.thief_daredevil = proto_specialization_filter.thief_daredevil();
-    specialization_filter.warrior_berserker = proto_specialization_filter.warrior_berserker();
-    specialization_filter.elementalist_weaver = proto_specialization_filter.elementalist_weaver();
-    specialization_filter.engineer_holosmith = proto_specialization_filter.engineer_holosmith();
-    specialization_filter.guardian_firebrand = proto_specialization_filter.guardian_firebrand();
-    specialization_filter.mesmer_mirage = proto_specialization_filter.mesmer_mirage();
-    specialization_filter.necromancer_scourge = proto_specialization_filter.necromancer_scourge();
-    specialization_filter.ranger_soulbeast = proto_specialization_filter.ranger_soulbeast();
-    specialization_filter.revenant_renegade = proto_specialization_filter.revenant_renegade();
-    specialization_filter.thief_deadeye = proto_specialization_filter.thief_deadeye();
-    specialization_filter.warrior_spellbreaker = proto_specialization_filter.warrior_spellbreaker();
-    specialization_filter.elementalist_catalyst = proto_specialization_filter.elementalist_catalyst();
-    specialization_filter.engineer_mechanist = proto_specialization_filter.engineer_mechanist();
-    specialization_filter.guardian_willbender = proto_specialization_filter.guardian_willbender();
-    specialization_filter.mesmer_virtuoso = proto_specialization_filter.mesmer_virtuoso();
-    specialization_filter.necromancer_harbinger = proto_specialization_filter.necromancer_harbinger();
-    specialization_filter.ranger_untamed = proto_specialization_filter.ranger_untamed();
-    specialization_filter.revenant_vindicator = proto_specialization_filter.revenant_vindicator();
-    specialization_filter.thief_specter = proto_specialization_filter.thief_specter();
-    specialization_filter.warrior_bladesworn = proto_specialization_filter.warrior_bladesworn();
-    specialization_filter.elementalist_air = proto_specialization_filter.elementalist_air();
-    specialization_filter.elementalist_arcane = proto_specialization_filter.elementalist_arcane();
-    specialization_filter.elementalist_earth = proto_specialization_filter.elementalist_earth();
-    specialization_filter.elementalist_fire = proto_specialization_filter.elementalist_fire();
-    specialization_filter.elementalist_water = proto_specialization_filter.elementalist_water();
-    specialization_filter.engineer_alchemy = proto_specialization_filter.engineer_alchemy();
-    specialization_filter.engineer_explosives = proto_specialization_filter.engineer_explosives();
-    specialization_filter.engineer_firearms = proto_specialization_filter.engineer_firearms();
-    specialization_filter.engineer_inventions = proto_specialization_filter.engineer_inventions();
-    specialization_filter.engineer_tools = proto_specialization_filter.engineer_tools();
-    specialization_filter.guardian_honor = proto_specialization_filter.guardian_honor();
-    specialization_filter.guardian_radiance = proto_specialization_filter.guardian_radiance();
-    specialization_filter.guardian_valor = proto_specialization_filter.guardian_valor();
-    specialization_filter.guardian_virtues = proto_specialization_filter.guardian_virtues();
-    specialization_filter.guardian_zeal = proto_specialization_filter.guardian_zeal();
-    specialization_filter.mesmer_chaos = proto_specialization_filter.mesmer_chaos();
-    specialization_filter.mesmer_domination = proto_specialization_filter.mesmer_domination();
-    specialization_filter.mesmer_dueling = proto_specialization_filter.mesmer_dueling();
-    specialization_filter.mesmer_illusions = proto_specialization_filter.mesmer_illusions();
-    specialization_filter.mesmer_inspiration = proto_specialization_filter.mesmer_inspiration();
-    specialization_filter.necromancer_blood_magic = proto_specialization_filter.necromancer_blood_magic();
-    specialization_filter.necromancer_curses = proto_specialization_filter.necromancer_curses();
-    specialization_filter.necromancer_death_magic = proto_specialization_filter.necromancer_death_magic();
-    specialization_filter.necromancer_soul_reaping = proto_specialization_filter.necromancer_soul_reaping();
-    specialization_filter.necromancer_spite = proto_specialization_filter.necromancer_spite();
-    specialization_filter.ranger_beastmastery = proto_specialization_filter.ranger_beastmastery();
-    specialization_filter.ranger_marksmanship = proto_specialization_filter.ranger_marksmanship();
-    specialization_filter.ranger_nature_magic = proto_specialization_filter.ranger_nature_magic();
-    specialization_filter.ranger_skirmishing = proto_specialization_filter.ranger_skirmishing();
-    specialization_filter.ranger_wilderness_survival = proto_specialization_filter.ranger_wilderness_survival();
-    specialization_filter.revenant_corruption = proto_specialization_filter.revenant_corruption();
-    specialization_filter.revenant_devastation = proto_specialization_filter.revenant_devastation();
-    specialization_filter.revenant_invocation = proto_specialization_filter.revenant_invocation();
-    specialization_filter.revenant_retribution = proto_specialization_filter.revenant_retribution();
-    specialization_filter.revenant_salvation = proto_specialization_filter.revenant_salvation();
-    specialization_filter.thief_acrobatics = proto_specialization_filter.thief_acrobatics();
-    specialization_filter.thief_critical_strikes = proto_specialization_filter.thief_critical_strikes();
-    specialization_filter.thief_deadly_arts = proto_specialization_filter.thief_deadly_arts();
-    specialization_filter.thief_shadow_arts = proto_specialization_filter.thief_shadow_arts();
-    specialization_filter.thief_trickery = proto_specialization_filter.thief_trickery();
-    specialization_filter.warrior_arms = proto_specialization_filter.warrior_arms();
-    specialization_filter.warrior_defense = proto_specialization_filter.warrior_defense();
-    specialization_filter.warrior_discipline = proto_specialization_filter.warrior_discipline();
-    specialization_filter.warrior_strength = proto_specialization_filter.warrior_strength();
-    specialization_filter.warrior_tactics = proto_specialization_filter.warrior_tactics();
-    return specialization_filter;
+    specialization_filter.elementalist_tempest = input.elementalist_tempest();
+    specialization_filter.engineer_scrapper = input.engineer_scrapper();
+    specialization_filter.guardian_dragonhunter = input.guardian_dragonhunter();
+    specialization_filter.mesmer_chronomancer = input.mesmer_chronomancer();
+    specialization_filter.necromancer_reaper = input.necromancer_reaper();
+    specialization_filter.ranger_druid = input.ranger_druid();
+    specialization_filter.revenant_herald = input.revenant_herald();
+    specialization_filter.thief_daredevil = input.thief_daredevil();
+    specialization_filter.warrior_berserker = input.warrior_berserker();
+    specialization_filter.elementalist_weaver = input.elementalist_weaver();
+    specialization_filter.engineer_holosmith = input.engineer_holosmith();
+    specialization_filter.guardian_firebrand = input.guardian_firebrand();
+    specialization_filter.mesmer_mirage = input.mesmer_mirage();
+    specialization_filter.necromancer_scourge = input.necromancer_scourge();
+    specialization_filter.ranger_soulbeast = input.ranger_soulbeast();
+    specialization_filter.revenant_renegade = input.revenant_renegade();
+    specialization_filter.thief_deadeye = input.thief_deadeye();
+    specialization_filter.warrior_spellbreaker = input.warrior_spellbreaker();
+    specialization_filter.elementalist_catalyst = input.elementalist_catalyst();
+    specialization_filter.engineer_mechanist = input.engineer_mechanist();
+    specialization_filter.guardian_willbender = input.guardian_willbender();
+    specialization_filter.mesmer_virtuoso = input.mesmer_virtuoso();
+    specialization_filter.necromancer_harbinger = input.necromancer_harbinger();
+    specialization_filter.ranger_untamed = input.ranger_untamed();
+    specialization_filter.revenant_vindicator = input.revenant_vindicator();
+    specialization_filter.thief_specter = input.thief_specter();
+    specialization_filter.warrior_bladesworn = input.warrior_bladesworn();
+    specialization_filter.elementalist_air = input.elementalist_air();
+    specialization_filter.elementalist_arcane = input.elementalist_arcane();
+    specialization_filter.elementalist_earth = input.elementalist_earth();
+    specialization_filter.elementalist_fire = input.elementalist_fire();
+    specialization_filter.elementalist_water = input.elementalist_water();
+    specialization_filter.engineer_alchemy = input.engineer_alchemy();
+    specialization_filter.engineer_explosives = input.engineer_explosives();
+    specialization_filter.engineer_firearms = input.engineer_firearms();
+    specialization_filter.engineer_inventions = input.engineer_inventions();
+    specialization_filter.engineer_tools = input.engineer_tools();
+    specialization_filter.guardian_honor = input.guardian_honor();
+    specialization_filter.guardian_radiance = input.guardian_radiance();
+    specialization_filter.guardian_valor = input.guardian_valor();
+    specialization_filter.guardian_virtues = input.guardian_virtues();
+    specialization_filter.guardian_zeal = input.guardian_zeal();
+    specialization_filter.mesmer_chaos = input.mesmer_chaos();
+    specialization_filter.mesmer_domination = input.mesmer_domination();
+    specialization_filter.mesmer_dueling = input.mesmer_dueling();
+    specialization_filter.mesmer_illusions = input.mesmer_illusions();
+    specialization_filter.mesmer_inspiration = input.mesmer_inspiration();
+    specialization_filter.necromancer_blood_magic = input.necromancer_blood_magic();
+    specialization_filter.necromancer_curses = input.necromancer_curses();
+    specialization_filter.necromancer_death_magic = input.necromancer_death_magic();
+    specialization_filter.necromancer_soul_reaping = input.necromancer_soul_reaping();
+    specialization_filter.necromancer_spite = input.necromancer_spite();
+    specialization_filter.ranger_beastmastery = input.ranger_beastmastery();
+    specialization_filter.ranger_marksmanship = input.ranger_marksmanship();
+    specialization_filter.ranger_nature_magic = input.ranger_nature_magic();
+    specialization_filter.ranger_skirmishing = input.ranger_skirmishing();
+    specialization_filter.ranger_wilderness_survival = input.ranger_wilderness_survival();
+    specialization_filter.revenant_corruption = input.revenant_corruption();
+    specialization_filter.revenant_devastation = input.revenant_devastation();
+    specialization_filter.revenant_invocation = input.revenant_invocation();
+    specialization_filter.revenant_retribution = input.revenant_retribution();
+    specialization_filter.revenant_salvation = input.revenant_salvation();
+    specialization_filter.thief_acrobatics = input.thief_acrobatics();
+    specialization_filter.thief_critical_strikes = input.thief_critical_strikes();
+    specialization_filter.thief_deadly_arts = input.thief_deadly_arts();
+    specialization_filter.thief_shadow_arts = input.thief_shadow_arts();
+    specialization_filter.thief_trickery = input.thief_trickery();
+    specialization_filter.warrior_arms = input.warrior_arms();
+    specialization_filter.warrior_defense = input.warrior_defense();
+    specialization_filter.warrior_discipline = input.warrior_discipline();
+    specialization_filter.warrior_strength = input.warrior_strength();
+    specialization_filter.warrior_tactics = input.warrior_tactics();
+    *value = specialization_filter;
+    *is_set = true;
 }
 
 void specialization_filter_to_proto(SpecializationFilter value, std::function<void(waypoint::SpecializationFilter*)> setter) {
diff --git a/xml_converter/src/attribute/specialization_filter_gen.hpp b/xml_converter/src/attribute/specialization_filter_gen.hpp
index fe9eba54..586bff71 100644
--- a/xml_converter/src/attribute/specialization_filter_gen.hpp
+++ b/xml_converter/src/attribute/specialization_filter_gen.hpp
@@ -94,8 +94,9 @@ void xml_attribute_to_specialization_filter(
     std::vector<XMLError*>* errors,
     SpecializationFilter* value,
     bool* is_set);
+
 std::string specialization_filter_to_xml_attribute(const std::string& attribute_name, const SpecializationFilter* value);
 
-SpecializationFilter from_proto_specialization_filter(waypoint::SpecializationFilter proto_specialization_filter);
+void proto_to_specialization_filter(waypoint::SpecializationFilter input, SpecializationFilter* value, bool* is_set);
 
 void specialization_filter_to_proto(SpecializationFilter value, std::function<void(waypoint::SpecializationFilter*)> setter);
diff --git a/xml_converter/src/attribute/species_filter_gen.cpp b/xml_converter/src/attribute/species_filter_gen.cpp
index 73f5cbfc..fda583eb 100644
--- a/xml_converter/src/attribute/species_filter_gen.cpp
+++ b/xml_converter/src/attribute/species_filter_gen.cpp
@@ -73,14 +73,15 @@ string species_filter_to_xml_attribute(const std::string& attribute_name, const
     return " " + attribute_name + "=\"" + output + "\"";
 }
 
-SpeciesFilter from_proto_species_filter(waypoint::SpeciesFilter proto_species_filter) {
+void proto_to_species_filter(waypoint::SpeciesFilter input, SpeciesFilter* value, bool* is_set) {
     SpeciesFilter species_filter;
-    species_filter.asura = proto_species_filter.asura();
-    species_filter.charr = proto_species_filter.charr();
-    species_filter.human = proto_species_filter.human();
-    species_filter.norn = proto_species_filter.norn();
-    species_filter.sylvari = proto_species_filter.sylvari();
-    return species_filter;
+    species_filter.asura = input.asura();
+    species_filter.charr = input.charr();
+    species_filter.human = input.human();
+    species_filter.norn = input.norn();
+    species_filter.sylvari = input.sylvari();
+    *value = species_filter;
+    *is_set = true;
 }
 
 void species_filter_to_proto(SpeciesFilter value, std::function<void(waypoint::SpeciesFilter*)> setter) {
diff --git a/xml_converter/src/attribute/species_filter_gen.hpp b/xml_converter/src/attribute/species_filter_gen.hpp
index ceb45754..51de4d7d 100644
--- a/xml_converter/src/attribute/species_filter_gen.hpp
+++ b/xml_converter/src/attribute/species_filter_gen.hpp
@@ -27,8 +27,9 @@ void xml_attribute_to_species_filter(
     std::vector<XMLError*>* errors,
     SpeciesFilter* value,
     bool* is_set);
+
 std::string species_filter_to_xml_attribute(const std::string& attribute_name, const SpeciesFilter* value);
 
-SpeciesFilter from_proto_species_filter(waypoint::SpeciesFilter proto_species_filter);
+void proto_to_species_filter(waypoint::SpeciesFilter input, SpeciesFilter* value, bool* is_set);
 
 void species_filter_to_proto(SpeciesFilter value, std::function<void(waypoint::SpeciesFilter*)> setter);
diff --git a/xml_converter/src/attribute/string.cpp b/xml_converter/src/attribute/string.cpp
index 9aa2a395..b93272e5 100644
--- a/xml_converter/src/attribute/string.cpp
+++ b/xml_converter/src/attribute/string.cpp
@@ -6,6 +6,7 @@
 
 #include "../rapid_helpers.hpp"
 #include "../rapidxml-1.13/rapidxml.hpp"
+#include "../string_helper.hpp"
 
 using namespace std;
 
@@ -32,6 +33,16 @@ string string_to_xml_attribute(const string& attribute_name, const string* value
     return " " + attribute_name + "=\"" + *value + "\"";
 }
 
+////////////////////////////////////////////////////////////////////////////////
+// proto_to_string
+//
+// Parses a string from a proto field.
+////////////////////////////////////////////////////////////////////////////////
+void proto_to_string(string input, string* value, bool* is_set) {
+    *value = input;
+    *is_set = true;
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // string_to_proto
 //
@@ -40,3 +51,15 @@ string string_to_xml_attribute(const string& attribute_name, const string* value
 void string_to_proto(std::string value, std::function<void(std::string)> setter) {
     setter(value);
 }
+
+void proto_display_name_to_display_name_and_name(
+    std::string input,
+    std::string* display_name,
+    bool* is_display_name_set,
+    std::string* name,
+    bool* is_name_set) {
+    *display_name = input;
+    *is_display_name_set = true;
+    *name = normalize(input);
+    *is_name_set = true;
+}
diff --git a/xml_converter/src/attribute/string.hpp b/xml_converter/src/attribute/string.hpp
index 663fe137..97d139c1 100644
--- a/xml_converter/src/attribute/string.hpp
+++ b/xml_converter/src/attribute/string.hpp
@@ -16,9 +16,12 @@ void xml_attribute_to_string(
 
 std::string string_to_xml_attribute(const std::string& attribute_name, const std::string* value);
 
-// Zero Cost Abstraction identity functions to make parsing and writing protobufs more uniform
-inline std::string const& from_proto_string(const std::string& x) {
-    return x;
-}
+void proto_to_string(std::string input, std::string* value, bool* is_set);
 
 void string_to_proto(std::string value, std::function<void(std::string)> setter);
+
+// These do not belong here, they should be split out into attribute specific
+// files. However we dont have a way to dynamically include attribute specific
+// source files yet so they are going to live here until we build that out.
+void proto_display_name_to_display_name_and_name(std::string input, std::string* display_name, bool* is_display_name_set, std::string* name, bool* is_name_set);
+#define do_nothing(...)
diff --git a/xml_converter/src/attribute/trail_data.cpp b/xml_converter/src/attribute/trail_data.cpp
index 4082091f..9de6ac2d 100644
--- a/xml_converter/src/attribute/trail_data.cpp
+++ b/xml_converter/src/attribute/trail_data.cpp
@@ -90,16 +90,17 @@ string trail_data_to_xml_attribute(const string& attribute_name, const TrailData
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// from_proto_trail_data
+// proto_to_trail_data
 //
-// Returns a TrailData parsed from proto.
+// Parses a TrailData from a proto field.
 ////////////////////////////////////////////////////////////////////////////////
-TrailData from_proto_trail_data(waypoint::TrailData attribute_value) {
+void proto_to_trail_data(waypoint::TrailData input, TrailData* value, bool* is_set) {
     TrailData trail_data;
-    trail_data.points_x = {attribute_value.points_x().begin(), attribute_value.points_x().end()};
-    trail_data.points_y = {attribute_value.points_y().begin(), attribute_value.points_y().end()};
-    trail_data.points_z = {attribute_value.points_z().begin(), attribute_value.points_z().end()};
-    return trail_data;
+    trail_data.points_x = {input.points_x().begin(), input.points_x().end()};
+    trail_data.points_y = {input.points_y().begin(), input.points_y().end()};
+    trail_data.points_z = {input.points_z().begin(), input.points_z().end()};
+    *value = trail_data;
+    *is_set = true;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
diff --git a/xml_converter/src/attribute/trail_data.hpp b/xml_converter/src/attribute/trail_data.hpp
index f6d4da39..ee7c7f18 100644
--- a/xml_converter/src/attribute/trail_data.hpp
+++ b/xml_converter/src/attribute/trail_data.hpp
@@ -29,6 +29,6 @@ void xml_attribute_to_trail_data(
 
 std::string trail_data_to_xml_attribute(const std::string& attribute_name, const TrailData* value);
 
-TrailData from_proto_trail_data(waypoint::TrailData attribute_value);
+void proto_to_trail_data(waypoint::TrailData input, TrailData* value, bool* is_set);
 
 void trail_data_to_proto(TrailData value, std::function<void(waypoint::TrailData*)> setter);
diff --git a/xml_converter/src/attribute/unique_id.cpp b/xml_converter/src/attribute/unique_id.cpp
index b8180528..e78fcf5c 100644
--- a/xml_converter/src/attribute/unique_id.cpp
+++ b/xml_converter/src/attribute/unique_id.cpp
@@ -33,11 +33,17 @@ string unique_id_to_xml_attribute(const string& attribute_name, const UniqueId*
     return " " + attribute_name + "=\"" + base64_encode(&(value->guid[0]), value->guid.size()) + "\"";
 }
 
-UniqueId from_proto_unique_id(string attribute_value) {
+////////////////////////////////////////////////////////////////////////////////
+// proto_to_unique_id
+//
+// Parses a UniqueId from a proto field.
+////////////////////////////////////////////////////////////////////////////////
+void proto_to_unique_id(std::string input, UniqueId* value, bool* is_set) {
     UniqueId unique_id;
-    std::vector<uint8_t> guid(attribute_value.begin(), attribute_value.end());
+    std::vector<uint8_t> guid(input.begin(), input.end());
     unique_id.guid = guid;
-    return unique_id;
+    *value = unique_id;
+    *is_set = true;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
diff --git a/xml_converter/src/attribute/unique_id.hpp b/xml_converter/src/attribute/unique_id.hpp
index 830914fc..310ce0e9 100644
--- a/xml_converter/src/attribute/unique_id.hpp
+++ b/xml_converter/src/attribute/unique_id.hpp
@@ -25,6 +25,6 @@ void xml_attribute_to_unique_id(
 
 std::string unique_id_to_xml_attribute(const std::string& attribute_name, const UniqueId* value);
 
-UniqueId from_proto_unique_id(std::string attribute_value);
+void proto_to_unique_id(std::string input, UniqueId* value, bool* is_set);
 
 void unique_id_to_proto(UniqueId value, std::function<void(std::string)> setter);
diff --git a/xml_converter/src/category_gen.cpp b/xml_converter/src/category_gen.cpp
index 037c143c..c530a06e 100644
--- a/xml_converter/src/category_gen.cpp
+++ b/xml_converter/src/category_gen.cpp
@@ -97,7 +97,7 @@ waypoint::Category Category::as_protobuf() const {
         bool_to_proto(this->default_visibility, setter);
     }
     if (this->display_name_is_set) {
-        std::function<void(std::string)> setter = [&proto_category](std::string val) { proto_category.set_display_name(val); };
+        std::function<void(std::string)> setter = [&proto_category](std::string val) { proto_category.set_name(val); };
         string_to_proto(this->display_name, setter);
     }
     if (this->is_separator_is_set) {
@@ -106,7 +106,7 @@ waypoint::Category Category::as_protobuf() const {
     }
     if (this->name_is_set) {
         std::function<void(std::string)> setter = [&proto_category](std::string val) { proto_category.set_name(val); };
-        string_to_proto(this->name, setter);
+        do_nothing(this->name, setter);
     }
     if (this->tooltip_description_is_set) {
         std::function<void(std::string)> setter = [&proto_category](std::string val) { proto_category.set_tip_description(val); };
@@ -117,23 +117,18 @@ waypoint::Category Category::as_protobuf() const {
 
 void Category::parse_protobuf(waypoint::Category proto_category) {
     if (proto_category.default_visibility() != 0) {
-        this->default_visibility = from_proto_bool(proto_category.default_visibility());
-        this->default_visibility_is_set = true;
+        proto_to_bool(proto_category.default_visibility(), &(this->default_visibility), &(this->default_visibility_is_set));
     }
-    if (proto_category.display_name() != "") {
-        this->display_name = from_proto_string(proto_category.display_name());
-        this->display_name_is_set = true;
+    if (proto_category.name() != "") {
+        proto_display_name_to_display_name_and_name(proto_category.name(), &(this->display_name), &(this->display_name_is_set), &(this->name), &(this->name_is_set));
     }
     if (proto_category.is_separator() != 0) {
-        this->is_separator = from_proto_bool(proto_category.is_separator());
-        this->is_separator_is_set = true;
+        proto_to_bool(proto_category.is_separator(), &(this->is_separator), &(this->is_separator_is_set));
     }
     if (proto_category.name() != "") {
-        this->name = from_proto_string(proto_category.name());
-        this->name_is_set = true;
+        do_nothing(proto_category.name(), &(this->name), &(this->name_is_set));
     }
     if (proto_category.tip_description() != "") {
-        this->tooltip_description = from_proto_string(proto_category.tip_description());
-        this->tooltip_description_is_set = true;
+        proto_to_string(proto_category.tip_description(), &(this->tooltip_description), &(this->tooltip_description_is_set));
     }
 }
diff --git a/xml_converter/src/icon_gen.cpp b/xml_converter/src/icon_gen.cpp
index 23b67434..573d5e72 100644
--- a/xml_converter/src/icon_gen.cpp
+++ b/xml_converter/src/icon_gen.cpp
@@ -601,191 +601,144 @@ waypoint::Icon Icon::as_protobuf() const {
 
 void Icon::parse_protobuf(waypoint::Icon proto_icon) {
     if (proto_icon.achievement_bit() != 0) {
-        this->achievement_bitmask = from_proto_int(proto_icon.achievement_bit());
-        this->achievement_bitmask_is_set = true;
+        proto_to_int(proto_icon.achievement_bit(), &(this->achievement_bitmask), &(this->achievement_bitmask_is_set));
     }
     if (proto_icon.achievement_id() != 0) {
-        this->achievement_id = from_proto_int(proto_icon.achievement_id());
-        this->achievement_id_is_set = true;
+        proto_to_int(proto_icon.achievement_id(), &(this->achievement_id), &(this->achievement_id_is_set));
     }
     if (proto_icon.trigger().auto_trigger() != 0) {
-        this->auto_trigger = from_proto_bool(proto_icon.trigger().auto_trigger());
-        this->auto_trigger_is_set = true;
+        proto_to_bool(proto_icon.trigger().auto_trigger(), &(this->auto_trigger), &(this->auto_trigger_is_set));
     }
     if (proto_icon.trigger().bounce_delay() != 0) {
-        this->bounce_delay = from_proto_float(proto_icon.trigger().bounce_delay());
-        this->bounce_delay_is_set = true;
+        proto_to_float(proto_icon.trigger().bounce_delay(), &(this->bounce_delay), &(this->bounce_delay_is_set));
     }
     if (proto_icon.trigger().bounce_duration() != 0) {
-        this->bounce_duration = from_proto_float(proto_icon.trigger().bounce_duration());
-        this->bounce_duration_is_set = true;
+        proto_to_float(proto_icon.trigger().bounce_duration(), &(this->bounce_duration), &(this->bounce_duration_is_set));
     }
     if (proto_icon.trigger().bounce_height() != 0) {
-        this->bounce_height = from_proto_float(proto_icon.trigger().bounce_height());
-        this->bounce_height_is_set = true;
+        proto_to_float(proto_icon.trigger().bounce_height(), &(this->bounce_height), &(this->bounce_height_is_set));
     }
     if (proto_icon.can_fade() != 0) {
-        this->can_fade = from_proto_bool(proto_icon.can_fade());
-        this->can_fade_is_set = true;
+        proto_to_bool(proto_icon.can_fade(), &(this->can_fade), &(this->can_fade_is_set));
     }
     if (proto_icon.has_category()) {
-        this->category = from_proto_marker_category(proto_icon.category());
-        this->category_is_set = true;
+        proto_to_marker_category(proto_icon.category(), &(this->category), &(this->category_is_set));
     }
     if (proto_icon.has_rgba_color()) {
-        this->color = from_proto_color(proto_icon.rgba_color());
-        this->color_is_set = true;
+        proto_to_color(proto_icon.rgba_color(), &(this->color), &(this->color_is_set));
     }
     if (proto_icon.trigger().action_copy_clipboard() != "") {
-        this->copy_clipboard = from_proto_string(proto_icon.trigger().action_copy_clipboard());
-        this->copy_clipboard_is_set = true;
+        proto_to_string(proto_icon.trigger().action_copy_clipboard(), &(this->copy_clipboard), &(this->copy_clipboard_is_set));
     }
     if (proto_icon.trigger().action_copy_message() != "") {
-        this->copy_message = from_proto_string(proto_icon.trigger().action_copy_message());
-        this->copy_message_is_set = true;
+        proto_to_string(proto_icon.trigger().action_copy_message(), &(this->copy_message), &(this->copy_message_is_set));
     }
     if (proto_icon.cull_chirality() != 0) {
-        this->cull_chirality = from_proto_cull_chirality(proto_icon.cull_chirality());
-        this->cull_chirality_is_set = true;
+        proto_to_cull_chirality(proto_icon.cull_chirality(), &(this->cull_chirality), &(this->cull_chirality_is_set));
     }
     if (proto_icon.distance_fade_end() != 0) {
-        this->distance_fade_end = from_proto_float(proto_icon.distance_fade_end());
-        this->distance_fade_end_is_set = true;
+        proto_to_float(proto_icon.distance_fade_end(), &(this->distance_fade_end), &(this->distance_fade_end_is_set));
     }
     if (proto_icon.distance_fade_start() != 0) {
-        this->distance_fade_start = from_proto_float(proto_icon.distance_fade_start());
-        this->distance_fade_start_is_set = true;
+        proto_to_float(proto_icon.distance_fade_start(), &(this->distance_fade_start), &(this->distance_fade_start_is_set));
     }
     if (proto_icon.has_euler_rotation()) {
-        this->euler_rotation = from_proto_euler_rotation(proto_icon.euler_rotation());
-        this->euler_rotation_is_set = true;
+        proto_to_euler_rotation(proto_icon.euler_rotation(), &(this->euler_rotation), &(this->euler_rotation_is_set));
     }
     if (proto_icon.has_festival_filter()) {
-        this->festival_filter = from_proto_festival_filter(proto_icon.festival_filter());
-        this->festival_filter_is_set = true;
+        proto_to_festival_filter(proto_icon.festival_filter(), &(this->festival_filter), &(this->festival_filter_is_set));
     }
     if (proto_icon.guid() != "") {
-        this->guid = from_proto_unique_id(proto_icon.guid());
-        this->guid_is_set = true;
+        proto_to_unique_id(proto_icon.guid(), &(this->guid), &(this->guid_is_set));
     }
     if (proto_icon.trigger().has_countdown() != 0) {
-        this->has_countdown = from_proto_bool(proto_icon.trigger().has_countdown());
-        this->has_countdown_is_set = true;
+        proto_to_bool(proto_icon.trigger().has_countdown(), &(this->has_countdown), &(this->has_countdown_is_set));
     }
     if (proto_icon.height_offset() != 0) {
-        this->height_offset = from_proto_float(proto_icon.height_offset());
-        this->height_offset_is_set = true;
+        proto_to_float(proto_icon.height_offset(), &(this->height_offset), &(this->height_offset_is_set));
     }
     if (proto_icon.trigger().has_action_hide_category()) {
-        this->hide_category = from_proto_marker_category(proto_icon.trigger().action_hide_category());
-        this->hide_category_is_set = true;
+        proto_to_marker_category(proto_icon.trigger().action_hide_category(), &(this->hide_category), &(this->hide_category_is_set));
     }
     if (proto_icon.has_texture_path()) {
-        this->icon = from_proto_image(proto_icon.texture_path());
-        this->icon_is_set = true;
+        proto_to_image(proto_icon.texture_path(), &(this->icon), &(this->icon_is_set));
     }
     if (proto_icon.tentative__scale() != 0) {
-        this->icon_size = from_proto_float(proto_icon.tentative__scale());
-        this->icon_size_is_set = true;
+        proto_to_float(proto_icon.tentative__scale(), &(this->icon_size), &(this->icon_size_is_set));
     }
     if (proto_icon.trigger().action_info_message() != "") {
-        this->info_message = from_proto_string(proto_icon.trigger().action_info_message());
-        this->info_message_is_set = true;
+        proto_to_string(proto_icon.trigger().action_info_message(), &(this->info_message), &(this->info_message_is_set));
     }
     if (proto_icon.trigger().invert_display() != 0) {
-        this->invert_visibility = from_proto_bool(proto_icon.trigger().invert_display());
-        this->invert_visibility_is_set = true;
+        proto_to_bool(proto_icon.trigger().invert_display(), &(this->invert_visibility), &(this->invert_visibility_is_set));
     }
     if (proto_icon.map_display_size() != 0) {
-        this->map_display_size = from_proto_int(proto_icon.map_display_size());
-        this->map_display_size_is_set = true;
+        proto_to_int(proto_icon.map_display_size(), &(this->map_display_size), &(this->map_display_size_is_set));
     }
     if (proto_icon.map_id() != 0) {
-        this->map_id = from_proto_int(proto_icon.map_id());
-        this->map_id_is_set = true;
+        proto_to_int(proto_icon.map_id(), &(this->map_id), &(this->map_id_is_set));
     }
     if (proto_icon.has_map_type_filter()) {
-        this->map_type_filter = from_proto_map_type_filter(proto_icon.map_type_filter());
-        this->map_type_filter_is_set = true;
+        proto_to_map_type_filter(proto_icon.map_type_filter(), &(this->map_type_filter), &(this->map_type_filter_is_set));
     }
     if (proto_icon.maximum_size_on_screen() != 0) {
-        this->maximum_size_on_screen = from_proto_int(proto_icon.maximum_size_on_screen());
-        this->maximum_size_on_screen_is_set = true;
+        proto_to_int(proto_icon.maximum_size_on_screen(), &(this->maximum_size_on_screen), &(this->maximum_size_on_screen_is_set));
     }
     if (proto_icon.minimum_size_on_screen() != 0) {
-        this->minimum_size_on_screen = from_proto_int(proto_icon.minimum_size_on_screen());
-        this->minimum_size_on_screen_is_set = true;
+        proto_to_int(proto_icon.minimum_size_on_screen(), &(this->minimum_size_on_screen), &(this->minimum_size_on_screen_is_set));
     }
     if (proto_icon.has_mount_filter()) {
-        this->mount_filter = from_proto_mount_filter(proto_icon.mount_filter());
-        this->mount_filter_is_set = true;
+        proto_to_mount_filter(proto_icon.mount_filter(), &(this->mount_filter), &(this->mount_filter_is_set));
     }
     if (proto_icon.has_position()) {
-        this->position = from_proto_position(proto_icon.position());
-        this->position_is_set = true;
+        proto_to_position(proto_icon.position(), &(this->position), &(this->position_is_set));
     }
     if (proto_icon.has_profession_filter()) {
-        this->profession_filter = from_proto_profession_filter(proto_icon.profession_filter());
-        this->profession_filter_is_set = true;
+        proto_to_profession_filter(proto_icon.profession_filter(), &(this->profession_filter), &(this->profession_filter_is_set));
     }
     if (proto_icon.tentative__render_ingame() != 0) {
-        this->render_ingame = from_proto_bool(proto_icon.tentative__render_ingame());
-        this->render_ingame_is_set = true;
+        proto_to_bool(proto_icon.tentative__render_ingame(), &(this->render_ingame), &(this->render_ingame_is_set));
     }
     if (proto_icon.tentative__render_on_map() != 0) {
-        this->render_on_map = from_proto_bool(proto_icon.tentative__render_on_map());
-        this->render_on_map_is_set = true;
+        proto_to_bool(proto_icon.tentative__render_on_map(), &(this->render_on_map), &(this->render_on_map_is_set));
     }
     if (proto_icon.tentative__render_on_minimap() != 0) {
-        this->render_on_minimap = from_proto_bool(proto_icon.tentative__render_on_minimap());
-        this->render_on_minimap_is_set = true;
+        proto_to_bool(proto_icon.tentative__render_on_minimap(), &(this->render_on_minimap), &(this->render_on_minimap_is_set));
     }
     if (proto_icon.trigger().reset_behavior() != 0) {
-        this->reset_behavior = from_proto_reset_behavior(proto_icon.trigger().reset_behavior());
-        this->reset_behavior_is_set = true;
+        proto_to_reset_behavior(proto_icon.trigger().reset_behavior(), &(this->reset_behavior), &(this->reset_behavior_is_set));
     }
     if (proto_icon.trigger().reset_length() != 0) {
-        this->reset_length = from_proto_float(proto_icon.trigger().reset_length());
-        this->reset_length_is_set = true;
+        proto_to_float(proto_icon.trigger().reset_length(), &(this->reset_length), &(this->reset_length_is_set));
     }
     if (proto_icon.scale_on_map_with_zoom() != 0) {
-        this->scale_on_map_with_zoom = from_proto_bool(proto_icon.scale_on_map_with_zoom());
-        this->scale_on_map_with_zoom_is_set = true;
+        proto_to_bool(proto_icon.scale_on_map_with_zoom(), &(this->scale_on_map_with_zoom), &(this->scale_on_map_with_zoom_is_set));
     }
     if (proto_icon.bhdraft__schedule() != "") {
-        this->schedule = from_proto_string(proto_icon.bhdraft__schedule());
-        this->schedule_is_set = true;
+        proto_to_string(proto_icon.bhdraft__schedule(), &(this->schedule), &(this->schedule_is_set));
     }
     if (proto_icon.bhdraft__schedule_duration() != 0) {
-        this->schedule_duration = from_proto_float(proto_icon.bhdraft__schedule_duration());
-        this->schedule_duration_is_set = true;
+        proto_to_float(proto_icon.bhdraft__schedule_duration(), &(this->schedule_duration), &(this->schedule_duration_is_set));
     }
     if (proto_icon.trigger().has_action_show_category()) {
-        this->show_category = from_proto_marker_category(proto_icon.trigger().action_show_category());
-        this->show_category_is_set = true;
+        proto_to_marker_category(proto_icon.trigger().action_show_category(), &(this->show_category), &(this->show_category_is_set));
     }
     if (proto_icon.has_specialization_filter()) {
-        this->specialization_filter = from_proto_specialization_filter(proto_icon.specialization_filter());
-        this->specialization_filter_is_set = true;
+        proto_to_specialization_filter(proto_icon.specialization_filter(), &(this->specialization_filter), &(this->specialization_filter_is_set));
     }
     if (proto_icon.has_species_filter()) {
-        this->species_filter = from_proto_species_filter(proto_icon.species_filter());
-        this->species_filter_is_set = true;
+        proto_to_species_filter(proto_icon.species_filter(), &(this->species_filter), &(this->species_filter_is_set));
     }
     if (proto_icon.trigger().has_action_toggle_category()) {
-        this->toggle_category = from_proto_marker_category(proto_icon.trigger().action_toggle_category());
-        this->toggle_category_is_set = true;
+        proto_to_marker_category(proto_icon.trigger().action_toggle_category(), &(this->toggle_category), &(this->toggle_category_is_set));
     }
     if (proto_icon.tip_description() != "") {
-        this->tooltip_description = from_proto_string(proto_icon.tip_description());
-        this->tooltip_description_is_set = true;
+        proto_to_string(proto_icon.tip_description(), &(this->tooltip_description), &(this->tooltip_description_is_set));
     }
     if (proto_icon.tip_name() != "") {
-        this->tooltip_name = from_proto_string(proto_icon.tip_name());
-        this->tooltip_name_is_set = true;
+        proto_to_string(proto_icon.tip_name(), &(this->tooltip_name), &(this->tooltip_name_is_set));
     }
     if (proto_icon.trigger().range() != 0) {
-        this->trigger_range = from_proto_float(proto_icon.trigger().range());
-        this->trigger_range_is_set = true;
+        proto_to_float(proto_icon.trigger().range(), &(this->trigger_range), &(this->trigger_range_is_set));
     }
 }
diff --git a/xml_converter/src/trail_gen.cpp b/xml_converter/src/trail_gen.cpp
index b04ae43b..87a14049 100644
--- a/xml_converter/src/trail_gen.cpp
+++ b/xml_converter/src/trail_gen.cpp
@@ -359,111 +359,84 @@ waypoint::Trail Trail::as_protobuf() const {
 
 void Trail::parse_protobuf(waypoint::Trail proto_trail) {
     if (proto_trail.achievement_bit() != 0) {
-        this->achievement_bitmask = from_proto_int(proto_trail.achievement_bit());
-        this->achievement_bitmask_is_set = true;
+        proto_to_int(proto_trail.achievement_bit(), &(this->achievement_bitmask), &(this->achievement_bitmask_is_set));
     }
     if (proto_trail.achievement_id() != 0) {
-        this->achievement_id = from_proto_int(proto_trail.achievement_id());
-        this->achievement_id_is_set = true;
+        proto_to_int(proto_trail.achievement_id(), &(this->achievement_id), &(this->achievement_id_is_set));
     }
     if (proto_trail.animation_speed() != 0) {
-        this->animation_speed = from_proto_float(proto_trail.animation_speed());
-        this->animation_speed_is_set = true;
+        proto_to_float(proto_trail.animation_speed(), &(this->animation_speed), &(this->animation_speed_is_set));
     }
     if (proto_trail.can_fade() != 0) {
-        this->can_fade = from_proto_bool(proto_trail.can_fade());
-        this->can_fade_is_set = true;
+        proto_to_bool(proto_trail.can_fade(), &(this->can_fade), &(this->can_fade_is_set));
     }
     if (proto_trail.has_category()) {
-        this->category = from_proto_marker_category(proto_trail.category());
-        this->category_is_set = true;
+        proto_to_marker_category(proto_trail.category(), &(this->category), &(this->category_is_set));
     }
     if (proto_trail.has_rgba_color()) {
-        this->color = from_proto_color(proto_trail.rgba_color());
-        this->color_is_set = true;
+        proto_to_color(proto_trail.rgba_color(), &(this->color), &(this->color_is_set));
     }
     if (proto_trail.cull_chirality() != 0) {
-        this->cull_chirality = from_proto_cull_chirality(proto_trail.cull_chirality());
-        this->cull_chirality_is_set = true;
+        proto_to_cull_chirality(proto_trail.cull_chirality(), &(this->cull_chirality), &(this->cull_chirality_is_set));
     }
     if (proto_trail.distance_fade_end() != 0) {
-        this->distance_fade_end = from_proto_float(proto_trail.distance_fade_end());
-        this->distance_fade_end_is_set = true;
+        proto_to_float(proto_trail.distance_fade_end(), &(this->distance_fade_end), &(this->distance_fade_end_is_set));
     }
     if (proto_trail.distance_fade_start() != 0) {
-        this->distance_fade_start = from_proto_float(proto_trail.distance_fade_start());
-        this->distance_fade_start_is_set = true;
+        proto_to_float(proto_trail.distance_fade_start(), &(this->distance_fade_start), &(this->distance_fade_start_is_set));
     }
     if (proto_trail.has_festival_filter()) {
-        this->festival_filter = from_proto_festival_filter(proto_trail.festival_filter());
-        this->festival_filter_is_set = true;
+        proto_to_festival_filter(proto_trail.festival_filter(), &(this->festival_filter), &(this->festival_filter_is_set));
     }
     if (proto_trail.guid() != "") {
-        this->guid = from_proto_unique_id(proto_trail.guid());
-        this->guid_is_set = true;
+        proto_to_unique_id(proto_trail.guid(), &(this->guid), &(this->guid_is_set));
     }
     if (proto_trail.is_wall() != 0) {
-        this->is_wall = from_proto_bool(proto_trail.is_wall());
-        this->is_wall_is_set = true;
+        proto_to_bool(proto_trail.is_wall(), &(this->is_wall), &(this->is_wall_is_set));
     }
     if (proto_trail.map_display_size() != 0) {
-        this->map_display_size = from_proto_int(proto_trail.map_display_size());
-        this->map_display_size_is_set = true;
+        proto_to_int(proto_trail.map_display_size(), &(this->map_display_size), &(this->map_display_size_is_set));
     }
     if (proto_trail.map_id() != 0) {
-        this->map_id = from_proto_int(proto_trail.map_id());
-        this->map_id_is_set = true;
+        proto_to_int(proto_trail.map_id(), &(this->map_id), &(this->map_id_is_set));
     }
     if (proto_trail.has_map_type_filter()) {
-        this->map_type_filter = from_proto_map_type_filter(proto_trail.map_type_filter());
-        this->map_type_filter_is_set = true;
+        proto_to_map_type_filter(proto_trail.map_type_filter(), &(this->map_type_filter), &(this->map_type_filter_is_set));
     }
     if (proto_trail.has_mount_filter()) {
-        this->mount_filter = from_proto_mount_filter(proto_trail.mount_filter());
-        this->mount_filter_is_set = true;
+        proto_to_mount_filter(proto_trail.mount_filter(), &(this->mount_filter), &(this->mount_filter_is_set));
     }
     if (proto_trail.has_profession_filter()) {
-        this->profession_filter = from_proto_profession_filter(proto_trail.profession_filter());
-        this->profession_filter_is_set = true;
+        proto_to_profession_filter(proto_trail.profession_filter(), &(this->profession_filter), &(this->profession_filter_is_set));
     }
     if (proto_trail.tentative__render_ingame() != 0) {
-        this->render_ingame = from_proto_bool(proto_trail.tentative__render_ingame());
-        this->render_ingame_is_set = true;
+        proto_to_bool(proto_trail.tentative__render_ingame(), &(this->render_ingame), &(this->render_ingame_is_set));
     }
     if (proto_trail.tentative__render_on_map() != 0) {
-        this->render_on_map = from_proto_bool(proto_trail.tentative__render_on_map());
-        this->render_on_map_is_set = true;
+        proto_to_bool(proto_trail.tentative__render_on_map(), &(this->render_on_map), &(this->render_on_map_is_set));
     }
     if (proto_trail.tentative__render_on_minimap() != 0) {
-        this->render_on_minimap = from_proto_bool(proto_trail.tentative__render_on_minimap());
-        this->render_on_minimap_is_set = true;
+        proto_to_bool(proto_trail.tentative__render_on_minimap(), &(this->render_on_minimap), &(this->render_on_minimap_is_set));
     }
     if (proto_trail.bhdraft__schedule() != "") {
-        this->schedule = from_proto_string(proto_trail.bhdraft__schedule());
-        this->schedule_is_set = true;
+        proto_to_string(proto_trail.bhdraft__schedule(), &(this->schedule), &(this->schedule_is_set));
     }
     if (proto_trail.bhdraft__schedule_duration() != 0) {
-        this->schedule_duration = from_proto_float(proto_trail.bhdraft__schedule_duration());
-        this->schedule_duration_is_set = true;
+        proto_to_float(proto_trail.bhdraft__schedule_duration(), &(this->schedule_duration), &(this->schedule_duration_is_set));
     }
     if (proto_trail.has_specialization_filter()) {
-        this->specialization_filter = from_proto_specialization_filter(proto_trail.specialization_filter());
-        this->specialization_filter_is_set = true;
+        proto_to_specialization_filter(proto_trail.specialization_filter(), &(this->specialization_filter), &(this->specialization_filter_is_set));
     }
     if (proto_trail.has_species_filter()) {
-        this->species_filter = from_proto_species_filter(proto_trail.species_filter());
-        this->species_filter_is_set = true;
+        proto_to_species_filter(proto_trail.species_filter(), &(this->species_filter), &(this->species_filter_is_set));
     }
     if (proto_trail.has_texture_path()) {
-        this->texture = from_proto_image(proto_trail.texture_path());
-        this->texture_is_set = true;
+        proto_to_image(proto_trail.texture_path(), &(this->texture), &(this->texture_is_set));
     }
     if (proto_trail.has_trail_data()) {
-        this->trail_data = from_proto_trail_data(proto_trail.trail_data());
-        this->trail_data_is_set = true;
+        proto_to_trail_data(proto_trail.trail_data(), &(this->trail_data), &(this->trail_data_is_set));
     }
     if (proto_trail.scale() != 0) {
-        this->trail_scale = from_proto_float(proto_trail.scale());
-        this->trail_scale_is_set = true;
+        proto_to_float(proto_trail.scale(), &(this->trail_scale), &(this->trail_scale_is_set));
     }
 }