added scare warning to string editing to explain null-termination

This commit is contained in:
Jack Mac 2021-09-15 12:14:05 -04:00
parent c3dbd1b21f
commit ff10eb01c8
3 changed files with 105 additions and 29 deletions

View File

@ -373,7 +373,12 @@ impl<'ui> DrawListMut<'ui> {
/// .build(); /// .build();
/// } /// }
/// ``` /// ```
pub fn add_image(&'ui self, texture_id: TextureId, p_min: [f32; 2], p_max: [f32; 2]) -> Image<'_> { pub fn add_image(
&'ui self,
texture_id: TextureId,
p_min: [f32; 2],
p_max: [f32; 2],
) -> Image<'_> {
Image::new(self, texture_id, p_min, p_max) Image::new(self, texture_id, p_min, p_max)
} }
@ -562,7 +567,13 @@ pub struct Triangle<'ui> {
} }
impl<'ui> Triangle<'ui> { impl<'ui> Triangle<'ui> {
fn new<C>(draw_list: &'ui DrawListMut<'_>, p1: [f32; 2], p2: [f32; 2], p3: [f32; 2], c: C) -> Self fn new<C>(
draw_list: &'ui DrawListMut<'_>,
p1: [f32; 2],
p2: [f32; 2],
p3: [f32; 2],
c: C,
) -> Self
where where
C: Into<ImColor32>, C: Into<ImColor32>,
{ {

View File

@ -169,6 +169,20 @@ pub struct InputText<'ui, 'p, L, H = &'static str, T = PassthroughCallback> {
} }
impl<'ui, 'p, L: AsRef<str>> InputText<'ui, 'p, L> { impl<'ui, 'p, L: AsRef<str>> InputText<'ui, 'p, L> {
/// Creates a new input text widget to edit the given string.
///
/// # String Editing
///
/// Please note, ImGui requires this string to be null-terminated. We accomplish this
/// by appending and then removing a null terminator (`\0`) from the String you pass in.
/// This has several consequences:
/// 1. The string's backing buffer may be resized and relocated even without edits as result
/// of this pushed char.
/// 2. **The string will appear truncated if the string contains `\0` inside it.** This will not
/// cause memory *unsafety*, but it will limit your usage. If that's the case, please pre-process
/// your string.
/// 3. Truncations by ImGui appear to be done primarily by insertions of `\0` to the truncation point.
/// We will handle this for you and edit the string "properly" too, but this might show up in callbacks.
pub fn new(ui: &'ui Ui<'ui>, label: L, buf: &'p mut String) -> Self { pub fn new(ui: &'ui Ui<'ui>, label: L, buf: &'p mut String) -> Self {
InputText { InputText {
label, label,
@ -203,22 +217,22 @@ where
impl_text_flags!(InputText); impl_text_flags!(InputText);
/// By default (as of 0.8.0), imgui-rs will automatically handle string resizes // I am commenting this ability out for now -- because we need to push `\0` for imgui,
/// for [InputText] and [InputTextMultiline]. // we may resize the buffer no matter what, and we must do that.
/// // The solution for this will be, I suspect, to build a second api channel that takes
/// If, for some reason, you don't want this, you can run this function to prevent this. // an `&mut CStr`, which is ugly! I suspect few to none will want no-resizing, so I'm deferring
/// In that case, edits which would cause a resize will not occur. // fixing the problem. -- sanbox-irl 09/15/2021, see #523 for more
/// //
/// # Safety // /// By default (as of 0.8.0), imgui-rs will automatically handle string resizes
/// Importantly, we silently push and pop a `\0` to the string given here. // /// for [InputText] and [InputTextMultiline].
/// If you do not want mutable access (ie, do not want that string to resize), // ///
/// you **must** make sure to null-terminate it yourself. This is janky, but ImGui // /// If, for some reason, you don't want this, you can run this function to prevent this.
/// expects a null termination, and we didn't want to re-allocate an entire string per call. // /// In that case, edits which would cause a resize will not occur.
#[inline] // /// #[inline]
pub unsafe fn do_not_resize(mut self) -> Self { // pub unsafe fn do_not_resize(mut self) -> Self {
self.flags.remove(InputTextFlags::CALLBACK_RESIZE); // self.flags.remove(InputTextFlags::CALLBACK_RESIZE);
self // self
} // }
#[inline] #[inline]
pub fn callback<T2: InputTextCallbackHandler>( pub fn callback<T2: InputTextCallbackHandler>(
@ -251,6 +265,20 @@ where
} }
} }
/// Builds the string editor, performing string editing operations.
///
/// # String Editing
///
/// Please note, ImGui requires this string to be null-terminated. We accomplish this
/// by appending and then removing a null terminator (`\0`) from the String you pass in.
/// This has several consequences:
/// 1. The string's backing buffer may be resized and relocated even without edits as result
/// of this pushed char.
/// 2. **The string will appear truncated if the string contains `\0` inside it.** This will not
/// cause memory *unsafety*, but it will limit your usage. If that's the case, please pre-process
/// your string.
/// 3. Truncations by ImGui appear to be done primarily by insertions of `\0` to the truncation point.
/// We will handle this for you and edit the string "properly" too, but this might show up in callbacks.
pub fn build(self) -> bool { pub fn build(self) -> bool {
// needs to be null-terminated! // needs to be null-terminated!
self.buf.push('\0'); self.buf.push('\0');
@ -309,6 +337,20 @@ pub struct InputTextMultiline<'ui, 'p, L, T = PassthroughCallback> {
} }
impl<'ui, 'p, L: AsRef<str>> InputTextMultiline<'ui, 'p, L, PassthroughCallback> { impl<'ui, 'p, L: AsRef<str>> InputTextMultiline<'ui, 'p, L, PassthroughCallback> {
/// Creates a new input text widget to edit the given string.
///
/// # String Editing
///
/// Please note, ImGui requires this string to be null-terminated. We accomplish this
/// by appending and then removing a null terminator (`\0`) from the String you pass in.
/// This has several consequences:
/// 1. The string's backing buffer may be resized and relocated even without edits as result
/// of this pushed char.
/// 2. **The string will appear truncated if the string contains `\0` inside it.** This will not
/// cause memory *unsafety*, but it will limit your usage. If that's the case, please pre-process
/// your string.
/// 3. Truncations by ImGui appear to be done primarily by insertions of `\0` to the truncation point.
/// We will handle this for you and edit the string "properly" too, but this might show up in callbacks.
pub fn new(ui: &'ui Ui<'ui>, label: L, buf: &'p mut String, size: [f32; 2]) -> Self { pub fn new(ui: &'ui Ui<'ui>, label: L, buf: &'p mut String, size: [f32; 2]) -> Self {
InputTextMultiline { InputTextMultiline {
label, label,
@ -324,16 +366,21 @@ impl<'ui, 'p, L: AsRef<str>> InputTextMultiline<'ui, 'p, L, PassthroughCallback>
impl<'ui, 'p, T: InputTextCallbackHandler, L: AsRef<str>> InputTextMultiline<'ui, 'p, L, T> { impl<'ui, 'p, T: InputTextCallbackHandler, L: AsRef<str>> InputTextMultiline<'ui, 'p, L, T> {
impl_text_flags!(InputText); impl_text_flags!(InputText);
/// By default (as of 0.8.0), imgui-rs will automatically handle string resizes // I am commenting this ability out for now -- because we need to push `\0` for imgui,
/// for [InputText] and [InputTextMultiline]. // we may resize the buffer no matter what, and we must do that.
/// // The solution for this will be, I suspect, to build a second api channel that takes
/// If, for some reason, you don't want this, you can run this function to prevent this. // an `&mut CStr`, which is ugly! I suspect few to none will want no-resizing, so I'm deferring
/// In that case, edits which would cause a resize will not occur. // fixing the problem. -- sanbox-irl 09/15/2021, see #523 for more
#[inline] // /// By default (as of 0.8.0), imgui-rs will automatically handle string resizes
pub fn do_not_resize(mut self) -> Self { // /// for [InputText] and [InputTextMultiline].
self.flags.remove(InputTextFlags::CALLBACK_RESIZE); // ///
self // /// If, for some reason, you don't want this, you can run this function to prevent this.
} // /// In that case, edits which would cause a resize will not occur.
// #[inline]
// pub fn do_not_resize(mut self) -> Self {
// self.flags.remove(InputTextFlags::CALLBACK_RESIZE);
// self
// }
#[inline] #[inline]
pub fn callback<T2: InputTextCallbackHandler>( pub fn callback<T2: InputTextCallbackHandler>(
@ -364,6 +411,20 @@ impl<'ui, 'p, T: InputTextCallbackHandler, L: AsRef<str>> InputTextMultiline<'ui
} }
} }
/// Builds the string editor, performing string editing operations.
///
/// # String Editing
///
/// Please note, ImGui requires this string to be null-terminated. We accomplish this
/// by appending and then removing a null terminator (`\0`) from the String you pass in.
/// This has several consequences:
/// 1. The string's backing buffer may be resized and relocated even without edits as result
/// of this pushed char.
/// 2. **The string will appear truncated if the string contains `\0` inside it.** This will not
/// cause memory *unsafety*, but it will limit your usage. If that's the case, please pre-process
/// your string.
/// 3. Truncations by ImGui appear to be done primarily by insertions of `\0` to the truncation point.
/// We will handle this for you and edit the string "properly" too, but this might show up in callbacks.
pub fn build(self) -> bool { pub fn build(self) -> bool {
// needs to be null-terminated! // needs to be null-terminated!
self.buf.push('\0'); self.buf.push('\0');

View File

@ -59,7 +59,11 @@ impl<'ui> Ui<'ui> {
/// color.pop(); /// color.pop();
/// ``` /// ```
#[doc(alias = "PushStyleColorVec4")] #[doc(alias = "PushStyleColorVec4")]
pub fn push_style_color(&self, style_color: StyleColor, color: [f32; 4]) -> ColorStackToken<'_> { pub fn push_style_color(
&self,
style_color: StyleColor,
color: [f32; 4],
) -> ColorStackToken<'_> {
unsafe { sys::igPushStyleColor_Vec4(style_color as i32, color.into()) }; unsafe { sys::igPushStyleColor_Vec4(style_color as i32, color.into()) };
ColorStackToken::new(self) ColorStackToken::new(self)
} }