netlist_db/parser/
data_meas.rs

1use std::{collections::HashMap, path::PathBuf};
2
3use super::{
4    BEGIN_TITLE,
5    utils::{name_str, space, space_newline},
6};
7use crate::{err::ParseError, span::LocatedSpan};
8use nom::{
9    IResult, Parser,
10    branch::alt,
11    bytes::complete::{tag, take_until},
12    character::complete::char,
13    combinator::{map, opt},
14    multi::{many1, separated_list1},
15    sequence::delimited,
16};
17use tokio::fs::read_to_string;
18
19const FAILED_MEAS: &str = "failed";
20
21#[inline]
22fn float(i: LocatedSpan) -> IResult<LocatedSpan, Option<f64>> {
23    alt((
24        map(super::utils::float, Some),
25        map(tag(FAILED_MEAS), |_| None),
26    ))
27    .parse_complete(i)
28}
29
30#[inline]
31fn data_meas_csv_nom<'a>(
32    i: LocatedSpan<'a>,
33    data_prefix: Option<&str>,
34) -> IResult<LocatedSpan<'a>, HashMap<String, Vec<Option<f64>>>> {
35    map(
36        (
37            take_until(BEGIN_TITLE),
38            take_until("\n"),
39            space_newline,
40            separated_list1((space, char(','), space), map(name_str, |(s, _)| s)),
41            opt(char('#')),
42            opt((space, char(','))),
43            many1(delimited(
44                space_newline,
45                separated_list1((space, char(','), space), float),
46                opt((space, char(','))),
47            )),
48        ),
49        |(_, _, _, names, _, _, value_table): (_, _, _, Vec<&str>, _, _, Vec<Vec<Option<f64>>>)| {
50            names
51                .into_iter()
52                .enumerate()
53                .filter_map(|(name_idx, name)| {
54                    if let Some(prefix) = data_prefix {
55                        if !name.starts_with(prefix) {
56                            return None;
57                        }
58                    }
59                    Some((
60                        name.to_owned(),
61                        value_table.iter().map(|values| values[name_idx]).collect(),
62                    ))
63                })
64                .collect()
65        },
66    )
67    .parse_complete(i)
68}
69
70#[inline]
71pub async fn data_meas_csv(
72    path: PathBuf,
73    data_prefix: Option<&str>,
74) -> Result<HashMap<String, Vec<Option<f64>>>, ()> {
75    match read_to_string(&path).await {
76        Ok(s) => {
77            let (_, out) = data_meas_csv_nom(s.as_str().into(), data_prefix).map_err(|e| {
78                let err: ParseError = e.into();
79                err.report(&mut true, &crate::FileId::Include { path }, &s);
80            })?;
81            Ok(out)
82        }
83        Err(e) => {
84            let err: ParseError = e.into();
85            err.report(&mut true, &crate::FileId::Include { path }, "");
86            Err(())
87        }
88    }
89}
90
91#[tokio::test]
92async fn sim_mt0_csv() {
93    crate::utlis::test::init_logger();
94    const DATA: &str = include_str!("../../tests/sim.mt0.csv");
95    _ = dbg!(data_meas_csv_nom(DATA.into(), None));
96    _ = dbg!(
97        data_meas_csv("tests/sim.mt0.csv".into(), Some("kcell"))
98            .await
99            .unwrap()
100    );
101}