use std::collections::HashMap;
use context_error::{BasicKind, BoxedError};
use serde::{Deserialize, Serialize};
use serde_json::Value;
use crate::{
parse_json::{ParseJson, use_serde},
prelude::AminoAcid,
};
#[derive(Clone, Copy, Debug)]
pub struct FullGlycan {}
impl GlycanAttachement for FullGlycan {
fn get_default_fragments(&self, _attachment: Option<AminoAcid>) -> GlycanPeptideFragment {
GlycanPeptideFragment::FULL
}
fn get_specific_fragments(
&self,
_attachment: Option<AminoAcid>,
) -> HashMap<BackboneFragmentKind, GlycanPeptideFragment> {
HashMap::new()
}
}
pub trait GlycanAttachement {
fn get_default_fragments(&self, attachment: Option<AminoAcid>) -> GlycanPeptideFragment;
fn get_specific_fragments(
&self,
attachment: Option<AminoAcid>,
) -> HashMap<BackboneFragmentKind, GlycanPeptideFragment>;
}
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
pub struct GlycanPeptideFragment {
pub(super) full: bool,
pub(super) core: Option<(Option<usize>, Option<usize>)>,
}
impl std::ops::Add<&Self> for GlycanPeptideFragment {
type Output = Self;
fn add(self, rhs: &Self) -> Self::Output {
Self {
full: self.full || rhs.full,
core: self
.core
.and_then(|c| rhs.core.map(|r| (c, r)))
.map(|(c, r)| (c.0.min(r.0), c.1.max(r.1)))
.or(self.core)
.or(rhs.core),
}
}
}
impl GlycanPeptideFragment {
pub const FULL: Self = Self {
full: true,
core: None,
};
pub const CORE_AND_FREE: Self = Self {
full: false,
core: Some((None, Some(1))),
};
pub const CORE: Self = Self {
full: false,
core: Some((Some(1), Some(1))),
};
pub const FREE: Self = Self {
full: false,
core: Some((None, Some(0))),
};
pub const fn full(self) -> bool {
self.full
}
pub const fn core(self) -> Option<(Option<usize>, Option<usize>)> {
self.core
}
}
impl ParseJson for GlycanPeptideFragment {
fn from_json_value(value: Value) -> Result<Self, BoxedError<'static, BasicKind>> {
use_serde(value)
}
}
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
#[expect(non_camel_case_types)]
pub enum BackboneFragmentKind {
a,
b,
c,
d,
v,
w,
x,
y,
z,
}
impl std::fmt::Display for BackboneFragmentKind {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"{}",
match self {
Self::a => "a",
Self::b => "b",
Self::c => "c",
Self::d => "d",
Self::x => "x",
Self::y => "y",
Self::v => "v",
Self::w => "w",
Self::z => "z",
}
)
}
}
impl ParseJson for BackboneFragmentKind {
fn from_json_value(value: Value) -> Result<Self, BoxedError<'static, BasicKind>> {
use_serde(value)
}
}