Skip to main content

nox_spirv/
core.rs

1use core::{
2    ffi::{CStr, FromBytesWithNulError},
3    slice,
4    fmt::{self, Display},
5    ops::Deref,
6};
7
8/// A trait for types, which can be trivially converted from and to [`u32`].
9pub trait Word: Sized {
10    
11    fn from_word(word: u32) -> Self;
12}
13
14impl Word for u32 { 
15
16    #[inline]
17    fn from_word(word: u32) -> Self {
18        word
19    }
20}
21
22#[inline]
23pub(crate) fn slice_as_bytes<T>(slice: &[T]) -> &[u8] {
24    unsafe {
25        slice::from_raw_parts(slice.as_ptr() as *const u8, size_of_val(slice))
26    }
27}
28
29/// Represents a string inside SPIR-V.
30//
31/// Doesn't do any extra allocations and is trivially copyable.
32#[derive(Default, Clone, Copy, PartialEq, Eq, Debug, Hash)]
33pub struct CompilerStr<'a> {
34    bytes: &'a [u8],
35}
36
37impl<'a> Deref for CompilerStr<'a> {
38
39    type Target = [u8];
40
41    fn deref(&self) -> &Self::Target {
42        self.bytes
43    }
44}
45
46impl<'a> CompilerStr<'a> {
47
48    pub fn new(words: &'a [u32]) -> Self {
49        let bytes = slice_as_bytes(words);
50        let len = bytes
51            .iter()
52            .copied()
53            .take_while(|&byte| byte != 0)
54            .count() + 1;
55        Self {
56            bytes: &bytes[0..len],
57        }
58    }
59
60    #[inline]
61    pub fn to_cstr(&self) -> Result<&'a CStr, FromBytesWithNulError> {
62        CStr::from_bytes_with_nul(
63            self.bytes
64        )
65    }
66}
67
68impl Display for CompilerStr<'_> {
69
70    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
71        write!(f, "{}", str
72            ::from_utf8(&self.bytes[0..self.bytes.len()-1])
73            .unwrap_or("<utf8-error>"
74        ))
75    }
76}
77
78/// Specifies the value of a literal constant.
79#[derive(Clone, Copy, Debug)]
80pub enum Literal {
81    /// Not representable in Rust without nightly.
82    F16(u16),
83    F32(f32),
84    F64(f64),
85    I8(i8),
86    I16(i16),
87    I32(i32),
88    I64(i64),
89    U8(u8),
90    U16(u16),
91    U32(u32),
92    U64(u64),
93}
94
95impl Literal {
96
97    #[inline]
98    pub fn as_usize(self) -> Option<usize> {
99        match self {
100            Self::I8(x) => Some(x as usize),
101            Self::I16(x) => Some(x as usize),
102            Self::I32(x) => Some(x as usize),
103            Self::I64(x) => Some(x as usize),
104            Self::U8(x) => Some(x as usize),
105            Self::U16(x) => Some(x as usize),
106            Self::U32(x) => Some(x as usize),
107            Self::U64(x) => Some(x as usize),
108            _ => None,
109        }
110    }
111}
112
113impl Display for Literal {
114
115    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
116        match self {
117            Self::F16(x) => write!(f, "{x:#x}"),
118            Self::F32(x) => write!(f, "{x}"),
119            Self::F64(x) => write!(f, "{x}"),
120            Self::I8(x) => write!(f, "{x}"),
121            Self::I16(x) => write!(f, "{x}"),
122            Self::I32(x) => write!(f, "{x}"),
123            Self::I64(x) => write!(f, "{x}"),
124            Self::U8(x) => write!(f, "{x}"),
125            Self::U16(x) => write!(f, "{x}"),
126            Self::U32(x) => write!(f, "{x}"),
127            Self::U64(x) => write!(f, "{x}"),
128        }
129    }
130}