got binary logging actually fully working (!!!)
diff --git a/aos/common/logging/logging_impl.cc b/aos/common/logging/logging_impl.cc
index bdc14ec..0413072 100644
--- a/aos/common/logging/logging_impl.cc
+++ b/aos/common/logging/logging_impl.cc
@@ -57,16 +57,15 @@
 
 }  // namespace
 namespace internal {
+namespace {
 
-void FillInMessage(log_level level, const char *format, va_list ap,
-                   LogMessage *message) {
+void FillInMessageBase(log_level level, LogMessage *message) {
   Context *context = Context::Get();
 
-  ExecuteFormat(message->message, sizeof(message->message), format, ap);
-
   message->level = level;
   message->source = context->source;
-  memcpy(message->name, context->name.c_str(), context->name.size() + 1);
+  memcpy(message->name, context->name.c_str(), context->name.size());
+  message->name_length = context->name.size();
 
   time::Time now = time::Time::Now();
   message->seconds = now.sec();
@@ -75,12 +74,75 @@
   message->sequence = context->sequence++;
 }
 
+}  // namespace
+
+void FillInMessageStructure(log_level level,
+                            const ::std::string &message_string, size_t size,
+                            const MessageType *type,
+                            const ::std::function<size_t(char *)> &serialize,
+                            LogMessage *message) {
+  type_cache::AddShm(type->id);
+  message->structure.type_id = type->id;
+
+  FillInMessageBase(level, message);
+
+  if (message_string.size() + size > sizeof(message->structure.serialized)) {
+    LOG(FATAL, "serialized struct %s (size %zd) and message %s too big\n",
+        type->name.c_str(), size, message_string.c_str());
+  }
+  message->structure.string_length = message_string.size();
+  memcpy(message->structure.serialized, message_string.data(),
+         message->structure.string_length);
+
+  message->message_length = serialize(
+      &message->structure.serialized[message->structure.string_length]);
+  message->type = LogMessage::Type::kStruct;
+}
+
+void FillInMessage(log_level level, const char *format, va_list ap,
+                   LogMessage *message) {
+  FillInMessageBase(level, message);
+
+  message->message_length =
+      ExecuteFormat(message->message, sizeof(message->message), format, ap);
+  message->type = LogMessage::Type::kString;
+}
+
 void PrintMessage(FILE *output, const LogMessage &message) {
-  fprintf(output, "%s(%" PRId32 ")(%05" PRIu16 "): %s at"
-          " %010" PRId32 ".%09" PRId32 "s: %s",
-          message.name, static_cast<int32_t>(message.source), message.sequence,
-          log_str(message.level), message.seconds, message.nseconds,
-          message.message);
+#define BASE_FORMAT \
+  "%.*s(%" PRId32 ")(%05" PRIu16 "): %s at %010" PRId32 ".%09" PRId32 "s: "
+#define BASE_ARGS                                             \
+  static_cast<int>(message.name_length), message.name,        \
+      static_cast<int32_t>(message.source), message.sequence, \
+      log_str(message.level), message.seconds, message.nseconds
+  switch (message.type) {
+    case LogMessage::Type::kString:
+      fprintf(output, BASE_FORMAT "%.*s", BASE_ARGS,
+              static_cast<int>(message.message_length), message.message);
+      break;
+    case LogMessage::Type::kStruct:
+      char buffer[LOG_MESSAGE_LEN];
+      size_t output_length = sizeof(buffer);
+      size_t input_length = message.message_length;
+      if (!PrintMessage(
+              buffer, &output_length,
+              message.structure.serialized + message.structure.string_length,
+              &input_length, type_cache::Get(message.structure.type_id))) {
+        LOG(FATAL,
+            "printing message (%.*s) of type %s into %zu-byte buffer failed\n",
+            static_cast<int>(message.message_length), message.message,
+            type_cache::Get(message.structure.type_id).name.c_str(),
+            sizeof(buffer));
+      }
+      if (input_length > 0) {
+        LOG(WARNING, "%zu extra bytes on message of type %s\n", input_length,
+            type_cache::Get(message.structure.type_id).name.c_str());
+      }
+      fprintf(output, BASE_FORMAT "%.*s: %.*s\n", BASE_ARGS,
+              static_cast<int>(message.message_length), message.message,
+              static_cast<int>(output_length), buffer);
+      break;
+  }
 }
 
 }  // namespace internal