pipa-lang 1.0.0-alpha.1

A tiny template language
Documentation
// SPDX-FileCopyrightText: Copyright 2026 olav@occy.org
// SPDX-License-Identifier: MPL-2.0

use crate::value::Value;
use crate::value::bytes::Bytes;
use crate::value::list::List;
use crate::value::map::Map;

pub(crate) trait Equivalent {
    fn equivalent(&self, other: &Self) -> bool;
}

impl<T: Equivalent> Equivalent for Option<T> {
    fn equivalent(&self, other: &Self) -> bool {
        match (self, other) {
            (Some(a), Some(b)) => a.equivalent(b),
            (None, None) => true,
            _ => false,
        }
    }
}

impl<T: PartialEq, U: Equivalent> Equivalent for (T, U) {
    fn equivalent(&self, other: &Self) -> bool {
        self.0 == other.0 && self.1.equivalent(&other.1)
    }
}

impl Equivalent for Value {
    fn equivalent(&self, other: &Self) -> bool {
        match (self, other) {
            (Value::Bytes(a), Value::Bytes(b)) => a.equivalent(b),
            (Value::List(a), Value::List(b)) => a.equivalent(b),
            (Value::Map(a), Value::Map(b)) => a.equivalent(b),
            _ => false,
        }
    }
}

impl Equivalent for Bytes {
    fn equivalent(&self, other: &Self) -> bool {
        self.data == other.data
    }
}

impl Equivalent for List {
    fn equivalent(&self, other: &Self) -> bool {
        self.data.len() == other.data.len()
            && self
                .data
                .iter()
                .enumerate()
                .all(|(i, d)| other.get(i).is_some_and(|o| d.equivalent(o)))
    }
}

impl Equivalent for Map {
    fn equivalent(&self, other: &Self) -> bool {
        self.data.len() == other.data.len()
            && self
                .data
                .iter()
                .all(|(k, v)| other.get(k).is_some_and(|o| v.equivalent(o)))
    }
}