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            &[]
133        } else {
134            unsafe { slice::from_raw_parts(self.data, self.size as usize) }
135        }
136    }
137
138    /// Returns the vector as a mutable slice
139    #[inline]
140    pub fn as_slice_mut(&mut self) -> &mut [T] {
141        if self.size == 0 || self.data.is_null() {
142            &mut []
143        } else {
144            unsafe { slice::from_raw_parts_mut(self.data, self.size as usize) }
145        }
146    }
147
148    /// Returns the number of elements in the vector
149    #[inline]
150    pub fn len(&self) -> usize {
151        self.size as usize
152    }
153
154    /// Returns true if the vector is empty
155    #[inline]
156    pub fn is_empty(&self) -> bool {
157        self.size == 0
158    }
159}
160
161impl<T> Default for ImVector<T> {
162    fn default() -> Self {
163        Self {
164            size: 0,
165            capacity: 0,
166            data: std::ptr::null_mut(),
167        }
168    }
169}
170
171impl<T> ImVector<T> {
172    /// Returns an iterator over the elements
173    #[inline]
174    pub fn iter(&self) -> slice::Iter<'_, T> {
175        self.as_slice().iter()
176    }
177
178    /// Returns a mutable iterator over the elements
179    #[inline]
180    pub fn iter_mut(&mut self) -> slice::IterMut<'_, T> {
181        self.as_slice_mut().iter_mut()
182    }
183}
184
185/// Cast a bindgen-generated `ImVector_*` to our generic `ImVector<T>` view.
186///
187/// Safety: `raw` must be a pointer/reference to a C `ImVector` instantiated
188/// with the same element type `T` (layout-compatible). Only use with
189/// bindgen-generated `ImVector_*` structs from dear-imgui-sys.
190#[inline]
191pub unsafe fn imvector_cast_ref<T, R>(raw: &R) -> &ImVector<T> {
192    unsafe { &*(raw as *const R as *const ImVector<T>) }
193}
194
195/// Mutable variant of [`imvector_cast_ref`]. See its safety contract.
196#[inline]
197pub unsafe fn imvector_cast_mut<T, R>(raw: &mut R) -> &mut ImVector<T> {
198    unsafe { &mut *(raw as *mut R as *mut ImVector<T>) }
199}
200
201/// Marks a type as a transparent wrapper over a raw type
202pub trait RawWrapper {
203    /// Wrapped raw type
204    type Raw;
205    /// Returns an immutable reference to the wrapped raw value
206    ///
207    /// # Safety
208    ///
209    /// It is up to the caller to use the returned raw reference without causing undefined
210    /// behaviour or breaking safety rules.
211    unsafe fn raw(&self) -> &Self::Raw;
212    /// Returns a mutable reference to the wrapped raw value
213    ///
214    /// # Safety
215    ///
216    /// It is up to the caller to use the returned mutable raw reference without causing undefined
217    /// behaviour or breaking safety rules.
218    unsafe fn raw_mut(&mut self) -> &mut Self::Raw;
219}
220
221/// Casting from/to a raw type that has the same layout and alignment as the target type
222///
223/// # Safety
224///
225/// Each function outlines its own safety contract, which generally is
226/// that the cast from `T` to `Self` is valid.
227pub unsafe trait RawCast<T>: Sized {
228    /// Casts an immutable reference from the raw type
229    ///
230    /// # Safety
231    ///
232    /// It is up to the caller to guarantee the cast is valid.
233    #[inline]
234    unsafe fn from_raw(raw: &T) -> &Self {
235        unsafe { &*(raw as *const _ as *const Self) }
236    }
237
238    /// Casts a mutable reference from the raw type
239    ///
240    /// # Safety
241    ///
242    /// It is up to the caller to guarantee the cast is valid.
243    #[inline]
244    unsafe fn from_raw_mut(raw: &mut T) -> &mut Self {
245        unsafe { &mut *(raw as *mut _ as *mut Self) }
246    }
247
248    /// Casts an immutable reference to the raw type
249    ///
250    /// # Safety
251    ///
252    /// It is up to the caller to guarantee the cast is valid.
253    #[inline]
254    unsafe fn raw(&self) -> &T {
255        unsafe { &*(self as *const _ as *const T) }
256    }
257
258    /// Casts a mutable reference to the raw type
259    ///
260    /// # Safety
261    ///
262    /// It is up to the caller to guarantee the cast is valid.
263    #[inline]
264    unsafe fn raw_mut(&mut self) -> &mut T {
265        unsafe { &mut *(self as *mut _ as *mut T) }
266    }
267}