1#[cfg(feature = "use-compiled-tools")]
2pub mod external {
3 use spirv_tools_sys::shared;
4
5 pub struct ExternalBinary {
6 inner: *mut shared::Binary,
7 }
8
9 impl ExternalBinary {
10 #[inline]
11 pub(crate) fn new(bin: *mut shared::Binary) -> Self {
12 Self { inner: bin }
13 }
14 }
15
16 impl AsRef<[u32]> for ExternalBinary {
17 #[inline]
18 fn as_ref(&self) -> &[u32] {
19 unsafe { std::slice::from_raw_parts((*self.inner).code, (*self.inner).size) }
20 }
21 }
22
23 impl AsRef<[u8]> for ExternalBinary {
24 #[inline]
25 fn as_ref(&self) -> &[u8] {
26 unsafe {
27 std::slice::from_raw_parts(
28 (*self.inner).code.cast(),
29 (*self.inner).size * size_of::<u32>(),
30 )
31 }
32 }
33 }
34
35 impl Drop for ExternalBinary {
36 #[inline]
37 fn drop(&mut self) {
38 unsafe {
39 shared::binary_destroy(self.inner);
40 }
41 }
42 }
43}
44
45pub enum Binary {
46 #[cfg(feature = "use-compiled-tools")]
47 External(external::ExternalBinary),
48 OwnedU32(Vec<u32>),
49 OwnedU8(Vec<u8>),
50}
51
52impl Binary {
53 #[inline]
55 pub fn as_bytes(&self) -> &[u8] {
56 self.as_ref()
57 }
58
59 #[inline]
61 pub fn as_words(&self) -> &[u32] {
62 self.as_ref()
63 }
64}
65
66impl TryFrom<Vec<u8>> for Binary {
67 type Error = crate::Error;
68
69 #[inline]
70 fn try_from(v: Vec<u8>) -> Result<Self, Self::Error> {
71 if v.len() % size_of::<u32>() != 0 {
72 Err(crate::Error {
73 inner: spirv_tools_sys::shared::SpirvResult::InvalidBinary,
74 diagnostic: None,
75 })
76 } else {
77 Ok(Binary::OwnedU8(v))
78 }
79 }
80}
81
82impl AsRef<[u32]> for Binary {
83 #[inline]
84 fn as_ref(&self) -> &[u32] {
85 match self {
86 #[cfg(feature = "use-compiled-tools")]
87 Self::External(bin) => bin.as_ref(),
88 Self::OwnedU32(v) => v,
89 Self::OwnedU8(v) => {
90 to_binary(v).unwrap()
92 }
93 }
94 }
95}
96
97impl AsRef<[u8]> for Binary {
98 #[inline]
99 fn as_ref(&self) -> &[u8] {
100 match self {
101 #[cfg(feature = "use-compiled-tools")]
102 Self::External(bin) => bin.as_ref(),
103 Self::OwnedU32(v) => from_binary(v),
104 Self::OwnedU8(v) => v,
105 }
106 }
107}
108
109use std::fmt;
110
111impl fmt::Debug for Binary {
112 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
113 let mut ds = match self {
114 #[cfg(feature = "use-compiled-tools")]
115 Self::External(_) => f.debug_struct("External"),
116 Self::OwnedU32(_) => f.debug_struct("OwnedU32"),
117 Self::OwnedU8(_) => f.debug_struct("OwnedU8"),
118 };
119
120 ds.field("word_count", &self.as_words().len()).finish()
121 }
122}
123
124#[inline]
127pub fn from_binary(bin: &[u32]) -> &[u8] {
128 unsafe { std::slice::from_raw_parts(bin.as_ptr().cast(), size_of_val(bin)) }
129}
130
131#[inline]
134pub fn to_binary(bytes: &[u8]) -> Result<&[u32], crate::Error> {
135 if bytes.len() % size_of::<u32>() != 0 {
136 return Err(crate::Error {
137 inner: spirv_tools_sys::shared::SpirvResult::InvalidBinary,
138 diagnostic: None,
139 });
140 }
141 if bytes.as_ptr().addr() % size_of::<u32>() != 0 {
142 return Err(crate::Error {
143 inner: spirv_tools_sys::shared::SpirvResult::InvalidBinary,
144 diagnostic: None,
145 });
146 }
147
148 #[allow(clippy::size_of_in_element_count)]
149 Ok(
150 unsafe {
151 std::slice::from_raw_parts(bytes.as_ptr().cast(), bytes.len() / size_of::<u32>())
152 },
153 )
154}