Add code for finding 0-delineated packets

Change-Id: I9c75b29b67fd60241537196ed08369318f8ddba2
diff --git a/y2019/jevois/cobs_test.cc b/y2019/jevois/cobs_test.cc
index 320bde3..d7b35b6 100644
--- a/y2019/jevois/cobs_test.cc
+++ b/y2019/jevois/cobs_test.cc
@@ -126,5 +126,167 @@
   EncodeAndDecode<253>(data_span.subspan(0, 253));
 }
 
+// Tests parsing a few packets, one byte at a time.
+TEST(CobsPacketizerTest, BasicSingleByte) {
+  CobsPacketizer<5> packetizer;
+
+  ASSERT_TRUE(packetizer.received_packet().empty());
+  packetizer.ParseData(std::array<char, 1>{{1}});
+  ASSERT_TRUE(packetizer.received_packet().empty());
+  packetizer.ParseData(std::array<char, 1>{{2}});
+  ASSERT_TRUE(packetizer.received_packet().empty());
+  packetizer.ParseData(std::array<char, 1>{{3}});
+  ASSERT_TRUE(packetizer.received_packet().empty());
+  packetizer.ParseData(std::array<char, 1>{{0}});
+  ASSERT_FALSE(packetizer.received_packet().empty());
+  EXPECT_EQ(gsl::span<const char>(std::array<char, 3>{{1, 2, 3}}),
+            packetizer.received_packet());
+  packetizer.clear_received_packet();
+  ASSERT_TRUE(packetizer.received_packet().empty());
+
+  ASSERT_TRUE(packetizer.received_packet().empty());
+  packetizer.ParseData(std::array<char, 1>{{5}});
+  ASSERT_TRUE(packetizer.received_packet().empty());
+  packetizer.ParseData(std::array<char, 1>{{0}});
+  ASSERT_FALSE(packetizer.received_packet().empty());
+  EXPECT_EQ(gsl::span<const char>(std::array<char, 1>{{5}}),
+            packetizer.received_packet());
+
+  ASSERT_FALSE(packetizer.received_packet().empty());
+  packetizer.ParseData(std::array<char, 1>{{9}});
+  ASSERT_FALSE(packetizer.received_packet().empty());
+  EXPECT_EQ(gsl::span<const char>(std::array<char, 1>{{5}}),
+            packetizer.received_packet());
+  packetizer.ParseData(std::array<char, 1>{{7}});
+  ASSERT_FALSE(packetizer.received_packet().empty());
+  EXPECT_EQ(gsl::span<const char>(std::array<char, 1>{{5}}),
+            packetizer.received_packet());
+  packetizer.ParseData(std::array<char, 1>{{0}});
+  ASSERT_FALSE(packetizer.received_packet().empty());
+  EXPECT_EQ(gsl::span<const char>(std::array<char, 2>{{9, 7}}),
+            packetizer.received_packet());
+}
+
+// Tests parsing a few packets, one span per packet.
+TEST(CobsPacketizerTest, BasicSinglePacket) {
+  CobsPacketizer<5> packetizer;
+
+  ASSERT_TRUE(packetizer.received_packet().empty());
+  packetizer.ParseData(std::array<char, 3>{{1, 2, 3}});
+  ASSERT_TRUE(packetizer.received_packet().empty());
+  packetizer.ParseData(std::array<char, 1>{{0}});
+  ASSERT_FALSE(packetizer.received_packet().empty());
+  EXPECT_EQ(gsl::span<const char>(std::array<char, 3>{{1, 2, 3}}),
+            packetizer.received_packet());
+  packetizer.clear_received_packet();
+  ASSERT_TRUE(packetizer.received_packet().empty());
+
+  ASSERT_TRUE(packetizer.received_packet().empty());
+  packetizer.ParseData(std::array<char, 1>{{5}});
+  ASSERT_TRUE(packetizer.received_packet().empty());
+  packetizer.ParseData(std::array<char, 1>{{0}});
+  ASSERT_FALSE(packetizer.received_packet().empty());
+  EXPECT_EQ(gsl::span<const char>(std::array<char, 1>{{5}}),
+            packetizer.received_packet());
+
+  ASSERT_FALSE(packetizer.received_packet().empty());
+  packetizer.ParseData(std::array<char, 2>{{9, 7}});
+  ASSERT_FALSE(packetizer.received_packet().empty());
+  EXPECT_EQ(gsl::span<const char>(std::array<char, 1>{{5}}),
+            packetizer.received_packet());
+  packetizer.ParseData(std::array<char, 1>{{0}});
+  ASSERT_FALSE(packetizer.received_packet().empty());
+  EXPECT_EQ(gsl::span<const char>(std::array<char, 2>{{9, 7}}),
+            packetizer.received_packet());
+}
+
+// Tests parsing a few packets, one span per packet including its terminator.
+TEST(CobsPacketizerTest, BasicSinglePacketWithTerminator) {
+  CobsPacketizer<5> packetizer;
+
+  ASSERT_TRUE(packetizer.received_packet().empty());
+  packetizer.ParseData(std::array<char, 4>{{1, 2, 3, 0}});
+  ASSERT_FALSE(packetizer.received_packet().empty());
+  EXPECT_EQ(gsl::span<const char>(std::array<char, 3>{{1, 2, 3}}),
+            packetizer.received_packet());
+  packetizer.clear_received_packet();
+  ASSERT_TRUE(packetizer.received_packet().empty());
+
+  ASSERT_TRUE(packetizer.received_packet().empty());
+  packetizer.ParseData(std::array<char, 2>{{5, 0}});
+  ASSERT_FALSE(packetizer.received_packet().empty());
+  EXPECT_EQ(gsl::span<const char>(std::array<char, 1>{{5}}),
+            packetizer.received_packet());
+
+  ASSERT_FALSE(packetizer.received_packet().empty());
+  packetizer.ParseData(std::array<char, 3>{{9, 7, 0}});
+  ASSERT_FALSE(packetizer.received_packet().empty());
+  EXPECT_EQ(gsl::span<const char>(std::array<char, 2>{{9, 7}}),
+            packetizer.received_packet());
+}
+
+// Tests parsing a packet in the same span as the previous terminator.
+TEST(CobsPacketizerTest, OverlappingEnd) {
+  CobsPacketizer<5> packetizer;
+
+  ASSERT_TRUE(packetizer.received_packet().empty());
+  packetizer.ParseData(std::array<char, 3>{{1, 2, 3}});
+  ASSERT_TRUE(packetizer.received_packet().empty());
+
+  ASSERT_TRUE(packetizer.received_packet().empty());
+  packetizer.ParseData(std::array<char, 2>{{0, 5}});
+  ASSERT_FALSE(packetizer.received_packet().empty());
+  EXPECT_EQ(gsl::span<const char>(std::array<char, 3>{{1, 2, 3}}),
+            packetizer.received_packet());
+  packetizer.clear_received_packet();
+  ASSERT_TRUE(packetizer.received_packet().empty());
+  packetizer.ParseData(std::array<char, 1>{{0}});
+  ASSERT_FALSE(packetizer.received_packet().empty());
+  EXPECT_EQ(gsl::span<const char>(std::array<char, 1>{{5}}),
+            packetizer.received_packet());
+}
+
+// Tests parsing a packet in the same span as the previous terminator, including
+// its terminator (so we skip the first packet).
+TEST(CobsPacketizerTest, OverlappingTwoEnds) {
+  CobsPacketizer<5> packetizer;
+
+  ASSERT_TRUE(packetizer.received_packet().empty());
+  packetizer.ParseData(std::array<char, 3>{{1, 2, 3}});
+  ASSERT_TRUE(packetizer.received_packet().empty());
+
+  ASSERT_TRUE(packetizer.received_packet().empty());
+  packetizer.ParseData(std::array<char, 3>{{0, 5, 0}});
+  ASSERT_FALSE(packetizer.received_packet().empty());
+  // We skip the {{1, 2, 3}} packet (arbitrarily; either that packet or this one
+  // has to be skipped).
+  EXPECT_EQ(gsl::span<const char>(std::array<char, 1>{{5}}),
+            packetizer.received_packet());
+}
+
+// Tests parsing a packet in the same span as the previous terminator, including
+// its terminator (so we skip the first packet), and then starting another new
+// packet.
+TEST(CobsPacketizerTest, OverlappingTwoEndsAndPartial) {
+  CobsPacketizer<5> packetizer;
+
+  ASSERT_TRUE(packetizer.received_packet().empty());
+  packetizer.ParseData(std::array<char, 3>{{1, 2, 3}});
+  ASSERT_TRUE(packetizer.received_packet().empty());
+
+  ASSERT_TRUE(packetizer.received_packet().empty());
+  packetizer.ParseData(std::array<char, 4>{{0, 5, 0, 8}});
+  ASSERT_FALSE(packetizer.received_packet().empty());
+  // We skip the {{5}} packet (arbitrarily; either that packet or this one has
+  // to be skipped).
+  EXPECT_EQ(gsl::span<const char>(std::array<char, 3>{{1, 2, 3}}),
+            packetizer.received_packet());
+
+  packetizer.ParseData(std::array<char, 1>{{0}});
+  ASSERT_FALSE(packetizer.received_packet().empty());
+  EXPECT_EQ(gsl::span<const char>(std::array<char, 1>{{8}}),
+            packetizer.received_packet());
+}
+
 }  // namespace jevois
 }  // namespace frc971