fn parse()

in resctl-demo/src/doc/markup_rd.rs [228:385]


    fn parse(input: &str) -> Result<(RdCmd, Option<String>)> {
        let mut args: Vec<&str> = input.split_whitespace().collect();

        let mut cond = None;
        if args.len() >= 2 {
            let arg = args.last().unwrap();
            if arg.starts_with("%") && arg.ends_with("%") {
                cond = Some(arg[1..arg.len() - 1].to_string());
                args.pop();
            }
        }

        let cmd = match args[0] {
            "id" => {
                if args.len() != 2 {
                    bail!("invalid number of arguments");
                }
                RdCmd::Id(args[1].into())
            }
            "on" | "off" | "toggle" => {
                if args.len() < 2 {
                    bail!("too few arguments");
                }
                let sw = match args[1] {
                    "bench-hashd" => RdSwitch::BenchHashd,
                    "bench-hashd-loop" => RdSwitch::BenchHashdLoop,
                    "bench-iocost" => RdSwitch::BenchIoCost,
                    "bench-needed" => RdSwitch::BenchNeeded,
                    "hashd" | "hashd-A" => RdSwitch::HashdA,
                    "hashd-B" => RdSwitch::HashdB,
                    "sideload" | "sysload" => {
                        if (args[0] == "off" && args.len() != 3)
                            || (args[0] != "off" && args.len() != 4)
                        {
                            bail!("incorrect number of arguments");
                        }
                        let (tag, id) = match args[0] {
                            "off" => (args[2].to_string(), "".into()),
                            _ => (args[2].to_string(), args[3].to_string()),
                        };
                        if args[1] == "sideload" {
                            RdSwitch::Sideload(tag, id)
                        } else {
                            RdSwitch::Sysload(tag, id)
                        }
                    }
                    "cpu-resctl" => RdSwitch::CpuResCtl,
                    "mem-resctl" => RdSwitch::MemResCtl,
                    "io-resctl" => RdSwitch::IoResCtl,
                    "oomd" => RdSwitch::Oomd,
                    "oomd-work-mem-pressure" => RdSwitch::OomdWorkMemPressure,
                    "oomd-work-senpai" => RdSwitch::OomdWorkSenpai,
                    "oomd-sys-mem-pressure" => RdSwitch::OomdSysMemPressure,
                    "oomd-sys-senpai" => RdSwitch::OomdSysSenpai,
                    _ => bail!("invalid switch target"),
                };
                match &sw {
                    RdSwitch::Sideload(_, _) | RdSwitch::Sysload(_, _) => {}
                    _ if args.len() != 2 => bail!("too many arguments"),
                    _ => {}
                }
                match args[0] {
                    "on" => RdCmd::On(sw),
                    "off" => RdCmd::Off(sw),
                    "toggle" => RdCmd::Toggle(sw),
                    _ => bail!("???"),
                }
            }
            "knob" => {
                let val = match args.len() {
                    2 => -1.0,
                    3 => match args[2].parse() {
                        Ok(v) if v >= 0.0 && v <= 1.0 => v,
                        Ok(v) => bail!("{} is out of range [0.0, 1.0]", v),
                        Err(e) => bail!("failed to parse knob value ({:?})", &e),
                    },
                    _ => bail!("invalid number of arguments"),
                };
                let knob = match args[1] {
                    "hashd-load" | "hashd-A-load" => RdKnob::HashdALoad,
                    "hashd-lat-target-pct" | "hashd-A-lat-target-pct" => RdKnob::HashdALatTargetPct,
                    "hashd-lat-target" | "hashd-A-lat-target" => RdKnob::HashdALatTarget,
                    "hashd-mem" | "hashd-A-mem" => RdKnob::HashdAMem,
                    "hashd-file-addr-stdev" | "hashd-A-file-addr-stdev" => {
                        RdKnob::HashdAFileAddrStdev
                    }
                    "hashd-anon-addr-stdev" | "hashd-A-anon-addr-stdev" => {
                        RdKnob::HashdAAnonAddrStdev
                    }
                    "hashd-file" | "hashd-A-file" => RdKnob::HashdAFile,
                    "hashd-file-max" | "hashd-A-file-max" => RdKnob::HashdAFileMax,
                    "hashd-log-bps" | "hashd-A-write" => RdKnob::HashdALogBps,
                    "hashd-weight" | "hashd-A-weight" => RdKnob::HashdAWeight,
                    "hashd-B-load" => RdKnob::HashdBLoad,
                    "hashd-B-lat-target-pct" => RdKnob::HashdBLatTargetPct,
                    "hashd-B-lat-target" => RdKnob::HashdBLatTarget,
                    "hashd-B-mem" => RdKnob::HashdBMem,
                    "hashd-B-file-addr-stdev" => RdKnob::HashdBFileAddrStdev,
                    "hashd-B-anon-addr-stdev" => RdKnob::HashdBAnonAddrStdev,
                    "hashd-B-file" => RdKnob::HashdBFile,
                    "hashd-B-file-max" => RdKnob::HashdBFileMax,
                    "hashd-B-log-bps" => RdKnob::HashdBLogBps,
                    "hashd-B-weight" => RdKnob::HashdBWeight,
                    "sys-cpu-ratio" => RdKnob::SysCpuRatio,
                    "sys-io-ratio" => RdKnob::SysIoRatio,
                    "mem-margin" => RdKnob::MemMargin,
                    "balloon" => RdKnob::Balloon,
                    "cpu-headroom" => RdKnob::CpuHeadroom,
                    _ => bail!("invalid knob target"),
                };
                RdCmd::Knob(knob, val)
            }
            "graph" => match args.len() {
                1 => RdCmd::Graph("".into()),
                2 => RdCmd::Graph(args[1].into()),
                _ => bail!("invalid number of arguments"),
            },
            "reset" => {
                if args.len() != 2 {
                    bail!("invalid number of arguments");
                }
                let reset = match args[1] {
                    "benches" => RdReset::Benches,
                    "hashds" => RdReset::Hashds,
                    "hashd-params" => RdReset::HashdParams,
                    "sideloads" => RdReset::Sideloads,
                    "sysloads" => RdReset::Sysloads,
                    "resctl" => RdReset::ResCtl,
                    "resctl-params" => RdReset::ResCtlParams,
                    "oomd" => RdReset::Oomd,
                    "graph" => RdReset::Graph,
                    "secondaries" => RdReset::Secondaries,
                    "all-workloads" => RdReset::AllWorkloads,
                    "protections" => RdReset::Protections,
                    "all" => RdReset::All,
                    "params" => RdReset::Params,
                    "all-with-params" => RdReset::AllWithParams,
                    "prep" => RdReset::Prep,
                    _ => bail!("invalid reset target"),
                };
                RdCmd::Reset(reset)
            }
            "jump" => {
                if args.len() != 2 {
                    bail!("invalid number of arguments");
                }
                RdCmd::Jump(args[1].into())
            }
            "(" | ")" => {
                if args.len() != 1 {
                    bail!("invalid number of arguments");
                }
                RdCmd::Group(Vec::new())
            }
            _ => bail!("invalid command"),
        };
        Ok((cmd, cond))
    }