diff --git a/examples/Cargo.toml b/examples/Cargo.toml index 0fdf9f0..9861468 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -10,6 +10,9 @@ lvgl = { path = "../lvgl" } lvgl-sys = { path = "../lvgl-sys" } embedded-graphics = "0.6" embedded-graphics-simulator = "0.2.0" +heapless = "0.5.5" +cstr_core = { version = "0.2.0" } +typenum = "1.12.0" [[example]] name = "demo" diff --git a/examples/demo.rs b/examples/demo.rs index ebeef3c..2af638e 100644 --- a/examples/demo.rs +++ b/examples/demo.rs @@ -1,3 +1,4 @@ +use cstr_core::{CStr, CString}; use embedded_graphics::pixelcolor::Rgb565; use embedded_graphics::prelude::*; use embedded_graphics_simulator::{ @@ -44,7 +45,7 @@ fn main() -> Result<(), LvError> { style_time.set_text_color(State::DEFAULT, Color::from_rgb((255, 255, 255))); time.add_style(Part::Main, style_time)?; time.set_align(&mut screen, Align::Center, 0, 0)?; - time.set_text("20:46")?; + time.set_text(CString::new("20:46").unwrap().as_c_str())?; time.set_width(240)?; time.set_height(240)?; @@ -52,15 +53,29 @@ fn main() -> Result<(), LvError> { bt.set_width(50)?; bt.set_height(80)?; bt.set_recolor(true)?; - bt.set_text("#5794f2 \u{F293}#")?; + bt.set_text(CString::new("#5794f2 \u{F293}#").unwrap().as_c_str())?; bt.set_label_align(LabelAlign::Left)?; bt.set_align(&mut screen, Align::InTopLeft, 0, 0)?; + fn set_text(text: S) -> Result<(), ()> + where + S: AsRef, + { + let _v: *const i8 = text.as_ref().as_ptr(); + Ok(()) + } + + let mut t: heapless::String = heapless::String::from("test"); + t.push('\0').unwrap(); + set_text(CStr::from_bytes_with_nul(t.as_bytes()).unwrap()).unwrap(); + set_text(CStr::from_bytes_with_nul("test\0".as_bytes()).unwrap()).unwrap(); + set_text(cstr_core::CString::new("test").unwrap().as_c_str()).unwrap(); + let mut power = Label::new(&mut screen)?; power.set_recolor(true)?; power.set_width(80)?; power.set_height(20)?; - power.set_text("#fade2a 20%#")?; + power.set_text(CString::new("#fade2a 20%#").unwrap().as_c_str())?; power.set_label_align(LabelAlign::Right)?; power.set_align(&mut screen, Align::InTopRight, 0, 0)?; @@ -83,7 +98,8 @@ fn main() -> Result<(), LvError> { if i > 59 { i = 0; } - time.set_text(format!("21:{:02}", i).as_str())?; + let val = format!("21:{:02}", i); + time.set_text(CString::new(val.as_str()).unwrap().as_c_str())?; i = 1 + i; sleep(Duration::from_secs(1)); diff --git a/lvgl-codegen/src/lib.rs b/lvgl-codegen/src/lib.rs index 260761d..d0778b1 100644 --- a/lvgl-codegen/src/lib.rs +++ b/lvgl-codegen/src/lib.rs @@ -19,7 +19,7 @@ lazy_static! { ("i32", "i32"), ("u8", "u8"), ("bool", "bool"), - ("* const cty :: c_char", "&str"), + ("* const cty :: c_char", "_"), ] .iter() .cloned() @@ -259,17 +259,11 @@ impl LvArg { } pub fn get_processing(&self) -> TokenStream { - let ident = self.get_name_ident(); // TODO: A better way to handle this, instead of `is_sometype()`, is using the Rust // type system itself. - if self.typ.is_str() { - quote! { - let #ident = cstr_core::CString::new(#ident)?; - } - } else { - // No need to pre-process this type of argument - quote! {} - } + + // No need to pre-process this type of argument + quote! {} } pub fn get_value_usage(&self) -> TokenStream { @@ -339,7 +333,7 @@ impl Rusty for LvType { match TYPE_MAPPINGS.get(self.literal_name.as_str()) { Some(name) => { let val = if self.is_str() { - quote!(&str) + quote!(&cstr_core::CStr) } else { let ident = format_ident!("{}", name); quote!(#ident) @@ -573,8 +567,8 @@ mod test { let code = label_set_text.code(&parent_widget).unwrap(); let expected_code = quote! { - pub fn set_text(&mut self, text: &str) -> crate::LvResult<()> { - let text = cstr_core::CString::new(text)?; + + pub fn set_text(&mut self, text: &cstr_core::CStr) -> crate::LvResult<()> { unsafe { lvgl_sys::lv_label_set_text( self.core.raw()?.as_mut(), @@ -583,6 +577,7 @@ mod test { } Ok(()) } + }; assert_eq!(code.to_string(), expected_code.to_string()); diff --git a/lvgl/Cargo.toml b/lvgl/Cargo.toml index 968055f..45d851c 100644 --- a/lvgl/Cargo.toml +++ b/lvgl/Cargo.toml @@ -17,6 +17,8 @@ cty = "0.2.1" embedded-graphics = "0.6.2" cstr_core = { version = "0.2.0", default-features = false, features = ["alloc"] } bitflags = "1.2.1" +heapless = "0.5.5" +typenum = "1.12.0" [build-dependencies] quote = "1.0.7" diff --git a/lvgl/src/display.rs b/lvgl/src/display.rs index 3c8b4d3..5741002 100644 --- a/lvgl/src/display.rs +++ b/lvgl/src/display.rs @@ -19,23 +19,21 @@ impl DisplayDriver { // Declare a buffer for the refresh rate // TODO: Make this an external configuration const REFRESH_BUFFER_LEN: usize = 2; - let refresh_buffer1 = vec![ - Color::from_rgb((0, 0, 0)).raw; - lvgl_sys::LV_HOR_RES_MAX as usize * REFRESH_BUFFER_LEN - ]; + const BUF_SIZE: usize = lvgl_sys::LV_HOR_RES_MAX as usize * REFRESH_BUFFER_LEN; - let refresh_buffer2 = vec![ - Color::from_rgb((0, 0, 0)).raw; - lvgl_sys::LV_HOR_RES_MAX as usize * REFRESH_BUFFER_LEN - ]; + let refresh_buffer1: [lvgl_sys::lv_color_t; BUF_SIZE] = + [Color::from_rgb((0, 0, 0)).raw; BUF_SIZE]; + + let refresh_buffer2: [lvgl_sys::lv_color_t; BUF_SIZE] = + [Color::from_rgb((0, 0, 0)).raw; BUF_SIZE]; // Create a display buffer for LittlevGL let mut display_buffer = MaybeUninit::::uninit(); // Initialize the display buffer lvgl_sys::lv_disp_buf_init( display_buffer.as_mut_ptr(), - Box::into_raw(refresh_buffer1.into_boxed_slice()) as *mut cty::c_void, - Box::into_raw(refresh_buffer2.into_boxed_slice()) as *mut cty::c_void, + Box::into_raw(Box::new(refresh_buffer1)) as *mut cty::c_void, + Box::into_raw(Box::new(refresh_buffer2)) as *mut cty::c_void, lvgl_sys::LV_HOR_RES_MAX * REFRESH_BUFFER_LEN as u32, ); let display_buffer = Box::new(display_buffer.assume_init()); diff --git a/lvgl/src/support.rs b/lvgl/src/support.rs index 47a48e6..0111652 100644 --- a/lvgl/src/support.rs +++ b/lvgl/src/support.rs @@ -12,6 +12,8 @@ pub enum LvError { InvalidReference, Uninitialized, InvalidNulByteString, + StringSizeTooShort, + StringCannotAppendNulByte, AlreadyInUse, }