packlist: less normalization to support proper roundtrips (which only truncate trailing spaces)

fogti
Sep 21, 2021, 11:32 AM
VHLGEBT74I5RXLGUWMVCXM64BYG7HOOFT7SURJ5TCTB3AAOQHIKQC

Dependencies

  • [2] NAZOIBER packlist: fix crash on empty input
  • [3] JWYGE7FX packlist : +reset utility
  • [4] BUI22CYQ +zhed-packlist
  • [5] 7WMS7RLP packlist: add support for parsing of multiple premarkers per item
  • [6] V4EAN7NN move some stuff around; more packlist stuff

Change contents

  • replacement in crates/zhed-packlist/src/serial.rs at line 1
    [4.34][4.0:42](),[4.42][4.35:74](),[4.34][4.35:74]()
    use crate::{ItemData, PackList, Section};
    use std::{collections::BTreeMap, fmt};
    [4.34]
    [4.116]
    use crate::{Item, ItemDetails, PackList, Spaced};
    use alloc::{string::ToString, vec::Vec};
    use core::fmt;
  • replacement in crates/zhed-packlist/src/serial.rs at line 5
    [4.117][4.117:167]()
    #[derive(thiserror::Error, Debug, PartialEq, Eq)]
    [4.117]
    [4.167]
    #[derive(Debug, PartialEq, Eq)]
    #[cfg_attr(feature = "std", derive(thiserror::Error))]
  • replacement in crates/zhed-packlist/src/serial.rs at line 8
    [4.184][4.184:417](),[4.417][2.0:31]()
    #[error("unexpected data after range specification in header")]
    DataAfterRangeSpec,
    #[error("section is defined multiple times")]
    SectionOverwritten(String),
    #[error("invalid item: {0}")]
    InvalidItem(String),
    #[error("unexpected EOF")]
    [4.184]
    [2.31]
    /// ```
    /// use zhed_packlist::{PackList, ParseError};
    /// assert_eq!("".parse::<PackList>(), Err(ParseError::UnexpectedEof));
    /// ```
    #[cfg_attr(feature = "std", error("unexpected EOF"))]
  • replacement in crates/zhed-packlist/src/serial.rs at line 16
    [4.420][4.420:458]()
    impl std::str::FromStr for PackList {
    [4.420]
    [4.458]
    impl core::str::FromStr for PackList {
  • replacement in crates/zhed-packlist/src/serial.rs at line 20
    [4.531][4.531:563]()
    let mut it = s.lines();
    [4.531]
    [4.563]
    let mut it = s.lines().map(|i| i.trim_end());
  • replacement in crates/zhed-packlist/src/serial.rs at line 22
    [4.564][4.564:609](),[4.609][2.51:131](),[2.131][4.658:1399](),[4.658][4.658:1399]()
    // 1st line: packlist name and range
    let mut fst = it.next().map(|x| x.trim()).ok_or(Error::UnexpectedEof)?;
    if let Some(x) = fst.strip_suffix(':') {
    fst = x;
    }
    let (name, range) = {
    let (rstart, rend) = (fst.find('('), fst.rfind(')'));
    if rstart.is_some() && rend.is_some() && rstart.unwrap() < rend.unwrap() {
    let (rstart, rend) = (rstart.unwrap(), rend.unwrap());
    if rend != (fst.len() - 1) {
    return Err(Error::DataAfterRangeSpec);
    }
    let mut name = fst[..rstart].trim();
    if let Some(x) = name.strip_suffix(':') {
    name = x.trim();
    }
    (name, &fst[rstart + 1..rend])
    } else {
    (fst, "")
    }
    };
    [4.564]
    [4.1399]
    // 1st line: packlist name
    let name = it.next().ok_or(Error::UnexpectedEof)?;
  • replacement in crates/zhed-packlist/src/serial.rs at line 26
    [4.1425][4.1425:1532](),[4.1532][4.43:419](),[4.419][4.1808:2344](),[4.1808][4.1808:2344]()
    let mut sections = BTreeMap::new();
    let mut section = (String::new(), Section::default());
    macro_rules! commit {
    () => {{
    if sections.contains_key(&section.0) {
    return Err(Error::SectionOverwritten(section.0));
    }
    sections.insert(
    std::mem::take(&mut section.0),
    std::mem::take(&mut section.1),
    );
    }};
    }
    for line in it {
    if line.trim().is_empty() {
    continue;
    }
    let (itemdata, desc) = parse_item(line)?;
    if let Some(x) = desc.strip_prefix('#') {
    commit!();
    section.0 = x.trim().to_string();
    section.1.summary = itemdata;
    } else {
    section.1.items.push((itemdata, desc));
    }
    }
    if !section.0.is_empty() || !section.1.items.is_empty() {
    commit!();
    }
    [4.1425]
    [4.2344]
    let items = it
    .map(|line| match line.parse() {
    Ok(x) => x,
    Err(x) => match x {},
    })
    .collect();
  • replacement in crates/zhed-packlist/src/serial.rs at line 35
    [4.2403][4.2403:2463]()
    range: range.to_string(),
    sections,
    [4.2403]
    [4.2463]
    items,
    })
    }
    }
    impl core::str::FromStr for Item {
    type Err = core::convert::Infallible;
    fn from_str(line: &str) -> Result<Self, core::convert::Infallible> {
    let (det, text) = parse_itemdet(line)
    .map(|(det, rest)| (Some(det), rest))
    .unwrap_or((None, line));
    Ok(Self {
    det,
    text: text.to_string(),
  • replacement in crates/zhed-packlist/src/serial.rs at line 54
    [4.2483][4.2483:2548](),[4.2548][4.420:477]()
    fn parse_item(line: &str) -> Result<(ItemData, String), Error> {
    let mkerr = || Error::InvalidItem(line.to_string());
    [4.2483]
    [4.2548]
    fn parse_itemdet(mut line: &str) -> Option<(ItemDetails, &str)> {
  • replacement in crates/zhed-packlist/src/serial.rs at line 56
    [4.2572][4.478:507]()
    return Err(mkerr());
    [4.2572]
    [4.507]
    return None;
  • replacement in crates/zhed-packlist/src/serial.rs at line 58
    [4.513][4.513:555]()
    let mut it = line.chars().peekable();
    [4.513]
    [4.555]
    let mut ret = ItemDetails {
    markers: Vec::new(),
    multiplier: None,
    };
  • replacement in crates/zhed-packlist/src/serial.rs at line 63
    [4.556][4.556:868]()
    // parse premarkers
    let mut premarkers = Vec::new();
    while it.next_if(|i| *i == '[').is_some() {
    let premarker = it.next().ok_or_else(mkerr)?;
    let _ = it.next().ok_or_else(mkerr)?;
    let c2 = it.next().ok_or_else(mkerr)?;
    if c2 != ']' {
    return Err(mkerr());
    [4.556]
    [4.868]
    // parse markers
    while let Some(x) = line.strip_prefix('[') {
    let mut it = x.chars();
    let a = it.next()?;
    let b = it.next()?;
    if ']' != it.next()? {
    return None;
  • replacement in crates/zhed-packlist/src/serial.rs at line 71
    [4.878][4.878:975]()
    premarkers.push(premarker);
    while it.next_if(|i| i.is_whitespace()).is_some() {}
    [4.878]
    [4.2630]
    line = it.as_str();
    let wsl = it
    .take_while(|i| i.is_whitespace())
    .map(|i| i.len_utf8())
    .sum::<usize>();
    let (space, rest) = line.split_at(wsl);
    ret.markers.push(Spaced {
    val: [a, b],
    space: space.to_string(),
    });
    line = rest;
  • replacement in crates/zhed-packlist/src/serial.rs at line 83
    [4.2636][4.976:1036]()
    if premarkers.is_empty() {
    return Err(mkerr());
    [4.2636]
    [4.2895]
    if ret.markers.is_empty() {
    return None;
  • replacement in crates/zhed-packlist/src/serial.rs at line 87
    [4.2991][4.2991:3382](),[4.3475][4.3475:3493](),[4.3493][4.1037:1111]()
    // check for multiplier
    // btp : backtrack point if no valid multiplier is found
    let btp = it.clone();
    let mut multiplier = None;
    while let Some(x) = it.next_if(|i| i.is_ascii_digit()) {
    let m = multiplier.get_or_insert(0);
    *m *= 10;
    *m += u32::from((x as u8) - b'0');
    }
    if it.next_if(|&i| i == 'x').is_none() {
    multiplier = None;
    it = btp;
    } else {
    while it.next_if(|i| i.is_whitespace()).is_some() {}
    [4.2991]
    [4.3493]
    if let Some((val, space, rest)) = parse_multiplier(line) {
    ret.multiplier = Some(Spaced {
    val,
    space: space.to_string(),
    });
    line = rest;
  • replacement in crates/zhed-packlist/src/serial.rs at line 95
    [4.3500][4.1112:1253]()
    Ok((
    ItemData {
    premarkers,
    multiplier: multiplier.unwrap_or(1),
    },
    it.collect(),
    ))
    [4.3500]
    [4.3605]
    Some((ret, line))
  • replacement in crates/zhed-packlist/src/serial.rs at line 98
    [4.3608][4.3608:3937](),[4.3937][4.1254:1320]()
    impl fmt::Display for PackList {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
    f.write_str(&self.name)?;
    if !self.range.is_empty() {
    write!(f, " ({})", self.range)?;
    }
    writeln!(f)?;
    for (section, sdata) in &self.sections {
    if !section.is_empty() {
    writeln!(f, "\n{}# {}", sdata.summary, section)?;
    [4.3608]
    [4.4212]
    fn parse_multiplier(line: &str) -> Option<(u32, &str, &str)> {
    if !line.starts_with(|i: char| i.is_ascii_digit()) {
    return None;
    }
    let mut multiplier = 0;
    let mut it = line.chars();
    loop {
    match it.next() {
    Some('x') => {
    let tmp = it.as_str();
    let wsl = it
    .take_while(|i| i.is_whitespace())
    .map(|i| i.len_utf8())
    .sum::<usize>();
    let (a, b) = tmp.split_at(wsl);
    return Some((multiplier, a, b));
  • replacement in crates/zhed-packlist/src/serial.rs at line 115
    [4.4226][4.4226:4265](),[4.4265][4.1321:1375]()
    for item in &sdata.items {
    writeln!(f, "{}{}", item.0, item.1)?;
    [4.4226]
    [4.4486]
    Some(i) if i.is_ascii_digit() => {
    multiplier *= 10;
    multiplier += u32::from((i as u8) - b'0');
  • edit in crates/zhed-packlist/src/serial.rs at line 119
    [4.4500]
    [4.1376]
    _ => return None,
    }
    }
    }
    impl fmt::Display for PackList {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
    writeln!(f, "{}", self.name.trim_end())?;
    for item in &self.items {
    writeln!(f, "{}", item)?;
  • replacement in crates/zhed-packlist/src/serial.rs at line 134
    [4.1410][4.1410:1443]()
    impl fmt::Display for ItemData {
    [4.1410]
    [4.1443]
    impl fmt::Display for Item {
  • replacement in crates/zhed-packlist/src/serial.rs at line 136
    [4.1506][4.1506:1579]()
    for i in &self.premarkers {
    write!(f, "[{} ] ", i)?;
    [4.1506]
    [4.4500]
    if let Some(x) = &self.det {
    fmt::Display::fmt(x, f)?;
  • replacement in crates/zhed-packlist/src/serial.rs at line 139
    [4.4510][4.1580:1663]()
    if self.multiplier != 1 {
    write!(f, "{}x ", self.multiplier)?;
    [4.4510]
    [4.1663]
    f.write_str(self.text.trim_end())
    }
    }
    impl fmt::Display for ItemDetails {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
    for m in &self.markers {
    write!(f, "[{}{}]{}", m.val[0], m.val[1], m.space)?;
    }
    if let Some(x) = &self.multiplier {
    write!(f, "{}x{}", x.val, x.space)?;
  • edit in crates/zhed-packlist/src/serial.rs at line 158
    [4.4577]
    [2.132]
    use alloc::{string::String, vec};
  • edit in crates/zhed-packlist/src/serial.rs at line 160
    [2.162][4.1674:1675](),[4.4577][4.1674:1675](),[4.1675][4.4577:5021](),[4.4577][4.4577:5021](),[4.5021][4.1676:2595](),[4.2595][4.5587:5602](),[4.5587][4.5587:5602](),[4.5602][4.2596:3413](),[4.3413][4.5836:6204](),[4.5836][4.5836:6204](),[4.6204][4.3414:3827]()
    #[test]
    fn ex0() {
    let inp1 = r#"Packliste Ölland (80 Tage, 50 Nächtsle):
    [ ] 15 Ruß
    [ ] 132x Wattestäbe
    [# ] 0x Handtuch
    [- ] 5000x # Wachsbaum ...
    [ ] Ranke
    [* ] 5 x Metrik + BNaumbnd
    "#;
    let inp2 = r#"Packliste Ölland (80 Tage, 50 Nächtsle)
    [ ] 15 Ruß
    [ ] 132x Wattestäbe
    [# ] 0x Handtuch
    [- ] 5000x # Wachsbaum ...
    [ ] Ranke
    [* ] 5 x Metrik + BNaumbnd
    "#;
    let mut sections = BTreeMap::new();
    sections.insert(
    String::new(),
    Section {
    summary: ItemData::default(),
    items: vec![
    (
    ItemData {
    premarkers: vec![' '],
    multiplier: 1,
    },
    "15 Ruß".to_string(),
    ),
    (
    ItemData {
    premarkers: vec![' '],
    multiplier: 132,
    },
    "Wattestäbe".to_string(),
    ),
    (
    ItemData {
    premarkers: vec!['#'],
    multiplier: 0,
    },
    "Handtuch".to_string(),
    ),
    ],
    },
    );
    sections.insert(
    "Wachsbaum ...".to_string(),
    Section {
    summary: ItemData {
    premarkers: vec!['-'],
    multiplier: 5000,
    },
    items: vec![
    (
    ItemData {
    premarkers: vec![' '],
    multiplier: 1,
    },
    "Ranke".to_string(),
    ),
    (
    ItemData {
    premarkers: vec!['*'],
    multiplier: 1,
    },
    "5 x Metrik + BNaumbnd".to_string(),
    ),
    ],
    },
    );
    let res = PackList {
    name: "Packliste Ölland".to_string(),
    range: "80 Tage, 50 Nächtsle".to_string(),
    sections,
    };
    assert_eq!(inp1.parse::<PackList>().unwrap(), res);
    assert_eq!(inp2.parse::<PackList>().unwrap(), res);
    assert_eq!(res.to_string(), inp2);
    }
    #[test]
    fn fail0() {
    assert_eq!(
    "Packl (xyz) ...\n".parse::<PackList>(),
    Err(Error::DataAfterRangeSpec)
    );
    assert_eq!(
    "P\n[ ] # 1\n[ ] # 1\n".parse::<PackList>(),
    Err(Error::SectionOverwritten("1".to_string()))
    );
    assert_eq!(
    "P\n[ ]".parse::<PackList>(),
    Err(Error::InvalidItem("[ ]".to_string()))
    );
    }
  • edit in crates/zhed-packlist/src/serial.rs at line 162
    [4.3840][2.163:270]()
    fn fail1() {
    assert_eq!("".parse::<PackList>(), Err(Error::UnexpectedEof));
    }
    #[test]
  • replacement in crates/zhed-packlist/src/serial.rs at line 163
    [4.3855][4.3855:3924]()
    let inp1 = r#"Packliste Ölland:
    [* ] [ _] [. ] 15 132x Ruß
    [4.3855]
    [4.3924]
    let inp = r#"Packliste Ölland:
  • replacement in crates/zhed-packlist/src/serial.rs at line 166
    [4.3953][4.3953:4404]()
    let inp2 = r#"Packliste Ölland
    [* ] [ ] [. ] 15 132x Ruß
    [* ] [ ] [. ] 132x Ruß
    "#;
    let mut sections = BTreeMap::new();
    sections.insert(
    String::new(),
    Section {
    summary: ItemData::default(),
    items: vec![
    (
    ItemData {
    premarkers: vec!['*', ' ', '.'],
    multiplier: 1,
    [4.3953]
    [4.4404]
    let res = PackList {
    name: "Packliste Ölland:".to_string(),
    items: vec![Item {
    det: Some(ItemDetails {
    markers: vec![
    Spaced {
    val: ['*', ' '],
    space: " ".to_string(),
  • replacement in crates/zhed-packlist/src/serial.rs at line 175
    [4.4431][4.4431:4669]()
    "15 132x Ruß".to_string(),
    ),
    (
    ItemData {
    premarkers: vec!['*', ' ', '.'],
    multiplier: 132,
    [4.4431]
    [4.4669]
    Spaced {
    val: [' ', '_'],
    space: " ".to_string(),
  • replacement in crates/zhed-packlist/src/serial.rs at line 179
    [4.4696][4.4696:4944]()
    "Ruß".to_string(),
    ),
    ],
    },
    );
    let res = PackList {
    name: "Packliste Ölland".to_string(),
    range: String::new(),
    sections,
    [4.4696]
    [4.4944]
    Spaced {
    val: ['.', ' '],
    space: " ".to_string(),
    },
    ],
    multiplier: Some(Spaced {
    val: 132,
    space: " ".to_string(),
    }),
    }),
    text: "Ruß".to_string(),
    }],
  • replacement in crates/zhed-packlist/src/serial.rs at line 192
    [4.4955][4.4955:5118]()
    assert_eq!(inp1.parse::<PackList>().unwrap(), res);
    assert_eq!(inp2.parse::<PackList>().unwrap(), res);
    assert_eq!(res.to_string(), inp2);
    [4.4955]
    [2.271]
    assert_eq!(inp.parse::<PackList>().unwrap(), res);
    assert_eq!(res.to_string(), inp);
  • edit in crates/zhed-packlist/src/serial.rs at line 201
    [2.403]
    [4.6509]
    #[test]
    fn correctly_trimmed(s in "(?s:.+)") {
    let s2: String = s.lines().flat_map(|i| i.trim_end().chars().chain(core::iter::once('\n'))).collect();
    let x1 = s.parse::<PackList>().unwrap();
    let x2 = s2.parse::<PackList>().unwrap();
    assert_eq!(x1, x2);
    }
    #[test]
    fn roundtrip(s in "(?s:[^\r]+\n)".prop_filter("line ends are trimmed", |v| v.lines().all(|l| l == l.trim_end()))) {
    assert_eq!(s, s.parse::<PackList>().unwrap().to_string());
    }
  • replacement in crates/zhed-packlist/src/lib.rs at line 1
    [4.73][4.74:106]()
    use std::collections::BTreeMap;
    [4.73]
    [4.106]
    #![cfg_attr(not(feature = "std"), no_std)]
    #![forbid(
    unsafe_code,
    clippy::as_conversions,
    clippy::cast_ptr_alignment,
    trivial_casts,
    unconditional_recursion
    )]
    extern crate alloc;
    use alloc::{string::String, vec, vec::Vec};
  • replacement in crates/zhed-packlist/src/lib.rs at line 19
    [4.240][4.240:308]()
    pub range: String,
    pub sections: BTreeMap<String, Section>,
    [4.240]
    [4.308]
    pub items: Vec<Item>,
    }
    #[derive(Clone, Debug, PartialEq, Eq)]
    pub struct Item {
    pub det: Option<ItemDetails>,
    pub text: String,
  • replacement in crates/zhed-packlist/src/lib.rs at line 28
    [4.311][4.311:447]()
    #[derive(Clone, Debug, Default, PartialEq, Eq)]
    pub struct Section {
    pub summary: ItemData,
    pub items: Vec<(ItemData, String)>,
    [4.311]
    [4.447]
    /// packlist item details
    #[derive(Clone, Debug, PartialEq, Eq)]
    pub struct ItemDetails {
    pub markers: Vec<Spaced<[char; 2]>>,
    pub multiplier: Option<Spaced<u32>>,
  • replacement in crates/zhed-packlist/src/lib.rs at line 36
    [4.489][4.489:511](),[4.511][4.5119:5150](),[4.5150][4.536:561](),[4.536][4.536:561]()
    pub struct ItemData {
    pub premarkers: Vec<char>,
    pub multiplier: u32,
    [4.489]
    [4.561]
    pub struct Spaced<T> {
    pub val: T,
    // white space folloing the value
    pub space: String,
  • replacement in crates/zhed-packlist/src/lib.rs at line 42
    [4.564][4.564:592]()
    impl Default for ItemData {
    [4.564]
    [4.592]
    impl Default for ItemDetails {
  • replacement in crates/zhed-packlist/src/lib.rs at line 45
    [4.634][4.5151:5186](),[4.5186][4.662:689](),[4.662][4.662:689]()
    premarkers: vec![' '],
    multiplier: 1,
    [4.634]
    [4.689]
    markers: vec![Spaced {
    val: [' ', ' '],
    space: String::new(),
    }],
    multiplier: None,
  • replacement in crates/zhed-packlist/src/lib.rs at line 54
    [4.708][4.708:765](),[4.765][4.5187:5286](),[4.5286][4.838:844](),[4.838][4.838:844]()
    impl PackList {
    pub fn reset_premarkers(&mut self) {
    self.sections
    .values_mut()
    .for_each(|sd| sd.reset_premarkers());
    }
    [4.708]
    [4.844]
    pub trait Commands {
    fn reset_markers(&mut self);
    }
    pub mod prelude {
    pub use crate::Commands as _;
  • replacement in crates/zhed-packlist/src/lib.rs at line 62
    [4.847][4.847:903](),[4.903][4.5287:5491]()
    impl Section {
    pub fn reset_premarkers(&mut self) {
    core::iter::once(&mut self.summary)
    .chain(self.items.iter_mut().map(|item| &mut item.0))
    .flat_map(|item| item.premarkers.iter_mut())
    .for_each(|i| *i = ' ');
    [4.847]
    [4.1012]
    impl Commands for PackList {
    fn reset_markers(&mut self) {
    self.items.iter_mut().for_each(|i| i.reset_markers());
  • replacement in crates/zhed-packlist/src/lib.rs at line 68
    [4.1021][4.1021:1064]()
    #[cfg(test)]
    mod tests {
    use super::*;
    [4.1021]
    [4.1064]
    impl Commands for Item {
    fn reset_markers(&mut self) {
    if let Some(x) = &mut self.det {
    x.reset_markers();
    }
    }
    }
  • replacement in crates/zhed-packlist/src/lib.rs at line 76
    [4.1065][4.1065:1138](),[4.1138][4.5492:6411](),[4.6411][4.1704:1719](),[4.1704][4.1704:1719](),[4.1719][4.6412:7229](),[4.7229][4.1953:2171](),[4.1953][4.1953:2171](),[4.2171][4.7230:8957](),[4.8957][4.2739:2754](),[4.2739][4.2739:2754](),[4.2754][4.8958:8969](),[4.8969][4.2988:3232](),[4.2988][4.2988:3232]()
    #[test]
    fn ex0rs() {
    let mut sections = BTreeMap::new();
    sections.insert(
    String::new(),
    Section {
    summary: ItemData::default(),
    items: vec![
    (
    ItemData {
    premarkers: vec![' '],
    multiplier: 1,
    },
    "15 Ruß".to_string(),
    ),
    (
    ItemData {
    premarkers: vec![' '],
    multiplier: 132,
    },
    "Wattestäbe".to_string(),
    ),
    (
    ItemData {
    premarkers: vec!['#'],
    multiplier: 0,
    },
    "Handtuch".to_string(),
    ),
    ],
    },
    );
    sections.insert(
    "Wachsbaum ...".to_string(),
    Section {
    summary: ItemData {
    premarkers: vec!['-'],
    multiplier: 5000,
    },
    items: vec![
    (
    ItemData {
    premarkers: vec![' '],
    multiplier: 1,
    },
    "Ranke".to_string(),
    ),
    (
    ItemData {
    premarkers: vec!['*'],
    multiplier: 1,
    },
    "5 x Metrik + BNaumbnd".to_string(),
    ),
    ],
    },
    );
    let mut res = PackList {
    name: "Packliste Ölland".to_string(),
    range: "80 Tage, 50 Nächtsle".to_string(),
    sections,
    };
    let mut sections2 = BTreeMap::new();
    sections2.insert(
    String::new(),
    Section {
    summary: ItemData::default(),
    items: vec![
    (
    ItemData {
    premarkers: vec![' '],
    multiplier: 1,
    },
    "15 Ruß".to_string(),
    ),
    (
    ItemData {
    premarkers: vec![' '],
    multiplier: 132,
    },
    "Wattestäbe".to_string(),
    ),
    (
    ItemData {
    premarkers: vec![' '],
    multiplier: 0,
    },
    "Handtuch".to_string(),
    ),
    ],
    },
    );
    sections2.insert(
    "Wachsbaum ...".to_string(),
    Section {
    summary: ItemData {
    premarkers: vec![' '],
    multiplier: 5000,
    },
    items: vec![
    (
    ItemData {
    premarkers: vec![' '],
    multiplier: 1,
    },
    "Ranke".to_string(),
    ),
    (
    ItemData {
    premarkers: vec![' '],
    multiplier: 1,
    },
    "5 x Metrik + BNaumbnd".to_string(),
    ),
    ],
    },
    );
    let res2 = PackList {
    name: "Packliste Ölland".to_string(),
    range: "80 Tage, 50 Nächtsle".to_string(),
    sections: sections2,
    };
    res.reset_premarkers();
    assert_eq!(res, res2);
    [4.1065]
    [4.3232]
    impl Commands for ItemDetails {
    fn reset_markers(&mut self) {
    self.markers.iter_mut().for_each(|i| i.val = [' ', ' ']);
  • edit in crates/zhed-packlist/src/bin/zhed-packlist-reset.rs at line 2
    [3.83]
    [3.83]
    use zhed_packlist::prelude::*;
  • replacement in crates/zhed-packlist/src/bin/zhed-packlist-reset.rs at line 8
    [3.178][3.178:277]()
    std::io::stdin().lock().read_to_string(&mut inp).expect("unable to read packlist from stdin");
    [3.178]
    [3.277]
    std::io::stdin()
    .lock()
    .read_to_string(&mut inp)
    .expect("unable to read packlist from stdin");
  • replacement in crates/zhed-packlist/src/bin/zhed-packlist-reset.rs at line 13
    [3.367][3.367:394]()
    pl.reset_premarkers();
    [3.367]
    [3.394]
    pl.reset_markers();
  • replacement in crates/zhed-packlist/Cargo.toml at line 7
    [4.3361][4.8970:8988]()
    thiserror = "1.0"
    [4.3361]
    [2.404]
    [dependencies.thiserror]
    version = "1.0"
    optional = true
  • edit in crates/zhed-packlist/Cargo.toml at line 14
    [2.441]
    [features]
    std = [ "thiserror" ]