[fidlcat] generates value for time

Adds a Kind enum to all the integer types.

The PrettyPrint method for integer types is no longer templated.

For uint64, this cl adds the time kind.

Moves DisplayTime from FidlcatPrinter to PrettyPrinter.

For types which are handled by the new mechanism, we now use the fidl
syntax: zx.time

Updates AccessBase::ComputeType() to handle time.

Two new syscalls can use the new mechanism:
- zx_nanosleep
- zx_channel_call

Change-Id: Ibc8d58fa3f30c9f577e58fb1b4e58253ac6c58f0
Reviewed-on: https://fuchsia-review.googlesource.com/c/fuchsia/+/377778
Reviewed-by: Jeremy Manson <jeremymanson@google.com>
Testability-Review: Jeremy Manson <jeremymanson@google.com>
Commit-Queue: Vincent Belliard <vbelliard@google.com>
diff --git a/src/lib/fidl_codec/printer.cc b/src/lib/fidl_codec/printer.cc
index 1e34c83..a76d8a6 100644
--- a/src/lib/fidl_codec/printer.cc
+++ b/src/lib/fidl_codec/printer.cc
@@ -46,6 +46,28 @@
   fidl_codec::DisplayHandle(colors_, handle, os_);
 }
 
+void PrettyPrinter::DisplayTime(zx_time_t time_ns) {
+  if (time_ns == ZX_TIME_INFINITE) {
+    (*this) << fidl_codec::Blue << "ZX_TIME_INFINITE" << fidl_codec::ResetColor;
+  } else if (time_ns == ZX_TIME_INFINITE_PAST) {
+    (*this) << fidl_codec::Blue << "ZX_TIME_INFINITE_PAST" << fidl_codec::ResetColor;
+  } else {
+    // Gets the time in seconds.
+    time_t value = time_ns / kOneBillion;
+    struct tm tm;
+    if (localtime_r(&value, &tm) == &tm) {
+      char buffer[100];
+      strftime(buffer, sizeof(buffer), "%c", &tm);
+      // And now, displays the nano seconds.
+      (*this) << fidl_codec::Blue << buffer << " and ";
+      snprintf(buffer, sizeof(buffer), "%09" PRId64, time_ns % kOneBillion);
+      (*this) << buffer << " ns" << fidl_codec::ResetColor;
+    } else {
+      (*this) << fidl_codec::Red << "unknown time" << fidl_codec::ResetColor;
+    }
+  }
+}
+
 void PrettyPrinter::IncrementTabulations() {
   ++tabulations_;
   if (need_to_print_header_) {
diff --git a/src/lib/fidl_codec/printer.h b/src/lib/fidl_codec/printer.h
index 993fee9..09acb62 100644
--- a/src/lib/fidl_codec/printer.h
+++ b/src/lib/fidl_codec/printer.h
@@ -21,6 +21,7 @@
 namespace fidl_codec {
 
 constexpr int kTabSize = 2;
+constexpr uint64_t kOneBillion = 1'000'000'000L;
 
 struct Colors {
   Colors(const char* new_reset, const char* new_red, const char* new_green, const char* new_blue,
@@ -62,6 +63,9 @@
   // for this handle (if any).
   virtual void DisplayHandle(const zx_handle_info_t& handle);
 
+  // Displays a time.
+  void DisplayTime(zx_time_t time_ns);
+
   void IncrementTabulations();
   void DecrementTabulations();
   void NeedHeader();
diff --git a/src/lib/fidl_codec/wire_types.cc b/src/lib/fidl_codec/wire_types.cc
index 35b2946..a4290c8 100644
--- a/src/lib/fidl_codec/wire_types.cc
+++ b/src/lib/fidl_codec/wire_types.cc
@@ -194,33 +194,193 @@
 
 std::string Int8Type::Name() const { return "int8"; }
 
+void Int8Type::PrettyPrint(const Value* value, PrettyPrinter& printer) const {
+  uint64_t absolute;
+  bool negative;
+  if (!value->GetIntegerValue(&absolute, &negative)) {
+    printer << Red << "invalid" << ResetColor;
+  } else {
+    switch (kind_) {
+      case Kind::kDecimal:
+        printer << Blue;
+        if (negative) {
+          printer << '-';
+        }
+        printer << absolute << ResetColor;
+        break;
+    }
+  }
+}
+
 void Int8Type::Visit(TypeVisitor* visitor) const { visitor->VisitInt8Type(this); }
 
 std::string Int16Type::Name() const { return "int16"; }
 
+void Int16Type::PrettyPrint(const Value* value, PrettyPrinter& printer) const {
+  uint64_t absolute;
+  bool negative;
+  if (!value->GetIntegerValue(&absolute, &negative)) {
+    printer << Red << "invalid" << ResetColor;
+  } else {
+    switch (kind_) {
+      case Kind::kDecimal:
+        printer << Blue;
+        if (negative) {
+          printer << '-';
+        }
+        printer << absolute << ResetColor;
+        break;
+    }
+  }
+}
+
 void Int16Type::Visit(TypeVisitor* visitor) const { visitor->VisitInt16Type(this); }
 
 std::string Int32Type::Name() const { return "int32"; }
 
+void Int32Type::PrettyPrint(const Value* value, PrettyPrinter& printer) const {
+  uint64_t absolute;
+  bool negative;
+  if (!value->GetIntegerValue(&absolute, &negative)) {
+    printer << Red << "invalid" << ResetColor;
+  } else {
+    switch (kind_) {
+      case Kind::kDecimal:
+        printer << Blue;
+        if (negative) {
+          printer << '-';
+        }
+        printer << absolute << ResetColor;
+        break;
+    }
+  }
+}
+
 void Int32Type::Visit(TypeVisitor* visitor) const { visitor->VisitInt32Type(this); }
 
-std::string Int64Type::Name() const { return "int64"; }
+std::string Int64Type::Name() const {
+  switch (kind_) {
+    case Kind::kDecimal:
+      return "int64";
+    case Kind::kTime:
+      return "zx.time";
+  }
+}
+
+void Int64Type::PrettyPrint(const Value* value, PrettyPrinter& printer) const {
+  uint64_t absolute;
+  bool negative;
+  if (!value->GetIntegerValue(&absolute, &negative)) {
+    printer << Red << "invalid" << ResetColor;
+  } else {
+    switch (kind_) {
+      case Kind::kDecimal:
+        printer << Blue;
+        if (negative) {
+          printer << '-';
+        }
+        printer << absolute << ResetColor;
+        break;
+      case Kind::kTime:
+        printer.DisplayTime(static_cast<zx_time_t>(absolute));
+        break;
+    }
+  }
+}
 
 void Int64Type::Visit(TypeVisitor* visitor) const { visitor->VisitInt64Type(this); }
 
 std::string Uint8Type::Name() const { return "uint8"; }
 
+void Uint8Type::PrettyPrint(const Value* value, PrettyPrinter& printer) const {
+  uint64_t absolute;
+  bool negative;
+  if (!value->GetIntegerValue(&absolute, &negative)) {
+    printer << Red << "invalid" << ResetColor;
+  } else {
+    FXL_DCHECK(!negative);
+    switch (kind_) {
+      case Kind::kDecimal:
+        printer << Blue << absolute << ResetColor;
+        break;
+      case Kind::kHexaDecimal:
+        printer << Blue << std::hex << absolute << std::dec << ResetColor;
+        break;
+    }
+  }
+}
+
 void Uint8Type::Visit(TypeVisitor* visitor) const { visitor->VisitUint8Type(this); }
 
 std::string Uint16Type::Name() const { return "uint16"; }
 
+void Uint16Type::PrettyPrint(const Value* value, PrettyPrinter& printer) const {
+  uint64_t absolute;
+  bool negative;
+  if (!value->GetIntegerValue(&absolute, &negative)) {
+    printer << Red << "invalid" << ResetColor;
+  } else {
+    FXL_DCHECK(!negative);
+    switch (kind_) {
+      case Kind::kDecimal:
+        printer << Blue << absolute << ResetColor;
+        break;
+      case Kind::kHexaDecimal:
+        printer << Blue << std::hex << absolute << std::dec << ResetColor;
+        break;
+    }
+  }
+}
+
 void Uint16Type::Visit(TypeVisitor* visitor) const { visitor->VisitUint16Type(this); }
 
 std::string Uint32Type::Name() const { return "uint32"; }
 
+void Uint32Type::PrettyPrint(const Value* value, PrettyPrinter& printer) const {
+  uint64_t absolute;
+  bool negative;
+  if (!value->GetIntegerValue(&absolute, &negative)) {
+    printer << Red << "invalid" << ResetColor;
+  } else {
+    FXL_DCHECK(!negative);
+    switch (kind_) {
+      case Kind::kDecimal:
+        printer << Blue << absolute << ResetColor;
+        break;
+      case Kind::kHexaDecimal:
+        printer << Blue << std::hex << absolute << std::dec << ResetColor;
+        break;
+    }
+  }
+}
+
 void Uint32Type::Visit(TypeVisitor* visitor) const { visitor->VisitUint32Type(this); }
 
-std::string Uint64Type::Name() const { return "uint64"; }
+std::string Uint64Type::Name() const {
+  switch (kind_) {
+    case Kind::kDecimal:
+    case Kind::kHexaDecimal:
+      return "uint64";
+  }
+}
+
+void Uint64Type::PrettyPrint(const Value* value, PrettyPrinter& printer) const {
+  uint64_t absolute;
+  bool negative;
+  if (!value->GetIntegerValue(&absolute, &negative)) {
+    printer << Red << "invalid" << ResetColor;
+  } else {
+    FXL_DCHECK(!negative);
+    switch (kind_) {
+      case Kind::kDecimal:
+        printer << Blue << absolute << ResetColor;
+        break;
+      case Kind::kHexaDecimal:
+        printer << Blue << std::hex << absolute << std::dec << ResetColor;
+        break;
+    }
+  }
+}
 
 void Uint64Type::Visit(TypeVisitor* visitor) const { visitor->VisitUint64Type(this); }
 
diff --git a/src/lib/fidl_codec/wire_types.h b/src/lib/fidl_codec/wire_types.h
index bba0bf1..b6dbb43 100644
--- a/src/lib/fidl_codec/wire_types.h
+++ b/src/lib/fidl_codec/wire_types.h
@@ -128,7 +128,7 @@
                 "IntegralType can only be used for integers");
 
  public:
-  explicit IntegralType(bool hexadecimal_display) : hexadecimal_display_(hexadecimal_display) {}
+  IntegralType() = default;
 
   size_t InlineSize() const override { return sizeof(T); }
 
@@ -147,98 +147,118 @@
     }
     return std::make_unique<IntegerValue>(value, false);
   }
-
-  void PrettyPrint(const Value* value, PrettyPrinter& printer) const override {
-    uint64_t absolute;
-    bool negative;
-    if (!value->GetIntegerValue(&absolute, &negative)) {
-      printer << Red << "invalid" << ResetColor;
-    } else {
-      printer << Blue;
-      if (negative) {
-        printer << '-';
-      }
-      if (hexadecimal_display_) {
-        printer << std::hex << absolute << std::dec << ResetColor;
-      } else {
-        printer << absolute << ResetColor;
-      }
-    }
-  }
-
- private:
-  bool hexadecimal_display_;
 };
 
 class Int8Type : public IntegralType<int8_t> {
  public:
-  explicit Int8Type(bool hexadecimal_display = false) : IntegralType<int8_t>(hexadecimal_display) {}
+  enum class Kind { kDecimal };
+
+  explicit Int8Type(Kind kind = Kind::kDecimal) : kind_(kind) {}
 
   std::string Name() const override;
+  void PrettyPrint(const Value* value, PrettyPrinter& printer) const override;
   void Visit(TypeVisitor* visitor) const override;
+
+ private:
+  Kind kind_;
 };
 
 class Int16Type : public IntegralType<int16_t> {
  public:
-  explicit Int16Type(bool hexadecimal_display = false)
-      : IntegralType<int16_t>(hexadecimal_display) {}
+  enum class Kind { kDecimal };
+
+  explicit Int16Type(Kind kind = Kind::kDecimal) : kind_(kind) {}
 
   std::string Name() const override;
+  void PrettyPrint(const Value* value, PrettyPrinter& printer) const override;
   void Visit(TypeVisitor* visitor) const override;
+
+ private:
+  Kind kind_;
 };
 
 class Int32Type : public IntegralType<int32_t> {
  public:
-  explicit Int32Type(bool hexadecimal_display = false)
-      : IntegralType<int32_t>(hexadecimal_display) {}
+  enum class Kind { kDecimal };
+
+  explicit Int32Type(Kind kind = Kind::kDecimal) : kind_(kind) {}
 
   std::string Name() const override;
+  void PrettyPrint(const Value* value, PrettyPrinter& printer) const override;
   void Visit(TypeVisitor* visitor) const override;
+
+ private:
+  Kind kind_;
 };
 
 class Int64Type : public IntegralType<int64_t> {
  public:
-  explicit Int64Type(bool hexadecimal_display = false)
-      : IntegralType<int64_t>(hexadecimal_display) {}
+  enum class Kind { kDecimal, kTime };
+
+  explicit Int64Type(Kind kind = Kind::kDecimal) : kind_(kind) {}
 
   std::string Name() const override;
+  void PrettyPrint(const Value* value, PrettyPrinter& printer) const override;
   void Visit(TypeVisitor* visitor) const override;
+
+ private:
+  Kind kind_;
 };
 
 class Uint8Type : public IntegralType<uint8_t> {
  public:
-  explicit Uint8Type(bool hexadecimal_display = false)
-      : IntegralType<uint8_t>(hexadecimal_display) {}
+  enum class Kind { kDecimal, kHexaDecimal };
+
+  explicit Uint8Type(Kind kind = Kind::kDecimal) : kind_(kind) {}
 
   std::string Name() const override;
+  void PrettyPrint(const Value* value, PrettyPrinter& printer) const override;
   void Visit(TypeVisitor* visitor) const override;
+
+ private:
+  Kind kind_;
 };
 
 class Uint16Type : public IntegralType<uint16_t> {
  public:
-  explicit Uint16Type(bool hexadecimal_display = false)
-      : IntegralType<uint16_t>(hexadecimal_display) {}
+  enum class Kind { kDecimal, kHexaDecimal };
+
+  explicit Uint16Type(Kind kind = Kind::kDecimal) : kind_(kind) {}
 
   std::string Name() const override;
+  void PrettyPrint(const Value* value, PrettyPrinter& printer) const override;
   void Visit(TypeVisitor* visitor) const override;
+
+ private:
+  Kind kind_;
 };
 
 class Uint32Type : public IntegralType<uint32_t> {
  public:
-  explicit Uint32Type(bool hexadecimal_display = false)
-      : IntegralType<uint32_t>(hexadecimal_display) {}
+  enum class Kind { kDecimal, kHexaDecimal };
+
+  explicit Uint32Type(Kind kind = Kind::kDecimal) : kind_(kind) {}
 
   std::string Name() const override;
+  void PrettyPrint(const Value* value, PrettyPrinter& printer) const override;
   void Visit(TypeVisitor* visitor) const override;
+
+ private:
+  Kind kind_;
 };
 
 class Uint64Type : public IntegralType<uint64_t> {
  public:
-  explicit Uint64Type(bool hexadecimal_display = false)
-      : IntegralType<uint64_t>(hexadecimal_display) {}
+  enum class Kind { kDecimal, kHexaDecimal };
+
+  explicit Uint64Type(Kind kind = Kind::kDecimal) : kind_(kind) {}
 
   std::string Name() const override;
+  void PrettyPrint(const Value* value, PrettyPrinter& printer) const override;
   void Visit(TypeVisitor* visitor) const override;
+
+ private:
+  Kind kind_;
 };
 
 // A generic type that can be used for any numeric value that corresponds to a
diff --git a/tools/fidlcat/interception_tests/channel_test.cc b/tools/fidlcat/interception_tests/channel_test.cc
index 0b92443..c6205ce 100644
--- a/tools/fidlcat/interception_tests/channel_test.cc
+++ b/tools/fidlcat/interception_tests/channel_test.cc
@@ -553,11 +553,11 @@
                   "test_3141 \x1B[31m3141\x1B[0m:\x1B[31m8764\x1B[0m zx_channel_call("
                   "handle:\x1B[32mhandle\x1B[0m: \x1B[31mcefa1db0\x1B[0m, "
                   "options:\x1B[32muint32\x1B[0m: \x1B[34m0\x1B[0m, "
-                  "deadline:\x1B[32mtime\x1B[0m: \x1B[34mZX_TIME_INFINITE\x1B[0m, "
+                  "deadline:\x1B[32mzx.time\x1B[0m: \x1B[34mZX_TIME_INFINITE\x1B[0m, "
                   "rd_num_bytes:\x1B[32muint32\x1B[0m: \x1B[34m100\x1B[0m, "
                   "rd_num_handles:\x1B[32muint32\x1B[0m: \x1B[34m64\x1B[0m)\n"
                   "  \x1B[31mCan't decode message: num_bytes=16 num_handles=2 "
-                  "ordinal=77e4cceb00000000\x1B[0m\n"
+                  "txid=aaaaaaaa ordinal=77e4cceb00000000\x1B[0m\n"
                   "    data=\n"
                   "      0000: \x1B[31maa, aa, aa, aa\x1B[0m, 00, 00, 00, 01\x1B[31m"
                   ", 00, 00, 00, 00\x1B[0m, eb, cc, e4, 77\x1B[0m\n"
@@ -565,7 +565,7 @@
                   "      0000: 01234567, 89abcdef\n"
                   "  -> \x1B[32mZX_OK\x1B[0m\n"
                   "    \x1B[31mCan't decode message: num_bytes=16 num_handles=2 "
-                  "ordinal=77e4cceb00000000\x1B[0m\n"
+                  "txid=aaaaaaaa ordinal=77e4cceb00000000\x1B[0m\n"
                   "      data=\n"
                   "        0000: \x1B[31maa, aa, aa, aa\x1B[0m, 00, 00, 00, 01\x1B[31m"
                   ", 00, 00, 00, 00\x1B[0m, eb, cc, e4, 77\x1B[0m\n"
@@ -588,12 +588,12 @@
     "test_3141 \x1B[31m3141\x1B[0m:\x1B[31m8764\x1B[0m zx_channel_call("
     "handle:\x1B[32mhandle\x1B[0m: \x1B[31mcefa1db0\x1B[0m, "
     "options:\x1B[32muint32\x1B[0m: \x1B[34m0\x1B[0m, "
-    "deadline:\x1B[32mtime\x1B[0m: \x1B[34mZX_TIME_INFINITE\x1B[0m, "
+    "deadline:\x1B[32mzx.time\x1B[0m: \x1B[34mZX_TIME_INFINITE\x1B[0m, "
     "rd_num_bytes:\x1B[32muint32\x1B[0m: \x1B[34m100\x1B[0m, "
     "rd_num_handles:\x1B[32muint32\x1B[0m: \x1B[34m64\x1B[0m)\n"
     "test_3141 \x1B[31m3141\x1B[0m:\x1B[31m8764\x1B[0m "
     "  \x1B[31mCan't decode message: num_bytes=16 num_handles=2 "
-    "ordinal=77e4cceb00000000\x1B[0m\n"
+    "txid=aaaaaaaa ordinal=77e4cceb00000000\x1B[0m\n"
     "test_3141 \x1B[31m3141\x1B[0m:\x1B[31m8764\x1B[0m "
     "    data=\n"
     "test_3141 \x1B[31m3141\x1B[0m:\x1B[31m8764\x1B[0m "
@@ -607,7 +607,7 @@
     "  -> \x1B[32mZX_OK\x1B[0m\n"
     "test_3141 \x1B[31m3141\x1B[0m:\x1B[31m8764\x1B[0m "
     "    \x1B[31mCan't decode message: num_bytes=16 num_handles=2 "
-    "ordinal=77e4cceb00000000\x1B[0m\n"
+    "txid=aaaaaaaa ordinal=77e4cceb00000000\x1B[0m\n"
     "test_3141 \x1B[31m3141\x1B[0m:\x1B[31m8764\x1B[0m "
     "      data=\n"
     "test_3141 \x1B[31m3141\x1B[0m:\x1B[31m8764\x1B[0m "
diff --git a/tools/fidlcat/interception_tests/clock_test.cc b/tools/fidlcat/interception_tests/clock_test.cc
index 37d646a..ee8a82a 100644
--- a/tools/fidlcat/interception_tests/clock_test.cc
+++ b/tools/fidlcat/interception_tests/clock_test.cc
@@ -72,7 +72,7 @@
 
 CLOCK_GET_DISPLAY_TEST(
     ZxClockGet, ZX_OK,
-    ClockExpected(kClockGetTestValue / kOneBillion,
+    ClockExpected(kClockGetTestValue / fidl_codec::kOneBillion,
                   "\n"
                   "test_3141 \x1B[31m3141\x1B[0m:\x1B[31m8764\x1B[0m zx_clock_get("
                   "clock_id:\x1B[32mclock\x1B[0m: \x1B[31mZX_CLOCK_UTC\x1B[0m)\n"
@@ -102,7 +102,7 @@
 
 CLOCK_GET_MONOTONIC_DISPLAY_TEST(
     ZxClockGetMonotonic, kClockGetMonotonicTestValue,
-    ClockExpected(kClockGetMonotonicTestValue / kOneBillion,
+    ClockExpected(kClockGetMonotonicTestValue / fidl_codec::kOneBillion,
                   "\n"
                   "test_3141 \x1B[31m3141\x1B[0m:\x1B[31m8764\x1B[0m zx_clock_get_monotonic()\n"
                   "  -> \x1B[32mtime\x1B[0m: \x1B[34m%c and 115697412 ns\x1B[0m\n")
@@ -134,7 +134,7 @@
 
 DEADLINE_AFTER_DISPLAY_TEST(
     ZxDeadlineAfter, kDeadlineAfterTestValue, kDeadlineAfterTestDuration,
-    ClockExpected(kDeadlineAfterTestValue / kOneBillion,
+    ClockExpected(kDeadlineAfterTestValue / fidl_codec::kOneBillion,
                   "\n"
                   "test_3141 \x1B[31m3141\x1B[0m:\x1B[31m8764\x1B[0m zx_deadline_after("
                   "nanoseconds:\x1B[32mduration\x1B[0m: \x1B[34m1000 nano seconds\x1B[0m)\n"
diff --git a/tools/fidlcat/interception_tests/interception_workflow_test.cc b/tools/fidlcat/interception_tests/interception_workflow_test.cc
index ec97d3d..502621d 100644
--- a/tools/fidlcat/interception_tests/interception_workflow_test.cc
+++ b/tools/fidlcat/interception_tests/interception_workflow_test.cc
@@ -504,6 +504,7 @@
   std::string result = ss.str();
   ASSERT_EQ(
       "zx_clock_get_monotonic\n"
+      "zx_nanosleep\n"
       "zx_ticks_get\n"
       "zx_ticks_per_second\n"
       "zx_system_get_dcache_line_size\n"
@@ -516,6 +517,7 @@
       "zx_channel_read\n"
       "zx_channel_read_etc\n"
       "zx_channel_write\n"
+      "zx_channel_call\n"
       "zx_thread_exit\n"
       "zx_process_exit\n"
       "zx_job_create\n"
@@ -577,7 +579,6 @@
       "processargs_extract_handles\n"
       "__libc_extensions_init\n"
       "zx_clock_get\n"
-      "zx_nanosleep\n"
       "zx_deadline_after\n"
       "zx_clock_adjust\n"
       "zx_system_get_version\n"
@@ -598,7 +599,6 @@
       "zx_object_set_property\n"
       "zx_object_get_info\n"
       "zx_object_get_child\n"
-      "zx_channel_call\n"
       "zx_socket_create\n"
       "zx_socket_write\n"
       "zx_socket_read\n"
diff --git a/tools/fidlcat/lib/event.cc b/tools/fidlcat/lib/event.cc
index 2294f32..50edeee 100644
--- a/tools/fidlcat/lib/event.cc
+++ b/tools/fidlcat/lib/event.cc
@@ -21,28 +21,6 @@
   (*this) << fidl_codec::StatusName(status) << fidl_codec::ResetColor;
 }
 
-void FidlcatPrinter::DisplayTime(zx_time_t time_ns) {
-  if (time_ns == ZX_TIME_INFINITE) {
-    (*this) << fidl_codec::Blue << "ZX_TIME_INFINITE" << fidl_codec::ResetColor;
-  } else if (time_ns == ZX_TIME_INFINITE_PAST) {
-    (*this) << fidl_codec::Blue << "ZX_TIME_INFINITE_PAST" << fidl_codec::ResetColor;
-  } else {
-    // Gets the time in seconds.
-    time_t value = time_ns / kOneBillion;
-    struct tm tm;
-    if (localtime_r(&value, &tm) == &tm) {
-      char buffer[100];
-      strftime(buffer, sizeof(buffer), "%c", &tm);
-      // And now, displays the nano seconds.
-      (*this) << fidl_codec::Blue << buffer << " and ";
-      snprintf(buffer, sizeof(buffer), "%09" PRId64, time_ns % kOneBillion);
-      (*this) << buffer << " ns" << fidl_codec::ResetColor;
-    } else {
-      (*this) << fidl_codec::Red << "unknown time" << fidl_codec::ResetColor;
-    }
-  }
-}
-
 bool FidlcatPrinter::DisplayReturnedValue(SyscallReturnType type, int64_t returned_value) {
   switch (type) {
     case SyscallReturnType::kNoReturn:
diff --git a/tools/fidlcat/lib/event.h b/tools/fidlcat/lib/event.h
index 5e1baf2..90bd650 100644
--- a/tools/fidlcat/lib/event.h
+++ b/tools/fidlcat/lib/event.h
@@ -32,7 +32,6 @@
 
   void DisplayHandle(const zx_handle_info_t& handle) override;
   void DisplayStatus(zx_status_t status);
-  void DisplayTime(zx_time_t time_ns);
   bool DisplayReturnedValue(SyscallReturnType type, int64_t returned_value);
   void DisplayInline(
       const std::vector<std::unique_ptr<fidl_codec::StructMember>>& members,
diff --git a/tools/fidlcat/lib/syscall_decoder_dispatcher.cc b/tools/fidlcat/lib/syscall_decoder_dispatcher.cc
index c20e55d..f5f707b 100644
--- a/tools/fidlcat/lib/syscall_decoder_dispatcher.cc
+++ b/tools/fidlcat/lib/syscall_decoder_dispatcher.cc
@@ -134,21 +134,23 @@
     case SyscallType::kUint8:
       return std::make_unique<fidl_codec::Uint8Type>();
     case SyscallType::kUint8Hexa:
-      return std::make_unique<fidl_codec::Uint8Type>(/*hexadecimal_display=*/true);
+      return std::make_unique<fidl_codec::Uint8Type>(fidl_codec::Uint8Type::Kind::kHexaDecimal);
     case SyscallType::kUint16:
       return std::make_unique<fidl_codec::Uint16Type>();
     case SyscallType::kUint16Hexa:
-      return std::make_unique<fidl_codec::Uint16Type>(/*hexadecimal_display=*/true);
+      return std::make_unique<fidl_codec::Uint16Type>(fidl_codec::Uint16Type::Kind::kHexaDecimal);
     case SyscallType::kUint32:
       return std::make_unique<fidl_codec::Uint32Type>();
     case SyscallType::kUint32Hexa:
-      return std::make_unique<fidl_codec::Uint32Type>(/*hexadecimal_display=*/true);
+      return std::make_unique<fidl_codec::Uint32Type>(fidl_codec::Uint32Type::Kind::kHexaDecimal);
     case SyscallType::kUint64:
       return std::make_unique<fidl_codec::Uint64Type>();
     case SyscallType::kUint64Hexa:
-      return std::make_unique<fidl_codec::Uint64Type>(/*hexadecimal_display=*/true);
+      return std::make_unique<fidl_codec::Uint64Type>(fidl_codec::Uint64Type::Kind::kHexaDecimal);
     case SyscallType::kHandle:
       return std::make_unique<fidl_codec::HandleType>();
+    case SyscallType::kTime:
+      return std::make_unique<fidl_codec::Int64Type>(fidl_codec::Int64Type::Kind::kTime);
     default:
       return nullptr;
   }
diff --git a/tools/fidlcat/lib/type_decoder.h b/tools/fidlcat/lib/type_decoder.h
index 989e42d..f0db3f88 100644
--- a/tools/fidlcat/lib/type_decoder.h
+++ b/tools/fidlcat/lib/type_decoder.h
@@ -22,7 +22,6 @@
 
 namespace fidlcat {
 
-#define kOneBillion 1'000'000'000L
 #define kSecondsPerMinute 60
 #define kMinutesPerHour 60
 #define kHoursPerDay 24
@@ -189,8 +188,8 @@
     duration_ns = -duration_ns;
   }
   const char* separator = "";
-  int64_t nanoseconds = duration_ns % kOneBillion;
-  int64_t seconds = duration_ns / kOneBillion;
+  int64_t nanoseconds = duration_ns % fidl_codec::kOneBillion;
+  int64_t seconds = duration_ns / fidl_codec::kOneBillion;
   if (seconds != 0) {
     int64_t minutes = seconds / kSecondsPerMinute;
     if (minutes != 0) {
@@ -252,13 +251,13 @@
   } else if (time.time_ns() == ZX_TIME_INFINITE_PAST) {
     os << time.colors().blue << "ZX_TIME_INFINITE_PAST" << time.colors().reset;
   } else {
-    time_t value = time.time_ns() / kOneBillion;
+    time_t value = time.time_ns() / fidl_codec::kOneBillion;
     struct tm tm;
     if (localtime_r(&value, &tm) == &tm) {
       char buffer[100];
       strftime(buffer, sizeof(buffer), "%c", &tm);
       os << time.colors().blue << buffer << " and ";
-      snprintf(buffer, sizeof(buffer), "%09" PRId64, time.time_ns() % kOneBillion);
+      snprintf(buffer, sizeof(buffer), "%09" PRId64, time.time_ns() % fidl_codec::kOneBillion);
       os << buffer << " ns" << time.colors().reset;
     } else {
       os << time.colors().red << "unknown time" << time.colors().reset;