dear_imgui_rs/
internal.rs

1//! Internal low-level types
2//!
3//! Exposes helpers mirroring Dear ImGui internals (e.g. `ImVector`, data type
4//! markers). These are primarily for advanced integrations; APIs may change.
5//!
6#![allow(
7    clippy::cast_possible_truncation,
8    clippy::cast_sign_loss,
9    clippy::as_conversions
10)]
11use crate::sys;
12use std::ffi::c_int;
13use std::slice;
14
15/// A primary data type
16#[repr(i32)]
17#[derive(Copy, Clone, Debug, Eq, PartialEq)]
18pub enum DataType {
19    I8 = sys::ImGuiDataType_S8 as i32,
20    U8 = sys::ImGuiDataType_U8 as i32,
21    I16 = sys::ImGuiDataType_S16 as i32,
22    U16 = sys::ImGuiDataType_U16 as i32,
23    I32 = sys::ImGuiDataType_S32 as i32,
24    U32 = sys::ImGuiDataType_U32 as i32,
25    I64 = sys::ImGuiDataType_S64 as i32,
26    U64 = sys::ImGuiDataType_U64 as i32,
27    F32 = sys::ImGuiDataType_Float as i32,
28    F64 = sys::ImGuiDataType_Double as i32,
29}
30
31/// Primitive type marker.
32///
33/// If this trait is implemented for a type, it is assumed to have *exactly* the same
34/// representation in memory as the primitive value described by the associated `KIND` constant.
35///
36/// # Safety
37/// The `DataType` *must* have the same representation as the primitive value of `KIND`.
38pub unsafe trait DataTypeKind: Copy {
39    const KIND: DataType;
40}
41
42unsafe impl DataTypeKind for i8 {
43    const KIND: DataType = DataType::I8;
44}
45unsafe impl DataTypeKind for u8 {
46    const KIND: DataType = DataType::U8;
47}
48unsafe impl DataTypeKind for i16 {
49    const KIND: DataType = DataType::I16;
50}
51unsafe impl DataTypeKind for u16 {
52    const KIND: DataType = DataType::U16;
53}
54unsafe impl DataTypeKind for i32 {
55    const KIND: DataType = DataType::I32;
56}
57unsafe impl DataTypeKind for u32 {
58    const KIND: DataType = DataType::U32;
59}
60unsafe impl DataTypeKind for i64 {
61    const KIND: DataType = DataType::I64;
62}
63unsafe impl DataTypeKind for u64 {
64    const KIND: DataType = DataType::U64;
65}
66unsafe impl DataTypeKind for f32 {
67    const KIND: DataType = DataType::F32;
68}
69unsafe impl DataTypeKind for f64 {
70    const KIND: DataType = DataType::F64;
71}
72
73unsafe impl DataTypeKind for usize {
74    #[cfg(target_pointer_width = "16")]
75    const KIND: DataType = DataType::U16;
76
77    #[cfg(target_pointer_width = "32")]
78    const KIND: DataType = DataType::U32;
79
80    #[cfg(target_pointer_width = "64")]
81    const KIND: DataType = DataType::U64;
82
83    // Fallback for when we are on a weird system width
84    //
85    #[cfg(not(any(
86        target_pointer_width = "16",
87        target_pointer_width = "32",
88        target_pointer_width = "64"
89    )))]
90    compile_error!(
91        "cannot impl DataTypeKind for usize: unsupported target pointer width. supported values are 16, 32, 64"
92    );
93}
94
95unsafe impl DataTypeKind for isize {
96    #[cfg(target_pointer_width = "16")]
97    const KIND: DataType = DataType::I16;
98
99    #[cfg(target_pointer_width = "32")]
100    const KIND: DataType = DataType::I32;
101
102    #[cfg(target_pointer_width = "64")]
103    const KIND: DataType = DataType::I64;
104
105    // Fallback for when we are on a weird system width
106    //
107    #[cfg(not(any(
108        target_pointer_width = "16",
109        target_pointer_width = "32",
110        target_pointer_width = "64"
111    )))]
112    compile_error!(
113        "cannot impl DataTypeKind for isize: unsupported target pointer width. supported values are 16, 32, 64"
114    );
115}
116
117/// A generic version of the raw imgui-sys ImVector struct types
118///
119/// This provides a safe Rust interface to Dear ImGui's vector type.
120#[repr(C)]
121pub struct ImVector<T> {
122    pub(crate) size: c_int,
123    pub(crate) capacity: c_int,
124    pub(crate) data: *mut T,
125}
126
127impl<T> ImVector<T> {
128    /// Returns the vector as a slice
129    #[inline]
130    pub fn as_slice(&self) -> &[T] {
131        if self.size <= 0 || self.data.is_null() {
132            return &[];
133        }
134        let len = match usize::try_from(self.size) {
135            Ok(len) => len,
136            Err(_) => return &[],
137        };
138        unsafe { slice::from_raw_parts(self.data, len) }
139    }
140
141    /// Returns the vector as a mutable slice
142    #[inline]
143    pub fn as_slice_mut(&mut self) -> &mut [T] {
144        if self.size <= 0 || self.data.is_null() {
145            return &mut [];
146        }
147        let len = match usize::try_from(self.size) {
148            Ok(len) => len,
149            Err(_) => return &mut [],
150        };
151        unsafe { slice::from_raw_parts_mut(self.data, len) }
152    }
153
154    /// Returns the number of elements in the vector
155    #[inline]
156    pub fn len(&self) -> usize {
157        if self.size <= 0 {
158            return 0;
159        }
160        usize::try_from(self.size).unwrap_or(0)
161    }
162
163    /// Returns true if the vector is empty
164    #[inline]
165    pub fn is_empty(&self) -> bool {
166        self.size <= 0
167    }
168}
169
170impl<T> Default for ImVector<T> {
171    fn default() -> Self {
172        Self {
173            size: 0,
174            capacity: 0,
175            data: std::ptr::null_mut(),
176        }
177    }
178}
179
180impl<T> ImVector<T> {
181    /// Returns an iterator over the elements
182    #[inline]
183    pub fn iter(&self) -> slice::Iter<'_, T> {
184        self.as_slice().iter()
185    }
186
187    /// Returns a mutable iterator over the elements
188    #[inline]
189    pub fn iter_mut(&mut self) -> slice::IterMut<'_, T> {
190        self.as_slice_mut().iter_mut()
191    }
192}
193
194/// Cast a bindgen-generated `ImVector_*` to our generic `ImVector<T>` view.
195///
196/// # Safety
197/// `raw` must be a pointer/reference to a C `ImVector` instantiated with the same element type
198/// `T` (layout-compatible). Only use with bindgen-generated `ImVector_*` structs from
199/// `dear-imgui-sys`.
200#[inline]
201pub unsafe fn imvector_cast_ref<T, R>(raw: &R) -> &ImVector<T> {
202    unsafe { &*(raw as *const R as *const ImVector<T>) }
203}
204
205/// Mutable variant of [`imvector_cast_ref`]. See its safety contract.
206///
207/// # Safety
208/// Same as [`imvector_cast_ref`], but additionally the caller must ensure the `ImVector` is
209/// uniquely borrowed for the duration of the returned `&mut` reference.
210#[inline]
211pub unsafe fn imvector_cast_mut<T, R>(raw: &mut R) -> &mut ImVector<T> {
212    unsafe { &mut *(raw as *mut R as *mut ImVector<T>) }
213}
214
215/// Update internal hovered window and input capture flags.
216///
217/// This is a thin wrapper around Dear ImGui's internal
218/// `UpdateHoveredWindowAndCaptureFlags()` helper. It is intended for advanced
219/// platform backends that need to drive ImGui's hovering/capture logic
220/// manually (e.g. when aggregating input from multiple sources).
221///
222/// Most applications and backends do **not** need to call this directly.
223#[doc(alias = "UpdateHoveredWindowAndCaptureFlags")]
224pub fn update_hovered_window_and_capture_flags(mouse_pos: [f32; 2]) {
225    unsafe {
226        let pos = sys::ImVec2 {
227            x: mouse_pos[0],
228            y: mouse_pos[1],
229        };
230        sys::igUpdateHoveredWindowAndCaptureFlags(pos.into());
231    }
232}
233
234/// Marks a type as a transparent wrapper over a raw type
235pub trait RawWrapper {
236    /// Wrapped raw type
237    type Raw;
238    /// Returns an immutable reference to the wrapped raw value
239    ///
240    /// # Safety
241    ///
242    /// It is up to the caller to use the returned raw reference without causing undefined
243    /// behaviour or breaking safety rules.
244    unsafe fn raw(&self) -> &Self::Raw;
245    /// Returns a mutable reference to the wrapped raw value
246    ///
247    /// # Safety
248    ///
249    /// It is up to the caller to use the returned mutable raw reference without causing undefined
250    /// behaviour or breaking safety rules.
251    unsafe fn raw_mut(&mut self) -> &mut Self::Raw;
252}
253
254/// Casting from/to a raw type that has the same layout and alignment as the target type
255///
256/// # Safety
257///
258/// Each function outlines its own safety contract, which generally is
259/// that the cast from `T` to `Self` is valid.
260pub unsafe trait RawCast<T>: Sized {
261    /// Casts an immutable reference from the raw type
262    ///
263    /// # Safety
264    ///
265    /// It is up to the caller to guarantee the cast is valid.
266    #[inline]
267    unsafe fn from_raw(raw: &T) -> &Self {
268        unsafe { &*(raw as *const _ as *const Self) }
269    }
270
271    /// Casts a mutable reference from the raw type
272    ///
273    /// # Safety
274    ///
275    /// It is up to the caller to guarantee the cast is valid.
276    #[inline]
277    unsafe fn from_raw_mut(raw: &mut T) -> &mut Self {
278        unsafe { &mut *(raw as *mut _ as *mut Self) }
279    }
280
281    /// Casts an immutable reference to the raw type
282    ///
283    /// # Safety
284    ///
285    /// It is up to the caller to guarantee the cast is valid.
286    #[inline]
287    unsafe fn raw(&self) -> &T {
288        unsafe { &*(self as *const _ as *const T) }
289    }
290
291    /// Casts a mutable reference to the raw type
292    ///
293    /// # Safety
294    ///
295    /// It is up to the caller to guarantee the cast is valid.
296    #[inline]
297    unsafe fn raw_mut(&mut self) -> &mut T {
298        unsafe { &mut *(self as *mut _ as *mut T) }
299    }
300}