1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
use block_device::BlockDevice;
use crate::BUFFER_SIZE;
use crate::tool::read_le_u32;

#[derive(Debug, Copy, Clone)]
pub struct FAT<T>
    where T: BlockDevice + Clone + Copy,
          <T as BlockDevice>::Error: core::fmt::Debug {
    device: T,
    fat_offset: usize,
    start_cluster: u32,
    previous_cluster: u32,
    pub(crate) current_cluster: u32,
    next_cluster: Option<u32>,
    buffer: [u8; BUFFER_SIZE],
}

impl<T> FAT<T>
    where T: BlockDevice + Clone + Copy,
          <T as BlockDevice>::Error: core::fmt::Debug {
    pub(crate) fn new(cluster: u32, device: T, fat_offset: usize) -> Self {
        Self {
            device,
            fat_offset,
            start_cluster: cluster,
            previous_cluster: 0,
            current_cluster: 0,
            next_cluster: None,
            buffer: [0; BUFFER_SIZE],
        }
    }

    pub(crate) fn blank_cluster(&mut self) -> u32 {
        let mut cluster = 0;
        let mut done = false;

        for block in 0.. {
            self.device.read(&mut self.buffer,
                             self.fat_offset + block * BUFFER_SIZE,
                             1).unwrap();
            for i in (0..BUFFER_SIZE).step_by(4) {
                if read_le_u32(&self.buffer[i..i + 4]) == 0 {
                    done = true;
                    break;
                } else { cluster += 1; }
            }
            if done { break; }
        }
        cluster
    }

    pub(crate) fn write(&mut self, cluster: u32, value: u32) {
        let offset = (cluster as usize) * 4;
        let block_offset = offset / BUFFER_SIZE;
        let offset_left = offset % BUFFER_SIZE;
        let offset = self.fat_offset + block_offset * BUFFER_SIZE;
        let mut value: [u8; 4] = value.to_be_bytes();
        value.reverse();

        self.device.read(&mut self.buffer,
                         offset,
                         1).unwrap();
        self.buffer[offset_left..offset_left + 4].copy_from_slice(&value);
        self.device.write(&self.buffer,
                          offset,
                          1).unwrap();
    }

    pub(crate) fn refresh(&mut self, start_cluster: u32) {
        self.current_cluster = 0;
        self.start_cluster = start_cluster;
    }

    pub(crate) fn previous(&mut self) {
        if self.current_cluster != 0 {
            self.next_cluster = Some(self.current_cluster);
            self.current_cluster = self.previous_cluster;
        }
    }

    pub(crate) fn next_is_none(&self) -> bool {
        self.next_cluster.is_none()
    }

    fn current_cluster_usize(&self) -> usize {
        self.current_cluster as usize
    }
}

impl<T> Iterator for FAT<T>
    where T: BlockDevice + Clone + Copy,
          <T as BlockDevice>::Error: core::fmt::Debug {
    type Item = Self;

    fn next(&mut self) -> Option<Self::Item> {
        if self.current_cluster == 0 {
            self.current_cluster = self.start_cluster;
        } else {
            let next_cluster = self.next_cluster;
            if next_cluster.is_some() {
                self.previous_cluster = self.current_cluster;
                self.current_cluster = next_cluster.unwrap();
            } else {
                return None;
            }
        }

        let offset = self.current_cluster_usize() * 4;
        let block_offset = offset / BUFFER_SIZE;
        let offset_left = offset % BUFFER_SIZE;

        self.device.read(&mut self.buffer,
                         self.fat_offset + block_offset * BUFFER_SIZE,
                         1).unwrap();

        let next_cluster = read_le_u32(&self.buffer[offset_left..offset_left + 4]);
        let next_cluster = if next_cluster == 0x0FFFFFFF {
            None
        } else {
            Some(next_cluster)
        };

        self.next_cluster = next_cluster;

        Some(Self {
            next_cluster,
            ..(*self)
        })
    }
}