#![allow(dead_code)]
#![warn(clippy::all)]
#![warn(clippy::pedantic)]
use slang_sys::*;
use std::ffi::CStr;
use std::num::NonZeroU32;
use std::ptr;
mod result;
pub use slang_sys as ffi;
use result::into_result;
use result::Result;
macro_rules! handle_wrapper_struct_impl {
($wrapper_name:ident, $inner:ty) => {
impl ::std::fmt::Debug for $wrapper_name<'_> {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
f.debug_tuple(stringify!($wrapper_name))
.field(&self.handle)
.finish()
}
}
impl<'a> $wrapper_name<'a> {
#[inline]
pub fn wrap(inner: $inner) -> Self {
Self {
handle: inner,
phantom: ::std::marker::PhantomData,
}
}
#[inline]
pub fn get(&self) -> $inner {
self.handle
}
}
impl From<$inner> for $wrapper_name<'_> {
fn from(inner: $inner) -> Self {
Self::wrap(inner)
}
}
};
}
macro_rules! handle_wrapper_struct {
($wrapper_name:ident, $inner:ty) => {
pub struct $wrapper_name<'a> {
handle: $inner,
phantom: ::std::marker::PhantomData<&'a $inner>,
}
handle_wrapper_struct_impl!($wrapper_name, $inner);
};
}
macro_rules! handle_wrapper_struct_copy {
($wrapper_name:ident, $inner:ty) => {
#[derive(Copy, Clone)]
pub struct $wrapper_name<'a> {
handle: $inner,
phantom: ::std::marker::PhantomData<&'a $inner>,
}
handle_wrapper_struct_impl!($wrapper_name, $inner);
};
}
handle_wrapper_struct!(Session, *mut SlangSession);
impl Default for Session<'_> {
fn default() -> Self {
unsafe { spCreateSession(ptr::null()).into() }
}
}
impl Session<'_> {
pub fn new() -> Self {
Self::default()
}
fn check_compile_target_support(&self, target: SlangCompileTarget) -> Result {
unsafe { into_result(spSessionCheckCompileTargetSupport(self.get(), target)) }
}
fn check_pass_through_support(&self, pass_through: SlangPassThrough) -> Result {
unsafe { into_result(spSessionCheckPassThroughSupport(self.get(), pass_through)) }
}
fn add_builtins(&self, source_path: impl AsRef<CStr>, source_string: impl AsRef<CStr>) {
unsafe {
spAddBuiltins(
self.get(),
source_path.as_ref().as_ptr(),
source_string.as_ref().as_ptr(),
)
}
}
fn create_compile_request(&self) -> CompileRequest {
unsafe { spCreateCompileRequest(self.get()).into() }
}
fn find_profile(&self, name: impl AsRef<CStr>) -> Option<ProfileId> {
unsafe {
let profile = spFindProfile(self.get(), name.as_ref().as_ptr());
NonZeroU32::new(profile)
}
}
}
impl Drop for Session<'_> {
fn drop(&mut self) {
unsafe {
spDestroySession(self.get());
}
}
}
handle_wrapper_struct_copy!(CodeGenTarget, i32);
handle_wrapper_struct_copy!(TranslationUnitIndex, i32);
handle_wrapper_struct_copy!(EntryPointIndex, i32);
handle_wrapper_struct!(CompileRequest, *mut SlangCompileRequest);
impl<'a> CompileRequest<'a> {
fn add_code_gen_target(&self, target: SlangCompileTarget) -> CodeGenTarget {
unsafe { spAddCodeGenTarget(self.get(), target).into() }
}
fn set_target_profile(&self, target_index: CodeGenTarget, profile: ProfileId) {
unsafe { spSetTargetProfile(self.get(), target_index.get(), profile.get()) }
}
fn add_translation_unit(
&self,
language: SlangSourceLanguage,
name: impl AsRef<CStr>,
) -> TranslationUnitIndex {
unsafe { spAddTranslationUnit(self.get(), language, name.as_ref().as_ptr()).into() }
}
fn add_translation_unit_source_string(
&self,
translation_unit_index: TranslationUnitIndex,
path: impl AsRef<CStr>,
source: impl AsRef<CStr>,
) {
unsafe {
spAddTranslationUnitSourceString(
self.get(),
translation_unit_index.get(),
path.as_ref().as_ptr(),
source.as_ref().as_ptr(),
)
}
}
fn add_entry_point(
&self,
translation_unit_index: TranslationUnitIndex,
name: impl AsRef<CStr>,
stage: SlangStage,
) -> EntryPointIndex {
unsafe {
spAddEntryPoint(
self.get(),
translation_unit_index.get(),
name.as_ref().as_ptr(),
stage,
)
.into()
}
}
fn compile(&self) -> Result {
unsafe { into_result(spCompile(self.get())) }
}
fn get_diagnostic_output(&self) -> &'a CStr {
unsafe { CStr::from_ptr(spGetDiagnosticOutput(self.get())) }
}
fn get_entry_point_code(&self, entry_point_index: EntryPointIndex) -> &'a [u8] {
unsafe {
let out_size = std::ptr::null_mut();
let blob = spGetEntryPointCode(self.get(), entry_point_index.get(), out_size);
std::slice::from_raw_parts(blob as *const u8, *out_size)
}
}
}
impl Drop for CompileRequest<'_> {
fn drop(&mut self) {
unsafe {
spDestroyCompileRequest(self.get());
}
}
}
type ProfileId = NonZeroU32;