stripper_xml/
channels.rs

1use itertools::Itertools;
2use serde::{Deserialize, Serialize, Serializer};
3
4#[derive(Deserialize, Serialize)]
5#[derive(Clone, Debug, Default, Eq, PartialEq, Ord, PartialOrd, Hash)]
6#[serde(rename_all = "PascalCase")]
7pub struct Init {
8    pub incoming: String,
9    pub scales: String,
10    pub channels: Channels,
11}
12
13#[derive(Deserialize, Serialize)]
14#[derive(Clone, Debug, Default, Eq, PartialEq, Ord, PartialOrd, Hash)]
15#[serde(rename_all = "PascalCase")]
16pub struct Channels {
17    pub channel: Vec<Channel>
18}
19
20#[derive(Clone, Debug, Default, Eq, PartialEq, Ord, PartialOrd, Hash)]
21pub struct Channel (pub Vec<i32>);
22
23impl<'de> Deserialize<'de> for Channel {
24    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
25    where
26        D: serde::Deserializer<'de> {
27        use serde::de::Error;
28        let channel_str = String::deserialize(deserializer)?;
29        let entries: Result<Vec<i32>, _> = channel_str.split(',')
30            .map(|e| e.parse())
31            .collect();
32        let entries = entries.map_err(Error::custom)?;
33        Ok(Self(entries))
34    }
35}
36
37impl Serialize for Channel {
38    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
39    where
40        S: Serializer,
41    {
42        let res = self.0.iter().map(ToString::to_string).join(",");
43        serializer.serialize_str(&res)
44    }
45}
46
47#[cfg(test)]
48mod tests {
49    use super::*;
50
51    #[test]
52    fn deser_init() {
53        const REF_CHANNELS: &str = r#"<?xml version="1.0" encoding="UTF-8"?>
54<Init>
55  <Incoming> p p with NNPDF31_nnlo_as_0118/0 </Incoming>
56  <Scales> muR = HT, muF = HT </Scales>
57  <Channels>
58    <Channel> 0,5,1,1,2,2,3,3,4,4,5,5 </Channel>
59    <Channel> 1,5,1,-1,2,-2,3,-3,4,-4,5,-5 </Channel>
60    <Channel> 2,20,1,2,1,3,1,4,1,5,2,1,2,3,2,4,2,5,3,1,3,2,3,4,3,5,4,1,4,2,4,3,4,5,5,1,5,2,5,3,5,4 </Channel>
61    <Channel> 3,20,1,-2,1,-3,1,-4,1,-5,2,-1,2,-3,2,-4,2,-5,3,-1,3,-2,3,-4,3,-5,4,-1,4,-2,4,-3,4,-5,5,-1,5,-2,5,-3,5,-4 </Channel>
62    <Channel> 4,5,1,21,2,21,3,21,4,21,5,21 </Channel>
63    <Channel> 5,5,-1,1,-2,2,-3,3,-4,4,-5,5 </Channel>
64    <Channel> 6,5,-1,-1,-2,-2,-3,-3,-4,-4,-5,-5 </Channel>
65    <Channel> 7,20,-1,2,-1,3,-1,4,-1,5,-2,1,-2,3,-2,4,-2,5,-3,1,-3,2,-3,4,-3,5,-4,1,-4,2,-4,3,-4,5,-5,1,-5,2,-5,3,-5,4 </Channel>
66    <Channel> 8,20,-1,-2,-1,-3,-1,-4,-1,-5,-2,-1,-2,-3,-2,-4,-2,-5,-3,-1,-3,-2,-3,-4,-3,-5,-4,-1,-4,-2,-4,-3,-4,-5,-5,-1,-5,-2,-5,-3,-5,-4 </Channel>
67    <Channel> 9,5,-1,21,-2,21,-3,21,-4,21,-5,21 </Channel>
68    <Channel> 10,5,21,1,21,2,21,3,21,4,21,5 </Channel>
69    <Channel> 11,5,21,-1,21,-2,21,-3,21,-4,21,-5 </Channel>
70    <Channel> 12,1,21,21 </Channel>
71  </Channels>
72</Init>
73"#;
74        let init: Init = quick_xml::de::from_str(REF_CHANNELS).unwrap();
75        assert_eq!(init.channels.channel[5].0, [5,5,-1,1,-2,2,-3,3,-4,4,-5,5]);
76    }
77}