homework: options instead panics

This commit is contained in:
4 changed files with 42 additions and 39 deletions

View File

@@ -71,8 +71,8 @@
### Описание/Пошаговая инструкция выполнения домашнего задания: ### Описание/Пошаговая инструкция выполнения домашнего задания:
Добавить обработку ошибок: Добавить обработку ошибок:
- [ ] Заменить паники на возврат Option в методах получения комнаты по ключу. - [x] Заменить паники на возврат Option в методах получения комнаты по ключу.
- [ ] Заменить паники на возврат Option в методах получения устройства по ключу. - [x] Заменить паники на возврат Option в методах получения устройства по ключу.
Доработать хранение объектов: Доработать хранение объектов:
- [ ] Заменить массивы устройств и комнат на ассоциативные коллекции из std. В качестве ключей использовать строки. - [ ] Заменить массивы устройств и комнат на ассоциативные коллекции из std. В качестве ключей использовать строки.

View File

@@ -13,20 +13,16 @@ impl House {
} }
} }
fn check_bounds(&self, idx: usize) { fn is_valid_idx(&self, idx: usize) -> bool {
if idx >= self.rooms.len() { idx < self.rooms.len()
panic!("Index is out of bounds")
}
} }
pub fn get_room(&self, idx: usize) -> &Room { pub fn get_room(&self, idx: usize) -> Option<&Room> {
self.check_bounds(idx); if self.is_valid_idx(idx) { Some(&self.rooms[idx]) } else { None }
&self.rooms[idx]
} }
pub fn get_room_mut(&mut self, idx: usize) -> &mut Room { pub fn get_room_mut(&mut self, idx: usize) -> Option<&mut Room> {
self.check_bounds(idx); if self.is_valid_idx(idx) { Some(&mut self.rooms[idx]) } else { None }
&mut self.rooms[idx]
} }
pub fn print_status(&self) { pub fn print_status(&self) {
@@ -70,22 +66,33 @@ mod tests {
house.print_status(); house.print_status();
assert_eq!(house.address, "Best street, 777"); assert_eq!(house.address, "Best street, 777");
assert_eq!(format!("{}", house.get_room(0).get_device(0).display()), "DEV:Thermometer[ 20.0 ]"); assert_eq!(
assert_eq!(format!("{}", house.get_room(0).get_device(1).display()), "DEV:PowerSocket[ OFF : 0.0 ]"); format!("{}", house.get_room(0).unwrap().get_device(0).unwrap().display()),
assert_eq!(format!("{}", house.get_room(1).get_device(0).display()), "DEV:PowerSocket[ ON : 11.1 ]"); "DEV:Thermometer[ 20.0 ]"
);
assert_eq!(
format!("{}", house.get_room(0).unwrap().get_device(1).unwrap().display()),
"DEV:PowerSocket[ OFF : 0.0 ]"
);
assert_eq!(
format!("{}", house.get_room(1).unwrap().get_device(0).unwrap().display()),
"DEV:PowerSocket[ ON : 11.1 ]"
);
let Device::PowerSocket(powers_socket) = house.get_room_mut(0).get_device_mut(1) else { let Device::PowerSocket(powers_socket) = house.get_room_mut(0).unwrap().get_device_mut(1).unwrap() else {
unreachable!() unreachable!()
}; };
powers_socket.set_on(true); powers_socket.set_on(true);
assert_eq!(format!("{}", house.get_room(0).get_device(1).display()), "DEV:PowerSocket[ ON : 12.3 ]"); assert_eq!(
format!("{}", house.get_room(0).unwrap().get_device(1).unwrap().display()),
"DEV:PowerSocket[ ON : 12.3 ]"
);
} }
#[test] #[test]
#[should_panic(expected = "Index is out of bounds")] fn check_out_of_bounds() {
fn panic_test() {
let house = create_test_house(); let house = create_test_house();
house.check_bounds(2); assert!(house.get_room(2).is_none());
} }
} }

View File

@@ -26,7 +26,7 @@ fn main() {
house.print_status(); house.print_status();
print!("# Switching off a power socket in Hall... "); print!("# Switching off a power socket in Hall... ");
let Device::PowerSocket(power_socket) = house.get_room_mut(0).get_device_mut(0) else { let Device::PowerSocket(power_socket) = house.get_room_mut(0).unwrap().get_device_mut(0).unwrap() else {
println!("FAILED!"); println!("FAILED!");
return; return;
}; };

View File

@@ -13,20 +13,17 @@ impl Room {
} }
} }
fn check_bounds(&self, idx: usize) { fn is_valid_idx(&self, idx: usize) -> bool {
if idx >= self.devices.len() { idx < self.devices.len()
panic!("Index is out of bounds")
}
} }
pub fn get_device(&self, idx: usize) -> &Device { pub fn get_device(&self, idx: usize) -> Option<&Device> {
self.check_bounds(idx); if self.is_valid_idx(idx) { Some(&self.devices[idx]) } else { None }
&self.devices[idx]
} }
pub fn get_device_mut(&mut self, idx: usize) -> &mut Device { pub fn get_device_mut(&mut self, idx: usize) -> Option<&mut Device> {
self.check_bounds(idx); self.is_valid_idx(idx);
&mut self.devices[idx] Some(&mut self.devices[idx])
} }
pub fn print_status(&self) { pub fn print_status(&self) {
@@ -53,21 +50,20 @@ mod tests {
assert_eq!(room.name, "test_room"); assert_eq!(room.name, "test_room");
room.print_status(); room.print_status();
assert_eq!(format!("{}", room.get_device(0).display()), "DEV:PowerSocket[ OFF : 0.0 ]"); assert_eq!(format!("{}", room.get_device(0).unwrap().display()), "DEV:PowerSocket[ OFF : 0.0 ]");
assert_eq!(format!("{}", room.get_device(1).display()), "DEV:Thermometer[ 21.6 ]"); assert_eq!(format!("{}", room.get_device(1).unwrap().display()), "DEV:Thermometer[ 21.6 ]");
let Device::PowerSocket(power_socket) = room.get_device_mut(0) else { let Device::PowerSocket(power_socket) = room.get_device_mut(0).unwrap() else {
unreachable!() unreachable!()
}; };
power_socket.set_on(true); power_socket.set_on(true);
assert_eq!(format!("{}", room.get_device(0).display()), "DEV:PowerSocket[ ON : 12.3 ]"); assert_eq!(format!("{}", room.get_device(0).unwrap().display()), "DEV:PowerSocket[ ON : 12.3 ]");
assert_eq!(format!("{}", room.get_device(1).display()), "DEV:Thermometer[ 21.6 ]"); assert_eq!(format!("{}", room.get_device(1).unwrap().display()), "DEV:Thermometer[ 21.6 ]");
} }
#[test] #[test]
#[should_panic(expected = "Index is out of bounds")] fn check_out_of_bounds() {
fn panic_test() {
let room = Room::new( let room = Room::new(
"test_room", "test_room",
Box::new([ Box::new([
@@ -75,6 +71,6 @@ mod tests {
Device::Thermometer(Thermometer::new(21.56)), Device::Thermometer(Thermometer::new(21.56)),
]), ]),
); );
room.check_bounds(2); assert!(room.get_device(2).is_none());
} }
} }