ufbx/
prelude.rs

1use std::any::Any;
2use std::{ptr, str, slice};
3use std::marker::PhantomData;
4use std::ops::{Deref, Index};
5use std::alloc::{self,Layout,System,GlobalAlloc};
6use std::ffi::c_void;
7use std::cmp::min;
8use std::io::{Read,Seek,SeekFrom};
9use std::fs::File;
10use std::mem;
11use std::string;
12use std::ptr::NonNull;
13use std::fmt::{self, Debug, Display, Formatter};
14use crate::{OpenFileInfo, RawThreadPool};
15use crate::generated::{RawStream, RawAllocator, RawVertexStream, Progress, ProgressResult, Error, Vec2, Vec3, Vec4};
16use crate::generated::format_error;
17
18pub type Real = f64;
19pub type ThreadPoolContext = usize;
20pub type OpenFileContext = usize;
21
22#[repr(C)]
23pub struct List<T> {
24    pub data: *const T,
25    pub count: usize,
26    _marker: PhantomData<T>,
27}
28
29impl<T> List<T> {
30    pub(crate) unsafe fn from_slice(slice: &[T]) -> List<T> {
31        List {
32            data: slice.as_ptr(),
33            count: slice.len(),
34            _marker: PhantomData,
35        }
36    }
37    pub(crate) unsafe fn as_static_ref(&self) -> &'static [T] {
38        slice_from_ptr(self.data, self.count)
39    }
40}
41
42impl<T> AsRef<[T]> for List<T> {
43    fn as_ref(&self) -> &[T] {
44        unsafe { slice_from_ptr(self.data, self.count) }
45    }
46}
47
48impl<T> Deref for List<T> {
49    type Target = [T];
50    fn deref(&self) -> &Self::Target {
51        unsafe { slice_from_ptr(self.data, self.count) }
52    }
53}
54
55impl<'a, T> IntoIterator for &'a List<T> {
56    type Item = &'a T;
57    type IntoIter = slice::Iter<'a, T>;
58    fn into_iter(self) -> Self::IntoIter {
59        self.as_ref().into_iter()
60    }
61}
62
63impl<T> Index<usize> for List<T> {
64    type Output = T;
65    fn index(&self, index: usize) -> &T {
66        &self.as_ref()[index]
67    }
68}
69
70#[repr(C)]
71pub struct RefList<T> {
72    data: *const Ref<T>,
73    pub count: usize,
74    _marker: PhantomData<T>,
75}
76
77impl<T> RefList<T> {
78    #[allow(dead_code)]
79    pub(crate) unsafe fn as_static_ref(&self) -> &'static [Ref<T>] {
80        slice_from_ptr(self.data, self.count)
81    }
82}
83
84impl<T> AsRef<[Ref<T>]> for RefList<T> {
85    fn as_ref(&self) -> &[Ref<T>] {
86        unsafe { slice_from_ptr(self.data, self.count) }
87    }
88}
89
90impl<T> Deref for RefList<T> {
91    type Target = [Ref<T>];
92    fn deref(&self) -> &Self::Target {
93        unsafe { slice_from_ptr(self.data, self.count) }
94    }
95}
96
97pub struct RefIter<'a, T> {
98    inner: slice::Iter<'a, Ref<T>>,
99}
100
101impl<'a, T> Iterator for RefIter<'a, T> {
102    type Item = &'a T;
103    fn next(&mut self) -> Option<Self::Item> {
104        self.inner.next().map(|v| v.as_ref())
105    }
106}
107
108impl<'a, T> IntoIterator for &'a RefList<T> {
109    type Item = &'a T;
110    type IntoIter = RefIter<'a, T>;
111    fn into_iter(self) -> RefIter<'a, T> {
112        RefIter::<'_, T> { inner: self.as_ref().into_iter() }
113    }
114}
115
116impl<T> Index<usize> for RefList<T> {
117    type Output = T;
118    fn index(&self, index: usize) -> &T {
119        &self.as_ref()[index]
120    }
121}
122
123#[repr(transparent)]
124pub struct Ref<T> {
125    ptr: NonNull<T>,
126    _marker: PhantomData<T>,
127}
128
129impl<T> AsRef<T> for Ref<T> {
130    fn as_ref(&self) -> &T {
131        unsafe { &*self.ptr.as_ptr() }
132    }
133}
134
135impl<T> Deref for Ref<T> {
136    type Target = T;
137    fn deref(&self) -> &Self::Target {
138        unsafe { &*self.ptr.as_ptr() }
139    }
140}
141
142#[repr(C)]
143pub struct RawString {
144    pub data: *const u8,
145    pub length: usize,
146}
147
148impl RawString {
149    fn new(s: &[u8]) -> Self {
150        RawString {
151            data: s.as_ptr(),
152            length: s.len(),
153        }
154    }
155}
156
157impl Default for RawString {
158    fn default() -> Self {
159        RawString {
160            data: ptr::null(),
161            length: 0,
162        }
163    }
164}
165
166#[repr(C)]
167pub struct RawBlob {
168    pub data: *const u8,
169    pub size: usize,
170}
171
172impl RawBlob {
173    fn new(s: &[u8]) -> Self {
174        RawBlob {
175            data: s.as_ptr(),
176            size: s.len(),
177        }
178    }
179}
180
181impl Default for RawBlob {
182    fn default() -> Self {
183        RawBlob {
184            data: ptr::null(),
185            size: 0,
186        }
187    }
188}
189
190#[repr(C)]
191pub struct RawList<T> {
192    pub data: *const T,
193    pub count: usize,
194}
195
196impl<T> Default for RawList<T> {
197    fn default() -> Self {
198        RawList {
199            data: ptr::null(),
200            count: 0,
201        }
202    }
203}
204
205#[repr(C)]
206#[allow(dead_code)] // Currently not used
207pub struct OptionRef<T> {
208    ptr: *const T,
209    _marker: PhantomData<T>,
210}
211
212impl<T> OptionRef<T> {
213    pub fn is_some(&self) -> bool { self.ptr.is_null() }
214    pub fn is_none(&self) -> bool { !self.ptr.is_null() }
215
216    pub fn as_ref(&self) -> Option<&T> {
217        unsafe { self.ptr.as_ref() }
218    }
219}
220
221#[repr(C)]
222pub struct String {
223    data: *const u8,
224    pub length: usize,
225    _marker: PhantomData<u8>,
226}
227
228impl String {
229    pub(crate) unsafe fn as_static_ref(&self) -> &'static str {
230        str::from_utf8_unchecked(slice_from_ptr(self.data, self.length))
231    }
232}
233
234impl AsRef<str> for String {
235    fn as_ref(&self) -> &str {
236        unsafe { str::from_utf8_unchecked(slice_from_ptr(self.data, self.length)) }
237    }
238}
239
240impl Deref for String {
241    type Target = str;
242    fn deref(&self) -> &Self::Target {
243        self.as_ref()
244    }
245}
246
247impl Default for String {
248    fn default () -> String {
249        String{ data: ptr::null(), length: 0, _marker: PhantomData }
250    }
251}
252
253impl Display for String {
254    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
255        f.write_str(self.deref())
256    }
257}
258
259impl<'a> PartialEq<&'a str> for String {
260    fn eq(&self, rhs: &&'a str) -> bool {
261        &self.as_ref() == rhs
262    }
263}
264
265impl Debug for String {
266    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
267        write!(f, "{:?}", self.as_ref())
268    }
269}
270
271#[repr(C)]
272pub struct Blob {
273    data: *const u8,
274    pub size: usize,
275    _marker: PhantomData<u8>,
276}
277
278unsafe fn slice_from_ptr<'a, T>(data: *const T, len: usize) -> &'a [T] {
279    if len > 0 {
280        slice::from_raw_parts(data, len)
281    } else {
282        &[]
283    }
284}
285
286unsafe fn slice_from_ptr_mut<'a, T>(data: *mut T, len: usize) -> &'a mut [T] {
287    if len > 0 {
288        slice::from_raw_parts_mut(data, len)
289    } else {
290        &mut []
291    }
292}
293
294impl Deref for Blob {
295    type Target = [u8];
296    fn deref(&self) -> &Self::Target {
297        unsafe { slice_from_ptr(self.data, self.size) }
298    }
299}
300
301pub trait AllocatorInterface {
302    fn alloc(&mut self, layout: Layout) -> *mut u8;
303    fn free(&mut self, ptr: *mut u8, layout: Layout);
304    fn realloc(&mut self, ptr: *mut u8, old_layout: Layout, new_layout: Layout) -> *mut u8 {
305        self.free(ptr, old_layout);
306        self.alloc(new_layout)
307    }
308    fn free_allocator(&mut self) { }
309}
310
311#[repr(transparent)]
312#[derive(Default)]
313pub struct Unsafe<T>(T);
314
315impl<T> Unsafe<T> {
316    pub unsafe fn new(t: T) -> Self { Self(t) }
317}
318
319impl<T> Unsafe<T> where T: Default {
320    pub fn take(&mut self) -> T { mem::take(&mut self.0) }
321}
322
323pub trait StreamInterface {
324    fn read(&mut self, buf: &mut [u8]) -> Option<usize>;
325    fn skip(&mut self, bytes: usize) -> bool {
326        #![allow(deprecated)]
327        unsafe {
328            let mut local_buf: [mem::MaybeUninit<u8>; 512] = mem::MaybeUninit::uninit().assume_init();
329            let mut left = bytes;
330            while left > 0 {
331                let to_read = min(left, local_buf.len());
332                let num_read = self.read(mem::transmute(&mut local_buf[0..to_read])).unwrap_or(0);
333                if num_read != to_read { return false }
334                left -= num_read
335            }
336            true
337        }
338    }
339    fn size(&mut self) -> u64 { 0 }
340    fn close(&mut self) { }
341}
342
343pub enum Stream {
344    File(File),
345    Read(Box<dyn Read>),
346    Box(Box<dyn StreamInterface>),
347    Raw(Unsafe<RawStream>),
348}
349
350unsafe extern "C" fn global_alloc(_user: *mut c_void, size: usize) -> *mut c_void {
351    let layout = Layout::from_size_align(size, 8).unwrap();
352    alloc::alloc(layout) as *mut _
353}
354
355unsafe extern "C" fn global_realloc(_user: *mut c_void, ptr: *mut c_void, old_size: usize, new_size: usize) -> *mut c_void {
356    let old_layout = Layout::from_size_align(old_size, 8).unwrap();
357    alloc::realloc(ptr as *mut _, old_layout, new_size) as *mut _
358}
359
360unsafe extern "C" fn global_free(_user: *mut c_void, ptr: *mut c_void, size: usize) {
361    let layout = Layout::from_size_align(size, 8).unwrap();
362    alloc::dealloc(ptr as *mut _, layout)
363}
364
365unsafe extern "C" fn system_alloc(_user: *mut c_void, size: usize) -> *mut c_void {
366    let layout = Layout::from_size_align(size, 8).unwrap();
367    System.alloc(layout) as *mut _
368}
369
370unsafe extern "C" fn system_realloc(_user: *mut c_void, ptr: *mut c_void, old_size: usize, new_size: usize) -> *mut c_void {
371    let old_layout = Layout::from_size_align(old_size, 8).unwrap();
372    System.realloc(ptr as *mut _, old_layout, new_size) as *mut _
373}
374
375unsafe extern "C" fn system_free(_user: *mut c_void, ptr: *mut c_void, size: usize) {
376    let layout = Layout::from_size_align(size, 8).unwrap();
377    System.dealloc(ptr as *mut _, layout)
378}
379
380unsafe extern "C" fn allocator_imp_alloc(user: *mut c_void, size: usize) -> *mut c_void {
381    let ator: &mut Box<dyn AllocatorInterface> = &mut *(user as *mut Box<dyn AllocatorInterface>);
382    let layout = Layout::from_size_align(size, 8).unwrap();
383    ator.alloc(layout) as *mut _
384}
385
386unsafe extern "C" fn allocator_imp_realloc(user: *mut c_void, ptr: *mut c_void, old_size: usize, new_size: usize) -> *mut c_void {
387    let ator: &mut Box<dyn AllocatorInterface> = &mut *(user as *mut Box<dyn AllocatorInterface>);
388    let old_layout = Layout::from_size_align(old_size, 8).unwrap();
389    let new_layout = Layout::from_size_align(new_size, 8).unwrap();
390    ator.realloc(ptr as *mut _, old_layout, new_layout) as *mut _
391}
392
393unsafe extern "C" fn allocator_imp_free(user: *mut c_void, ptr: *mut c_void, size: usize) {
394    let ator: &mut Box<dyn AllocatorInterface> = &mut *(user as *mut Box<dyn AllocatorInterface>);
395    let layout = Layout::from_size_align(size, 8).unwrap();
396    ator.free(ptr as *mut _, layout)
397}
398
399unsafe extern "C" fn allocator_imp_box_free_allocator(user: *mut c_void) {
400    let mut ator = Box::from_raw(user as *mut Box<dyn AllocatorInterface>);
401    ator.free_allocator()
402}
403
404pub enum Allocator {
405    Libc,
406    Global,
407    System,
408    Box(Box<dyn AllocatorInterface>),
409    Raw(Unsafe<RawAllocator>),
410}
411
412impl Default for Allocator {
413    fn default() -> Self { Allocator::Global }
414}
415
416impl Allocator {
417    pub(crate) fn from_rust(&self) -> RawAllocator {
418        match self {
419        Allocator::Libc => RawAllocator {
420            alloc_fn: None,
421            realloc_fn: None,
422            free_fn: None,
423            free_allocator_fn: None,
424            user: ptr::null::<c_void>() as *mut c_void,
425        },
426        Allocator::Global => RawAllocator {
427            alloc_fn: Some(global_alloc),
428            realloc_fn: Some(global_realloc),
429            free_fn: Some(global_free),
430            free_allocator_fn: None,
431            user: ptr::null::<c_void>() as *mut c_void,
432        },
433        Allocator::System => RawAllocator {
434            alloc_fn: Some(system_alloc),
435            realloc_fn: Some(system_realloc),
436            free_fn: Some(system_free),
437            free_allocator_fn: None,
438            user: ptr::null::<c_void>() as *mut c_void,
439        },
440        _ => panic!("required mutable reference"),
441        }
442    }
443    pub(crate) fn from_rust_mut(&mut self) -> RawAllocator {
444        match self {
445        Allocator::Box(b) => RawAllocator {
446            alloc_fn: Some(allocator_imp_alloc),
447            realloc_fn: Some(allocator_imp_realloc),
448            free_fn: Some(allocator_imp_free),
449            free_allocator_fn: Some(allocator_imp_box_free_allocator),
450            user: Box::into_raw(Box::new(b)) as *mut _,
451        },
452        Allocator::Raw(raw) => raw.take(),
453        _ => Self::from_rust(self),
454        }
455    }
456}
457
458pub enum ThreadPool {
459    None,
460    Raw(Unsafe<RawThreadPool>),
461}
462
463impl Default for ThreadPool {
464    fn default() -> Self { ThreadPool::None }
465}
466impl ThreadPool {
467    pub(crate) fn from_rust(&self) -> RawThreadPool {
468        match self {
469        ThreadPool::None => RawThreadPool {
470            init_fn: None,
471            run_fn: None,
472            wait_fn: None,
473            free_fn: None,
474            user: ptr::null::<c_void>() as *mut c_void,
475        },
476        _ => panic!("required mutable reference"),
477        }
478    }
479    pub(crate) fn from_rust_mut(&mut self) -> RawThreadPool {
480        match self {
481        ThreadPool::None => RawThreadPool {
482            init_fn: None,
483            run_fn: None,
484            wait_fn: None,
485            free_fn: None,
486            user: ptr::null::<c_void>() as *mut c_void,
487        },
488        ThreadPool::Raw(raw) => raw.take(),
489        }
490    }
491}
492
493pub struct VertexStream<'a> {
494    pub(crate) data: *mut c_void,
495    pub(crate) vertex_count: usize,
496    pub(crate) vertex_size: usize,
497    _marker: PhantomData<&'a mut ()>,
498}
499
500impl VertexStream<'_> {
501    pub fn new<T: Copy + Sized>(data: &mut [T]) -> VertexStream<'_> {
502        return VertexStream {
503            data: data.as_mut_ptr() as *mut c_void,
504            vertex_count: data.len(),
505            vertex_size: mem::size_of::<T>(),
506            _marker: PhantomData,
507        }
508    }
509}
510
511impl<'a> FromRust for [VertexStream<'a>] {
512    type Result = Vec<RawVertexStream>;
513    fn from_rust_mut(&mut self, _arena: &mut Arena) -> Self::Result {
514        self.iter().map(|s| RawVertexStream {
515            data: s.data,
516            vertex_count: s.vertex_count,
517            vertex_size: s.vertex_size,
518        }).collect()
519    }
520}
521
522unsafe extern "C" fn stream_read_read(user: *mut c_void, buf: *mut c_void, size: usize) -> usize {
523    let imp = &mut *(user as *mut Box<dyn Read>);
524    imp.read(slice_from_ptr_mut(buf as *mut u8, size)).unwrap_or(usize::MAX)
525}
526
527unsafe extern "C" fn stream_read_close(user: *mut c_void) {
528    let _ = Box::from_raw(user as *mut Box<dyn Read>);
529}
530
531unsafe extern "C" fn stream_imp_read(user: *mut c_void, buf: *mut c_void, size: usize) -> usize {
532    let imp = &mut *(user as *mut Box<dyn StreamInterface>);
533    imp.read(slice_from_ptr_mut(buf as *mut u8, size)).unwrap_or(usize::MAX)
534}
535
536unsafe extern "C" fn stream_imp_skip(user: *mut c_void, size: usize) -> bool {
537    let imp = &mut *(user as *mut Box<dyn StreamInterface>);
538    imp.skip(size)
539}
540
541unsafe extern "C" fn stream_imp_size(user: *mut c_void) -> u64 {
542    let imp = &mut *(user as *mut Box<dyn StreamInterface>);
543    imp.size()
544}
545
546unsafe extern "C" fn stream_imp_box_close(user: *mut c_void) {
547    let mut imp = Box::from_raw(user as *mut Box<dyn StreamInterface>);
548    imp.close()
549}
550
551// TODO: Expose these somehow
552#[allow(dead_code)]
553struct StreamRead<T: Read>(T);
554
555impl<T: Read> StreamInterface for StreamRead<T> {
556    fn read(&mut self, buf: &mut [u8]) -> Option<usize> {
557        self.0.read(buf).ok()
558    }
559}
560
561struct StreamReadSeek<T: Read + Seek>(T);
562
563impl<T: Read + Seek> StreamInterface for StreamReadSeek<T> {
564    fn read(&mut self, buf: &mut [u8]) -> Option<usize> {
565        self.0.read(buf).ok()
566    }
567    fn skip(&mut self, bytes: usize) -> bool {
568        match self.0.stream_position() {
569            Ok(cur) => match self.0.seek(SeekFrom::Current(bytes as i64)) {
570                Ok(pos) => pos == cur + (bytes as u64),
571                Err(_) => false,
572            },
573            Err(_) => false,
574        }
575    }
576    fn size(&mut self) -> u64 {
577        if let Ok(start) = self.0.stream_position() {
578            if let Ok(end) = self.0.seek(SeekFrom::End(0)) {
579                if self.0.seek(SeekFrom::Start(start)).is_ok() {
580                    return end - start
581                } else {
582                    return u64::MAX
583                }
584            }
585        }
586        0
587    }
588}
589
590impl Stream {
591    pub(crate) fn from_rust_mut(&mut self) -> RawStream {
592        let local = mem::replace(self, Stream::Raw(unsafe { Unsafe::new(Default::default()) }));
593        match local {
594            Stream::File(file) => {
595                let mut inner = Stream::Box(Box::new(StreamReadSeek(file)));
596                inner.from_rust_mut()
597            },
598            Stream::Read(b) => RawStream {
599                read_fn: Some(stream_read_read),
600                skip_fn: None,
601                size_fn: None,
602                close_fn: Some(stream_read_close),
603                user: Box::into_raw(Box::new(b)) as *mut _,
604            },
605            Stream::Box(b) => RawStream {
606                read_fn: Some(stream_imp_read),
607                skip_fn: Some(stream_imp_skip),
608                size_fn: Some(stream_imp_size),
609                close_fn: Some(stream_imp_box_close),
610                user: Box::into_raw(Box::new(b)) as *mut _,
611            },
612            Stream::Raw(mut raw) => raw.take(),
613        }
614    }
615}
616
617pub unsafe extern "C" fn call_progress_cb<F>(user: *mut c_void, progress: *const Progress) -> ProgressResult
618    where F: FnMut(&Progress) -> ProgressResult
619{
620    let func: &mut F = &mut *(user as *mut F);
621    (func)(&*progress)
622}
623
624pub unsafe extern "C" fn call_open_file_cb<F>(user: *mut c_void, dst: *mut RawStream, path: *const u8, path_len: usize, info: *const OpenFileInfo) -> bool
625    where F: FnMut(&str, &OpenFileInfo) -> Option<Stream>
626{
627    let func: &mut F = &mut *(user as *mut F);
628
629    let path_str = match str::from_utf8(slice_from_ptr(path, path_len)) {
630        Ok(path_str) => path_str,
631        Err(_) => return false,
632    };
633
634    let mut stream = match (func)(path_str, &*info) {
635        Some(stream) => stream,
636        None => return false,
637    };
638
639    *dst = stream.from_rust_mut();
640    true
641}
642
643pub unsafe extern "C" fn call_close_memory_cb<F>(user: *mut c_void, data: *mut c_void, data_size: usize)
644    where F: FnMut(*mut c_void, usize) -> ()
645{
646    let func: &mut F = &mut *(user as *mut F);
647    (func)(data, data_size)
648}
649
650#[repr(transparent)]
651pub struct InlineBuf<T> {
652    pub data: mem::MaybeUninit<T>,
653}
654
655impl<T> Default for InlineBuf<T> {
656    fn default() -> Self {
657        Self { data: mem::MaybeUninit::uninit() }
658    }
659}
660
661impl Debug for Error {
662    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
663        #![allow(deprecated)]
664        unsafe {
665            let mut local_buf: [mem::MaybeUninit<u8>; 1024] = mem::MaybeUninit::uninit().assume_init();
666            let length = format_error(mem::transmute(local_buf.as_mut_slice()), self);
667            f.write_str(str::from_utf8_unchecked(mem::transmute(&local_buf[..length])))
668        }
669    }
670}
671
672#[repr(C)]
673pub struct ExternalRef<'a, T> {
674    data: T,
675    _marker: PhantomData<&'a T>,
676}
677
678impl<'a, T> ExternalRef<'a, T> {
679    pub unsafe fn new(t: T) -> Self {
680        Self {
681            data: t,
682            _marker: PhantomData,
683        }
684    }
685}
686
687impl<'a, T> AsRef<T> for ExternalRef<'a, T> {
688    fn as_ref(&self) -> &T {
689        &self.data
690    }
691}
692
693impl<'a, T> Deref for ExternalRef<'a, T> {
694    type Target = T;
695    fn deref(&self) -> &Self::Target {
696        &self.data
697    }
698}
699
700pub(crate) struct Arena {
701    items: Vec<Box<dyn Any>>,
702}
703
704impl Arena {
705    pub fn new() -> Arena {
706        Arena{
707            items: Vec::new(),
708        }
709    }
710
711    #[allow(unused)]
712    pub fn push_box<T: 'static>(&mut self, s: Box<T>) -> *const T {
713        let ptr = Box::as_ref(&s) as *const T;
714        self.items.push(s);
715        ptr
716    }
717    pub fn push_vec<T: 'static>(&mut self, vec: Vec<T>) -> *const T {
718        if vec.len() == 0 { return ptr::null(); }
719        let ptr = vec.as_ptr();
720        self.items.push(Box::new(vec));
721        ptr
722    }
723}
724
725pub fn format_flags(f: &mut fmt::Formatter<'_>, names: &[(&str, u32)], value: u32) -> fmt::Result {
726    let mut has_any = false;
727
728    for (name, v) in names {
729        if (value & v) != 0 {
730            let prefix = if has_any { "|" } else { "" };
731            has_any = true;
732            write!(f, "{}{}", prefix, name)?;
733        }
734    }
735
736    if !has_any {
737            write!(f, "NONE")?;
738    }
739
740    Ok(())
741}
742
743impl fmt::Display for Vec2 {
744    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
745        match (f.precision(), f.sign_plus()) {
746            (None, false) => write!(f, "({}, {})", self.x, self.y),
747            (None, true) => write!(f, "({:+}, {:+})", self.x, self.y),
748            (Some(p), false) => write!(f, "({1:.0$}, {2:.0$})", p, self.x, self.y),
749            (Some(p), true) => write!(f, "({1:+.0$}, {2:+.0$})", p, self.x, self.y),
750        }
751    }
752}
753
754impl fmt::Display for Vec3 {
755    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
756        match (f.precision(), f.sign_plus()) {
757            (None, false) => write!(f, "({}, {}, {})", self.x, self.y, self.z),
758            (None, true) => write!(f, "({:+}, {:+}, {:+})", self.x, self.y, self.z),
759            (Some(p), false) => write!(f, "({1:.0$}, {2:.0$}, {3:.0$})", p, self.x, self.y, self.z),
760            (Some(p), true) => write!(f, "({1:+.0$}, {2:+.0$}, {3:+.0$})", p, self.x, self.y, self.z),
761        }
762    }
763}
764
765impl fmt::Display for Vec4 {
766    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
767        match (f.precision(), f.sign_plus()) {
768            (None, false) => write!(f, "({}, {}, {}, {})", self.x, self.y, self.z, self.w),
769            (None, true) => write!(f, "({:+}, {:+}, {:+}, {})", self.x, self.y, self.z, self.w),
770            (Some(p), false) => write!(f, "({1:.0$}, {2:.0$}, {3:.0$}, {4:.0$})", p, self.x, self.y, self.z, self.w),
771            (Some(p), true) => write!(f, "({1:+.0$}, {2:+.0$}, {3:+.0$}, {4:+.0$})", p, self.x, self.y, self.z, self.w),
772        }
773    }
774}
775
776pub(crate) trait FromRust {
777    type Result: 'static;
778    fn from_rust(&self, _arena: &mut Arena) -> Self::Result {
779        panic!("type must be used via mutable reference")
780    }
781    fn from_rust_mut(&mut self, arena: &mut Arena) -> Self::Result {
782        self.from_rust(arena)
783    }
784}
785
786pub enum StringOpt<'a> {
787    Unset,
788    Ref(&'a str),
789    Owned(string::String),
790}
791
792impl Default for StringOpt<'_> {
793    fn default() -> Self {
794        StringOpt::Unset
795    }
796}
797
798impl<'a> From<&'a str> for StringOpt<'a> {
799    fn from(v: &'a str) -> Self {
800        StringOpt::Ref(v)
801    }
802}
803
804impl<'a> From<string::String> for StringOpt<'a> {
805    fn from(v: string::String) -> Self {
806        StringOpt::Owned(v)
807    }
808}
809
810impl<'a> FromRust for StringOpt<'a> {
811    type Result = RawString;
812    fn from_rust(&self, _arena: &mut Arena) -> Self::Result {
813        match self {
814        StringOpt::Unset => RawString::default(),
815        StringOpt::Ref(r) => RawString::new(r.as_bytes()),
816        StringOpt::Owned(r) => RawString::new(r.as_bytes()),
817        }
818    }
819}
820
821pub enum BlobOpt<'a> {
822    Unset,
823    Ref(&'a [u8]),
824    Owned(Vec<u8>),
825}
826
827impl Default for BlobOpt<'_> {
828    fn default() -> Self {
829        BlobOpt::Unset
830    }
831}
832
833impl<'a> From<&'a [u8]> for BlobOpt<'a> {
834    fn from(v: &'a [u8]) -> Self {
835        BlobOpt::Ref(v)
836    }
837}
838
839impl<'a> From<Vec<u8>> for BlobOpt<'a> {
840    fn from(v: Vec<u8>) -> Self {
841        BlobOpt::Owned(v)
842    }
843}
844
845impl<'a> FromRust for BlobOpt<'a> {
846    type Result = RawBlob;
847    fn from_rust(&self, _arena: &mut Arena) -> Self::Result {
848        match self {
849        BlobOpt::Unset => RawBlob::default(),
850        BlobOpt::Ref(r) => RawBlob::new(r),
851        BlobOpt::Owned(r) => RawBlob::new(r.as_slice()),
852        }
853    }
854}
855
856pub enum ListOpt<'a, T> {
857    Unset,
858    Ref(&'a [T]),
859    Mut(&'a mut [T]),
860    Owned(Vec<T>),
861}
862
863impl<T> Default for ListOpt<'_, T> {
864    fn default() -> Self {
865        ListOpt::Unset
866    }
867}
868
869impl<'a, T> From<&'a [T]> for ListOpt<'a, T> {
870    fn from(v: &'a [T]) -> Self {
871        ListOpt::Ref(v)
872    }
873}
874
875impl<'a, T> From<Vec<T>> for ListOpt<'a, T> {
876    fn from(v: Vec<T>) -> Self {
877        ListOpt::Owned(v)
878    }
879}
880
881impl<'a, T: FromRust> FromRust for ListOpt<'a, T> {
882    type Result = RawList<T::Result>;
883
884    fn from_rust(&self, arena: &mut Arena) -> Self::Result {
885        let items: Vec<T::Result> = match self {
886            ListOpt::Unset => return RawList::default(),
887            ListOpt::Ref(v) => v.iter().map(|v| T::from_rust(v, arena)).collect(),
888            ListOpt::Mut(v) => v.iter().map(|v| T::from_rust(v, arena)).collect(),
889            ListOpt::Owned(v) => v.iter().map(|v| T::from_rust(v, arena)).collect(),
890        };
891        let count = items.len();
892        RawList { data: arena.push_vec(items), count }
893    }
894
895    fn from_rust_mut(&mut self, arena: &mut Arena) -> Self::Result {
896        let items: Vec<T::Result> = match mem::take(self) {
897            ListOpt::Unset => return RawList::default(),
898            ListOpt::Ref(v) => v.iter().map(|v| T::from_rust(v, arena)).collect(),
899            ListOpt::Mut(v) => v.into_iter().map(|v| T::from_rust_mut(v, arena)).collect(),
900            ListOpt::Owned(v) => v.into_iter().map(|mut v| T::from_rust_mut(&mut v, arena)).collect(),
901        };
902        let count = items.len();
903        RawList { data: arena.push_vec(items), count }
904    }
905
906}
907
908impl<T: Copy + 'static> FromRust for T {
909    type Result = T;
910    fn from_rust(&self, _arena: &mut Arena) -> Self::Result {
911        *self
912    }
913}