l3_fn_config 0.0.2-alpha.1

Parsing l3.toml config files
Documentation
use crate::{
    configs::LambdaRuntimeConfig, configs::NodeLambdaConfig, configs::PythonLambdaConfig,
    ConfigParseError, NodeVersion, OptionallyParsable, PythonVersion,
};

impl OptionallyParsable<&toml::Table> for LambdaRuntimeConfig {
    fn has_value(l3_t: &&toml::Table) -> bool {
        l3_t.contains_key("node_opts")
            || l3_t.contains_key("node_version")
            || l3_t.contains_key("python_opts")
            || l3_t.contains_key("python_version")
    }

    fn parse(t: &toml::Table) -> Result<Self, ConfigParseError> {
        Ok(Self {
            node: parse_node_config(t)?,
            python: parse_python_config(t)?,
        })
    }
}

fn parse_node_config(t: &toml::Table) -> Result<Option<NodeLambdaConfig>, ConfigParseError> {
    let version = parse_node_version(t.get("node_version"))?;
    match t.get("node_opts") {
        Some(toml::Value::Table(node_opts_t)) => Ok(Some(NodeLambdaConfig {
            version: match parse_node_version(node_opts_t.get("version"))? {
                Some(node_opts_version) => {
                    if version
                        .as_ref()
                        .map(|v| v == &node_opts_version)
                        .unwrap_or(true)
                    {
                        Some(node_opts_version)
                    } else {
                        return Err(ConfigParseError::Misconfigured {
                            actual: "node_version and node_opts.version do not match".into(),
                            expected: "use node_version or node_opts.version".into(),
                            field: "node_opts.version".into(),
                        });
                    }
                }
                None => version,
            },
        })),
        None => {
            if version.is_none() {
                Ok(None)
            } else {
                Ok(Some(NodeLambdaConfig { version }))
            }
        }
        _ => panic!(),
    }
}

fn parse_node_version(
    node_version_v: Option<&toml::Value>,
) -> Result<Option<NodeVersion>, ConfigParseError> {
    match node_version_v {
        Some(toml::Value::String(version_s)) => {
            Ok(Some(NodeVersion::try_from(version_s.as_str())?))
        }
        Some(toml::Value::Integer(version_i)) => {
            Ok(Some(NodeVersion::try_from(version_i.to_string().as_str())?))
        }
        None => Ok(None),
        _ => panic!(),
    }
}

fn parse_python_config(t: &toml::Table) -> Result<Option<PythonLambdaConfig>, ConfigParseError> {
    let version = parse_python_version(t.get("python_version"))?;
    match t.get("python_opts") {
        Some(toml::Value::Table(python_opts_t)) => Ok(Some(PythonLambdaConfig {
            version: match parse_python_version(python_opts_t.get("version"))? {
                Some(python_opts_version) => {
                    if version
                        .as_ref()
                        .map(|v| v == &python_opts_version)
                        .unwrap_or(true)
                    {
                        Some(python_opts_version)
                    } else {
                        return Err(ConfigParseError::Misconfigured {
                            actual: "python_version and python_opts.version do not match".into(),
                            expected: "use python_version or python_opts.version".into(),
                            field: "python_opts.version".into(),
                        });
                    }
                }
                None => version,
            },
        })),
        None => {
            if version.is_none() {
                Ok(None)
            } else {
                Ok(Some(PythonLambdaConfig { version }))
            }
        }
        _ => panic!(),
    }
}

fn parse_python_version(
    node_version_v: Option<&toml::Value>,
) -> Result<Option<PythonVersion>, ConfigParseError> {
    match node_version_v {
        Some(toml::Value::String(version_s)) => {
            Ok(Some(PythonVersion::try_from(version_s.as_str())?))
        }
        Some(toml::Value::Float(version_f)) => Ok(Some(PythonVersion::try_from(
            version_f.to_string().as_str(),
        )?)),
        None => Ok(None),
        _ => panic!(),
    }
}