1use core::{borrow::Borrow, fmt, iter::FromIterator, marker::PhantomData, ops, ptr, slice};
3use std::io;
4
5use crate::{
6 codec::ImageCodec,
7 error::{errcode_to_result, expect_mem_err, OutOfMemory, Result},
8 util::range_to_tuple,
9 variant::WrappedBlCore,
10};
11
12#[repr(transparent)]
18pub struct Array<T: ArrayType> {
19 core: ffi::BLArrayCore,
20 _pd: PhantomData<T>,
21}
22
23unsafe impl<T: ArrayType> WrappedBlCore for Array<T> {
24 type Core = ffi::BLArrayCore;
25 const IMPL_TYPE_INDEX: usize = T::IMPL_IDX;
26
27 #[inline]
28 fn from_core(core: Self::Core) -> Self {
29 Array {
30 core,
31 _pd: PhantomData,
32 }
33 }
34}
35
36impl<T: ArrayType> Array<T> {
37 pub fn new() -> Self {
39 Self::from_core(*Self::none())
40 }
41
42 pub fn with_capacity(cap: usize) -> Self {
44 let mut this = Array::from_core(*Self::none());
45 this.reserve(cap);
46 this
47 }
48
49 #[inline]
51 pub fn clear(&mut self) {
52 unsafe { ffi::blArrayClear(self.core_mut()) };
53 }
54
55 #[inline]
57 pub fn shrink_to_fit(&mut self) {
58 unsafe { expect_mem_err(ffi::blArrayShrink(self.core_mut())) };
59 }
60
61 #[inline]
68 pub fn reserve(&mut self, n: usize) {
69 self.try_reserve(n).expect("memory allocation failed");
70 }
71
72 #[inline]
74 pub fn try_reserve(&mut self, n: usize) -> std::result::Result<(), OutOfMemory> {
75 unsafe { OutOfMemory::from_errcode(ffi::blArrayReserve(self.core_mut(), n)) }
76 }
77
78 #[inline]
80 pub fn truncate(&mut self, n: usize) {
81 unsafe {
82 expect_mem_err(ffi::blArrayResize(
83 self.core_mut(),
84 n.min(self.len()),
85 ptr::null(),
86 ))
87 };
88 }
89
90 #[inline]
93 pub fn resize(&mut self, n: usize, fill: T)
94 where
95 T: Clone,
96 {
97 unsafe {
98 let diff = n.checked_sub(self.len()).unwrap_or_default();
99 let buff = vec![fill; diff];
100 expect_mem_err(ffi::blArrayResize(
101 self.core_mut(),
102 n,
103 buff.as_ptr() as *const _,
104 ))
105 };
106 }
107
108 #[inline]
110 pub fn remove(&mut self, index: usize) -> Result<()> {
111 unsafe { errcode_to_result(ffi::blArrayRemoveIndex(self.core_mut(), index)) }
112 }
113
114 #[inline]
116 pub fn remove_range<R: ops::RangeBounds<usize>>(&mut self, range: R) -> Result<()> {
117 let (start, end) = range_to_tuple(range, || self.len());
118 unsafe { errcode_to_result(ffi::blArrayRemoveRange(self.core_mut(), start, end)) }
119 }
120
121 #[inline]
123 pub fn as_slice(&self) -> &[T] {
124 self
125 }
126
127 #[inline]
129 pub fn len(&self) -> usize {
130 unsafe { ffi::blArrayGetSize(self.core()) }
131 }
132
133 #[inline]
135 pub fn is_empty(&self) -> bool {
136 self.len() == 0
137 }
138
139 #[inline]
141 pub fn capacity(&self) -> usize {
142 self.impl_().capacity as usize
143 }
144
145 #[inline]
146 fn data_ptr(&self) -> *const T {
147 unsafe { ffi::blArrayGetData(self.core()) as *const _ }
148 }
149}
150
151impl<T> Array<T>
152where
153 T: ArrayType + Clone,
154{
155 #[inline]
157 pub fn extend_from_slice<S: AsRef<[T]>>(&mut self, data: S) {
158 unsafe {
159 expect_mem_err(ffi::blArrayAppendView(
160 self.core_mut(),
161 data.as_ref().as_ptr() as *const _,
162 data.as_ref().len(),
163 ))
164 };
165 }
166
167 #[inline]
169 pub fn insert_from_slice<S: AsRef<[T]>>(&mut self, index: usize, data: S) {
170 unsafe {
171 expect_mem_err(ffi::blArrayInsertView(
172 self.core_mut(),
173 index,
174 data.as_ref().as_ptr() as *const _,
175 data.as_ref().len(),
176 ))
177 };
178 }
179
180 #[inline]
183 pub fn replace_from_slice<R, S>(&mut self, range: R, data: S)
184 where
185 R: ops::RangeBounds<usize>,
186 S: AsRef<[T]>,
187 {
188 let (start, end) = range_to_tuple(range, || self.len());
189 unsafe {
190 expect_mem_err(ffi::blArrayReplaceView(
191 self.core_mut(),
192 start,
193 end,
194 data.as_ref().as_ptr() as *const _,
195 data.as_ref().len(),
196 ))
197 };
198 }
199}
200
201impl<T: ArrayType> Extend<T> for Array<T> {
202 fn extend<I>(&mut self, iter: I)
203 where
204 I: IntoIterator<Item = T>,
205 {
206 for item in iter {
207 self.push(item);
208 }
209 }
210}
211
212impl<T: ArrayType> FromIterator<T> for Array<T> {
213 fn from_iter<I>(iter: I) -> Array<T>
214 where
215 I: IntoIterator<Item = T>,
216 {
217 let iter = iter.into_iter();
218 let len = iter.size_hint().1.unwrap_or(iter.size_hint().0);
219 let mut this = Self::with_capacity(len);
220 this.extend(iter);
221 this
222 }
223}
224
225impl<T: ArrayType + Clone> From<Vec<T>> for Array<T> {
226 fn from(v: Vec<T>) -> Self {
227 let mut this = Self::with_capacity(v.len());
228 this.extend_from_slice(&v);
229 this
230 }
231}
232
233impl<'a, T> From<&'a [T]> for Array<T>
234where
235 T: ArrayType + Clone,
236{
237 fn from(v: &[T]) -> Self {
238 let mut this = Self::with_capacity(v.len());
239 this.extend_from_slice(v);
240 this
241 }
242}
243
244impl io::Write for Array<u8> {
245 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
246 self.extend_from_slice(buf);
247 Ok(buf.len())
248 }
249
250 fn flush(&mut self) -> io::Result<()> {
251 Ok(())
252 }
253}
254
255impl<T: ArrayType> AsRef<[T]> for Array<T> {
256 #[inline]
257 fn as_ref(&self) -> &[T] {
258 self
259 }
260}
261
262impl<T: ArrayType> AsMut<[T]> for Array<T> {
263 #[inline]
264 fn as_mut(&mut self) -> &mut [T] {
265 self
266 }
267}
268
269impl<T: ArrayType> Borrow<[T]> for Array<T> {
270 #[inline]
271 fn borrow(&self) -> &[T] {
272 self
273 }
274}
275
276impl<T: ArrayType> ops::Deref for Array<T> {
277 type Target = [T];
278
279 #[inline]
280 fn deref(&self) -> &Self::Target {
281 unsafe { slice::from_raw_parts(self.data_ptr(), self.len()) }
282 }
283}
284
285impl<T: ArrayType> ops::DerefMut for Array<T> {
286 #[inline]
287 fn deref_mut(&mut self) -> &mut Self::Target {
288 unsafe {
289 let mut data_ptr = ptr::null_mut();
290 expect_mem_err(ffi::blArrayMakeMutable(self.core_mut(), &mut data_ptr));
291 slice::from_raw_parts_mut(data_ptr as _, self.len())
292 }
293 }
294}
295
296impl<T, I> ops::Index<I> for Array<T>
297where
298 T: ArrayType,
299 I: slice::SliceIndex<[T]>,
300{
301 type Output = I::Output;
302
303 #[inline]
304 fn index(&self, index: I) -> &Self::Output {
305 ops::Index::index(&**self, index)
306 }
307}
308
309impl<'a, T: ArrayType> IntoIterator for &'a Array<T> {
310 type Item = &'a T;
311 type IntoIter = slice::Iter<'a, T>;
312 fn into_iter(self) -> Self::IntoIter {
313 self.iter()
314 }
315}
316
317impl<T: ArrayType> Default for Array<T> {
318 #[inline]
319 fn default() -> Self {
320 Self::new()
321 }
322}
323
324impl<T: ArrayType> PartialEq for Array<T> {
325 #[inline]
326 fn eq(&self, other: &Self) -> bool {
327 unsafe { ffi::blArrayEquals(self.core(), other.core()) }
328 }
329}
330
331impl<T: ArrayType> Clone for Array<T> {
332 fn clone(&self) -> Self {
333 Self::from_core(self.init_weak())
334 }
335}
336
337impl<T> fmt::Debug for Array<T>
338where
339 T: ArrayType + fmt::Debug,
340{
341 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
342 write!(f, "{:?}", self.as_ref())
343 }
344}
345
346impl<T: ArrayType> Drop for Array<T> {
347 fn drop(&mut self) {
348 unsafe { ffi::blArrayReset(&mut self.core) };
349 }
350}
351
352impl<T> Array<T>
353where
354 T: ArrayType,
355{
356 #[inline]
357 pub fn push(&mut self, item: T) {
358 unsafe { T::push(self.core_mut(), item) };
359 }
360 #[inline]
361 pub fn insert(&mut self, index: usize, item: T) {
362 unsafe { T::insert(self.core_mut(), index, item) };
363 }
364 #[inline]
365 pub fn replace(&mut self, index: usize, item: T) {
366 unsafe { T::replace(self.core_mut(), index, item) };
367 }
368}
369
370impl Array<ImageCodec> {
371 #[inline]
373 pub fn find_codec_by_name(&self, name: &str) -> Option<&ImageCodec> {
374 self.iter().find(|c| c.name() == name)
375 }
376
377 #[inline]
379 pub fn find_codec_by_data<R: AsRef<[u8]>>(&self, data: R) -> Option<&ImageCodec> {
380 self.into_iter()
381 .max_by_key(|codec| codec.inspect_data(data.as_ref()))
382 }
383}
384
385use crate::variant::ImplType;
386
387pub trait ArrayType: Sized {
392 #[doc(hidden)]
393 const IMPL_IDX: usize;
394 #[doc(hidden)]
395 #[inline]
396 unsafe fn push(core: &mut ffi::BLArrayCore, item: Self) {
397 expect_mem_err(ffi::blArrayAppendItem(core, &item as *const _ as *const _));
398 }
399 #[doc(hidden)]
400 #[inline]
401 unsafe fn insert(core: &mut ffi::BLArrayCore, index: usize, item: Self) {
402 expect_mem_err(ffi::blArrayInsertItem(
403 core,
404 index,
405 &item as *const _ as *const _,
406 ));
407 }
408 #[doc(hidden)]
409 #[inline]
410 unsafe fn replace(core: &mut ffi::BLArrayCore, index: usize, item: Self) {
411 expect_mem_err(ffi::blArrayReplaceItem(
412 core,
413 index,
414 &item as *const _ as *const _,
415 ));
416 }
417}
418
419#[doc(hidden)]
420impl<T> ArrayType for T
421where
422 T: WrappedBlCore,
423{
424 const IMPL_IDX: usize = ImplType::ArrayVar as usize;
425 #[inline]
426 unsafe fn push(core: &mut ffi::BLArrayCore, item: Self) {
427 expect_mem_err(ffi::blArrayAppendItem(
428 core,
429 item.core() as *const _ as *const _,
430 ));
431 }
432 #[inline]
433 unsafe fn insert(core: &mut ffi::BLArrayCore, index: usize, item: Self) {
434 expect_mem_err(ffi::blArrayInsertItem(
435 core,
436 index,
437 item.core() as *const _ as *const _,
438 ));
439 }
440 #[inline]
441 unsafe fn replace(core: &mut ffi::BLArrayCore, index: usize, item: Self) {
442 expect_mem_err(ffi::blArrayReplaceItem(
443 core,
444 index,
445 item.core() as *const _ as *const _,
446 ));
447 }
448}
449
450impl<T> ArrayType for *const T {
451 const IMPL_IDX: usize = usize::IMPL_IDX;
452 #[inline]
453 unsafe fn push(core: &mut ffi::BLArrayCore, item: Self) {
454 usize::push(core, item as usize);
455 }
456 #[inline]
457 unsafe fn insert(core: &mut ffi::BLArrayCore, index: usize, item: Self) {
458 usize::insert(core, index, item as usize);
459 }
460 #[inline]
461 unsafe fn replace(core: &mut ffi::BLArrayCore, index: usize, item: Self) {
462 usize::insert(core, index, item as usize);
463 }
464}
465
466impl<T> ArrayType for *mut T {
467 const IMPL_IDX: usize = usize::IMPL_IDX;
468 #[inline]
469 unsafe fn push(core: &mut ffi::BLArrayCore, item: Self) {
470 usize::push(core, item as usize);
471 }
472 #[inline]
473 unsafe fn insert(core: &mut ffi::BLArrayCore, index: usize, item: Self) {
474 usize::insert(core, index, item as usize);
475 }
476 #[inline]
477 unsafe fn replace(core: &mut ffi::BLArrayCore, index: usize, item: Self) {
478 usize::insert(core, index, item as usize);
479 }
480}
481
482macro_rules! impl_array_type {
485 ($( $append:ident, $insert:ident, $replace:ident for $( ($ty:ty = $idx:expr) ),+);*$(;)*) => {
486 $(
487 $(
488 impl ArrayType for $ty {
489 const IMPL_IDX: usize = $idx as usize;
490 #[inline]
491 unsafe fn push(core: &mut ffi::BLArrayCore, item: Self) {
492 expect_mem_err(ffi::$append(core, item as _))
493 }
494 #[inline]
495 unsafe fn insert(core: &mut ffi::BLArrayCore, index: usize, item: Self) {
496 expect_mem_err(ffi::$insert(core, index, item as _))
497 }
498 #[inline]
499 unsafe fn replace(core: &mut ffi::BLArrayCore, index: usize, item: Self) {
500 expect_mem_err(ffi::$replace(core, index, item as _))
501 }
502 }
503 )+
504 )*
505 };
506 ($( ( $( $ty:ty ),+ = $idx:expr) );* $(;)*) => {
507 $(
508 $(
509 impl ArrayType for $ty {
510 const IMPL_IDX: usize = $idx as usize;
511 }
512 )+
513 )*
514 }
515}
516
517impl_array_type! {
518 blArrayAppendU8, blArrayInsertU8, blArrayInsertU8 for (i8 = ImplType::ArrayI8), (u8 = ImplType::ArrayU8);
519 blArrayAppendU16, blArrayInsertU16, blArrayInsertU16 for (i16 = ImplType::ArrayI16), (u16 = ImplType::ArrayU16);
520 blArrayAppendU32, blArrayInsertU32, blArrayInsertU32 for (i32 = ImplType::ArrayI32), (u32 = ImplType::ArrayU32);
521 blArrayAppendU64, blArrayInsertU64, blArrayInsertU64 for (i64 = ImplType::ArrayI64), (u64 = ImplType::ArrayU64);
522 blArrayAppendF32, blArrayInsertF32, blArrayInsertF32 for (f32 = ImplType::ArrayF32);
523 blArrayAppendF64, blArrayInsertF64, blArrayInsertF64 for (f64 = ImplType::ArrayF32);
524}
525
526#[cfg(target_pointer_width = "32")]
527impl_array_type!(blArrayAppendU32, blArrayInsertU32, blArrayInsertU32 for (isize = ImplType::ArrayI32), (usize = ImplType::ArrayU32));
528#[cfg(target_pointer_width = "64")]
529impl_array_type!(blArrayAppendU64, blArrayInsertU64, blArrayInsertU64 for (isize = ImplType::ArrayI64), (usize = ImplType::ArrayU64));
530
531mod scope {
532 use crate::{array::ArrayType, font_defs::*, geometry::*, variant::ImplType, Tag};
533 impl_array_type! {
534 (Tag = ImplType::ArrayStruct4);
535 (PointD, PointI, SizeD, SizeI, FontFeature, FontVariation = ImplType::ArrayStruct8);
536 (Circle = ImplType::ArrayStruct12);
537 (BoxD, BoxI, Ellipse, Line, RectD, RectI = ImplType::ArrayStruct16);
538 (Arc, Chord, Pie, RoundRect, Triangle = ImplType::ArrayStruct24);
539 }
540}
541
542#[cfg(test)]
543mod test_array {
544 use crate::{array::Array, image::Image, path::Path};
545
546 #[test]
547 fn test_array_resize() {
548 let mut arr = Array::<i32>::new();
549 arr.resize(10, 32);
550 assert_eq!(&[32; 10][..], &*arr);
551
552 let mut path = Path::new();
553 path.move_to(1.0, 2.0);
554 let mut arr = Array::<Path>::new();
555 arr.resize(10, path.clone());
556 assert_eq!(&vec![path; 10][..], &*arr);
557 }
558
559 #[test]
560 fn test_array_ops_prim() {
561 let mut arr = Array::<i32>::new();
562 arr.push(32);
563 arr.push(24);
564 arr.push(16);
565 arr.push(8);
566 arr.remove(2).unwrap();
567 arr.insert(1, 0);
568 assert_eq!(&[32, 0, 24, 8], &*arr);
569 }
570
571 #[test]
572 fn test_array_ops_objects() {
573 let img = [
574 Image::new(1, 1, Default::default()).unwrap(),
575 Image::new(2, 2, Default::default()).unwrap(),
576 Image::new(3, 3, Default::default()).unwrap(),
577 Image::new(4, 4, Default::default()).unwrap(),
578 Image::new(5, 5, Default::default()).unwrap(),
579 ];
580 let mut arr = Array::<Image>::new();
581 for img in img.iter().take(4) {
582 arr.push(img.clone());
583 }
584 arr.remove(2).unwrap();
585 arr.insert(1, img[4].clone());
586 assert_eq!(
587 &[
588 img[0].clone(),
589 img[4].clone(),
590 img[1].clone(),
591 img[3].clone()
592 ][..],
593 &*arr
594 );
595 }
596
597 #[test]
598 fn test_array_deref_mut() {
599 let data = [0, 1, 2, 3, 4, 5];
600 let mut arr = Array::<i32>::from(&data[..]);
601 assert_eq!(&data, &*arr);
602 for i in 0..data.len() / 2 {
603 arr.swap(i, data.len() - 1 - i);
604 }
605 assert_eq!(&[5, 4, 3, 2, 1, 0], &*arr);
606 }
607}