adnv 1.5.1

CLI that tracks, checks and auto-updates infrastructure dependency versions across Terraform, Helm, Docker, Git and npm
Documentation
use std::{cmp, fmt, ops};

use crate::parsers::hcl::{
    Pair, Rule,
    ast::{Str, expr::Expression},
};

#[derive(Clone)]
pub struct Object<'i>(Vec<(ObjectKey<'i>, Expression<'i>)>);

impl<'i> Object<'i> {
    pub fn get_by_name(&self, name: &str) -> Option<&Expression<'i>> {
        self.iter()
            .find_map(|(key, value)| if key == name { Some(value) } else { None })
    }
}

impl<'i> Object<'i> {
    pub(super) fn process(pair: Pair<'i>) -> Self {
        let mut items = pair.into_inner();

        let mut data = Vec::with_capacity(items.size_hint().0 / 2);

        while let Some(key) = items.next() {
            let key = ObjectKey::process(key);

            let value = items.next().unwrap();
            let value = Expression::process(value);

            data.push((key, value));
        }

        Self(data)
    }
}

impl<'i> ops::Deref for Object<'i> {
    type Target = [(ObjectKey<'i>, Expression<'i>)];

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl fmt::Debug for Object<'_> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_map()
            .entries(self.0.iter().map(|(key, val)| (key, val)))
            .finish()
    }
}

#[derive(Debug, Clone)]
pub enum ObjectKey<'i> {
    Ident(Str<'i>),
    Expr(Expression<'i>),
}

impl<'i> ObjectKey<'i> {
    pub fn as_ident(&self) -> Option<Str<'i>> {
        if let Self::Ident(s) = self {
            Some(*s)
        } else {
            None
        }
    }

    pub fn as_expr(&self) -> Option<&Expression<'i>> {
        if let Self::Expr(v) = self {
            Some(v)
        } else {
            None
        }
    }
}

impl<'i> ObjectKey<'i> {
    fn process(pair: Pair<'i>) -> Self {
        match pair.as_rule() {
            Rule::Identifier => ObjectKey::Ident(Str::from(pair)),
            Rule::Expression => ObjectKey::Expr(Expression::process(pair)),
            rule => unreachable!("{rule:?}"),
        }
    }
}

impl cmp::PartialEq<str> for ObjectKey<'_> {
    fn eq(&self, other: &str) -> bool {
        self.as_ident().is_some_and(|id| id == other)
    }
}