Skip to content

Commit

Permalink
#17 alerts and ctors
Browse files Browse the repository at this point in the history
  • Loading branch information
yegor256 committed Oct 14, 2022
1 parent 6e86d8f commit d38904a
Show file tree
Hide file tree
Showing 5 changed files with 155 additions and 84 deletions.
1 change: 1 addition & 0 deletions .rultor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ release:
script: |-
[[ "${tag}" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]] || exit -1
sed -i -e "s/^version = \"0.0.0\"/version = \"${tag}\"/" Cargo.toml
sed -i -e "s/0.0.0/${tag}/" src/lib.rs
cargo --color=never test -vv
cargo --color=never fmt --check
cargo clippy
Expand Down
73 changes: 73 additions & 0 deletions src/alerts.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
// Copyright (c) 2022 Yegor Bugayenko
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

use crate::{Alert, Sodg};

impl Sodg {
/// Attach a new alert to this SODG.
pub fn alert_on(&mut self, a: Alert) {
self.alerts.push(a);
}

/// Disable all alerts.
pub fn alerts_off(&mut self) {
self.alerts_active = false;
}

/// Enable all alerts.
pub fn alerts_on(&mut self) {
self.alerts_active = true;
}
}

#[cfg(test)]
use anyhow::Result;

#[test]
fn panic_on_simple_alert() -> Result<()> {
let mut g = Sodg::empty();
g.alert_on(|_, _| vec![format!("{}", "oops")]);
assert!(g.add(0).is_err());
Ok(())
}

#[test]
fn dont_panic_when_alerts_disabled() -> Result<()> {
let mut g = Sodg::empty();
g.alert_on(|_, _| vec!["should never happen".to_string()]);
g.alerts_off();
assert!(!g.add(0).is_err());
Ok(())
}

#[test]
fn panic_on_complex_alert() -> Result<()> {
let mut g = Sodg::empty();
g.alert_on(|_, vx| {
let v = 42;
if vx.contains(&v) {
vec![format!("Vertex no.{v} is not allowed")]
} else {
vec![]
}
});
assert!(g.add(42).is_err());
Ok(())
}
57 changes: 57 additions & 0 deletions src/ctors.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// Copyright (c) 2022 Yegor Bugayenko
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

use crate::Sodg;
use std::collections::HashMap;

impl Sodg {
/// Makes an empty Sodg, with no vertices and no edges.
pub fn empty() -> Self {
let mut g = Sodg {
vertices: HashMap::new(),
next_v: 0,
alerts: vec![],
alerts_active: true,
};
g.alert_on(|g, vx| {
let mut errors = Vec::new();
for v in vx.iter() {
for e in g.vertices.get(v).unwrap().edges.iter() {
if !g.vertices.contains_key(&e.to) {
errors.push(format!("Edge ν{}.{} arrives to lost ν{}", v, e.a, e.to));
}
}
}
errors
});
g
}
}

#[cfg(test)]
use anyhow::Result;

#[test]
fn makes_an_empty_sodg() -> Result<()> {
let mut g = Sodg::empty();
g.add(0)?;
assert_eq!(1, g.vertices.len());
Ok(())
}
76 changes: 24 additions & 52 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,22 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

//! This is a memory structure with vertices and edges between them,
//! which we call Surging Object DiGraph (SODG), because it expects
//! modifications comping from a user (through [`Sodg::add`],
//! [`Sodg::bind`], and [`Sodg::put`]) and then decides itself when
//! it's time to delete some vertices (something similar to
//! "garbage collection"). For example, here is how you create a simple
//! graph:
//!
//! ```
//! ```

#![doc(html_root_url = "https://docs.rs/sodg/0.0.0")]
#![deny(warnings)]

mod alerts;
mod ctors;
mod debug;
mod edge;
mod hex;
Expand All @@ -36,10 +50,13 @@ mod xml;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;

