From e20dd384f504dc24f1a99e98c779e6e11d2949e6 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Wed, 17 Mar 2021 15:25:37 +0100 Subject: [PATCH] Expose an iterator to interpreter::Struct --- sixtyfps_runtime/corelib/slice.rs | 6 ++++ sixtyfps_runtime/interpreter/api.rs | 51 +++++++++++++++++++++++++++-- 2 files changed, 55 insertions(+), 2 deletions(-) diff --git a/sixtyfps_runtime/corelib/slice.rs b/sixtyfps_runtime/corelib/slice.rs index 76acec8d3..d9d7e30ea 100644 --- a/sixtyfps_runtime/corelib/slice.rs +++ b/sixtyfps_runtime/corelib/slice.rs @@ -88,3 +88,9 @@ impl<'a, T> core::ops::Deref for Slice<'a, T> { self.as_slice() } } + +impl<'a, T> Default for Slice<'a, T> { + fn default() -> Self { + Self::from_slice(&[]) + } +} diff --git a/sixtyfps_runtime/interpreter/api.rs b/sixtyfps_runtime/interpreter/api.rs index 38ab249eb..d4c49a1a9 100644 --- a/sixtyfps_runtime/interpreter/api.rs +++ b/sixtyfps_runtime/interpreter/api.rs @@ -877,7 +877,7 @@ pub(crate) mod ffi { // Safety: there should be no way to construct a StructOpaque without it holding an actual Struct unsafe { std::mem::transmute::<&StructOpaque, &Struct>(self) } } - fn as_mut_struct(&mut self) -> &mut Struct { + fn as_struct_mut(&mut self) -> &mut Struct { // Safety: there should be no way to construct a StructOpaque without it holding an actual Struct unsafe { std::mem::transmute::<&mut StructOpaque, &mut Struct>(self) } } @@ -920,7 +920,54 @@ pub(crate) mod ffi { name: &Slice, value: &ValueOpaque, ) { - stru.as_mut_struct() + stru.as_struct_mut() .set_field(std::str::from_utf8(&name).unwrap().into(), value.as_value().clone()) } + + type StructIterator<'a> = std::collections::hash_map::Iter<'a, String, Value>; + #[repr(C)] + pub struct StructIteratorOpaque<'a>([usize; 5], std::marker::PhantomData>); + const _: usize = + std::mem::size_of::() - std::mem::size_of::(); + + #[no_mangle] + pub unsafe extern "C" fn sixtyfps_interpreter_struct_iterator_destructor( + val: *mut StructIteratorOpaque, + ) { + drop(std::ptr::read(val as *mut StructIterator)) + } + + /// The result of the sixtyfps_interpreter_struct_iterator_next function + /// If the iterator was at the end, the key will be empty, and the value will be None + #[repr(C)] + pub struct StructIteratorResult<'a> { + k: Slice<'a, u8>, + v: Option<&'a Value>, + } + + /// Advance the iterator and return the next value, or an + #[no_mangle] + pub unsafe extern "C" fn sixtyfps_interpreter_struct_iterator_next<'a>( + iter: &'a mut StructIteratorOpaque, + ) -> StructIteratorResult<'a> { + if let Some((str, val)) = + (*(iter as *mut StructIteratorOpaque as *mut StructIterator)).next() + { + StructIteratorResult { k: Slice::from_slice(str.as_bytes()), v: Some(val) } + } else { + StructIteratorResult { k: Slice::default(), v: None } + } + } + + #[no_mangle] + pub extern "C" fn sixtyfps_interpreter_struct_make_iter<'a>( + stru: &'a StructOpaque, + ) -> StructIteratorOpaque<'a> { + let ret_it: StructIterator = stru.as_struct().0.iter(); + unsafe { + let mut r = std::mem::MaybeUninit::::uninit(); + std::ptr::write(r.as_mut_ptr() as *mut StructIterator, ret_it); + r.assume_init() + } + } }