summary refs log blame commit diff stats
path: root/tests/common/mod.rs
blob: d0b9e89dd75c1bf100d2cac7e60d6db1686f0f51 (plain) (tree)

























                                                                              
                                                






                              
                                            
































                                                 
                      





                                         
                      





                                       
                      





                                         
                      









































































                                                                                         
                                                        












                                                                                    









                                                    
 
/*
 * This file is part of Datafu
 * Copyright (C) 2021  Soni L.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */

use std::borrow::Borrow;
use std::borrow::Cow;
use std::collections::BTreeMap;

use datafu::RefOwn;
use datafu::PatternTypes;
use datafu::KVPair;

#[derive(PartialEq, Eq, PartialOrd, Ord, Debug)]
pub enum Value {
    U(usize),
    B(bool),
    M(BTreeMap<Value, Value>),
    S(Cow<'static, str>),
}

#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub enum Dummy {
}

trait ValueHelper {
    fn as_value(&self) -> Result<&Value, &str>;
}

impl ValueHelper for Value {
    fn as_value(&self) -> Result<&Value, &str> {
        Ok(self)
    }
}

impl ValueHelper for &str {
    fn as_value(&self) -> Result<&Value, &str> {
        Err(self)
    }
}

impl PartialEq<str> for Value {
    fn eq(&self, other: &str) -> bool {
        matches!(self, Value::S(l) if l == other)
    }
}

impl PartialEq<Value> for str {
    fn eq(&self, other: &Value) -> bool {
        matches!(other, Value::S(r) if self == r)
    }
}

impl PartialEq<Dummy> for Value {
    fn eq(&self, other: &Dummy) -> bool {
        let _ = other;
        unreachable!()
    }
}

impl PartialEq<Value> for Dummy {
    fn eq(&self, other: &Value) -> bool {
        let _ = other;
        unreachable!()
    }
}

impl PartialEq<str> for Dummy {
    fn eq(&self, other: &str) -> bool {
        let _ = other;
        unreachable!()
    }
}

impl PartialEq<Dummy> for str {
    fn eq(&self, other: &Dummy) -> bool {
        let _ = other;
        unreachable!()
    }
}

impl<'a> PartialEq for dyn ValueHelper + 'a {
    fn eq(&self, other: &(dyn ValueHelper + 'a)) -> bool {
        match (self.as_value(), other.as_value()) {
            (a, b) if a == b => true,
            (Ok(Value::S(a)), Err(b)) | (Err(b), Ok(Value::S(a))) => {
                a.eq(b)
            },
            _ => false,
        }
    }
}

impl<'a> PartialOrd for dyn ValueHelper + 'a {
    fn partial_cmp(&self, other: &(dyn ValueHelper + 'a)) -> Option<std::cmp::Ordering> {
        Some(self.cmp(other))
    }
}

impl<'a> Eq for dyn ValueHelper + 'a {
}

impl<'a> Ord for dyn ValueHelper + 'a {
    fn cmp(&self, other: &(dyn ValueHelper + 'a)) -> std::cmp::Ordering {
        match (self.as_value(), other.as_value()) {
            (Ok(a), Ok(b)) => a.cmp(b),
            (Err(a), Err(b)) => a.cmp(b),
            (Ok(Value::S(a)), Err(b)) => (**a).cmp(b),
            (Err(a), Ok(Value::S(b))) => a.cmp(b.borrow()),
            (Ok(_), Err(_)) => std::cmp::Ordering::Less,
            (Err(_), Ok(_)) => std::cmp::Ordering::Greater,
        }
    }
}

impl From<&'static str> for Value {
    fn from(x: &'static str) -> Value {
        Value::S(x.into())
    }
}


impl<'a> Borrow<dyn ValueHelper + 'a> for Value {
    fn borrow(&self) -> &(dyn ValueHelper + 'a) {
        self
    }
}

impl PatternTypes for Value {
    type Ref = Self;
    type Own = Dummy;

    fn pairs<'b>(
        item: RefOwn<'b, Self, Dummy>
    ) -> Option<Box<dyn Iterator<Item=KVPair<'b, Self>> + 'b>> {
        match item {
            RefOwn::Ref(Value::M(map)) => {
                Some(Box::new(map.iter().map(|(a, b)| (a.into(), b.into()))))
            },
            _ => None
        }
    }

    fn get<'a, 'b>(
        item: RefOwn<'b, Self, Dummy>,
        key: RefOwn<'a, Self, Dummy>
    ) -> Option<Option<KVPair<'b, Self>>> {
        match item {
            RefOwn::Ref(Value::M(map)) => {
                Some(match key {
                    RefOwn::Ref(key) => map.get_key_value(key),
                    RefOwn::Own(_key) => unreachable!(),
                    RefOwn::Str(key) => map.get_key_value(&key as &dyn ValueHelper),
                }.map(|(k,v)| (k.into(), v.into())))
            },
            _ => None
        }
    }

    fn matches(
        left: RefOwn<'_, Self, Dummy>,
        right: RefOwn<'_, Self, Dummy>
    ) -> bool {
        left == right
    }

    fn as_str<'b>(
        item: RefOwn<'b, Self, Dummy>
    ) -> Option<&'b str> {
        match item {
            RefOwn::Str(key) => Some(key),
            RefOwn::Ref(Value::S(key)) => Some(key),
            _ => None,
        }
    }
}