File indexing completed on 2025-01-18 10:06:17
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #pragma once
0011
0012 #include "pybind11.h"
0013 #include "detail/common.h"
0014
0015 #include <deque>
0016 #include <list>
0017 #include <map>
0018 #include <ostream>
0019 #include <set>
0020 #include <unordered_map>
0021 #include <unordered_set>
0022 #include <valarray>
0023
0024
0025 #if defined(PYBIND11_HAS_OPTIONAL)
0026 # include <optional>
0027 #elif defined(PYBIND11_HAS_EXP_OPTIONAL)
0028 # include <experimental/optional>
0029 #endif
0030
0031 #if defined(PYBIND11_HAS_VARIANT)
0032 # include <variant>
0033 #endif
0034
0035 PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
0036 PYBIND11_NAMESPACE_BEGIN(detail)
0037
0038
0039
0040 template <typename T, typename U>
0041 using forwarded_type = conditional_t<std::is_lvalue_reference<T>::value,
0042 remove_reference_t<U> &,
0043 remove_reference_t<U> &&>;
0044
0045
0046
0047 template <typename T, typename U>
0048 constexpr forwarded_type<T, U> forward_like(U &&u) {
0049 return std::forward<detail::forwarded_type<T, U>>(std::forward<U>(u));
0050 }
0051
0052
0053
0054 template <typename C>
0055 using has_reserve_method = std::is_same<decltype(std::declval<C>().reserve(0)), void>;
0056
0057 template <typename Type, typename Key>
0058 struct set_caster {
0059 using type = Type;
0060 using key_conv = make_caster<Key>;
0061
0062 private:
0063 template <typename T = Type, enable_if_t<has_reserve_method<T>::value, int> = 0>
0064 void reserve_maybe(const anyset &s, Type *) {
0065 value.reserve(s.size());
0066 }
0067 void reserve_maybe(const anyset &, void *) {}
0068
0069 public:
0070 bool load(handle src, bool convert) {
0071 if (!isinstance<anyset>(src)) {
0072 return false;
0073 }
0074 auto s = reinterpret_borrow<anyset>(src);
0075 value.clear();
0076 reserve_maybe(s, &value);
0077 for (auto entry : s) {
0078 key_conv conv;
0079 if (!conv.load(entry, convert)) {
0080 return false;
0081 }
0082 value.insert(cast_op<Key &&>(std::move(conv)));
0083 }
0084 return true;
0085 }
0086
0087 template <typename T>
0088 static handle cast(T &&src, return_value_policy policy, handle parent) {
0089 if (!std::is_lvalue_reference<T>::value) {
0090 policy = return_value_policy_override<Key>::policy(policy);
0091 }
0092 pybind11::set s;
0093 for (auto &&value : src) {
0094 auto value_ = reinterpret_steal<object>(
0095 key_conv::cast(detail::forward_like<T>(value), policy, parent));
0096 if (!value_ || !s.add(std::move(value_))) {
0097 return handle();
0098 }
0099 }
0100 return s.release();
0101 }
0102
0103 PYBIND11_TYPE_CASTER(type, const_name("set[") + key_conv::name + const_name("]"));
0104 };
0105
0106 template <typename Type, typename Key, typename Value>
0107 struct map_caster {
0108 using key_conv = make_caster<Key>;
0109 using value_conv = make_caster<Value>;
0110
0111 private:
0112 template <typename T = Type, enable_if_t<has_reserve_method<T>::value, int> = 0>
0113 void reserve_maybe(const dict &d, Type *) {
0114 value.reserve(d.size());
0115 }
0116 void reserve_maybe(const dict &, void *) {}
0117
0118 public:
0119 bool load(handle src, bool convert) {
0120 if (!isinstance<dict>(src)) {
0121 return false;
0122 }
0123 auto d = reinterpret_borrow<dict>(src);
0124 value.clear();
0125 reserve_maybe(d, &value);
0126 for (auto it : d) {
0127 key_conv kconv;
0128 value_conv vconv;
0129 if (!kconv.load(it.first.ptr(), convert) || !vconv.load(it.second.ptr(), convert)) {
0130 return false;
0131 }
0132 value.emplace(cast_op<Key &&>(std::move(kconv)), cast_op<Value &&>(std::move(vconv)));
0133 }
0134 return true;
0135 }
0136
0137 template <typename T>
0138 static handle cast(T &&src, return_value_policy policy, handle parent) {
0139 dict d;
0140 return_value_policy policy_key = policy;
0141 return_value_policy policy_value = policy;
0142 if (!std::is_lvalue_reference<T>::value) {
0143 policy_key = return_value_policy_override<Key>::policy(policy_key);
0144 policy_value = return_value_policy_override<Value>::policy(policy_value);
0145 }
0146 for (auto &&kv : src) {
0147 auto key = reinterpret_steal<object>(
0148 key_conv::cast(detail::forward_like<T>(kv.first), policy_key, parent));
0149 auto value = reinterpret_steal<object>(
0150 value_conv::cast(detail::forward_like<T>(kv.second), policy_value, parent));
0151 if (!key || !value) {
0152 return handle();
0153 }
0154 d[std::move(key)] = std::move(value);
0155 }
0156 return d.release();
0157 }
0158
0159 PYBIND11_TYPE_CASTER(Type,
0160 const_name("dict[") + key_conv::name + const_name(", ") + value_conv::name
0161 + const_name("]"));
0162 };
0163
0164 template <typename Type, typename Value>
0165 struct list_caster {
0166 using value_conv = make_caster<Value>;
0167
0168 bool load(handle src, bool convert) {
0169 if (!isinstance<sequence>(src) || isinstance<bytes>(src) || isinstance<str>(src)) {
0170 return false;
0171 }
0172 auto s = reinterpret_borrow<sequence>(src);
0173 value.clear();
0174 reserve_maybe(s, &value);
0175 for (const auto &it : s) {
0176 value_conv conv;
0177 if (!conv.load(it, convert)) {
0178 return false;
0179 }
0180 value.push_back(cast_op<Value &&>(std::move(conv)));
0181 }
0182 return true;
0183 }
0184
0185 private:
0186 template <typename T = Type, enable_if_t<has_reserve_method<T>::value, int> = 0>
0187 void reserve_maybe(const sequence &s, Type *) {
0188 value.reserve(s.size());
0189 }
0190 void reserve_maybe(const sequence &, void *) {}
0191
0192 public:
0193 template <typename T>
0194 static handle cast(T &&src, return_value_policy policy, handle parent) {
0195 if (!std::is_lvalue_reference<T>::value) {
0196 policy = return_value_policy_override<Value>::policy(policy);
0197 }
0198 list l(src.size());
0199 ssize_t index = 0;
0200 for (auto &&value : src) {
0201 auto value_ = reinterpret_steal<object>(
0202 value_conv::cast(detail::forward_like<T>(value), policy, parent));
0203 if (!value_) {
0204 return handle();
0205 }
0206 PyList_SET_ITEM(l.ptr(), index++, value_.release().ptr());
0207 }
0208 return l.release();
0209 }
0210
0211 PYBIND11_TYPE_CASTER(Type, const_name("list[") + value_conv::name + const_name("]"));
0212 };
0213
0214 template <typename Type, typename Alloc>
0215 struct type_caster<std::vector<Type, Alloc>> : list_caster<std::vector<Type, Alloc>, Type> {};
0216
0217 template <typename Type, typename Alloc>
0218 struct type_caster<std::deque<Type, Alloc>> : list_caster<std::deque<Type, Alloc>, Type> {};
0219
0220 template <typename Type, typename Alloc>
0221 struct type_caster<std::list<Type, Alloc>> : list_caster<std::list<Type, Alloc>, Type> {};
0222
0223 template <typename ArrayType, typename Value, bool Resizable, size_t Size = 0>
0224 struct array_caster {
0225 using value_conv = make_caster<Value>;
0226
0227 private:
0228 template <bool R = Resizable>
0229 bool require_size(enable_if_t<R, size_t> size) {
0230 if (value.size() != size) {
0231 value.resize(size);
0232 }
0233 return true;
0234 }
0235 template <bool R = Resizable>
0236 bool require_size(enable_if_t<!R, size_t> size) {
0237 return size == Size;
0238 }
0239
0240 public:
0241 bool load(handle src, bool convert) {
0242 if (!isinstance<sequence>(src)) {
0243 return false;
0244 }
0245 auto l = reinterpret_borrow<sequence>(src);
0246 if (!require_size(l.size())) {
0247 return false;
0248 }
0249 size_t ctr = 0;
0250 for (const auto &it : l) {
0251 value_conv conv;
0252 if (!conv.load(it, convert)) {
0253 return false;
0254 }
0255 value[ctr++] = cast_op<Value &&>(std::move(conv));
0256 }
0257 return true;
0258 }
0259
0260 template <typename T>
0261 static handle cast(T &&src, return_value_policy policy, handle parent) {
0262 list l(src.size());
0263 ssize_t index = 0;
0264 for (auto &&value : src) {
0265 auto value_ = reinterpret_steal<object>(
0266 value_conv::cast(detail::forward_like<T>(value), policy, parent));
0267 if (!value_) {
0268 return handle();
0269 }
0270 PyList_SET_ITEM(l.ptr(), index++, value_.release().ptr());
0271 }
0272 return l.release();
0273 }
0274
0275 PYBIND11_TYPE_CASTER(ArrayType,
0276 const_name<Resizable>(const_name(""), const_name("Annotated["))
0277 + const_name("list[") + value_conv::name + const_name("]")
0278 + const_name<Resizable>(const_name(""),
0279 const_name(", FixedSize(")
0280 + const_name<Size>() + const_name(")]")));
0281 };
0282
0283 template <typename Type, size_t Size>
0284 struct type_caster<std::array<Type, Size>>
0285 : array_caster<std::array<Type, Size>, Type, false, Size> {};
0286
0287 template <typename Type>
0288 struct type_caster<std::valarray<Type>> : array_caster<std::valarray<Type>, Type, true> {};
0289
0290 template <typename Key, typename Compare, typename Alloc>
0291 struct type_caster<std::set<Key, Compare, Alloc>>
0292 : set_caster<std::set<Key, Compare, Alloc>, Key> {};
0293
0294 template <typename Key, typename Hash, typename Equal, typename Alloc>
0295 struct type_caster<std::unordered_set<Key, Hash, Equal, Alloc>>
0296 : set_caster<std::unordered_set<Key, Hash, Equal, Alloc>, Key> {};
0297
0298 template <typename Key, typename Value, typename Compare, typename Alloc>
0299 struct type_caster<std::map<Key, Value, Compare, Alloc>>
0300 : map_caster<std::map<Key, Value, Compare, Alloc>, Key, Value> {};
0301
0302 template <typename Key, typename Value, typename Hash, typename Equal, typename Alloc>
0303 struct type_caster<std::unordered_map<Key, Value, Hash, Equal, Alloc>>
0304 : map_caster<std::unordered_map<Key, Value, Hash, Equal, Alloc>, Key, Value> {};
0305
0306
0307 template <typename Type, typename Value = typename Type::value_type>
0308 struct optional_caster {
0309 using value_conv = make_caster<Value>;
0310
0311 template <typename T>
0312 static handle cast(T &&src, return_value_policy policy, handle parent) {
0313 if (!src) {
0314 return none().release();
0315 }
0316 if (!std::is_lvalue_reference<T>::value) {
0317 policy = return_value_policy_override<Value>::policy(policy);
0318 }
0319
0320 return value_conv::cast(*std::forward<T>(src), policy, parent);
0321 }
0322
0323 bool load(handle src, bool convert) {
0324 if (!src) {
0325 return false;
0326 }
0327 if (src.is_none()) {
0328 return true;
0329 }
0330 value_conv inner_caster;
0331 if (!inner_caster.load(src, convert)) {
0332 return false;
0333 }
0334
0335 value.emplace(cast_op<Value &&>(std::move(inner_caster)));
0336 return true;
0337 }
0338
0339 PYBIND11_TYPE_CASTER(Type, const_name("Optional[") + value_conv::name + const_name("]"));
0340 };
0341
0342 #if defined(PYBIND11_HAS_OPTIONAL)
0343 template <typename T>
0344 struct type_caster<std::optional<T>> : public optional_caster<std::optional<T>> {};
0345
0346 template <>
0347 struct type_caster<std::nullopt_t> : public void_caster<std::nullopt_t> {};
0348 #endif
0349
0350 #if defined(PYBIND11_HAS_EXP_OPTIONAL)
0351 template <typename T>
0352 struct type_caster<std::experimental::optional<T>>
0353 : public optional_caster<std::experimental::optional<T>> {};
0354
0355 template <>
0356 struct type_caster<std::experimental::nullopt_t>
0357 : public void_caster<std::experimental::nullopt_t> {};
0358 #endif
0359
0360
0361 struct variant_caster_visitor {
0362 return_value_policy policy;
0363 handle parent;
0364
0365 using result_type = handle;
0366
0367 template <typename T>
0368 result_type operator()(T &&src) const {
0369 return make_caster<T>::cast(std::forward<T>(src), policy, parent);
0370 }
0371 };
0372
0373
0374
0375
0376
0377 template <template <typename...> class Variant>
0378 struct visit_helper {
0379 template <typename... Args>
0380 static auto call(Args &&...args) -> decltype(visit(std::forward<Args>(args)...)) {
0381 return visit(std::forward<Args>(args)...);
0382 }
0383 };
0384
0385
0386 template <typename Variant>
0387 struct variant_caster;
0388
0389 template <template <typename...> class V, typename... Ts>
0390 struct variant_caster<V<Ts...>> {
0391 static_assert(sizeof...(Ts) > 0, "Variant must consist of at least one alternative.");
0392
0393 template <typename U, typename... Us>
0394 bool load_alternative(handle src, bool convert, type_list<U, Us...>) {
0395 auto caster = make_caster<U>();
0396 if (caster.load(src, convert)) {
0397 value = cast_op<U>(std::move(caster));
0398 return true;
0399 }
0400 return load_alternative(src, convert, type_list<Us...>{});
0401 }
0402
0403 bool load_alternative(handle, bool, type_list<>) { return false; }
0404
0405 bool load(handle src, bool convert) {
0406
0407
0408
0409
0410 if (convert && load_alternative(src, false, type_list<Ts...>{})) {
0411 return true;
0412 }
0413 return load_alternative(src, convert, type_list<Ts...>{});
0414 }
0415
0416 template <typename Variant>
0417 static handle cast(Variant &&src, return_value_policy policy, handle parent) {
0418 return visit_helper<V>::call(variant_caster_visitor{policy, parent},
0419 std::forward<Variant>(src));
0420 }
0421
0422 using Type = V<Ts...>;
0423 PYBIND11_TYPE_CASTER(Type,
0424 const_name("Union[")
0425 + ::pybind11::detail::concat(make_caster<Ts>::name...)
0426 + const_name("]"));
0427 };
0428
0429 #if defined(PYBIND11_HAS_VARIANT)
0430 template <typename... Ts>
0431 struct type_caster<std::variant<Ts...>> : variant_caster<std::variant<Ts...>> {};
0432
0433 template <>
0434 struct type_caster<std::monostate> : public void_caster<std::monostate> {};
0435 #endif
0436
0437 PYBIND11_NAMESPACE_END(detail)
0438
0439 inline std::ostream &operator<<(std::ostream &os, const handle &obj) {
0440 #ifdef PYBIND11_HAS_STRING_VIEW
0441 os << str(obj).cast<std::string_view>();
0442 #else
0443 os << (std::string) str(obj);
0444 #endif
0445 return os;
0446 }
0447
0448 PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)