use std::{fmt::Display, str::FromStr};
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Var {
pub sequence: String,
pub position: i32,
pub deletion: String,
pub insertion: String,
}
impl Var {
pub fn new(sequence: String, position: i32, deletion: String, insertion: String) -> Self {
Self {
sequence,
position,
deletion,
insertion,
}
}
}
impl FromStr for Var {
type Err = anyhow::Error;
fn from_str(spdi: &str) -> Result<Self, Self::Err> {
let mut parts = spdi.rsplitn(4, ':');
let insertion = parts.next().unwrap().to_string();
let deletion = parts.next().unwrap().to_string();
let position = parts
.next()
.unwrap()
.parse::<i32>()
.map_err(|e| anyhow::anyhow!("Could not parse position: {}", e))?;
let sequence = parts.next().unwrap().to_string();
Ok(Self {
sequence,
position,
deletion,
insertion,
})
}
}
impl Display for Var {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"{}:{}:{}:{}",
self.sequence, self.position, self.deletion, self.insertion
)
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Pos {
pub sequence: String,
pub position: i32,
}
impl Pos {
pub fn new(sequence: String, position: i32) -> Self {
Self { sequence, position }
}
}
impl FromStr for Pos {
type Err = anyhow::Error;
fn from_str(spdi: &str) -> Result<Self, Self::Err> {
let mut parts = spdi.rsplitn(2, ':');
let position = parts
.next()
.unwrap()
.parse::<i32>()
.map_err(|e| anyhow::anyhow!("Could not parse position: {}", e))?;
let sequence = parts.next().unwrap().to_string();
Ok(Self { sequence, position })
}
}
impl Display for Pos {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}:{}", self.sequence, self.position)
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Range {
pub sequence: String,
pub start: i32,
pub end: i32,
}
impl Range {
pub fn new(sequence: String, start: i32, end: i32) -> Self {
Self {
sequence,
start,
end,
}
}
}
impl FromStr for Range {
type Err = anyhow::Error;
fn from_str(spdi: &str) -> Result<Self, Self::Err> {
let mut parts = spdi.rsplitn(3, ':');
let end = parts
.next()
.unwrap()
.parse::<i32>()
.map_err(|e| anyhow::anyhow!("Could not parse end position: {}", e))?;
let start = parts
.next()
.unwrap()
.parse::<i32>()
.map_err(|e| anyhow::anyhow!("Could not parse start position: {}", e))?;
let sequence = parts.next().unwrap().to_string();
Ok(Self {
sequence,
start,
end,
})
}
}
impl Display for Range {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}:{}:{}", self.sequence, self.start, self.end)
}
}
impl From<Range> for (Pos, Pos) {
fn from(val: Range) -> Self {
(
Pos::new(val.sequence.clone(), val.start),
Pos::new(val.sequence, val.end),
)
}
}
#[cfg(test)]
mod test {
use super::*;
use pretty_assertions::assert_eq;
#[test]
fn var_new() {
let var = Var::new(
String::from("NC_000001.11"),
123,
String::from("A"),
String::from("T"),
);
assert_eq!(var.sequence, "NC_000001.11");
assert_eq!(var.position, 123);
assert_eq!(var.deletion, "A");
assert_eq!(var.insertion, "T");
}
#[test]
fn var_from_str() {
let var = Var::from_str("NC_000001.11:123:A:T").unwrap();
assert_eq!(var.sequence, "NC_000001.11");
assert_eq!(var.position, 123);
assert_eq!(var.deletion, "A");
assert_eq!(var.insertion, "T");
}
#[test]
fn var_display() {
let var = Var::new(
String::from("NC_000001.11"),
123,
String::from("A"),
String::from("T"),
);
assert_eq!(var.to_string(), "NC_000001.11:123:A:T");
}
#[test]
fn pos_new() {
let pos = Pos::new(String::from("NC_000001.11"), 123);
assert_eq!(pos.sequence, "NC_000001.11");
assert_eq!(pos.position, 123);
}
#[test]
fn pos_from_str() {
let pos = Pos::from_str("NC_000001.11:123").unwrap();
assert_eq!(pos.sequence, "NC_000001.11");
assert_eq!(pos.position, 123);
}
#[test]
fn pos_display() {
let pos = Pos::new(String::from("NC_000001.11"), 123);
assert_eq!(pos.to_string(), "NC_000001.11:123");
}
#[test]
fn range_new() {
let range = Range::new(String::from("NC_000001.11"), 123, 456);
assert_eq!(range.sequence, "NC_000001.11");
assert_eq!(range.start, 123);
assert_eq!(range.end, 456);
}
#[test]
fn range_from_str() {
let range = Range::from_str("NC_000001.11:123:456").unwrap();
assert_eq!(range.sequence, "NC_000001.11");
assert_eq!(range.start, 123);
assert_eq!(range.end, 456);
}
#[test]
fn range_display() {
let range = Range::new(String::from("NC_000001.11"), 123, 456);
assert_eq!(range.to_string(), "NC_000001.11:123:456");
}
}