diff --git a/Cargo.lock b/Cargo.lock index f1ddc35..4f2ef07 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6,6 +6,17 @@ version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b585a98a234c46fc563103e9278c9391fde1f4e6850334da895d27edb9580f62" +[[package]] +name = "async-trait" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eb7f9ad01405feb3c1dac82463038945cf88eea4569acaf3ad662233496dd96" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "autocfg" version = "1.0.0" @@ -496,6 +507,7 @@ checksum = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" name = "rustybar" version = "0.1.0" dependencies = [ + "async-trait", "chrono", "dbus", "dbus-tokio", diff --git a/Cargo.toml b/Cargo.toml index 01c5078..a03e466 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,6 +6,7 @@ edition = "2018" [dependencies] +async-trait = "0.1" chrono = "0.4" dbus = "0.8" dbus-tokio = "0.5" diff --git a/src/main.rs b/src/main.rs index 48e5d7f..e6e3289 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,7 +3,6 @@ pub mod tile; pub mod tiles; use dbus_tokio::connection::new_session_sync; -use tile::Tile; use tokio::sync::mpsc::channel; use uuid::Uuid; @@ -20,31 +19,21 @@ async fn main() -> Result<(), Box> { let (sender, receiver) = channel(1024); - let tiles: Vec> = vec![ - Box::new(tiles::Load::new( - 0, - sender.clone(), - Uuid::new_v4().to_string().into(), - )), - Box::new(tiles::Memory::new( - 1, - sender.clone(), - Uuid::new_v4().to_string().into(), - )), - Box::new(tiles::Hostname::new( - 2, - sender.clone(), - Uuid::new_v4().to_string().into(), - )), - Box::new(tiles::Time::new( - 3, - sender, - Uuid::new_v4().to_string().into(), - )), + let mut index = 0usize; + let mut wrap = |module| { + let tile = tile::Tile::new(index, sender.clone(), Uuid::new_v4().to_string().into(), module); + index += 1; + tile + }; + let tiles = vec![ + wrap(Box::new(tiles::Load::new())), + wrap(Box::new(tiles::Memory::new())), + wrap(Box::new(tiles::Hostname::new())), + wrap(Box::new(tiles::Time::new())), ]; let num_tiles = tiles.len(); - for tile in tiles { + for tile in tiles.into_iter() { tile.spawn(); } diff --git a/src/tile.rs b/src/tile.rs index 864836f..a3f590c 100644 --- a/src/tile.rs +++ b/src/tile.rs @@ -1,6 +1,9 @@ +use async_trait::async_trait; use serde::{ser::Serializer, Serialize}; use smart_default::SmartDefault; +use std::fmt::Debug; use std::sync::Arc; +use tokio::sync::mpsc::{error::SendError, Sender}; use tokio::task::JoinHandle; #[derive(Copy, Clone, Debug, Serialize)] @@ -80,6 +83,49 @@ pub struct TileData { pub block: Block, } -pub trait Tile: Send + std::fmt::Debug { - fn spawn(self: Box) -> JoinHandle>>; +#[async_trait] +pub trait TileModule: Send + std::fmt::Debug { + async fn run(&mut self, sender: &mut BlockSender) -> Result<(), Box>; } + +#[derive(Debug)] +pub struct BlockSender { + sender_id: usize, + sender: Sender, + instance: Arc, +} + +impl BlockSender { + pub async fn send(&mut self, mut block: Block) -> Result<(), SendError> { + block.instance = self.instance.clone(); + let data = TileData { + block, + sender_id: self.sender_id, + }; + self.sender.send(data).await + } +} + +#[derive(Debug)] +pub struct Tile { + sender: BlockSender, + module: Box, +} + +impl Tile { + pub fn new(sender_id: usize, sender: Sender, instance: Arc, module: Box) -> Self { + Tile { + sender: BlockSender { + sender_id, + sender, + instance, + }, + module, + } + } + pub fn spawn(mut self) -> JoinHandle>> { + tokio::spawn(async move { + self.module.run(&mut self.sender).await + }) + } +} \ No newline at end of file diff --git a/src/tiles/hostname.rs b/src/tiles/hostname.rs index 55eef21..494c5be 100644 --- a/src/tiles/hostname.rs +++ b/src/tiles/hostname.rs @@ -1,31 +1,20 @@ -use crate::tile::{Block, Tile, TileData}; -use std::sync::Arc; +use crate::tile::{Block, BlockSender, TileModule}; +use async_trait::async_trait; use tokio::fs::File; use tokio::prelude::*; -use tokio::sync::mpsc::{error::SendError, Sender}; -use tokio::task::JoinHandle; -#[derive(Debug)] -pub struct Hostname { - sender_id: usize, - sender: Sender, - instance: Arc, -} +#[derive(Debug, Default)] +pub struct Hostname; impl Hostname { - pub fn new(sender_id: usize, sender: Sender, instance: Arc) -> Hostname { - Hostname { - sender_id, - sender, - instance, - } + pub fn new() -> Hostname { + Hostname } +} - async fn send(&mut self, data: TileData) -> Result<(), SendError> { - self.sender.send(data).await - } - - async fn run(&mut self) -> Result<(), Box> { +#[async_trait] +impl TileModule for Hostname { + async fn run(&mut self, sender: &mut BlockSender) -> Result<(), Box> { let mut raw = String::new(); File::open("/proc/sys/kernel/hostname") .await? @@ -33,24 +22,11 @@ impl Hostname { .await?; let block = Block { full_text: raw.trim_end_matches('\n').into(), - instance: self.instance.clone(), name: "hostname".into(), ..Default::default() }; - let data = TileData { - block, - sender_id: self.sender_id, - }; - self.send(data).await?; + sender.send(block).await?; // What's the hostname gonna do? Change? Ok(()) } } - -impl Tile for Hostname { - fn spawn(mut self: Box) -> JoinHandle>> { - tokio::spawn(async move { - self.run().await - }) - } -} diff --git a/src/tiles/load.rs b/src/tiles/load.rs index a940358..09d4cea 100644 --- a/src/tiles/load.rs +++ b/src/tiles/load.rs @@ -1,33 +1,22 @@ -use crate::tile::{Block, Tile, TileData}; -use std::sync::Arc; +use crate::tile::{Block, BlockSender, TileModule}; +use async_trait::async_trait; use std::time::Duration; use tokio::fs::File; use tokio::prelude::*; -use tokio::sync::mpsc::{error::SendError, Sender}; -use tokio::task::JoinHandle; use tokio::time::interval; -#[derive(Debug)] -pub struct Load { - sender_id: usize, - sender: Sender, - instance: Arc, -} +#[derive(Debug, Default)] +pub struct Load; impl Load { - pub fn new(sender_id: usize, sender: Sender, instance: Arc) -> Load { - Load { - sender_id, - sender, - instance, - } + pub fn new() -> Self { + Load } +} - async fn send(&mut self, data: TileData) -> Result<(), SendError> { - self.sender.send(data).await - } - - async fn run(&mut self) -> Result<(), Box> { +#[async_trait] +impl TileModule for Load { + async fn run(&mut self, sender: &mut BlockSender) -> Result<(), Box> { let mut timer = interval(Duration::from_secs(5)); loop { timer.tick().await; @@ -39,23 +28,10 @@ impl Load { let (load, _rest) = raw.split_at(raw.find(' ').unwrap_or(0)); let block = Block { full_text: load.into(), - instance: self.instance.clone(), name: "load".into(), ..Default::default() }; - let data = TileData { - block, - sender_id: self.sender_id, - }; - self.send(data).await?; + sender.send(block).await?; } } } - -impl Tile for Load { - fn spawn(mut self: Box) -> JoinHandle>> { - tokio::spawn(async move { - self.run().await - }) - } -} diff --git a/src/tiles/memory.rs b/src/tiles/memory.rs index 25772e7..5031a7f 100644 --- a/src/tiles/memory.rs +++ b/src/tiles/memory.rs @@ -1,32 +1,18 @@ -use crate::tile::{Block, Tile, TileData}; +use crate::tile::{Block, BlockSender, TileModule}; +use async_trait::async_trait; use std::io; use std::str; -use std::sync::Arc; use std::time::Duration; use tokio::fs::File; use tokio::prelude::*; -use tokio::sync::mpsc::{error::SendError, Sender}; -use tokio::task::JoinHandle; use tokio::time::interval; -#[derive(Debug)] -pub struct Memory { - sender_id: usize, - sender: Sender, - instance: Arc, -} +#[derive(Debug, Default)] +pub struct Memory; impl Memory { - pub fn new(sender_id: usize, sender: Sender, instance: Arc) -> Memory { - Memory { - sender_id, - sender, - instance, - } - } - - async fn send(&mut self, data: TileData) -> Result<(), SendError> { - self.sender.send(data).await + pub fn new() -> Memory { + Memory } fn prettify_kib(kib: u64) -> Box { @@ -64,8 +50,11 @@ impl Memory { .ok_or_else(|| io::Error::from(io::ErrorKind::InvalidData))? .parse()?) } +} - async fn run(&mut self) -> Result<(), Box> { +#[async_trait] +impl TileModule for Memory { + async fn run(&mut self, sender: &mut BlockSender) -> Result<(), Box> { let mut timer = interval(Duration::from_secs(5)); let mut raw = [0u8; 256]; loop { @@ -94,25 +83,10 @@ impl Memory { let block = Block { full_text, short_text: Some(short_text), - instance: self.instance.clone(), name: "memory".into(), ..Default::default() }; - let data = TileData { - block, - sender_id: self.sender_id, - }; - self.send(data).await?; + sender.send(block).await?; } } } - -impl Tile for Memory { - fn spawn(mut self: Box) -> JoinHandle>> { - tokio::spawn(async move { - let result = self.run().await; - eprintln!("Error in Memory: {:?}", result); - result - }) - } -} diff --git a/src/tiles/time.rs b/src/tiles/time.rs index 4cf9c3b..a315574 100644 --- a/src/tiles/time.rs +++ b/src/tiles/time.rs @@ -1,55 +1,46 @@ -use crate::tile::{Block, Tile, TileData}; +use crate::tile::{Block, BlockSender, TileModule}; +use async_trait::async_trait; use chrono::prelude::*; use chrono::DateTime; -use std::sync::Arc; use std::time::Duration; -use tokio::sync::mpsc::{error::SendError, Sender}; -use tokio::task::JoinHandle; use tokio::time::delay_for; #[derive(Debug)] pub struct Time { - sender_id: usize, - sender: Sender, - instance: Arc, format: Box, short_format: Box, } impl Time { - pub fn new(sender_id: usize, sender: Sender, instance: Arc) -> Time { + pub fn new() -> Time { + Default::default() + } + + fn send_time(&mut self, time: DateTime) -> Block { + Block { + full_text: time.format(&self.format).to_string().into(), + short_text: Some(time.format(&self.short_format).to_string().into()), + name: "time".into(), + ..Default::default() + } + } +} + +impl Default for Time { + fn default() -> Self { Time { - sender_id, - sender, - instance, format: "%Y-%m-%d %H:%M:%S".into(), short_format: "%H:%M:%S".into(), } } +} - async fn send(&mut self, data: TileData) -> Result<(), SendError> { - self.sender.send(data).await - } - - async fn send_time(&mut self, time: DateTime) -> Result<(), SendError> { - let block = Block { - full_text: time.format(&self.format).to_string().into(), - short_text: Some(time.format(&self.short_format).to_string().into()), - instance: self.instance.clone(), - name: "time".into(), - ..Default::default() - }; - let data = TileData { - sender_id: self.sender_id, - block, - }; - self.send(data).await - } - - async fn run(&mut self) -> Result<(), Box> { +#[async_trait] +impl TileModule for Time { + async fn run(&mut self, sender: &mut BlockSender) -> Result<(), Box> { let mut time = Local::now(); loop { - self.send_time(time).await?; + sender.send(self.send_time(time)).await?; time = Local::now(); let millis_part = time.naive_local().timestamp_subsec_millis() as u64; let delay_ms = 1000u64 - millis_part % 1000; // Don't crash if we hit a leap second @@ -57,11 +48,3 @@ impl Time { } } } - -impl Tile for Time { - fn spawn(mut self: Box) -> JoinHandle>> { - tokio::spawn(async move { - self.run().await - }) - } -}