Modify the uart_buffer code to support reading

For reads, we push one character at a time and then read multiple ones.
We want to do this for the camera board.

Change-Id: I8a32dcaf0aa822a5642f388c58e02e17564203f3
diff --git a/motors/peripheral/uart_buffer.h b/motors/peripheral/uart_buffer.h
index 63dd70d..879ab5c 100644
--- a/motors/peripheral/uart_buffer.h
+++ b/motors/peripheral/uart_buffer.h
@@ -15,15 +15,25 @@
   // Returns the number of characters added.
   __attribute__((warn_unused_result)) int PushSpan(gsl::span<const char> data);
 
+  // max is the maximum size the returned spans should be.
+  // The data in the result is only valid until another method is called.
+  // Note that this may not return all available data when doing so would
+  // require wrapping around, but it will always return a non-empty span if any
+  // data is available.
+  gsl::span<const char> PopSpan(int max);
+
   bool empty() const { return size_ == 0; }
+  bool full() const { return size_ == kSize; }
 
   // This may only be called when !empty().
   char PopSingle();
+  // This may only be called when !full().
+  void PushSingle(char c);
 
   static constexpr int size() { return kSize; }
 
  private:
-  // The index at which we will push the next character.
+  // The index at which we will pop the next character.
   int start_ = 0;
   // How many characters we currently have.
   int size_ = 0;
@@ -31,7 +41,7 @@
   ::std::array<char, kSize> data_;
 };
 
-template<int kSize>
+template <int kSize>
 int UartBuffer<kSize>::PushSpan(gsl::span<const char> data) {
   const int end_location = (start_ + size_) % kSize;
   const int remaining_end = ::std::min(kSize - size_, kSize - end_location);
@@ -52,7 +62,16 @@
   return on_end + on_start;
 }
 
-template<int kSize>
+template <int kSize>
+gsl::span<const char> UartBuffer<kSize>::PopSpan(int max) {
+  const size_t result_size = std::min(max, std::min(kSize - start_, size_));
+  const auto result = gsl::span<const char>(data_).subspan(start_, result_size);
+  start_ = (start_ + result_size) % kSize;
+  size_ -= result_size;
+  return result;
+}
+
+template <int kSize>
 char UartBuffer<kSize>::PopSingle() {
   const char r = data_[start_];
   --size_;
@@ -60,6 +79,13 @@
   return r;
 }
 
+template <int kSize>
+void UartBuffer<kSize>::PushSingle(char c) {
+  const int end_location = (start_ + size_) % kSize;
+  data_[end_location] = c;
+  ++size_;
+}
+
 }  // namespace teensy
 }  // namespace frc971