refactor, added ip validation
Some checks failed
/ Check (push) Successful in 1m33s
/ Format (push) Successful in 1m23s
/ Clippy (push) Has started running
/ Build (push) Has been cancelled

This commit is contained in:
Phani Pavan K
2025-08-29 10:40:24 +05:30
parent 4eab7aeaac
commit ebd66bfaf6
8 changed files with 90 additions and 60 deletions

View File

@@ -1,10 +1,7 @@
use crate::app::status::EntryCreation;
use regex::Regex;
use serde::{Deserialize, Serialize};
use std::{
error::Error,
fmt::Display,
io::ErrorKind,
num::{IntErrorKind, ParseIntError},
};
use std::fmt::Display;
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct Entry {
@@ -25,18 +22,26 @@ impl Display for Entry {
}
impl Entry {
pub fn new(fromIP: String, toIP: String, fromPort: String, toPort: String) -> Option<Self> {
if fromPort.parse::<i32>().is_ok_and(|a| a > 1 && a < 65535)
&& toPort.parse::<i32>().is_ok_and(|a| a > 1 && a < 65535)
pub fn new(
fromIP: String,
toIP: String,
fromPort: String,
toPort: String,
) -> Result<Self, EntryCreation> {
let ip = Regex::new("/^(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)(?:\\.(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)){3}$/").unwrap();
if !fromPort.parse::<i32>().is_ok_and(|a| a > 1 && a < 65535)
|| !toPort.parse::<i32>().is_ok_and(|a| a > 1 && a < 65535)
{
Some(Entry {
Err(EntryCreation::PortValidationError)
} else if !ip.is_match(&fromIP) || !ip.is_match(&toIP) {
Err(EntryCreation::IPValidationError)
} else {
Ok(Entry {
fromIP,
toIP,
fromPort,
toPort,
})
} else {
None
}
}
}

View File

@@ -15,8 +15,6 @@ pub struct AppState {
pub toIP: String,
pub toPort: String,
pub screen: CurrentScreen,
pub field: Option<EditingField>,
// pub current: Option<Entry>,
pub currentlyEditing: Option<EditingField>,
pub entries: Vec<Entry>,
pub confDir: String,
@@ -32,7 +30,6 @@ impl AppState {
toPort: String::new(),
currentlyEditing: None,
screen: CurrentScreen::Main,
field: None,
entries: settings.entries,
confDir: confDir,
}
@@ -45,7 +42,7 @@ impl AppState {
self.fromPort.clone(),
self.toPort.clone(),
) {
Some(entry) => {
Ok(entry) => {
self.entries.push(entry);
self.fromIP = String::new();
self.toIP = String::new();
@@ -59,17 +56,6 @@ impl AppState {
}
}
pub fn startEditing(&mut self) {
if let Some(currentField) = &self.currentlyEditing {
match currentField {
EditingField::ToIP => {}
_ => self.currentlyEditing = Some(EditingField::FromIP),
}
} else {
self.currentlyEditing = Some(EditingField::FromIP);
}
}
pub fn nextField(&mut self) {
if let Some(currentField) = &self.currentlyEditing {
self.currentlyEditing = match currentField {

View File

@@ -25,7 +25,7 @@ impl Settings {
Err(_) => {
let newSet = Settings { entries: vec![] };
let payload = serde_json::to_string_pretty(&newSet).unwrap();
std::fs::write(config, payload);
let _ = std::fs::write(config, payload);
newSet
}
}
@@ -33,6 +33,6 @@ impl Settings {
pub fn save(&self, config: &String) {
let payload = serde_json::to_string(self).unwrap();
std::fs::write(config, payload);
let _ = std::fs::write(config, payload);
}
}

View File

@@ -1,4 +1,4 @@
#[allow(non_snake_case)]
#![allow(non_snake_case)]
mod app;
mod ui;
@@ -114,7 +114,7 @@ fn runApp<B: Backend>(app: &mut AppState, terminal: &mut Terminal<B>) -> Result<
(KeyModifiers::NONE, KeyCode::Tab) => app.nextField(),
(KeyModifiers::SHIFT, KeyCode::Tab) => app.prevField(),
(m, KeyCode::Char(v)) => {
(_, KeyCode::Char(v)) => {
if let Some(e) = &app.currentlyEditing {
let mut isIP = false;
let opField = match e {

23
src/ui/centeredRect.rs Normal file
View File

@@ -0,0 +1,23 @@
use ratatui::layout::{Constraint, Direction, Layout, Rect};
pub fn centered_rect(percent_x: u16, percent_y: u16, r: Rect) -> Rect {
// Cut the given rectangle into three vertical pieces
let popup_layout = Layout::default()
.direction(Direction::Vertical)
.constraints([
Constraint::Percentage((100 - percent_y) / 2),
Constraint::Percentage(percent_y),
Constraint::Percentage((100 - percent_y) / 2),
])
.split(r);
// Then cut the middle vertical piece into three width-wise pieces
Layout::default()
.direction(Direction::Horizontal)
.constraints([
Constraint::Percentage((100 - percent_x) / 2),
Constraint::Percentage(percent_x),
Constraint::Percentage((100 - percent_x) / 2),
])
.split(popup_layout[1])[1] // Return the middle chunk
}

View File

@@ -1,18 +1,17 @@
#![allow(non_snake_case)]
mod centeredRect;
use ratatui::{
Frame,
layout::{Constraint, Layout},
layout::{Constraint, Direction, Layout},
style::{Color, Style},
text::{Line, Span, Text},
widgets::{Block, Borders, List, ListItem, Paragraph},
};
use ratatui::{
layout::{Direction, Rect},
widgets::Wrap,
widgets::{Block, Borders, List, ListItem, Paragraph, Wrap},
};
use crate::app::status::CurrentScreen;
use crate::app::{AppState, status::EditingField};
use crate::ui::centeredRect::centered_rect;
pub fn ui(frame: &mut Frame, app: &AppState) {
let chunks = Layout::default()
@@ -131,7 +130,6 @@ pub fn ui(frame: &mut Frame, app: &AppState) {
EditingField::ToIP => "To IP",
EditingField::FromPort => "From Port",
EditingField::ToPort => "To Port",
_ => "Something ",
};
Span::styled(
format!("Editing: {curEdit}"),
@@ -170,25 +168,3 @@ pub fn ui(frame: &mut Frame, app: &AppState) {
frame.render_widget(helpFooter, footerChunks[0]);
frame.render_widget(keyBindFooter, footerChunks[1]);
}
fn centered_rect(percent_x: u16, percent_y: u16, r: Rect) -> Rect {
// Cut the given rectangle into three vertical pieces
let popup_layout = Layout::default()
.direction(Direction::Vertical)
.constraints([
Constraint::Percentage((100 - percent_y) / 2),
Constraint::Percentage(percent_y),
Constraint::Percentage((100 - percent_y) / 2),
])
.split(r);
// Then cut the middle vertical piece into three width-wise pieces
Layout::default()
.direction(Direction::Horizontal)
.constraints([
Constraint::Percentage((100 - percent_x) / 2),
Constraint::Percentage(percent_x),
Constraint::Percentage((100 - percent_x) / 2),
])
.split(popup_layout[1])[1] // Return the middle chunk
}