ICU4X
International Components for Unicode
Loading...
Searching...
No Matches
diplomat_runtime.hpp
Go to the documentation of this file.
1#ifndef ICU4X_DIPLOMAT_RUNTIME_CPP_H
2#define ICU4X_DIPLOMAT_RUNTIME_CPP_H
3
4#include <optional>
5#include <string>
6#include <string_view>
7#include <type_traits>
8#include <variant>
9#include <cstdint>
10#include <functional>
11#include <memory>
12#include <limits>
13
14
15#if __cplusplus >= 202002L
16#include <span>
17#else
18#include <array>
19#endif
20
21#ifndef DIPLOMAT_LIFETIME_BOUND
22#if defined(__has_cpp_attribute)
23#if __has_cpp_attribute(msvc::lifetimebound)
24#define DIPLOMAT_LIFETIME_BOUND [[msvc::lifetimebound]]
25#elif __has_cpp_attribute(clang::lifetimebound)
26#define DIPLOMAT_LIFETIME_BOUND [[clang::lifetimebound]]
27#endif
28#endif
29#endif
30
31#ifndef DIPLOMAT_LIFETIME_BOUND
32#define DIPLOMAT_LIFETIME_BOUND
33#endif
34
35namespace icu4x {
36namespace diplomat {
37
38namespace capi {
39extern "C" {
40
41static_assert(sizeof(char) == sizeof(uint8_t), "your architecture's `char` is not 8 bits");
42static_assert(sizeof(char16_t) == sizeof(uint16_t), "your architecture's `char16_t` is not 16 bits");
43static_assert(sizeof(char32_t) == sizeof(uint32_t), "your architecture's `char32_t` is not 32 bits");
44
45typedef struct DiplomatWrite {
46 void* context;
47 char* buf;
48 size_t len;
49 size_t cap;
50 bool grow_failed;
51 void (*flush)(struct DiplomatWrite*);
52 bool (*grow)(struct DiplomatWrite*, size_t);
53} DiplomatWrite;
54
55bool diplomat_is_str(const char* buf, size_t len);
56
57#define MAKE_SLICES(name, c_ty) \
58 typedef struct Diplomat##name##View { \
59 const c_ty* data; \
60 size_t len; \
61 } Diplomat##name##View; \
62 typedef struct Diplomat##name##ViewMut { \
63 c_ty* data; \
64 size_t len; \
65 } Diplomat##name##ViewMut; \
66 typedef struct Diplomat##name##Array { \
67 const c_ty* data; \
68 size_t len; \
69 } Diplomat##name##Array;
70
71#define MAKE_SLICES_AND_OPTIONS(name, c_ty) \
72 MAKE_SLICES(name, c_ty) \
73 typedef struct Option##name {union { c_ty ok; }; bool is_ok; } Option##name; \
74 typedef struct Option##name##View {union { Diplomat##name##View ok; }; bool is_ok; } Option##name##View; \
75 typedef struct Option##name##ViewMut {union { Diplomat##name##ViewMut ok; }; bool is_ok; } Option##name##ViewMut; \
76 typedef struct Option##name##Array {union { Diplomat##name##Array ok; }; bool is_ok; } Option##name##Array; \
77
79MAKE_SLICES_AND_OPTIONS(U8, uint8_t)
80MAKE_SLICES_AND_OPTIONS(I16, int16_t)
81MAKE_SLICES_AND_OPTIONS(U16, uint16_t)
82MAKE_SLICES_AND_OPTIONS(I32, int32_t)
83MAKE_SLICES_AND_OPTIONS(U32, uint32_t)
84MAKE_SLICES_AND_OPTIONS(I64, int64_t)
85MAKE_SLICES_AND_OPTIONS(U64, uint64_t)
86MAKE_SLICES_AND_OPTIONS(Isize, intptr_t)
87MAKE_SLICES_AND_OPTIONS(Usize, size_t)
89MAKE_SLICES_AND_OPTIONS(F64, double)
91MAKE_SLICES_AND_OPTIONS(Char, char32_t)
92MAKE_SLICES_AND_OPTIONS(String, char)
93MAKE_SLICES_AND_OPTIONS(String16, char16_t)
94MAKE_SLICES_AND_OPTIONS(Strings, DiplomatStringView)
95MAKE_SLICES_AND_OPTIONS(Strings16, DiplomatString16View)
96
97} // extern "C"
98} // namespace capi
99
100extern "C" inline void _flush(capi::DiplomatWrite* w) {
101 std::string* string = reinterpret_cast<std::string*>(w->context);
102 string->resize(w->len);
103}
104
105extern "C" inline bool _grow_impl(capi::DiplomatWrite* w, uintptr_t requested) {
106 std::string* string = reinterpret_cast<std::string*>(w->context);
107 string->resize(requested);
108 w->cap = string->length();
109 w->buf = &(*string)[0];
110 return true;
111}
112
113extern "C" inline bool _grow(capi::DiplomatWrite* w, size_t requested) {
114 return _grow_impl(w, static_cast<uintptr_t>(requested));
115}
116
117inline capi::DiplomatWrite WriteFromString(std::string& string) {
118 capi::DiplomatWrite w;
119 w.context = &string;
120 w.buf = &string[0];
121 w.len = string.length();
122 w.cap = string.length();
123 // Will never become true, as _grow is infallible.
124 w.grow_failed = false;
125 w.flush = _flush;
126 w.grow = _grow;
127 return w;
128}
129
130// This "trait" allows one to use _write() methods to efficiently
131// write to a custom string type. To do this you need to write a specialized
132// `WriteTrait<YourType>` (see WriteTrait<std::string> below)
133// that is capable of constructing a DiplomatWrite, which can wrap
134// your string type with appropriate resize/flush functionality.
135template<typename T> struct WriteTrait {
136 // Fill in this method on a specialization to implement this trait
137 // static inline capi::DiplomatWrite Construct(T& t);
138};
139
140template<> struct WriteTrait<std::string> {
141 static inline capi::DiplomatWrite Construct(std::string& t) {
142 return diplomat::WriteFromString(t);
143 }
144};
145
146template<class T> struct Ok {
148
149 // Move constructor always allowed
150 Ok(T&& i): inner(std::forward<T>(i)) {}
151
152 // copy constructor allowed only for trivially copyable types
154 Ok(const T& i) : inner(i) {}
155
156 Ok() = default;
161};
162
163
166
167 // Move constructor always allowed
168 Err(T&& i): inner(std::forward<T>(i)) {}
169
170 // copy constructor allowed only for trivially copyable types
172 Err(const T& i) : inner(i) {}
173
174 Err() = default;
179};
180
181template<class T, class E>
183protected:
184 std::variant<Ok<T>, Err<E>> val;
185public:
186
187 result(Ok<T>&& v): val(std::move(v)) {}
188 result(Err<E>&& v): val(std::move(v)) {}
189 result() = default;
190 result(const result &) = default;
191 result& operator=(const result&) = default;
195 bool is_ok() const {
196 return std::holds_alternative<Ok<T>>(this->val);
197 }
198 bool is_err() const {
199 return std::holds_alternative<Err<E>>(this->val);
200 }
201
202 template<typename U = T, typename std::enable_if_t<!std::is_reference_v<U>, std::nullptr_t> = nullptr>
203 std::optional<T> ok() && {
204 if (!this->is_ok()) {
205 return std::nullopt;
206 }
207 return std::make_optional(std::move(std::get<Ok<T>>(std::move(this->val)).inner));
208 }
209
210 template<typename U = E, typename std::enable_if_t<!std::is_reference_v<U>, std::nullptr_t> = nullptr>
211 std::optional<E> err() && {
212 if (!this->is_err()) {
213 return std::nullopt;
214 }
215 return std::make_optional(std::move(std::get<Err<E>>(std::move(this->val)).inner));
216 }
217
218 // std::optional does not work with reference types directly, so wrap them if present
219 template<typename U = T, typename std::enable_if_t<std::is_reference_v<U>, std::nullptr_t> = nullptr>
220 std::optional<std::reference_wrapper<std::remove_reference_t<T>>> ok() && {
221 if (!this->is_ok()) {
222 return std::nullopt;
223 }
224 return std::make_optional(std::reference_wrapper(std::forward<T>(std::get<Ok<T>>(std::move(this->val)).inner)));
225 }
226
227 template<typename U = E, typename std::enable_if_t<std::is_reference_v<U>, std::nullptr_t> = nullptr>
228 std::optional<std::reference_wrapper<std::remove_reference_t<E>>> err() && {
229 if (!this->is_err()) {
230 return std::nullopt;
231 }
232 return std::make_optional(std::reference_wrapper(std::forward<E>(std::get<Err<E>>(std::move(this->val)).inner)));
233 }
234
235 void set_ok(T&& t) {
236 this->val = Ok<T>(std::move(t));
237 }
238
239 void set_err(E&& e) {
240 this->val = Err<E>(std::move(e));
241 }
242
243 template<typename T2>
245 if (this->is_err()) {
246 return result<T2, E>(Err<E>(std::get<Err<E>>(std::move(this->val))));
247 } else {
248 return result<T2, E>(Ok<T2>(std::move(t)));
249 }
250 }
251};
252
253class Utf8Error {};
254
255// Use custom std::span on C++17, otherwise use std::span
256#if __cplusplus >= 202002L
257
258constexpr std::size_t dynamic_extent = std::dynamic_extent;
259template<class T, std::size_t E = dynamic_extent> using span = std::span<T, E>;
260
261#else // __cplusplus < 202002L
262
263// C++-17-compatible-ish std::span
264constexpr size_t dynamic_extent = std::numeric_limits<std::size_t>::max();
265template <class T, std::size_t Extent = dynamic_extent>
266class span {
267public:
268 constexpr span(T *data = nullptr, size_t size = Extent)
269 : data_(data), size_(size) {}
270
271 constexpr span(const span<T> &o)
272 : data_(o.data_), size_(o.size_) {}
273 template <size_t N>
274 constexpr span(std::array<typename std::remove_const_t<T>, N> &arr)
275 : data_(const_cast<T *>(arr.data())), size_(N) {}
276
277 constexpr T* data() const noexcept {
278 return this->data_;
279 }
280 constexpr size_t size() const noexcept {
281 return this->size_;
282 }
283
284 constexpr T *begin() const noexcept { return data(); }
285 constexpr T *end() const noexcept { return data() + size(); }
286
288 data_ = o.data_;
289 size_ = o.size_;
290 }
291
292private:
293 T* data_;
294 size_t size_;
295};
296
297#endif // __cplusplus >= 202002L
298
299// An ABI stable std::basic_string_view equivalent for the case of string
300// views in slices
301template <class CharT, class Traits = std::char_traits<CharT>>
303public:
304 using std_string_view = std::basic_string_view<CharT, Traits>;
305 using traits_type = typename std_string_view::traits_type;
306 using value_type = typename std_string_view::value_type;
307 using pointer = typename std_string_view::pointer;
308 using const_pointer = typename std_string_view::const_pointer;
309 using size_type = typename std_string_view::size_type;
310 using difference_type = typename std_string_view::difference_type;
311
314
315 constexpr basic_string_view_for_slice(const basic_string_view_for_slice& other) noexcept = default;
316
319
322
324
326 : data_{s.data(), s.size()} {}
327
329 data_ = {s.data(), s.size()};
330 return *this;
331 }
332
333 constexpr operator std_string_view() const noexcept { return {data(), size()}; }
334 constexpr std_string_view as_sv() const noexcept { return *this; }
335
336 constexpr const_pointer data() const noexcept { return data_.data; }
337 constexpr size_type size() const noexcept { return data_.len; }
338
339private:
340 using capi_type =
341 std::conditional_t<std::is_same_v<value_type, char>,
342 capi::DiplomatStringView,
343 std::conditional_t<std::is_same_v<value_type, char16_t>,
344 capi::DiplomatString16View,
345 void>>;
346
347 static_assert(!std::is_void_v<capi_type>,
348 "ABI compatible string_views are only supported for char and char16_t");
349
350 capi_type data_;
351};
352
353// We only implement these specialisations as diplomat doesn't provide c abi
354// types for others
357
360
361// Interop between std::function & our C Callback wrapper type
362
363template <typename T, typename = void>
364struct as_ffi {
365 using type = T;
366};
367
368template <typename T>
369struct as_ffi<T, std::void_t<decltype(std::declval<std::remove_pointer_t<T>>().AsFFI())>> {
370 using type = decltype(std::declval<std::remove_pointer_t<T>>().AsFFI());
371};
372
373template <typename T>
374struct as_ffi<std::unique_ptr<T>> {
375 using type = decltype(std::declval<T>().AsFFI());
376};
377
378template<typename T>
379using as_ffi_t = typename as_ffi<T>::type;
380
381template<typename T>
382using replace_string_view_t = std::conditional_t<std::is_same_v<T, std::string_view>, capi::DiplomatStringView, T>;
383
384template<typename T, typename = void>
386 using type = T;
387};
388
389#define MAKE_SLICE_CONVERTERS(name, c_ty) \
390 template<typename T> \
391 struct diplomat_c_span_convert<T, std::enable_if_t<std::is_same_v<T, span<const c_ty>>>> { \
392 using type = diplomat::capi::Diplomat##name##View; \
393 }; \
394 template<typename T> \
395 struct diplomat_c_span_convert<T, std::enable_if_t<std::is_same_v<T, span<c_ty>>>> { \
396 using type = diplomat::capi::Diplomat##name##ViewMut; \
397 }; \
398
399#if !defined(__sun) || !defined(_CHAR_IS_SIGNED)
400// int8_t and char are the same type on Solaris. Guard this definition to avoid
401// conflicts.
402MAKE_SLICE_CONVERTERS(I8, int8_t)
403#endif
404MAKE_SLICE_CONVERTERS(U8, uint8_t)
405MAKE_SLICE_CONVERTERS(I16, int16_t)
406MAKE_SLICE_CONVERTERS(U16, uint16_t)
407MAKE_SLICE_CONVERTERS(I32, int32_t)
408MAKE_SLICE_CONVERTERS(U32, uint32_t)
409MAKE_SLICE_CONVERTERS(I64, int64_t)
410MAKE_SLICE_CONVERTERS(U64, uint64_t)
411MAKE_SLICE_CONVERTERS(F32, float)
412MAKE_SLICE_CONVERTERS(F64, double)
413MAKE_SLICE_CONVERTERS(Bool, bool)
414MAKE_SLICE_CONVERTERS(Char, char32_t)
415MAKE_SLICE_CONVERTERS(String, char)
416MAKE_SLICE_CONVERTERS(String16, char16_t)
417
418template<typename T>
420
421template<typename T>
423 static constexpr bool value = false;
424 using type = T;
425};
426
427template<typename T>
428struct is_unique_ptr<std::unique_ptr<T>> {
429 static constexpr bool value = true;
430 using type = T;
431};
432
433template<typename T>
435
436template<typename T>
438 static constexpr bool value = false;
439};
440
441template<typename T>
442struct is_optional<std::optional<T>> {
443 static constexpr bool value = true;
444};
445
446template<typename T>
448
450template<typename T>
452
453namespace fn_trait_helpers {
454 // For a given T, creates a function that take in the C ABI version & return the C++ type.
455 template<typename T>
457 if constexpr(std::is_same_v<T, std::string_view>) {
458 return std::string_view{val.data, val.len};
459 } else if constexpr (!std::is_same_v<T, diplomat_c_span_convert_t<T>>) {
460 return T{ val.data, val.len };
461 } else if constexpr (!std::is_same_v<T, as_ffi_t<T>>) {
462 if constexpr (std::is_lvalue_reference_v<T>) {
463 return *std::remove_reference_t<T>::FromFFI(val);
464 } else if constexpr (is_unique_ptr_v<T>) {
465 return T(is_unique_ptr<T>::type::FromFFI(val));
466 }
467 else {
468 return T::FromFFI(val);
469 }
470 }
471 else {
472 return val;
473 }
474 }
475
476 template<typename T>
478 if constexpr(std::is_same_v<T, std::string_view>) {
479 return {val.data(), val.size()};
480 } else if constexpr (!std::is_same_v<T, diplomat_c_span_convert_t<T>>) {
481 // Can we convert straight away to our slice type, or (in the case of ABI compatible structs), do we have to do a reinterpret cast?
482 if constexpr(std::is_same_v<decltype(std::declval<T>().data()), decltype(replace_fn_t<T>::data)>) {
483 return replace_fn_t<T> { val.data(), val.size() };
484 } else {
485 return replace_fn_t<T> { reinterpret_cast<decltype(replace_fn_t<T>::data)>(val.data()), val.size() };
486 }
487 } else if constexpr(!std::is_same_v<T, as_ffi_t<T>>) {
488 return val.AsFFI();
489 } else {
490 return val;
491 }
492 }
493
494 template<typename TOut, typename T>
496 constexpr bool has_ok = !std::is_same_v<T, std::monostate>;
497
498 bool is_ok = optional.has_value();
499
500 TOut out;
501 out.is_ok = is_ok;
502
503 if constexpr(has_ok) {
504 if (is_ok) {
505 out.ok = replace_ret<T>(optional.value());
506 }
507 }
508 return out;
509 }
510
511 template<typename T, typename E, typename TOut>
512 TOut replace_result(diplomat::result<T, E> res) {
513 auto is_ok = res.is_ok();
514
515 constexpr bool has_ok = !std::is_same_v<T, std::monostate>;
516 constexpr bool has_err = !std::is_same_v<E, std::monostate>;
517
518 TOut out;
519 out.is_ok = is_ok;
520
521 if constexpr (has_ok) {
522 if (is_ok) {
523 auto val = std::move(res).ok().value();
524 if constexpr (is_optional_v<T>) {
525 out.ok = replace_optional_ret<decltype(out.ok)>(val);
526 } else {
527 out.ok = replace_ret<T>(val);
528 }
529 }
530 }
531
532 if constexpr(has_err) {
533 if (!is_ok) {
534 auto val = std::move(res).err().value();
535 if constexpr(is_optional_v<E>) {
536 out.err = replace_optional_ret<decltype(out.err)>(val);
537 } else {
538 out.err = replace_ret<E>(val);
539 }
540 }
541 }
542
543 return out;
544 }
545} // namespace fn_traits
546
547template <typename T> struct fn_traits;
548
549template <typename Ret, typename... Args> struct fn_traits<std::function<Ret(Args...)>> {
550 using fn_ptr_t = Ret(Args...);
551 using function_t = std::function<fn_ptr_t>;
552 using ret = Ret;
553
554 static Ret c_run_callback(const void *cb, replace_fn_t<Args>... args) {
555 return (*reinterpret_cast<const function_t *>(cb))(fn_trait_helpers::replace<Args>(args)...);
556 }
557
558 template<typename T, typename E, typename TOut>
559 static TOut c_run_callback_result(const void *cb, replace_fn_t<Args>... args) {
560 result<T, E> res = c_run_callback(cb, args...);
561
562 return fn_trait_helpers::replace_result<T, E, TOut>(res);
563 }
564
565 // For DiplomatOption<>
566 template<typename T, typename TOut>
567 static TOut c_run_callback_diplomat_option(const void *cb, replace_fn_t<Args>... args) {
568 std::optional<T> ret = c_run_callback(cb, args...);
569
570 return fn_trait_helpers::replace_optional_ret<TOut>(ret);
571 }
572
573 // All we need to do is just convert one pointer to another, while keeping the arguments the same:
574 template<typename T>
576 Ret out = c_run_callback(cb, args...);
577
578 if constexpr(std::is_pointer_v<Ret>) {
579 return out->AsFFI();
580 } else {
581 return out.AsFFI();
582 }
583 }
584
585 static void c_delete(const void *cb) {
586 delete reinterpret_cast<const function_t *>(cb);
587 }
588
589 fn_traits(function_t) {} // Allows less clunky construction (avoids decltype)
590};
591
592// additional deduction guide required
593template<class T>
595
596// Trait for extracting inner types from either T*, std::optional, or std::unique_ptr.
597// These are the three potential types returned by next() functions
598template<typename T> struct inner { /* only T*, std::optional, and std::unique_ptr are supported */ };
599template<typename T> struct inner<T*> { using type = T; };
600template<typename T> struct inner<std::unique_ptr<T>> { using type = T; };
601template<typename T> struct inner<std::optional<T>>{ using type = T; };
602
604inline const U get_inner_if_present(T v) {
605 if constexpr(std::is_same_v<T,U>) {
606 return std::move(v);
607 } else {
608 return *std::move(v);
609 }
610}
611
612// Adapter for iterator types
613template<typename T, typename U = void> struct has_next : std::false_type {};
614template<typename T> struct has_next < T, std::void_t<decltype(std::declval<T>().next())>> : std::true_type {};
615template<typename T> constexpr bool has_next_v = has_next<T>::value;
616
618template<typename T>
620 static_assert(has_next_v<T>, "next_to_iter_helper may only be used with types implementing next()");
621 using next_type = decltype(std::declval<T>().next());
622
623 // STL Iterator trait definitions
626 using reference = std::add_lvalue_reference_t<value_type>;
627 using iterator_category = std::input_iterator_tag;
628
629 next_to_iter_helper(std::unique_ptr<T>&& ptr) : _ptr(std::move(ptr)), _curr(_ptr->next()) {}
630
631 // https://en.cppreference.com/w/cpp/named_req/InputIterator requires that the type be copyable
632 next_to_iter_helper(const next_to_iter_helper& o) : _ptr(o._ptr), _curr(o._curr) {}
633
634 void operator++() { _curr = _ptr->next(); }
635 void operator++(int) { ++(*this); }
636 const value_type& operator*() const { return *_curr; }
637
638 bool operator!=(std::nullopt_t) {
639 return (bool)_curr;
640 }
641
642 std::shared_ptr<T> _ptr; // shared to satisfy the copyable requirement
644};
645
646} // namespace diplomat
647} // namespace icu4x
648#endif
Definition diplomat_runtime.hpp:253
Definition diplomat_runtime.hpp:302
typename std_string_view::const_pointer const_pointer
Definition diplomat_runtime.hpp:308
constexpr basic_string_view_for_slice(const const_pointer s)
Definition diplomat_runtime.hpp:320
constexpr basic_string_view_for_slice(const basic_string_view_for_slice &other) noexcept=default
constexpr basic_string_view_for_slice & operator=(const basic_string_view_for_slice &view) noexcept=default
constexpr size_type size() const noexcept
Definition diplomat_runtime.hpp:337
std::basic_string_view< CharT, Traits > std_string_view
Definition diplomat_runtime.hpp:304
typename std_string_view::size_type size_type
Definition diplomat_runtime.hpp:309
typename std_string_view::traits_type traits_type
Definition diplomat_runtime.hpp:305
constexpr basic_string_view_for_slice & operator=(const std_string_view &s) noexcept
Definition diplomat_runtime.hpp:328
typename std_string_view::difference_type difference_type
Definition diplomat_runtime.hpp:310
constexpr basic_string_view_for_slice(const std_string_view &s) noexcept
Definition diplomat_runtime.hpp:325
constexpr const_pointer data() const noexcept
Definition diplomat_runtime.hpp:336
constexpr basic_string_view_for_slice() noexcept
Definition diplomat_runtime.hpp:312
constexpr basic_string_view_for_slice(const const_pointer s, const size_type count)
Definition diplomat_runtime.hpp:317
typename std_string_view::pointer pointer
Definition diplomat_runtime.hpp:307
typename std_string_view::value_type value_type
Definition diplomat_runtime.hpp:306
constexpr std_string_view as_sv() const noexcept
Definition diplomat_runtime.hpp:334
Definition diplomat_runtime.hpp:182
std::optional< E > err() &&
Definition diplomat_runtime.hpp:211
void set_ok(T &&t)
Definition diplomat_runtime.hpp:235
std::optional< std::reference_wrapper< std::remove_reference_t< E > > > err() &&
Definition diplomat_runtime.hpp:228
bool is_err() const
Definition diplomat_runtime.hpp:198
result & operator=(result &&) noexcept=default
void set_err(E &&e)
Definition diplomat_runtime.hpp:239
result(Ok< T > &&v)
Definition diplomat_runtime.hpp:187
std::optional< std::reference_wrapper< std::remove_reference_t< T > > > ok() &&
Definition diplomat_runtime.hpp:220
result(const result &)=default
result(Err< E > &&v)
Definition diplomat_runtime.hpp:188
std::optional< T > ok() &&
Definition diplomat_runtime.hpp:203
result< T2, E > replace_ok(T2 &&t)
Definition diplomat_runtime.hpp:244
result & operator=(const result &)=default
std::variant< Ok< T >, Err< E > > val
Definition diplomat_runtime.hpp:184
Definition diplomat_runtime.hpp:266
constexpr T * end() const noexcept
Definition diplomat_runtime.hpp:285
constexpr T * data() const noexcept
Definition diplomat_runtime.hpp:277
void operator=(span< T > o)
Definition diplomat_runtime.hpp:287
constexpr span(T *data=nullptr, size_t size=Extent)
Definition diplomat_runtime.hpp:268
constexpr span(std::array< typename std::remove_const_t< T >, N > &arr)
Definition diplomat_runtime.hpp:274
constexpr size_t size() const noexcept
Definition diplomat_runtime.hpp:280
constexpr T * begin() const noexcept
Definition diplomat_runtime.hpp:284
constexpr span(const span< T > &o)
Definition diplomat_runtime.hpp:271
#define MAKE_SLICES_AND_OPTIONS(name, c_ty)
Definition diplomat_runtime.hpp:71
#define MAKE_SLICE_CONVERTERS(name, c_ty)
Definition diplomat_runtime.hpp:389
TOut replace_optional_ret(std::optional< T > optional)
Definition diplomat_runtime.hpp:495
replace_fn_t< T > replace_ret(T val)
Definition diplomat_runtime.hpp:477
T replace(replace_fn_t< T > val)
Definition diplomat_runtime.hpp:456
typename as_ffi< T >::type as_ffi_t
Definition diplomat_runtime.hpp:379
constexpr bool is_optional_v
Definition diplomat_runtime.hpp:447
bool _grow_impl(capi::DiplomatWrite *w, uintptr_t requested)
Definition diplomat_runtime.hpp:105
const U get_inner_if_present(T v)
Definition diplomat_runtime.hpp:604
constexpr bool is_unique_ptr_v
Definition diplomat_runtime.hpp:434
constexpr size_t dynamic_extent
Definition diplomat_runtime.hpp:264
std::conditional_t< std::is_same_v< T, std::string_view >, capi::DiplomatStringView, T > replace_string_view_t
Definition diplomat_runtime.hpp:382
diplomat_c_span_convert_t< replace_string_view_t< as_ffi_t< T > > > replace_fn_t
Replace the argument types from the std::function with the argument types for th function pointer.
Definition diplomat_runtime.hpp:451
constexpr bool has_next_v
Definition diplomat_runtime.hpp:615
typename diplomat_c_span_convert< T >::type diplomat_c_span_convert_t
Definition diplomat_runtime.hpp:419
Definition Bidi.d.hpp:13
Definition diplomat_runtime.hpp:164
Err(const T &i)
Definition diplomat_runtime.hpp:172
Err(T &&i)
Definition diplomat_runtime.hpp:168
T inner
Definition diplomat_runtime.hpp:165
Err(Err &&) noexcept=default
Definition diplomat_runtime.hpp:146
Ok(const T &i)
Definition diplomat_runtime.hpp:154
Ok(T &&i)
Definition diplomat_runtime.hpp:150
T inner
Definition diplomat_runtime.hpp:147
Ok(Ok &&) noexcept=default
static capi::DiplomatWrite Construct(std::string &t)
Definition diplomat_runtime.hpp:141
Definition diplomat_runtime.hpp:135
decltype(std::declval< T >().AsFFI()) type
Definition diplomat_runtime.hpp:375
Definition diplomat_runtime.hpp:364
T type
Definition diplomat_runtime.hpp:365
Definition diplomat_runtime.hpp:385
T type
Definition diplomat_runtime.hpp:386
std::function< fn_ptr_t > function_t
Definition diplomat_runtime.hpp:551
static T c_run_callback_diplomat_opaque(const void *cb, replace_fn_t< Args >... args)
Definition diplomat_runtime.hpp:575
static Ret c_run_callback(const void *cb, replace_fn_t< Args >... args)
Definition diplomat_runtime.hpp:554
fn_traits(function_t)
Definition diplomat_runtime.hpp:589
static void c_delete(const void *cb)
Definition diplomat_runtime.hpp:585
Definition diplomat_runtime.hpp:547
Definition diplomat_runtime.hpp:613
T type
Definition diplomat_runtime.hpp:599
T type
Definition diplomat_runtime.hpp:601
T type
Definition diplomat_runtime.hpp:600
Definition diplomat_runtime.hpp:598
Definition diplomat_runtime.hpp:437
T type
Definition diplomat_runtime.hpp:430
Definition diplomat_runtime.hpp:422
T type
Definition diplomat_runtime.hpp:424
Helper template enabling native iteration over unique ptrs to objects which implement next()
Definition diplomat_runtime.hpp:619
void operator++()
Definition diplomat_runtime.hpp:634
void operator++(int)
Definition diplomat_runtime.hpp:635
next_to_iter_helper(const next_to_iter_helper &o)
Definition diplomat_runtime.hpp:632
next_type _curr
Definition diplomat_runtime.hpp:643
bool operator!=(std::nullopt_t)
Definition diplomat_runtime.hpp:638
std::input_iterator_tag iterator_category
Definition diplomat_runtime.hpp:627
next_to_iter_helper(std::unique_ptr< T > &&ptr)
Definition diplomat_runtime.hpp:629
std::shared_ptr< T > _ptr
Definition diplomat_runtime.hpp:642
const value_type & operator*() const
Definition diplomat_runtime.hpp:636
std::add_lvalue_reference_t< value_type > reference
Definition diplomat_runtime.hpp:626
typename inner< next_type >::type value_type
Definition diplomat_runtime.hpp:624
decltype(std::declval< T >().next()) next_type
Definition diplomat_runtime.hpp:621