/*
* 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 .
*/
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),
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 for Value {
fn eq(&self, other: &str) -> bool {
matches!(self, Value::S(l) if l == other)
}
}
impl PartialEq for str {
fn eq(&self, other: &Value) -> bool {
matches!(other, Value::S(r) if self == r)
}
}
impl PartialEq for Value {
fn eq(&self, other: &Dummy) -> bool {
let _ = other;
unreachable!()
}
}
impl PartialEq for Dummy {
fn eq(&self, other: &Value) -> bool {
let _ = other;
unreachable!()
}
}
impl PartialEq for Dummy {
fn eq(&self, other: &str) -> bool {
let _ = other;
unreachable!()
}
}
impl PartialEq 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 {
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 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> + '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