/// Instances of this type can be used in `Sodg::alert_on` method,
/// in order to ensure runtime consistency of data inside the graph.
pub type Alert = fn(g: &Sodg, vx: Vec<u32>) -> Vec<String>;

/// This struct represents a Simple Object DiGraph (SODG). You add vertices
/// to it, bind them one to one with edges
/// This struct represents a Surging Object DiGraph (SODG). You add vertices
/// to it, bind them one to one with edges, put data into some of them,
/// and read data back:
///
/// ```
/// use sodg::Sodg;
Expand All @@ -51,6 +68,9 @@ pub type Alert = fn(g: &Sodg, vx: Vec<u32>) -> Vec<String>;
/// sodg.bind(1, 2, "b").unwrap();
/// assert_eq!(2, sodg.find(0, "a.b").unwrap());
/// ```
///
/// This package is used in [reo](https://github.com/objectionary/reo)
/// project, as a memory model for objects and dependencies between them.
#[derive(Serialize, Deserialize)]
pub struct Sodg {
vertices: HashMap<u32, Vertex>,
Expand All @@ -62,6 +82,8 @@ pub struct Sodg {
alerts_active: bool,
}

/// It is an object-oriented representation of binary data
/// in hexadecimal format, which can be put into vertices of the graph.
#[derive(Serialize, Deserialize)]
pub struct Hex {
bytes: Vec<u8>,
Expand All @@ -85,45 +107,6 @@ pub struct Script {
root: u32,
}

impl Sodg {
/// Makes an empty Sodg, with no vertices and no edges.
pub fn empty() -> Self {
let mut g = Sodg {
vertices: HashMap::new(),
next_v: 0,
alerts: vec![],
alerts_active: true,
};
g.alert_on(|g, vx| {
let mut errors = Vec::new();
for v in vx.iter() {
for e in g.vertices.get(v).unwrap().edges.iter() {
if !g.vertices.contains_key(&e.to) {
errors.push(format!("Edge ν{}.{} arrives to lost ν{}", v, e.a, e.to));
}
}
}
errors
});
g
}

/// Attach a new alert to this SODG.
pub fn alert_on(&mut self, a: Alert) {
self.alerts.push(a);
}

/// Disable all alerts.
pub fn alerts_off(&mut self) {
self.alerts_active = false;
}

/// Enable all alerts.
pub fn alerts_on(&mut self) {
self.alerts_active = true;
}
}

#[cfg(test)]
use simple_logger::SimpleLogger;

Expand All @@ -139,14 +122,3 @@ fn init() {
.init()
.unwrap();
}

#[cfg(test)]
use anyhow::Result;

#[test]
fn makes_an_empty_sodg() -> Result<()> {
let mut g = Sodg::empty();
g.add(0)?;
assert_eq!(1, g.vertices.len());
Ok(())
}
32 changes: 0 additions & 32 deletions src/ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -322,35 +322,3 @@ fn finds_all_kids() -> Result<()> {
assert_eq!(2, g.kids(0)?.iter().count());
Ok(())
}

#[test]
fn panic_on_simple_alert() -> Result<()> {
let mut g = Sodg::empty();
g.alert_on(|_, _| vec![format!("{}", "oops")]);
assert!(g.add(0).is_err());
Ok(())
}

#[test]
fn dont_panic_when_alerts_disabled() -> Result<()> {
let mut g = Sodg::empty();
g.alert_on(|_, _| vec!["should never happen".to_string()]);
g.alerts_off();
assert!(!g.add(0).is_err());
Ok(())
}

#[test]
fn panic_on_complex_alert() -> Result<()> {
let mut g = Sodg::empty();
g.alert_on(|_, vx| {
let v = 42;
if vx.contains(&v) {
vec![format!("Vertex no.{v} is not allowed")]
} else {
vec![]
}
});
assert!(g.add(42).is_err());
Ok(())
}

0 comments on commit d38904a

Please sign in to comment.