Allow SkSpan(data, size) ctor to accept any integral-typed size.

We can reduce the boilerplate casts needed in the code by allowing
SkSpan to take any integral type here, not just size_t.

Change-Id: I3a34b8d21d83ae00af7a8e7af31a65e1f1f31b03
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/601321
Reviewed-by: Brian Osman <brianosman@google.com>
Reviewed-by: Herb Derby <herb@google.com>
Commit-Queue: John Stiles <johnstiles@google.com>
diff --git a/include/core/SkSpan.h b/include/core/SkSpan.h
index 4e4d02c..ad8f126 100644
--- a/include/core/SkSpan.h
+++ b/include/core/SkSpan.h
@@ -9,6 +9,7 @@
 #define SkSpan_DEFINED
 
 #include "include/core/SkTypes.h"
+#include "include/private/SkTo.h"
 
 #include <cstddef>
 #include <initializer_list>
@@ -63,9 +64,11 @@
 class SkSpan {
 public:
     constexpr SkSpan() : fPtr{nullptr}, fSize{0} {}
-    constexpr SkSpan(T* ptr, size_t size) : fPtr{ptr}, fSize{size} {
-        SkASSERT(ptr || size == 0);  // disallow nullptr + a nonzero size
-        SkASSERT(size < kMaxSize);
+
+    template <typename Integer, std::enable_if_t<std::is_integral_v<Integer>, bool> = true>
+    constexpr SkSpan(T* ptr, Integer size) : fPtr{ptr}, fSize{SkToSizeT(size)} {
+        SkASSERT(ptr || fSize == 0);  // disallow nullptr + a nonzero size
+        SkASSERT(fSize < kMaxSize);
     }
     template <typename U, typename = typename std::enable_if<std::is_same<const U, T>::value>::type>
     constexpr SkSpan(const SkSpan<U>& that) : fPtr(std::data(that)), fSize{std::size(that)} {}
diff --git a/tests/SkSpanTest.cpp b/tests/SkSpanTest.cpp
index 63b4851..196eadd 100644
--- a/tests/SkSpanTest.cpp
+++ b/tests/SkSpanTest.cpp
@@ -7,7 +7,10 @@
 
 #include "include/core/SkSpan.h"
 #include "tests/Test.h"
+
 #include <array>
+#include <cstddef>
+#include <cstdint>
 #include <vector>
 
 DEF_TEST(SkSpanBasicTemplateGuide, reporter) {
@@ -96,3 +99,32 @@
         REPORTER_ASSERT(reporter, test_span_parameter(s));
     }
 }
+
+DEF_TEST(SkSpanDeduceSize, reporter) {
+    int d[] = {1, 2, 3, 4, 5};
+    {
+        int s = std::size(d);
+        SkSpan span = SkSpan{d, s};
+        REPORTER_ASSERT(reporter, span.size() == std::size(d));
+    }
+    {
+        uint32_t s = std::size(d);
+        SkSpan span = SkSpan{d, s};
+        REPORTER_ASSERT(reporter, span.size() == std::size(d));
+    }
+    {
+        size_t s = std::size(d);
+        SkSpan span = SkSpan{d, s};
+        REPORTER_ASSERT(reporter, span.size() == std::size(d));
+    }
+    {
+        struct C {
+            int* data() { return nullptr; }
+            int size() const { return 0; }
+        };
+
+        C c;
+        SkSpan span = SkSpan(c);
+        REPORTER_ASSERT(reporter, span.size() == 0);
+    }
+}