ICU4X
International Components for Unicode
Loading...
Searching...
No Matches
diplomat_runtime.hpp
Go to the documentation of this file.
1#ifndef DIPLOMAT_RUNTIME_CPP_H
2#define DIPLOMAT_RUNTIME_CPP_H
3
4#include <optional>
5#include <string>
6#include <type_traits>
7#include <variant>
8
9#if __cplusplus >= 202002L
10#include <span>
11#else
12#include <array>
13#endif
14
15namespace diplomat {
16
17namespace capi {
18extern "C" {
19
20static_assert(sizeof(char) == sizeof(uint8_t), "your architecture's `char` is not 8 bits");
21static_assert(sizeof(char16_t) == sizeof(uint16_t), "your architecture's `char16_t` is not 16 bits");
22static_assert(sizeof(char32_t) == sizeof(uint32_t), "your architecture's `char32_t` is not 32 bits");
23
24typedef struct DiplomatWrite {
25 void* context;
26 char* buf;
27 size_t len;
28 size_t cap;
29 bool grow_failed;
30 void (*flush)(struct DiplomatWrite*);
31 bool (*grow)(struct DiplomatWrite*, size_t);
32} DiplomatWrite;
33
34bool diplomat_is_str(const char* buf, size_t len);
35
36#define MAKE_SLICES(name, c_ty) \
37 typedef struct Diplomat##name##View { \
38 const c_ty* data; \
39 size_t len; \
40 } Diplomat##name##View; \
41 typedef struct Diplomat##name##ViewMut { \
42 c_ty* data; \
43 size_t len; \
44 } Diplomat##name##ViewMut; \
45 typedef struct Diplomat##name##Array { \
46 const c_ty* data; \
47 size_t len; \
48 } Diplomat##name##Array;
49
50#define MAKE_SLICES_AND_OPTIONS(name, c_ty) \
51 MAKE_SLICES(name, c_ty) \
52 typedef struct Option##name {union { c_ty ok; }; bool is_ok; } Option##name;
53
55MAKE_SLICES_AND_OPTIONS(U8, uint8_t)
56MAKE_SLICES_AND_OPTIONS(I16, int16_t)
57MAKE_SLICES_AND_OPTIONS(U16, uint16_t)
58MAKE_SLICES_AND_OPTIONS(I32, int32_t)
59MAKE_SLICES_AND_OPTIONS(U32, uint32_t)
60MAKE_SLICES_AND_OPTIONS(I64, int64_t)
61MAKE_SLICES_AND_OPTIONS(U64, uint64_t)
62MAKE_SLICES_AND_OPTIONS(Isize, intptr_t)
63MAKE_SLICES_AND_OPTIONS(Usize, size_t)
65MAKE_SLICES_AND_OPTIONS(F64, double)
67MAKE_SLICES_AND_OPTIONS(Char, char32_t)
68MAKE_SLICES(String, char)
69MAKE_SLICES(String16, char16_t)
70MAKE_SLICES(Strings, DiplomatStringView)
71MAKE_SLICES(Strings16, DiplomatString16View)
72
73} // extern "C"
74} // namespace capi
75
76extern "C" inline void _flush(capi::DiplomatWrite* w) {
77 std::string* string = reinterpret_cast<std::string*>(w->context);
78 string->resize(w->len);
79};
80
81extern "C" inline bool _grow(capi::DiplomatWrite* w, uintptr_t requested) {
82 std::string* string = reinterpret_cast<std::string*>(w->context);
83 string->resize(requested);
84 w->cap = string->length();
85 w->buf = &(*string)[0];
86 return true;
87};
88
89inline capi::DiplomatWrite WriteFromString(std::string& string) {
90 capi::DiplomatWrite w;
91 w.context = &string;
92 w.buf = &string[0];
93 w.len = string.length();
94 w.cap = string.length();
95 // Will never become true, as _grow is infallible.
96 w.grow_failed = false;
97 w.flush = _flush;
98 w.grow = _grow;
99 return w;
100};
101
102template<class T> struct Ok {
104 Ok(T&& i): inner(std::move(i)) {}
105 // We don't want to expose an lvalue-capable constructor in general
106 // however there is no problem doing this for trivially copyable types
107 template<typename X = T, typename = typename std::enable_if<std::is_trivially_copyable<X>::value>::type>
108 Ok(T i): inner(i) {}
109 Ok() = default;
110 Ok(Ok&&) noexcept = default;
111 Ok(const Ok &) = default;
112 Ok& operator=(const Ok&) = default;
113 Ok& operator=(Ok&&) noexcept = default;
114};
115
116template<class T> struct Err {
118 Err(T&& i): inner(std::move(i)) {}
119 // We don't want to expose an lvalue-capable constructor in general
120 // however there is no problem doing this for trivially copyable types
121 template<typename X = T, typename = typename std::enable_if<std::is_trivially_copyable<X>::value>::type>
122 Err(T i): inner(i) {}
123 Err() = default;
124 Err(Err&&) noexcept = default;
125 Err(const Err &) = default;
126 Err& operator=(const Err&) = default;
127 Err& operator=(Err&&) noexcept = default;
128};
129
130template<class T, class E>
131class result {
132private:
133 std::variant<Ok<T>, Err<E>> val;
134public:
135 result(Ok<T>&& v): val(std::move(v)) {}
136 result(Err<E>&& v): val(std::move(v)) {}
137 result() = default;
138 result(const result &) = default;
139 result& operator=(const result&) = default;
140 result& operator=(result&&) noexcept = default;
141 result(result &&) noexcept = default;
142 ~result() = default;
143 bool is_ok() const {
144 return std::holds_alternative<Ok<T>>(this->val);
145 };
146 bool is_err() const {
147 return std::holds_alternative<Err<E>>(this->val);
148 };
149
150 std::optional<T> ok() && {
151 if (!this->is_ok()) {
152 return std::nullopt;
153 }
154 return std::make_optional(std::move(std::get<Ok<T>>(std::move(this->val)).inner));
155 };
156 std::optional<E> err() && {
157 if (!this->is_err()) {
158 return std::nullopt;
159 }
160 return std::make_optional(std::move(std::get<Err<E>>(std::move(this->val)).inner));
161 }
162
163 void set_ok(T&& t) {
164 this->val = Ok<T>(std::move(t));
165 }
166
167 void set_err(E&& e) {
168 this->val = Err<E>(std::move(e));
169 }
170
171 template<typename T2>
173 if (this->is_err()) {
174 return result<T2, E>(Err<E>(std::get<Err<E>>(std::move(this->val))));
175 } else {
176 return result<T2, E>(Ok<T2>(std::move(t)));
177 }
178 }
179};
180
181class Utf8Error {};
182
183// Use custom std::span on C++17, otherwise use std::span
184#if __cplusplus >= 202002L
185
186template<class T> using span = std::span<T>;
187
188#else // __cplusplus < 202002L
189
190// C++-17-compatible std::span
191template<class T>
192class span {
193
194public:
195 constexpr span(T* data, size_t size)
196 : data_(data), size_(size) {}
197 template<size_t N>
198 constexpr span(std::array<typename std::remove_const<T>::type, N>& arr)
199 : data_(const_cast<T*>(arr.data())), size_(N) {}
200 constexpr T* data() const noexcept {
201 return this->data_;
202 }
203 constexpr size_t size() const noexcept {
204 return this->size_;
205 }
206private:
207 T* data_;
208 size_t size_;
209};
210
211#endif // __cplusplus >= 202002L
212
213} // namespace diplomat
214
215#endif
Definition: diplomat_runtime.hpp:181
Definition: diplomat_runtime.hpp:131
result(Err< E > &&v)
Definition: diplomat_runtime.hpp:136
result(const result &)=default
result & operator=(const result &)=default
result & operator=(result &&) noexcept=default
bool is_err() const
Definition: diplomat_runtime.hpp:146
result(Ok< T > &&v)
Definition: diplomat_runtime.hpp:135
std::optional< T > ok() &&
Definition: diplomat_runtime.hpp:150
std::optional< E > err() &&
Definition: diplomat_runtime.hpp:156
void set_ok(T &&t)
Definition: diplomat_runtime.hpp:163
result< T2, E > replace_ok(T2 &&t)
Definition: diplomat_runtime.hpp:172
result()=default
void set_err(E &&e)
Definition: diplomat_runtime.hpp:167
Definition: diplomat_runtime.hpp:192
constexpr T * data() const noexcept
Definition: diplomat_runtime.hpp:200
constexpr size_t size() const noexcept
Definition: diplomat_runtime.hpp:203
constexpr span(std::array< typename std::remove_const< T >::type, N > &arr)
Definition: diplomat_runtime.hpp:198
constexpr span(T *data, size_t size)
Definition: diplomat_runtime.hpp:195
#define MAKE_SLICES(name, c_ty)
Definition: diplomat_runtime.hpp:36
#define MAKE_SLICES_AND_OPTIONS(name, c_ty)
Definition: diplomat_runtime.hpp:50
Definition: diplomat_runtime.hpp:15
bool _grow(capi::DiplomatWrite *w, uintptr_t requested)
Definition: diplomat_runtime.hpp:81
void _flush(capi::DiplomatWrite *w)
Definition: diplomat_runtime.hpp:76
capi::DiplomatWrite WriteFromString(std::string &string)
Definition: diplomat_runtime.hpp:89
Definition: diplomat_runtime.hpp:116
Err(T i)
Definition: diplomat_runtime.hpp:122
T inner
Definition: diplomat_runtime.hpp:117
Err(T &&i)
Definition: diplomat_runtime.hpp:118
Err(Err &&) noexcept=default
Err()=default
Definition: diplomat_runtime.hpp:102
Ok(T i)
Definition: diplomat_runtime.hpp:108
Ok(T &&i)
Definition: diplomat_runtime.hpp:104
T inner
Definition: diplomat_runtime.hpp:103
Ok()=default
Ok(Ok &&) noexcept=default