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}