-[[package]]
-name = "libc"
-version = "0.2.43"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
-name = "redox_syscall"
-version = "0.1.40"
-source = "registry+https://github.com/rust-lang/crates.io-index"
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
[[package]]
name = "stud-rust-base"
version = "0.1.0"
-dependencies = [
- "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "time"
-version = "0.1.40"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
- "redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "winapi"
-version = "0.3.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "winapi-i686-pc-windows-gnu"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
-name = "winapi-x86_64-pc-windows-gnu"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[metadata]
-"checksum libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)" = "76e3a3ef172f1a0b9a9ff0dd1491ae5e6c948b94479a3021819ba7d860c8645d"
-"checksum redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "c214e91d3ecf43e9a4e41e578973adeb14b474f2bee858742d127af75a0112b1"
-"checksum time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "d825be0eb33fda1a7e68012d51e9c7f451dc1a69391e7fdc197060bb8c56667b"
-"checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0"
-"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
-"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
name = "stud-rust-base"
version = "0.1.0"
authors = ["Tim Zeitz <tim.zeitz@kit.edu>"]
-
-[dependencies]
-time = "0.1.40"
+edition = '2021'
Rust hat einen exzellenten Linter, der einem sehr hilft idiomatischen und performanten Code zu schreiben.
Das ist insbesondere wenn man noch nicht viel Erfahrung mit der Sprache hat extrem sinnvoll!
-Installieren kann man Clippy mit `rustup component add clippy-preview`.
+Installieren kann man Clippy mit `rustup component add clippy`.
Anstatt `cargo check` ruft man dann `cargo clippy` auf und kann sich auf viel hilfreiches Feedback freuen.
# Rust Routenplanungs-Basis-Framework
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] {
## Hinweise zur Nutzung im Routenplanungspraktikum
-Der Quellcode soll durch das Ausführen von `cargo build --all` mit dem aktuellen stabilen Compiler (1.29.2) übersetzt werden können.
+Der Quellcode soll durch das Ausführen von `cargo build --all` mit dem aktuellen stabilen Compiler (1.38.0) übersetzt werden können.
Auf den Poolraumrechner ist kein Rust Compiler vorinstalliert.
Sie können aber für ihren Nutzer lokal `rustup` und damit dann einen aktuellen Compiler installieren.
Die Nutzung von nicht stabilen nightly Features ist nicht erlaubt.
Das verwenden externer crates ist nicht erlaubt.
-Die Rust-Standardbibliothek ist nicht extern.
+Die Rust-Standardbibliothek gilt nicht als extern.
--- /dev/null
+max_width = 160
-extern crate stud_rust_base;
-use stud_rust_base::{io::*, cli::CliErr};
-use std::{env, fmt::Display, error::Error};
+use std::{env, error::Error, fmt::Display};
+use stud_rust_base::{cli::CliErr, io::*};
fn main() -> Result<(), Box<dyn Error>> {
- let mut args = env::args();
- args.next();
-
- match &args.collect::<Vec<String>>()[..] {
- [data_type, input1, input2] => {
+ let mut args = env::args().skip(1);
+ match &(args.next(), args.next(), args.next()) {
+ (Some(data_type), Some(input1), Some(input2)) => {
match data_type.as_ref() {
- "i8" => { compare_values(&Vec::<i8>::load_from(input1)?, &Vec::<i8>::load_from(input2)?); Ok(()) },
- "u8" => { compare_values(&Vec::<u8>::load_from(input1)?, &Vec::<u8>::load_from(input2)?); Ok(()) },
- "i16" => { compare_values(&Vec::<i16>::load_from(input1)?, &Vec::<i16>::load_from(input2)?); Ok(()) },
- "u16" => { compare_values(&Vec::<u16>::load_from(input1)?, &Vec::<u16>::load_from(input2)?); Ok(()) },
- "i32" => { compare_values(&Vec::<i32>::load_from(input1)?, &Vec::<i32>::load_from(input2)?); Ok(()) },
- "u32" => { compare_values(&Vec::<u32>::load_from(input1)?, &Vec::<u32>::load_from(input2)?); Ok(()) },
- "i64" => { compare_values(&Vec::<i64>::load_from(input1)?, &Vec::<i64>::load_from(input2)?); Ok(()) },
- "u64" => { compare_values(&Vec::<u64>::load_from(input1)?, &Vec::<u64>::load_from(input2)?); Ok(()) },
- "f32" => { compare_values(&Vec::<f32>::load_from(input1)?, &Vec::<f32>::load_from(input2)?); Ok(()) },
- "f64" => { compare_values(&Vec::<f64>::load_from(input1)?, &Vec::<f64>::load_from(input2)?); Ok(()) },
- "int8" => { compare_values(&Vec::<i8>::load_from(input1)?, &Vec::<i8>::load_from(input2)?); Ok(()) },
- "uint8" => { compare_values(&Vec::<u8>::load_from(input1)?, &Vec::<u8>::load_from(input2)?); Ok(()) },
- "int16" => { compare_values(&Vec::<i16>::load_from(input1)?, &Vec::<i16>::load_from(input2)?); Ok(()) },
- "uint16" => { compare_values(&Vec::<u16>::load_from(input1)?, &Vec::<u16>::load_from(input2)?); Ok(()) },
- "int32" => { compare_values(&Vec::<i32>::load_from(input1)?, &Vec::<i32>::load_from(input2)?); Ok(()) },
- "uint32" => { compare_values(&Vec::<u32>::load_from(input1)?, &Vec::<u32>::load_from(input2)?); Ok(()) },
- "int64" => { compare_values(&Vec::<i64>::load_from(input1)?, &Vec::<i64>::load_from(input2)?); Ok(()) },
- "uint64" => { compare_values(&Vec::<u64>::load_from(input1)?, &Vec::<u64>::load_from(input2)?); Ok(()) },
- "float32" => { compare_values(&Vec::<f32>::load_from(input1)?, &Vec::<f32>::load_from(input2)?); Ok(()) },
- "float64" => { compare_values(&Vec::<f64>::load_from(input1)?, &Vec::<f64>::load_from(input2)?); Ok(()) },
+ "i8" | "int8" => compare_values::<i8>(&Vec::load_from(input1)?, &Vec::load_from(input2)?),
+ "u8" | "uint8" => compare_values::<u8>(&Vec::load_from(input1)?, &Vec::load_from(input2)?),
+ "i16" | "int16" => compare_values::<i16>(&Vec::load_from(input1)?, &Vec::load_from(input2)?),
+ "u16" | "uint16" => compare_values::<u16>(&Vec::load_from(input1)?, &Vec::load_from(input2)?),
+ "i32" | "int32" => compare_values::<i32>(&Vec::load_from(input1)?, &Vec::load_from(input2)?),
+ "u32" | "uint32" => compare_values::<u32>(&Vec::load_from(input1)?, &Vec::load_from(input2)?),
+ "i64" | "int64" => compare_values::<i64>(&Vec::load_from(input1)?, &Vec::load_from(input2)?),
+ "u64" | "uint64" => compare_values::<u64>(&Vec::load_from(input1)?, &Vec::load_from(input2)?),
+ "f32" | "float32" => compare_values::<f32>(&Vec::load_from(input1)?, &Vec::load_from(input2)?),
+ "f64" | "float64" => compare_values::<f64>(&Vec::load_from(input1)?, &Vec::load_from(input2)?),
_ => {
print_usage();
- Err(Box::new(CliErr("Invalid data type")))
+ return Err(Box::new(CliErr("Invalid data type")));
}
- }
- },
+ };
+ Ok(())
+ }
_ => {
print_usage();
Err(Box::new(CliErr("Invalid arguments")))
- },
+ }
}
}
fn print_usage() {
- eprintln!("Usage: decode_vector data_type vector1_file vector2_file
+ eprintln!(
+ "Usage: decode_vector data_type vector1_file vector2_file
Compares two vectors of elements in binary format. data_type can be one of
* i8
* f32
* f64
-");
+"
+ );
}
-fn compare_values<T>(values1: &[T], values2: &[T]) where
+fn compare_values<T>(values1: &[T], values2: &[T])
+where
T: Display,
- T: PartialOrd
+ T: PartialOrd,
{
if values1.len() != values2.len() {
println!("0");
- eprintln!("Can only compare vectors of equal size. The first vector has {} elements. The second vector has {} elements.", values1.len(), values2.len());
- return
+ eprintln!(
+ "Can only compare vectors of equal size. The first vector has {} elements. The second vector has {} elements.",
+ values1.len(),
+ values2.len()
+ );
+ return;
}
let mut v1_smaller_count = 0;
let mut first_diff = None;
for (i, (v1, v2)) in values1.iter().zip(values2.iter()).enumerate() {
- if v1 < v2 { v1_smaller_count += 1; }
- if v2 < v1 { v2_smaller_count += 1; }
+ if v1 < v2 {
+ v1_smaller_count += 1;
+ }
+ if v2 < v1 {
+ v2_smaller_count += 1;
+ }
if first_diff.is_none() && v1 != v2 {
first_diff = Some(i)
eprintln!("{} elements are different.", v1_smaller_count + v2_smaller_count);
eprintln!("The vectors have {} elements.", values1.len());
eprintln!("The first element that differs is at index {}.", index);
- },
+ }
None => {
println!("{}", values1.len());
eprintln!("The vectors are the same and have {} elements.", values1.len());
- },
+ }
}
}
-extern crate stud_rust_base;
-use stud_rust_base::{io::*, cli::CliErr};
use std::{env, error::Error};
+use stud_rust_base::{cli::CliErr, io::*};
fn main() -> Result<(), Box<dyn Error>> {
- let mut args = env::args();
- args.next();
-
- match &args.collect::<Vec<String>>()[..] {
- [data_type, input] => {
- match data_type.as_ref() {
- "i8" => { print_values(Vec::<i8>::load_from(input)?); Ok(()) },
- "u8" => { print_values(Vec::<u8>::load_from(input)?); Ok(()) },
- "i16" => { print_values(Vec::<i16>::load_from(input)?); Ok(()) },
- "u16" => { print_values(Vec::<u16>::load_from(input)?); Ok(()) },
- "i32" => { print_values(Vec::<i32>::load_from(input)?); Ok(()) },
- "u32" => { print_values(Vec::<u32>::load_from(input)?); Ok(()) },
- "i64" => { print_values(Vec::<i64>::load_from(input)?); Ok(()) },
- "u64" => { print_values(Vec::<u64>::load_from(input)?); Ok(()) },
- "f32" => { print_values(Vec::<f32>::load_from(input)?); Ok(()) },
- "f64" => { print_values(Vec::<f64>::load_from(input)?); Ok(()) },
- "int8" => { print_values(Vec::<i8>::load_from(input)?); Ok(()) },
- "uint8" => { print_values(Vec::<u8>::load_from(input)?); Ok(()) },
- "int16" => { print_values(Vec::<i16>::load_from(input)?); Ok(()) },
- "uint16" => { print_values(Vec::<u16>::load_from(input)?); Ok(()) },
- "int32" => { print_values(Vec::<i32>::load_from(input)?); Ok(()) },
- "uint32" => { print_values(Vec::<u32>::load_from(input)?); Ok(()) },
- "int64" => { print_values(Vec::<i64>::load_from(input)?); Ok(()) },
- "uint64" => { print_values(Vec::<u64>::load_from(input)?); Ok(()) },
- "float32" => { print_values(Vec::<f32>::load_from(input)?); Ok(()) },
- "float64" => { print_values(Vec::<f64>::load_from(input)?); Ok(()) },
- _ => {
- print_usage();
- Err(Box::new(CliErr("Invalid data type")))
- }
+ let mut args = env::args().skip(1);
+ match (args.next(), args.next()) {
+ (Some(data_type), Some(ref input)) => match data_type.as_ref() {
+ "i8" | "int8" => print_values(Vec::<i8>::load_from(input)?),
+ "u8" | "uint8" => print_values(Vec::<u8>::load_from(input)?),
+ "i16" | "int16" => print_values(Vec::<i16>::load_from(input)?),
+ "u16" | "uint16" => print_values(Vec::<u16>::load_from(input)?),
+ "i32" | "int32" => print_values(Vec::<i32>::load_from(input)?),
+ "u32" | "uint32" => print_values(Vec::<u32>::load_from(input)?),
+ "i64" | "int64" => print_values(Vec::<i64>::load_from(input)?),
+ "u64" | "uint64" => print_values(Vec::<u64>::load_from(input)?),
+ "f32" | "float32" => print_values(Vec::<f32>::load_from(input)?),
+ "f64" | "float64" => print_values(Vec::<f64>::load_from(input)?),
+ _ => {
+ print_usage();
+ return Err(Box::new(CliErr("Invalid data type")));
}
},
_ => {
print_usage();
- Err(Box::new(CliErr("Invalid arguments")))
- },
- }
+ return Err(Box::new(CliErr("Invalid arguments")));
+ }
+ };
+ Ok(())
}
fn print_usage() {
- eprintln!("Usage: decode_vector data_type input_vector_file
+ eprintln!(
+ "Usage: decode_vector data_type input_vector_file
Reads binary data from input_vector_file and writes the data to the standard output. data_type can be one of
* i8
* f32
* f64
-");
+"
+ );
}
use std::fmt::Display;
-fn print_values<T>(values: Vec<T>) where
- T: Display
+fn print_values<T>(values: Vec<T>)
+where
+ T: Display,
{
for v in values {
println!("{}", v);
-extern crate stud_rust_base;
-use stud_rust_base::{io::*, cli::CliErr};
use std::{env, error::Error};
+use stud_rust_base::{cli::CliErr, io::*};
fn main() -> Result<(), Box<dyn Error>> {
- let mut args = env::args();
- args.next();
-
- match &args.collect::<Vec<String>>()[..] {
- [data_type, output] => {
+ let mut args = env::args().skip(1);
+ match (args.next(), args.next()) {
+ (Some(data_type), Some(ref output)) => {
match data_type.as_ref() {
- "i8" => { parse_input::<i8>()?.write_to(output)?; Ok(()) },
- "u8" => { parse_input::<u8>()?.write_to(output)?; Ok(()) },
- "i16" => { parse_input::<i16>()?.write_to(output)?; Ok(()) },
- "u16" => { parse_input::<u16>()?.write_to(output)?; Ok(()) },
- "i32" => { parse_input::<i32>()?.write_to(output)?; Ok(()) },
- "u32" => { parse_input::<u32>()?.write_to(output)?; Ok(()) },
- "i64" => { parse_input::<i64>()?.write_to(output)?; Ok(()) },
- "u64" => { parse_input::<u64>()?.write_to(output)?; Ok(()) },
- "f32" => { parse_input::<f32>()?.write_to(output)?; Ok(()) },
- "f64" => { parse_input::<f64>()?.write_to(output)?; Ok(()) },
- "int8" => { parse_input::<i8>()?.write_to(output)?; Ok(()) },
- "uint8" => { parse_input::<u8>()?.write_to(output)?; Ok(()) },
- "int16" => { parse_input::<i16>()?.write_to(output)?; Ok(()) },
- "uint16" => { parse_input::<u16>()?.write_to(output)?; Ok(()) },
- "int32" => { parse_input::<i32>()?.write_to(output)?; Ok(()) },
- "uint32" => { parse_input::<u32>()?.write_to(output)?; Ok(()) },
- "int64" => { parse_input::<i64>()?.write_to(output)?; Ok(()) },
- "uint64" => { parse_input::<u64>()?.write_to(output)?; Ok(()) },
- "float32" => { parse_input::<f32>()?.write_to(output)?; Ok(()) },
- "float64" => { parse_input::<f64>()?.write_to(output)?; Ok(()) },
+ "i8" | "int8" => parse_input::<i8>()?.write_to(output)?,
+ "u8" | "uint8" => parse_input::<u8>()?.write_to(output)?,
+ "i16" | "int16" => parse_input::<i16>()?.write_to(output)?,
+ "u16" | "uint16" => parse_input::<u16>()?.write_to(output)?,
+ "i32" | "int32" => parse_input::<i32>()?.write_to(output)?,
+ "u32" | "uint32" => parse_input::<u32>()?.write_to(output)?,
+ "i64" | "int64" => parse_input::<i64>()?.write_to(output)?,
+ "u64" | "uint64" => parse_input::<u64>()?.write_to(output)?,
+ "f32" | "float32" => parse_input::<f32>()?.write_to(output)?,
+ "f64" | "float64" => parse_input::<f64>()?.write_to(output)?,
_ => {
print_usage();
- Err(Box::new(CliErr("Invalid data type")))
+ return Err(Box::new(CliErr("Invalid data type")));
}
- }
- },
+ };
+ Ok(())
+ }
_ => {
print_usage();
Err(Box::new(CliErr("Invalid arguments")))
- },
+ }
}
}
use std::str::FromStr;
-fn parse_input<T>() -> Result<Vec<T>, Box<dyn Error>> where
+fn parse_input<T>() -> Result<Vec<T>, Box<dyn Error>>
+where
T: FromStr,
- <T as FromStr>::Err: Error + 'static
+ <T as FromStr>::Err: Error + 'static,
{
- use std::io::{BufRead, stdin};
+ use std::io::{stdin, BufRead};
let mut values = Vec::new();
-extern crate stud_rust_base;
+use stud_rust_base::{io::*, time::report_time, types::*};
-use stud_rust_base::{
- types::*,
- io::*,
- time::report_time,
-};
+use std::{env, error::Error, path::Path};
-use std::{env, path::Path};
-
-fn main() {
- let mut args = env::args();
- args.next();
-
- let arg = &args.next().expect("No directory arg given");
+fn main() -> Result<(), Box<dyn Error>> {
+ let arg = &env::args().nth(1).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(),
}
}
}
/// Updates the key of an element if the new key is smaller than the old key.
- /// Does nothing if the new key is larger.
- /// Panics if the element is not part of the queue.
+ /// Panics if the element is not part of the queue or if the new key is larger.
pub fn decrease_key(&mut self, element: T) {
let position = self.positions[element.as_index()];
+ assert!(element <= self.data[position]);
self.data[position] = element;
self.move_up_in_tree(position);
}
/// Updates the key of an element if the new key is larger than the old key.
- /// Does nothing if the new key is smaller.
- /// Panics if the element is not part of the queue.
+ /// Panics if the element is not part of the queue or if the new key is smaller.
pub fn increase_key(&mut self, element: T) {
let position = self.positions[element.as_index()];
+ assert!(element >= self.data[position]);
self.data[position] = element;
self.move_down_in_tree(position);
}
}
}
-
// 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
unsafe fn new(data: &'a mut [T], pos: usize) -> Self {
debug_assert!(pos < data.len());
let elt = ptr::read(&data[pos]);
- Hole {
- data,
- elt: Some(elt),
- pos,
- }
+ Hole { data, elt: Some(elt), pos }
}
/// Returns a reference to the element removed.
//! 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());
//! A small base framework for route planning student projects.
-extern crate time as time_crate;
-
pub mod cli;
pub mod index_heap;
pub mod io;
//! This module contains a few utilities to measure how long executing algorithms takes.
-//! It utilizes the `time` crate.
-use time_crate as time;
+use std::time::*;
/// This function will measure how long it takes to execute the given lambda,
/// print the time and return the result of the lambda.
pub fn report_time<Out, F: FnOnce() -> Out>(name: &str, f: F) -> Out {
- let start = time::now();
- println!("starting {}", name);
+ let start = Instant::now();
+ eprintln!("starting {}", name);
let res = f();
- println!("done {} - took: {}", name, (time::now() - start));
+ eprintln!("done {} - took: {}s", name, start.elapsed().as_secs_f64());
res
}
/// This function will measure how long it takes to execute the given lambda
/// and return a tuple of the result of the lambda and a duration object.
-pub fn measure<Out, F: FnOnce() -> Out>(f: F) -> (Out, time::Duration) {
- let start = time::now();
+pub fn measure<Out, F: FnOnce() -> Out>(f: F) -> (Out, Duration) {
+ let start = Instant::now();
let res = f();
- (res, time::now() - start)
+ (res, start.elapsed())
}
/// A struct to repeatedly measure the time passed since the timer was started
#[derive(Debug)]
pub struct Timer {
- start: time::Tm
+ start: Instant,
}
impl Default for Timer {
impl Timer {
/// Create and start a new `Timer`
pub fn new() -> Timer {
- Timer { start: time::now() }
+ Timer { start: Instant::now() }
}
/// Reset the `Timer`
pub fn restart(&mut self) {
- self.start = time::now();
+ self.start = Instant::now();
}
/// Print the passed time in ms since the timer was started
pub fn report_passed_ms(&self) {
- println!("{}ms", (time::now() - self.start).num_milliseconds());
+ eprintln!("{}ms", self.start.elapsed().as_secs_f64() * 1000.0);
}
/// Return the number of ms passed since the timer was started as a `i64`
- pub fn get_passed_ms(&self) -> i64 {
- (time::now() - self.start).num_milliseconds()
+ pub fn get_passed_ms(&self) -> f64 {
+ self.start.elapsed().as_secs_f64() * 1000.0
+ }
+
+ /// Return the number of ms passed since the timer was started as a `std::time::Duration`
+ pub fn get_passed(&self) -> Duration {
+ self.start.elapsed()
}
}