implemented and tested PrintField
diff --git a/aos/build/queues/compiler.rb b/aos/build/queues/compiler.rb
index bcd497a..e53e217 100644
--- a/aos/build/queues/compiler.rb
+++ b/aos/build/queues/compiler.rb
@@ -1,17 +1,4 @@
-$LOAD_PATH.unshift(".")
-["tokenizer.rb","q_file.rb","queue_group.rb","queue.rb","namespaces.rb",
-"interface.rb","errors.rb", "q_struct.rb"].each do |name|
-	require File.dirname(__FILE__) + "/objects/" + name
-end
-["standard_types.rb","auto_gen.rb","file_pair_types.rb",
-"dep_file_pair.rb"].each do |name|
-	require File.dirname(__FILE__) + "/cpp_pretty_print/" + name
-end
-["q_file.rb","message_dec.rb","queue_dec.rb", "q_struct.rb"].each do |name|
-	require File.dirname(__FILE__) + "/output/" + name
-end
-require "fileutils"
-require "pathname"
+require File.dirname(__FILE__) + '/load.rb'
 
 def parse_args(globals,args)
 	i = 0
diff --git a/aos/build/queues/load.rb b/aos/build/queues/load.rb
new file mode 100644
index 0000000..c299d80
--- /dev/null
+++ b/aos/build/queues/load.rb
@@ -0,0 +1,14 @@
+$LOAD_PATH.unshift(".")
+["tokenizer.rb","q_file.rb","queue_group.rb","queue.rb","namespaces.rb",
+"interface.rb","errors.rb", "q_struct.rb"].each do |name|
+	require File.dirname(__FILE__) + "/objects/" + name
+end
+["standard_types.rb","auto_gen.rb","file_pair_types.rb",
+"dep_file_pair.rb"].each do |name|
+	require File.dirname(__FILE__) + "/cpp_pretty_print/" + name
+end
+["q_file.rb","message_dec.rb","queue_dec.rb", "q_struct.rb"].each do |name|
+	require File.dirname(__FILE__) + "/output/" + name
+end
+require "fileutils"
+require "pathname"
diff --git a/aos/build/queues/output/message_dec.rb b/aos/build/queues/output/message_dec.rb
index 6cf44c2..f1a6375 100644
--- a/aos/build/queues/output/message_dec.rb
+++ b/aos/build/queues/output/message_dec.rb
@@ -34,7 +34,7 @@
 		return "{\n" + @members.collect() { |elem| elem.simpleStr() + "\n"}.join("") + "}"
 	end
 	def getTypeID()
-		return "0x" + (((Digest::SHA1.hexdigest(simpleStr())[0..3].to_i(16)) << 16) + size).to_s(16)
+		return "0x" + (((Digest::SHA1.hexdigest(simpleStr())[0..3].to_i(16)) << 16) | size).to_s(16)
 	end
 	def add_member(member)
 		@members << member
@@ -264,7 +264,9 @@
 		f_call.args.dont_wrap = true
 	end
 	def getTypeID()
-		Digest::SHA1.hexdigest(@type)[0..7].to_i(16) | 0x4000 #ensures is primative
+		Digest::SHA1.hexdigest(@type)[0..7].to_i(16) |
+                0x2000 | # marks it as primitive
+                size
 	end
 	def simpleStr()
 		"#{@type} #{@name}"
