1use std::collections::{HashMap, HashSet};
2use std::{
3 ffi::{c_void, CString},
4 mem::ManuallyDrop,
5};
6
7use crate::{
8 dart_array::DartArray,
9 ffi::{DartHandleFinalizer, *},
10};
11
12pub trait IntoDart {
17 fn into_dart(self) -> DartCObject;
19}
20
21pub trait IntoDartExceptPrimitive: IntoDart {}
25
26impl<T> IntoDart for T
27where
28 T: Into<DartCObject>,
29{
30 fn into_dart(self) -> DartCObject {
31 self.into()
32 }
33}
34
35impl<T> IntoDartExceptPrimitive for T where T: IntoDart + Into<DartCObject> {}
36
37impl IntoDart for () {
38 fn into_dart(self) -> DartCObject {
39 DartCObject {
40 ty: DartCObjectType::DartNull,
41 value: DartCObjectValue { as_bool: false },
45 }
46 }
47}
48
49#[cfg(feature = "anyhow")]
50impl IntoDart for anyhow::Error {
51 fn into_dart(self) -> DartCObject {
52 format!("{:?}", self).into_dart()
53 }
54}
55
56impl IntoDart for std::backtrace::Backtrace {
57 fn into_dart(self) -> DartCObject {
58 format!("{:?}", self).into_dart()
59 }
60}
61
62#[cfg(feature = "backtrace")]
63impl IntoDart for backtrace::Backtrace {
64 fn into_dart(self) -> DartCObject {
65 format!("{:?}", self).into_dart()
66 }
67}
68
69impl IntoDart for i32 {
70 fn into_dart(self) -> DartCObject {
71 DartCObject {
72 ty: DartCObjectType::DartInt32,
73 value: DartCObjectValue { as_int32: self },
74 }
75 }
76}
77
78impl IntoDart for i64 {
79 fn into_dart(self) -> DartCObject {
80 DartCObject {
81 ty: DartCObjectType::DartInt64,
82 value: DartCObjectValue { as_int64: self },
83 }
84 }
85}
86
87impl IntoDart for f32 {
88 fn into_dart(self) -> DartCObject {
89 (self as f64).into_dart()
90 }
91}
92
93impl IntoDart for f64 {
94 fn into_dart(self) -> DartCObject {
95 DartCObject {
96 ty: DartCObjectType::DartDouble,
97 value: DartCObjectValue { as_double: self },
98 }
99 }
100}
101
102impl IntoDart for bool {
103 fn into_dart(self) -> DartCObject {
104 DartCObject {
105 ty: DartCObjectType::DartBool,
106 value: DartCObjectValue { as_bool: self },
107 }
108 }
109}
110
111impl IntoDartExceptPrimitive for bool {}
116
117impl IntoDart for String {
118 fn into_dart(self) -> DartCObject {
119 let s = CString::new(self).unwrap_or_default();
120 s.into_dart()
121 }
122}
123
124impl IntoDartExceptPrimitive for String {}
125
126impl IntoDart for &'_ str {
127 fn into_dart(self) -> DartCObject {
128 self.to_string().into_dart()
129 }
130}
131
132impl IntoDartExceptPrimitive for &'_ str {}
133
134impl IntoDart for CString {
135 fn into_dart(self) -> DartCObject {
136 DartCObject {
137 ty: DartCObjectType::DartString,
138 value: DartCObjectValue {
139 as_string: self.into_raw(),
140 },
141 }
142 }
143}
144
145impl IntoDartExceptPrimitive for CString {}
146
147pub(crate) trait DartTypedDataTypeVisitor {
151 fn visit<T: DartTypedDataTypeTrait>(&self);
152}
153
154pub trait DartTypedDataTypeTrait {
156 fn dart_typed_data_type() -> DartTypedDataType;
157
158 fn function_pointer_of_free_zero_copy_buffer() -> DartHandleFinalizer;
159}
160
161fn vec_to_dart_native_external_typed_data<T>(
162 vec_from_rust: Vec<T>,
163) -> DartCObject
164where
165 T: DartTypedDataTypeTrait,
166{
167 if vec_from_rust.is_empty() {
168 let data = DartNativeTypedData {
169 ty: T::dart_typed_data_type(),
170 length: 0,
171 values: std::ptr::null_mut(),
172 };
173 return DartCObject {
174 ty: DartCObjectType::DartTypedData,
175 value: DartCObjectValue {
176 as_typed_data: data,
177 },
178 };
179 }
180
181 let mut vec = vec_from_rust;
182 vec.shrink_to_fit();
183 let length = vec.len();
184 assert_eq!(length, vec.capacity());
185 let ptr = vec.as_mut_ptr();
186
187 DartCObject {
188 ty: DartCObjectType::DartExternalTypedData,
189 value: DartCObjectValue {
190 as_external_typed_data: DartNativeExternalTypedData {
191 ty: T::dart_typed_data_type(),
192 length: length as isize,
193 data: ptr as *mut u8,
194 peer: Box::into_raw(Box::new(vec)).cast(),
195 callback: T::function_pointer_of_free_zero_copy_buffer(),
196 },
197 },
198 }
199}
200
201macro_rules! dart_typed_data_type_trait_impl {
202 ($($dart_type:path => $rust_type:ident + $free_zero_copy_buffer_func:ident),+) => {
203 $(
204 impl DartTypedDataTypeTrait for $rust_type {
205 fn dart_typed_data_type() -> DartTypedDataType {
206 $dart_type
207 }
208
209 fn function_pointer_of_free_zero_copy_buffer() -> DartHandleFinalizer {
210 $free_zero_copy_buffer_func
211 }
212 }
213
214 impl<const N: usize> IntoDart for [$rust_type;N] {
215 fn into_dart(self) -> DartCObject {
216 let vec: Vec<_> = self.into();
217 vec.into_dart()
218 }
219 }
220
221 #[cfg(not(feature="zero-copy"))]
222 impl IntoDart for Vec<$rust_type> {
223 fn into_dart(self) -> DartCObject {
224 let mut vec = ManuallyDrop::new(self);
225 let data = DartNativeTypedData {
226 ty: $rust_type::dart_typed_data_type(),
227 length: vec.len() as isize,
228 values: vec.as_mut_ptr() as *mut _,
229 };
230 DartCObject {
231 ty: DartCObjectType::DartTypedData,
232 value: DartCObjectValue {
233 as_typed_data: data,
234 },
235 }
236 }
237 }
238 #[cfg(feature="zero-copy")]
239 impl IntoDart for Vec<$rust_type> {
240 fn into_dart(self) -> DartCObject {
241 vec_to_dart_native_external_typed_data(self)
242 }
243 }
244
245 impl IntoDartExceptPrimitive for Vec<$rust_type> {}
246
247 impl IntoDart for HashSet<$rust_type> {
248 fn into_dart(self) -> DartCObject {
249 self.into_iter().collect::<Vec<_>>().into_dart()
250 }
251 }
252
253 #[doc(hidden)]
254 #[no_mangle]
255 pub(crate) unsafe extern "C" fn $free_zero_copy_buffer_func(
256 _isolate_callback_data: *mut c_void,
257 peer: *mut c_void,
258 ) {
259 drop(Box::from_raw(peer.cast::<Vec<$rust_type>>()));
260 }
261 )+
262
263 pub(crate) fn visit_dart_typed_data_type<V: DartTypedDataTypeVisitor>(ty: DartTypedDataType, visitor: &V) {
264 match ty {
265 $(
266 $dart_type => visitor.visit::<$rust_type>(),
267 )+
268 _ => panic!("visit_dart_typed_data_type see unexpected DartTypedDataType={:?}", ty)
269 }
270 }
271 }
272}
273
274dart_typed_data_type_trait_impl!(
275 DartTypedDataType::Int8 => i8 + free_zero_copy_buffer_i8,
276 DartTypedDataType::Uint8 => u8 + free_zero_copy_buffer_u8,
277 DartTypedDataType::Int16 => i16 + free_zero_copy_buffer_i16,
278 DartTypedDataType::Uint16 => u16 + free_zero_copy_buffer_u16,
279 DartTypedDataType::Int32 => i32 + free_zero_copy_buffer_i32,
280 DartTypedDataType::Uint32 => u32 + free_zero_copy_buffer_u32,
281 DartTypedDataType::Int64 => i64 + free_zero_copy_buffer_i64,
282 DartTypedDataType::Uint64 => u64 + free_zero_copy_buffer_u64,
283 DartTypedDataType::Float32 => f32 + free_zero_copy_buffer_f32,
284 DartTypedDataType::Float64 => f64 + free_zero_copy_buffer_f64
285);
286
287macro_rules! isize_usize {
288 ($rust_type:ident, $delegate_target_type:ident) => {
289 impl<const N: usize> IntoDart for [$rust_type; N] {
290 fn into_dart(self) -> DartCObject {
291 let vec: Vec<_> = self.into();
292 vec.into_dart()
293 }
294 }
295
296 impl IntoDart for Vec<$rust_type> {
297 fn into_dart(self) -> DartCObject {
298 let vec: Vec<$delegate_target_type> =
299 self.into_iter().map(|x| x as _).collect();
300 vec.into_dart()
301 }
302 }
303
304 impl<const N: usize> IntoDart for ZeroCopyBuffer<[$rust_type; N]> {
305 fn into_dart(self) -> DartCObject {
306 let vec: Vec<$rust_type> = self.0.into();
307 ZeroCopyBuffer(vec).into_dart()
308 }
309 }
310
311 impl IntoDart for ZeroCopyBuffer<Vec<$rust_type>> {
312 fn into_dart(self) -> DartCObject {
313 let vec: Vec<$delegate_target_type> =
314 self.0.into_iter().map(|x| x as _).collect();
315 ZeroCopyBuffer(vec).into_dart()
316 }
317 }
318
319 impl IntoDartExceptPrimitive for Vec<$rust_type> {}
320 };
321}
322
323isize_usize!(isize, i64);
324isize_usize!(usize, u64);
325
326impl<T> IntoDart for ZeroCopyBuffer<Vec<T>>
327where
328 T: DartTypedDataTypeTrait,
329{
330 fn into_dart(self) -> DartCObject {
331 vec_to_dart_native_external_typed_data(self.0)
332 }
333}
334
335impl<T> IntoDartExceptPrimitive for ZeroCopyBuffer<Vec<T>> where
336 T: DartTypedDataTypeTrait
337{
338}
339
340impl<T> IntoDart for Vec<T>
341where
342 T: IntoDartExceptPrimitive,
343{
344 fn into_dart(self) -> DartCObject {
345 DartArray::from(self.into_iter()).into_dart()
346 }
347}
348
349impl<T> IntoDartExceptPrimitive for Vec<T> where T: IntoDartExceptPrimitive {}
350
351impl<T> IntoDart for HashSet<T>
352where
353 T: IntoDartExceptPrimitive,
354{
355 fn into_dart(self) -> DartCObject {
356 self.into_iter().collect::<Vec<_>>().into_dart()
358 }
359}
360
361impl<T> IntoDartExceptPrimitive for HashSet<T> where T: IntoDartExceptPrimitive {}
362
363impl<K, V> IntoDart for HashMap<K, V>
364where
365 K: IntoDart,
366 V: IntoDart,
367 (K, V): IntoDartExceptPrimitive,
368{
369 fn into_dart(self) -> DartCObject {
370 self.into_iter().collect::<Vec<_>>().into_dart()
372 }
373}
374
375impl<K, V> IntoDartExceptPrimitive for HashMap<K, V>
376where
377 K: IntoDart,
378 V: IntoDart,
379{
380}
381
382impl<T, const N: usize> IntoDart for ZeroCopyBuffer<[T; N]>
383where
384 T: DartTypedDataTypeTrait,
385{
386 fn into_dart(self) -> DartCObject {
387 let vec: Vec<_> = self.0.into();
388 ZeroCopyBuffer(vec).into_dart()
389 }
390}
391
392impl<T, const N: usize> IntoDartExceptPrimitive for ZeroCopyBuffer<[T; N]> where
393 T: DartTypedDataTypeTrait
394{
395}
396
397impl<T, const N: usize> IntoDart for [T; N]
398where
399 T: IntoDartExceptPrimitive,
400{
401 fn into_dart(self) -> DartCObject {
402 DartArray::from(IntoIterator::into_iter(self)).into_dart()
403 }
404}
405
406impl<T> IntoDart for Option<T>
407where
408 T: IntoDart,
409{
410 fn into_dart(self) -> DartCObject {
411 match self {
412 Some(v) => v.into_dart(),
413 None => ().into_dart(),
414 }
415 }
416}
417
418impl<T> IntoDartExceptPrimitive for Option<T> where T: IntoDart {}
419
420impl<T, E> IntoDart for Result<T, E>
421where
422 T: IntoDart,
423 E: ToString,
424{
425 fn into_dart(self) -> DartCObject {
426 match self {
427 Ok(v) => v.into_dart(),
428 Err(e) => e.to_string().into_dart(),
429 }
430 }
431}
432
433impl<T, E> IntoDartExceptPrimitive for Result<T, E>
434where
435 T: IntoDart,
436 E: ToString,
437{
438}
439
440#[cfg(target_pointer_width = "64")]
443impl<T> IntoDart for *const T {
444 fn into_dart(self) -> DartCObject {
445 DartCObject {
446 ty: DartCObjectType::DartInt64,
447 value: DartCObjectValue {
448 as_int64: self as _,
449 },
450 }
451 }
452}
453
454#[cfg(target_pointer_width = "64")]
455impl<T> IntoDart for *mut T {
456 fn into_dart(self) -> DartCObject {
457 DartCObject {
458 ty: DartCObjectType::DartInt64,
459 value: DartCObjectValue {
460 as_int64: self as _,
461 },
462 }
463 }
464}
465
466#[cfg(target_pointer_width = "32")]
467impl<T> IntoDart for *const T {
468 fn into_dart(self) -> DartCObject {
469 DartCObject {
470 ty: DartCObjectType::DartInt32,
471 value: DartCObjectValue {
472 as_int32: self as _,
473 },
474 }
475 }
476}
477
478#[cfg(target_pointer_width = "32")]
479impl<T> IntoDart for *mut T {
480 fn into_dart(self) -> DartCObject {
481 DartCObject {
482 ty: DartCObjectType::DartInt32,
483 value: DartCObjectValue {
484 as_int32: self as _,
485 },
486 }
487 }
488}
489
490macro_rules! impl_into_dart_for_tuple {
491 ($( ($($A:ident)+) )*) => {$(
492 impl<$($A: IntoDart),+> IntoDart for ($($A),+,) {
493 #[allow(non_snake_case)]
494 fn into_dart(self) -> DartCObject {
495 let ($($A),+,) = self;
496 vec![$($A.into_dart()),+].into_dart()
497 }
498 }
499 impl<$($A: IntoDart),+> IntoDartExceptPrimitive for ($($A),+,) {}
500 )*};
501}
502
503impl_into_dart_for_tuple! {
504 (A)
505 (A B)
506 (A B C)
507 (A B C D)
508 (A B C D E)
509 (A B C D E F)
510 (A B C D E F G)
511 (A B C D E F G H)
512 (A B C D E F G H I)
513 (A B C D E F G H I J)
514}