backport some nice things from routing engine and cleanup a bit master
authorTim "S.D.Eagle" Zeitz <dev.tim.zeitz@gmail.com>
Tue, 3 Dec 2019 10:17:38 +0000 (11:17 +0100)
committerTim "S.D.Eagle" Zeitz <dev.tim.zeitz@gmail.com>
Tue, 3 Dec 2019 10:17:38 +0000 (11:17 +0100)
README.md
src/bin/example.rs
src/cli.rs
src/index_heap.rs
src/io.rs

index 7239043..59210f9 100644 (file)
--- a/README.md
+++ b/README.md
@@ -53,12 +53,11 @@ Die entsprechenden Funktionen sind über Traits definiert und können so direkt
 Das kann z.B. so aussehen:
 
 ```Rust
 Das kann z.B. so aussehen:
 
 ```Rust
-extern crate stud_rust_base;
 use stud_rust_base::io::*;
 
 use stud_rust_base::io::*;
 
-let head = Vec::<u32>::load_from("head_file_name").expect("could not read head");
-let lat = Vec::<f32>::load_from("node_latitude_file_name").expect("could not read lat");
-head.write_to("output_file").expect("could not write head");
+let head = Vec::<u32>::load_from("head_file_name")?;
+let lat = Vec::<f32>::load_from("node_latitude_file_name")?;
+head.write_to(&"output_file")?;
 ```
 
 Die Dateien in `src/bin/` sind einmal ein Beispielprogramm sowieso Hilfsprogramme.
 ```
 
 Die Dateien in `src/bin/` sind einmal ein Beispielprogramm sowieso Hilfsprogramme.
@@ -79,12 +78,11 @@ Diese heißen `first_out`, `head` und `weight`.
 Um über die ausgehenden Kanten eines Knoten zu iterieren können Sie den folgenden Code verwenden:
 
 ```Rust
 Um über die ausgehenden Kanten eines Knoten zu iterieren können Sie den folgenden Code verwenden:
 
 ```Rust
-extern crate stud_rust_base;
 use stud_rust_base::{types::*, io::*};
 
 use stud_rust_base::{types::*, io::*};
 
