use crate::utils::Either;
pub struct Message {
pub source: String,
pub target: Vec<Target>,
pub command: Command,
pub params: Vec<String>,
pub valid: bool,
pub error: Option<String>,
}
impl Message {
pub fn parse(raw_input: Vec<u8>, source_client: Option<String>) -> Self {
if raw_input.len() < 1 {
return Message {
source: "".to_string(),
target: Vec::new(),
command: Command::NAMES,
params: Vec::new(),
valid: false,
error: Some("No data".to_string()),
};
}
let split_message: Vec<Vec<u8>> = raw_input.into_iter().fold(Vec::new(), |mut acc, x| {
if x == 32 || acc.is_empty() {
acc.push(Vec::new());
}
acc.last_mut().unwrap().push(x);
acc
});
let source = source_client.unwrap_or({
match Message::parse_source(split_message[0].clone()) {
Either::Left(x) => x,
Either::Right(y) => return y,
}
});
Message {
source: source,
target: Vec::new(),
command: Command::NAMES,
valid: true,
params: Vec::new(),
error: None,
}
}
fn parse_source(source_input: Vec<u8>) -> Either<String, Message> {
if source_input.len() < 2 {
return Either::Right(Message {
source: "".to_string(),
target: Vec::new(),
command: Command::NAMES,
params: Vec::new(),
valid: false,
error: Some("No Source value:= empty data".to_string()),
});
}
if source_input[0] == 58 {
match String::from_utf8(source_input.clone().split_off(1)) {
Ok(x) => return Either::Left(x),
Err(_) => {
return Either::Right(Message {
source: "".to_string(),
target: Vec::new(),
command: Command::NAMES,
params: Vec::new(),
valid: false,
error: Some("Failed to parse source".to_string()),
});
}
}
} else {
return Either::Right(Message {
source: "".to_string(),
target: Vec::new(),
command: Command::NAMES,
params: Vec::new(),
valid: false,
error: Some("Invalid source format:= requires ':'".to_string()),
});
}
}
}
struct Target {
id: String,
target_type: TargetType,
}
enum TargetType {
CLIENT,
SERVER,
CHANNEL,
}
enum Command {
NAMES,
PRIVMSG,
NICK,
}
#[test]
fn test_valid_source() {
let message = ":TestClient".as_bytes().to_vec();
let source = Message::parse_source(message);
let source_string = match source {
Either::Left(x) => x,
Either::Right(_) => "None".to_string(),
};
assert_eq!(source_string, "TestClient");
}
#[test]
fn test_invalid_source() {
let message = ":".as_bytes().to_vec();
let source = Message::parse_source(message);
let source_string = match source {
Either::Left(x) => x,
Either::Right(y) => y.error.unwrap(),
};
assert_eq!(source_string, "No Source value:= empty data");
}
#[test]
fn test_empty_source() {
let message = Vec::new();
let source = Message::parse_source(message);
let source_string = match source {
Either::Left(x) => x,
Either::Right(y) => y.error.unwrap(),
};
assert_eq!(source_string, "No Source value:= empty data");
}
#[test]
fn test_format_source() {
let message = "TestClient".as_bytes().to_vec();
let source = Message::parse_source(message);
let source_string = match source {
Either::Left(x) => x,
Either::Right(y) => y.error.unwrap(),
};
assert_eq!(source_string, "Invalid source format:= requires ':'");
}