1 use std;
2 use std::ffi::CStr;
3 use std::marker::PhantomData;
4 use std::os::raw::c_char;
5 use super::ChunkRef;
6 use crate::rustimpl;
7
8 pub struct TextKeysCStrIter<'a> {
9 pub(crate) k: *mut *mut c_char,
10 pub(crate) v: *mut *mut c_char,
11 pub(crate) n: usize,
12 pub(crate) _p: PhantomData<&'a CStr>,
13 }
14
15 impl<'a> Iterator for TextKeysCStrIter<'a> {
16 type Item = (&'a CStr, &'a CStr);
next(&mut self) -> Option<Self::Item>17 fn next(&mut self) -> Option<Self::Item> {
18 if self.n > 0 {
19 unsafe {
20 debug_assert!(!(*self.k).is_null()); let k = CStr::from_ptr(*self.k);
21 debug_assert!(!(*self.v).is_null()); let v = CStr::from_ptr(*self.v);
22 self.n -= 1;
23 self.k = self.k.offset(1);
24 self.v = self.v.offset(1);
25 Some((k, v))
26 }
27 } else {
28 None
29 }
30 }
31 }
32
33 pub struct ITextKeysIter<'a> {
34 pub(crate) k: *mut *mut c_char,
35 pub(crate) l: *mut *mut c_char,
36 pub(crate) t: *mut *mut c_char,
37 pub(crate) s: *mut *mut c_char,
38 pub(crate) n: usize,
39 pub(crate) _p: PhantomData<&'a str>,
40 }
41
42 /// Invalid encoding truncates the strings
43 impl<'a> Iterator for ITextKeysIter<'a> {
44 type Item = (&'a str, &'a str, &'a str, &'a str);
next(&mut self) -> Option<Self::Item>45 fn next(&mut self) -> Option<Self::Item> {
46 if self.n > 0 {
47 unsafe {
48 debug_assert!(!(*self.k).is_null()); let k = CStr::from_ptr(*self.k);
49 debug_assert!(!(*self.l).is_null()); let l = CStr::from_ptr(*self.l);
50 debug_assert!(!(*self.t).is_null()); let t = CStr::from_ptr(*self.t);
51 debug_assert!(!(*self.s).is_null()); let s = CStr::from_ptr(*self.s);
52 self.n -= 1;
53 self.k = self.k.offset(1);
54 self.l = self.l.offset(1);
55 self.t = self.t.offset(1);
56 self.s = self.s.offset(1);
57 Some((
58 cstr_to_str(k),
59 cstr_to_str(l),
60 cstr_to_str(t),
61 cstr_to_str(s)))
62 }
63 } else {
64 None
65 }
66 }
67 }
68
cstr_to_str(s: &CStr) -> &str69 fn cstr_to_str(s: &CStr) -> &str {
70 match s.to_str() {
71 Ok(s) => s,
72 Err(e) => {
73 std::str::from_utf8(&s.to_bytes()[0..e.valid_up_to()]).unwrap()
74 }
75 }
76 }
77
78 pub struct ChunksIter<'a> {
79 pub(crate) data: &'a [u8],
80 }
81
82 impl<'a> Iterator for ChunksIter<'a> {
83 type Item = ChunkRef<'a>;
next(&mut self) -> Option<Self::Item>84 fn next(&mut self) -> Option<Self::Item> {
85 let header_len = 12;
86 if self.data.len() < header_len {
87 return None;
88 }
89
90 let len = rustimpl::lodepng_chunk_length(self.data);
91 if self.data.len() < len + header_len {
92 return None;
93 }
94 let c = ChunkRef::new(&self.data[0..len + header_len]);
95 self.data = rustimpl::lodepng_chunk_next(self.data);
96 Some(c)
97 }
98 }
99