Add LogPartsSorter to sort messages from a log file

Based on https://docs.google.com/document/d/1RZ6ZlADRUHmwiFOOmXA87FHPLFuN-7mS7tbFCwguZDE/edit#
we need to start by sorting all the messages from a set of parts.  Make
a class and test this.  (The testing infrastructure looks a bit
over-kill, but will be re-used a lot for the following tests).

Change-Id: Ifa1ba880ddf7cf923f24826e504b902a4787ad03
diff --git a/aos/events/logging/logfile_utils.h b/aos/events/logging/logfile_utils.h
index 25f02f9..13c83cf 100644
--- a/aos/events/logging/logfile_utils.h
+++ b/aos/events/logging/logfile_utils.h
@@ -14,6 +14,7 @@
 #include <utility>
 #include <vector>
 
+#include "absl/container/btree_set.h"
 #include "absl/types/span.h"
 #include "aos/containers/resizeable_buffer.h"
 #include "aos/events/event_loop.h"
@@ -280,6 +281,10 @@
 
   std::string_view filename() const { return message_reader_.filename(); }
 
+  const LogFileHeader *log_file_header() const {
+    return message_reader_.log_file_header();
+  }
+
   // Returns the minimum amount of data needed to queue up for sorting before
   // we are guarenteed to not see data out of order.
   std::chrono::nanoseconds max_out_of_order_duration() const {
@@ -326,6 +331,44 @@
 
 std::ostream &operator<<(std::ostream &os, const Message &m);
 
+// Class to sort the resulting messages from a PartsMessageReader.
+class LogPartsSorter {
+ public:
+  LogPartsSorter(LogParts log_parts);
+
+  // Returns the current log file header.
+  // TODO(austin): Is this the header we want to report?  Do we want a better
+  // start time?
+  // TODO(austin): Report a start time from the LogParts.  Figure out how that
+  // all works.
+  const LogFileHeader *log_file_header() const {
+    return parts_message_reader_.log_file_header();
+  }
+
+  // The time this data is sorted until.
+  monotonic_clock::time_point sorted_until() const { return sorted_until_; }
+
+  // Returns the next sorted message from the log file.  It is safe to call
+  // std::move() on the result to move the data flatbuffer from it.
+  Message *Front();
+  // Pops the front message.  This should only be called after a call to
+  // Front().
+  void PopFront();
+
+  // Returns a debug string representing the contents of this sorter.
+  std::string DebugString() const;
+
+ private:
+  // Log parts reader we are wrapping.
+  PartsMessageReader parts_message_reader_;
+  // Cache of the time we are sorted until.
+  aos::monotonic_clock::time_point sorted_until_ = monotonic_clock::min_time;
+
+  // Set used for efficient sorting of messages.  We can benchmark and evaluate
+  // other data structures if this proves to be the bottleneck.
+  absl::btree_set<Message> messages_;
+};
+
 class TimestampMerger;
 
 // A design requirement is that the relevant data for a channel is not more than