use super::helpers::{
extract_parameter_suffix, is_parameter_keyword, parse_float_tuple, parse_float_vector,
parse_float_with_comma_decimal, parse_pnd, parse_spillover,
};
use super::{
ByteKeyword, FloatKeyword, IntegerKeyword, KeywordCreationResult, MixedKeyword, StringKeyword,
};
use crate::{byteorder::ByteOrder, datatype::FcsDataType};
use std::sync::Arc;
#[allow(deprecated)]
pub fn parse_fixed_keywords(key: &str, value: &str) -> Option<KeywordCreationResult> {
let trimmed_value = value.trim();
match key {
"FIL" => Some(KeywordCreationResult::String(StringKeyword::FIL(
Arc::from(trimmed_value),
))),
"GUID" => Some(KeywordCreationResult::String(StringKeyword::GUID(
Arc::from(trimmed_value),
))),
"BYTEORD" => Some(
ByteOrder::from_keyword_str(trimmed_value)
.map(|byte_order| KeywordCreationResult::Byte(ByteKeyword::BYTEORD(byte_order)))
.unwrap_or(KeywordCreationResult::UnableToParse),
),
"DATATYPE" => Some(
FcsDataType::from_keyword_str(trimmed_value)
.map(|data_type| KeywordCreationResult::Byte(ByteKeyword::DATATYPE(data_type)))
.unwrap_or(KeywordCreationResult::UnableToParse),
),
"PAR" => Some(
trimmed_value
.parse::<usize>()
.map(|n| KeywordCreationResult::Int(IntegerKeyword::PAR(n)))
.unwrap_or(KeywordCreationResult::UnableToParse),
),
"TOT" => Some(
trimmed_value
.parse::<usize>()
.map(|n| KeywordCreationResult::Int(IntegerKeyword::TOT(n)))
.unwrap_or(KeywordCreationResult::UnableToParse),
),
"BEGINDATA" => Some(
trimmed_value
.parse::<usize>()
.map(|n| KeywordCreationResult::Int(IntegerKeyword::BeginData(n)))
.unwrap_or(KeywordCreationResult::UnableToParse),
),
"ENDDATA" => Some(
trimmed_value
.parse::<usize>()
.map(|n| KeywordCreationResult::Int(IntegerKeyword::EndData(n)))
.unwrap_or(KeywordCreationResult::UnableToParse),
),
"BEGINANALYSIS" => Some(
trimmed_value
.parse::<usize>()
.map(|n| KeywordCreationResult::Int(IntegerKeyword::BeginAnalysis(n)))
.unwrap_or(KeywordCreationResult::UnableToParse),
),
"ENDANALYSIS" => Some(
trimmed_value
.parse::<usize>()
.map(|n| KeywordCreationResult::Int(IntegerKeyword::EndAnalysis(n)))
.unwrap_or(KeywordCreationResult::UnableToParse),
),
"BEGINTEXT" => Some(
trimmed_value
.parse::<usize>()
.map(|n| KeywordCreationResult::Int(IntegerKeyword::BeginText(n)))
.unwrap_or(KeywordCreationResult::UnableToParse),
),
"ENDTEXT" => Some(
trimmed_value
.parse::<usize>()
.map(|n| KeywordCreationResult::Int(IntegerKeyword::EndText(n)))
.unwrap_or(KeywordCreationResult::UnableToParse),
),
"BEGINDATETIME" => Some(KeywordCreationResult::String(StringKeyword::BEGINDATETIME(
Arc::from(trimmed_value),
))),
"ENDDATETIME" => Some(KeywordCreationResult::String(StringKeyword::ENDDATETIME(
Arc::from(trimmed_value),
))),
"CARRIERID" => Some(KeywordCreationResult::String(StringKeyword::CARRIERID(
Arc::from(trimmed_value),
))),
"CARRIERTYPE" => Some(KeywordCreationResult::String(StringKeyword::CARRIERTYPE(
Arc::from(trimmed_value),
))),
"LOCATIONID" => Some(KeywordCreationResult::String(StringKeyword::LOCATIONID(
Arc::from(trimmed_value),
))),
"FLOWRATE" => Some(KeywordCreationResult::String(StringKeyword::FLOWRATE(
Arc::from(trimmed_value),
))),
"SPILLOVER" => parse_spillover(trimmed_value).map(KeywordCreationResult::Mixed),
"SPILL" => parse_spillover(trimmed_value).map(KeywordCreationResult::Mixed),
"COMP" => parse_spillover(trimmed_value).map(KeywordCreationResult::Mixed),
"VOL" => Some(KeywordCreationResult::String(StringKeyword::VOL(
Arc::from(trimmed_value),
))),
"ORIGINALITY" => Some(KeywordCreationResult::String(StringKeyword::ORIGINALITY(
Arc::from(trimmed_value),
))),
"LAST_MODIFIER" => Some(KeywordCreationResult::String(StringKeyword::LastModifier(
Arc::from(trimmed_value),
))),
"LAST_MODIFIED" => Some(KeywordCreationResult::String(StringKeyword::LastModified(
Arc::from(trimmed_value),
))),
"CYT" => Some(KeywordCreationResult::String(StringKeyword::CYT(
Arc::from(trimmed_value),
))),
#[allow(deprecated)]
"DATE" => Some(KeywordCreationResult::String(StringKeyword::DATE(
Arc::from(trimmed_value),
))),
#[allow(deprecated)]
"BTIM" => Some(KeywordCreationResult::String(StringKeyword::BTIM(
Arc::from(trimmed_value),
))),
#[allow(deprecated)]
"ETIM" => Some(KeywordCreationResult::String(StringKeyword::ETIM(
Arc::from(trimmed_value),
))),
#[allow(deprecated)]
"MODE" => Some(KeywordCreationResult::String(StringKeyword::MODE(
Arc::from(trimmed_value),
))),
#[allow(deprecated)]
"PLATEID" => Some(KeywordCreationResult::String(StringKeyword::PLATEID(
Arc::from(trimmed_value),
))),
#[allow(deprecated)]
"PLATENAME" => Some(KeywordCreationResult::String(StringKeyword::PLATENAME(
Arc::from(trimmed_value),
))),
#[allow(deprecated)]
"WELLID" => Some(KeywordCreationResult::String(StringKeyword::WELLID(
Arc::from(trimmed_value),
))),
#[allow(deprecated)]
"GATE" => Some(KeywordCreationResult::String(StringKeyword::GATE(
Arc::from(trimmed_value),
))),
_ => None,
}
}
pub fn parse_parameter_keywords(key: &str, value: &str) -> Option<KeywordCreationResult> {
if !is_parameter_keyword(key) {
return None;
}
let suffix = extract_parameter_suffix(key)?;
let trimmed_value = value.trim();
let suffix_upper = suffix.to_uppercase();
match suffix_upper.as_str() {
"G" => parse_float_with_comma_decimal(trimmed_value)
.map(|gain| KeywordCreationResult::Float(FloatKeyword::PnG(gain)))
.map_or(Some(KeywordCreationResult::UnableToParse), Some),
"E" => {
if let Some((f1, f2)) = parse_float_tuple(trimmed_value) {
Some(KeywordCreationResult::Mixed(MixedKeyword::PnE(f1, f2)))
} else if let Some(single_val) = parse_float_with_comma_decimal(trimmed_value) {
Some(KeywordCreationResult::Mixed(MixedKeyword::PnE(
single_val, 0.0,
)))
} else {
Some(KeywordCreationResult::UnableToParse)
}
}
"R" => {
if let Some(range_float) = parse_float_with_comma_decimal(trimmed_value) {
Some(KeywordCreationResult::Int(IntegerKeyword::PnR(range_float as usize)))
} else {
Some(
trimmed_value
.parse::<usize>()
.map(|range| KeywordCreationResult::Int(IntegerKeyword::PnR(range)))
.unwrap_or(KeywordCreationResult::UnableToParse),
)
}
},
"B" => Some(
trimmed_value
.parse::<usize>()
.map(|bits| KeywordCreationResult::Int(IntegerKeyword::PnB(bits)))
.unwrap_or(KeywordCreationResult::UnableToParse),
),
"V" => Some(
trimmed_value
.parse::<usize>()
.map(|voltage_range| KeywordCreationResult::Int(IntegerKeyword::PnV(voltage_range)))
.unwrap_or(KeywordCreationResult::UnableToParse),
),
"L" => {
let cleaned_value = trimmed_value
.strip_prefix('(')
.and_then(|s| s.strip_suffix(')'))
.unwrap_or(trimmed_value);
cleaned_value
.split(',')
.map(|s| s.trim().parse::<usize>().ok())
.collect::<Option<Vec<usize>>>()
.map(|wl| KeywordCreationResult::Mixed(MixedKeyword::PnL(wl)))
.map_or(Some(KeywordCreationResult::UnableToParse), Some)
}
"DISPLAY" => Some(KeywordCreationResult::String(StringKeyword::PnDISPLAY(
Arc::from(trimmed_value),
))),
"N" => Some(KeywordCreationResult::String(StringKeyword::PnN(
Arc::from(trimmed_value),
))),
"S" => Some(KeywordCreationResult::String(StringKeyword::PnS(
Arc::from(trimmed_value),
))),
"F" => Some(KeywordCreationResult::String(StringKeyword::PnF(
Arc::from(trimmed_value),
))),
"TYPE" => Some(KeywordCreationResult::String(StringKeyword::PnType(
Arc::from(trimmed_value),
))),
"DET" => Some(KeywordCreationResult::String(StringKeyword::PnDET(
Arc::from(trimmed_value),
))),
"TAG" => Some(KeywordCreationResult::String(StringKeyword::PnTAG(
Arc::from(trimmed_value),
))),
"ANALYTE" => Some(KeywordCreationResult::String(StringKeyword::PnANALYTE(
Arc::from(trimmed_value),
))),
"FEATURE" => Some(KeywordCreationResult::String(StringKeyword::PnFEATURE(
Arc::from(trimmed_value),
))),
"D" => parse_pnd(trimmed_value)
.map(KeywordCreationResult::Mixed)
.map_or(Some(KeywordCreationResult::UnableToParse), Some),
"DATATYPE" => Some(
FcsDataType::from_keyword_str(trimmed_value)
.map(|data_type| {
KeywordCreationResult::Byte(ByteKeyword::PnDATATYPE(data_type))
})
.unwrap_or(KeywordCreationResult::UnableToParse),
),
_ => {
eprintln!(
"Unknown parameter keyword suffix: '{}' for key: '{}' with value: '{}'",
suffix, key, value
);
None
}
}
}
pub fn parse_gate_keywords(key: &str, value: &str) -> Option<KeywordCreationResult> {
let suffix = extract_parameter_suffix(key)?;
if !key.starts_with("G") {
return None;
}
let trimmed_value = value.trim();
match suffix.as_str() {
#[allow(deprecated)]
"E" => {
if let Some((f1, f2)) = parse_float_tuple(trimmed_value) {
Some(KeywordCreationResult::Mixed(MixedKeyword::GnE(f1, f2)))
} else {
Some(KeywordCreationResult::Mixed(MixedKeyword::GnE(0.0, 0.0)))
}
}
#[allow(deprecated)]
"F" => Some(KeywordCreationResult::String(StringKeyword::GnF(
Arc::from(trimmed_value),
))),
#[allow(deprecated)]
"N" => Some(KeywordCreationResult::String(StringKeyword::GnN(
Arc::from(trimmed_value),
))),
#[allow(deprecated)]
"P" => Some(KeywordCreationResult::String(StringKeyword::GnP(
Arc::from(trimmed_value),
))),
#[allow(deprecated)]
"R" => Some(KeywordCreationResult::String(StringKeyword::GnR(
Arc::from(trimmed_value),
))),
#[allow(deprecated)]
"S" => Some(KeywordCreationResult::String(StringKeyword::GnS(
Arc::from(trimmed_value),
))),
#[allow(deprecated)]
"T" => Some(KeywordCreationResult::String(StringKeyword::GnT(
Arc::from(trimmed_value),
))),
#[allow(deprecated)]
"V" => Some(KeywordCreationResult::String(StringKeyword::GnV(
Arc::from(trimmed_value),
))),
_ => None,
}
}
pub fn parse_region_keywords(key: &str, value: &str) -> Option<KeywordCreationResult> {
let suffix = extract_parameter_suffix(key)?;
if !key.starts_with("R") {
return None;
}
let trimmed_value = value.trim();
match suffix.as_str() {
"W" => parse_float_vector(trimmed_value)
.map(|vec| KeywordCreationResult::Mixed(MixedKeyword::RnW(vec)))
.map_or(Some(KeywordCreationResult::UnableToParse), Some),
_ => None,
}
}