1use crate::header::*;
2use byteorder::{BigEndian, ByteOrder, LittleEndian};
3use std::{
4 fmt,
5 io::{self, Read},
6};
7
8#[derive(Clone, Copy)]
24pub struct KtxDecoder<R> {
25 header: KtxHeader,
26 data: R,
27}
28
29impl<R> AsRef<KtxHeader> for KtxDecoder<R> {
30 #[inline]
31 fn as_ref(&self) -> &KtxHeader {
32 &self.header
33 }
34}
35
36impl<R> fmt::Debug for KtxDecoder<R> {
37 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
38 fmt.debug_struct("KtxDecoder")
39 .field("header", &self.header)
40 .finish()
41 }
42}
43
44impl<R: io::Read> KtxDecoder<R> {
45 #[inline]
47 pub fn new(mut data: R) -> io::Result<Self> {
48 let mut header_data = [0; 64];
49 data.read_exact(&mut header_data)?;
50 let header = KtxHeader::new(&header_data);
51 Ok(Self { header, data })
52 }
53
54 #[inline]
56 pub fn read_textures(self) -> Textures<R> {
57 Textures {
58 header: self.header,
59 data: self.data,
60 next_level: 0,
61 }
62 }
63
64 #[inline]
76 pub fn header(&self) -> KtxHeader {
77 self.header
78 }
79}
80
81#[derive(Debug)]
86pub struct Textures<R> {
87 header: KtxHeader,
88 data: R,
89 next_level: u32,
90}
91
92impl<R: io::Read> Iterator for Textures<R> {
93 type Item = Vec<u8>;
94
95 fn next(&mut self) -> Option<Self::Item> {
96 if self.next_level >= self.header.mipmap_levels() {
97 None
98 } else {
99 if self.next_level == 0 && self.header.bytes_of_key_value_data() != 0 {
101 let mut discard = Vec::with_capacity(self.header.bytes_of_key_value_data() as _);
102 self.data
103 .by_ref()
104 .take(self.header.bytes_of_key_value_data() as _)
105 .read_to_end(&mut discard)
106 .ok()?;
107 }
108
109 self.next_level += 1;
110 let mut level_len = {
111 let mut len = [0; 4];
112 self.data.read_exact(&mut len).ok()?;
113 if self.header.big_endian() {
114 BigEndian::read_u32(&len)
115 } else {
116 LittleEndian::read_u32(&len)
117 }
118 };
119
120 if self.header.array_elements() == 0 && self.header.faces() == 6 {
121 level_len *= 6;
123 }
124
125 let mut level = Vec::with_capacity(level_len as _);
126 self.data
127 .by_ref()
128 .take(level_len as _)
129 .read_to_end(&mut level)
130 .ok()?;
131 Some(level)
132 }
133 }
134}
135
136impl<R: io::Read> std::iter::FusedIterator for Textures<R> {}