homework: add method to retrieve device to house and implement From trait for PowerSocket and Thermometer

This commit is contained in:
5 changed files with 68 additions and 10 deletions

View File

@@ -79,10 +79,10 @@
- [x] Реализовать трейт Debug на всех типах.
- [x] Добавить возможность динамически добавлять/удалять устройства в комнату.
- [x] Добавить возможность динамически добавлять/удалять комнату в дом.
- [ ] Добавить в тип умного дома метод, позволяющий сразу получить ссылку на умное устройство. Метод принимает имя комнаты
- [x] Добавить в тип умного дома метод, позволяющий сразу получить ссылку на умное устройство. Метод принимает имя комнаты
и имя устройства. В случае, если устройство или комната не найдены, возвращать тип ошибки, сообщающий, что именно
произошло. Тип ошибки должен реализовывать трейт `std::error::Error`.
- [ ] Добавить реализации трейта `From`, позволяющие преобразовывать объекты умной розетки и умного термометра в объект
- [x] Добавить реализации трейта `From`, позволяющие преобразовывать объекты умной розетки и умного термометра в объект
умного устройства.
- [ ] Написать макрос для упрощенного создания комнаты, принимающий пары вида (ключ, объект умной розетки) или (ключ,
объект умного термометра) и возвращающий объект комнаты, содержащей все перечисленные устройства с

View File

@@ -30,6 +30,18 @@ impl Device {
}
}
impl From<super::Thermometer> for Device {
fn from(value: super::Thermometer) -> Self {
Device::Thermometer(value)
}
}
impl From<super::PowerSocket> for Device {
fn from(value: super::PowerSocket) -> Self {
Device::PowerSocket(value)
}
}
#[cfg(test)]
mod tests {
use super::*;

23
smart-house/src/error.rs Normal file
View File

@@ -0,0 +1,23 @@
use std::fmt::{Display, Formatter};
#[derive(Debug)]
pub struct Error {
message: String,
}
impl Error {
pub fn new(message: impl AsRef<str>) -> 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 {}

View File

@@ -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");
}
}

View File

@@ -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;