20
20
#define RUST_FMT_H
21
21
22
22
#include " rust-system.h"
23
-
24
- // FIXME: How to encode Option?
23
+ #include " optional.h"
25
24
26
25
namespace Rust {
27
26
namespace Fmt {
28
27
29
28
namespace ffi {
30
29
30
+ extern " C" {
31
+
32
+ unsigned char *rust_ffi_alloc (size_t count, size_t elem_size, size_t align);
33
+
34
+ void rust_ffi_dealloc (unsigned char *data, size_t count, size_t elem_size,
35
+ size_t align);
36
+
37
+ } // extern "C"
38
+
39
+ template <typename T> class FFIVec
40
+ {
41
+ T *data;
42
+ size_t len;
43
+ size_t cap;
44
+
45
+ public:
46
+ FFIVec () : data ((T *) alignof (T)), len (0 ), cap (0 ) {}
47
+
48
+ FFIVec (const FFIVec &) = delete ;
49
+ FFIVec &operator = (const FFIVec &) = delete ;
50
+
51
+ FFIVec (FFIVec &&other) : data (other.data), len (other.len), cap (other.cap)
52
+ {
53
+ other.data = (T *) alignof (T);
54
+ other.len = 0 ;
55
+ other.cap = 0 ;
56
+ }
57
+
58
+ FFIVec &operator = (FFIVec &&other)
59
+ {
60
+ this ->~FFIVec ();
61
+ new (this ) FFIVec (std::move (other));
62
+ return *this ;
63
+ }
64
+
65
+ ~FFIVec ()
66
+ {
67
+ // T can't be zero-sized
68
+ if (cap)
69
+ rust_ffi_dealloc ((unsigned char *) data, cap, sizeof (T), alignof (T));
70
+ }
71
+
72
+ size_t size () const { return len; }
73
+
74
+ const T &operator [] (size_t idx) const
75
+ {
76
+ rust_assert (idx <= len);
77
+ return data[idx];
78
+ }
79
+
80
+ T *begin () { return data; }
81
+ const T *begin () const { return data; }
82
+ T *end () { return data + len; }
83
+ const T *end () const { return data + len; }
84
+ };
85
+
86
+ template <typename T> class FFIOpt
87
+ {
88
+ struct alignas (T) Inner
89
+ {
90
+ char data[sizeof (T)];
91
+ } inner;
92
+ bool is_some;
93
+
94
+ public:
95
+ template <typename U> FFIOpt (U &&val) : is_some (true )
96
+ {
97
+ new (inner.data ) T (std::forward<U> (val));
98
+ }
99
+
100
+ FFIOpt () : is_some (false ) {}
101
+
102
+ FFIOpt (const FFIOpt &other) : is_some (other.is_some)
103
+ {
104
+ if (is_some)
105
+ new (inner.data ) T (*(const T *) other.inner .data );
106
+ }
107
+
108
+ FFIOpt (FFIOpt &&other) : is_some (other.is_some)
109
+ {
110
+ if (is_some)
111
+ new (inner.data ) T (std::move (*(const T *) other.inner .data ));
112
+ }
113
+
114
+ ~FFIOpt ()
115
+ {
116
+ if (is_some)
117
+ ((T *) inner.data )->~T ();
118
+ }
119
+
120
+ FFIOpt &operator = (const FFIOpt &other)
121
+ {
122
+ this ->~FFIOpt ();
123
+ new (this ) FFIOpt (other);
124
+ return *this ;
125
+ }
126
+
127
+ FFIOpt &operator = (FFIOpt &&other)
128
+ {
129
+ this ->~FFIOpt ();
130
+ new (this ) FFIOpt (std::move (other));
131
+ return *this ;
132
+ }
133
+
134
+ tl::optional<std::reference_wrapper<T>> get_opt ()
135
+ {
136
+ return (T *) inner.data ;
137
+ }
138
+
139
+ tl::optional<std::reference_wrapper<const T>> get_opt () const
140
+ {
141
+ return (const T *) inner.data ;
142
+ }
143
+ };
144
+
31
145
struct RustHamster
32
146
{
33
147
const char *ptr;
34
148
size_t len;
35
149
36
150
std::string to_string () const ;
151
+
152
+ explicit RustHamster (const std::string &str)
153
+ : ptr (str.data ()), len (str.size ())
154
+ {}
37
155
};
38
156
39
157
// / Enum of alignments which are supported.
@@ -166,33 +284,33 @@ struct Count
166
284
struct FormatSpec
167
285
{
168
286
// / Optionally specified character to fill alignment with.
169
- const uint32_t * fill;
287
+ FFIOpt< uint32_t > fill;
170
288
// / Span of the optionally specified fill character.
171
- const InnerSpan * fill_span;
289
+ FFIOpt< InnerSpan> fill_span;
172
290
// / Optionally specified alignment.
173
291
Alignment align;
174
292
// / The `+` or `-` flag.
175
- const Sign * sign;
293
+ FFIOpt< Sign> sign;
176
294
// / The `#` flag.
177
295
bool alternate;
178
296
// / The `0` flag.
179
297
bool zero_pad;
180
298
// / The `x` or `X` flag. (Only for `Debug`.)
181
- const DebugHex * debug_hex;
299
+ FFIOpt< DebugHex> debug_hex;
182
300
// / The integer precision to use.
183
301
Count precision;
184
302
// / The span of the precision formatting flag (for diagnostics).
185
- const InnerSpan * precision_span;
303
+ FFIOpt< InnerSpan> precision_span;
186
304
// / The string width requested for the resulting format.
187
305
Count width;
188
306
// / The span of the width formatting flag (for diagnostics).
189
- const InnerSpan * width_span;
307
+ FFIOpt< InnerSpan> width_span;
190
308
// / The descriptor string representing the name of the format desired for
191
309
// / this argument, this can be empty or any number of characters, although
192
310
// / it is required to be one word.
193
311
RustHamster ty;
194
312
// / The span of the descriptor string (for diagnostics).
195
- const InnerSpan * ty_span;
313
+ FFIOpt< InnerSpan> ty_span;
196
314
};
197
315
198
316
// / Representation of an argument specification.
@@ -238,26 +356,6 @@ struct Piece
238
356
};
239
357
};
240
358
241
- struct PieceSlice
242
- {
243
- const Piece *base_ptr;
244
- size_t len;
245
- size_t cap;
246
- };
247
-
248
- struct RustString
249
- {
250
- const unsigned char *ptr;
251
- size_t len;
252
- size_t cap;
253
- };
254
-
255
- struct FormatArgsHandle
256
- {
257
- PieceSlice piece_slice;
258
- RustString rust_string;
259
- };
260
-
261
359
enum ParseMode
262
360
{
263
361
Format = 0 ,
@@ -266,12 +364,10 @@ enum ParseMode
266
364
267
365
extern " C" {
268
366
269
- FormatArgsHandle collect_pieces (const char * input, bool append_newline,
270
- ParseMode parse_mode);
367
+ FFIVec<Piece> collect_pieces (RustHamster input, bool append_newline,
368
+ ParseMode parse_mode);
271
369
272
- FormatArgsHandle clone_pieces (const FormatArgsHandle &);
273
-
274
- void destroy_pieces (FormatArgsHandle);
370
+ FFIVec<Piece> clone_pieces (const FFIVec<Piece> &);
275
371
276
372
} // extern "C"
277
373
@@ -281,33 +377,20 @@ struct Pieces
281
377
{
282
378
static Pieces collect (const std::string &to_parse, bool append_newline,
283
379
ffi::ParseMode parse_mode);
284
- ~Pieces ();
285
-
286
- Pieces (const Pieces &other);
287
- Pieces &operator = (const Pieces &other);
288
380
289
- Pieces (Pieces &&other);
290
-
291
- const std::vector<ffi::Piece> &get_pieces () const { return pieces_vector; }
292
-
293
- // {
294
- // slice = clone_pieces (&other.slice);
295
- // to_parse = other.to_parse;
296
-
297
- // return *this;
298
- // }
381
+ const ffi::FFIVec<ffi::Piece> &get_pieces () const { return data->second ; }
299
382
300
383
private:
301
- Pieces (ffi::FormatArgsHandle handle, std::vector<ffi::Piece> &&pieces_vector)
302
- : pieces_vector (std::move (pieces_vector)), handle (handle)
384
+ Pieces (std::string str, ffi::FFIVec<ffi::Piece> pieces)
385
+ : data (
386
+ std::make_shared<decltype (data)::element_type> (std::move (str),
387
+ std::move (pieces)))
303
388
{}
304
389
305
- std::vector<ffi::Piece> pieces_vector;
306
-
307
- // this memory is held for FFI reasons - it needs to be released and cloned
308
- // precisely, so try to not access it/modify it if possible. you should
309
- // instead work with `pieces_vector`
310
- ffi::FormatArgsHandle handle;
390
+ // makes copying simpler
391
+ // also, we'd need to keep the parsed string in a shared_ptr anyways
392
+ // since we store pointers into the parsed string
393
+ std::shared_ptr<std::pair<std::string, ffi::FFIVec<ffi::Piece>>> data;
311
394
};
312
395
313
396
} // namespace Fmt
0 commit comments