diff --git a/aos/build/queues/print_field.rb b/aos/build/queues/print_field.rb
new file mode 100644
index 0000000..8e9521e
--- /dev/null
+++ b/aos/build/queues/print_field.rb
@@ -0,0 +1,54 @@
+require File.dirname(__FILE__) + '/load.rb'
+
+TypeNames = [8, 16, 32, 64].collect do |size|
+  ["uint#{size}_t", "int#{size}_t"]
+end.flatten + ['bool', 'float', 'char', 'double']
+
+File.open(ARGV[0], 'w') do |output|
+  output.puts <<END
+// This file is generated by #{File.expand_path(__FILE__)}.
+// DO NOT EDIT BY HAND!
+
+#include <sys/types.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include <stdio.h>
+
+#include "aos/common/byteorder.h"
+
+namespace aos {
+
+bool PrintField(char *output, size_t *output_bytes, void *input,
+                size_t *input_bytes, uint32_t type) {
+  switch (type) {
+#{TypeNames.collect do |name|
+  message_element = Target::MessageElement.new(name, 'value')
+  statement = MessageElementStmt.new(name, 'value')
+  message_element.size = statement.size
+  print_args = []
+  message_element.fetchPrintArgs(print_args)
+  next <<END2
+    case #{message_element.getTypeID()}:
+      {
+        if (*input_bytes < #{statement.size}) return false;
+        *input_bytes -= #{statement.size};
+        #{name} value;
+        to_host(static_cast<const char *>(input), &value);
+        int ret = snprintf(output, *output_bytes,
+                           "#{statement.toPrintFormat()}",
+                           #{print_args[0]});
+        if (ret < 0) return false;
+        if (static_cast<unsigned int>(ret) >= *output_bytes) return false;
+        *output_bytes -= ret + 1;
+        return true;
+      }
+END2
+end.join('')}
+    default:
+      return false;
+  }
+}
+
+}  // namespace aos
+END
+end
diff --git a/aos/common/common.gyp b/aos/common/common.gyp
index a774936..7c38c53 100644
--- a/aos/common/common.gyp
+++ b/aos/common/common.gyp
@@ -44,8 +44,12 @@
     {
       'target_name': 'queue_types',
       'type': 'static_library',
+      'variables': {
+        'print_field_cc': '<(SHARED_INTERMEDIATE_DIR)/print_field.cc',
+      },
       'sources': [
         'queue_types.cc',
+        '<(print_field_cc)',
       ],
       'dependencies': [
         '<(AOS)/build/aos.gyp:logging_interface',
@@ -53,6 +57,23 @@
         '<(AOS)/linux_code/ipc_lib/ipc_lib.gyp:core_lib',
         'mutex',
       ],
+      'actions': [
+        {
+          'variables': {
+            'script': '<(AOS)/build/queues/print_field.rb',
+          },
+          'action_name': 'gen_print_field',
+          'inputs': [
+            '<(script)',
+            '<!@(find <(AOS)/build/queues/ -name *.rb)',
+          ],
+          'outputs': [
+            '<(print_field_cc)',
+          ],
+          'action': ['ruby', '<(script)', '<(print_field_cc)'],
+          'message': 'Generating print_field.cc',
+        },
+      ],
     },
     {
       'target_name': 'queue_types_test',
diff --git a/aos/common/queue_types.h b/aos/common/queue_types.h
index 9955fe7..cf7287f 100644
--- a/aos/common/queue_types.h
+++ b/aos/common/queue_types.h
@@ -15,18 +15,21 @@
 // output is where to write the text representation.
 // output_bytes should point to the number of bytes available to write in
 // output. It will be reduced by the number of bytes that were actually written.
-// input is where to read the data in from.
+// input is where to read the data in from (in network byte order, aka from
+// Serialize).
 // input_bytes should point to the number of bytes available to read from input.
 // It will be reduced by the number of bytes that were actually read.
 // type is the ID of a type to print. It must be a primitive type.
 //
+// Returns true for success and false for not.
+//
 // The implementation of this is generated by the ruby code.
-// TODO(brians): Actually do that.
 bool PrintField(char *output, size_t *output_bytes, void *input,
-                size_t *input_bytes, uint32_t type);
+                size_t *input_bytes, uint32_t type)
+    __attribute__((warn_unused_result));
 
 // The type IDs this uses are 2 parts: a 16 bit size and a 16 bit hash. Sizes
-// for primitive types are stored with 8192 added.
+// for primitive types are stored with 8192 (0x2000) added.
 //
 // Serializing/deserializing includes all of the fields too.
 struct MessageType {
@@ -69,7 +72,7 @@
   static MessageType *Deserialize(const char *buffer, size_t *bytes);
 
   static bool IsPrimitive(uint32_t type_id) {
-    return (type_id & 0xFFFF) >= 8192;
+    return (type_id & 0x2000) != 0;
   }
 
   // The type ID for this.
@@ -95,9 +98,9 @@
   DISALLOW_COPY_AND_ASSIGN(MessageType);
 };
 
-// Implements a cache of types which usually works per-process but can (when
-// explicitly instructed) put a type in shared memory which other processes will
-// automatically receive.
+// Implements a cache of types which generally works per-process but can (when
+// instructed) put a type in shared memory which other processes will
+// automatically be able to retrieve.
 // All of these functions are thread-safe.
 namespace type_cache {
 
diff --git a/aos/common/queue_types_test.cc b/aos/common/queue_types_test.cc
index 287d555..a23c33b 100644
--- a/aos/common/queue_types_test.cc
+++ b/aos/common/queue_types_test.cc
@@ -5,8 +5,13 @@
 #include "gtest/gtest.h"
 
 #include "aos/common/test_queue.q.h"
+#include "aos/common/byteorder.h"
+
+using ::aos::common::testing::Structure;
+using ::aos::common::testing::MessageWithStructure;
 
 namespace aos {
+namespace testing {
 
 typedef MessageType::Field Field;
 
@@ -70,4 +75,57 @@
   EXPECT_TRUE(Equal(kTestType1, *deserialized));
 }
 
+class PrintFieldTest : public ::testing::Test {
+ public:
+  char input[128], output[128];
+  size_t input_bytes, output_bytes;
+};
+
+TEST_F(PrintFieldTest, Basic) {
+  static const uint16_t kData = 971;
+  input_bytes = sizeof(kData);
+  to_network(&kData, input);
+  output_bytes = sizeof(output);
+  ASSERT_TRUE(PrintField(output, &output_bytes, input, &input_bytes,
+                         Structure::GetType()->fields[1]->type));
+  EXPECT_EQ(0u, input_bytes);
+  EXPECT_EQ(sizeof(output) - 4, output_bytes);
+  EXPECT_EQ(::std::string("971\0", 4),
+            ::std::string(output, sizeof(output) - output_bytes));
+}
+
+// Tests PrintField with trailing input bytes and no extra output bytes.
+TEST_F(PrintFieldTest, OtherSizes) {
+  static const float kData = 16.78;
+  static const ::std::string kString("16.780001");
+  static const size_t kExtraInputBytes = 4;
+  input_bytes = sizeof(kData) + kExtraInputBytes;
+  to_network(&kData, input);
+  output_bytes = kString.size() + 1;
+  assert(output_bytes <= sizeof(output));
+  ASSERT_TRUE(PrintField(output, &output_bytes, input, &input_bytes,
+                         Structure::GetType()->fields[2]->type));
+  EXPECT_EQ(kExtraInputBytes, input_bytes);
+  EXPECT_EQ(0u, output_bytes);
+  EXPECT_EQ(kString, ::std::string(output));
+}
+
+TEST_F(PrintFieldTest, InputTooSmall) {
+  static const float kData = 0;
+  input_bytes = sizeof(kData) - 1;
+  output_bytes = sizeof(output);
+  EXPECT_FALSE(PrintField(output, &output_bytes, input, &input_bytes,
+                          Structure::GetType()->fields[2]->type));
+}
+
+TEST_F(PrintFieldTest, OutputTooSmall) {
+  static const uint16_t kData = 12345;
+  input_bytes = sizeof(input);
+  to_network(&kData, input);
+  output_bytes = 5;
+  EXPECT_FALSE(PrintField(output, &output_bytes, input, &input_bytes,
+                          Structure::GetType()->fields[1]->type));
+}
+
+}  // namespace testing
 }  // namespace aos
diff --git a/aos/common/test_queue.q b/aos/common/test_queue.q
index 878be08..d603802 100644
--- a/aos/common/test_queue.q
+++ b/aos/common/test_queue.q
@@ -3,6 +3,7 @@
 struct Structure {
   bool struct_bool;
   uint16_t struct_int;
+  float struct_float;
 };
 
 message MessageWithStructure {