bp3d_proto/util/
mod.rs

1// Copyright (c) 2024, BlockProject 3D
2//
3// All rights reserved.
4//
5// Redistribution and use in source and binary forms, with or without modification,
6// are permitted provided that the following conditions are met:
7//
8//     * Redistributions of source code must retain the above copyright notice,
9//       this list of conditions and the following disclaimer.
10//     * Redistributions in binary form must reproduce the above copyright notice,
11//       this list of conditions and the following disclaimer in the documentation
12//       and/or other materials provided with the distribution.
13//     * Neither the name of BlockProject 3D nor the names of its contributors
14//       may be used to endorse or promote products derived from this software
15//       without specific prior written permission.
16//
17// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
21// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
29mod scalar;
30
31pub use scalar::*;
32
33pub trait Size {
34    const SIZE: usize;
35
36    fn size(&self) -> usize {
37        Self::SIZE
38    }
39}
40
41pub trait MultiOptionExt {
42    type Output;
43
44    fn to_single(self) -> Option<Self::Output>;
45}
46
47impl<T, T1> MultiOptionExt for (Option<T>, Option<T1>) {
48    type Output = (T, T1);
49
50    fn to_single(self) -> Option<Self::Output> {
51        let t = self.0?;
52        let t1 = self.1?;
53        Some((t, t1))
54    }
55}
56
57#[macro_export]
58macro_rules! transmute {
59    (<f64, u64>($value: expr)) => {
60        $value.to_bits()
61    };
62    (<u64, f64>($value: expr)) => {
63        f64::from_bits($value)
64    };
65    (<f32, u32>($value: expr)) => {
66        $value.to_bits()
67    };
68    (<u32, f32>($value: expr)) => {
69        f32::from_bits($value)
70    };
71    (<$src: ty, $dst: ty>($value: expr)) => {
72        unsafe { std::mem::transmute::<$src, $dst>($value) }
73    };
74}
75
76/// This trait represents any structure type.
77pub trait Wrap<T: AsRef<[u8]>>: Sized + Size {
78    /// Wraps the given data buffer.
79    ///
80    /// # Arguments
81    ///
82    /// * `data`: the data buffer to wrap as this structure.
83    ///
84    /// returns: Self
85    ///
86    /// # Panics
87    ///
88    /// This function will panic if the passed data buffer is too small to store the entire
89    /// structure.
90    fn wrap(data: T) -> Self {
91        if data.as_ref().len() < Self::SIZE {
92            panic!("attempt to wrap a too small buffer");
93        }
94        unsafe { Self::wrap_unchecked(data) }
95    }
96
97    /// Wraps the given data buffer.
98    ///
99    /// # Arguments
100    ///
101    /// * `data`: the data buffer to wrap as this structure type.
102    ///
103    /// returns: Self
104    ///
105    /// # Safety
106    ///
107    /// This function assumes the size of the buffer passed in is always at least the size of this
108    /// structure.
109    unsafe fn wrap_unchecked(data: T) -> Self;
110}