From 133aa1b9c43295ceb25cf31a9ca79336627d73fb Mon Sep 17 00:00:00 2001 From: Alexander Baranov Date: Wed, 17 Dec 2025 18:25:44 +0300 Subject: [PATCH] add Room struct --- smart-house/README.md | 10 ++-- smart-house/src/device.rs | 8 ++- smart-house/src/device/power_socket.rs | 9 +++ smart-house/src/device/thermometer.rs | 9 +++ smart-house/src/room.rs | 76 ++++++++++++++++++++++++++ 5 files changed, 106 insertions(+), 6 deletions(-) diff --git a/smart-house/README.md b/smart-house/README.md index c3e3f7e..6412abc 100644 --- a/smart-house/README.md +++ b/smart-house/README.md @@ -30,11 +30,11 @@ - [x] Возвращать текущую мощность: если выключено — ноль, иначе произвольное число. - [x] Опишите тип: умное устройство. Тип должен содержать одно из устройств (умный термометр или розетку) и предоставлять следующий функционал: - [x] Выводить в стандартный вывод сообщение о состоянии устройства. -- [ ] Опишите тип: комната, содержащая массив умных устройств. Тип должен предоставлять следующий функционал: - - [ ] Конструктор, принимающий массив устройств. - - [ ] Можно получить ссылку на устройство по указанному индексу. - - [ ] Можно получить мутабельную ссылку на устройство по указанному индексу. - - [ ] Выводить в стандартный вывод отчёт о всех устройствах в комнате. +- [x] Опишите тип: комната, содержащая массив умных устройств. Тип должен предоставлять следующий функционал: + - [x] Конструктор, принимающий массив устройств. + - [x] Можно получить ссылку на устройство по указанному индексу. + - [x] Можно получить мутабельную ссылку на устройство по указанному индексу. + - [x] Выводить в стандартный вывод отчёт о всех устройствах в комнате. - [ ] Опишите тип: умный дом, содержащий массив комнат. Тип должен предоставлять следующий функционал: - [ ] Конструктор, принимающий массив комнат. - [ ] Можно получить ссылку на комнату по указанному индексу. diff --git a/smart-house/src/device.rs b/smart-house/src/device.rs index d9ca68d..9a73a64 100644 --- a/smart-house/src/device.rs +++ b/smart-house/src/device.rs @@ -3,6 +3,12 @@ mod power_socket; mod thermometer; -trait Device { +pub trait Device { fn print_status(&self); + fn as_any(&self) -> &dyn Any; + fn as_mut_any(&mut self) -> &mut dyn Any; } + +pub use power_socket::PowerSocket; +use std::any::Any; +pub use thermometer::Thermometer; diff --git a/smart-house/src/device/power_socket.rs b/smart-house/src/device/power_socket.rs index edc2907..edba6f2 100644 --- a/smart-house/src/device/power_socket.rs +++ b/smart-house/src/device/power_socket.rs @@ -1,6 +1,7 @@ #![allow(unused)] use crate::device::Device; +use std::any::Any; use std::fmt::Display; pub struct PowerSocket { @@ -35,6 +36,14 @@ impl Device for PowerSocket { fn print_status(&self) { println!("{}", self.display()) } + + fn as_any(&self) -> &dyn Any { + self + } + + fn as_mut_any(&mut self) -> &mut dyn Any { + self + } } #[cfg(test)] diff --git a/smart-house/src/device/thermometer.rs b/smart-house/src/device/thermometer.rs index a63fb95..86b4256 100644 --- a/smart-house/src/device/thermometer.rs +++ b/smart-house/src/device/thermometer.rs @@ -1,5 +1,6 @@ #![allow(unused)] +use std::any::Any; use std::fmt::Display; pub struct Thermometer { @@ -24,6 +25,14 @@ impl super::Device for Thermometer { fn print_status(&self) { println!("{}", self.display()) } + + fn as_any(&self) -> &dyn Any { + self + } + + fn as_mut_any(&mut self) -> &mut dyn Any { + self + } } #[cfg(test)] diff --git a/smart-house/src/room.rs b/smart-house/src/room.rs index 8b13789..861f0ee 100644 --- a/smart-house/src/room.rs +++ b/smart-house/src/room.rs @@ -1 +1,77 @@ +#![allow(unused)] +use crate::device::Device; +struct Room<'a> { + name: String, + devices: &'a mut [Box], +} + +impl<'a> Room<'a> { + pub fn new(name: impl AsRef, devices: &'a mut [Box]) -> Self { + Self { + name: name.as_ref().to_string(), + devices, + } + } + + pub fn get(&'a self, idx: usize) -> &'a dyn Device { + if idx >= self.devices.len() { + panic!("Index is out of bounds") + } + self.devices[idx].as_ref() + } + + pub fn get_mut(&'a mut self, idx: usize) -> &'a mut dyn Device { + if idx >= self.devices.len() { + panic!("Index is out of bounds") + } + self.devices[idx].as_mut() + } + + pub fn print(&self) { + println!("{}", "=".repeat(16)); + println!("{}:", self.name); + println!("{}", "-".repeat(16)); + for d in self.devices.iter() { + d.print_status(); + } + println!("{}", "=".repeat(16)); + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::device::{PowerSocket, Thermometer}; + use std::fmt::format; + use std::mem; + + #[test] + fn smoke_test() { + let mut devices = Box::new([Box::new(PowerSocket::new(12.34, false)) as Box, Box::new(Thermometer::new(21.56))]); + let mut room = Room::new("test_room", &mut *devices); + assert_eq!(room.name, "test_room"); + room.print(); + + assert_eq!( + format!("{}", room.get(0).as_any().downcast_ref::().unwrap().display()), + "PowerSocket[ OFF : 0.0 ]" + ); + assert_eq!( + format!("{}", room.get(1).as_any().downcast_ref::().unwrap().display()), + "Thermometer[ 21.6 ]" + ); + + room.get_mut(0).as_mut_any().downcast_mut::().unwrap().set_on(true); + + // room.print(); // TODO satisfy compiler + } + + #[test] + #[should_panic(expected = "Index is out of bounds")] + fn panic_test() { + let mut devices = [Box::new(PowerSocket::new(12.34, false)) as Box, Box::new(Thermometer::new(21.56))]; + let mut room = Room::new("test_room", &mut devices); + room.get(2); + } +}