Skip to main content

skia_safe/core/
data_table.rs

1use crate::prelude::*;
2use skia_bindings::{self as sb, SkDataTable, SkRefCntBase};
3use std::{
4    ffi::{CStr, c_void},
5    fmt, mem,
6    ops::Index,
7};
8
9pub type DataTable = RCHandle<SkDataTable>;
10unsafe_send_sync!(DataTable);
11require_type_equality!(sb::SkDataTable_INHERITED, sb::SkRefCnt);
12
13impl NativeRefCountedBase for SkDataTable {
14    type Base = SkRefCntBase;
15}
16
17impl Index<usize> for DataTable {
18    type Output = [u8];
19
20    fn index(&self, index: usize) -> &Self::Output {
21        self.at(index)
22    }
23}
24
25impl fmt::Debug for DataTable {
26    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
27        f.debug_struct("DataTable")
28            .field("count", &self.count())
29            .finish()
30    }
31}
32
33impl DataTable {
34    pub fn is_empty(&self) -> bool {
35        self.count() == 0
36    }
37
38    pub fn count(&self) -> usize {
39        unsafe { sb::C_SkDataTable_count(self.native()) }
40            .try_into()
41            .unwrap()
42    }
43
44    pub fn at_size(&self, index: usize) -> usize {
45        assert!(index < self.count());
46        unsafe { self.native().atSize(index.try_into().unwrap()) }
47    }
48
49    pub fn at(&self, index: usize) -> &[u8] {
50        unsafe { self.at_t(index) }
51    }
52
53    #[allow(clippy::missing_safety_doc)]
54    pub unsafe fn at_t<T: Copy>(&self, index: usize) -> &[T] {
55        unsafe {
56            assert!(index < self.count());
57            let mut size = usize::default();
58            let ptr = self.native().at(index.try_into().unwrap(), &mut size);
59            let element_size = mem::size_of::<T>();
60            assert_eq!(size % element_size, 0);
61            let elements = size / element_size;
62            safer::from_raw_parts(ptr as _, elements)
63        }
64    }
65
66    pub fn at_str(&self, index: usize) -> &CStr {
67        let bytes = self.at(index);
68        CStr::from_bytes_with_nul(bytes).unwrap()
69    }
70
71    pub fn new_empty() -> Self {
72        DataTable::from_ptr(unsafe { sb::C_SkDataTable_MakeEmpty() }).unwrap()
73    }
74
75    pub fn from_slices(slices: &[&[u8]]) -> Self {
76        let ptrs: Vec<*const c_void> = slices.iter().map(|s| s.as_ptr() as _).collect();
77        let sizes: Vec<usize> = slices.iter().map(|s| s.len()).collect();
78        unsafe {
79            DataTable::from_ptr(sb::C_SkDataTable_MakeCopyArrays(
80                ptrs.as_ptr(),
81                sizes.as_ptr(),
82                slices.len().try_into().unwrap(),
83            ))
84            .unwrap()
85        }
86    }
87
88    pub fn from_slice<T: Copy>(slice: &[T]) -> Self {
89        unsafe {
90            DataTable::from_ptr(sb::C_SkDataTable_MakeCopyArray(
91                slice.as_ptr() as _,
92                mem::size_of::<T>(),
93                slice.len().try_into().unwrap(),
94            ))
95            .unwrap()
96        }
97    }
98
99    // TODO: wrap MakeArrayProc()
100
101    pub fn iter(&self) -> Iter {
102        Iter {
103            table: self,
104            count: self.count(),
105            current: 0,
106        }
107    }
108}
109
110#[derive(Debug)]
111pub struct Iter<'a> {
112    table: &'a DataTable,
113    count: usize,
114    current: usize,
115}
116
117impl<'a> Iterator for Iter<'a> {
118    type Item = &'a [u8];
119
120    fn next(&mut self) -> Option<Self::Item> {
121        if self.current < self.count {
122            let r = Some(self.table.at(self.current));
123            self.current += 1;
124            r
125        } else {
126            None
127        }
128    }
129}