hocon-rs 0.2.0

Rust implementation of HOCON
Documentation
use std::{
    cell::RefCell,
    fmt::Display,
    ops::{Deref, DerefMut},
};

use tracing::trace;

use crate::{
    join_format,
    merge::{path::RefPath, value::Value},
};

#[derive(Debug, Clone, PartialEq)]
pub(crate) enum Array {
    Merged(Vec<RefCell<Value>>),
    Unmerged(Vec<RefCell<Value>>),
}

impl Array {
    pub(crate) fn new(values: Vec<RefCell<Value>>) -> Self {
        Array::Unmerged(values)
    }

    pub(crate) fn is_merged(&self) -> bool {
        matches!(self, Array::Merged(_))
    }

    pub(crate) fn from_raw(
        parent: Option<&RefPath>,
        raw: crate::raw::raw_array::RawArray,
    ) -> crate::Result<Self> {
        let mut values = Vec::with_capacity(raw.len());
        for val in raw.into_inner() {
            let val = Value::from_raw(parent, val)?;
            values.push(RefCell::new(val));
        }
        Ok(Self::new(values))
    }

    pub(crate) fn as_merged(&mut self) {
        let array = std::mem::take(self.deref_mut());
        *self = Self::Merged(array);
    }

    pub(crate) fn as_unmerged(&mut self) {
        let array = std::mem::take(self.deref_mut());
        *self = Self::Unmerged(array);
    }

    pub(crate) fn try_become_merged(&mut self) -> bool {
        if self.is_merged() {
            return true;
        }
        let all_merged = self.iter_mut().all(|v| v.get_mut().try_become_merged());
        if all_merged {
            self.as_merged();
            trace!("{} become merged", self);
        }
        all_merged
    }

    pub(crate) fn into_inner(self) -> Vec<RefCell<Value>> {
        match self {
            Array::Merged(array) | Array::Unmerged(array) => array,
        }
    }
}

impl Deref for Array {
    type Target = Vec<RefCell<Value>>;

    fn deref(&self) -> &Self::Target {
        match self {
            Array::Merged(array) | Array::Unmerged(array) => array,
        }
    }
}

impl DerefMut for Array {
    fn deref_mut(&mut self) -> &mut Self::Target {
        match self {
            Array::Merged(array) | Array::Unmerged(array) => array,
        }
    }
}

impl Display for Array {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "[")?;
        join_format(
            self.iter(),
            f,
            |f| write!(f, ", "),
            |f, v| write!(f, "{}", v.borrow()),
        )?;
        write!(f, "]")?;
        Ok(())
    }
}