dear_imgui/
internal.rs

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