Reduce duplication between the tiles

This commit is contained in:
Skye Jensen 2020-06-03 01:20:18 -04:00
parent bd09432ba9
commit 187aa4e695
8 changed files with 129 additions and 172 deletions

12
Cargo.lock generated
View file

@ -6,6 +6,17 @@ version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b585a98a234c46fc563103e9278c9391fde1f4e6850334da895d27edb9580f62" 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]] [[package]]
name = "autocfg" name = "autocfg"
version = "1.0.0" version = "1.0.0"
@ -496,6 +507,7 @@ checksum = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84"
name = "rustybar" name = "rustybar"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"async-trait",
"chrono", "chrono",
"dbus", "dbus",
"dbus-tokio", "dbus-tokio",

View file

@ -6,6 +6,7 @@ edition = "2018"
[dependencies] [dependencies]
async-trait = "0.1"
chrono = "0.4" chrono = "0.4"
dbus = "0.8" dbus = "0.8"
dbus-tokio = "0.5" dbus-tokio = "0.5"

View file

@ -3,7 +3,6 @@ pub mod tile;
pub mod tiles; pub mod tiles;
use dbus_tokio::connection::new_session_sync; use dbus_tokio::connection::new_session_sync;
use tile::Tile;
use tokio::sync::mpsc::channel; use tokio::sync::mpsc::channel;
use uuid::Uuid; use uuid::Uuid;
@ -20,31 +19,21 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
let (sender, receiver) = channel(1024); let (sender, receiver) = channel(1024);
let tiles: Vec<Box<dyn Tile>> = vec![ let mut index = 0usize;
Box::new(tiles::Load::new( let mut wrap = |module| {
0, let tile = tile::Tile::new(index, sender.clone(), Uuid::new_v4().to_string().into(), module);
sender.clone(), index += 1;
Uuid::new_v4().to_string().into(), tile
)), };
Box::new(tiles::Memory::new( let tiles = vec![
1, wrap(Box::new(tiles::Load::new())),
sender.clone(), wrap(Box::new(tiles::Memory::new())),
Uuid::new_v4().to_string().into(), wrap(Box::new(tiles::Hostname::new())),
)), wrap(Box::new(tiles::Time::new())),
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 num_tiles = tiles.len(); let num_tiles = tiles.len();
for tile in tiles { for tile in tiles.into_iter() {
tile.spawn(); tile.spawn();
} }

View file

@ -1,6 +1,9 @@
use async_trait::async_trait;
use serde::{ser::Serializer, Serialize}; use serde::{ser::Serializer, Serialize};
use smart_default::SmartDefault; use smart_default::SmartDefault;
use std::fmt::Debug;
use std::sync::Arc; use std::sync::Arc;
use tokio::sync::mpsc::{error::SendError, Sender};
use tokio::task::JoinHandle; use tokio::task::JoinHandle;
#[derive(Copy, Clone, Debug, Serialize)] #[derive(Copy, Clone, Debug, Serialize)]
@ -80,6 +83,49 @@ pub struct TileData {
pub block: Block, pub block: Block,
} }
pub trait Tile: Send + std::fmt::Debug { #[async_trait]
fn spawn(self: Box<Self>) -> JoinHandle<Result<(), Box<dyn std::error::Error + Send + Sync>>>; pub trait TileModule: Send + std::fmt::Debug {
async fn run(&mut self, sender: &mut BlockSender) -> Result<(), Box<dyn std::error::Error + Send + Sync>>;
}
#[derive(Debug)]
pub struct BlockSender {
sender_id: usize,
sender: Sender<TileData>,
instance: Arc<str>,
}
impl BlockSender {
pub async fn send(&mut self, mut block: Block) -> Result<(), SendError<TileData>> {
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<dyn TileModule>,
}
impl Tile {
pub fn new(sender_id: usize, sender: Sender<TileData>, instance: Arc<str>, module: Box<dyn TileModule>) -> Self {
Tile {
sender: BlockSender {
sender_id,
sender,
instance,
},
module,
}
}
pub fn spawn(mut self) -> JoinHandle<Result<(), Box<dyn std::error::Error + Send + Sync>>> {
tokio::spawn(async move {
self.module.run(&mut self.sender).await
})
}
} }

View file

@ -1,31 +1,20 @@
use crate::tile::{Block, Tile, TileData}; use crate::tile::{Block, BlockSender, TileModule};
use std::sync::Arc; use async_trait::async_trait;
use tokio::fs::File; use tokio::fs::File;
use tokio::prelude::*; use tokio::prelude::*;
use tokio::sync::mpsc::{error::SendError, Sender};
use tokio::task::JoinHandle;
#[derive(Debug)] #[derive(Debug, Default)]
pub struct Hostname { pub struct Hostname;
sender_id: usize,
sender: Sender<TileData>,
instance: Arc<str>,
}
impl Hostname { impl Hostname {
pub fn new(sender_id: usize, sender: Sender<TileData>, instance: Arc<str>) -> Hostname { pub fn new() -> Hostname {
Hostname { Hostname
sender_id,
sender,
instance,
}
} }
}
async fn send(&mut self, data: TileData) -> Result<(), SendError<TileData>> { #[async_trait]
self.sender.send(data).await impl TileModule for Hostname {
} async fn run(&mut self, sender: &mut BlockSender) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
async fn run(&mut self) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
let mut raw = String::new(); let mut raw = String::new();
File::open("/proc/sys/kernel/hostname") File::open("/proc/sys/kernel/hostname")
.await? .await?
@ -33,24 +22,11 @@ impl Hostname {
.await?; .await?;
let block = Block { let block = Block {
full_text: raw.trim_end_matches('\n').into(), full_text: raw.trim_end_matches('\n').into(),
instance: self.instance.clone(),
name: "hostname".into(), name: "hostname".into(),
..Default::default() ..Default::default()
}; };
let data = TileData { sender.send(block).await?;
block,
sender_id: self.sender_id,
};
self.send(data).await?;
// What's the hostname gonna do? Change? // What's the hostname gonna do? Change?
Ok(()) Ok(())
} }
} }
impl Tile for Hostname {
fn spawn(mut self: Box<Self>) -> JoinHandle<Result<(), Box<dyn std::error::Error + Send + Sync>>> {
tokio::spawn(async move {
self.run().await
})
}
}

View file

@ -1,33 +1,22 @@
use crate::tile::{Block, Tile, TileData}; use crate::tile::{Block, BlockSender, TileModule};
use std::sync::Arc; use async_trait::async_trait;
use std::time::Duration; use std::time::Duration;
use tokio::fs::File; use tokio::fs::File;
use tokio::prelude::*; use tokio::prelude::*;
use tokio::sync::mpsc::{error::SendError, Sender};
use tokio::task::JoinHandle;
use tokio::time::interval; use tokio::time::interval;
#[derive(Debug)] #[derive(Debug, Default)]
pub struct Load { pub struct Load;
sender_id: usize,
sender: Sender<TileData>,
instance: Arc<str>,
}
impl Load { impl Load {
pub fn new(sender_id: usize, sender: Sender<TileData>, instance: Arc<str>) -> Load { pub fn new() -> Self {
Load { Load
sender_id,
sender,
instance,
}
} }
}
async fn send(&mut self, data: TileData) -> Result<(), SendError<TileData>> { #[async_trait]
self.sender.send(data).await impl TileModule for Load {
} async fn run(&mut self, sender: &mut BlockSender) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
async fn run(&mut self) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
let mut timer = interval(Duration::from_secs(5)); let mut timer = interval(Duration::from_secs(5));
loop { loop {
timer.tick().await; timer.tick().await;
@ -39,23 +28,10 @@ impl Load {
let (load, _rest) = raw.split_at(raw.find(' ').unwrap_or(0)); let (load, _rest) = raw.split_at(raw.find(' ').unwrap_or(0));
let block = Block { let block = Block {
full_text: load.into(), full_text: load.into(),
instance: self.instance.clone(),
name: "load".into(), name: "load".into(),
..Default::default() ..Default::default()
}; };
let data = TileData { sender.send(block).await?;
block,
sender_id: self.sender_id,
};
self.send(data).await?;
} }
} }
} }
impl Tile for Load {
fn spawn(mut self: Box<Self>) -> JoinHandle<Result<(), Box<dyn std::error::Error + Send + Sync>>> {
tokio::spawn(async move {
self.run().await
})
}
}

