diff --git a/smart-house/README.md b/smart-house/README.md index 1324022..ea115e7 100644 --- a/smart-house/README.md +++ b/smart-house/README.md @@ -79,10 +79,10 @@ - [x] Реализовать трейт Debug на всех типах. - [x] Добавить возможность динамически добавлять/удалять устройства в комнату. - [x] Добавить возможность динамически добавлять/удалять комнату в дом. -- [ ] Добавить в тип умного дома метод, позволяющий сразу получить ссылку на умное устройство. Метод принимает имя комнаты +- [x] Добавить в тип умного дома метод, позволяющий сразу получить ссылку на умное устройство. Метод принимает имя комнаты и имя устройства. В случае, если устройство или комната не найдены, возвращать тип ошибки, сообщающий, что именно произошло. Тип ошибки должен реализовывать трейт `std::error::Error`. -- [ ] Добавить реализации трейта `From`, позволяющие преобразовывать объекты умной розетки и умного термометра в объект +- [x] Добавить реализации трейта `From`, позволяющие преобразовывать объекты умной розетки и умного термометра в объект умного устройства. - [ ] Написать макрос для упрощенного создания комнаты, принимающий пары вида (ключ, объект умной розетки) или (ключ, объект умного термометра) и возвращающий объект комнаты, содержащей все перечисленные устройства с diff --git a/smart-house/src/device.rs b/smart-house/src/device.rs index bc07094..6879709 100644 --- a/smart-house/src/device.rs +++ b/smart-house/src/device.rs @@ -30,6 +30,18 @@ impl Device { } } +impl From for Device { + fn from(value: super::Thermometer) -> Self { + Device::Thermometer(value) + } +} + +impl From for Device { + fn from(value: super::PowerSocket) -> Self { + Device::PowerSocket(value) + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/smart-house/src/error.rs b/smart-house/src/error.rs new file mode 100644 index 0000000..edb1227 --- /dev/null +++ b/smart-house/src/error.rs @@ -0,0 +1,23 @@ +use std::fmt::{Display, Formatter}; + +#[derive(Debug)] +pub struct Error { + message: String, +} + +impl Error { + pub fn new(message: impl AsRef) -> Self { + Self { + message: message.as_ref().to_string(), + } + } +} + +impl Display for Error { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + f.write_fmt(format_args!("{}", self.message))?; + Ok(()) + } +} + +impl std::error::Error for Error {} diff --git a/smart-house/src/house.rs b/smart-house/src/house.rs index 2154434..7c80473 100644 --- a/smart-house/src/house.rs +++ b/smart-house/src/house.rs @@ -1,4 +1,4 @@ -use crate::Room; +use crate::{Device, Error, Room}; use std::collections::HashMap; #[derive(Debug)] @@ -36,6 +36,16 @@ impl House { self.rooms.remove(key) } + pub fn get_device(&self, room: &str, device: &str) -> Result<&Device, Error> { + let Some(room) = self.get_room(room) else { + return Err(Error::new(format!("no room named '{}' found", room))); + }; + let Some(device) = room.get_device(device) else { + return Err(Error::new(format!("no device named '{}' found in room '{}'", device, room.get_name()))); + }; + Ok(device) + } + pub fn print_status(&self) { println!("HOUSE '{}':", self.address); println!("{}", "=".repeat(32)); @@ -58,17 +68,14 @@ mod tests { Room::new( "main", Box::new([ - Device::Thermometer(Thermometer::new("ThermA", 20.0)), - Device::PowerSocket(PowerSocket::new("PSocA", 12.34, false)), - Device::PowerSocket(PowerSocket::new("PSocB", 10.01, true)), + Thermometer::new("ThermA", 20.0).into(), + PowerSocket::new("PSocA", 12.34, false).into(), + PowerSocket::new("PSocB", 10.01, true).into(), ]), ), Room::new( "bedroom", - Box::new([ - Device::PowerSocket(PowerSocket::new("PSocC", 11.11, true)), - Device::Thermometer(Thermometer::new("ThermB", 17.99)), - ]), + Box::new([PowerSocket::new("PSocC", 11.11, true).into(), Thermometer::new("ThermB", 17.99).into()]), ), ]), ) @@ -124,4 +131,18 @@ mod tests { assert_eq!(result.get_name(), "bedroom"); assert_eq!(house.rooms.len(), 2); } + + #[test] + fn test_get_device() { + let house = create_test_house(); + + let result = house.get_device("empty", "dummy"); + assert_eq!(result.unwrap_err().to_string(), "no room named 'empty' found"); + + let result = house.get_device("main", "dummy"); + assert_eq!(result.unwrap_err().to_string(), "no device named 'dummy' found in room 'main'"); + + let result = house.get_device("main", "ThermA"); + assert_eq!(result.unwrap().get_name(), "ThermA"); + } } diff --git a/smart-house/src/lib.rs b/smart-house/src/lib.rs index 106c327..8247aa6 100644 --- a/smart-house/src/lib.rs +++ b/smart-house/src/lib.rs @@ -1,10 +1,12 @@ mod device; +mod error; mod house; mod power_socket; mod room; mod thermometer; pub use device::Device; +pub use error::Error; pub use house::House; pub use power_socket::PowerSocket; pub use room::Room;