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