Das kann z.B. so aussehen:
```Rust
-extern crate stud_rust_base;
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.
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::*};
-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] {
-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 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;
- 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(())
}
//! 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)]
//! }
//! }
//!
-//! 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 }));
//!
//! ```
#[derive(Debug)]
pub struct IndexdMinHeap<T: Ord + Indexing> {
positions: Vec<usize>,
- data: Vec<T>
+ data: Vec<T>,
}
const TREE_ARITY: usize = 4;
pub fn new(max_index: usize) -> IndexdMinHeap<T> {
IndexdMinHeap {
positions: vec![INVALID_POSITION; max_index],
- data: Vec::new()
+ data: Vec::new(),
}
}
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
}
}
-
// 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
//! 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
//!
-//! ```
-//! 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
}
}
+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>();
}
/// 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())
}
}
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.
- 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());