pub const BITS_IN_BYTE: usize = 8; pub const BITS_IN_WORD: usize = 32; use std::fs::File; use std::io::{Cursor, Write, Read}; use crate::simulator::disk::SECTOR_SIZE; pub struct BitMap { num_bits: usize, num_words: usize, map: Vec, } impl BitMap { /// Initialize a bitmap with "nitems" bits, so that every bit is clear. /// it can be added somewhere on a list. /// /// ### Parameters /// - **nitems** is the number of bits in the bitmap. ///---------------------------------------------------------------------- pub fn init_bitmap(&self, n_items: usize) -> BitMap { let mut tmp: Vec; BitMap{ num_bits: n_items, num_words: (n_items + SECTOR_SIZE as usize -1) / SECTOR_SIZE as usize, map: tmp, }; *self } /// Set the "nth" bit in a bitmap. /// ### Parameters /// - **which** is the number of the bit to be set. pub fn mark(&mut self, which: usize) { assert!(which >= 0 && which < self.num_bits); self.map[which / BITS_IN_WORD] |= 1 << (which % BITS_IN_WORD); } /// return true if the "nth" bit is set. /// /// ### Paramenters /// - **which** is the number of the bit to be tested. pub fn test(&self, which: usize) -> bool { assert!(which < self.num_bits); (self.map[which / BITS_IN_WORD] & (1 << (which % BITS_IN_WORD))) != 0 } /// Return the number of the first bit which is clear. /// As a side effect, set the bit (mark it as in use). /// (In other words, find and allocate a bit.) /// If no bits are clear, return ERROR pub fn find(&mut self) -> i32 { for i in 0..self.num_bits { if !self.test(i) { self.mark(i); return i as i32; } } -1 } /// Clear the "nth" bit in a bitmap. /// ### Parameters /// - **which** is the number of the bit to be cleared. pub fn clear(&mut self, which: usize) { assert!(which < self.num_bits, "index out of range"); let word_idx = which / BITS_IN_WORD; let bit_idx = which % BITS_IN_WORD; self.map[word_idx] &= !(1 << bit_idx); } /// Return the number of clear bits in the bitmap. /// (In other words, how many bits are unallocated?) pub fn num_clear(&self) -> i32 { let mut count = 0; for i in 0..self.num_bits { if !self.test(i) { count += 1; } } count } /// Print the contents of the bitmap, for debugging. /// Could be done in a number of ways, but we just print the #'s of /// all the bits that are set in the bitmap. pub fn print(&self) { println!("Bitmap set:"); for i in 0..self.num_bits { if self.test(i) { print!("{}, ", i); } } println!(); } ///Initialize the contents of a bitmap from a Nachos file. /// /// ### Parameters /// - **file** is the place to read the bitmap from pub fn fetch_from(&mut self, file_path: &str) -> std::io::Result<&Vec> { // Ouvre le fichier en mode lecture seule let mut file = File::open(file_path)?; // Lit les octets du fichier dans un buffer let mut buffer = vec![0; self.num_words * std::mem::size_of::()]; file.read_exact(&mut buffer)?; // Convertit les octets en vecteur de u32 self.map = vec![0; self.num_words]; for i in 0..self.num_words { let j = i * std::mem::size_of::(); let bytes = [ buffer[j], buffer[j+1], buffer[j+2], buffer[j+3] ]; self.map[i] = u32::from_le_bytes(bytes); } Ok(&self.map) } /// Store the contents of a bitmap to a Nachos file. /// /// ### Paramenters /// - **file** is the place to write the bitmap to pub fn write_back(&mut self, file_path: &str) -> std::io::Result<()> { // Encapsule le vecteur dans un std::io::Cursor pour l'utiliser comme un std::io::Write let mut cursor = Cursor::new(Vec::::new()); for u32_val in self.map.as_mut_slice() { cursor.write_all(&u32_val.to_le_bytes())?; } // Ouvre le fichier en mode écriture let mut file = File::create(file_path)?; // Écrit les données dans le fichier file.write_all(&cursor.into_inner())?; Ok(()) } }