View file

@ -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::io;
use std::str; use std::str;
use std::sync::Arc;
use std::time::Duration; use std::time::Duration;
use tokio::fs::File; use tokio::fs::File;
use tokio::prelude::*; use tokio::prelude::*;
use tokio::sync::mpsc::{error::SendError, Sender};
use tokio::task::JoinHandle;
use tokio::time::interval; use tokio::time::interval;
#[derive(Debug)] #[derive(Debug, Default)]
pub struct Memory { pub struct Memory;
sender_id: usize,
sender: Sender<TileData>,
instance: Arc<str>,
}
impl Memory { impl Memory {
pub fn new(sender_id: usize, sender: Sender<TileData>, instance: Arc<str>) -> Memory { pub fn new() -> Memory {
Memory { Memory
sender_id,
sender,
instance,
}
}
async fn send(&mut self, data: TileData) -> Result<(), SendError<TileData>> {
self.sender.send(data).await
} }
fn prettify_kib(kib: u64) -> Box<str> { fn prettify_kib(kib: u64) -> Box<str> {
@ -64,8 +50,11 @@ impl Memory {
.ok_or_else(|| io::Error::from(io::ErrorKind::InvalidData))? .ok_or_else(|| io::Error::from(io::ErrorKind::InvalidData))?
.parse()?) .parse()?)
} }
}
async fn run(&mut self) -> Result<(), Box<dyn std::error::Error + Send + Sync>> { #[async_trait]
impl TileModule for Memory {
async fn run(&mut self, sender: &mut BlockSender) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
let mut timer = interval(Duration::from_secs(5)); let mut timer = interval(Duration::from_secs(5));
let mut raw = [0u8; 256]; let mut raw = [0u8; 256];
loop { loop {
@ -94,25 +83,10 @@ impl Memory {
let block = Block { let block = Block {
full_text, full_text,
short_text: Some(short_text), short_text: Some(short_text),
instance: self.instance.clone(),
name: "memory".into(), name: "memory".into(),
..Default::default() ..Default::default()
}; };
let data = TileData { sender.send(block).await?;
block,
sender_id: self.sender_id,
};
self.send(data).await?;
} }
} }
} }
impl Tile for Memory {
fn spawn(mut self: Box<Self>) -> JoinHandle<Result<(), Box<dyn std::error::Error + Send + Sync>>> {
tokio::spawn(async move {
let result = self.run().await;
eprintln!("Error in Memory: {:?}", result);
result
})
}
}

