diff --git a/smart-house/README.md b/smart-house/README.md index ca4334f..8c9ff59 100644 --- a/smart-house/README.md +++ b/smart-house/README.md @@ -185,7 +185,7 @@ Реализовать билдер для умного дома, позволяющий инициализировать объект умного дома в [таком стиле](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=5d0527e4684f726d54dc375829d983f4). -- [ ] До добавления первой комнаты, билдер запрещает добавлять устройства. Это должно контролироваться компилятором. +- [x] До добавления первой комнаты, билдер запрещает добавлять устройства. Это должно контролироваться компилятором. Реализовать компоновщик для построения отчёта об объектах умного дома в [таком стиле](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=c07dfc726e8ccbccdcc2d88a79d3f190). diff --git a/smart-house/src/bin/room_builder.rs b/smart-house/src/bin/room_builder.rs new file mode 100644 index 0000000..f59bb2b --- /dev/null +++ b/smart-house/src/bin/room_builder.rs @@ -0,0 +1,11 @@ +use smart_house::{HouseBuilder, PowerSocket, PrintStatus, Thermometer}; + +fn main() { + let house = HouseBuilder::new() + .add_room("Main") + .add_device("PSockA", PowerSocket::stub(12.0, false)) + .add_room("Hall") + .add_device("ThermA", Thermometer::stub(18.5)) + .build(); + house.print_status(); +} diff --git a/smart-house/src/builders.rs b/smart-house/src/builders.rs index 71e797c..924a65b 100644 --- a/smart-house/src/builders.rs +++ b/smart-house/src/builders.rs @@ -1,51 +1,53 @@ use crate::{Device, House, Room}; use std::collections::HashMap; -struct HouseBuilder { +pub struct HouseBuilder { rooms: HashMap, } impl HouseBuilder { - fn new() -> Self { - Self { - rooms: HashMap::new() - } + pub fn new() -> Self { + Self { rooms: HashMap::new() } } - fn build(self) -> House { - House::new(self.rooms) - } - - fn add_room(self, name: &str) -> RoomBuilder { + pub fn add_room(self, name: &str) -> RoomBuilder { RoomBuilder { parent: self, name: name.to_string(), - devices: HashMap::new() + devices: HashMap::new(), } } + + pub fn build(self) -> House { + House::new(self.rooms) + } } -struct RoomBuilder { +impl Default for HouseBuilder { + fn default() -> Self { + Self::new() + } +} + +pub struct RoomBuilder { parent: HouseBuilder, name: String, devices: HashMap, } impl RoomBuilder { - - fn add_device(mut self, name: &str, device: Device) -> Self { - self.devices.insert(name.to_string(), device); + pub fn add_device(mut self, name: &str, device: impl Into) -> Self { + self.devices.insert(name.to_string(), device.into()); self } - fn add_room(mut self, name: &str) -> RoomBuilder { + pub fn add_room(mut self, name: &str) -> RoomBuilder { self.parent.rooms.insert(self.name, Room::new(self.devices)); self.parent.add_room(name) } - fn build(mut self) -> House { + pub fn build(mut self) -> House { self.parent.rooms.insert(self.name, Room::new(self.devices)); self.parent.build() } - } diff --git a/smart-house/src/device.rs b/smart-house/src/device.rs index 2cb4ae3..16835b5 100644 --- a/smart-house/src/device.rs +++ b/smart-house/src/device.rs @@ -1,5 +1,6 @@ use crate::PrintStatus; use std::fmt::Display; +use std::io::Write; #[derive(Debug)] pub enum Device { @@ -33,8 +34,8 @@ impl From for Device { } impl PrintStatus for Device { - fn print_status(&self) { - println!("{}", self.display()); + fn print_status_into(&self, out: &mut impl Write) -> Result<(), std::io::Error> { + out.write_fmt(format_args!("{}", self.display())) } } diff --git a/smart-house/src/house.rs b/smart-house/src/house.rs index a619e7c..9741ad4 100644 --- a/smart-house/src/house.rs +++ b/smart-house/src/house.rs @@ -1,5 +1,6 @@ use crate::{Device, Error, PrintStatus, Room}; use std::collections::HashMap; +use std::io::Write; #[derive(Debug)] pub struct House { @@ -39,13 +40,15 @@ impl House { } impl PrintStatus for House { - fn print_status(&self) { + fn print_status_into(&self, out: &mut impl Write) -> Result<(), std::io::Error> { for (room_name, room) in self.rooms.iter() { - println!("{}:", room_name); - println!("{}", "-".repeat(32)); - room.print_status(); + out.write_fmt(format_args!("{}:", room_name))?; + out.write_fmt(format_args!("{}", "-".repeat(32)))?; + room.print_status_into(out)?; + out.write_fmt(format_args!("\n"))?; println!(); } + Ok(()) } } diff --git a/smart-house/src/lib.rs b/smart-house/src/lib.rs index 77b82da..35c3fd0 100644 --- a/smart-house/src/lib.rs +++ b/smart-house/src/lib.rs @@ -8,6 +8,7 @@ mod builders; mod print_status; mod thermometer; +pub use builders::{HouseBuilder, RoomBuilder}; pub use device::Device; pub use error::Error; pub use house::House; diff --git a/smart-house/src/print_status.rs b/smart-house/src/print_status.rs index 3f06159..92308dc 100644 --- a/smart-house/src/print_status.rs +++ b/smart-house/src/print_status.rs @@ -1,3 +1,9 @@ pub trait PrintStatus { - fn print_status(&self); + fn print_status_into(&self, out: &mut impl std::io::Write) -> Result<(), std::io::Error>; + + fn print_status(&self) { + if let Err(e) = self.print_status_into(&mut std::io::stdout()) { + eprintln!("Unexpected print error: {:?}", e); + } + } } diff --git a/smart-house/src/room.rs b/smart-house/src/room.rs index 38efac2..f54c5a9 100644 --- a/smart-house/src/room.rs +++ b/smart-house/src/room.rs @@ -1,5 +1,6 @@ use crate::{Device, PrintStatus}; use std::collections::HashMap; +use std::io::Write; #[derive(Debug)] pub struct Room { @@ -29,11 +30,12 @@ impl Room { } impl PrintStatus for Room { - fn print_status(&self) { + fn print_status_into(&self, out: &mut impl Write) -> Result<(), std::io::Error> { for (name, device) in self.devices.iter() { - print!("{} => ", name); - device.print_status(); + out.write_fmt(format_args!("{} => ", name))?; + device.print_status_into(out)?; } + Ok(()) } }