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