Make Serialize take an allocated buffer.

Makes memory management more explicit on the client
side.

Change-Id: I517aa8fb916fccec7c61c5dbee51f163a0a947ea
diff --git a/gatekeeper_messages.cpp b/gatekeeper_messages.cpp
index 03f5b3f..abcedf9 100644
--- a/gatekeeper_messages.cpp
+++ b/gatekeeper_messages.cpp
@@ -26,6 +26,11 @@
  * Methods for serializing/deserializing SizedBuffers
  */
 
+struct serial_header_t {
+    uint32_t error;
+    uint32_t user_id;
+};
+
 static inline size_t serialized_buffer_size(const SizedBuffer &buf) {
     return sizeof(uint32_t) + buf.length;
 }
@@ -65,31 +70,37 @@
     }
 }
 
-uint8_t *GateKeeperMessage::Serialize() const {
-    if (error != ERROR_NONE) {
-        uint32_t *error_buf = new uint32_t;
-        *error_buf = static_cast<uint32_t>(error);
-        return reinterpret_cast<uint8_t *>(error_buf);
-    } else {
-        uint8_t *buf = new uint8_t[2*sizeof(uint32_t) + nonErrorSerializedSize()];
-        uint32_t error_value = static_cast<uint32_t>(error);
-        memcpy(buf, &error_value, sizeof(uint32_t));
-        memcpy(buf + sizeof(uint32_t), &user_id, sizeof(user_id));
-        nonErrorSerialize(buf + 2*sizeof(uint32_t));
-        return buf;
+size_t GateKeeperMessage::Serialize(uint8_t *buffer, const uint8_t *end) const {
+    size_t bytes_written = 0;
+    if (buffer + GetSerializedSize() != end) {
+        return 0;
     }
+
+    serial_header_t *header = reinterpret_cast<serial_header_t *>(buffer);
+    if (error != ERROR_NONE) {
+        if (buffer + sizeof(error) > end) return 0;
+        header->error = error;
+        bytes_written += sizeof(error);
+    } else {
+        if (buffer + sizeof(serial_header_t) + nonErrorSerializedSize() > end)
+            return 0;
+        header->error = error;
+        header->user_id = user_id;
+        nonErrorSerialize(buffer + sizeof(*header));
+        bytes_written += sizeof(*header) + nonErrorSerializedSize();
+    }
+
+    return bytes_written;
 }
 
 gatekeeper_error_t GateKeeperMessage::Deserialize(const uint8_t *payload, const uint8_t *end) {
     uint32_t error_value;
     if (payload + sizeof(uint32_t) > end) return ERROR_INVALID;
-    memcpy(&error_value, payload, sizeof(uint32_t));
-    error = static_cast<gatekeeper_error_t>(error_value);
-    payload += sizeof(uint32_t);
-    if (error == ERROR_NONE) {
+    const serial_header_t *header = reinterpret_cast<const serial_header_t *>(payload);
+    if (header->error == ERROR_NONE) {
         if (payload == end) return ERROR_INVALID;
-        user_id = *((uint32_t *) payload);
-        error = nonErrorDeserialize(payload + sizeof(uint32_t), end);
+        user_id = header->user_id;
+        error = nonErrorDeserialize(payload + sizeof(*header), end);
     }
 
     return error;