From f4c3420bf38f7f2c73fb52780383adecfedf4fc0 Mon Sep 17 00:00:00 2001
From: Michael Bloom <mike.r.bloom@protonmail.com>
Date: Wed, 13 Nov 2024 15:13:52 -0500
Subject: [PATCH] Add at method to span

---
 include/etl/span.h                | 40 +++++++++++++++++++++++++++++++
 test/test_span_dynamic_extent.cpp | 16 +++++++++++++
 test/test_span_fixed_extent.cpp   | 16 +++++++++++++
 3 files changed, 72 insertions(+)

diff --git a/include/etl/span.h b/include/etl/span.h
index f1077ea77..7aa11c960 100644
--- a/include/etl/span.h
+++ b/include/etl/span.h
@@ -272,6 +272,26 @@ namespace etl
     {
       pbegin = other.pbegin;
       return *this;
+    } 
+
+    //*************************************************************************
+    /// Returns a reference to the value at index 'i'.
+    //*************************************************************************
+    ETL_NODISCARD ETL_CONSTEXPR14 reference at(size_t i)
+    {
+      ETL_ASSERT(i < size(), ETL_ERROR(array_out_of_range));
+
+      return pbegin[i];
+    }
+
+    //*************************************************************************
+    /// Returns a const reference to the value at index 'i'.
+    //*************************************************************************
+    ETL_NODISCARD ETL_CONSTEXPR14 const_reference at(size_t i) const
+    {
+      ETL_ASSERT(i < size(), ETL_ERROR(array_out_of_range));
+
+      return pbegin[i];
     }
 
     //*************************************************************************
@@ -614,6 +634,26 @@ namespace etl
       return *this;
     }
 
+    //*************************************************************************
+    /// Returns a reference to the value at index 'i'.
+    //*************************************************************************
+    ETL_NODISCARD ETL_CONSTEXPR14 reference at(size_t i)
+    {
+      ETL_ASSERT(i < size(), ETL_ERROR(array_out_of_range));
+
+      return pbegin[i];
+    }
+
+    //*************************************************************************
+    /// Returns a const reference to the value at index 'i'.
+    //*************************************************************************
+    ETL_NODISCARD ETL_CONSTEXPR14 const_reference at(size_t i) const
+    {
+      ETL_ASSERT(i < size(), ETL_ERROR(array_out_of_range));
+
+      return pbegin[i];
+    }
+
     //*************************************************************************
     /// Returns a reference to the indexed value.
     //*************************************************************************
diff --git a/test/test_span_dynamic_extent.cpp b/test/test_span_dynamic_extent.cpp
index 3d7df1ec0..300ee58c5 100644
--- a/test/test_span_dynamic_extent.cpp
+++ b/test/test_span_dynamic_extent.cpp
@@ -445,6 +445,22 @@ namespace
       CHECK_EQUAL(etldata.data(), cview.data());
     }
 
+    //*************************************************************************
+    TEST(test_at)
+    {
+      View  view(etldata.begin(), etldata.end());
+      CView cview(etldata.begin(), etldata.end());
+
+      for (size_t i = 0UL; i < etldata.size(); ++i)
+      {
+        CHECK_EQUAL(etldata.at(i), view.at(i));
+        CHECK_EQUAL(etldata.at(i), cview.at(i));
+      }
+
+      CHECK_THROW({ int d = view.at(view.size()); (void)d; }, etl::array_out_of_range);
+      CHECK_THROW({ int d = cview.at(cview.size()); (void)d; }, etl::array_out_of_range);
+    }
+
     //*************************************************************************
     TEST(test_index_operator)
     {
diff --git a/test/test_span_fixed_extent.cpp b/test/test_span_fixed_extent.cpp
index 157170a09..2c760783a 100644
--- a/test/test_span_fixed_extent.cpp
+++ b/test/test_span_fixed_extent.cpp
@@ -433,6 +433,22 @@ namespace
       CHECK_EQUAL(etldata.data(), cview.data());
     }
 
+    //*************************************************************************
+    TEST(test_at)
+    {
+      View  view(etldata.begin(), etldata.end());
+      CView cview(etldata.begin(), etldata.end());
+
+      for (size_t i = 0UL; i < etldata.size(); ++i)
+      {
+        CHECK_EQUAL(etldata.at(i), view.at(i));
+        CHECK_EQUAL(etldata.at(i), cview.at(i));
+      }
+
+      CHECK_THROW({ int d = view.at(view.size()); (void)d; }, etl::array_out_of_range);
+      CHECK_THROW({ int d = cview.at(cview.size()); (void)d; }, etl::array_out_of_range);
+    }
+
     //*************************************************************************
     TEST(test_index_operator)
     {