1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
use crate::proto::gen::tasks::{Variable, VariableNamespace};
use std::cmp::Ordering;
use std::hash::{Hash, Hasher};
impl Variable {
pub fn new(ns: VariableNamespace, name: &str) -> Self {
if name.contains(':') {
panic!("Variable names may not contain colons")
}
Self {
namespace: ns as i32,
name: String::from(name),
}
}
pub fn new_signal(id: &str) -> Self {
Self::new(VariableNamespace::Signal, id)
}
pub fn new_scale(id: &str) -> Self {
Self::new(VariableNamespace::Scale, id)
}
pub fn new_data(id: &str) -> Self {
Self::new(VariableNamespace::Data, id)
}
pub fn ns(&self) -> VariableNamespace {
VariableNamespace::from_i32(self.namespace).unwrap()
}
}
impl Eq for Variable {}
impl PartialOrd for Variable {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl Ord for Variable {
fn cmp(&self, other: &Self) -> Ordering {
if self.namespace == other.namespace {
self.name.cmp(&other.name)
} else {
self.namespace.cmp(&other.namespace)
}
}
}
// The Prost structs derive PartialEq but not Hash, so we need to implement Hash here.
// This is a bad idea in general since PartialEq and Hash must be consistent, but there's
// not a prost option to disable deriving PartialEq, or to derive Hash. This Hash implementation
// is simple enough that the risk of inconsistency is low.
#[allow(clippy::derived_hash_with_manual_eq)]
impl Hash for Variable {
fn hash<H: Hasher>(&self, state: &mut H) {
self.namespace.hash(state);
self.name.hash(state);
}
}
// A variable with scope. In a Vega spec, variables may be defined at the top-level, or they
// may be defined inside nested group marks. The scope is a `Vec<usize>` and it encodes the level
// at which the variable is defined.
// - An empty scope corresponds to a variable defined at the top level of the specification.
// - Each element of the scope vector represents a level of nesting, where the integer is the
// index into the collection of group marks.
//
// A scope of `vec![0, 1]` means that the variable is defined in a group mark that is nested two
// levels deep. At the top level, the first group mark is chosen. At the second level,
// the second group mark is chosen.
// #[derive(Clone, Debug, PartialOrd, PartialEq, Eq, Hash, Ord)]
// pub struct ScopedVariable {
// pub variable: Variable,
// pub scope: Vec<usize>,
// }
//
// impl ScopedVariable {
// pub fn new(ns: VariableNamespace, name: &str, scope: Vec<usize>) -> Self {
// Self {
// variable: Variable::new(ns, name),
// scope,
// }
// }
//
// pub fn new_signal(id: &str, scope: Vec<usize>) -> Self {
// Self::new(VariableNamespace::Signal, id, scope)
// }
//
// pub fn new_scale(id: &str, scope: Vec<usize>) -> Self {
// Self::new(VariableNamespace::Scale, id, scope)
// }
//
// pub fn new_data(id: &str, scope: Vec<usize>) -> Self {
// Self::new(VariableNamespace::Data, id, scope)
// }
// }