builders - done

This commit is contained in:
8 changed files with 55 additions and 29 deletions

View File

@@ -185,7 +185,7 @@
Реализовать билдер для умного дома, позволяющий инициализировать объект умного дома в [таком стиле](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=5d0527e4684f726d54dc375829d983f4). Реализовать билдер для умного дома, позволяющий инициализировать объект умного дома в [таком стиле](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). Реализовать компоновщик для построения отчёта об объектах умного дома в [таком стиле](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=c07dfc726e8ccbccdcc2d88a79d3f190).

View File

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

View File

@@ -1,51 +1,53 @@
use crate::{Device, House, Room}; use crate::{Device, House, Room};
use std::collections::HashMap; use std::collections::HashMap;
struct HouseBuilder { pub struct HouseBuilder {
rooms: HashMap<String, Room>, rooms: HashMap<String, Room>,
} }
impl HouseBuilder { impl HouseBuilder {
fn new() -> Self { pub fn new() -> Self {
Self { Self { rooms: HashMap::new() }
rooms: HashMap::new()
}
} }
fn build(self) -> House { pub fn add_room(self, name: &str) -> RoomBuilder {
House::new(self.rooms)
}
fn add_room(self, name: &str) -> RoomBuilder {
RoomBuilder { RoomBuilder {
parent: self, parent: self,
name: name.to_string(), 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, parent: HouseBuilder,
name: String, name: String,
devices: HashMap<String, Device>, devices: HashMap<String, Device>,
} }
impl RoomBuilder { impl RoomBuilder {
pub fn add_device(mut self, name: &str, device: impl Into<Device>) -> Self {
fn add_device(mut self, name: &str, device: Device) -> Self { self.devices.insert(name.to_string(), device.into());
self.devices.insert(name.to_string(), device);
self 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.rooms.insert(self.name, Room::new(self.devices));
self.parent.add_room(name) 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.rooms.insert(self.name, Room::new(self.devices));
self.parent.build() self.parent.build()
} }
} }

View File

@@ -1,5 +1,6 @@
use crate::PrintStatus; use crate::PrintStatus;
use std::fmt::Display; use std::fmt::Display;
use std::io::Write;
#[derive(Debug)] #[derive(Debug)]
pub enum Device { pub enum Device {
@@ -33,8 +34,8 @@ impl From<super::PowerSocket> for Device {
} }
impl PrintStatus for Device { impl PrintStatus for Device {
fn print_status(&self) { fn print_status_into(&self, out: &mut impl Write) -> Result<(), std::io::Error> {
println!("{}", self.display()); out.write_fmt(format_args!("{}", self.display()))
} }
} }

View File

@@ -1,5 +1,6 @@
use crate::{Device, Error, PrintStatus, Room}; use crate::{Device, Error, PrintStatus, Room};
use std::collections::HashMap; use std::collections::HashMap;
use std::io::Write;
#[derive(Debug)] #[derive(Debug)]
pub struct House { pub struct House {
@@ -39,13 +40,15 @@ impl House {
} }
impl PrintStatus for 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() { for (room_name, room) in self.rooms.iter() {
println!("{}:", room_name); out.write_fmt(format_args!("{}:", room_name))?;
println!("{}", "-".repeat(32)); out.write_fmt(format_args!("{}", "-".repeat(32)))?;
room.print_status(); room.print_status_into(out)?;
out.write_fmt(format_args!("\n"))?;
println!(); println!();
} }
Ok(())
} }
} }

View File

@@ -8,6 +8,7 @@ mod builders;
mod print_status; mod print_status;
mod thermometer; mod thermometer;
pub use builders::{HouseBuilder, RoomBuilder};
pub use device::Device; pub use device::Device;
pub use error::Error; pub use error::Error;
pub use house::House; pub use house::House;

View File

@@ -1,3 +1,9 @@
pub trait PrintStatus { 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);
}
}
} }

View File

@@ -1,5 +1,6 @@
use crate::{Device, PrintStatus}; use crate::{Device, PrintStatus};
use std::collections::HashMap; use std::collections::HashMap;
use std::io::Write;
#[derive(Debug)] #[derive(Debug)]
pub struct Room { pub struct Room {
@@ -29,11 +30,12 @@ impl Room {
} }
impl PrintStatus for 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() { for (name, device) in self.devices.iter() {
print!("{} => ", name); out.write_fmt(format_args!("{} => ", name))?;
device.print_status(); device.print_status_into(out)?;
} }
Ok(())
} }
} }