File size: 5,943 Bytes
5f923cd
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
--- include/nanobind_json/nanobind_json.hpp 
+++ include/nanobind_json/nanobind_json.hpp 
@@ -13,13 +13,15 @@
 
 #include "nlohmann/json.hpp"
 
-#include "nanobind/nanobind.hpp"
+#include <nanobind/nanobind.h>
+#include <nanobind/stl/string.h>
 
 namespace nb = nanobind;
 namespace nl = nlohmann;
 
 namespace pyjson
 {
+
     inline nb::object from_json(const nl::json& j)
     {
         if (j.is_null())
@@ -40,7 +42,7 @@
         }
         else if (j.is_string())
         {
-            return nb::str(j.get<std::string>());
+            return nb::str(j.get<std::string>().c_str());
         }
         else if (j.is_array())
         {
@@ -56,7 +58,7 @@
             nb::dict obj;
             for (nl::json::const_iterator it = j.cbegin(); it != j.cend(); ++it)
             {
-                obj[nb::str(it.key())] = from_json(it.value());
+                obj[nb::str(it.key().c_str())] = from_json(it.value());
             }
             return std::move(obj);
         }
@@ -70,24 +72,24 @@
         }
         if (nb::isinstance<nb::bool_>(obj))
         {
-            return obj.cast<bool>();
+            return nb::cast<bool>(obj);
         }
         if (nb::isinstance<nb::int_>(obj))
         {
-            return obj.cast<long>();
+            return nb::cast<long>(obj);
         }
         if (nb::isinstance<nb::float_>(obj))
         {
-            return obj.cast<double>();
+            return nb::cast<double>(obj);
         }
         if (nb::isinstance<nb::bytes>(obj))
         {
-            nb::module base64 = nb::module::import("base64");
-            return base64.attr("b64encode")(obj).attr("decode")("utf-8").cast<std::string>();
+            nb::module_ base64 = nb::module_::import_("base64");
+            return nb::cast<std::string>(base64.attr("b64encode")(obj).attr("decode")("utf-8"));
         }
         if (nb::isinstance<nb::str>(obj))
         {
-            return obj.cast<std::string>();
+            return nb::cast<std::string>(obj);
         }
         if (nb::isinstance<nb::tuple>(obj) || nb::isinstance<nb::list>(obj))
         {
@@ -103,11 +105,11 @@
             auto out = nl::json::object();
             for (const nb::handle key : obj)
             {
-                out[nb::str(key).cast<std::string>()] = to_json(obj[key]);
+                out[nb::cast<std::string>(nb::str(key))] = to_json(obj[key]);
             }
             return out;
         }
-        throw std::runtime_error("to_json not implemented for this type of object: " + nb::repr(obj).cast<std::string>());
+        throw std::runtime_error("to_json not implemented for this type of object: " + nb::cast<std::string>(nb::repr(obj)));
     }
 }
 
@@ -123,7 +125,7 @@
             j = pyjson::to_json(obj);                      \
         }                                                  \
                                                            \
-        inline static T from_json(const json& j)           \
+        inline static nb::object from_json(const json& j)  \
         {                                                  \
             return pyjson::from_json(j);                   \
         }                                                  \
@@ -151,12 +153,6 @@
     MAKE_NLJSON_SERIALIZER_DESERIALIZER(nb::dict);
 
     MAKE_NLJSON_SERIALIZER_ONLY(nb::handle);
-    MAKE_NLJSON_SERIALIZER_ONLY(nb::detail::item_accessor);
-    MAKE_NLJSON_SERIALIZER_ONLY(nb::detail::list_accessor);
-    MAKE_NLJSON_SERIALIZER_ONLY(nb::detail::tuple_accessor);
-    MAKE_NLJSON_SERIALIZER_ONLY(nb::detail::sequence_accessor);
-    MAKE_NLJSON_SERIALIZER_ONLY(nb::detail::str_attr_accessor);
-    MAKE_NLJSON_SERIALIZER_ONLY(nb::detail::obj_attr_accessor);
 
     #undef MAKE_NLJSON_SERIALIZER
     #undef MAKE_NLJSON_SERIALIZER_ONLY
@@ -167,28 +163,53 @@
 {
     namespace detail
     {
-        template <> struct type_caster<nl::json>
-        {
-        public:
-            NANOBIND_TYPE_CASTER(nl::json, _("json"));
+    
+    template <> struct type_caster<nl::json> {
+        using Value = nl::json;
 
-            bool load(handle src, bool)
-            {
-                try {
-                    value = pyjson::to_json(src);
-                    return true;
-                }
-                catch (...)
-                {
-                    return false;
-                }
-            }
+        template <typename T> using Cast = Value;
+
+        // Value name for docstring generation
+        static constexpr auto Name = const_name("Json");
 
-            static handle cast(nl::json src, return_value_policy /* policy */, handle /* parent */)
+        /// Python -> C++ caster, populates `caster1` and `caster2` upon success
+        bool from_python(handle src, uint8_t flags,
+                        cleanup_list *cleanup) noexcept {
+            try {
+                value = pyjson::to_json(src);
+                return true;
+            }
+            catch (...)
             {
-                object obj = pyjson::from_json(src);
-                return obj.release();
+                return false;
             }
-        };
+        }
+
+        template <typename T>
+        static handle from_cpp(T *value, rv_policy policy, cleanup_list *cleanup) {
+            if (!value)
+                return none().release();
+            return from_cpp(*value, policy, cleanup);
+        }
+
+        template<typename T>
+        static handle from_cpp(T &&value, rv_policy policy,
+                              cleanup_list *cleanup) noexcept {
+            object obj = pyjson::from_json(value);
+            return obj.release();
+        }
+
+        template <typename T>
+        bool can_cast() const noexcept {
+            return true;
+        }
+
+        /// Return the constructed tuple by copying from the sub-casters
+        explicit operator Value() {
+            return value;
+        }
+
+        Value value;
+    };
     }
 }