View file

@ -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::prelude::*;
use chrono::DateTime; use chrono::DateTime;
use std::sync::Arc;
use std::time::Duration; use std::time::Duration;
use tokio::sync::mpsc::{error::SendError, Sender};
use tokio::task::JoinHandle;
use tokio::time::delay_for; use tokio::time::delay_for;
#[derive(Debug)] #[derive(Debug)]
pub struct Time { pub struct Time {
sender_id: usize,
sender: Sender<TileData>,
instance: Arc<str>,
format: Box<str>, format: Box<str>,
short_format: Box<str>, short_format: Box<str>,
} }
impl Time { impl Time {
pub fn new(sender_id: usize, sender: Sender<TileData>, instance: Arc<str>) -> Time { pub fn new() -> Time {
Default::default()
}
fn send_time(&mut self, time: DateTime<Local>) -> 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 { Time {
sender_id,
sender,
instance,
format: "%Y-%m-%d %H:%M:%S".into(), format: "%Y-%m-%d %H:%M:%S".into(),
short_format: "%H:%M:%S".into(), short_format: "%H:%M:%S".into(),
} }
} }
}
async fn send(&mut self, data: TileData) -> Result<(), SendError<TileData>> { #[async_trait]
self.sender.send(data).await impl TileModule for Time {
} async fn run(&mut self, sender: &mut BlockSender) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
async fn send_time(&mut self, time: DateTime<Local>) -> Result<(), SendError<TileData>> {
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<dyn std::error::Error + Send + Sync>> {
let mut time = Local::now(); let mut time = Local::now();
loop { loop {
self.send_time(time).await?; sender.send(self.send_time(time)).await?;
time = Local::now(); time = Local::now();
let millis_part = time.naive_local().timestamp_subsec_millis() as u64; 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 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<Self>) -> JoinHandle<Result<(), Box<dyn std::error::Error + Send + Sync>>> {
tokio::spawn(async move {
self.run().await
})
}
}