Skip to main content

iso9660_simple/
iter.rs

1use alloc::borrow::ToOwned;
2use alloc::string::String;
3use alloc::vec;
4use core::cell::RefCell;
5use zerocopy::IntoBytes;
6
7use crate::{
8    ISO9660, ISODirectoryEntry, ISODirectoryRecord, ISOInternalFlags, PRIMARY_VOLUME_DESCRIPTOR_POSITION, Read, descriptors::{Descriptor, DescriptorType}
9};
10
11pub struct DirectoryIter<'iso> {
12    iso: RefCell<&'iso mut ISO9660>,
13    byte_offset: RefCell<usize>,
14}
15
16impl<'iso> DirectoryIter<'iso> {
17    pub fn new(iso: &'iso mut ISO9660, byte_offset: usize) -> Self {
18        Self {
19            iso: iso.into(),
20            byte_offset: byte_offset.into(),
21        }
22    }
23}
24
25impl Iterator for &DirectoryIter<'_> {
26    type Item = ISODirectoryEntry;
27
28    fn next(&mut self) -> Option<Self::Item> {
29        let mut record = ISODirectoryRecord::default();
30        let ptr = record.as_mut_bytes();
31
32        self.iso
33            .borrow_mut()
34            .device
35            .read(*self.byte_offset.borrow() as _, ptr);
36
37        if record.length == 0 {
38            return None;
39        }
40
41        let main_part_size = size_of::<ISODirectoryRecord>();
42
43        let name: String;
44
45        if self.iso.borrow().flags.contains(ISOInternalFlags::HasJoliet) {
46            name = self.iso.borrow_mut().read_joliet_name(
47                *self.byte_offset.borrow() + main_part_size,
48                record.file_identifier_length as _
49            ).expect("Expected a valid UCS-2 name");
50        } else {
51            let main_part_size = main_part_size + record.file_identifier_length as usize;
52            let extension_size = record.length as usize - main_part_size;
53
54            // println!("Ext size: {}", extension_size);
55
56            let rr_name = self.iso.borrow_mut().read_rock_ridge_name(
57                *self.byte_offset.borrow(),
58                main_part_size,
59                extension_size,
60            );
61
62            name = if let Some(n) = rr_name {
63                n
64            } else {
65                let size = record.file_identifier_length as usize;
66
67                let mut result = vec![0; size];
68
69                self.iso.borrow_mut().device.read(
70                    *self.byte_offset.borrow() + size_of::<ISODirectoryRecord>(),
71                    &mut result,
72                );
73
74                let final_name = if result[0] == 0 {
75                    "."
76                } else if result[0] == 1 {
77                    ".."
78                } else {
79                    str::from_utf8(&result).unwrap()
80                };
81
82                final_name.to_owned()
83            };
84        }
85
86        *self.byte_offset.borrow_mut() += record.length as usize;
87
88        Some(ISODirectoryEntry { record, name })
89    }
90}
91
92pub struct DescriptorIterator<'dev> {
93    device: &'dev mut dyn Read,
94    position: usize,
95}
96
97impl<'a> DescriptorIterator<'a> {
98    pub fn new(dev: &'a mut dyn Read) -> Self {
99        Self {
100            device: dev,
101            position: PRIMARY_VOLUME_DESCRIPTOR_POSITION,
102        }
103    }
104}
105
106impl<'a> Iterator for DescriptorIterator<'a> {
107    type Item = Descriptor;
108
109    fn next(&mut self) -> Option<Self::Item> {
110        let mut buffer = [0u8; 2048];
111
112        self.device.read(self.position, &mut buffer)?;
113
114        loop {
115            let Ok(descriptor): Result<Self::Item, _> = zerocopy::try_transmute!(buffer) else {
116                // invalid type, skip to next descriptor immediately
117                self.position += core::mem::size_of::<Descriptor>();
118                continue;
119            };
120
121            break if descriptor.desc_type == DescriptorType::Terminator {
122                None
123            } else {
124                self.position += core::mem::size_of::<Descriptor>();
125                Some(descriptor)
126            };
127        }
128    }
129}