Skip to content

Commit

Permalink
Remove dependency on rand for no_std compatibility
Browse files Browse the repository at this point in the history
  • Loading branch information
kapilsinha committed Jan 9, 2023
1 parent 6e07fd7 commit 23c249e
Show file tree
Hide file tree
Showing 10 changed files with 72 additions and 111 deletions.
20 changes: 13 additions & 7 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
name = "graphlib"
version = "0.6.3"
authors = ["Octavian Oncescu <[email protected]>"]
edition = "2018"
edition = "2021"
repository = "https://github.com/purpleprotocol/graphlib"
keywords = ["graph", "data-structures", "mutable", "graph-algorithm", "no-std"]
categories = ["data-structures", "no-std"]
Expand All @@ -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 = []
Expand Down
12 changes: 5 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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.

Expand Down
4 changes: 4 additions & 0 deletions rust-toolchain.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[toolchain]
channel = "nightly-2022-09-08"
components = [ "rustfmt" ]
targets = [ "wasm32-unknown-unknown" ]
10 changes: 2 additions & 8 deletions src/dot.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,7 @@
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;
Expand Down Expand Up @@ -43,7 +37,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);
dot::Id::new(hex).unwrap()
}

Expand Down
2 changes: 2 additions & 0 deletions src/edge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
32 changes: 17 additions & 15 deletions src/graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 = "";
Expand Down Expand Up @@ -80,6 +78,8 @@ pub struct Graph<T> {
/// Mapping between vertex ids and outbound edges
outbound_table: HashMap<VertexId, Vec<VertexId>>,

next_vertex_id: u32,

#[cfg(feature = "dot")]
/// Mapping between vertices and labels
vertex_labels: HashMap<VertexId, String>,
Expand Down Expand Up @@ -109,6 +109,7 @@ impl<T> Graph<T> {
tips: HashSet::new(),
inbound_table: HashMap::new(),
outbound_table: HashMap::new(),
next_vertex_id: 1,

#[cfg(feature = "dot")]
vertex_labels: HashMap::new(),
Expand Down Expand Up @@ -139,6 +140,7 @@ impl<T> Graph<T> {
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),
Expand Down Expand Up @@ -264,7 +266,10 @@ impl<T> Graph<T> {
/// 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);
Expand All @@ -282,7 +287,7 @@ impl<T> Graph<T> {
/// let mut graph: Graph<usize> = 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);
Expand Down Expand Up @@ -316,7 +321,7 @@ impl<T> Graph<T> {
/// let mut graph: Graph<usize> = 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);
Expand Down Expand Up @@ -347,7 +352,7 @@ impl<T> Graph<T> {
/// let mut graph: Graph<usize> = 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);
Expand Down Expand Up @@ -385,7 +390,7 @@ impl<T> Graph<T> {
/// let mut graph: Graph<usize> = 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);
Expand Down Expand Up @@ -420,7 +425,7 @@ impl<T> Graph<T> {
/// let mut graph: Graph<usize> = 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);
Expand Down Expand Up @@ -1371,7 +1376,7 @@ impl<T> Graph<T> {
/// use graphlib::{Graph, VertexId};
///
/// let mut graph: Graph<usize> = 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);
Expand Down Expand Up @@ -1403,7 +1408,7 @@ impl<T> Graph<T> {
/// use graphlib::{Graph, VertexId};
///
/// let mut graph: Graph<usize> = 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);
Expand Down Expand Up @@ -1471,7 +1476,7 @@ impl<T> Graph<T> {
/// use graphlib::{Graph, VertexId};
///
/// let mut graph: Graph<usize> = 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);
Expand Down Expand Up @@ -1526,7 +1531,7 @@ impl<T> Graph<T> {
/// use graphlib::{Graph, VertexId};
///
/// let mut graph: Graph<usize> = 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);
Expand Down Expand Up @@ -1843,9 +1848,6 @@ mod tests {
fn test_add_edge_cycle_check() {
let mut graph: Graph<usize> = 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);

Expand Down
10 changes: 5 additions & 5 deletions src/iterators/dijkstra.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<usize> = Graph::new();
let result = Dijkstra::new(&graph, &random_vertex);
Expand All @@ -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<usize> = Graph::new();
let v1 = graph.add_vertex(1);
Expand Down Expand Up @@ -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<usize> = Graph::new();
let v1 = graph.add_vertex(1);
Expand All @@ -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<usize> = Graph::new();
let v1 = graph.add_vertex(1);
Expand All @@ -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<usize> = Graph::new();
let v1 = graph.add_vertex(1);
Expand Down
2 changes: 1 addition & 1 deletion src/iterators/owning_iterator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ mod tests {
#[test]
fn it_yields_correct_vertex_ids() {
let ids: VecDeque<VertexId> =
vec![VertexId::random(), VertexId::random(), VertexId::random()]
vec![VertexId::new(1), VertexId::new(2), VertexId::new(3)]
.iter()
.cloned()
.collect();
Expand Down
72 changes: 14 additions & 58 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -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<usize> = 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]
Expand All @@ -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;
Loading

0 comments on commit 23c249e

Please sign in to comment.