From c2f6cc2c3707ff2d72d730a3b28fac4d3f388579 Mon Sep 17 00:00:00 2001 From: kapilsinha Date: Wed, 21 Dec 2022 17:11:08 -0800 Subject: [PATCH 1/3] Patch 'dot' feature Add a DEFAULT_LABEL variable to fix compilation error --- src/graph.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/graph.rs b/src/graph.rs index 0b53391..a5c6437 100644 --- a/src/graph.rs +++ b/src/graph.rs @@ -27,6 +27,9 @@ use alloc::vec::Vec; #[cfg(feature = "dot")] use super::SEED; +#[cfg(feature = "dot")] +const DEFAULT_LABEL: &str = ""; + #[derive(Clone, Debug, PartialEq)] /// Graph operation error pub enum GraphErr { From 6e07fd7e61c1d573cd4622ddd02a3fa4e8c9783b Mon Sep 17 00:00:00 2001 From: Kapil Sinha Date: Wed, 21 Dec 2022 18:14:44 -0800 Subject: [PATCH 2/3] Replace 'no_std' feature with 'std' feature Features should be additive. From the Cargo Book (https://doc.rust-lang.org/cargo/reference/features.html): For example, if you want to optionally support no_std environments, do not use a no_std feature. Instead, use a std feature that enables std. --- Cargo.toml | 6 ++---- src/dot.rs | 12 ++++++------ src/edge.rs | 8 ++++---- src/graph.rs | 16 ++++++++-------- src/iterators/bfs.rs | 12 ++++++------ src/iterators/dfs.rs | 12 ++++++------ src/iterators/dijkstra.rs | 10 +++++----- src/iterators/owning_iterator.rs | 14 +++++++------- src/iterators/topo.rs | 6 +++--- src/iterators/values.rs | 4 ++-- src/iterators/vertices.rs | 8 ++++---- src/lib.rs | 2 +- 12 files changed, 54 insertions(+), 56 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 52e12c7..93ab173 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,14 +29,12 @@ name = "benchmark" harness = false [features] -default = [] +default = ["hashbrown/nightly"] # use `cargo bench --features sbench` only if you want benchmarks with 10 million # iterations (may fail on some systems) sbench = [] -# nightly feature for `no_std` -# for build use `cargo +nightly build --features no_std` -no_std = ["hashbrown/nightly"] +std = [] [package.metadata.docs.rs] features = ["dot"] diff --git a/src/dot.rs b/src/dot.rs index c96760a..ec9c939 100644 --- a/src/dot.rs +++ b/src/dot.rs @@ -1,21 +1,21 @@ use crate::{Graph, GraphErr, VertexId}; -#[cfg(feature = "no_std")] +#[cfg(not(feature = "std"))] use core::io::Write; -#[cfg(not(feature = "no_std"))] +#[cfg(feature = "std")] use std::io::Write; -#[cfg(feature = "no_std")] +#[cfg(not(feature = "std"))] use core::borrow::Cow; -#[cfg(not(feature = "no_std"))] +#[cfg(feature = "std")] use std::borrow::Cow; -#[cfg(feature = "no_std")] +#[cfg(not(feature = "std"))] use core::fmt::Debug; -#[cfg(not(feature = "no_std"))] +#[cfg(feature = "std")] use std::fmt::Debug; type Nd = VertexId; diff --git a/src/edge.rs b/src/edge.rs index c1ef7f7..4a8a143 100644 --- a/src/edge.rs +++ b/src/edge.rs @@ -1,14 +1,14 @@ // Copyright 2019 Octavian Oncescu use crate::vertex_id::VertexId; -#[cfg(not(feature = "no_std"))] +#[cfg(feature = "std")] use std::hash::Hash; -#[cfg(not(feature = "no_std"))] +#[cfg(feature = "std")] use std::hash::Hasher; -#[cfg(feature = "no_std")] +#[cfg(not(feature = "std"))] extern crate alloc; -#[cfg(feature = "no_std")] +#[cfg(not(feature = "std"))] use core::hash::{Hash, Hasher}; #[derive(Clone, Debug)] diff --git a/src/graph.rs b/src/graph.rs index a5c6437..478675b 100644 --- a/src/graph.rs +++ b/src/graph.rs @@ -5,23 +5,23 @@ use crate::iterators::*; use crate::vertex_id::VertexId; use hashbrown::{HashMap, HashSet}; -#[cfg(feature = "no_std")] +#[cfg(not(feature = "std"))] use core::iter; -#[cfg(not(feature = "no_std"))] +#[cfg(feature = "std")] use std::iter; -#[cfg(feature = "no_std")] +#[cfg(not(feature = "std"))] use core::fmt::Debug; -#[cfg(not(feature = "no_std"))] +#[cfg(feature = "std")] use std::fmt::Debug; -#[cfg(feature = "no_std")] +#[cfg(not(feature = "std"))] extern crate alloc; -#[cfg(feature = "no_std")] +#[cfg(not(feature = "std"))] use alloc::boxed::Box; -#[cfg(feature = "no_std")] +#[cfg(not(feature = "std"))] use alloc::vec; -#[cfg(feature = "no_std")] +#[cfg(not(feature = "std"))] use alloc::vec::Vec; #[cfg(feature = "dot")] diff --git a/src/iterators/bfs.rs b/src/iterators/bfs.rs index ffba428..c50da31 100644 --- a/src/iterators/bfs.rs +++ b/src/iterators/bfs.rs @@ -4,21 +4,21 @@ use crate::graph::Graph; use crate::vertex_id::VertexId; use hashbrown::HashSet; -#[cfg(not(feature = "no_std"))] +#[cfg(feature = "std")] use std::collections::VecDeque; -#[cfg(feature = "no_std")] +#[cfg(not(feature = "std"))] extern crate alloc; -#[cfg(feature = "no_std")] +#[cfg(not(feature = "std"))] use alloc::collections::vec_deque::VecDeque; -#[cfg(feature = "no_std")] +#[cfg(not(feature = "std"))] use alloc::vec::Vec; -#[cfg(feature = "no_std")] +#[cfg(not(feature = "std"))] use core::fmt::Debug; -#[cfg(not(feature = "no_std"))] +#[cfg(feature = "std")] use std::fmt::Debug; #[derive(Debug)] diff --git a/src/iterators/dfs.rs b/src/iterators/dfs.rs index 1c50d0c..26cd653 100644 --- a/src/iterators/dfs.rs +++ b/src/iterators/dfs.rs @@ -4,21 +4,21 @@ use crate::graph::Graph; use crate::iterators::VertexIter; use crate::vertex_id::VertexId; -#[cfg(feature = "no_std")] +#[cfg(not(feature = "std"))] use core::iter::{Chain, Cloned, Peekable}; use hashbrown::HashSet; -#[cfg(not(feature = "no_std"))] +#[cfg(feature = "std")] use std::iter::{Chain, Cloned, Peekable}; -#[cfg(feature = "no_std")] +#[cfg(not(feature = "std"))] extern crate alloc; -#[cfg(feature = "no_std")] +#[cfg(not(feature = "std"))] use alloc::vec::Vec; -#[cfg(feature = "no_std")] +#[cfg(not(feature = "std"))] use core::fmt::Debug; -#[cfg(not(feature = "no_std"))] +#[cfg(feature = "std")] use std::fmt::Debug; #[derive(Debug)] diff --git a/src/iterators/dijkstra.rs b/src/iterators/dijkstra.rs index cf9166f..d862f7e 100644 --- a/src/iterators/dijkstra.rs +++ b/src/iterators/dijkstra.rs @@ -8,7 +8,7 @@ use crate::vertex_id::VertexId; use hashbrown::HashMap; use hashbrown::HashSet; -#[cfg(not(feature = "no_std"))] +#[cfg(feature = "std")] use std::{ cmp::Ordering, collections::{BinaryHeap, VecDeque}, @@ -17,14 +17,14 @@ use std::{ iter, }; -#[cfg(feature = "no_std")] +#[cfg(not(feature = "std"))] extern crate alloc; -#[cfg(feature = "no_std")] +#[cfg(not(feature = "std"))] use alloc::boxed::Box; -#[cfg(feature = "no_std")] +#[cfg(not(feature = "std"))] use alloc::collections::{binary_heap::BinaryHeap, vec_deque::VecDeque}; -#[cfg(feature = "no_std")] +#[cfg(not(feature = "std"))] use core::{cmp::Ordering, f32, fmt::Debug, iter}; #[derive(PartialEq, Debug)] diff --git a/src/iterators/owning_iterator.rs b/src/iterators/owning_iterator.rs index 0b40b89..710db6b 100644 --- a/src/iterators/owning_iterator.rs +++ b/src/iterators/owning_iterator.rs @@ -2,25 +2,25 @@ use crate::vertex_id::VertexId; -#[cfg(not(feature = "no_std"))] +#[cfg(feature = "std")] use std::fmt::Debug; -#[cfg(not(feature = "no_std"))] +#[cfg(feature = "std")] use std::marker::PhantomData; -#[cfg(feature = "no_std")] +#[cfg(not(feature = "std"))] use core::marker::PhantomData; -#[cfg(feature = "no_std")] +#[cfg(not(feature = "std"))] use core::mem; -#[cfg(not(feature = "no_std"))] +#[cfg(feature = "std")] use std::mem; -#[cfg(not(feature = "no_std"))] +#[cfg(feature = "std")] use std::collections::VecDeque; -#[cfg(feature = "no_std")] +#[cfg(not(feature = "std"))] use alloc::collections::VecDeque; /// Iterator that owns the data. diff --git a/src/iterators/topo.rs b/src/iterators/topo.rs index 442c499..74bbe05 100644 --- a/src/iterators/topo.rs +++ b/src/iterators/topo.rs @@ -5,13 +5,13 @@ use crate::vertex_id::VertexId; use hashbrown::HashMap; -#[cfg(feature = "no_std")] +#[cfg(not(feature = "std"))] use alloc::vec::Vec; -#[cfg(feature = "no_std")] +#[cfg(not(feature = "std"))] use core::fmt::Debug; -#[cfg(not(feature = "no_std"))] +#[cfg(feature = "std")] use std::fmt::Debug; const PANIC_MSG: &str = "graph contains cycle(s)"; diff --git a/src/iterators/values.rs b/src/iterators/values.rs index a2418e1..705ec87 100644 --- a/src/iterators/values.rs +++ b/src/iterators/values.rs @@ -1,8 +1,8 @@ // Copyright 2019 Octavian Oncescu -#[cfg(feature = "no_std")] +#[cfg(not(feature = "std"))] extern crate alloc; -#[cfg(feature = "no_std")] +#[cfg(not(feature = "std"))] use alloc::boxed::Box; /// Generic values Iterator. diff --git a/src/iterators/vertices.rs b/src/iterators/vertices.rs index 6d29617..02cf790 100644 --- a/src/iterators/vertices.rs +++ b/src/iterators/vertices.rs @@ -1,13 +1,13 @@ // Copyright 2019 Octavian Oncescu use crate::vertex_id::VertexId; -#[cfg(feature = "no_std")] +#[cfg(not(feature = "std"))] use core::fmt::Debug; -#[cfg(feature = "no_std")] +#[cfg(not(feature = "std"))] extern crate alloc; -#[cfg(feature = "no_std")] +#[cfg(not(feature = "std"))] use alloc::boxed::Box; -#[cfg(not(feature = "no_std"))] +#[cfg(feature = "std")] use std::fmt::Debug; pub(crate) trait MergedTrait<'a>: Iterator + Debug {} diff --git a/src/lib.rs b/src/lib.rs index b28a70b..3bf5fbf 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -70,6 +70,6 @@ pub(crate) fn gen_bytes() -> [u8; 16] { ))) } -#[cfg(feature = "no_std")] +#[cfg(not(feature = "std"))] #[macro_use] extern crate alloc; From 39f86979233c68ec1cfc4fa89672c2c146654d38 Mon Sep 17 00:00:00 2001 From: Kapil Sinha Date: Sun, 8 Jan 2023 19:13:34 -0800 Subject: [PATCH 3/3] Remove dependency on rand for no_std compatibility --- Cargo.toml | 20 +++++---- README.md | 12 +++--- rust-toolchain.toml | 4 ++ src/dot.rs | 16 +------ src/edge.rs | 2 + src/graph.rs | 32 +++++++------- src/iterators/dijkstra.rs | 10 ++--- src/iterators/owning_iterator.rs | 2 +- src/lib.rs | 72 +++++++------------------------- src/vertex_id.rs | 21 ++++++---- 10 files changed, 75 insertions(+), 116 deletions(-) create mode 100644 rust-toolchain.toml diff --git a/Cargo.toml b/Cargo.toml index 93ab173..23cec2f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,7 @@ name = "graphlib" version = "0.6.3" authors = ["Octavian Oncescu "] -edition = "2018" +edition = "2021" repository = "https://github.com/purpleprotocol/graphlib" keywords = ["graph", "data-structures", "mutable", "graph-algorithm", "no-std"] categories = ["data-structures", "no-std"] @@ -14,22 +14,28 @@ readme = "README.md" travis-ci = { repository = "purpleprotocol/graphlib", branch = "master" } [dependencies] -rand = { version = "0.7.3", default-features = false } -rand_core = { version = "0.5.1", default-features = false } -rand_isaac = { version = "0.2.0", default-features = false } -hex = { version = "0.4.0", default-features = false } +hex = { version = "0.4.3", default-features = false, features = ["alloc"] } hashbrown = { version = "0.6.3", default-features = false, features = ["inline-more", "ahash"] } -dot = { version = "0.1.4", optional = true } +dot = { version = "0.1.4", default-features = false, optional = true } [dev-dependencies] criterion = "0.3.0" +[lib] +name = "graphlib" +path = "src/lib.rs" +crate-type = [ + "lib", +] + [[bench]] name = "benchmark" harness = false [features] -default = ["hashbrown/nightly"] +# std needs to be a default feature or else you get the following error: +# ink! only supports compilation as `std` or `no_std` + `wasm32-unknown`" +default = ["hashbrown/nightly", "std"] # use `cargo bench --features sbench` only if you want benchmarks with 10 million # iterations (may fail on some systems) sbench = [] diff --git a/README.md b/README.md index 0960b60..501ea82 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,11 @@ Graphlib is a simple and powerful Rust graph library. This library attempts to provide a generic api for building, mutating and iterating over graphs that is similar to that of other data-structures found in Rust i.e. `Vec`, `HashMap`, `VecDeque`, etc. +## Modifications in this fork from the original +1. Fix compilation error when dot feature is enabled. +2. Replace no_std feature with a std feature (and reverse the default behavior). +3. Remove the dependency on rand. This library causes problems in constrained environments that do not have access to an RNG. + ### Using Graphlib ```rust use graphlib::Graph; @@ -34,13 +39,6 @@ assert_eq!(graph.vertex_count(), 1); assert_eq!(graph.edge_count(), 0); ``` -### Using without `std` -In `Cargo.toml`: -```toml -[dependencies] -graphlib = { version = "*", features = ["no_std"] } -``` - ### Contributing We welcome anyone wishing to contribute to Graphlib! Check out the [issues section][issues] of the repository before starting out. diff --git a/rust-toolchain.toml b/rust-toolchain.toml new file mode 100644 index 0000000..e6a80a9 --- /dev/null +++ b/rust-toolchain.toml @@ -0,0 +1,4 @@ +[toolchain] +channel = "nightly-2022-09-08" +components = [ "rustfmt" ] +targets = [ "wasm32-unknown-unknown" ] diff --git a/src/dot.rs b/src/dot.rs index ec9c939..a417a11 100644 --- a/src/dot.rs +++ b/src/dot.rs @@ -1,23 +1,11 @@ use crate::{Graph, GraphErr, VertexId}; #[cfg(not(feature = "std"))] -use core::io::Write; - -#[cfg(feature = "std")] -use std::io::Write; - -#[cfg(not(feature = "std"))] -use core::borrow::Cow; +use alloc::borrow::Cow; #[cfg(feature = "std")] use std::borrow::Cow; -#[cfg(not(feature = "std"))] -use core::fmt::Debug; - -#[cfg(feature = "std")] -use std::fmt::Debug; - type Nd = VertexId; type Ed<'a> = (&'a VertexId, &'a VertexId); @@ -43,7 +31,7 @@ impl<'a, T> dot::Labeller<'a, Nd, Ed<'a>> for DotGraph<'a, T> { } fn node_id(&'a self, n: &Nd) -> dot::Id<'a> { - let hex = format!("N{}", hex::encode(n.bytes())); + let hex = format!("N{}", n.val()); dot::Id::new(hex).unwrap() } diff --git a/src/edge.rs b/src/edge.rs index 4a8a143..0589dbb 100644 --- a/src/edge.rs +++ b/src/edge.rs @@ -40,12 +40,14 @@ impl Edge { /// Returns true if the given vertex ids are the /// inbound and outbound vertices of the edge. + #[allow(dead_code)] pub(crate) fn matches(&self, a: &VertexId, b: &VertexId) -> bool { a == &self.outbound && b == &self.inbound } /// Returns true if either the inbound or outbound /// vertex is matching the given `VertexId`. + #[allow(dead_code)] pub(crate) fn matches_any(&self, id: &VertexId) -> bool { id == &self.inbound || id == &self.outbound } diff --git a/src/graph.rs b/src/graph.rs index 478675b..918a194 100644 --- a/src/graph.rs +++ b/src/graph.rs @@ -24,8 +24,6 @@ use alloc::vec; #[cfg(not(feature = "std"))] use alloc::vec::Vec; -#[cfg(feature = "dot")] -use super::SEED; #[cfg(feature = "dot")] const DEFAULT_LABEL: &str = ""; @@ -80,6 +78,8 @@ pub struct Graph { /// Mapping between vertex ids and outbound edges outbound_table: HashMap>, + next_vertex_id: u32, + #[cfg(feature = "dot")] /// Mapping between vertices and labels vertex_labels: HashMap, @@ -109,6 +109,7 @@ impl Graph { tips: HashSet::new(), inbound_table: HashMap::new(), outbound_table: HashMap::new(), + next_vertex_id: 1, #[cfg(feature = "dot")] vertex_labels: HashMap::new(), @@ -139,6 +140,7 @@ impl Graph { tips: HashSet::with_capacity(capacity), inbound_table: HashMap::with_capacity(capacity), outbound_table: HashMap::with_capacity(capacity), + next_vertex_id: 1, #[cfg(feature = "dot")] vertex_labels: HashMap::with_capacity(capacity), @@ -264,7 +266,10 @@ impl Graph { /// assert_eq!(graph.fetch(&id).unwrap(), &1); /// ``` pub fn add_vertex(&mut self, item: T) -> VertexId { - let id = VertexId::random(); + let id = VertexId::new(self.next_vertex_id); + // This library is clearly not thread-safe, so we do not bother + // using an atomic int + self.next_vertex_id += 1; self.vertices.insert(id, (item, id)); self.roots.insert(id); @@ -282,7 +287,7 @@ impl Graph { /// let mut graph: Graph = Graph::new(); /// /// // Id of vertex that is not place in the graph - /// let id = VertexId::random(); + /// let id = VertexId::new(100); /// /// let v1 = graph.add_vertex(1); /// let v2 = graph.add_vertex(2); @@ -316,7 +321,7 @@ impl Graph { /// let mut graph: Graph = Graph::new(); /// /// // Id of vertex that is not place in the graph - /// let id = VertexId::random(); + /// let id = VertexId::new(100); /// /// let v1 = graph.add_vertex(1); /// let v2 = graph.add_vertex(2); @@ -347,7 +352,7 @@ impl Graph { /// let mut graph: Graph = Graph::new(); /// /// // Id of vertex that is not place in the graph - /// let id = VertexId::random(); + /// let id = VertexId::new(100); /// /// let v1 = graph.add_vertex(1); /// let v2 = graph.add_vertex(2); @@ -385,7 +390,7 @@ impl Graph { /// let mut graph: Graph = Graph::new(); /// /// // Id of vertex that is not place in the graph - /// let id = VertexId::random(); + /// let id = VertexId::new(100); /// /// let v1 = graph.add_vertex(1); /// let v2 = graph.add_vertex(2); @@ -420,7 +425,7 @@ impl Graph { /// let mut graph: Graph = Graph::new(); /// /// // Id of vertex that is not place in the graph - /// let id = VertexId::random(); + /// let id = VertexId::new(100); /// /// let v1 = graph.add_vertex(1); /// let v2 = graph.add_vertex(2); @@ -1371,7 +1376,7 @@ impl Graph { /// use graphlib::{Graph, VertexId}; /// /// let mut graph: Graph = Graph::new(); - /// let random_id = VertexId::random(); + /// let random_id = VertexId::new(100); /// /// let v1 = graph.add_vertex(0); /// let v2 = graph.add_vertex(1); @@ -1403,7 +1408,7 @@ impl Graph { /// use graphlib::{Graph, VertexId}; /// /// let mut graph: Graph = Graph::new(); - /// let random_id = VertexId::random(); + /// let random_id = VertexId::new(100); /// /// let v1 = graph.add_vertex(0); /// let v2 = graph.add_vertex(1); @@ -1471,7 +1476,7 @@ impl Graph { /// use graphlib::{Graph, VertexId}; /// /// let mut graph: Graph = Graph::new(); - /// let random_id = VertexId::random(); + /// let random_id = VertexId::new(100); /// let mut vertex_id: usize = 1; /// /// let v1 = graph.add_vertex(0); @@ -1526,7 +1531,7 @@ impl Graph { /// use graphlib::{Graph, VertexId}; /// /// let mut graph: Graph = Graph::new(); - /// let random_id = VertexId::random(); + /// let random_id = VertexId::new(100); /// let mut vertex_id: usize = 1; /// /// let v1 = graph.add_vertex(0); @@ -1843,9 +1848,6 @@ mod tests { fn test_add_edge_cycle_check() { let mut graph: Graph = Graph::new(); - // Id of vertex that is not place in the graph - let id = VertexId::random(); - let v1 = graph.add_vertex(1); let v2 = graph.add_vertex(2); diff --git a/src/iterators/dijkstra.rs b/src/iterators/dijkstra.rs index d862f7e..b2e61b0 100644 --- a/src/iterators/dijkstra.rs +++ b/src/iterators/dijkstra.rs @@ -184,7 +184,7 @@ mod tests { #[test] fn test_new_with_empty_graph() { - let random_vertex = VertexId::random(); + let random_vertex = VertexId::new(100); let graph: Graph = Graph::new(); let result = Dijkstra::new(&graph, &random_vertex); @@ -194,7 +194,7 @@ mod tests { #[test] fn test_new_with_invalid_source() { - let random_vertex = VertexId::random(); + let random_vertex = VertexId::new(100); let mut graph: Graph = Graph::new(); let v1 = graph.add_vertex(1); @@ -222,7 +222,7 @@ mod tests { #[test] fn test_set_source_with_invalid_vertex() { - let random_vertex = VertexId::random(); + let random_vertex = VertexId::new(100); let mut graph: Graph = Graph::new(); let v1 = graph.add_vertex(1); @@ -237,7 +237,7 @@ mod tests { #[test] fn test_get_path_to_with_invalid_vertex() { - let random_vertex = VertexId::random(); + let random_vertex = VertexId::new(100); let mut graph: Graph = Graph::new(); let v1 = graph.add_vertex(1); @@ -252,7 +252,7 @@ mod tests { #[test] fn test_get_distance_with_invalid_vertex() { - let random_vertex = VertexId::random(); + let random_vertex = VertexId::new(100); let mut graph: Graph = Graph::new(); let v1 = graph.add_vertex(1); diff --git a/src/iterators/owning_iterator.rs b/src/iterators/owning_iterator.rs index 710db6b..8158c23 100644 --- a/src/iterators/owning_iterator.rs +++ b/src/iterators/owning_iterator.rs @@ -73,7 +73,7 @@ mod tests { #[test] fn it_yields_correct_vertex_ids() { let ids: VecDeque = - vec![VertexId::random(), VertexId::random(), VertexId::random()] + vec![VertexId::new(1), VertexId::new(2), VertexId::new(3)] .iter() .cloned() .collect(); diff --git a/src/lib.rs b/src/lib.rs index 3bf5fbf..0089add 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,42 +1,21 @@ // Copyright 2019 Octavian Oncescu -#![cfg_attr(feature = "no_std", no_std)] +// Need to set the no_std attribute to avoid +// compile_error! { "ink! only supports compilation as `std` or `no_std` + `wasm32-unknown`" } +#![cfg_attr(not(feature = "std"), no_std)] -//! # Graphlib -//! Graphlib is a simple and powerful Rust graph library. -//! -//! --- -//! -//! This library attempts to provide a generic api for building, mutating and iterating over graphs that is similar to that of other data-structures in rust i.e. `Vec`, `HashMap`, `VecDeque`, etc. -//! -//! ### Usage -//! ```rust -//! use graphlib::Graph; -//! -//! let mut graph: Graph = Graph::new(); -//! -//! // Add two vertices to the graph -//! let id1 = graph.add_vertex(1); -//! let id2 = graph.add_vertex(2); -//! -//! // Add an edge between the two vertices -//! graph.add_edge(&id1, &id2); -//! -//! assert_eq!(*graph.fetch(&id1).unwrap(), 1); -//! assert_eq!(*graph.fetch(&id2).unwrap(), 2); -//! -//! // The graph has 2 vertices and one edge at this point -//! assert_eq!(graph.vertex_count(), 2); -//! assert_eq!(graph.edge_count(), 1); -//! -//! // Remove one of the connected vertices -//! graph.remove(&id1); -//! -//! assert_eq!(graph.vertex_count(), 1); -//! assert_eq!(graph.edge_count(), 0); -//! ``` +#[macro_use] +extern crate alloc; -#![allow(mutable_transmutes)] +// # Graphlib +// Graphlib is a simple and powerful Rust graph library. +// +// --- +// +// This library attempts to provide a generic api for building, mutating and +// iterating over graphs that is similar to that of other data-structures +// in rust i.e. `Vec`, `HashMap`, `VecDeque`, etc. +// mod edge; #[macro_use] @@ -45,31 +24,8 @@ mod graph; pub mod iterators; mod vertex_id; -// use global variables to create VertexId::random() -use core::sync::atomic::AtomicUsize; - #[cfg(feature = "dot")] pub mod dot; pub use graph::*; pub use vertex_id::*; - -static SEED: AtomicUsize = AtomicUsize::new(0); - -use rand; -use rand::Rng; -use rand::SeedableRng; -use rand_core::RngCore; -use rand_isaac::IsaacRng; - -use core::sync::atomic::Ordering; - -pub(crate) fn gen_bytes() -> [u8; 16] { - IsaacRng::gen::<[u8; 16]>(&mut IsaacRng::seed_from_u64(IsaacRng::next_u64( - &mut IsaacRng::seed_from_u64(SEED.fetch_add(1, Ordering::Relaxed) as u64), - ))) -} - -#[cfg(not(feature = "std"))] -#[macro_use] -extern crate alloc; diff --git a/src/vertex_id.rs b/src/vertex_id.rs index 6d0c668..d15cf41 100644 --- a/src/vertex_id.rs +++ b/src/vertex_id.rs @@ -2,14 +2,12 @@ #[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] /// Id of a vertex -pub struct VertexId([u8; 16]); // 128bit +// pub struct VertexId([u8; 16]); // 128bit +pub struct VertexId(u32); impl core::fmt::Debug for VertexId { fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { - let mut buff: [u8; 32] = [0 as u8; 32]; - let _ = hex::encode_to_slice(self.0, &mut buff); - let s = core::str::from_utf8(&buff).unwrap(); - write!(f, "VertexId({})", s) + write!(f, "VertexId({})", self.0) } } @@ -20,11 +18,16 @@ impl core::convert::AsRef for VertexId { } impl VertexId { - pub fn random() -> VertexId { - VertexId(super::gen_bytes()) + + /// This is an unsafe function and generally should not be used! + /// It's made public for use largely in test contexts. + /// Otherwise you may risk creating two identical VertexId's in a graph + /// Use Graph::add_vertex(...) instead + pub fn new(val: u32) -> Self { + Self{0: val} } - pub fn bytes(&self) -> &[u8; 16] { - &self.0 + pub(crate) fn val(&self) -> u32 { + self.0 } }