use crate::mzml::attributes::{AttributeValue, LIST_ATTRIBUTES, SCAN_ATTRIBUTES};
use crate::mzml::cvparam::{Accession, CVParamValue, RawTerm, UserParam};
use crate::mzml::filedescription::SourceFileRef;
use crate::{FatalParseError, ParseError, SpectrumRef, Tag};
use std::collections::VecDeque;
use super::cvparam::{CVParam, HasCVParams, HasParamGroupRefs};
use super::writer::Writer;
use super::{MzMLReader, MzMLTag};
use quick_xml::events::{BytesStart, Event};
use std::io::{BufRead, Write};
use super::instrument::InstrumentConfigurationRef;
use super::referenceableparamgroup::ReferenceableParamGroupRef;
pub const ACCESSION_POSITION_X: &str = "IMS:1000050";
const B_ACCESSION_POSITION_X: &[u8] = b"IMS:1000050";
pub const ACCESSION_POSITION_Y: &str = "IMS:1000051";
const B_ACCESSION_POSITION_Y: &[u8] = b"IMS:1000051";
pub const ACCESSION_POSITION_Z: &str = "IMS:1000052";
const B_ACCESSION_POSITION_Z: &[u8] = b"IMS:1000052";
pub const ACCESSION_NO_COMBINATION: &str = "MS:1000795";
#[derive(Debug)]
pub struct Scan {
param_group_refs: Vec<ReferenceableParamGroupRef>,
cv_params: Vec<CVParam>,
user_params: Vec<UserParam>,
instrument_configuration_ref: Option<InstrumentConfigurationRef>,
scan_window_list: Vec<ScanWindow>,
x_position: Option<u32>,
y_position: Option<u32>,
z_position: Option<u32>,
}
impl Clone for Scan {
fn clone(&self) -> Self {
Self {
param_group_refs: self.param_group_refs.clone(),
cv_params: self.cv_params.clone(),
user_params: self.user_params.clone(),
instrument_configuration_ref: self.instrument_configuration_ref.clone(),
scan_window_list: self.scan_window_list.clone(),
x_position: self.x_position,
y_position: self.y_position,
z_position: self.z_position,
}
}
}
impl Default for Scan {
fn default() -> Self {
Self::new()
}
}
impl Scan {
pub fn new() -> Self {
Scan {
param_group_refs: Vec::new(),
cv_params: Vec::new(),
user_params: Vec::new(),
instrument_configuration_ref: None,
scan_window_list: Vec::new(),
x_position: None,
y_position: None,
z_position: None,
}
}
pub fn scan_window_list(&self) -> &Vec<ScanWindow> {
&self.scan_window_list
}
pub fn x_position(&self) -> Option<u32> {
self.x_position
}
pub fn y_position(&self) -> Option<u32> {
self.y_position
}
pub fn z_position(&self) -> Option<u32> {
self.z_position
}
pub fn set_x_position(&mut self, x: u32) {
self.x_position = Some(x);
}
pub fn set_y_position(&mut self, y: u32) {
self.y_position = Some(y);
}
pub(crate) fn add_raw_term<'a>(
&mut self,
raw_term: &RawTerm<'a>,
breadcrumbs: &VecDeque<(Tag, Option<String>)>,
errors: &mut VecDeque<ParseError>,
ignore_uncommon_tags: bool,
) {
match raw_term.raw_accession() {
B_ACCESSION_POSITION_X => {
self.x_position = Some(raw_term.value_as_u32()); }
B_ACCESSION_POSITION_Y => {
self.y_position = Some(raw_term.value_as_u32()); }
B_ACCESSION_POSITION_Z => {
self.z_position = Some(raw_term.value_as_u32()); }
_ => {
if !ignore_uncommon_tags {
self.cv_params
.push(raw_term.to_cv_param(breadcrumbs, errors))
}
}
}
}
}
impl MzMLTag for Scan {
fn parse_start_tag<B: BufRead>(
parser: &mut MzMLReader<B>,
start_event: &BytesStart,
) -> Result<Option<Self>, FatalParseError>
where
Self: std::marker::Sized,
{
if start_event.name().as_ref() != b"scan" {
return Err(FatalParseError::UnexpectedTag(format!(
"Unexpected event {:?} when processing Scan",
start_event,
)));
}
let attributes = parser.process_attributes(Tag::Scan, &SCAN_ATTRIBUTES, start_event)?;
let mut scan = Scan::new();
if let Some(AttributeValue::String(attribute)) =
attributes.get("instrumentConfigurationRef")
{
if let Some(instrument_configuration_ref) =
parser.instrument_configuration_ref(attribute)
{
scan.instrument_configuration_ref = Some(instrument_configuration_ref);
}
}
parser.breadcrumbs.push_back((Tag::Scan, None));
Ok(Some(scan))
}
fn parse_xml<B: BufRead>(
&mut self,
parser: &mut MzMLReader<B>,
buffer: &mut Vec<u8>,
) -> Result<(), FatalParseError> {
loop {
buffer.clear();
match parser.next(buffer)? {
Event::Start(start_event) | Event::Empty(start_event) => {
match start_event.name().as_ref() {
b"cvParam" => {
let raw_term = RawTerm::parse_start_tag(parser, &start_event)?;
self.add_raw_term(
&raw_term,
&parser.breadcrumbs,
&mut parser.errors,
parser.ignore_uncommon_tags,
);
}
b"referenceableParamGroupRef" => {
let param_group_ref =
ReferenceableParamGroupRef::parse_start_tag(parser, &start_event)?;
self.param_group_refs.push(param_group_ref);
}
b"userParam" => {
if let Some(user_param) =
UserParam::parse_start_tag(parser, &start_event)?
{
self.user_params.push(user_param);
}
}
b"scanWindowList" => {
if let Some(mut scan_window_list) =
ScanWindowList::parse_start_tag(parser, &start_event)?
{
scan_window_list.parse_xml(parser, buffer)?;
self.scan_window_list = scan_window_list.list;
}
}
_ => parser.errors.push_back(ParseError::UnexpectedTag(format!(
"{:?} unexpected when processing {:?}",
std::str::from_utf8(start_event.name().as_ref()),
Self::tag()
))),
}
}
Event::End(end_event) => {
if let b"scan" = end_event.name().as_ref() {
parser.breadcrumbs.pop_back();
break;
}
}
Event::Eof => {
return Err(FatalParseError::MissingClosingTag("scan".to_string()));
}
_ => {}
}
}
Ok(())
}
fn tag() -> Tag {
Tag::ScanList
}
fn write_xml<W: Write>(&self, writer: &mut Writer<W>) -> Result<(), quick_xml::Error> {
match &self.instrument_configuration_ref {
Some(ic_ref) => {
writer.start_tag_with_attr("scan", "instrumentConfigurationRef", ic_ref.id())?
}
None => writer.start_tag("scan")?,
}
self.write_ref_param_groups_xml(writer)?;
if let Some(x_position) = self.x_position {
let param = CVParam::new(
Accession::Term(writer.ontology().get(ACCESSION_POSITION_X).unwrap().clone()),
CVParamValue::Integer(x_position.into()),
);
param.write_xml(writer)?;
}
if let Some(y_position) = self.y_position {
let param = CVParam::new(
Accession::Term(writer.ontology().get(ACCESSION_POSITION_Y).unwrap().clone()),
CVParamValue::Integer(y_position.into()),
);
param.write_xml(writer)?;
}
self.write_params_xml(writer)?;
writer.end_tag("scan")
}
}
impl HasCVParams for Scan {
fn add_cv_param(&mut self, param: CVParam) {
match param.accession() {
ACCESSION_POSITION_X => {
self.x_position = param.value_as_u32(); }
ACCESSION_POSITION_Y => {
self.y_position = param.value_as_u32(); }
_ => {
self.cv_params.push(param);
}
}
}
fn cv_params(&self) -> &Vec<CVParam> {
&self.cv_params
}
fn cv_params_mut(&mut self) -> &mut Vec<CVParam> {
self.cv_params.as_mut()
}
fn add_user_param(&mut self, param: UserParam) {
self.user_params.push(param);
}
fn user_params(&self) -> &Vec<UserParam> {
&self.user_params
}
}
impl HasParamGroupRefs for Scan {
fn add_param_group_ref(&mut self, param_group_ref: ReferenceableParamGroupRef) {
self.param_group_refs.push(param_group_ref);
}
fn param_group_refs(&self) -> &Vec<ReferenceableParamGroupRef> {
&self.param_group_refs
}
}
#[derive(Debug)]
pub struct ScanList {
param_group_refs: Vec<ReferenceableParamGroupRef>,
cv_params: Vec<CVParam>,
user_params: Vec<UserParam>,
scans: Vec<Scan>,
}
impl Clone for ScanList {
fn clone(&self) -> Self {
Self {
param_group_refs: self.param_group_refs.clone(),
cv_params: self.cv_params.clone(),
user_params: self.user_params.clone(),
scans: self.scans.clone(),
}
}
}
pub struct ScanIter<'a> {
scan_list: &'a ScanList,
index: usize,
}
impl<'a> Iterator for ScanIter<'a> {
type Item = &'a Scan;
fn next(&mut self) -> Option<Self::Item> {
let scan = self.scan_list.scan(self.index);
self.index += 1;
scan
}
}
impl<'a> IntoIterator for &'a ScanList {
type Item = &'a Scan;
type IntoIter = ScanIter<'a>;
fn into_iter(self) -> Self::IntoIter {
ScanIter {
scan_list: self,
index: 0,
}
}
}
impl ScanList {
pub fn new(count: usize) -> Self {
ScanList {
param_group_refs: Vec::new(),
cv_params: Vec::new(),
user_params: Vec::new(),
scans: Vec::with_capacity(count),
}
}
pub fn add_scan(&mut self, scan: Scan) {
self.scans.push(scan);
}
pub fn scan(&self, index: usize) -> Option<&Scan> {
self.scans.get(index)
}
pub fn scan_mut(&mut self, index: usize) -> Option<&mut Scan> {
self.scans.get_mut(index)
}
pub fn first_scan_mut(&mut self) -> &mut Scan {
if self.scans.is_empty() {
self.scans.push(Scan::new())
}
self.scan_mut(0).unwrap()
}
pub fn len(&self) -> usize {
self.scans.len()
}
pub fn is_empty(&self) -> bool {
self.scans.is_empty()
}
}
impl MzMLTag for ScanList {
fn parse_start_tag<B: BufRead>(
parser: &mut MzMLReader<B>,
start_event: &BytesStart,
) -> Result<Option<Self>, FatalParseError>
where
Self: std::marker::Sized,
{
if start_event.name().as_ref() != b"scanList" {
return Err(FatalParseError::UnexpectedTag(format!(
"Unexpected event {:?} when processing ScanList",
start_event,
)));
}
let attributes = parser.process_attributes(Tag::ScanList, &LIST_ATTRIBUTES, start_event)?;
let count = match attributes.get("count") {
Some(&AttributeValue::Integer(count)) => count as usize,
_ => 0,
};
let scan_list = ScanList::new(count);
parser.breadcrumbs.push_back((Tag::ScanList, None));
Ok(Some(scan_list))
}
fn parse_xml<B: BufRead>(
&mut self,
parser: &mut MzMLReader<B>,
buffer: &mut Vec<u8>,
) -> Result<(), FatalParseError> {
let mut last_num_params = 0;
loop {
buffer.clear();
let next_event = parser.next(buffer)?;
match next_event {
Event::Start(start_event) | Event::Empty(start_event) => match start_event
.name()
.as_ref()
{
b"cvParam" => {
if let Some(cv_param) = CVParam::parse_start_tag(parser, &start_event)? {
self.cv_params.push(cv_param);
}
}
b"referenceableParamGroupRef" => {
let param_group_ref =
ReferenceableParamGroupRef::parse_start_tag(parser, &start_event)?;
self.param_group_refs.push(param_group_ref);
}
b"userParam" => {
if let Some(user_param) = UserParam::parse_start_tag(parser, &start_event)?
{
self.user_params.push(user_param);
}
}
b"scan" => {
if let Some(mut scan) = Scan::parse_start_tag(parser, &start_event)? {
scan.cv_params.reserve(last_num_params);
scan.parse_xml(parser, buffer)?;
last_num_params = scan.cv_params.len();
self.scans.push(scan);
}
}
_ => parser.errors.push_back(ParseError::UnexpectedTag(format!(
"{:?} unexpected when processing {:?}",
std::str::from_utf8(start_event.name().as_ref()),
Self::tag()
))),
},
Event::End(end_event) => {
if let b"scanList" = end_event.name().as_ref() {
parser.breadcrumbs.pop_back();
break;
}
}
Event::Eof => {
return Err(FatalParseError::MissingClosingTag("scanList".to_string()));
}
_ => {}
}
}
Ok(())
}
fn tag() -> Tag {
Tag::ScanList
}
fn write_xml<W: Write>(&self, writer: &mut Writer<W>) -> Result<(), quick_xml::Error> {
writer.start_tag_with_attr("scanList", "count", self.scans.len())?;
self.write_ref_param_groups_xml(writer)?;
self.write_params_xml(writer)?;
for scan in &self.scans {
scan.write_xml(writer)?;
}
writer.end_tag("scanList")
}
}
impl HasCVParams for ScanList {
fn add_cv_param(&mut self, param: CVParam) {
self.cv_params.push(param);
}
fn cv_params(&self) -> &Vec<CVParam> {
&self.cv_params
}
fn cv_params_mut(&mut self) -> &mut Vec<CVParam> {
self.cv_params.as_mut()
}
fn add_user_param(&mut self, param: UserParam) {
self.user_params.push(param);
}
fn user_params(&self) -> &Vec<UserParam> {
&self.user_params
}
}
impl HasParamGroupRefs for ScanList {
fn add_param_group_ref(&mut self, param_group_ref: ReferenceableParamGroupRef) {
self.param_group_refs.push(param_group_ref);
}
fn param_group_refs(&self) -> &Vec<ReferenceableParamGroupRef> {
&self.param_group_refs
}
}
pub struct ScanWindowList {
pub(crate) list: Vec<ScanWindow>,
}
impl ScanWindowList {
fn new(count: usize) -> Self {
ScanWindowList {
list: Vec::with_capacity(count),
}
}
}
impl MzMLTag for ScanWindowList {
fn parse_start_tag<B: BufRead>(
parser: &mut MzMLReader<B>,
start_event: &BytesStart,
) -> Result<Option<Self>, FatalParseError>
where
Self: std::marker::Sized,
{
if start_event.name().as_ref() != b"scanWindowList" {
return Err(FatalParseError::UnexpectedTag(format!(
"Unexpected event {:?} when processing ScanWindowList",
start_event,
)));
}
let attributes = parser.process_attributes(Self::tag(), &LIST_ATTRIBUTES, start_event)?;
let count = match attributes.get("count") {
Some(&AttributeValue::Integer(count)) => count as usize,
_ => 0,
};
parser.breadcrumbs.push_back((Tag::ScanWindowList, None));
Ok(Some(ScanWindowList::new(count)))
}
fn parse_xml<B: BufRead>(
&mut self,
parser: &mut MzMLReader<B>,
buffer: &mut Vec<u8>,
) -> Result<(), FatalParseError> {
let mut last_num_params = 0;
loop {
buffer.clear();
let next_event = parser.next(buffer)?;
match next_event {
Event::Start(start_event) | Event::Empty(start_event) => {
match start_event.name().as_ref() {
b"scanWindow" => {
if let Some(mut scan_window) =
ScanWindow::parse_start_tag(parser, &start_event)?
{
scan_window.cv_params.reserve(last_num_params);
scan_window.parse_xml(parser, buffer)?;
last_num_params = scan_window.cv_params.len();
self.list.push(scan_window);
}
}
_ => parser.errors.push_back(ParseError::UnexpectedTag(format!(
"{:?} unexpected when processing {:?}",
std::str::from_utf8(start_event.name().as_ref()),
Self::tag()
))),
}
}
Event::End(end_event) => {
if let b"scanWindowList" = end_event.name().as_ref() {
parser.breadcrumbs.pop_back();
break;
}
}
Event::Eof => {
return Err(FatalParseError::MissingClosingTag(
"scanWindowList".to_string(),
));
}
_ => {}
}
}
Ok(())
}
fn tag() -> Tag {
Tag::ScanWindowList
}
fn write_xml<W: Write>(&self, writer: &mut Writer<W>) -> Result<(), quick_xml::Error> {
writer.write_list("scanWindowList", &self.list)
}
}
#[derive(Debug)]
pub struct ScanWindow {
param_group_refs: Vec<ReferenceableParamGroupRef>,
cv_params: Vec<CVParam>,
user_params: Vec<UserParam>,
}
impl Clone for ScanWindow {
fn clone(&self) -> Self {
Self {
param_group_refs: self.param_group_refs.clone(),
cv_params: self.cv_params.clone(),
user_params: self.user_params.clone(),
}
}
}
impl Default for ScanWindow {
fn default() -> Self {
Self::new()
}
}
impl ScanWindow {
pub fn new() -> Self {
ScanWindow {
param_group_refs: Vec::new(),
cv_params: Vec::new(),
user_params: Vec::new(),
}
}
}
impl MzMLTag for ScanWindow {
fn parse_start_tag<B: BufRead>(
parser: &mut MzMLReader<B>,
start_event: &BytesStart,
) -> Result<Option<Self>, FatalParseError>
where
Self: std::marker::Sized,
{
if start_event.name().as_ref() != b"scanWindow" {
Err(FatalParseError::UnexpectedTag(format!(
"Unexpected event {:?} when processing ScanWindow",
start_event,
)))
} else {
parser.breadcrumbs.push_back((Tag::ScanWindow, None));
Ok(Some(ScanWindow::new()))
}
}
fn parse_xml<B: BufRead>(
&mut self,
parser: &mut MzMLReader<B>,
buffer: &mut Vec<u8>,
) -> Result<(), FatalParseError> {
loop {
buffer.clear();
let next_event = parser.next(buffer)?;
match next_event {
Event::Start(start_event) | Event::Empty(start_event) => match start_event
.name()
.as_ref()
{
b"cvParam" => {
if let Some(cv_param) = CVParam::parse_start_tag(parser, &start_event)? {
self.cv_params.push(cv_param);
}
}
b"referenceableParamGroupRef" => {
let param_group_ref =
ReferenceableParamGroupRef::parse_start_tag(parser, &start_event)?;
self.param_group_refs.push(param_group_ref);
}
b"userParam" => {
if let Some(user_param) = UserParam::parse_start_tag(parser, &start_event)?
{
self.user_params.push(user_param);
}
}
_ => parser.errors.push_back(ParseError::UnexpectedTag(format!(
"{:?} unexpected when processing {:?}",
std::str::from_utf8(start_event.name().as_ref()),
Self::tag()
))),
},
Event::End(end_event) => {
if let b"scanWindow" = end_event.name().as_ref() {
parser.breadcrumbs.pop_back();
break;
}
}
Event::Eof => {
return Err(FatalParseError::MissingClosingTag("scanWindow".to_string()));
}
_ => {}
}
}
Ok(())
}
fn tag() -> Tag {
Tag::ScanWindow
}
fn write_xml<W: Write>(&self, _writer: &mut Writer<W>) -> Result<(), quick_xml::Error> {
todo!()
}
}
impl HasCVParams for ScanWindow {
fn add_cv_param(&mut self, param: CVParam) {
self.cv_params.push(param);
}
fn cv_params(&self) -> &Vec<CVParam> {
&self.cv_params
}
fn cv_params_mut(&mut self) -> &mut Vec<CVParam> {
self.cv_params.as_mut()
}
fn add_user_param(&mut self, param: UserParam) {
self.user_params.push(param);
}
fn user_params(&self) -> &Vec<UserParam> {
&self.user_params
}
}
impl HasParamGroupRefs for ScanWindow {
fn add_param_group_ref(&mut self, param_group_ref: ReferenceableParamGroupRef) {
self.param_group_refs.push(param_group_ref);
}
fn param_group_refs(&self) -> &Vec<ReferenceableParamGroupRef> {
&self.param_group_refs
}
}
#[derive(Debug, Clone)]
pub struct PrecursorList {
pub(crate) list: Vec<Precursor>,
}
impl PrecursorList {
pub fn new(count: usize) -> Self {
PrecursorList {
list: Vec::with_capacity(count),
}
}
}
impl MzMLTag for PrecursorList {
fn parse_start_tag<B: BufRead>(
parser: &mut MzMLReader<B>,
start_event: &BytesStart,
) -> Result<Option<Self>, FatalParseError>
where
Self: std::marker::Sized,
{
if start_event.name().as_ref() != b"precursorList" {
return Err(FatalParseError::UnexpectedTag(format!(
"Unexpected event {:?} when processing PrecursorList",
start_event,
)));
}
let attributes = parser.process_attributes(Self::tag(), &LIST_ATTRIBUTES, start_event)?;
let count = match attributes.get("count") {
Some(&AttributeValue::Integer(count)) => count as usize,
_ => 0,
};
parser.breadcrumbs.push_back((Tag::PrecursorList, None));
Ok(Some(PrecursorList::new(count)))
}
fn parse_xml<B: BufRead>(
&mut self,
parser: &mut MzMLReader<B>,
buffer: &mut Vec<u8>,
) -> Result<(), FatalParseError> {
loop {
buffer.clear();
let next_event = parser.next(buffer)?;
let is_empty = matches!(next_event, Event::Empty(_));
match next_event {
Event::Start(start_event) | Event::Empty(start_event) => {
match start_event.name().as_ref() {
b"precursor" => {
if let Some(mut precursor) =
Precursor::parse_start_tag(parser, &start_event)?
{
if !is_empty {
precursor.parse_xml(parser, buffer)?;
}
self.list.push(precursor);
}
}
_ => parser.errors.push_back(ParseError::UnexpectedTag(format!(
"{:?} unexpected when processing {:?}",
std::str::from_utf8(start_event.name().as_ref()),
Self::tag()
))),
}
}
Event::End(end_event) => {
if let b"precursorList" = end_event.name().as_ref() {
parser.breadcrumbs.pop_back();
break;
}
}
Event::Eof => {
return Err(FatalParseError::MissingClosingTag(
"precursorList".to_string(),
));
}
_ => {}
}
}
Ok(())
}
fn tag() -> Tag {
Tag::PrecursorList
}
fn write_xml<W: Write>(&self, writer: &mut Writer<W>) -> Result<(), quick_xml::Error> {
if !self.list.is_empty() {
writer.write_list("precursorList", &self.list)?;
}
Ok(())
}
}
#[derive(Debug, Clone)]
pub struct Precursor {
param_group_refs: Vec<ReferenceableParamGroupRef>,
cv_params: Vec<CVParam>,
user_params: Vec<UserParam>,
external_spectrum_id: Option<String>,
source_file_ref: Option<SourceFileRef>,
spectrum_ref: Option<SpectrumRef>,
isolation_window: Option<IsolationWindow>,
pub(crate) selected_ion_list: Option<SelectedIonList>, activation: Activation,
}
impl Default for Precursor {
fn default() -> Self {
Self::new()
}
}
impl Precursor {
pub fn set_source_file_ref(&mut self, source_file_ref: SourceFileRef) {
self.source_file_ref = Some(source_file_ref);
}
pub fn set_spectrum_ref(&mut self, spectrum_ref: SpectrumRef) {
self.spectrum_ref = Some(spectrum_ref);
}
pub fn external_spectrum_id(&self) -> Option<&str> {
self.external_spectrum_id.as_deref()
}
}
impl Precursor {
pub fn new() -> Self {
Precursor {
param_group_refs: Vec::new(),
cv_params: Vec::new(),
user_params: Vec::new(),
external_spectrum_id: None,
source_file_ref: None,
spectrum_ref: None,
isolation_window: None,
selected_ion_list: None,
activation: Activation::new(),
}
}
pub fn isolation_window(&self) -> Option<&IsolationWindow> {
self.isolation_window.as_ref()
}
pub fn activation(&self) -> &Activation {
&self.activation
}
pub fn selected_ion_list(&self) -> Option<&Vec<SelectedIon>> {
match &self.selected_ion_list {
Some(selected_ion_list) => Some(&selected_ion_list.list),
None => None,
}
}
}
impl MzMLTag for Precursor {
fn parse_start_tag<B: BufRead>(
parser: &mut MzMLReader<B>,
start_event: &BytesStart,
) -> Result<Option<Self>, FatalParseError>
where
Self: std::marker::Sized,
{
if start_event.name().as_ref() != b"precursor" {
Err(FatalParseError::UnexpectedTag(format!(
"Unexpected event {:?} when processing Precursor",
start_event,
)))
} else {
parser.breadcrumbs.push_back((Tag::Precursor, None));
Ok(Some(Precursor::new()))
}
}
fn parse_xml<B: BufRead>(
&mut self,
parser: &mut MzMLReader<B>,
buffer: &mut Vec<u8>,
) -> Result<(), FatalParseError> {
loop {
buffer.clear();
let next_event = parser.next(buffer)?;
match next_event {
Event::Start(start_event) | Event::Empty(start_event) => match start_event
.name()
.as_ref()
{
b"cvParam" => {
if let Some(cv_param) = CVParam::parse_start_tag(parser, &start_event)? {
self.cv_params.push(cv_param);
}
}
b"referenceableParamGroupRef" => {
let param_group_ref =
ReferenceableParamGroupRef::parse_start_tag(parser, &start_event)?;
self.param_group_refs.push(param_group_ref);
}
b"userParam" => {
if let Some(user_param) = UserParam::parse_start_tag(parser, &start_event)?
{
self.user_params.push(user_param);
}
}
b"isolationWindow" => {
if let Some(mut isolation_window) =
IsolationWindow::parse_start_tag(parser, &start_event)?
{
isolation_window.parse_xml(parser, buffer)?;
self.isolation_window = Some(isolation_window);
}
}
b"selectedIonList" => {
if let Some(mut selected_ion_list) =
SelectedIonList::parse_start_tag(parser, &start_event)?
{
selected_ion_list.parse_xml(parser, buffer)?;
self.selected_ion_list = Some(selected_ion_list);
}
}
b"activation" => {
if let Some(mut activation) =
Activation::parse_start_tag(parser, &start_event)?
{
activation.parse_xml(parser, buffer)?;
self.activation = activation
}
}
_ => parser.errors.push_back(ParseError::UnexpectedTag(format!(
"{:?} unexpected when processing {:?}",
std::str::from_utf8(start_event.name().as_ref()),
Self::tag()
))),
},
Event::End(end_event) => {
if let b"precursor" = end_event.name().as_ref() {
parser.breadcrumbs.pop_back();
break;
}
}
Event::Eof => {
return Err(FatalParseError::MissingClosingTag("precursor".to_string()));
}
_ => {}
}
}
Ok(())
}
fn tag() -> Tag {
Tag::Precursor
}
fn write_xml<W: Write>(&self, writer: &mut Writer<W>) -> Result<(), quick_xml::Error> {
writer.start_tag("precursor")?;
self.write_ref_param_groups_xml(writer)?;
self.write_params_xml(writer)?;
if let Some(selected_ion_list) = &self.selected_ion_list {
selected_ion_list.write_xml(writer)?;
}
self.activation.write_xml(writer)?;
writer.end_tag("precursor")
}
}
impl HasCVParams for Precursor {
fn add_cv_param(&mut self, param: CVParam) {
self.cv_params.push(param);
}
fn cv_params(&self) -> &Vec<CVParam> {
&self.cv_params
}
fn cv_params_mut(&mut self) -> &mut Vec<CVParam> {
self.cv_params.as_mut()
}
fn add_user_param(&mut self, param: UserParam) {
self.user_params.push(param);
}
fn user_params(&self) -> &Vec<UserParam> {
&self.user_params
}
}
impl HasParamGroupRefs for Precursor {
fn add_param_group_ref(&mut self, param_group_ref: ReferenceableParamGroupRef) {
self.param_group_refs.push(param_group_ref);
}
fn param_group_refs(&self) -> &Vec<ReferenceableParamGroupRef> {
&self.param_group_refs
}
}
#[derive(Debug, Clone)]
pub struct Product {
isolation_window: Option<IsolationWindow>,
}
impl Default for Product {
fn default() -> Self {
Self::new()
}
}
impl Product {
pub fn new() -> Self {
Product {
isolation_window: None,
}
}
pub fn isolation_window(&self) -> Option<&IsolationWindow> {
self.isolation_window.as_ref()
}
}
impl MzMLTag for Product {
fn parse_start_tag<B: BufRead>(
parser: &mut MzMLReader<B>,
start_event: &BytesStart,
) -> Result<Option<Self>, FatalParseError>
where
Self: std::marker::Sized,
{
if start_event.name().as_ref() != b"product" {
Err(FatalParseError::UnexpectedTag(format!(
"Unexpected event {:?} when processing Product",
start_event,
)))
} else {
parser.breadcrumbs.push_back((Tag::Precursor, None));
Ok(Some(Product::new()))
}
}
fn parse_xml<B: BufRead>(
&mut self,
parser: &mut MzMLReader<B>,
buffer: &mut Vec<u8>,
) -> Result<(), FatalParseError> {
loop {
buffer.clear();
let next_event = parser.next(buffer)?;
match next_event {
Event::Start(start_event) | Event::Empty(start_event) => {
match start_event.name().as_ref() {
b"isolationWindow" => {
if let Some(mut isolation_window) =
IsolationWindow::parse_start_tag(parser, &start_event)?
{
isolation_window.parse_xml(parser, buffer)?;
self.isolation_window = Some(isolation_window);
}
}
_ => parser.errors.push_back(ParseError::UnexpectedTag(format!(
"{:?} unexpected when processing {:?}",
std::str::from_utf8(start_event.name().as_ref()),
Self::tag()
))),
}
}
Event::End(end_event) => {
if let b"product" = end_event.name().as_ref() {
parser.breadcrumbs.pop_back();
break;
}
}
Event::Eof => {
return Err(FatalParseError::MissingClosingTag("product".to_string()));
}
_ => {}
}
}
Ok(())
}
fn tag() -> Tag {
Tag::Product
}
fn write_xml<W: Write>(&self, writer: &mut Writer<W>) -> Result<(), quick_xml::Error> {
writer.start_tag("product")?;
if let Some(isolation_window) = &self.isolation_window {
isolation_window.write_xml(writer)?;
}
writer.end_tag("product")
}
}
#[derive(Debug, Clone)]
pub struct SelectedIonList {
pub(crate) list: Vec<SelectedIon>,
}
impl SelectedIonList {
pub fn new(count: usize) -> Self {
SelectedIonList {
list: Vec::with_capacity(count),
}
}
}
impl MzMLTag for SelectedIonList {
fn parse_start_tag<B: BufRead>(
parser: &mut MzMLReader<B>,
start_event: &BytesStart,
) -> Result<Option<Self>, FatalParseError>
where
Self: std::marker::Sized,
{
if start_event.name().as_ref() != b"selectedIonList" {
return Err(FatalParseError::UnexpectedTag(format!(
"Unexpected event {:?} when processing SelectedIonList",
start_event,
)));
}
let attributes = parser.process_attributes(Self::tag(), &LIST_ATTRIBUTES, start_event)?;
let count = match attributes.get("count") {
Some(&AttributeValue::Integer(count)) => count as usize,
_ => 0,
};
parser.breadcrumbs.push_back((Tag::SelectedIonList, None));
Ok(Some(SelectedIonList::new(count)))
}
fn parse_xml<B: BufRead>(
&mut self,
parser: &mut MzMLReader<B>,
buffer: &mut Vec<u8>,
) -> Result<(), FatalParseError> {
loop {
buffer.clear();
let next_event = parser.next(buffer)?;
match next_event {
Event::Start(start_event) | Event::Empty(start_event) => {
match start_event.name().as_ref() {
b"selectedIon" => {
if let Some(mut selected_ion) =
SelectedIon::parse_start_tag(parser, &start_event)?
{
selected_ion.parse_xml(parser, buffer)?;
self.list.push(selected_ion);
}
}
_ => parser.errors.push_back(ParseError::UnexpectedTag(format!(
"{:?} unexpected when processing {:?}",
std::str::from_utf8(start_event.name().as_ref()),
Self::tag()
))),
}
}
Event::End(end_event) => {
if let b"selectedIonList" = end_event.name().as_ref() {
parser.breadcrumbs.pop_back();
break;
}
}
Event::Eof => {
return Err(FatalParseError::MissingClosingTag(
"selectedIonList".to_string(),
));
}
_ => {}
}
}
Ok(())
}
fn tag() -> Tag {
Tag::SelectedIonList
}
fn write_xml<W: Write>(&self, writer: &mut Writer<W>) -> Result<(), quick_xml::Error> {
if !self.list.is_empty() {
writer.write_list("selectedIonList", &self.list)?;
}
Ok(())
}
}
#[derive(Debug, Clone)]
pub struct SelectedIon {
param_group_refs: Vec<ReferenceableParamGroupRef>,
cv_params: Vec<CVParam>,
user_params: Vec<UserParam>,
}
impl Default for SelectedIon {
fn default() -> Self {
Self::new()
}
}
impl SelectedIon {
pub fn new() -> Self {
SelectedIon {
param_group_refs: Vec::new(),
cv_params: Vec::new(),
user_params: Vec::new(),
}
}
}
impl MzMLTag for SelectedIon {
fn parse_start_tag<B: BufRead>(
parser: &mut MzMLReader<B>,
start_event: &BytesStart,
) -> Result<Option<Self>, FatalParseError>
where
Self: std::marker::Sized,
{
if start_event.name().as_ref() != b"selectedIon" {
Err(FatalParseError::UnexpectedTag(format!(
"Unexpected event {:?} when processing SelectedIon",
start_event,
)))
} else {
parser.breadcrumbs.push_back((Tag::SelectedIon, None));
Ok(Some(SelectedIon::new()))
}
}
fn parse_xml<B: BufRead>(
&mut self,
parser: &mut MzMLReader<B>,
buffer: &mut Vec<u8>,
) -> Result<(), FatalParseError> {
loop {
buffer.clear();
let next_event = parser.next(buffer)?;
match next_event {
Event::Start(start_event) | Event::Empty(start_event) => match start_event
.name()
.as_ref()
{
b"cvParam" => {
if let Some(cv_param) = CVParam::parse_start_tag(parser, &start_event)? {
self.cv_params.push(cv_param);
}
}
b"referenceableParamGroupRef" => {
let param_group_ref =
ReferenceableParamGroupRef::parse_start_tag(parser, &start_event)?;
self.param_group_refs.push(param_group_ref);
}
b"userParam" => {
if let Some(user_param) = UserParam::parse_start_tag(parser, &start_event)?
{
self.user_params.push(user_param);
}
}
_ => parser.errors.push_back(ParseError::UnexpectedTag(format!(
"{:?} unexpected when processing {:?}",
std::str::from_utf8(start_event.name().as_ref()),
Self::tag()
))),
},
Event::End(end_event) => {
if let b"selectedIon" = end_event.name().as_ref() {
parser.breadcrumbs.pop_back();
break;
}
}
Event::Eof => {
return Err(FatalParseError::MissingClosingTag(
"selectedIon".to_string(),
));
}
_ => {}
}
}
Ok(())
}
fn tag() -> Tag {
Tag::SelectedIon
}
fn write_xml<W: Write>(&self, writer: &mut Writer<W>) -> Result<(), quick_xml::Error> {
writer.start_tag("selectedIon")?;
self.write_ref_param_groups_xml(writer)?;
self.write_params_xml(writer)?;
writer.end_tag("selectedIon")
}
}
impl HasCVParams for SelectedIon {
fn add_cv_param(&mut self, param: CVParam) {
self.cv_params.push(param);
}
fn cv_params(&self) -> &Vec<CVParam> {
&self.cv_params
}
fn cv_params_mut(&mut self) -> &mut Vec<CVParam> {
self.cv_params.as_mut()
}
fn add_user_param(&mut self, param: UserParam) {
self.user_params.push(param);
}
fn user_params(&self) -> &Vec<UserParam> {
&self.user_params
}
}
impl HasParamGroupRefs for SelectedIon {
fn add_param_group_ref(&mut self, param_group_ref: ReferenceableParamGroupRef) {
self.param_group_refs.push(param_group_ref);
}
fn param_group_refs(&self) -> &Vec<ReferenceableParamGroupRef> {
&self.param_group_refs
}
}
#[derive(Debug)]
pub struct Target {
param_group_refs: Vec<ReferenceableParamGroupRef>,
cv_params: Vec<CVParam>,
}
impl Clone for Target {
fn clone(&self) -> Self {
Self {
param_group_refs: self.param_group_refs.clone(),
cv_params: self.cv_params.clone(),
}
}
}
#[derive(Debug, Clone)]
pub struct IsolationWindow {
param_group_refs: Vec<ReferenceableParamGroupRef>,
cv_params: Vec<CVParam>,
user_params: Vec<UserParam>,
}
impl Default for IsolationWindow {
fn default() -> Self {
Self::new()
}
}
impl IsolationWindow {
pub fn new() -> Self {
IsolationWindow {
param_group_refs: Vec::new(),
cv_params: Vec::new(),
user_params: Vec::new(),
}
}
}
impl MzMLTag for IsolationWindow {
fn parse_start_tag<B: BufRead>(
parser: &mut MzMLReader<B>,
start_event: &BytesStart,
) -> Result<Option<Self>, FatalParseError>
where
Self: std::marker::Sized,
{
if start_event.name().as_ref() != b"isolationWindow" {
Err(FatalParseError::UnexpectedTag(format!(
"Unexpected event {:?} when processing IsolationWindow",
start_event,
)))
} else {
parser.breadcrumbs.push_back((Tag::IsolationWindow, None));
Ok(Some(IsolationWindow::new()))
}
}
fn parse_xml<B: BufRead>(
&mut self,
parser: &mut MzMLReader<B>,
buffer: &mut Vec<u8>,
) -> Result<(), FatalParseError> {
loop {
buffer.clear();
let next_event = parser.next(buffer)?;
match next_event {
Event::Start(start_event) | Event::Empty(start_event) => {
match start_event.name().as_ref() {
b"cvParam" => {
if let Some(cv_param) = CVParam::parse_start_tag(parser, &start_event)?
{
self.cv_params.push(cv_param);
}
}
b"referenceableParamGroupRef" => {
let param_group_ref =
ReferenceableParamGroupRef::parse_start_tag(parser, &start_event)?;
self.param_group_refs.push(param_group_ref);
}
b"userParam" => {
if let Some(user_param) =
UserParam::parse_start_tag(parser, &start_event)?
{
self.user_params.push(user_param);
}
}
_ => parser.errors.push_back(ParseError::UnexpectedTag(format!(
"{:?} unexpected when processing {:?}",
std::str::from_utf8(start_event.name().as_ref()),
Self::tag()
))),
}
}
Event::End(end_event) => {
if let b"isolationWindow" = end_event.name().as_ref() {
parser.breadcrumbs.pop_back();
break;
}
}
Event::Eof => {
return Err(FatalParseError::MissingClosingTag(
"isolationWindow".to_string(),
));
}
_ => {}
}
}
Ok(())
}
fn tag() -> Tag {
Tag::IsolationWindow
}
fn write_xml<W: Write>(&self, writer: &mut Writer<W>) -> Result<(), quick_xml::Error> {
writer.start_tag("isolationWindow")?;
self.write_ref_param_groups_xml(writer)?;
self.write_params_xml(writer)?;
writer.end_tag("isolationWindow")
}
}
impl HasCVParams for IsolationWindow {
fn add_cv_param(&mut self, param: CVParam) {
self.cv_params.push(param);
}
fn cv_params(&self) -> &Vec<CVParam> {
&self.cv_params
}
fn cv_params_mut(&mut self) -> &mut Vec<CVParam> {
self.cv_params.as_mut()
}
fn add_user_param(&mut self, param: UserParam) {
self.user_params.push(param);
}
fn user_params(&self) -> &Vec<UserParam> {
&self.user_params
}
}
impl HasParamGroupRefs for IsolationWindow {
fn add_param_group_ref(&mut self, param_group_ref: ReferenceableParamGroupRef) {
self.param_group_refs.push(param_group_ref);
}
fn param_group_refs(&self) -> &Vec<ReferenceableParamGroupRef> {
&self.param_group_refs
}
}
#[derive(Debug, Clone)]
pub struct Activation {
param_group_refs: Vec<ReferenceableParamGroupRef>,
cv_params: Vec<CVParam>,
user_params: Vec<UserParam>,
}
impl Default for Activation {
fn default() -> Self {
Self::new()
}
}
impl Activation {
pub fn new() -> Self {
Activation {
param_group_refs: Vec::new(),
cv_params: Vec::new(),
user_params: Vec::new(),
}
}
}
impl MzMLTag for Activation {
fn parse_start_tag<B: BufRead>(
parser: &mut MzMLReader<B>,
start_event: &BytesStart,
) -> Result<Option<Self>, FatalParseError>
where
Self: std::marker::Sized,
{
if start_event.name().as_ref() != b"activation" {
Err(FatalParseError::UnexpectedTag(format!(
"Unexpected event {:?} when processing Activation",
start_event,
)))
} else {
parser.breadcrumbs.push_back((Tag::Activation, None));
Ok(Some(Activation::new()))
}
}
fn parse_xml<B: BufRead>(
&mut self,
parser: &mut MzMLReader<B>,
buffer: &mut Vec<u8>,
) -> Result<(), FatalParseError> {
loop {
buffer.clear();
let next_event = parser.next(buffer)?;
match next_event {
Event::Start(start_event) | Event::Empty(start_event) => match start_event
.name()
.as_ref()
{
b"cvParam" => {
if let Some(cv_param) = CVParam::parse_start_tag(parser, &start_event)? {
self.cv_params.push(cv_param);
}
}
b"referenceableParamGroupRef" => {
let param_group_ref =
ReferenceableParamGroupRef::parse_start_tag(parser, &start_event)?;
self.param_group_refs.push(param_group_ref);
}
b"userParam" => {
if let Some(user_param) = UserParam::parse_start_tag(parser, &start_event)?
{
self.user_params.push(user_param);
}
}
_ => parser.errors.push_back(ParseError::UnexpectedTag(format!(
"{:?} unexpected when processing {:?}",
std::str::from_utf8(start_event.name().as_ref()),
Self::tag()
))),
},
Event::End(end_event) => {
if let b"activation" = end_event.name().as_ref() {
parser.breadcrumbs.pop_back();
break;
}
}
Event::Eof => {
return Err(FatalParseError::MissingClosingTag("activation".to_string()));
}
_ => {}
}
}
Ok(())
}
fn tag() -> Tag {
Tag::Activation
}
fn write_xml<W: Write>(&self, writer: &mut Writer<W>) -> Result<(), quick_xml::Error> {
writer.start_tag("activation")?;
self.write_ref_param_groups_xml(writer)?;
self.write_params_xml(writer)?;
writer.end_tag("activation")
}
}
impl HasCVParams for Activation {
fn add_cv_param(&mut self, param: CVParam) {
self.cv_params.push(param);
}
fn cv_params(&self) -> &Vec<CVParam> {
&self.cv_params
}
fn cv_params_mut(&mut self) -> &mut Vec<CVParam> {
self.cv_params.as_mut()
}
fn add_user_param(&mut self, param: UserParam) {
self.user_params.push(param);
}
fn user_params(&self) -> &Vec<UserParam> {
&self.user_params
}
}
impl HasParamGroupRefs for Activation {
fn add_param_group_ref(&mut self, param_group_ref: ReferenceableParamGroupRef) {
self.param_group_refs.push(param_group_ref);
}
fn param_group_refs(&self) -> &Vec<ReferenceableParamGroupRef> {
&self.param_group_refs
}
}