Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

<T as NativeObject>::raw() infallible, Obj store NonNull pointers #143

Merged
merged 2 commits into from
Jun 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions examples/sdl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,11 @@ fn main() -> LvResult<()> {

let mut screen_style = Style::default();
screen_style.set_bg_color(Color::from_rgb((0, 0, 0)));
screen.add_style(Part::Main, &mut screen_style)?;
screen.add_style(Part::Main, &mut screen_style);
// Create the button
let mut button = Btn::create(&mut screen)?;
button.set_align(Align::LeftMid, 30, 0)?;
button.set_size(180, 80)?;
button.set_align(Align::LeftMid, 30, 0);
button.set_size(180, 80);
let mut btn_lbl = Label::create(&mut button)?;
btn_lbl.set_text(CString::new("Click me!").unwrap().as_c_str())?;

Expand Down
10 changes: 5 additions & 5 deletions lvgl-codegen/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ impl Rusty for LvFunc {
pub fn create(parent: &mut impl crate::NativeObject) -> crate::LvResult<Self> {
unsafe {
let ptr = lvgl_sys::#original_func_name(
parent.raw()?.as_mut(),
parent.raw().as_mut(),
);
if let Some(raw) = core::ptr::NonNull::new(ptr) {
let core = <crate::Obj as crate::Widget>::from_raw(raw).unwrap();
Expand Down Expand Up @@ -196,7 +196,7 @@ impl Rusty for LvFunc {
.fold(quote!(), |args, (i, arg)| {
// if first arg is `const`, then it should be immutable
let next_arg = if i == 0 {
quote!(self.core.raw()?.as_mut())
quote!(self.core.raw().as_mut())
} else {
let var = arg.get_value_usage();
quote!(#var)
Expand Down Expand Up @@ -557,7 +557,7 @@ mod test {
let expected_code = quote! {
pub fn set_bg_end_angle(&mut self, end: u16) -> crate::LvResult<()> {
unsafe {
lvgl_sys::lv_arc_set_bg_end_angle(self.core.raw()?.as_mut(), end);
lvgl_sys::lv_arc_set_bg_end_angle(self.core.raw().as_mut(), end);
}
Ok(())
}
Expand Down Expand Up @@ -590,7 +590,7 @@ mod test {
pub fn set_text(&mut self, text: &cstr_core::CStr) -> crate::LvResult<()> {
unsafe {
lvgl_sys::lv_label_set_text(
self.core.raw()?.as_mut(),
self.core.raw().as_mut(),
text.as_ptr()
);
}
Expand Down Expand Up @@ -649,7 +649,7 @@ mod test {
pub fn create(parent: &mut impl crate::NativeObject) -> crate::LvResult<Self> {
unsafe {
let ptr = lvgl_sys::lv_arc_create(
parent.raw()?.as_mut(),
parent.raw().as_mut(),
);
if let Some(raw) = core::ptr::NonNull::new(ptr) {
let core = <crate::Obj as crate::Widget>::from_raw(raw).unwrap();
Expand Down
9 changes: 5 additions & 4 deletions lvgl/src/display.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::functions::CoreError;
use crate::Screen;
use crate::{disp_drv_register, disp_get_default, get_str_act, LvResult, NativeObject};
use crate::{disp_drv_register, disp_get_default, get_str_act, NativeObject};
use crate::{Box, Color};
use core::convert::TryInto;
#[cfg(feature = "nightly")]
Expand Down Expand Up @@ -77,10 +77,9 @@ impl<'a> Display {
}

/// Sets a `Screen` as currently active.
pub fn set_scr_act(&'a self, screen: &'a mut Screen) -> LvResult<()> {
let scr_ptr = unsafe { screen.raw()?.as_mut() };
pub fn set_scr_act(&'a self, screen: &'a mut Screen) {
let scr_ptr = unsafe { screen.raw().as_mut() };
unsafe { lvgl_sys::lv_disp_load_scr(scr_ptr) }
Ok(())
}

/// Registers a display from raw functions and values.
Expand All @@ -89,6 +88,7 @@ impl<'a> Display {
///
/// `hor_res` and `ver_res` must be nonzero, and the provided functions
/// must not themselves cause undefined behavior.
#[allow(clippy::too_many_arguments)]
pub unsafe fn register_raw<const N: usize>(
draw_buffer: DrawBuffer<N>,
hor_res: u32,
Expand Down Expand Up @@ -230,6 +230,7 @@ impl<'a, const N: usize> DisplayDriver<N> {
}))
}

#[allow(clippy::too_many_arguments)]
pub unsafe fn new_raw(
mut draw_buffer: DrawBuffer<N>,
flush_cb: Option<
Expand Down
5 changes: 2 additions & 3 deletions lvgl/src/functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,11 +72,10 @@ pub fn task_handler() {
pub fn event_send<W: for<'a> Widget<'a>>(
obj: &mut W,
event: Event<<W as Widget<'_>>::SpecialEvent>,
) -> LvResult<()> {
) {
unsafe {
lvgl_sys::lv_event_send(obj.raw()?.as_mut(), event.into(), ptr::null_mut());
lvgl_sys::lv_event_send(obj.raw().as_mut(), event.into(), ptr::null_mut());
};
Ok(())
}

/// Register an input device driver to LVGL.
Expand Down
2 changes: 1 addition & 1 deletion lvgl/src/lv_core/group.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ impl Group {

/// Adds an object to the group.
pub fn add_obj(&mut self, obj: &impl NativeObject) -> LvResult<()> {
unsafe { lvgl_sys::lv_group_add_obj(self.raw()?.as_mut(), obj.raw()?.as_mut()) }
unsafe { lvgl_sys::lv_group_add_obj(self.raw()?.as_mut(), obj.raw().as_mut()) }
Ok(())
}

Expand Down
98 changes: 45 additions & 53 deletions lvgl/src/lv_core/obj.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,24 @@ use crate::lv_core::style::Style;
use crate::{Align, LvError, LvResult};
use core::fmt::{self, Debug};
use core::marker::PhantomData;
use core::ptr;
use core::ptr::{self, NonNull};

/// Represents a native LVGL object.
pub trait NativeObject {
/// Provide common way to access to the underlying native object pointer.
fn raw(&self) -> LvResult<ptr::NonNull<lvgl_sys::lv_obj_t>>;
fn raw(&self) -> NonNull<lvgl_sys::lv_obj_t>;
}

/// Generic LVGL object.
///
/// This is the parent object of all widget types. It stores the native LVGL raw pointer.
/// This is the parent object of all widget types. It stores the native LVGL
/// raw pointer.
pub struct Obj<'a> {
// We use a raw pointer here because we do not control this memory address, it is controlled
// by LVGL's global state.
raw: *mut lvgl_sys::lv_obj_t,
// This is to ensure safety for style memory; it has no runtime impact
styles_used: PhantomData<&'a lvgl_sys::lv_style_t>,
// We use a raw pointer here because we do not control this memory address,
// it is controlled by LVGL's global state.
raw: NonNull<lvgl_sys::lv_obj_t>,
// This is to ensure safety for children memory; it has no runtime impact
dependents: PhantomData<&'a isize>,
}

impl Debug for Obj<'_> {
Expand All @@ -38,15 +39,15 @@ impl Debug for Obj<'_> {

// We need to manually impl methods on Obj since widget codegen is defined in
// terms of Obj
impl Obj<'_> {
pub fn create(parent: &mut impl NativeObject) -> LvResult<Self> {
impl<'a> Obj<'a> {
pub fn create(parent: &'a mut impl NativeObject) -> LvResult<Self> {
unsafe {
let ptr = lvgl_sys::lv_obj_create(parent.raw()?.as_mut());
if ptr::NonNull::new(ptr).is_some() {
let ptr = lvgl_sys::lv_obj_create(parent.raw().as_mut());
if let Some(nn_ptr) = ptr::NonNull::new(ptr) {
//(*ptr).user_data = Box::new(UserDataObj::empty()).into_raw() as *mut _;
Ok(Self {
raw: ptr,
styles_used: PhantomData,
raw: nn_ptr,
dependents: PhantomData::<&'a _>,
})
} else {
Err(LvError::InvalidReference)
Expand All @@ -56,17 +57,23 @@ impl Obj<'_> {

pub fn new() -> crate::LvResult<Self> {
let mut parent = crate::display::get_scr_act()?;
Self::create(&mut parent)
Self::create(unsafe { &mut *(&mut parent as *mut _) })
}

pub fn blank() -> LvResult<Self> {
match NonNull::new(unsafe { lvgl_sys::lv_obj_create(ptr::null_mut()) }) {
Some(raw) => Ok(Self {
raw,
dependents: PhantomData,
}),
None => Err(LvError::LvOOMemory),
}
}
}

impl NativeObject for Obj<'_> {
fn raw(&self) -> LvResult<ptr::NonNull<lvgl_sys::lv_obj_t>> {
if let Some(non_null_ptr) = ptr::NonNull::new(self.raw) {
Ok(non_null_ptr)
} else {
Err(LvError::InvalidReference)
}
fn raw(&self) -> ptr::NonNull<lvgl_sys::lv_obj_t> {
self.raw
}
}

Expand All @@ -85,92 +92,77 @@ pub trait Widget<'a>: NativeObject + Sized + 'a {
unsafe fn from_raw(raw_pointer: ptr::NonNull<lvgl_sys::lv_obj_t>) -> Option<Self>;

/// Adds a `Style` to a given widget.
fn add_style(&mut self, part: Self::Part, style: &'a mut Style) -> LvResult<()> {
fn add_style(&mut self, part: Self::Part, style: &'a mut Style) {
unsafe {
lvgl_sys::lv_obj_add_style(
self.raw()?.as_mut(),
self.raw().as_mut(),
style.raw.as_mut() as *mut _,
part.into(),
);
};
Ok(())
}

/// Sets a widget's position relative to its parent.
fn set_pos(&mut self, x: i16, y: i16) -> LvResult<()> {
fn set_pos(&mut self, x: i16, y: i16) {
unsafe {
lvgl_sys::lv_obj_set_pos(
self.raw()?.as_mut(),
self.raw().as_mut(),
x as lvgl_sys::lv_coord_t,
y as lvgl_sys::lv_coord_t,
);
}
Ok(())
}

/// Sets a widget's size. Alternatively, use `set_width()` and `set_height()`.
fn set_size(&mut self, w: i16, h: i16) -> LvResult<()> {
fn set_size(&mut self, w: i16, h: i16) {
unsafe {
lvgl_sys::lv_obj_set_size(
self.raw()?.as_mut(),
self.raw().as_mut(),
w as lvgl_sys::lv_coord_t,
h as lvgl_sys::lv_coord_t,
);
}
Ok(())
}

/// Sets a widget's width. Alternatively, use `set_size()`.
fn set_width(&mut self, w: u32) -> LvResult<()> {
fn set_width(&mut self, w: u32) {
unsafe {
lvgl_sys::lv_obj_set_width(self.raw()?.as_mut(), w as lvgl_sys::lv_coord_t);
lvgl_sys::lv_obj_set_width(self.raw().as_mut(), w as lvgl_sys::lv_coord_t);
}
Ok(())
}

/// Sets a widget's height. Alternatively, use `set_size()`.
fn set_height(&mut self, h: u32) -> LvResult<()> {
fn set_height(&mut self, h: u32) {
unsafe {
lvgl_sys::lv_obj_set_height(self.raw()?.as_mut(), h as lvgl_sys::lv_coord_t);
lvgl_sys::lv_obj_set_height(self.raw().as_mut(), h as lvgl_sys::lv_coord_t);
}
Ok(())
}

/// Sets a widget's align relative to its parent along with an offset.
fn set_align(&mut self, align: Align, x_mod: i32, y_mod: i32) -> LvResult<()> {
fn set_align(&mut self, align: Align, x_mod: i32, y_mod: i32) {
unsafe {
lvgl_sys::lv_obj_align(
self.raw()?.as_mut(),
self.raw().as_mut(),
align.into(),
x_mod as lvgl_sys::lv_coord_t,
y_mod as lvgl_sys::lv_coord_t,
);
}
Ok(())
}
}

impl<'a> Widget<'a> for Obj<'a> {
type SpecialEvent = u32;
type Part = Part;

unsafe fn from_raw(raw: ptr::NonNull<lvgl_sys::lv_obj_t>) -> Option<Self> {
unsafe fn from_raw(raw: NonNull<lvgl_sys::lv_obj_t>) -> Option<Self> {
Some(Self {
raw: raw.as_ptr(),
styles_used: PhantomData,
raw,
dependents: PhantomData,
})
}
}

impl Default for Obj<'_> {
fn default() -> Self {
Self {
raw: unsafe { lvgl_sys::lv_obj_create(ptr::null_mut()) },
styles_used: PhantomData,
}
}
}

macro_rules! define_object {
($item:ident) => {
define_object!($item, event = (), part = $crate::Part);
Expand All @@ -197,7 +189,7 @@ macro_rules! define_object {
{
use $crate::NativeObject;
unsafe {
let obj = self.raw()?.as_mut();
let obj = self.raw().as_mut();
obj.user_data = $crate::Box::into_raw($crate::Box::new(f)) as *mut _;
lvgl_sys::lv_obj_add_event_cb(
obj,
Expand All @@ -213,7 +205,7 @@ macro_rules! define_object {
}

impl $crate::NativeObject for $item<'_> {
fn raw(&self) -> $crate::LvResult<core::ptr::NonNull<lvgl_sys::lv_obj_t>> {
fn raw(&self) -> core::ptr::NonNull<lvgl_sys::lv_obj_t> {
self.core.raw()
}
}
Expand Down
21 changes: 14 additions & 7 deletions lvgl/src/lv_core/screen.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
use crate::{LvError, NativeObject, Obj, Part, Widget};
use crate::{LvError, LvResult, NativeObject, Obj, Part, Widget};

/// An LVGL screen.
#[derive(Debug, Default)]
#[derive(Debug)]
pub struct Screen<'a> {
raw: Obj<'a>,
}

impl Screen<'_> {
pub fn blank() -> LvResult<Self> {
Ok(Self { raw: Obj::blank()? })
}
}

impl NativeObject for Screen<'_> {
fn raw(&self) -> crate::LvResult<core::ptr::NonNull<lvgl_sys::lv_obj_t>> {
fn raw(&self) -> core::ptr::NonNull<lvgl_sys::lv_obj_t> {
self.raw.raw()
}
}
Expand All @@ -28,13 +34,14 @@ impl<'a> TryFrom<Obj<'a>> for Screen<'a> {
type Error = LvError;

fn try_from(value: Obj<'a>) -> Result<Self, Self::Error> {
match unsafe { value.raw()?.as_mut().parent } as usize {
match unsafe { value.raw().as_mut().parent } as usize {
0 => Ok(Self { raw: value }),
_ => Err(LvError::InvalidReference),
}
}
}

#[allow(clippy::from_over_into)]
impl<'a> Into<Obj<'a>> for Screen<'a> {
fn into(self) -> Obj<'a> {
self.raw
Expand Down Expand Up @@ -66,8 +73,8 @@ mod test {
let buffer = DrawBuffer::<{ (HOR_RES * VER_RES) as usize }>::default();
let display = Display::register(buffer, HOR_RES, VER_RES, |_| {}).unwrap();
let mut screen_old = display.get_scr_act().unwrap();
let mut screen_new = Screen::default();
display.set_scr_act(&mut screen_new).unwrap();
display.set_scr_act(&mut screen_old).unwrap();
let mut screen_new = Screen::blank().unwrap();
display.set_scr_act(&mut screen_new);
display.set_scr_act(&mut screen_old);
}
}
2 changes: 1 addition & 1 deletion lvgl/src/misc/anim.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ where
let anim =
NonNull::new(lvgl_sys::lv_anim_get(obj, None) as *mut lvgl_sys::lv_anim_t).unwrap();
// yes, we have to do it this way. Casting `obj` directly to `&mut Obj` segfaults
let obj = (*(obj as *mut T)).raw().unwrap();
let obj = (*(obj as *mut T)).raw();
if !anim.as_ref().user_data.is_null() {
let callback = &mut *(obj.as_ref().user_data as *mut F);
let mut obj_nondrop = Obj::from_raw(obj).unwrap();
Expand Down
Loading