-let first_out = Vec::<EdgeId>::load_from("first_out_file_name").expect("could not read first_out");
-let head = Vec::<NodeId>::load_from("head_file_name").expect("could not read head");
-let travel_time = Vec::<Weight>::load_from("weight_file_name").expect("could not read travel_time");
+let first_out = Vec::<EdgeId>::load_from("first_out_file_name")?;
+let head = Vec::<NodeId>::load_from("head_file_name")?;
+let travel_time = Vec::<Weight>::load_from("weight_file_name")?;
 
 let node_id = 42;
 for edge_id in first_out[node_id] .. first_out[node_id + 1] {
 
 let node_id = 42;
 for edge_id in first_out[node_id] .. first_out[node_id + 1] {
index f8e9434..68056b8 100644 (file)
@@ -1,28 +1,29 @@
-use stud_rust_base::{
-    types::*,
-    io::*,
-    time::report_time,
-};
+use stud_rust_base::{io::*, time::report_time, types::*};
 
 
-use std::{env, path::Path};
+use std::{env, error::Error, path::Path};
 
 
-fn main() {
+fn main() -> Result<(), Box<dyn Error>> {
     let mut args = env::args();
     args.next();
 
     let arg = &args.next().expect("No directory arg given");
     let path = Path::new(arg);
 
     let mut args = env::args();
     args.next();
 
     let arg = &args.next().expect("No directory arg given");
     let path = Path::new(arg);
 
-    let first_out = Vec::<EdgeId>::load_from(path.join("first_out").to_str().unwrap()).expect("could not read first_out");
-    let head = Vec::<NodeId>::load_from(path.join("head").to_str().unwrap()).expect("could not read head");
-    let travel_time = Vec::<Weight>::load_from(path.join("travel_time").to_str().unwrap()).expect("could not read travel_time");
+    let first_out = Vec::<EdgeId>::load_from(path.join("first_out"))?;
+    let head = Vec::<NodeId>::load_from(path.join("head"))?;
+    let travel_time = Vec::<Weight>::load_from(path.join("travel_time"))?;
 
     report_time("iterating over arcs of some node", || {
         let node_id = 42;
 
     report_time("iterating over arcs of some node", || {
         let node_id = 42;
-        for edge_id in first_out[node_id] .. first_out[node_id + 1] {
-            println!("There is an arc from {} to {} with weight {}", node_id, head[edge_id as usize], travel_time[edge_id as usize]);
+        for edge_id in first_out[node_id]..first_out[node_id + 1] {
+            println!(
+                "There is an arc from {} to {} with weight {}",
+                node_id, head[edge_id as usize], travel_time[edge_id as usize]
+            );
         }
     });
 
         }
     });
 
-    vec![42; 42].write_to(path.join("distances").to_str().unwrap()).expect("could not write distances");
+    vec![42; 42].write_to(&path.join("distances"))?;
+
+    Ok(())
 }
 }
index e66421d..fc083d1 100644 (file)
@@ -1,6 +1,6 @@
 //! Utility module for command line interfaces
 
 //! Utility module for command line interfaces
 
-use std::{fmt, fmt::Display, error::Error};
+use std::{error::Error, fmt, fmt::Display};
 
 /// An error struct to wrap simple static error messages
 #[derive(Debug)]
 
 /// An error struct to wrap simple static error messages
 #[derive(Debug)]
index a7af9ca..477dc87 100644 (file)
 //!     }
 //! }
 //!
 //!     }
 //! }
 //!
-//! fn main() {
-//!     let mut heap = IndexdMinHeap::new(3);
-//!     heap.push(State { node: 0, distance: 42 });
-//!     heap.push(State { node: 1, distance: 23 });
-//!     heap.push(State { node: 2, distance: 50000 });
-//!     assert_eq!(heap.peek().cloned(), Some(State { node: 1, distance: 23 }));
-//!     heap.decrease_key(State { node: 0, distance: 1 });
-//!     assert_eq!(heap.pop(), Some(State { node: 0, distance: 1 }));
-//! }
+//! let mut heap = IndexdMinHeap::new(3);
+//! heap.push(State { node: 0, distance: 42 });
+//! heap.push(State { node: 1, distance: 23 });
+//! heap.push(State { node: 2, distance: 50000 });
+//! assert_eq!(heap.peek().cloned(), Some(State { node: 1, distance: 23 }));
+//! heap.decrease_key(State { node: 0, distance: 1 });
+//! assert_eq!(heap.pop(), Some(State { node: 0, distance: 1 }));
 //!
 //! ```
 
 //!
 //! ```
 
@@ -55,7 +53,7 @@ pub trait Indexing {
 #[derive(Debug)]
 pub struct IndexdMinHeap<T: Ord + Indexing> {
     positions: Vec<usize>,
 #[derive(Debug)]
 pub struct IndexdMinHeap<T: Ord + Indexing> {
     positions: Vec<usize>,
-    data: Vec<T>
+    data: Vec<T>,
 }
 
 const TREE_ARITY: usize = 4;
 }
 
 const TREE_ARITY: usize = 4;
@@ -68,7 +66,7 @@ impl<T: Ord + Indexing> IndexdMinHeap<T> {
     pub fn new(max_index: usize) -> IndexdMinHeap<T> {
         IndexdMinHeap {
             positions: vec![INVALID_POSITION; max_index],
     pub fn new(max_index: usize) -> IndexdMinHeap<T> {
         IndexdMinHeap {
             positions: vec![INVALID_POSITION; max_index],
-            data: Vec::new()
+            data: Vec::new(),
         }
     }
 
         }
     }
 
@@ -170,7 +168,10 @@ impl<T: Ord + Indexing> IndexdMinHeap<T> {
             let mut hole = Hole::new(&mut self.data, position);
 
             loop {
             let mut hole = Hole::new(&mut self.data, position);
 
             loop {
-                if let Some(smallest_child) = IndexdMinHeap::<T>::children_index_range(position, heap_size).min_by_key(|&child_index| hole.get(child_index)) {
+                if let Some(smallest_child) =
+                    IndexdMinHeap::<T>::children_index_range(position, heap_size)
+                        .min_by_key(|&child_index| hole.get(child_index))
+                {
                     if hole.get(smallest_child) >= hole.element() {
                         self.positions[hole.element().as_index()] = position;
                         return; // no child is smaller
                     if hole.get(smallest_child) >= hole.element() {
                         self.positions[hole.element().as_index()] = position;
                         return; // no child is smaller
@@ -194,12 +195,10 @@ impl<T: Ord + Indexing> IndexdMinHeap<T> {
     }
 }
 
     }
 }
 
-
 // This is an optimization copied straight from the rust stdlib binary heap
 // it allows to avoid always swapping elements pairwise and rather
 // move each element only once.
 
 // This is an optimization copied straight from the rust stdlib binary heap
 // it allows to avoid always swapping elements pairwise and rather
 // move each element only once.
 
-
 /// Hole represents a hole in a slice i.e. an index without valid value
 /// (because it was moved from or duplicated).
 /// In drop, `Hole` will restore the slice by filling the hole
 /// Hole represents a hole in a slice i.e. an index without valid value
 /// (because it was moved from or duplicated).
 /// In drop, `Hole` will restore the slice by filling the hole
index 419fa45..52057af 100644 (file)
--- a/src/io.rs
+++ b/src/io.rs
@@ -1,26 +1,26 @@
 //! This module contains a few traits and blanket implementations
 //! This module contains a few traits and blanket implementations
-//! for (de)serializing and writing/reading numeric data to/from the disc.
+//! for (de)serializing and writing/reading data to/from the disc.
 //! To use it you should import the `Load` and `Store` traits and use the
 //! `load_from` and `write_to` methods.
 //!
 //! # Example
 //!
 //! To use it you should import the `Load` and `Store` traits and use the
 //! `load_from` and `write_to` methods.
 //!
 //! # Example
 //!
-//! ```
-//! use stud_rust_base::io::*;
+//! ```no_run
+//! use stud_rust_base::io::*;
 //!
 //!
-//! fn test() {
-//!     let head = Vec::<u32>::load_from("head_file_name").expect("could not read head");
-//!     let lat = Vec::<f32>::load_from("node_latitude_file_name").expect("could not read lat");
-//!     head.write_to("output_file").expect("could not write head");
-//! }
+//! let head = Vec::<u32>::load_from("head_file_name")?;
+//! let lat = Vec::<f32>::load_from("node_latitude_file_name")?;
+//! head.write_to(&"output_file")?;
+//! # Ok::<(), Box<dyn std::error::Error>>(())
 //! ```
 
 //! ```
 
-use std::fs;
-use std::fs::File;
-use std::io::prelude::*;
-use std::io::Result;
-use std::mem;
-use std::slice;
+use std::{
+    fs::{metadata, File},
+    io::{prelude::*, Result},
+    mem,
+    path::Path,
+    slice,
+};
 
 /// A trait which allows accessing the data of an object as a slice of bytes.
 /// The bytes should represent a serialization of the object and allow
 
 /// A trait which allows accessing the data of an object as a slice of bytes.
 /// The bytes should represent a serialization of the object and allow
@@ -49,6 +49,12 @@ impl<T: Copy> DataBytes for [T] {
     }
 }
 
     }
 }
 
+impl<T: Copy> DataBytes for Vec<T> {
+    fn data_bytes(&self) -> &[u8] {
+        &self[..].data_bytes()
+    }
+}
+
 impl<T: Copy> DataBytesMut for [T] {
     fn data_bytes_mut(&mut self) -> &mut [u8] {
         let num_bytes = self.len() * mem::size_of::<T>();
 impl<T: Copy> DataBytesMut for [T] {
     fn data_bytes_mut(&mut self) -> &mut [u8] {
         let num_bytes = self.len() * mem::size_of::<T>();
@@ -64,10 +70,10 @@ impl<T: Copy> DataBytesMut for Vec<T> {
 }
 
 /// A trait which extends the `DataBytes` trait and exposes a method to write objects to disk.
 }
 
 /// A trait which extends the `DataBytes` trait and exposes a method to write objects to disk.
-pub trait Store : DataBytes {
-    /// Writes the serialized object to the file with the given filename
-    fn write_to(&self, filename: &str) -> Result<()> {
-        File::create(filename)?.write_all(self.data_bytes())
+pub trait Store: DataBytes {
+    /// Writes the serialized object to the file with the given path
+    fn write_to(&self, path: &dyn AsRef<Path>) -> Result<()> {
+        File::create(path)?.write_all(self.data_bytes())
     }
 }
 
     }
 }
 
@@ -75,16 +81,16 @@ impl<T: DataBytes> Store for T {}
 impl<T> Store for [T] where [T]: DataBytes {}
 
 /// A trait to load serialized data back into objects.
 impl<T> Store for [T] where [T]: DataBytes {}
 
 /// A trait to load serialized data back into objects.
-pub trait Load : DataBytesMut + Sized {
+pub trait Load: DataBytesMut + Sized {
     /// This method must create an object of the correct size for serialized data with the given number of bytes.
     /// It should not be necessary to call this method directly.
     fn new_with_bytes(num_bytes: usize) -> Self;
 
     /// This method will load serialized data from the disk, create an object of the appropriate size,
     /// deserialize the bytes into the object and return the object.
     /// This method must create an object of the correct size for serialized data with the given number of bytes.
     /// It should not be necessary to call this method directly.
     fn new_with_bytes(num_bytes: usize) -> Self;
 
     /// This method will load serialized data from the disk, create an object of the appropriate size,
     /// deserialize the bytes into the object and return the object.
-    fn load_from(filename: &str) -> Result<Self> {
-        let metadata = fs::metadata(filename)?;
-        let mut file = File::open(filename)?;
+    fn load_from<P: AsRef<Path>>(path: P) -> Result<Self> {
+        let metadata = metadata(path.as_ref())?;
+        let mut file = File::open(path)?;
 
         let mut object = Self::new_with_bytes(metadata.len() as usize);
         assert_eq!(metadata.len() as usize, object.data_bytes_mut().len());
 
         let mut object = Self::new_with_bytes(metadata.len() as usize);
         assert_eq!(metadata.len() as usize, object.data_bytes_mut().len());