1pub mod adapters;
75
76#[cfg(test)]
78mod tests;
79
80use bitflags::*;
86use fxhash::*;
87use std::any::*;
88use std::collections::hash_map::*;
89use std::error::*;
90use std::ffi::*;
91use std::marker::*;
92use std::mem::*;
93use std::ops::*;
94use std::slice::*;
95use std::sync::*;
96
97#[derive(Copy, Clone, Debug, PartialEq, Eq)]
98pub struct Version {
99 pub major: u32,
100 pub minor: u32,
101 pub patch: u32,
102}
103
104pub fn get_version() -> Version {
105 let mut result = gvox_sys::GvoxVersion {
106 major: 0,
107 minor: 0,
108 patch: 0,
109 };
110 unsafe {
111 gvox_sys::gvox_get_version(&mut result);
112 }
113 Version {
114 major: result.major,
115 minor: result.minor,
116 patch: result.patch,
117 }
118}
119
120pub fn blit_region(
124 input_ctx: Option<&mut AdapterContext<'_, Input>>,
125 output_ctx: Option<&mut AdapterContext<'_, Output>>,
126 parse_ctx: &mut AdapterContext<'_, Parse>,
127 serialize_ctx: &mut AdapterContext<'_, Serialize>,
128 range: Option<&RegionRange>,
129 channel_flags: ChannelFlags,
130) -> Result<(), GvoxError> {
131 unsafe {
132 parse_ctx.context().execute_inner(|ctx| {
133 gvox_sys::gvox_blit_region(
134 if input_ctx.is_some() {
135 input_ctx.unwrap().as_mut_ptr()
136 } else {
137 std::ptr::null_mut() as *mut gvox_sys::GvoxAdapterContext
138 },
139 if output_ctx.is_some() {
140 output_ctx.unwrap().as_mut_ptr()
141 } else {
142 std::ptr::null_mut() as *mut gvox_sys::GvoxAdapterContext
143 },
144 parse_ctx.as_mut_ptr(),
145 serialize_ctx.as_mut_ptr(),
146 if range.is_some() {
147 range.unwrap() as *const RegionRange as *const gvox_sys::GvoxRegionRange
148 } else {
149 std::ptr::null() as *const gvox_sys::GvoxRegionRange
150 },
151 channel_flags.into(),
152 );
153
154 ctx.get_error()
155 })
156 }
157}
158
159pub fn blit_region_parse_driven(
161 input_ctx: Option<&mut AdapterContext<'_, Input>>,
162 output_ctx: Option<&mut AdapterContext<'_, Output>>,
163 parse_ctx: &mut AdapterContext<'_, Parse>,
164 serialize_ctx: &mut AdapterContext<'_, Serialize>,
165 range: Option<&RegionRange>,
166 channel_flags: ChannelFlags,
167) -> Result<(), GvoxError> {
168 unsafe {
169 parse_ctx.context().execute_inner(|ctx| {
170 gvox_sys::gvox_blit_region_parse_driven(
171 if input_ctx.is_some() {
172 input_ctx.unwrap().as_mut_ptr()
173 } else {
174 std::ptr::null_mut() as *mut gvox_sys::GvoxAdapterContext
175 },
176 if output_ctx.is_some() {
177 output_ctx.unwrap().as_mut_ptr()
178 } else {
179 std::ptr::null_mut() as *mut gvox_sys::GvoxAdapterContext
180 },
181 parse_ctx.as_mut_ptr(),
182 serialize_ctx.as_mut_ptr(),
183 if range.is_some() {
184 range.unwrap() as *const RegionRange as *const gvox_sys::GvoxRegionRange
185 } else {
186 std::ptr::null() as *const gvox_sys::GvoxRegionRange
187 },
188 channel_flags.into(),
189 );
190
191 ctx.get_error()
192 })
193 }
194}
195
196pub fn blit_region_serialize_driven(
198 input_ctx: Option<&mut AdapterContext<'_, Input>>,
199 output_ctx: Option<&mut AdapterContext<'_, Output>>,
200 parse_ctx: &mut AdapterContext<'_, Parse>,
201 serialize_ctx: &mut AdapterContext<'_, Serialize>,
202 range: Option<&RegionRange>,
203 channel_flags: ChannelFlags,
204) -> Result<(), GvoxError> {
205 unsafe {
206 parse_ctx.context().execute_inner(|ctx| {
207 gvox_sys::gvox_blit_region_serialize_driven(
208 if input_ctx.is_some() {
209 input_ctx.unwrap().as_mut_ptr()
210 } else {
211 std::ptr::null_mut() as *mut gvox_sys::GvoxAdapterContext
212 },
213 if output_ctx.is_some() {
214 output_ctx.unwrap().as_mut_ptr()
215 } else {
216 std::ptr::null_mut() as *mut gvox_sys::GvoxAdapterContext
217 },
218 parse_ctx.as_mut_ptr(),
219 serialize_ctx.as_mut_ptr(),
220 if range.is_some() {
221 range.unwrap() as *const RegionRange as *const gvox_sys::GvoxRegionRange
222 } else {
223 std::ptr::null() as *const gvox_sys::GvoxRegionRange
224 },
225 channel_flags.into(),
226 );
227
228 ctx.get_error()
229 })
230 }
231}
232
233#[derive(Clone, Debug, Default)]
236pub struct Context(Arc<Mutex<ContextInner>>);
237
238impl Context {
239 pub fn new() -> Self {
241 Self::default()
242 }
243
244 pub fn get_adapter<K: AdapterKind, A: AdapterDescriptor<K> + NamedAdapter>(
246 &self,
247 ) -> Result<Adapter<K, A>, GvoxError> {
248 let ptr = self.execute_inner(|ctx| ctx.get_raw_adapter::<K, A>())?;
249
250 Ok(Adapter {
251 ctx: self.clone(),
252 ptr,
253 data: PhantomData::default(),
254 })
255 }
256
257 pub fn register_adapter<
259 K: AdapterKind,
260 A: AdapterDescriptor<K> + NamedAdapter + private::RegisterableAdapter<K>,
261 >(
262 &self,
263 ) -> Result<Adapter<K, A>, GvoxError> {
264 self.execute_inner(|ctx| ctx.register_adapter::<K, A>())?;
265 self.get_adapter::<K, A>()
266 }
267
268 pub fn as_mut_ptr(&self) -> *mut gvox_sys::GvoxContext {
270 self.execute_inner(|ctx| ctx.ptr)
271 }
272
273 fn execute_inner<T>(&self, f: impl FnOnce(&mut ContextInner) -> T) -> T {
275 f(&mut self.0.lock().expect("Could not acquire context mutex."))
276 }
277}
278
279impl PartialEq for Context {
280 fn eq(&self, other: &Self) -> bool {
281 Arc::ptr_eq(&self.0, &other.0)
282 }
283}
284
285impl Eq for Context {}
286
287unsafe impl Send for Context {}
288unsafe impl Sync for Context {}
289
290#[derive(Clone, Debug)]
292struct ContextInner {
293 ptr: *mut gvox_sys::GvoxContext,
295 registered_adapter_types: FxHashMap<AdapterIdentifier, TypeId>,
297}
298
299impl ContextInner {
300 pub fn get_raw_adapter<K: AdapterKind, A: NamedAdapter>(
303 &self,
304 ) -> Result<*mut gvox_sys::GvoxAdapter, GvoxError> {
305 unsafe {
306 let adapter_type = self
307 .registered_adapter_types
308 .get(&AdapterIdentifier::new::<K, A>());
309 if adapter_type == Some(&TypeId::of::<A>()) {
310 let c_name =
311 CString::new(A::name()).expect("Failed to convert Rust string to C string");
312 let kind = TypeId::of::<K>();
313
314 let adapter = if kind == TypeId::of::<Input>() {
315 gvox_sys::gvox_get_input_adapter(self.ptr, c_name.as_ptr())
316 } else if kind == TypeId::of::<Output>() {
317 gvox_sys::gvox_get_output_adapter(self.ptr, c_name.as_ptr())
318 } else if kind == TypeId::of::<Parse>() {
319 gvox_sys::gvox_get_parse_adapter(self.ptr, c_name.as_ptr())
320 } else if kind == TypeId::of::<Serialize>() {
321 gvox_sys::gvox_get_serialize_adapter(self.ptr, c_name.as_ptr())
322 } else {
323 return Err(GvoxError::new(
324 ErrorType::Unknown,
325 "Unrecognized adapter type.".to_string(),
326 ));
327 };
328
329 self.get_error()
330 .and((!adapter.is_null()).then_some(adapter).ok_or_else(|| {
331 GvoxError::new(ErrorType::Unknown, "Adapter not found.".to_string())
332 }))
333 } else if adapter_type.is_some() {
334 Err(GvoxError::new(
335 ErrorType::InvalidParameter,
336 "The provided adapter was not of the correct type.".to_string(),
337 ))
338 } else {
339 Err(GvoxError::new(
340 ErrorType::InvalidParameter,
341 "The provided adapter was not found.".to_string(),
342 ))
343 }
344 }
345 }
346
347 fn register_adapter<K: AdapterKind, A: private::RegisterableAdapter<K>>(
349 &mut self,
350 ) -> Result<*mut gvox_sys::GvoxAdapter, GvoxError> {
351 unsafe {
352 let adapter = A::register_adapter(self.ptr)?;
353 self.add_external_adapter::<K, A>()?;
354 Ok(adapter)
355 }
356 }
357
358 pub unsafe fn create_raw_adapter_context(
365 &mut self,
366 adapter: *mut gvox_sys::GvoxAdapter,
367 config: *const c_void,
368 ) -> Result<*mut gvox_sys::GvoxAdapterContext, GvoxError> {
369 let result = gvox_sys::gvox_create_adapter_context(self.ptr, adapter, config);
370 self.get_error()?;
371 Ok(result)
372 }
373
374 pub unsafe fn add_external_adapter<K: AdapterKind, A: AdapterDescriptor<K> + NamedAdapter>(
384 &mut self,
385 ) -> Result<(), GvoxError> {
386 match self
387 .registered_adapter_types
388 .entry(AdapterIdentifier::new::<K, A>())
389 {
390 Entry::Vacant(v) => {
391 v.insert(TypeId::of::<A>());
392 Ok(())
393 }
394 Entry::Occupied(_) => Err(GvoxError::new(
395 ErrorType::InvalidParameter,
396 "Attempted to register duplicate adapter.".to_string(),
397 )),
398 }
399 }
400
401 fn add_default_adapters(&mut self) -> Result<(), GvoxError> {
403 unsafe {
404 self.add_external_adapter::<Input, adapters::ByteBuffer>()?;
405 self.add_external_adapter::<Output, adapters::ByteBuffer>()?;
406 self.add_external_adapter::<Output, adapters::StdOut>()?;
407 self.add_external_adapter::<Parse, adapters::GvoxPalette>()?;
408 self.add_external_adapter::<Parse, adapters::GvoxRaw>()?;
409 self.add_external_adapter::<Parse, adapters::GvoxBrickmap>()?;
410 self.add_external_adapter::<Parse, adapters::GvoxGlobalPalette>()?;
411 self.add_external_adapter::<Parse, adapters::GvoxOctree>()?;
412 self.add_external_adapter::<Parse, adapters::GvoxRunLengthEncoding>()?;
413 self.add_external_adapter::<Parse, adapters::MagicaVoxel>()?;
414 self.add_external_adapter::<Parse, adapters::Voxlap>()?;
415 self.add_external_adapter::<Parse, adapters::Kvx>()?;
416 self.add_external_adapter::<Serialize, adapters::ColoredText>()?;
417 self.add_external_adapter::<Serialize, adapters::GvoxPalette>()?;
418 self.add_external_adapter::<Serialize, adapters::GvoxRaw>()?;
419 self.add_external_adapter::<Serialize, adapters::GvoxBrickmap>()?;
420 self.add_external_adapter::<Serialize, adapters::GvoxGlobalPalette>()?;
421 self.add_external_adapter::<Serialize, adapters::GvoxOctree>()?;
422 self.add_external_adapter::<Serialize, adapters::GvoxRunLengthEncoding>()?;
423
424 Ok(())
425 }
426 }
427
428 fn get_error(&self) -> Result<(), GvoxError> {
430 unsafe { Self::get_error_from_raw_ptr(self.ptr) }
431 }
432
433 pub unsafe fn get_error_from_raw_ptr(ptr: *mut gvox_sys::GvoxContext) -> Result<(), GvoxError> {
435 let mut result = Ok(());
436
437 let mut code = gvox_sys::gvox_get_result(ptr);
438 let mut buf = Vec::new();
439 while code != gvox_sys::GvoxResult_GVOX_RESULT_SUCCESS {
440 let mut msg_size = 0;
441 gvox_sys::gvox_get_result_message(ptr, std::ptr::null_mut(), &mut msg_size);
442 buf.resize(msg_size, 0);
443 gvox_sys::gvox_get_result_message(ptr, buf.as_mut_ptr() as *mut i8, &mut msg_size);
444
445 result = Err(GvoxError::new(ErrorType::from(code),
446 std::str::from_utf8(buf.as_slice())
447 .unwrap_or_default()
448 .to_string(),
449 ));
450
451 gvox_sys::gvox_pop_result(ptr);
452 code = gvox_sys::gvox_get_result(ptr);
453 }
454
455 result
456 }
457}
458
459impl Default for ContextInner {
460 fn default() -> Self {
461 unsafe {
462 let ptr = gvox_sys::gvox_create_context();
463 let registered_adapter_types = FxHashMap::default();
464 let mut res = Self {
465 ptr,
466 registered_adapter_types,
467 };
468 res.add_default_adapters()
469 .expect("Could not add default adapters to gvox context.");
470
471 res
472 }
473 }
474}
475
476impl Drop for ContextInner {
477 fn drop(&mut self) {
478 unsafe { gvox_sys::gvox_destroy_context(self.ptr) }
479 }
480}
481
482#[derive(Clone, Debug, PartialEq, Eq, Hash)]
484struct AdapterIdentifier {
485 name: &'static str,
487 kind: TypeId,
489}
490
491impl AdapterIdentifier {
492 pub fn new<K: AdapterKind, A: NamedAdapter>() -> Self {
494 Self {
495 name: A::name(),
496 kind: TypeId::of::<K>(),
497 }
498 }
499}
500
501#[derive(Clone, Debug, PartialEq, Eq)]
503pub struct Adapter<K: AdapterKind, A: AdapterDescriptor<K>> {
504 ctx: Context,
506 ptr: *mut gvox_sys::GvoxAdapter,
508 data: PhantomData<(K, A)>,
510}
511
512impl<K: AdapterKind, A: AdapterDescriptor<K>> Adapter<K, A> {
513 pub fn context(&self) -> Context {
515 self.ctx.clone()
516 }
517
518 pub fn create_adapter_context<'a>(
520 &self,
521 config: A::Configuration<'a>,
522 ) -> Result<AdapterContext<'a, K>, GvoxError> {
523 unsafe {
524 let ctx = self.context();
525 let ptr = self.ctx.execute_inner(|ctx| {
526 ctx.create_raw_adapter_context(
527 self.ptr,
528 &config as *const A::Configuration<'a> as *const c_void,
529 )
530 })?;
531
532 if !ExternalHandler::is_external::<K, A>() {
533 AdapterContextHolder::from_raw(ptr)
534 .get_context_data()
535 .expect("No user data was associated with context.")
536 .ctx = self.ctx.as_mut_ptr();
537 }
538
539 Ok(AdapterContext {
540 ctx,
541 ptr,
542 data: PhantomData::default(),
543 })
544 }
545 }
546
547 pub fn as_mut_ptr(&mut self) -> *mut gvox_sys::GvoxAdapter {
549 self.ptr
550 }
551}
552
553#[derive(Debug, PartialEq, Eq)]
555pub struct AdapterContext<'a, K: AdapterKind> {
556 ctx: Context,
558 ptr: *mut gvox_sys::GvoxAdapterContext,
560 data: PhantomData<(&'a (), K)>,
562}
563
564impl<'a, K: AdapterKind> AdapterContext<'a, K> {
565 pub fn context(&self) -> Context {
567 self.ctx.clone()
568 }
569
570 pub fn as_mut_ptr(&mut self) -> *mut gvox_sys::GvoxAdapterContext {
572 self.ptr
573 }
574}
575
576impl<'a, K: AdapterKind> Drop for AdapterContext<'a, K> {
577 fn drop(&mut self) {
578 unsafe {
579 gvox_sys::gvox_destroy_adapter_context(self.as_mut_ptr());
580 }
581 }
582}
583
584pub trait AdapterKind: 'static + private::Sealed {}
586
587#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
589pub struct Input;
590
591impl AdapterKind for Input {}
592
593#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
595pub struct Output;
596
597impl AdapterKind for Output {}
598
599#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
601pub struct Parse;
602
603impl AdapterKind for Parse {}
604
605#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
607pub struct Serialize;
608
609impl AdapterKind for Serialize {}
610
611#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
613pub struct ExternalHandler;
614
615impl ExternalHandler {
616 pub fn is_external<K: AdapterKind, A: AdapterDescriptor<K>>() -> bool {
618 TypeId::of::<Self>() == TypeId::of::<A::Handler>()
619 }
620}
621
622pub trait AdapterDescriptor<K: AdapterKind>: 'static {
624 type Configuration<'a>;
626 type Handler: ?Sized;
628}
629
630pub trait NamedAdapter: 'static {
632 fn name() -> &'static str;
634}
635
636struct AdapterContextData {
638 pub ctx: *mut gvox_sys::GvoxContext,
640 pub user_data: Option<Box<dyn Any>>,
642}
643
644struct AdapterContextHolder(*mut gvox_sys::GvoxAdapterContext);
646
647impl AdapterContextHolder {
648 pub unsafe fn from_raw(ctx: *mut gvox_sys::GvoxAdapterContext) -> Self {
657 Self(ctx)
658 }
659
660 pub fn context_mut_ptr(&mut self) -> *mut gvox_sys::GvoxContext {
662 self.get_context_data()
663 .expect("No data was associated with the given adapter context.")
664 .ctx
665 }
666
667 pub fn push_error(&mut self, error: GvoxError) {
669 unsafe {
670 let message = CString::new(error.message.as_str()).unwrap_or_default();
671 gvox_sys::gvox_adapter_push_error(self.0, error.error_type() as i32, message.as_ptr());
672 }
673 }
674
675 pub fn user_data_operation<H: 'static>(
677 &mut self,
678 f: impl FnOnce(&mut H) -> Result<(), GvoxError>,
679 ) {
680 let mut result = Ok(());
681 if let Some(data) = self.get_user_data_holder() {
682 result = f(data
683 .downcast_mut::<H>()
684 .expect("Context user data was not of correct type."));
685 }
686
687 if let Err(error) = result {
688 self.push_error(error);
689 }
690 }
691
692 pub fn get_user_data_holder(&mut self) -> &mut Option<Box<dyn Any>> {
694 &mut self
695 .get_context_data()
696 .expect("No data was associated with the given adapter context.")
697 .user_data
698 }
699
700 fn get_context_data(&mut self) -> Option<&mut AdapterContextData> {
702 unsafe {
703 let res = gvox_sys::gvox_adapter_get_user_pointer(self.0) as *mut AdapterContextData;
704 (!res.is_null()).then(|| &mut *res)
705 }
706 }
707
708 fn set_context_data(&mut self, data: Option<AdapterContextData>) -> Option<AdapterContextData> {
710 unsafe {
711 let res = gvox_sys::gvox_adapter_get_user_pointer(self.0) as *mut AdapterContextData;
712 gvox_sys::gvox_adapter_set_user_pointer(
713 self.0,
714 data.map(|x| Box::into_raw(Box::new(x)) as *mut c_void)
715 .unwrap_or(std::ptr::null_mut()),
716 );
717 (!res.is_null()).then(|| *Box::from_raw(res))
718 }
719 }
720
721 unsafe extern "C" fn create<K: private::AdapterKindAssociation, D: AdapterDescriptor<K>>(
728 ptr: *mut gvox_sys::GvoxAdapterContext,
729 config: *const c_void,
730 ) where
731 D::Handler: BaseAdapterHandler<K, D>,
732 {
733 let mut ctx = Self::from_raw(ptr);
734 ctx.set_context_data(Some(AdapterContextData {
735 ctx: std::ptr::null_mut(),
736 user_data: None,
737 }));
738
739 match D::Handler::create(&*(config as *const D::Configuration<'_>)) {
740 Ok(value) => *ctx.get_user_data_holder() = Some(Box::new(value)),
741 Err(error) => ctx.push_error(error),
742 };
743 }
744
745 unsafe extern "C" fn destroy<K: private::AdapterKindAssociation, D: AdapterDescriptor<K>>(
752 ctx: *mut gvox_sys::GvoxAdapterContext,
753 ) where
754 D::Handler: BaseAdapterHandler<K, D>,
755 {
756 let mut ctx = Self::from_raw(ctx);
757 let data = take(ctx.get_user_data_holder());
758
759 if let Some(value) = data {
760 if let Err(error) = value
761 .downcast::<D::Handler>()
762 .expect("Context user data was not of correct type.")
763 .destroy()
764 {
765 ctx.push_error(error);
766 }
767 }
768
769 ctx.set_context_data(None);
770 }
771
772 unsafe extern "C" fn blit_begin<K: private::AdapterKindAssociation, D: AdapterDescriptor<K>>(
778 blit_ctx: *mut gvox_sys::GvoxBlitContext,
779 ctx: *mut gvox_sys::GvoxAdapterContext,
780 range: *const gvox_sys::GvoxRegionRange,
781 channel_flags: u32,
782 ) where
783 D::Handler: BaseAdapterHandler<K, D>,
784 {
785 use private::*;
786
787 let mut ctx = Self::from_raw(ctx);
788 let blit_ctx = K::BlitContext::new(ctx.context_mut_ptr(), blit_ctx);
789
790 let mut_range;
791 let opt_range = if range.is_null() {
792 None
793 } else {
794 mut_range = (*range).into();
795 Some(&mut_range)
796 };
797
798 ctx.user_data_operation::<D::Handler>(|h| {
799 h.blit_begin(&blit_ctx, opt_range, channel_flags.into())
800 });
801 }
802
803 unsafe extern "C" fn blit_end<K: private::AdapterKindAssociation, D: AdapterDescriptor<K>>(
809 blit_ctx: *mut gvox_sys::GvoxBlitContext,
810 ctx: *mut gvox_sys::GvoxAdapterContext,
811 ) where
812 D::Handler: BaseAdapterHandler<K, D>,
813 {
814 use private::*;
815
816 let mut ctx = Self::from_raw(ctx);
817 let blit_ctx = K::BlitContext::new(ctx.context_mut_ptr(), blit_ctx);
818
819 ctx.user_data_operation::<D::Handler>(|h| h.blit_end(&blit_ctx));
820 }
821}
822
823struct InputContextHolder(AdapterContextHolder);
825
826impl InputContextHolder {
827 unsafe fn from_raw(ctx: *mut gvox_sys::GvoxAdapterContext) -> Self {
835 Self(AdapterContextHolder::from_raw(ctx))
836 }
837
838 unsafe extern "C" fn read<D: AdapterDescriptor<Input>>(
845 ctx: *mut gvox_sys::GvoxAdapterContext,
846 position: usize,
847 size: usize,
848 data: *mut c_void,
849 ) where
850 D::Handler: InputAdapterHandler<D>,
851 {
852 let mut ctx = Self::from_raw(ctx);
853 let blit_ctx = InputBlitContext {};
854
855 ctx.0.user_data_operation::<D::Handler>(|h| {
856 h.read(
857 &blit_ctx,
858 position,
859 from_raw_parts_mut(data as *mut u8, size),
860 )
861 });
862 }
863}
864
865struct OutputContextHolder(AdapterContextHolder);
867
868impl OutputContextHolder {
869 unsafe fn from_raw(ctx: *mut gvox_sys::GvoxAdapterContext) -> Self {
877 Self(AdapterContextHolder::from_raw(ctx))
878 }
879
880 unsafe extern "C" fn write<D: AdapterDescriptor<Output>>(
887 ctx: *mut gvox_sys::GvoxAdapterContext,
888 position: usize,
889 size: usize,
890 data: *const c_void,
891 ) where
892 D::Handler: OutputAdapterHandler<D>,
893 {
894 let mut ctx = Self::from_raw(ctx);
895 let blit_ctx = OutputBlitContext {};
896
897 ctx.0.user_data_operation::<D::Handler>(|h| {
898 h.write(&blit_ctx, position, from_raw_parts(data as *const u8, size))
899 });
900 }
901
902 unsafe extern "C" fn reserve<D: AdapterDescriptor<Output>>(
908 ctx: *mut gvox_sys::GvoxAdapterContext,
909 size: usize,
910 ) where
911 D::Handler: OutputAdapterHandler<D>,
912 {
913 let mut ctx = Self::from_raw(ctx);
914 let blit_ctx = OutputBlitContext {};
915
916 ctx.0
917 .user_data_operation::<D::Handler>(|h| h.reserve(&blit_ctx, size));
918 }
919}
920
921struct ParseContextHolder(AdapterContextHolder);
923
924impl ParseContextHolder {
925 unsafe fn from_raw(ctx: *mut gvox_sys::GvoxAdapterContext) -> Self {
933 Self(AdapterContextHolder::from_raw(ctx))
934 }
935
936 unsafe extern "C" fn query_details<D: AdapterDescriptor<Parse>>(
938 ) -> gvox_sys::GvoxParseAdapterDetails
939 where
940 D::Handler: ParseAdapterHandler<D>,
941 {
942 let details = D::Handler::query_details();
943 gvox_sys::GvoxParseAdapterDetails {
944 preferred_blit_mode: details.preferred_blit_mode as i32,
945 }
946 }
947
948 unsafe extern "C" fn query_parsable_range<D: AdapterDescriptor<Parse>>(
955 blit_ctx: *mut gvox_sys::GvoxBlitContext,
956 ctx: *mut gvox_sys::GvoxAdapterContext,
957 ) -> gvox_sys::GvoxRegionRange
958 where
959 D::Handler: ParseAdapterHandler<D>,
960 {
961 use private::*;
962 let mut ctx = Self::from_raw(ctx);
963 let blit_ctx = ParseBlitContext::new(ctx.0.context_mut_ptr(), blit_ctx);
964
965 let mut res = RegionRange::default();
966 ctx.0.user_data_operation::<D::Handler>(|h| {
967 res = h.query_parsable_range(&blit_ctx);
968 Ok(())
969 });
970
971 res.into()
972 }
973
974 unsafe extern "C" fn query_region_flags<D: AdapterDescriptor<Parse>>(
981 blit_ctx: *mut gvox_sys::GvoxBlitContext,
982 ctx: *mut gvox_sys::GvoxAdapterContext,
983 range: *const gvox_sys::GvoxRegionRange,
984 channel_flags: u32,
985 ) -> u32
986 where
987 D::Handler: ParseAdapterHandler<D>,
988 {
989 use private::*;
990
991 let mut ctx = Self::from_raw(ctx);
992 let blit_ctx = ParseBlitContext::new(ctx.0.context_mut_ptr(), blit_ctx);
993
994 let mut res = 0;
995 ctx.0.user_data_operation::<D::Handler>(|h| {
996 res = h
997 .query_region_flags(&blit_ctx, &(*range).into(), channel_flags.into())?
998 .bits();
999 Ok(())
1000 });
1001
1002 res
1003 }
1004
1005 unsafe extern "C" fn load_region<D: AdapterDescriptor<Parse>>(
1012 blit_ctx: *mut gvox_sys::GvoxBlitContext,
1013 ctx: *mut gvox_sys::GvoxAdapterContext,
1014 range: *const gvox_sys::GvoxRegionRange,
1015 channel_flags: u32,
1016 ) -> gvox_sys::GvoxRegion
1017 where
1018 D::Handler: ParseAdapterHandler<D>,
1019 {
1020 use private::*;
1021
1022 let mut ctx = Self::from_raw(ctx);
1023 let blit_ctx = ParseBlitContext::new(ctx.0.context_mut_ptr(), blit_ctx);
1024
1025 let mut res = gvox_sys::GvoxRegion {
1026 range: RegionRange::default().into(),
1027 channels: 0,
1028 flags: 0,
1029 data: std::ptr::null_mut(),
1030 };
1031 ctx.0.user_data_operation::<D::Handler>(|h| {
1032 res = h
1033 .load_region(&blit_ctx, &(*range).into(), channel_flags.into())?
1034 .into();
1035 Ok(())
1036 });
1037 res
1038 }
1039
1040 unsafe extern "C" fn unload_region<D: AdapterDescriptor<Parse>>(
1047 blit_ctx: *mut gvox_sys::GvoxBlitContext,
1048 ctx: *mut gvox_sys::GvoxAdapterContext,
1049 region: *mut gvox_sys::GvoxRegion,
1050 ) where
1051 D::Handler: ParseAdapterHandler<D>,
1052 {
1053 use private::*;
1054
1055 let mut ctx = Self::from_raw(ctx);
1056 let blit_ctx = ParseBlitContext::new(ctx.0.context_mut_ptr(), blit_ctx);
1057
1058 ctx.0
1059 .user_data_operation::<D::Handler>(|h| h.unload_region(&blit_ctx, transmute(*region)));
1060 (*region).range = RegionRange::default().into();
1061 }
1062
1063 unsafe extern "C" fn sample_region<D: AdapterDescriptor<Parse>>(
1070 blit_ctx: *mut gvox_sys::GvoxBlitContext,
1071 ctx: *mut gvox_sys::GvoxAdapterContext,
1072 region: *const gvox_sys::GvoxRegion,
1073 offset: *const gvox_sys::GvoxOffset3D,
1074 channel_id: u32,
1075 ) -> gvox_sys::GvoxSample
1076 where
1077 D::Handler: ParseAdapterHandler<D>,
1078 {
1079 use private::*;
1080
1081 let mut ctx = Self::from_raw(ctx);
1082 let blit_ctx = ParseBlitContext::new(ctx.0.context_mut_ptr(), blit_ctx);
1083
1084 let mut res = Sample {
1085 data: 0,
1086 is_present: false,
1087 };
1088 ctx.0.user_data_operation::<D::Handler>(|h| {
1089 res = h.sample_region(
1090 &blit_ctx,
1091 &*transmute::<_, *const Region<<D::Handler as ParseAdapterHandler<D>>::RegionData>>(
1092 region,
1093 ),
1094 &(*offset).into(),
1095 ChannelId::try_from(channel_id)?,
1096 )?;
1097 Ok(())
1098 });
1099 gvox_sys::GvoxSample {
1100 data: res.data,
1101 is_present: res.is_present as u8,
1102 }
1103 }
1104
1105 unsafe extern "C" fn parse_region<D: AdapterDescriptor<Parse>>(
1106 blit_ctx: *mut gvox_sys::GvoxBlitContext,
1107 ctx: *mut gvox_sys::GvoxAdapterContext,
1108 range: *const gvox_sys::GvoxRegionRange,
1109 channel_flags: u32,
1110 ) where
1111 D::Handler: ParseAdapterHandler<D>,
1112 {
1113 use private::*;
1114
1115 let mut ctx = Self::from_raw(ctx);
1116 let blit_ctx = ParseBlitContext::new(ctx.0.context_mut_ptr(), blit_ctx);
1117
1118 ctx.0.user_data_operation::<D::Handler>(|h| {
1119 h.parse_region(&blit_ctx, &(*range).into(), channel_flags.into())
1120 });
1121 }
1122}
1123
1124struct SerializeContextHolder(AdapterContextHolder);
1126
1127impl SerializeContextHolder {
1128 unsafe fn from_raw(ctx: *mut gvox_sys::GvoxAdapterContext) -> Self {
1136 Self(AdapterContextHolder::from_raw(ctx))
1137 }
1138
1139 unsafe extern "C" fn serialize_region<D: AdapterDescriptor<Serialize>>(
1146 blit_ctx: *mut gvox_sys::GvoxBlitContext,
1147 ctx: *mut gvox_sys::GvoxAdapterContext,
1148 range: *const gvox_sys::GvoxRegionRange,
1149 channel_flags: u32,
1150 ) where
1151 D::Handler: SerializeAdapterHandler<D>,
1152 {
1153 use private::*;
1154
1155 let mut ctx = Self::from_raw(ctx);
1156 let blit_ctx = SerializeBlitContext::new(ctx.0.context_mut_ptr(), blit_ctx);
1157
1158 ctx.0.user_data_operation::<D::Handler>(|h| {
1159 h.serialize_region(
1160 &blit_ctx,
1161 &(*range).into(),
1162 ChannelFlags::from(channel_flags),
1163 )
1164 });
1165 }
1166
1167 unsafe extern "C" fn receive_region<D: AdapterDescriptor<Serialize>>(
1174 blit_ctx: *mut gvox_sys::GvoxBlitContext,
1175 ctx: *mut gvox_sys::GvoxAdapterContext,
1176 region: *const gvox_sys::GvoxRegion,
1177 ) where
1178 D::Handler: SerializeAdapterHandler<D>,
1179 {
1180 use private::*;
1181
1182 let mut ctx = Self::from_raw(ctx);
1183 let blit_ctx = SerializeBlitContext::new(ctx.0.context_mut_ptr(), blit_ctx);
1184
1185 let region_ref = RegionRef {
1186 blit_ctx: &blit_ctx,
1187 region: *region,
1188 };
1189
1190 ctx.0
1191 .user_data_operation::<D::Handler>(|h| h.receive_region(&blit_ctx, ®ion_ref));
1192
1193 std::mem::forget(region_ref);
1194 }
1195}
1196
1197pub struct InputBlitContext {}
1199
1200pub struct OutputBlitContext {}
1202
1203pub struct ParseBlitContext {
1205 blit_ctx: *mut gvox_sys::GvoxBlitContext,
1207 ctx: *mut gvox_sys::GvoxContext,
1209}
1210
1211impl ParseBlitContext {
1212 pub fn input_read(&self, position: usize, data: &mut [u8]) -> Result<(), GvoxError> {
1214 unsafe {
1215 gvox_sys::gvox_input_read(
1216 self.blit_ctx,
1217 position,
1218 data.len(),
1219 data.as_mut_ptr() as *mut c_void,
1220 );
1221 ContextInner::get_error_from_raw_ptr(self.ctx)
1222 }
1223 }
1224
1225 pub fn emit_region<T>(&self, region: &Region<T>) -> Result<(), GvoxError> {
1227 unsafe {
1228 gvox_sys::gvox_emit_region(
1229 self.blit_ctx,
1230 region as *const Region<T> as *const gvox_sys::GvoxRegion,
1231 );
1232 ContextInner::get_error_from_raw_ptr(self.ctx)
1233 }
1234 }
1235}
1236
1237pub struct SerializeBlitContext {
1239 blit_ctx: *mut gvox_sys::GvoxBlitContext,
1241 ctx: *mut gvox_sys::GvoxContext,
1243}
1244
1245impl SerializeBlitContext {
1246 pub fn query_region_flags(
1248 &self,
1249 range: &RegionRange,
1250 channel_flags: ChannelFlags,
1251 ) -> Result<RegionFlags, GvoxError> {
1252 unsafe {
1253 let flags = gvox_sys::gvox_query_region_flags(
1254 self.blit_ctx,
1255 range as *const RegionRange as *const gvox_sys::GvoxRegionRange,
1256 channel_flags.into(),
1257 );
1258 ContextInner::get_error_from_raw_ptr(self.ctx)
1259 .map(|()| RegionFlags::from_bits_truncate(flags))
1260 }
1261 }
1262
1263 pub fn load_region_range<'a>(
1265 &'a self,
1266 range: &RegionRange,
1267 channel_flags: ChannelFlags,
1268 ) -> Result<RegionRef<'a>, GvoxError> {
1269 unsafe {
1270 let region = gvox_sys::gvox_load_region_range(
1271 self.blit_ctx,
1272 &(*range).into(),
1273 channel_flags.into(),
1274 );
1275 ContextInner::get_error_from_raw_ptr(self.ctx).map(|()| RegionRef {
1276 blit_ctx: self,
1277 region,
1278 })
1279 }
1280 }
1281
1282 pub fn output_write(&self, position: usize, data: &[u8]) -> Result<(), GvoxError> {
1284 unsafe {
1285 gvox_sys::gvox_output_write(
1286 self.blit_ctx,
1287 position,
1288 data.len(),
1289 data.as_ptr() as *const c_void,
1290 );
1291 ContextInner::get_error_from_raw_ptr(self.ctx)
1292 }
1293 }
1294
1295 pub fn output_reserve(&self, size: usize) -> Result<(), GvoxError> {
1297 unsafe {
1298 gvox_sys::gvox_output_reserve(self.blit_ctx, size);
1299 ContextInner::get_error_from_raw_ptr(self.ctx)
1300 }
1301 }
1302}
1303
1304pub trait BaseAdapterHandler<
1306 K: AdapterKind + private::AdapterKindAssociation,
1307 D: AdapterDescriptor<K, Handler = Self>,
1308>: 'static + Sized
1309{
1310 fn create(config: &D::Configuration<'_>) -> Result<Self, GvoxError>;
1312 fn destroy(self) -> Result<(), GvoxError>;
1314
1315 fn blit_begin(
1317 &mut self,
1318 _: &K::BlitContext,
1319 _: Option<&RegionRange>,
1320 _: ChannelFlags,
1321 ) -> Result<(), GvoxError> {
1322 Ok(())
1323 }
1324 fn blit_end(&mut self, _: &K::BlitContext) -> Result<(), GvoxError> {
1326 Ok(())
1327 }
1328}
1329
1330pub trait InputAdapterHandler<D: AdapterDescriptor<Input, Handler = Self>>:
1332 BaseAdapterHandler<Input, D>
1333{
1334 fn read(
1336 &mut self,
1337 blit_ctx: &InputBlitContext,
1338 position: usize,
1339 data: &mut [u8],
1340 ) -> Result<(), GvoxError>;
1341}
1342
1343pub trait OutputAdapterHandler<D: AdapterDescriptor<Output, Handler = Self>>:
1345 BaseAdapterHandler<Output, D>
1346{
1347 fn write(
1349 &mut self,
1350 blit_ctx: &OutputBlitContext,
1351 position: usize,
1352 data: &[u8],
1353 ) -> Result<(), GvoxError>;
1354 fn reserve(&mut self, blit_ctx: &OutputBlitContext, size: usize) -> Result<(), GvoxError>;
1356}
1357
1358pub trait ParseAdapterHandler<D: AdapterDescriptor<Parse, Handler = Self>>:
1360 BaseAdapterHandler<Parse, D>
1361{
1362 type RegionData;
1364
1365 fn query_details() -> ParseAdapterDetails;
1367 fn query_parsable_range(&mut self, blit_ctx: &ParseBlitContext) -> RegionRange;
1369 fn query_region_flags(
1371 &mut self,
1372 blit_ctx: &ParseBlitContext,
1373 range: &RegionRange,
1374 channel_flags: ChannelFlags,
1375 ) -> Result<RegionFlags, GvoxError>;
1376 fn load_region(
1378 &mut self,
1379 blit_ctx: &ParseBlitContext,
1380 range: &RegionRange,
1381 channel_flags: ChannelFlags,
1382 ) -> Result<Region<Self::RegionData>, GvoxError>;
1383 fn unload_region(
1385 &mut self,
1386 blit_ctx: &ParseBlitContext,
1387 region: Region<Self::RegionData>,
1388 ) -> Result<(), GvoxError>;
1389 fn sample_region(
1391 &mut self,
1392 blit_ctx: &ParseBlitContext,
1393 region: &Region<Self::RegionData>,
1394 offset: &Offset3D,
1395 channel_id: ChannelId,
1396 ) -> Result<Sample, GvoxError>;
1397 fn parse_region(
1399 &mut self,
1400 blit_ctx: &ParseBlitContext,
1401 range: &RegionRange,
1402 channel_flags: ChannelFlags,
1403 ) -> Result<(), GvoxError>;
1404}
1405
1406pub trait SerializeAdapterHandler<D: AdapterDescriptor<Serialize, Handler = Self>>:
1408 BaseAdapterHandler<Serialize, D>
1409{
1410 type RegionData;
1412
1413 fn serialize_region(
1415 &mut self,
1416 blit_ctx: &SerializeBlitContext,
1417 range: &RegionRange,
1418 channel_flags: ChannelFlags,
1419 ) -> Result<(), GvoxError>;
1420
1421 fn receive_region(
1423 &mut self,
1424 blit_ctx: &SerializeBlitContext,
1425 region: &RegionRef<'_>,
1426 ) -> Result<(), GvoxError>;
1427}
1428
1429#[derive(Clone, Debug, Default)]
1431#[repr(C)]
1432pub struct Region<T> {
1433 pub range: RegionRange,
1435 pub channels: ChannelFlags,
1437 pub flags: RegionFlags,
1439 data: Box<T>,
1441}
1442
1443impl<T> Region<T> {
1444 pub fn new(range: RegionRange, channels: ChannelFlags, flags: RegionFlags, data: T) -> Self {
1446 let data = Box::new(data);
1447 Self {
1448 range,
1449 channels,
1450 flags,
1451 data,
1452 }
1453 }
1454}
1455
1456impl<T> Deref for Region<T> {
1457 type Target = T;
1458
1459 fn deref(&self) -> &Self::Target {
1460 &self.data
1461 }
1462}
1463
1464impl<T> DerefMut for Region<T> {
1465 fn deref_mut(&mut self) -> &mut Self::Target {
1466 &mut self.data
1467 }
1468}
1469
1470impl<T> From<Region<T>> for gvox_sys::GvoxRegion {
1471 fn from(value: Region<T>) -> Self {
1472 unsafe { transmute(value) }
1473 }
1474}
1475
1476pub struct RegionRef<'a> {
1478 blit_ctx: &'a SerializeBlitContext,
1480 region: gvox_sys::GvoxRegion,
1482}
1483
1484impl<'a> RegionRef<'a> {
1485 pub fn channels(&self) -> ChannelFlags {
1487 ChannelFlags::from(self.region.channels)
1488 }
1489
1490 pub fn flags(&self) -> RegionFlags {
1492 RegionFlags::from_bits_truncate(self.region.flags)
1493 }
1494
1495 pub fn range(&self) -> RegionRange {
1497 self.region.range.into()
1498 }
1499
1500 pub fn sample(&self, offset: &Offset3D, channel_id: ChannelId) -> Result<Sample, GvoxError> {
1502 unsafe {
1503 let res = gvox_sys::gvox_sample_region(
1504 self.blit_ctx.blit_ctx,
1505 &self.region as *const gvox_sys::GvoxRegion as *mut gvox_sys::GvoxRegion,
1506 &(*offset).into(),
1507 channel_id.into(),
1508 );
1509 ContextInner::get_error_from_raw_ptr(self.blit_ctx.ctx).map(|()| Sample {
1510 data: res.data,
1511 is_present: res.is_present != 0,
1512 })
1513 }
1514 }
1515}
1516
1517impl<'a> Drop for RegionRef<'a> {
1518 fn drop(&mut self) {
1519 unsafe {
1520 gvox_sys::gvox_unload_region_range(
1521 self.blit_ctx.blit_ctx,
1522 &mut self.region,
1523 &self.region.range,
1524 );
1525 }
1526 }
1527}
1528
1529#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
1531#[repr(C)]
1532pub struct Offset3D {
1533 pub x: i32,
1535 pub y: i32,
1537 pub z: i32,
1539}
1540
1541impl From<gvox_sys::GvoxOffset3D> for Offset3D {
1542 fn from(value: gvox_sys::GvoxOffset3D) -> Self {
1543 let gvox_sys::GvoxOffset3D { x, y, z } = value;
1544 Self { x, y, z }
1545 }
1546}
1547
1548impl From<Offset3D> for gvox_sys::GvoxOffset3D {
1549 fn from(value: Offset3D) -> Self {
1550 let Offset3D { x, y, z } = value;
1551 Self { x, y, z }
1552 }
1553}
1554
1555#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
1557#[repr(C)]
1558pub struct Extent3D {
1559 pub x: u32,
1561 pub y: u32,
1563 pub z: u32,
1565}
1566
1567impl From<gvox_sys::GvoxExtent3D> for Extent3D {
1568 fn from(value: gvox_sys::GvoxExtent3D) -> Self {
1569 let gvox_sys::GvoxExtent3D { x, y, z } = value;
1570 Self { x, y, z }
1571 }
1572}
1573
1574impl From<Extent3D> for gvox_sys::GvoxExtent3D {
1575 fn from(value: Extent3D) -> Self {
1576 let Extent3D { x, y, z } = value;
1577 Self { x, y, z }
1578 }
1579}
1580
1581#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
1583#[repr(C)]
1584pub struct RegionRange {
1585 pub offset: Offset3D,
1587 pub extent: Extent3D,
1589}
1590
1591impl From<gvox_sys::GvoxRegionRange> for RegionRange {
1592 fn from(value: gvox_sys::GvoxRegionRange) -> Self {
1593 Self {
1594 offset: value.offset.into(),
1595 extent: value.extent.into(),
1596 }
1597 }
1598}
1599
1600impl From<RegionRange> for gvox_sys::GvoxRegionRange {
1601 fn from(value: RegionRange) -> Self {
1602 Self {
1603 offset: value.offset.into(),
1604 extent: value.extent.into(),
1605 }
1606 }
1607}
1608
1609#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1611#[repr(i32)]
1612pub enum ErrorType {
1613 Unknown = gvox_sys::GvoxResult_GVOX_RESULT_ERROR_UNKNOWN,
1615 InvalidParameter = gvox_sys::GvoxResult_GVOX_RESULT_ERROR_INVALID_PARAMETER,
1617 InputAdapter = gvox_sys::GvoxResult_GVOX_RESULT_ERROR_INPUT_ADAPTER,
1619 OutputAdapter = gvox_sys::GvoxResult_GVOX_RESULT_ERROR_OUTPUT_ADAPTER,
1621 ParseAdapter = gvox_sys::GvoxResult_GVOX_RESULT_ERROR_PARSE_ADAPTER,
1623 SerializeAdapter = gvox_sys::GvoxResult_GVOX_RESULT_ERROR_SERIALIZE_ADAPTER,
1625 ParseAdapterInvalidInput = gvox_sys::GvoxResult_GVOX_RESULT_ERROR_PARSE_ADAPTER_INVALID_INPUT,
1627 ParseAdapterRequestedChannelNotPresent =
1629 gvox_sys::GvoxResult_GVOX_RESULT_ERROR_PARSE_ADAPTER_REQUESTED_CHANNEL_NOT_PRESENT,
1630 SerializeAdapterUnrepresentableData =
1632 gvox_sys::GvoxResult_GVOX_RESULT_ERROR_SERIALIZE_ADAPTER_UNREPRESENTABLE_DATA,
1633}
1634
1635impl From<i32> for ErrorType {
1636 fn from(value: i32) -> Self {
1637 match value {
1638 gvox_sys::GvoxResult_GVOX_RESULT_ERROR_UNKNOWN => Self::Unknown,
1639 gvox_sys::GvoxResult_GVOX_RESULT_ERROR_INVALID_PARAMETER => Self::InvalidParameter,
1640 gvox_sys::GvoxResult_GVOX_RESULT_ERROR_INPUT_ADAPTER => Self::InputAdapter,
1641 gvox_sys::GvoxResult_GVOX_RESULT_ERROR_OUTPUT_ADAPTER => Self::OutputAdapter,
1642 gvox_sys::GvoxResult_GVOX_RESULT_ERROR_PARSE_ADAPTER => Self::ParseAdapter,
1643 gvox_sys::GvoxResult_GVOX_RESULT_ERROR_SERIALIZE_ADAPTER => Self::SerializeAdapter,
1644 gvox_sys::GvoxResult_GVOX_RESULT_ERROR_PARSE_ADAPTER_INVALID_INPUT => Self::ParseAdapterInvalidInput,
1645 gvox_sys::GvoxResult_GVOX_RESULT_ERROR_PARSE_ADAPTER_REQUESTED_CHANNEL_NOT_PRESENT => Self::ParseAdapterRequestedChannelNotPresent,
1646 gvox_sys::GvoxResult_GVOX_RESULT_ERROR_SERIALIZE_ADAPTER_UNREPRESENTABLE_DATA => Self::SerializeAdapterUnrepresentableData,
1647 _ => Self::Unknown
1648 }
1649 }
1650}
1651
1652#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1654#[repr(i32)]
1655pub enum BlitMode {
1656 DontCare = gvox_sys::GvoxBlitMode_GVOX_BLIT_MODE_DONT_CARE,
1658 ParseDriven = gvox_sys::GvoxBlitMode_GVOX_BLIT_MODE_PARSE_DRIVEN,
1660 SerializeDriven = gvox_sys::GvoxBlitMode_GVOX_BLIT_MODE_SERIALIZE_DRIVEN,
1662}
1663
1664#[derive(Clone, Debug)]
1666pub struct ParseAdapterDetails {
1667 preferred_blit_mode: BlitMode,
1669}
1670
1671#[derive(Clone, Debug)]
1673pub struct GvoxError {
1674 ty: ErrorType,
1676 message: String,
1678}
1679
1680impl GvoxError {
1681 pub fn new(ty: ErrorType, message: impl Into<String>) -> Self {
1683 let message = Into::<String>::into(message);
1684 Self { ty, message }
1685 }
1686
1687 pub fn error_type(&self) -> ErrorType {
1689 self.ty
1690 }
1691}
1692
1693impl Error for GvoxError {
1694 fn description(&self) -> &str {
1695 &self.message
1696 }
1697}
1698
1699impl std::fmt::Display for GvoxError {
1700 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1701 f.write_fmt(format_args!("{:?}: {}", self.ty, self.message))
1702 }
1703}
1704
1705pub struct Sample {
1707 pub data: u32,
1708 pub is_present: bool,
1709}
1710
1711#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1713pub struct ChannelId(u32);
1714
1715impl ChannelId {
1716 pub const COLOR: Self = Self(gvox_sys::GVOX_CHANNEL_ID_COLOR);
1718 pub const NORMAL: Self = Self(gvox_sys::GVOX_CHANNEL_ID_NORMAL);
1720 pub const MATERIAL_ID: Self = Self(gvox_sys::GVOX_CHANNEL_ID_MATERIAL_ID);
1722 pub const ROUGHNESS: Self = Self(gvox_sys::GVOX_CHANNEL_ID_ROUGHNESS);
1724 pub const METALNESS: Self = Self(gvox_sys::GVOX_CHANNEL_ID_METALNESS);
1726 pub const TRANSPARENCY: Self = Self(gvox_sys::GVOX_CHANNEL_ID_TRANSPARENCY);
1728 pub const IOR: Self = Self(gvox_sys::GVOX_CHANNEL_ID_IOR);
1730 pub const EMISSIVE_COLOR: Self = Self(gvox_sys::GVOX_CHANNEL_ID_EMISSIVITY);
1732 pub const HARDNESS: Self = Self(gvox_sys::GVOX_CHANNEL_ID_HARDNESS);
1734
1735 pub fn iter() -> impl Iterator<Item = ChannelId> {
1737 (0..=gvox_sys::GVOX_CHANNEL_ID_LAST).map(ChannelId)
1738 }
1739}
1740
1741impl TryFrom<u32> for ChannelId {
1742 type Error = GvoxError;
1743
1744 fn try_from(value: u32) -> Result<Self, Self::Error> {
1745 (value <= gvox_sys::GVOX_CHANNEL_ID_LAST)
1746 .then_some(Self(value))
1747 .ok_or_else(|| {
1748 GvoxError::new(
1749 ErrorType::InvalidParameter,
1750 format!("Channel ID {value} is out of range 0..=31."),
1751 )
1752 })
1753 }
1754}
1755
1756impl From<ChannelId> for u32 {
1757 fn from(value: ChannelId) -> Self {
1758 value.0
1759 }
1760}
1761
1762impl BitAnd for ChannelId {
1763 type Output = ChannelFlags;
1764
1765 fn bitand(self, rhs: Self) -> Self::Output {
1766 ChannelFlags::from(self) & rhs
1767 }
1768}
1769
1770impl BitOr for ChannelId {
1771 type Output = ChannelFlags;
1772
1773 fn bitor(self, rhs: Self) -> Self::Output {
1774 ChannelFlags::from(self) | rhs
1775 }
1776}
1777
1778impl BitXor for ChannelId {
1779 type Output = ChannelFlags;
1780
1781 fn bitxor(self, rhs: Self) -> Self::Output {
1782 ChannelFlags::from(self) ^ rhs
1783 }
1784}
1785
1786impl BitAnd<ChannelFlags> for ChannelId {
1787 type Output = ChannelFlags;
1788
1789 fn bitand(self, rhs: ChannelFlags) -> Self::Output {
1790 ChannelFlags::from(self) & rhs
1791 }
1792}
1793
1794impl BitOr<ChannelFlags> for ChannelId {
1795 type Output = ChannelFlags;
1796
1797 fn bitor(self, rhs: ChannelFlags) -> Self::Output {
1798 ChannelFlags::from(self) | rhs
1799 }
1800}
1801
1802impl BitXor<ChannelFlags> for ChannelId {
1803 type Output = ChannelFlags;
1804
1805 fn bitxor(self, rhs: ChannelFlags) -> Self::Output {
1806 ChannelFlags::from(self) ^ rhs
1807 }
1808}
1809
1810#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
1812pub struct ChannelFlags(u32);
1813
1814impl ChannelFlags {
1815 pub const fn all() -> Self {
1817 Self(u32::MAX)
1818 }
1819
1820 pub fn contains(&self, x: ChannelId) -> bool {
1822 (self.0 & (1 << u32::from(x))) != 0
1823 }
1824
1825 pub const fn empty() -> Self {
1827 Self(0)
1828 }
1829}
1830
1831impl IntoIterator for ChannelFlags {
1832 type Item = ChannelId;
1833
1834 type IntoIter = Box<dyn Iterator<Item = Self::Item>>;
1835
1836 fn into_iter(self) -> Self::IntoIter {
1837 Box::new(ChannelId::iter().filter(move |&x| self.contains(x)))
1838 }
1839}
1840
1841impl From<ChannelId> for ChannelFlags {
1842 fn from(value: ChannelId) -> Self {
1843 Self(1 << value.0)
1844 }
1845}
1846
1847impl From<ChannelFlags> for u32 {
1848 fn from(value: ChannelFlags) -> Self {
1849 value.0
1850 }
1851}
1852
1853impl From<u32> for ChannelFlags {
1854 fn from(value: u32) -> Self {
1855 Self(value)
1856 }
1857}
1858
1859impl Not for ChannelFlags {
1860 type Output = Self;
1861
1862 fn not(self) -> Self::Output {
1863 Self(!self.0)
1864 }
1865}
1866
1867impl BitAnd for ChannelFlags {
1868 type Output = Self;
1869
1870 fn bitand(self, rhs: Self) -> Self::Output {
1871 Self(self.0 & rhs.0)
1872 }
1873}
1874
1875impl BitAndAssign for ChannelFlags {
1876 fn bitand_assign(&mut self, rhs: Self) {
1877 *self = *self & ChannelFlags::from(rhs);
1878 }
1879}
1880
1881impl BitOr for ChannelFlags {
1882 type Output = Self;
1883
1884 fn bitor(self, rhs: Self) -> Self::Output {
1885 Self(self.0 | ChannelFlags::from(rhs).0)
1886 }
1887}
1888
1889impl BitOrAssign for ChannelFlags {
1890 fn bitor_assign(&mut self, rhs: Self) {
1891 *self = *self | ChannelFlags::from(rhs);
1892 }
1893}
1894
1895impl BitXor for ChannelFlags {
1896 type Output = Self;
1897
1898 fn bitxor(self, rhs: Self) -> Self::Output {
1899 Self(self.0 ^ ChannelFlags::from(rhs).0)
1900 }
1901}
1902
1903impl BitXorAssign for ChannelFlags {
1904 fn bitxor_assign(&mut self, rhs: Self) {
1905 *self = *self ^ rhs;
1906 }
1907}
1908
1909impl BitAnd<ChannelId> for ChannelFlags {
1910 type Output = Self;
1911
1912 fn bitand(self, rhs: ChannelId) -> Self::Output {
1913 Self(self.0 & ChannelFlags::from(rhs).0)
1914 }
1915}
1916
1917impl BitAndAssign<ChannelId> for ChannelFlags {
1918 fn bitand_assign(&mut self, rhs: ChannelId) {
1919 *self = *self & ChannelFlags::from(rhs);
1920 }
1921}
1922
1923impl BitOr<ChannelId> for ChannelFlags {
1924 type Output = Self;
1925
1926 fn bitor(self, rhs: ChannelId) -> Self::Output {
1927 Self(self.0 | ChannelFlags::from(rhs).0)
1928 }
1929}
1930
1931impl BitOrAssign<ChannelId> for ChannelFlags {
1932 fn bitor_assign(&mut self, rhs: ChannelId) {
1933 *self = *self | ChannelFlags::from(rhs);
1934 }
1935}
1936
1937impl BitXor<ChannelId> for ChannelFlags {
1938 type Output = Self;
1939
1940 fn bitxor(self, rhs: ChannelId) -> Self::Output {
1941 Self(self.0 ^ ChannelFlags::from(rhs).0)
1942 }
1943}
1944
1945impl BitXorAssign<ChannelId> for ChannelFlags {
1946 fn bitxor_assign(&mut self, rhs: ChannelId) {
1947 *self = *self ^ ChannelFlags::from(rhs);
1948 }
1949}
1950
1951bitflags! {
1952 pub struct RegionFlags: u32 {
1954 const UNIFORM = gvox_sys::GVOX_REGION_FLAG_UNIFORM;
1956 }
1957}
1958
1959impl Default for RegionFlags {
1960 fn default() -> Self {
1961 Self::empty()
1962 }
1963}
1964
1965mod private {
1967 use super::*;
1968
1969 pub trait Sealed {}
1972
1973 impl Sealed for Input {}
1974 impl Sealed for Output {}
1975 impl Sealed for Parse {}
1976 impl Sealed for Serialize {}
1977
1978 pub trait BlitContextType: 'static + Sized {
1980 unsafe fn new(
1987 ctx: *mut gvox_sys::GvoxContext,
1988 blit_ctx: *mut gvox_sys::GvoxBlitContext,
1989 ) -> Self;
1990 }
1991
1992 impl BlitContextType for InputBlitContext {
1993 unsafe fn new(_: *mut gvox_sys::GvoxContext, _: *mut gvox_sys::GvoxBlitContext) -> Self {
1994 Self {}
1995 }
1996 }
1997
1998 impl BlitContextType for OutputBlitContext {
1999 unsafe fn new(_: *mut gvox_sys::GvoxContext, _: *mut gvox_sys::GvoxBlitContext) -> Self {
2000 Self {}
2001 }
2002 }
2003
2004 impl BlitContextType for ParseBlitContext {
2005 unsafe fn new(
2006 ctx: *mut gvox_sys::GvoxContext,
2007 blit_ctx: *mut gvox_sys::GvoxBlitContext,
2008 ) -> Self {
2009 Self { blit_ctx, ctx }
2010 }
2011 }
2012
2013 impl BlitContextType for SerializeBlitContext {
2014 unsafe fn new(
2015 ctx: *mut gvox_sys::GvoxContext,
2016 blit_ctx: *mut gvox_sys::GvoxBlitContext,
2017 ) -> Self {
2018 Self { blit_ctx, ctx }
2019 }
2020 }
2021
2022 pub trait AdapterKindAssociation: AdapterKind {
2024 type BlitContext: BlitContextType;
2026 }
2027
2028 impl AdapterKindAssociation for Input {
2029 type BlitContext = InputBlitContext;
2030 }
2031
2032 impl AdapterKindAssociation for Output {
2033 type BlitContext = OutputBlitContext;
2034 }
2035
2036 impl AdapterKindAssociation for Parse {
2037 type BlitContext = ParseBlitContext;
2038 }
2039
2040 impl AdapterKindAssociation for Serialize {
2041 type BlitContext = SerializeBlitContext;
2042 }
2043
2044 pub trait RegisterableAdapter<K: AdapterKind>: AdapterDescriptor<K> + NamedAdapter {
2047 unsafe fn register_adapter(
2054 ptr: *mut gvox_sys::GvoxContext,
2055 ) -> Result<*mut gvox_sys::GvoxAdapter, GvoxError>;
2056 }
2057
2058 impl<T: AdapterDescriptor<Input> + NamedAdapter> RegisterableAdapter<Input> for T
2059 where
2060 T::Handler: InputAdapterHandler<T>,
2061 {
2062 unsafe fn register_adapter(
2063 ptr: *mut gvox_sys::GvoxContext,
2064 ) -> Result<*mut gvox_sys::GvoxAdapter, GvoxError> {
2065 let name =
2066 CString::new(Self::name()).expect("Failed to convert Rust string to C string");
2067 let adapter_info = gvox_sys::GvoxInputAdapterInfo {
2068 base_info: create_base_adapter_info::<Input, Self>(&name),
2069 read: Some(InputContextHolder::read::<Self>),
2070 };
2071 let adapter = gvox_sys::gvox_register_input_adapter(ptr, &adapter_info);
2072 ContextInner::get_error_from_raw_ptr(ptr).map(|()| adapter)
2073 }
2074 }
2075
2076 impl<T: AdapterDescriptor<Output> + NamedAdapter> RegisterableAdapter<Output> for T
2077 where
2078 T::Handler: OutputAdapterHandler<T>,
2079 {
2080 unsafe fn register_adapter(
2081 ptr: *mut gvox_sys::GvoxContext,
2082 ) -> Result<*mut gvox_sys::GvoxAdapter, GvoxError> {
2083 let name =
2084 CString::new(Self::name()).expect("Failed to convert Rust string to C string");
2085 let adapter_info = gvox_sys::GvoxOutputAdapterInfo {
2086 base_info: create_base_adapter_info::<Output, Self>(&name),
2087 write: Some(OutputContextHolder::write::<Self>),
2088 reserve: Some(OutputContextHolder::reserve::<Self>),
2089 };
2090 let adapter = gvox_sys::gvox_register_output_adapter(ptr, &adapter_info);
2091 ContextInner::get_error_from_raw_ptr(ptr).map(|()| adapter)
2092 }
2093 }
2094
2095 impl<T: AdapterDescriptor<Parse> + NamedAdapter> RegisterableAdapter<Parse> for T
2096 where
2097 T::Handler: ParseAdapterHandler<T>,
2098 {
2099 unsafe fn register_adapter(
2100 ptr: *mut gvox_sys::GvoxContext,
2101 ) -> Result<*mut gvox_sys::GvoxAdapter, GvoxError> {
2102 let name =
2103 CString::new(Self::name()).expect("Failed to convert Rust string to C string");
2104 let adapter_info = gvox_sys::GvoxParseAdapterInfo {
2105 base_info: create_base_adapter_info::<Parse, Self>(&name),
2106 query_details: Some(ParseContextHolder::query_details::<Self>),
2107 query_parsable_range: Some(ParseContextHolder::query_parsable_range::<Self>),
2108 query_region_flags: Some(ParseContextHolder::query_region_flags::<Self>),
2109 load_region: Some(ParseContextHolder::load_region::<Self>),
2110 unload_region: Some(ParseContextHolder::unload_region::<Self>),
2111 sample_region: Some(ParseContextHolder::sample_region::<Self>),
2112 parse_region: Some(ParseContextHolder::parse_region::<Self>),
2113 };
2114 let adapter = gvox_sys::gvox_register_parse_adapter(ptr, &adapter_info);
2115 ContextInner::get_error_from_raw_ptr(ptr).map(|()| adapter)
2116 }
2117 }
2118
2119 impl<T: AdapterDescriptor<Serialize> + NamedAdapter> RegisterableAdapter<Serialize> for T
2120 where
2121 T::Handler: SerializeAdapterHandler<T>,
2122 {
2123 unsafe fn register_adapter(
2124 ptr: *mut gvox_sys::GvoxContext,
2125 ) -> Result<*mut gvox_sys::GvoxAdapter, GvoxError> {
2126 let name =
2127 CString::new(Self::name()).expect("Failed to convert Rust string to C string");
2128 let adapter_info = gvox_sys::GvoxSerializeAdapterInfo {
2129 base_info: create_base_adapter_info::<Serialize, Self>(&name),
2130 serialize_region: Some(SerializeContextHolder::serialize_region::<Self>),
2131 receive_region: Some(SerializeContextHolder::receive_region::<Self>),
2132 };
2133 let adapter = gvox_sys::gvox_register_serialize_adapter(ptr, &adapter_info);
2134 ContextInner::get_error_from_raw_ptr(ptr).map(|()| adapter)
2135 }
2136 }
2137
2138 fn create_base_adapter_info<K: AdapterKindAssociation, A: AdapterDescriptor<K>>(
2140 name: &CStr,
2141 ) -> gvox_sys::GvoxAdapterBaseInfo
2142 where
2143 A::Handler: BaseAdapterHandler<K, A>,
2144 {
2145 gvox_sys::GvoxAdapterBaseInfo {
2146 name_str: name.as_ptr(),
2147 create: Some(AdapterContextHolder::create::<K, A>),
2148 destroy: Some(AdapterContextHolder::destroy::<K, A>),
2149 blit_begin: Some(AdapterContextHolder::blit_begin::<K, A>),
2150 blit_end: Some(AdapterContextHolder::blit_end::<K, A>),
2151 }
2152 }
2153}