10
10
namespace pybind11 {
11
11
namespace detail {
12
12
13
- template <typename Type> struct type_caster <std::span<Type>> {
13
+ template <size_t N>
14
+ struct span_name_maker {
15
+ template <typename T>
16
+ static constexpr auto make (const T &t) {
17
+ return concat (t, span_name_maker<N-1 >::make (t));
18
+ }
19
+ };
20
+
21
+ template <>
22
+ struct span_name_maker <1 > {
23
+ template <typename T>
24
+ static constexpr auto make (const T &t) {
25
+ return t;
26
+ }
27
+ };
28
+
29
+ // span with fixed size converts to a tuple
30
+ template <typename Type, size_t Extent> struct type_caster <std::span<Type, Extent>> {
31
+ using span_type = typename std::span<Type, Extent>;
32
+ using value_conv = make_caster<Type>;
33
+ using value_type = typename std::remove_cv<Type>::type;
34
+
35
+ value_type backing_array[Extent] = {};
36
+
37
+ PYBIND11_TYPE_CASTER (span_type, _(" Tuple[" ) + span_name_maker<Extent>::make(value_conv::name) + _(" ]" ));
38
+
39
+ type_caster () : value(backing_array) {}
40
+
41
+ bool load (handle src, bool convert) {
42
+ if (!isinstance<sequence>(src) || isinstance<str>(src))
43
+ return false ;
44
+ auto s = reinterpret_borrow<sequence>(src);
45
+ if (s.size () != Extent)
46
+ return false ;
47
+ size_t i = 0 ;
48
+ for (auto it : s) {
49
+ value_conv conv;
50
+ if (!conv.load (it, convert))
51
+ return false ;
52
+ backing_array[i] = cast_op<Type &&>(std::move (conv));
53
+ i++;
54
+ }
55
+ return true ;
56
+ }
57
+
58
+ public:
59
+ template <typename T>
60
+ static handle cast (T &&src, return_value_policy policy, handle parent) {
61
+ if (!std::is_lvalue_reference<T>::value)
62
+ policy = return_value_policy_override<Type>::policy (policy);
63
+ tuple l (Extent);
64
+ size_t index = 0 ;
65
+ for (auto &&value : src) {
66
+ auto value_ = reinterpret_steal<object>(
67
+ value_conv::cast (forward_like<T>(value), policy, parent));
68
+ if (!value_)
69
+ return handle ();
70
+ PyTuple_SET_ITEM (l.ptr (), (ssize_t )index ++,
71
+ value_.release ().ptr ()); // steals a reference
72
+ }
73
+ return l.release ();
74
+ }
75
+ };
76
+
77
+
78
+ // span with dynamic extent
79
+ template <typename Type> struct type_caster <std::span<Type, std::dynamic_extent>> {
80
+ using span_type = typename std::span<Type, std::dynamic_extent>;
14
81
using value_conv = make_caster<Type>;
15
82
using value_type = typename std::remove_cv<Type>::type;
16
- PYBIND11_TYPE_CASTER (std::span<Type> , _(" List[" ) + value_conv::name + _(" ]" ));
83
+ PYBIND11_TYPE_CASTER (span_type , _(" List[" ) + value_conv::name + _(" ]" ));
17
84
18
85
wpi::SmallVector<value_type, 32 > vec;
19
86
bool load (handle src, bool convert) {
@@ -27,7 +94,7 @@ template <typename Type> struct type_caster<std::span<Type>> {
27
94
return false ;
28
95
vec.push_back (cast_op<Type &&>(std::move (conv)));
29
96
}
30
- value = std::span<Type> (std::data (vec), std::size (vec));
97
+ value = span_type (std::data (vec), std::size (vec));
31
98
return true ;
32
99
}
33
100
@@ -51,8 +118,9 @@ template <typename Type> struct type_caster<std::span<Type>> {
51
118
};
52
119
53
120
// span specialization: accepts any readonly buffers
54
- template <> struct type_caster <std::span<const uint8_t >> {
55
- PYBIND11_TYPE_CASTER (std::span<const uint8_t >, _(" buffer" ));
121
+ template <> struct type_caster <std::span<const uint8_t , std::dynamic_extent>> {
122
+ using span_type = typename std::span<const uint8_t , std::dynamic_extent>;
123
+ PYBIND11_TYPE_CASTER (span_type, _(" buffer" ));
56
124
57
125
bool load (handle src, bool convert) {
58
126
if (!isinstance<buffer>(src))
@@ -63,7 +131,7 @@ template <> struct type_caster<std::span<const uint8_t>> {
63
131
return false ;
64
132
}
65
133
66
- value = std::span< const uint8_t > ((const uint8_t *)req.ptr , req.size *req.itemsize );
134
+ value = span_type ((const uint8_t *)req.ptr , req.size *req.itemsize );
67
135
return true ;
68
136
}
69
137
@@ -75,7 +143,8 @@ template <> struct type_caster<std::span<const uint8_t>> {
75
143
};
76
144
77
145
// span specialization: writeable buffer
78
- template <> struct type_caster <std::span<uint8_t >> {
146
+ template <> struct type_caster <std::span<uint8_t , std::dynamic_extent>> {
147
+ using span_type = typename std::span<const uint8_t , std::dynamic_extent>;
79
148
PYBIND11_TYPE_CASTER (std::span<uint8_t >, _(" buffer" ));
80
149
81
150
bool load (handle src, bool convert) {
0 commit comments