use serde::{Deserialize, Serialize};
use crate::address::ContentAddress;
use crate::codec::{self, CodecError};
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct Definition {
pub kind: String,
pub name: String,
pub edges: Vec<(String, String)>,
pub axioms: Vec<String>,
pub lexical: Option<String>,
}
impl Definition {
pub fn address(&self) -> Result<ContentAddress, CodecError> {
let mut canon = self.clone();
canon.edges.sort();
canon.edges.dedup();
canon.axioms.sort();
canon.axioms.dedup();
codec::address_of(&canon)
}
}
#[cfg(test)]
mod tests {
use super::*;
fn base() -> Definition {
Definition {
kind: "Concept".into(),
name: "Employer".into(),
edges: vec![("Subsumption".into(), "Agent".into())],
axioms: vec!["EmployerIsAgent".into()],
lexical: Some("employer".into()),
}
}
#[test]
fn identical_definitions_share_an_address() {
assert_eq!(base().address().unwrap(), base().address().unwrap());
}
#[test]
fn changing_an_edge_changes_the_address() {
let mut b = base();
b.edges = vec![("Subsumption".into(), "Person".into())]; assert_ne!(base().address().unwrap(), b.address().unwrap());
}
#[test]
fn changing_an_axiom_changes_the_address() {
let mut b = base();
b.axioms = vec!["EmployerHiresEmployee".into()];
assert_ne!(base().address().unwrap(), b.address().unwrap());
}
#[test]
fn changing_the_lexical_changes_the_address() {
let mut b = base();
b.lexical = Some("boss".into());
assert_ne!(base().address().unwrap(), b.address().unwrap());
}
#[test]
fn same_name_different_definition_does_not_collide() {
let mut b = base();
b.edges.push(("Opposition".into(), "Employee".into()));
assert_ne!(base().address().unwrap(), b.address().unwrap());
}
#[test]
fn address_is_order_independent() {
let mut a = base();
a.edges = vec![
("Subsumption".into(), "Agent".into()),
("Opposition".into(), "Employee".into()),
];
a.axioms = vec!["B".into(), "A".into()];
let mut b = base();
b.edges = vec![
("Opposition".into(), "Employee".into()),
("Subsumption".into(), "Agent".into()),
];
b.axioms = vec!["A".into(), "B".into()];
assert_eq!(a.address().unwrap(), b.address().unwrap());
}
}