-
Notifications
You must be signed in to change notification settings - Fork 26
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Added rustfmt custom file * Added CLI validators * State as application member. Splitted event functions * Added Config * Removed terminal as member of application * Added renderer concept * Renaming Message types. Some refactorizations * Introduced command and actions * Separated actions and commands * Adapted read_file and UserData to Command/Action API * Adapted progress message * Fixed issues from refactorization * Update Readme.md * Apply fmt * Fixed rustfmt.toml
- Loading branch information
Showing
16 changed files
with
557 additions
and
623 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
control_brace_style = "ClosingNextLine" | ||
use_small_heuristics = "Max" | ||
reorder_impl_items = true | ||
reorder_imports = false | ||
reorder_modules = false | ||
trailing_semicolon = false | ||
use_field_init_shorthand = true | ||
use_try_shorthand = true | ||
where_single_line = true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
use crate::state::{State}; | ||
|
||
use message_io::network::{NetworkManager}; | ||
|
||
pub enum Processing { | ||
Completed, | ||
Partial, | ||
} | ||
|
||
pub trait Action: Send { | ||
fn process(&mut self, state: &mut State, network: &mut NetworkManager) -> Processing; | ||
} |
Large diffs are not rendered by default.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
pub mod send_file; | ||
|
||
use crate::action::{Action}; | ||
use crate::util::{Result}; | ||
|
||
use std::collections::{HashMap}; | ||
|
||
pub trait Command { | ||
fn name(&self) -> &'static str; | ||
fn parse_params(&self, params: Vec<&str>) -> Result<Box<dyn Action>>; | ||
} | ||
|
||
#[derive(Default)] | ||
pub struct CommandManager { | ||
parsers: HashMap<&'static str, Box<dyn Command>>, | ||
} | ||
|
||
impl CommandManager { | ||
pub const COMMAND_PREFIX: &'static str = "?"; | ||
|
||
pub fn with(mut self, command_parser: impl Command + 'static) -> Self { | ||
self.parsers.insert(command_parser.name(), Box::new(command_parser)); | ||
self | ||
} | ||
|
||
pub fn find_command_action(&self, input: &str) -> Option<Result<Box<dyn Action>>> { | ||
let mut input = input.split_whitespace(); | ||
let start = input.next().expect("Input must have some content"); | ||
if start.starts_with(Self::COMMAND_PREFIX) { | ||
if let Some(parser) = self.parsers.get(&start[1..]) { | ||
return Some(parser.parse_params(input.collect())) | ||
} | ||
} | ||
None | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
use crate::action::{Action, Processing}; | ||
use crate::commands::{Command}; | ||
use crate::state::{State}; | ||
use crate::message::{NetMessage, Chunk}; | ||
use crate::util::{Result}; | ||
|
||
use message_io::network::{NetworkManager}; | ||
|
||
use std::path::{Path}; | ||
use std::io::{Read}; | ||
|
||
pub struct SendFileCommand; | ||
|
||
impl Command for SendFileCommand { | ||
fn name(&self) -> &'static str { | ||
"send" | ||
} | ||
|
||
fn parse_params(&self, params: Vec<&str>) -> Result<Box<dyn Action>> { | ||
let file_path = params.get(0).ok_or("No file specified")?; | ||
match SendFile::new(file_path) { | ||
Ok(action) => Ok(Box::new(action)), | ||
Err(e) => Err(e), | ||
} | ||
} | ||
} | ||
|
||
pub struct SendFile { | ||
file: std::fs::File, | ||
file_name: String, | ||
file_size: u64, | ||
progress_id: Option<usize>, | ||
} | ||
|
||
impl SendFile { | ||
const CHUNK_SIZE: usize = 65500; | ||
|
||
pub fn new(file_path: &str) -> Result<SendFile> { | ||
const READ_FILENAME_ERROR: &str = "Unable to read file name"; | ||
let file_path = Path::new(file_path); | ||
let file_name = file_path | ||
.file_name() | ||
.ok_or(READ_FILENAME_ERROR)? | ||
.to_str() | ||
.ok_or(READ_FILENAME_ERROR)? | ||
.to_string(); | ||
|
||
let file_size = std::fs::metadata(file_path)?.len(); | ||
let file = std::fs::File::open(file_path)?; | ||
|
||
Ok(SendFile { file, file_name, file_size, progress_id: None }) | ||
} | ||
} | ||
|
||
impl Action for SendFile { | ||
fn process(&mut self, state: &mut State, network: &mut NetworkManager) -> Processing { | ||
if self.progress_id.is_none() { | ||
let id = state.add_progress_message(&self.file_name, self.file_size); | ||
self.progress_id = Some(id); | ||
} | ||
|
||
let mut data = [0; Self::CHUNK_SIZE]; | ||
let (bytes_read, chunk, processing) = match self.file.read(&mut data) { | ||
Ok(0) => (0, Chunk::End, Processing::Completed), | ||
Ok(bytes_read) => (bytes_read, Chunk::Data(data.to_vec()), Processing::Partial), | ||
Err(error) => { | ||
let msg = format!("Error sending file. error: {}", error); | ||
state.add_system_error_message(msg); | ||
(0, Chunk::Error, Processing::Completed) | ||
} | ||
}; | ||
|
||
state.progress_message_update(self.progress_id.unwrap(), bytes_read as u64); | ||
|
||
let message = NetMessage::UserData(self.file_name.clone(), chunk); | ||
network.send_all(state.all_user_endpoints(), message).ok(); //Best effort | ||
|
||
processing | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
use serde::{Deserialize, Serialize}; | ||
|
||
#[derive(Serialize, Deserialize)] | ||
pub enum Chunk { | ||
Data(Vec<u8>), | ||
Error, | ||
End, | ||
} | ||
|
||
#[derive(Serialize, Deserialize)] | ||
pub enum NetMessage { | ||
HelloLan(String, u16), // user_name, server_port | ||
HelloUser(String), // user_name | ||
UserMessage(String), // content | ||
UserData(String, Chunk), // file_name, chunk | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
use crate::ui::{self}; | ||
use crate::state::{State}; | ||
use crate::util::{Result}; | ||
|
||
use crossterm::terminal::{self}; | ||
use crossterm::{ExecutableCommand}; | ||
|
||
use tui::{Terminal}; | ||
use tui::backend::{CrosstermBackend}; | ||
|
||
use std::io::{self, Stdout}; | ||
|
||
pub struct Renderer { | ||
terminal: Terminal<CrosstermBackend<Stdout>>, | ||
} | ||
|
||
impl Renderer { | ||
pub fn new() -> Result<Renderer> { | ||
terminal::enable_raw_mode()?; | ||
io::stdout().execute(terminal::EnterAlternateScreen)?; | ||
|
||
Ok(Renderer { terminal: Terminal::new(CrosstermBackend::new(io::stdout()))? }) | ||
} | ||
|
||
pub fn render(&mut self, state: &State) -> Result<()> { | ||
self.terminal.draw(|frame| ui::draw(frame, state, frame.size()))?; | ||
Ok(()) | ||
} | ||
} | ||
|
||
impl Drop for Renderer { | ||
fn drop(&mut self) { | ||
io::stdout().execute(terminal::LeaveAlternateScreen).expect("Could not execute to stdout"); | ||
terminal::disable_raw_mode().expect("Terminal doesn't support to disable raw mode"); | ||
if std::thread::panicking() { | ||
eprintln!( | ||
"{}, example: {}", | ||
"termchat paniced, to log the error you can redirect stderror to a file", | ||
"termchat 2> termchat_log" | ||
); | ||
} | ||
} | ||
} |
Oops, something went wrong.