diff --git a/.gitea/workflows/cargo.yaml b/.gitea/workflows/cargo.yaml index 017d21c..f35cb90 100644 --- a/.gitea/workflows/cargo.yaml +++ b/.gitea/workflows/cargo.yaml @@ -16,9 +16,11 @@ jobs: - name: get repo uses: actions/checkout@v4 - name: install rust - uses: dtolnay/rust-toolchain@stable + uses: https://github.com/dtolnay/rust-toolchain@stable - name: install additional rust things - run: rustup component add rustfmt + run: | + rustup component add rustfmt + rustup component add clippy - name: config custom registry run: | mkdir -p ~/.cargo/ @@ -28,16 +30,16 @@ jobs: echo '[registries.cscherr]' >> ~/.cargo/config.toml echo 'index = "https://git.cscherr.de/PlexSheep/_cargo-index.git"' >> ~/.cargo/config.toml cat ~/.cargo/config.toml - - name: cargo check - run: cargo check --all-features --all-targets - - name: cargo fix - run: cargo fix --all-features --all-targets + - name: cargo clippy check + run: cargo clippy --all-features --all-targets + - name: cargo clippy fix + run: cargo clippy --fix --all-features --all-targets - name: cargo fmt run: cargo fmt --all - name: cargo test run: cargo test --all-features --all-targets - name: commit back to repository - uses: stefanzweifel/git-auto-commit-action@v5 + uses: https://github.com/stefanzweifel/git-auto-commit-action@v5 with: # Optional. Commit message for the created commit. # Defaults to "Apply automatic changes" diff --git a/.github/workflows/cargo.yaml b/.github/workflows/cargo.yaml new file mode 100644 index 0000000..ea06297 --- /dev/null +++ b/.github/workflows/cargo.yaml @@ -0,0 +1,47 @@ +name: cargo devel CI +on: + push: + branches: + - '**' + # - '!master' + +jobs: + CI: + runs-on: ubuntu-latest + name: cargo CI + permissions: + # Give the default GITHUB_TOKEN write permission to commit and push the + # added or changed files to the repository. + contents: write + steps: + - name: get repo + uses: actions/checkout@v4 + - name: install rust + uses: dtolnay/rust-toolchain@stable + - name: install additional rust things + run: | + rustup component add rustfmt + rustup component add clippy + - name: config custom registry + run: | + mkdir -p ~/.cargo/ + echo "" > ~/.cargo/config.toml + echo "[registry]" >> ~/.cargo/config.toml + echo 'cscherr = "cscherr"' >> ~/.cargo/config.toml + echo '[registries.cscherr]' >> ~/.cargo/config.toml + echo 'index = "https://git.cscherr.de/PlexSheep/_cargo-index.git"' >> ~/.cargo/config.toml + cat ~/.cargo/config.toml + - name: cargo clippy check + run: cargo clippy --all-features --all-targets + - name: cargo clippy fix + run: cargo clippy --fix --all-features --all-targets + - name: cargo fmt + run: cargo fmt --all + - name: cargo test + run: cargo test --all-features --all-targets + - name: commit back to repository + uses: stefanzweifel/git-auto-commit-action@v5 + with: + # Optional. Commit message for the created commit. + # Defaults to "Apply automatic changes" + commit_message: automatic cargo CI changes diff --git a/.github/workflows/maturin.yml b/.github/workflows/maturin.yml new file mode 100644 index 0000000..1bae4be --- /dev/null +++ b/.github/workflows/maturin.yml @@ -0,0 +1,120 @@ +# This file is autogenerated by maturin v1.4.0 +# To update, run +# +# maturin generate-ci github +# +name: CI + +on: + push: + branches: + - main + - master + tags: + - '*' + pull_request: + workflow_dispatch: + +permissions: + contents: read + +jobs: + linux: + runs-on: ubuntu-latest + strategy: + matrix: + target: [x86_64, x86, aarch64, armv7, s390x, ppc64le] + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-python@v4 + with: + python-version: '3.10' + - name: Build wheels + uses: PyO3/maturin-action@v1 + with: + target: ${{ matrix.target }} + args: --release --out dist --find-interpreter + sccache: 'true' + manylinux: auto + - name: Upload wheels + uses: actions/upload-artifact@v3 + with: + name: wheels + path: dist + + windows: + runs-on: windows-latest + strategy: + matrix: + target: [x64, x86] + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-python@v4 + with: + python-version: '3.10' + architecture: ${{ matrix.target }} + - name: Build wheels + uses: PyO3/maturin-action@v1 + with: + target: ${{ matrix.target }} + args: --release --out dist --find-interpreter + sccache: 'true' + - name: Upload wheels + uses: actions/upload-artifact@v3 + with: + name: wheels + path: dist + + macos: + runs-on: macos-latest + strategy: + matrix: + target: [x86_64, aarch64] + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-python@v4 + with: + python-version: '3.10' + - name: Build wheels + uses: PyO3/maturin-action@v1 + with: + target: ${{ matrix.target }} + args: --release --out dist --find-interpreter + sccache: 'true' + - name: Upload wheels + uses: actions/upload-artifact@v3 + with: + name: wheels + path: dist + + sdist: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Build sdist + uses: PyO3/maturin-action@v1 + with: + command: sdist + args: --out dist + - name: Upload sdist + uses: actions/upload-artifact@v3 + with: + name: wheels + path: dist + + release: + name: Release + runs-on: ubuntu-latest + if: "startsWith(github.ref, 'refs/tags/')" + needs: [linux, windows, macos, sdist] + steps: + - uses: actions/download-artifact@v3 + with: + name: wheels + - name: Publish to PyPI + uses: PyO3/maturin-action@v1 + env: + MATURIN_PYPI_TOKEN: ${{ secrets.PYPI_API_TOKEN }} + with: + command: upload + args: --non-interactive --skip-existing * diff --git a/.python-version b/.python-version new file mode 100644 index 0000000..871732e --- /dev/null +++ b/.python-version @@ -0,0 +1 @@ +rust diff --git a/Cargo.toml b/Cargo.toml index 1cdf892..e591a19 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,14 +3,14 @@ resolver = "2" members = [ ".", "members/libpt-core", - "members/libpt-math", "members/libpt-log", - "members/libpt-net", + "members/libpt-py", ] default-members = [".", "members/libpt-core"] + [workspace.package] publish = true -version = "0.3.11" +version = "0.4.0-alpha.1" edition = "2021" authors = ["Christoph J. Scherr "] license = "MIT" @@ -18,7 +18,7 @@ description = "Personal multitool" readme = "README.md" homepage = "https://git.cscherr.de/PlexSheep/pt" repository = "https://git.cscherr.de/PlexSheep/pt" -keywords = ["cli", "library"] +keywords = ["library"] categories = [ "command-line-utilities", "development-tools", @@ -28,11 +28,10 @@ categories = [ [workspace.dependencies] anyhow = "1.0.79" thiserror = "1.0.56" -libpt-core = { version = "0.3.11", path = "members/libpt-core" } -libpt-bintols = { version = "0.3.11", path = "members/libpt-bintols" } -libpt-log = { version = "0.3.11", path = "members/libpt-log" } -libpt-math = { version = "0.3.11", path = "members/libpt-math" } -libpt-net = { version = "0.3.11", path = "members/libpt-net" } +libpt-core = { version = "0.3.12", path = "members/libpt-core" } +libpt-bintols = { version = "0.3.12", path = "members/libpt-bintols" } +libpt-log = { version = "0.3.12", path = "members/libpt-log" } +libpt-py = { version = "0.3.12", path = "members/libpt-py" } [package] name = "libpt" @@ -49,13 +48,12 @@ keywords.workspace = true categories.workspace = true [features] -default = ["log", "core", "bin"] +default = ["log", "core"] core = [] -math = [] -log = [] -bintols = [] -net = [] -bin = ["dep:clap", "dep:clap-num", "dep:clap-verbosity-flag", "math", "bintols"] +full = ["default", "core", "log", "bintols"] +log = ["dep:libpt-log"] +bintols = ["dep:libpt-bintols", "log"] +# py = ["dep:libpt-py"] [lib] name = "libpt" @@ -65,23 +63,7 @@ crate-type = [ "rlib", ] -[[bin]] -name = "ccc" -path = "src/ccc/mod.rs" -required-features = ["bin", "math"] - -[[bin]] -name = "hedu" -path = "src/hedu/mod.rs" -required-features = ["bin", "bintols"] - - [dependencies] libpt-core = { workspace = true } -libpt-bintols = { workspace = true } -libpt-log = { workspace = true } -libpt-math = { workspace = true } -libpt-net = { workspace = true } -clap = { version = "4.4.4", features = ["derive"], optional = true } -clap-num = { version = "1.0.2", optional = true } -clap-verbosity-flag = { version = "2.0.1", optional = true } +libpt-bintols = { workspace = true, optional = true } +libpt-log = { workspace = true, optional = true } diff --git a/README.md b/README.md index 4c9a754..4f5336f 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,11 @@ # pt / libpt +![Project badge](https://img.shields.io/badge/language-Rust-blue.svg) +![Crates.io License](https://img.shields.io/crates/l/libpt) +![Gitea Release](https://img.shields.io/gitea/v/release/PlexSheep/pt?gitea_url=https%3A%2F%2Fgit.cscherr.de) +![Gitea language count](https://img.shields.io/gitea/languages/count/PlexSheep/pt?gitea_url=https%3A%2F%2Fgit.cscherr.de) +[![cargo checks and tests](https://github.com/PlexSheep/pt/actions/workflows/cargo.yaml/badge.svg)](https://github.com/PlexSheep/pt/actions/workflows/cargo.yaml) + ![pt-logo](data/media/pt-logo.svg) `pt` stands for either one of "personal tool", "plex tool", "pete" or something among those lines. @@ -9,6 +15,12 @@ crate, python module or executable. Let's see if I make it a bloated mess or stop committing after 30 hello worlds. +* [Original Repository](https://git.cscherr.de/PlexSheep/pt) +* [GitHub Mirror](https://github.com/PlexSheep/pt) +* [Codeberg Mirror](https://codeberg.org/PlexSheep/pt) +* [crates.io](https://crates.io/crates/libpt) +* [docs.rs](https://docs.rs/crate/libpt/) + ## Dependencies - See `cargo.toml` @@ -59,14 +71,6 @@ The documentation can be automatically generated with `cargo doc --open`. An up to date version of the Documentation can be found [here](https://docs.rs/libpt/) -## Mirrored - -The origin of this repository is [git.cscherr.de](https://git.cscherr.de/PlexSheep/pt) - -It is mirrored to: -- [Codeberg](https://codeberg.org/PlexSheep/pt) - - ## License **Pt is MIT Licensed** diff --git a/members/libpt-bintols/Cargo.toml b/members/libpt-bintols/Cargo.toml index 668a1a6..e40487b 100644 --- a/members/libpt-bintols/Cargo.toml +++ b/members/libpt-bintols/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "libpt-bintols" publish.workspace = true -version.workspace = true +version = "0.3.12" edition.workspace = true authors.workspace = true license.workspace = true diff --git a/members/libpt-bintols/src/display.rs b/members/libpt-bintols/src/display.rs index 949cbee..904190c 100644 --- a/members/libpt-bintols/src/display.rs +++ b/members/libpt-bintols/src/display.rs @@ -9,13 +9,13 @@ pub use num_traits::{PrimInt, ToPrimitive}; /// * `data` - The data you are trying to dump pub fn bytes_to_bin(data: &[u8]) -> String { let mut s = format!("0b{:08b}", data.first().unwrap()); - for i in 1..data.len() { - s.push_str(&format!("_{:08b}", data[i])); - if i % 8 == 0 { - s.push_str("\n") + for dat in data { + s.push_str(&format!("_{:08b}", dat)); + if dat % 8 == 0 { + s.push('\n') } } - return s; + s } /// Quickly format a number of Bytes [`usize`] with the corresponding @@ -34,17 +34,17 @@ where T: std::fmt::Debug, { if total < T::from(KIBI).unwrap() { - return format!("{total} B"); + format!("{total} B") } else if T::from(KIBI).unwrap() <= total && total < T::from(MEBI).unwrap() { - return format!("{:.2} K", total.to_f64().unwrap() / KIBI as f64); + format!("{:.2} K", total.to_f64().unwrap() / KIBI as f64) } else if T::from(MEBI).unwrap() <= total && total < T::from(GIBI).unwrap() { - return format!("{:.2} M", total.to_f64().unwrap() / MEBI as f64); + format!("{:.2} M", total.to_f64().unwrap() / MEBI as f64) } else if T::from(GIBI).unwrap() <= total && total < T::from(TEBI).unwrap() { - return format!("{:.2} G", total.to_f64().unwrap() / GIBI as f64); + format!("{:.2} G", total.to_f64().unwrap() / GIBI as f64) } else if T::from(TEBI).unwrap() <= total && total < T::from(PEBI).unwrap() { - return format!("{:.2} T", total.to_f64().unwrap() / TEBI as f64); + format!("{:.2} T", total.to_f64().unwrap() / TEBI as f64) } else if T::from(PEBI).unwrap() <= total && total < T::from(EXBI).unwrap() { - return format!("{:.2} P", total.to_f64().unwrap() / PEBI as f64); + format!("{:.2} P", total.to_f64().unwrap() / PEBI as f64) } // now we are starting to reach the sizes that are pretty unrealistic // (as of 2023 that is, hello future) @@ -53,9 +53,9 @@ where // to work with a fixed, larger sized datatype else { let total: u128 = total.to_u128().unwrap(); - if EXBI <= total && total < ZEBI { + if (EXBI..ZEBI).contains(&total) { return format!("{:.2} E", total.to_f64().unwrap() / EXBI as f64); - } else if ZEBI <= total && total < YOBI { + } else if (ZEBI..YOBI).contains(&total) { return format!("{:.2} Z", total.to_f64().unwrap() / ZEBI as f64); } else if YOBI <= total { return format!("{:.2} Y", total.to_f64().unwrap() / YOBI as f64); diff --git a/members/libpt-bintols/src/hedu/mod.rs b/members/libpt-bintols/src/hedu/mod.rs deleted file mode 100644 index 7d3e8a2..0000000 --- a/members/libpt-bintols/src/hedu/mod.rs +++ /dev/null @@ -1,239 +0,0 @@ -//! # Dump data -//! -//! This crate is part of [`pt`](../libpt/index.html), but can also be used as a standalone -//! module. -//! -//! Hedu is made for hexdumping data. `libpt` offers a cli application using this module. - -use crate::display::humanbytes; -use anyhow::{bail, Result}; -use libpt_log::{debug, error, trace, warn}; -use std::io::{prelude::*, Read, SeekFrom}; - -pub const BYTES_PER_LINE: usize = 16; -pub const LINE_SEP_HORIZ: char = '─'; -pub const LINE_SEP_VERT: char = '│'; -pub const CHAR_BORDER: &'static str = "|"; - -#[derive(Debug)] -pub struct Hedu { - pub chars: bool, - pub skip: usize, - pub show_identical: bool, - pub limit: usize, - stop: bool, - len: usize, - data_idx: usize, - rd_counter: usize, - buf: [[u8; BYTES_PER_LINE]; 2], - alt_buf: usize, - pub display_buf: String, - first_iter: bool, -} - -impl Hedu { - pub fn new(chars: bool, skip: usize, show_identical: bool, limit: usize) -> Self { - Hedu { - chars, - skip, - show_identical, - limit, - stop: false, - len: 0, - data_idx: 0, - rd_counter: 0, - buf: [[0; BYTES_PER_LINE]; 2], - alt_buf: 0, - display_buf: String::new(), - first_iter: true, - } - } - #[inline] - pub fn display(&mut self) { - println!("{}", self.display_buf); - self.display_buf = String::new(); - } - #[inline] - pub fn sep(&mut self) { - if self.chars { - self.display_buf += &format!("{LINE_SEP_HORIZ}").repeat(80); - } else { - self.display_buf += &format!("{LINE_SEP_HORIZ}").repeat(59); - } - self.display(); - } - #[inline] - pub fn newline(&mut self) { - self.display_buf += "\n"; - self.display(); - } - fn dump_a_line(&mut self) { - self.display_buf += &format!("{:08X} {LINE_SEP_VERT} ", self.data_idx); - if self.len != 0 { - for i in 0..self.len { - if i as usize % BYTES_PER_LINE == BYTES_PER_LINE / 2 { - self.display_buf += " "; - } - self.display_buf += &format!("{:02X} ", self.buf[self.alt_buf][i]); - } - if self.len == BYTES_PER_LINE / 2 { - self.display_buf += " " - } - for i in 0..(BYTES_PER_LINE - self.len) { - if i as usize % BYTES_PER_LINE == BYTES_PER_LINE / 2 { - self.display_buf += " "; - } - self.display_buf += " "; - } - } else { - self.display_buf += &format!("{:49}", ""); - } - if self.chars { - self.display_buf += &format!("{LINE_SEP_VERT} "); - if self.len != 0 { - self.display_buf += CHAR_BORDER; - for i in 0..self.len { - self.display_buf += - &format!("{}", mask_chars(self.buf[self.alt_buf][i] as char)); - } - self.display_buf += CHAR_BORDER; - } else { - self.display_buf += &format!("{:^8}", ""); - } - } - self.display(); - } - - fn skip_lines(&mut self, data: &mut dyn DataSource) -> Result<()> { - trace!(buf = format!("{:?}", self.buf), "found a duplicating line"); - let start_line = self.data_idx; - while self.buf[0] == self.buf[1] && self.len == BYTES_PER_LINE { - self.rd_data(data)?; - } - self.display_buf += &format!( - "******** {LINE_SEP_VERT} {:<49}", - format!( - "(repeats {} lines)", - self.data_idx - start_line / (BYTES_PER_LINE) + 1 - ) - ); - if self.chars { - self.display_buf += &format!("{LINE_SEP_VERT}"); - } - trace!( - buf = format!("{:X?}", self.buf), - "dumping buf after line skip" - ); - self.alt_buf ^= 1; // read into the other buf, so we can check for sameness - self.display(); - Ok(()) - } - pub fn dump(&mut self, data: &mut dyn DataSource) -> Result<()> { - // skip a given number of bytes - if self.skip > 0 { - data.skip(self.skip)?; - self.rd_counter += self.skip; - debug!( - data_idx = self.data_idx, - "Skipped {}", - humanbytes(self.skip) - ); - } - - // print the head - self.display_buf += &format!("DATA IDX {LINE_SEP_VERT} DATA AS HEX"); - if self.chars { - self.display_buf += &format!("{:width$} {LINE_SEP_VERT} DATA AS CHAR", "", width = 37); - } - self.display(); - self.sep(); - - // data dump loop - self.rd_data(data)?; - self.data_idx = 0; - while self.len > 0 || self.first_iter { - self.first_iter = false; - - self.dump_a_line(); - - // loop breaker logic - if self.stop || self.len < BYTES_PER_LINE { - break; - } - self.rd_data(data)?; - - // after line logic - if self.buf[0] == self.buf[1] && self.len == BYTES_PER_LINE && !self.show_identical { - self.skip_lines(data)?; - } - } - self.data_idx += BYTES_PER_LINE; - - self.sep(); - self.display_buf += &format!( - "{:08X} {LINE_SEP_VERT} read total:\t\t {:<8} {:<15}", - self.rd_counter, - humanbytes(self.rd_counter), - format!("({} B)", self.rd_counter) - ); - if self.chars { - self.display_buf += &format!("{LINE_SEP_VERT}"); - } - self.display(); - Ok(()) - } - #[inline] - fn adjust_counters(&mut self) { - self.rd_counter += self.len; - self.data_idx += self.len; - } - - fn rd_data(&mut self, data: &mut dyn DataSource) -> Result<()> { - match data.read(&mut self.buf[self.alt_buf]) { - Ok(mut len) => { - if self.limit != 0 && self.rd_counter + (BYTES_PER_LINE - 1) >= self.limit { - len = self.limit % BYTES_PER_LINE; - self.stop = true; - } - self.len = len; - self.adjust_counters(); - return Ok(()); - } - Err(err) => { - error!("error while reading data: {err}"); - bail!(err) - } - } - } -} - -pub trait DataSource: Read { - fn skip(&mut self, length: usize) -> std::io::Result<()>; -} -impl DataSource for std::io::Stdin { - fn skip(&mut self, _length: usize) -> std::io::Result<()> { - warn!("can't skip bytes for the stdin!"); - Ok(()) - } -} -impl DataSource for std::fs::File { - fn skip(&mut self, length: usize) -> std::io::Result<()> { - self.seek(SeekFrom::Current(length as i64))?; - // returns the new position from the start, we don't need it here. - Ok(()) - } -} - -fn mask_chars(c: char) -> char { - if c.is_ascii_graphic() { - return c; - } else if c == '\n' { - return '↩'; - } else if c == ' ' { - return '␣'; - } else if c == '\t' { - return '⭾'; - } else { - return '�'; - } -} diff --git a/members/libpt-bintols/src/lib.rs b/members/libpt-bintols/src/lib.rs index 36aa2bb..ca13f78 100644 --- a/members/libpt-bintols/src/lib.rs +++ b/members/libpt-bintols/src/lib.rs @@ -25,4 +25,3 @@ pub const YOBI: u128 = 2u128.pow(80); // use libpt_core; pub mod datalayout; pub mod display; -pub mod hedu; diff --git a/members/libpt-bintols/tests/datalayout.rs b/members/libpt-bintols/tests/datalayout.rs index 30a2012..3fe86c4 100644 --- a/members/libpt-bintols/tests/datalayout.rs +++ b/members/libpt-bintols/tests/datalayout.rs @@ -2,6 +2,6 @@ use libpt_bintols::*; #[test] fn mkdmp() { - let v = vec![true, true, false]; + let v = [true, true, false]; investigate_memory_layout!(bool, v); } diff --git a/members/libpt-core/Cargo.toml b/members/libpt-core/Cargo.toml index cacd5b9..f9cf89b 100644 --- a/members/libpt-core/Cargo.toml +++ b/members/libpt-core/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "libpt-core" publish.workspace = true -version.workspace = true +version = "0.3.12" edition.workspace = true authors.workspace = true license.workspace = true diff --git a/members/libpt-core/src/lib.rs b/members/libpt-core/src/lib.rs index 4844585..3245b8c 100644 --- a/members/libpt-core/src/lib.rs +++ b/members/libpt-core/src/lib.rs @@ -6,33 +6,7 @@ //! This crate implements core functionality useful for many use cases, such as macros, //! formatting functions and more. -//// ATTRIBUTES //////////////////////////////////////////////////////////////////////////////////// -// we want docs -#![warn(missing_docs)] -#![warn(rustdoc::missing_crate_level_docs)] -//////////////////////////////////////////////////////////////////////////////////////////////////// -// we want Debug everywhere. -#![warn(missing_debug_implementations)] -//////////////////////////////////////////////////////////////////////////////////////////////////// -// enable clippy's extra lints, the pedantic version -#![warn(clippy::pedantic)] - -//// IMPORTS /////////////////////////////////////////////////////////////////////////////////////// /// macros to make things faster in your code pub mod macros; /// some general use printing to stdout tools pub mod printing; - -//// CONSTANTS ///////////////////////////////////////////////////////////////////////////////////// - -//// STATICS /////////////////////////////////////////////////////////////////////////////////////// - -//// ENUMS ///////////////////////////////////////////////////////////////////////////////////////// - -//// STRUCTS /////////////////////////////////////////////////////////////////////////////////////// - -//// IMPLEMENTATION //////////////////////////////////////////////////////////////////////////////// - -//// PUBLIC FUNCTIONS ////////////////////////////////////////////////////////////////////////////// - -//// PRIVATE FUNCTIONS ///////////////////////////////////////////////////////////////////////////// diff --git a/members/libpt-core/src/macros.rs b/members/libpt-core/src/macros.rs index cb9385b..be5857b 100644 --- a/members/libpt-core/src/macros.rs +++ b/members/libpt-core/src/macros.rs @@ -2,33 +2,14 @@ //! //! This module implements macros for use with `libpt`. -//// ATTRIBUTES //////////////////////////////////////////////////////////////////////////////////// -// we want docs -#![warn(missing_docs)] -#![warn(rustdoc::missing_crate_level_docs)] -//////////////////////////////////////////////////////////////////////////////////////////////////// -// we want Debug everywhere. -#![warn(missing_debug_implementations)] -//////////////////////////////////////////////////////////////////////////////////////////////////// -// enable clippy's extra lints, the pedantic version -#![warn(clippy::pedantic)] - -//// IMPORTS /////////////////////////////////////////////////////////////////////////////////////// pub use crate::get_stdout_for; -//// CONSTANTS ///////////////////////////////////////////////////////////////////////////////////// - -//// STATICS /////////////////////////////////////////////////////////////////////////////////////// - -//// MACROS //////////////////////////////////////////////////////////////////////////////////////// /// ## catches what the expression would write to the `stdout` /// /// This macro takes an expression, executes it, and catches what it would write to the stdout. /// The buffer of the stdout will then be returned for further use. /// /// This is especially useful when testing loggers or other frontend CLI functions. -/// -/// Inspiration: [users.rust-lang.org](https://users.rust-lang.org/t/how-to-test-functions-that-use-println/67188/5) #[macro_export] macro_rules! get_stdout_for { ($test:expr) => {{ @@ -46,13 +27,3 @@ macro_rules! get_stdout_for { output }}; } - -//// ENUMS ///////////////////////////////////////////////////////////////////////////////////////// - -//// STRUCTS /////////////////////////////////////////////////////////////////////////////////////// - -//// IMPLEMENTATION //////////////////////////////////////////////////////////////////////////////// - -//// PUBLIC FUNCTIONS ////////////////////////////////////////////////////////////////////////////// - -//// PRIVATE FUNCTIONS ///////////////////////////////////////////////////////////////////////////// diff --git a/members/libpt-core/src/printing.rs b/members/libpt-core/src/printing.rs index c1d5bf4..808de0b 100644 --- a/members/libpt-core/src/printing.rs +++ b/members/libpt-core/src/printing.rs @@ -1,49 +1,11 @@ //! # tools that make printing stuff better -//// ATTRIBUTES //////////////////////////////////////////////////////////////////////////////////// -// we want docs -#![warn(missing_docs)] -#![warn(rustdoc::missing_crate_level_docs)] -// we want Debug everywhere. -#![warn(missing_debug_implementations)] -// enable clippy's extra lints, the pedantic version -#![warn(clippy::pedantic)] - -//// IMPORTS /////////////////////////////////////////////////////////////////////////////////////// -// reimport our macros to this module, so the user does not get confused when importing the macros -pub use crate::divider; -pub use crate::print_divider; - -//// TYPES ///////////////////////////////////////////////////////////////////////////////////////// - -//// CONSTANTS ///////////////////////////////////////////////////////////////////////////////////// - -//// STATICS /////////////////////////////////////////////////////////////////////////////////////// - -//// MACROS //////////////////////////////////////////////////////////////////////////////////////// /// Quickly get a one line visual divider -#[macro_export] -macro_rules! divider { - () => {{ - format!("{:=^80}", "=") - }}; +pub fn divider() -> String { + format!("{:=^80}", "=") } -//////////////////////////////////////////////////////////////////////////////////////////////////// /// Quickly print a one line visual divider -#[macro_export] -macro_rules! print_divider { - () => {{ - println!("{}", divider!()) - }}; +pub fn print_divider() { + println!("{:=^80}", "=") } - -//// ENUMS ///////////////////////////////////////////////////////////////////////////////////////// - -//// STRUCTS /////////////////////////////////////////////////////////////////////////////////////// - -//// IMPLEMENTATION //////////////////////////////////////////////////////////////////////////////// - -//// PUBLIC FUNCTIONS ////////////////////////////////////////////////////////////////////////////// - -//// PRIVATE FUNCTIONS ///////////////////////////////////////////////////////////////////////////// diff --git a/members/libpt-log/Cargo.toml b/members/libpt-log/Cargo.toml index a36149c..f71b73a 100644 --- a/members/libpt-log/Cargo.toml +++ b/members/libpt-log/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "libpt-log" publish.workspace = true -version.workspace = true +version = "0.3.12" edition.workspace = true authors.workspace = true license.workspace = true diff --git a/members/libpt-log/src/error.rs b/members/libpt-log/src/error.rs index 780885c..8119790 100644 --- a/members/libpt-log/src/error.rs +++ b/members/libpt-log/src/error.rs @@ -2,70 +2,22 @@ //! //! This module handles errors in logging contexts. -//// ATTRIBUTES //////////////////////////////////////////////////////////////////////////////////// -// we want docs -#![warn(missing_docs)] -#![warn(rustdoc::missing_crate_level_docs)] -// we want Debug everywhere. -#![warn(missing_debug_implementations)] -// enable clippy's extra lints, the pedantic version -#![warn(clippy::pedantic)] - -//// IMPORTS /////////////////////////////////////////////////////////////////////////////////////// use anyhow; use thiserror::Error; use tracing::subscriber::SetGlobalDefaultError; - -//// TYPES ///////////////////////////////////////////////////////////////////////////////////////// - -//// CONSTANTS ///////////////////////////////////////////////////////////////////////////////////// - -//// STATICS /////////////////////////////////////////////////////////////////////////////////////// - -//// MACROS //////////////////////////////////////////////////////////////////////////////////////// - -//// ENUMS ///////////////////////////////////////////////////////////////////////////////////////// /// ## Errors for the [Logger](super::Logger) -#[derive(Error)] +#[derive(Error, Debug)] pub enum Error { /// Bad IO operation #[error("Bad IO operation")] - IO(std::io::Error), + IO(#[from] std::io::Error), /// Various errors raised when the messenger is used in a wrong way #[error("Bad usage")] Usage(String), /// Could not assign logger as the global default - #[error("Could not assign as global default")] // TODO: make this more clear - SetGlobalDefaultFail(SetGlobalDefaultError), + #[error("Could not assign logger as global default")] + SetGlobalDefaultFail(#[from] SetGlobalDefaultError), + /// any other error type, wrapped in [anyhow::Error](anyhow::Error) + #[error(transparent)] + Other(#[from] anyhow::Error), } - -//// STRUCTS /////////////////////////////////////////////////////////////////////////////////////// - -//// IMPLEMENTATION //////////////////////////////////////////////////////////////////////////////// -impl From for Error { - fn from(value: std::io::Error) -> Self { - Error::IO(value) - } -} - -//////////////////////////////////////////////////////////////////////////////////////////////////// -impl From for Error { - fn from(value: SetGlobalDefaultError) -> Self { - Error::SetGlobalDefaultFail(value) - } -} - -//////////////////////////////////////////////////////////////////////////////////////////////////// -impl std::fmt::Debug for Error { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - Error::IO(e) => write!(f, ""), - Error::Usage(e) => write!(f, ""), - Error::SetGlobalDefaultFail(e) => write!(f, ""), - } - } -} - -//// PUBLIC FUNCTIONS ////////////////////////////////////////////////////////////////////////////// - -//// PRIVATE FUNCTIONS ///////////////////////////////////////////////////////////////////////////// diff --git a/members/libpt-log/src/lib.rs b/members/libpt-log/src/lib.rs index 242cc6c..1a06b08 100644 --- a/members/libpt-log/src/lib.rs +++ b/members/libpt-log/src/lib.rs @@ -14,12 +14,8 @@ //! - [`tracing_appender`]: Used to log to files //! - [`tracing_subscriber`]: Used to do actual logging, formatting, to stdout -//// ATTRIBUTES //////////////////////////////////////////////////////////////////////////////////// - -//// IMPORTS /////////////////////////////////////////////////////////////////////////////////////// use std::{ fmt, - ops::Deref, path::PathBuf, sync::atomic::{AtomicBool, Ordering}, }; @@ -28,55 +24,34 @@ pub mod error; use error::*; pub use tracing::{debug, error, info, trace, warn, Level}; -use tracing_appender::{ - self, - non_blocking::{NonBlocking, WorkerGuard}, -}; -use tracing_subscriber::{ - fmt::{ - format::FmtSpan, - time::{self, FormatTime}, - }, - prelude::*, -}; +use tracing_appender::{self, non_blocking::NonBlocking}; +use tracing_subscriber::fmt::{format::FmtSpan, time}; use anyhow::{bail, Result}; - -//// CONSTANTS ///////////////////////////////////////////////////////////////////////////////////// /// The log level used when none is specified pub const DEFAULT_LOG_LEVEL: Level = Level::INFO; /// The path where logs are stored when no path is given. /// /// Currently, this is `/dev/null`, meaning they will be written to the void = discarded. -pub const DEFAULT_LOG_DIR: &'static str = "/dev/null"; +pub const DEFAULT_LOG_DIR: &str = "/dev/null"; -//// STATICS /////////////////////////////////////////////////////////////////////////////////////// static INITIALIZED: AtomicBool = AtomicBool::new(false); -//// STRUCTS /////////////////////////////////////////////////////////////////////////////////////// /// ## Logger for [`pt`](../libpt/index.html) /// /// This struct exists mainly for the python module, so that we can use the same logger with both /// python and rust. pub struct Logger; -//// IMPLEMENTATION //////////////////////////////////////////////////////////////////////////////// /// ## Main implementation impl Logger { - /// ## create a `Logger` - /// - /// Creates a new uninitialized [`Logger`] object. - pub fn new() -> Self { - let l = Logger {}; - l - } /// ## initializes the logger /// /// Will enable the logger to be used. /// /// Assumes some defaults, use [`init_customized`](Self::init_customized) for more control - pub fn init(log_dir: Option, max_level: Option, uptime: bool) -> Result<()> { - Self::init_customized( + pub fn build(log_dir: Option, max_level: Option, uptime: bool) -> Result { + Self::build_customized( log_dir.is_some(), log_dir.unwrap_or(PathBuf::from(DEFAULT_LOG_DIR)), true, @@ -99,8 +74,8 @@ impl Logger { /// useful in cases with only one sender to the logging framework. /// /// Assumes some defaults, use [`init_customized`](Self::init_customized) for more control - pub fn init_mini(max_level: Option) -> Result<()> { - Self::init_customized( + pub fn build_mini(max_level: Option) -> Result { + Self::build_customized( false, PathBuf::from(DEFAULT_LOG_DIR), true, @@ -117,10 +92,12 @@ impl Logger { ) } + // TODO: make the args a struct for easy access + // /// ## initializes the logger /// /// Will enable the logger to be used. - pub fn init_customized( + pub fn build_customized( log_to_file: bool, log_dir: PathBuf, ansi: bool, @@ -134,11 +111,11 @@ impl Logger { pretty: bool, show_time: bool, uptime: bool, // uptime instead of system time - ) -> Result<()> { + ) -> Result { // only init if no init has been performed yet if INITIALIZED.load(Ordering::Relaxed) { warn!("trying to reinitialize the logger, ignoring"); - bail!(Error::Usage(format!("logging is already initialized"))); + bail!(Error::Usage("logging is already initialized".to_string())); } let subscriber = tracing_subscriber::fmt::Subscriber::builder() .with_level(display_level) @@ -222,7 +199,7 @@ impl Logger { } } INITIALIZED.store(true, Ordering::Relaxed); - Ok(()) + Ok(Logger {}) } /// ## logging at [`Level::ERROR`] @@ -262,7 +239,6 @@ impl Logger { } } -//////////////////////////////////////////////////////////////////////////////////////////////////// impl fmt::Debug for Logger { /// ## DEBUG representation for [`Logger`] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { @@ -274,10 +250,7 @@ impl fmt::Debug for Logger { } } -//// PUBLIC FUNCTIONS ////////////////////////////////////////////////////////////////////////////// - -//// PRIVATE FUNCTIONS ///////////////////////////////////////////////////////////////////////////// fn new_file_appender(log_dir: PathBuf) -> NonBlocking { let file_appender = tracing_appender::rolling::daily(log_dir.clone(), "log"); - return tracing_appender::non_blocking(file_appender).0; + tracing_appender::non_blocking(file_appender).0 } diff --git a/members/libpt-math/Cargo.toml b/members/libpt-math/Cargo.toml deleted file mode 100644 index 34b56d1..0000000 --- a/members/libpt-math/Cargo.toml +++ /dev/null @@ -1,21 +0,0 @@ -[package] -name = "libpt-math" -publish.workspace = true -version.workspace = true -edition.workspace = true -authors.workspace = true -license.workspace = true -description.workspace = true -readme.workspace = true -homepage.workspace = true -repository.workspace = true -keywords.workspace = true -categories.workspace = true - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -num = "0.4.1" -num-traits = "0.2.16" -libpt-core = { workspace = true } -libpt-log = { workspace = true } diff --git a/members/libpt-math/src/ccc/mod.rs b/members/libpt-math/src/ccc/mod.rs deleted file mode 100644 index 84efe1f..0000000 --- a/members/libpt-math/src/ccc/mod.rs +++ /dev/null @@ -1,41 +0,0 @@ -//! # Calculate expressions -//! -//! This crate is part of [`pt`](../libpt/index.html), but can also be used as a standalone -//! module. -//! -//! Calculate Calculations with your Calculator (`ccc`) -//! -//! This modules aim is to take a term of any kind ([String]) and calculate it's value, be it -//! variable based or a concrete numerical value. It implements different operators and -//! (mathematical) functions. - -//// ATTRIBUTES //////////////////////////////////////////////////////////////////////////////////// -// we want docs -#![warn(missing_docs)] -#![warn(rustdoc::missing_crate_level_docs)] -// we want Debug everywhere. -#![warn(missing_debug_implementations)] -// enable clippy's extra lints, the pedantic version -#![warn(clippy::pedantic)] - -//// IMPORTS /////////////////////////////////////////////////////////////////////////////////////// - -//// TYPES ///////////////////////////////////////////////////////////////////////////////////////// - -//// CONSTANTS ///////////////////////////////////////////////////////////////////////////////////// - -//// STATICS /////////////////////////////////////////////////////////////////////////////////////// - -//// MACROS //////////////////////////////////////////////////////////////////////////////////////// - -//// ENUMS ///////////////////////////////////////////////////////////////////////////////////////// - -//// STRUCTS /////////////////////////////////////////////////////////////////////////////////////// - -//// IMPLEMENTATION //////////////////////////////////////////////////////////////////////////////// - -//// PUBLIC FUNCTIONS ////////////////////////////////////////////////////////////////////////////// - -//// PRIVATE FUNCTIONS ///////////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/members/libpt-math/src/lib.rs b/members/libpt-math/src/lib.rs deleted file mode 100644 index dbafa06..0000000 --- a/members/libpt-math/src/lib.rs +++ /dev/null @@ -1,38 +0,0 @@ -//! # General Mathmatics functionalities -//! -//! This crate is part of [`pt`](../libpt/index.html), but can also be used as a standalone -//! module. -//! -//! This module is currently empty, but will contain many math functionalities in a future version. - -//// ATTRIBUTES //////////////////////////////////////////////////////////////////////////////////// -// we want docs -#![warn(missing_docs)] -#![warn(rustdoc::missing_crate_level_docs)] -// we want Debug everywhere. -#![warn(missing_debug_implementations)] -// enable clippy's extra lints, the pedantic version -#![warn(clippy::pedantic)] - -//// IMPORTS /////////////////////////////////////////////////////////////////////////////////////// -pub mod ccc; - -//// TYPES ///////////////////////////////////////////////////////////////////////////////////////// - -//// CONSTANTS ///////////////////////////////////////////////////////////////////////////////////// - -//// STATICS /////////////////////////////////////////////////////////////////////////////////////// - -//// MACROS //////////////////////////////////////////////////////////////////////////////////////// - -//// ENUMS ///////////////////////////////////////////////////////////////////////////////////////// - -//// STRUCTS /////////////////////////////////////////////////////////////////////////////////////// - -//// IMPLEMENTATION //////////////////////////////////////////////////////////////////////////////// - -//// PUBLIC FUNCTIONS ////////////////////////////////////////////////////////////////////////////// - -//// PRIVATE FUNCTIONS ///////////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/members/libpt-net/Cargo.toml b/members/libpt-net/Cargo.toml deleted file mode 100644 index 4a4e4bf..0000000 --- a/members/libpt-net/Cargo.toml +++ /dev/null @@ -1,24 +0,0 @@ -[package] -name = "libpt-net" -publish.workspace = true -version.workspace = true -edition.workspace = true -authors.workspace = true -license.workspace = true -description.workspace = true -readme.workspace = true -homepage.workspace = true -repository.workspace = true -keywords.workspace = true -categories.workspace = true - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -humantime = "2.1.0" -libpt-core = { workspace = true } -libpt-log = { workspace = true } -libpt-math = { workspace = true } -reqwest = { version = "0.11.20", features = ["blocking"] } -serde = { version = "1.0.188", features = ["serde_derive"] } -serde_json = "1.0.107" diff --git a/members/libpt-net/src/lib.rs b/members/libpt-net/src/lib.rs deleted file mode 100644 index f00c877..0000000 --- a/members/libpt-net/src/lib.rs +++ /dev/null @@ -1,40 +0,0 @@ -//! # various networking tools -//! -//! This crate is part of [`pt`](../libpt/index.html), but can also be used as a standalone -//! module. -//! -//! The networking module contains various tools related to connections. For example, it contains a -//! tool that has the purpose to check if your connection is consistently available. - -//// ATTRIBUTES //////////////////////////////////////////////////////////////////////////////////// -// we want docs -#![warn(missing_docs)] -#![warn(rustdoc::missing_crate_level_docs)] -//////////////////////////////////////////////////////////////////////////////////////////////////// -// we want Debug everywhere. -#![warn(missing_debug_implementations)] -//////////////////////////////////////////////////////////////////////////////////////////////////// -// enable clippy's extra lints, the pedantic version -#![warn(clippy::pedantic)] - -//// IMPORTS /////////////////////////////////////////////////////////////////////////////////////// -/// monitor your connection -pub mod monitoring; - -//// CONSTANTS ///////////////////////////////////////////////////////////////////////////////////// -/// how long to wait for a remove server to respond in ms -pub const DEFAULT_REQUEST_TIMEOUT: u64 = 2000; - -//// STATICS /////////////////////////////////////////////////////////////////////////////////////// - -//// MACROS //////////////////////////////////////////////////////////////////////////////////////// - -//// ENUMS ///////////////////////////////////////////////////////////////////////////////////////// - -//// STRUCTS /////////////////////////////////////////////////////////////////////////////////////// - -//// IMPLEMENTATION //////////////////////////////////////////////////////////////////////////////// - -//// PUBLIC FUNCTIONS ////////////////////////////////////////////////////////////////////////////// - -//// PRIVATE FUNCTIONS ///////////////////////////////////////////////////////////////////////////// diff --git a/members/libpt-net/src/monitoring/mod.rs b/members/libpt-net/src/monitoring/mod.rs deleted file mode 100644 index 306c78f..0000000 --- a/members/libpt-net/src/monitoring/mod.rs +++ /dev/null @@ -1,33 +0,0 @@ -//! # monitor your network -//! -//! This module offers functions to monitor your network. - -//// ATTRIBUTES //////////////////////////////////////////////////////////////////////////////////// -// we want docs -#![warn(missing_docs)] -#![warn(rustdoc::missing_crate_level_docs)] -//////////////////////////////////////////////////////////////////////////////////////////////////// -// we want Debug everywhere. -#![warn(missing_debug_implementations)] -//////////////////////////////////////////////////////////////////////////////////////////////////// -// enable clippy's extra lints, the pedantic version -#![warn(clippy::pedantic)] - -//// IMPORTS /////////////////////////////////////////////////////////////////////////////////////// -pub mod uptime; - -//// CONSTANTS ///////////////////////////////////////////////////////////////////////////////////// - -//// STATICS /////////////////////////////////////////////////////////////////////////////////////// - -//// MACROS //////////////////////////////////////////////////////////////////////////////////////// - -//// ENUMS ///////////////////////////////////////////////////////////////////////////////////////// - -//// STRUCTS /////////////////////////////////////////////////////////////////////////////////////// - -//// IMPLEMENTATION //////////////////////////////////////////////////////////////////////////////// - -//// PUBLIC FUNCTIONS ////////////////////////////////////////////////////////////////////////////// - -//// PRIVATE FUNCTIONS ///////////////////////////////////////////////////////////////////////////// diff --git a/members/libpt-net/src/monitoring/uptime.rs b/members/libpt-net/src/monitoring/uptime.rs deleted file mode 100644 index 21b55f8..0000000 --- a/members/libpt-net/src/monitoring/uptime.rs +++ /dev/null @@ -1,275 +0,0 @@ -//! # monitor your network uptime -//! -//! This method offers a way to monitor your networks/hosts uptime. This is achieved by making -//! HTTPS requests to a given list of -//! -//! Warning: This module is not unit tested. - -//// ATTRIBUTES //////////////////////////////////////////////////////////////////////////////////// -// we want docs -#![warn(missing_docs)] -#![warn(rustdoc::missing_crate_level_docs)] -//////////////////////////////////////////////////////////////////////////////////////////////////// -// we want Debug everywhere. -#![warn(missing_debug_implementations)] -//////////////////////////////////////////////////////////////////////////////////////////////////// -// enable clippy's extra lints, the pedantic version -#![warn(clippy::pedantic)] - -use std::{fmt, time::Duration}; - -//// IMPORTS /////////////////////////////////////////////////////////////////////////////////////// -use libpt_log::*; - -use reqwest; - -use humantime::{format_duration, format_rfc3339}; -use std::time::SystemTime; - -use serde::{Deserialize, Serialize}; -use serde_json; - -use libpt_core::divider; - -//// TYPES ///////////////////////////////////////////////////////////////////////////////////////// - -//// CONSTANTS ///////////////////////////////////////////////////////////////////////////////////// -/// urls used for checking by default -pub const DEFAULT_CHECK_URLS: &'static [&'static str] = - &["https://www.cscherr.de", "https://www.cloudflare.com"]; - -//// STATICS /////////////////////////////////////////////////////////////////////////////////////// - -//// MACROS //////////////////////////////////////////////////////////////////////////////////////// - -//// ENUMS ///////////////////////////////////////////////////////////////////////////////////////// - -//// STRUCTS /////////////////////////////////////////////////////////////////////////////////////// -/// ## Describes an uptime status -/// -/// [`UptimeStatus`] describes the result of an uptime check. -#[derive(Serialize, Deserialize)] -pub struct UptimeStatus { - /// true if the [`UptimeStatus`] is considered successful - pub success: bool, - /// the percentage of reachable urls out of the total urls - pub success_ratio: u8, - /// the percentage of reachable urls out of the total urls that need to be reachable in order - /// for this [`UptimeStatus`] to be considered a success. - pub success_ratio_target: u8, - /// the number of reachable [`urls`](UptimeStatus::urls) - pub reachable: usize, - /// which urls to check in [`check()`](UptimeStatus::check) - pub urls: Vec, - /// timeout length for requests (in ms) - pub timeout: u64, -} - -//// IMPLEMENTATION //////////////////////////////////////////////////////////////////////////////// -/// Main implementation -impl UptimeStatus { - /// ## create a new `UptimeStatus` and perform it's check - pub fn new(success_ratio_target: u8, urls: Vec, timeout: u64) -> Self { - assert!(success_ratio_target <= 100); - let mut status = UptimeStatus { - success: false, - success_ratio: 0, - success_ratio_target, - reachable: 0, - urls, - timeout, - }; - status.urls.dedup(); - - status.check(); - - return status; - } - - /// ## check for success with the given urls - /// - /// Makes the actual https requests and updates fields accordingly. - /// - /// Note: Blocking execution for all requests, timeout is set to - /// [REQUEST_TIMEOUT](crate::networking::REQUEST_TIMEOUT). - pub fn check(&mut self) { - self.reachable = 0; - self.urls.iter().for_each(|url| { - let client = reqwest::blocking::Client::builder() - .timeout(Duration::from_millis(self.timeout)) - .build() - .expect("could not build a client for https requests"); - let response = client.get(url.clone()).send(); - if response.is_ok() { - self.reachable += 1 - } - }); - self.calc_success(); - } - - /// ## calculate the success based on the `reachable` and `total` - /// - /// Calculates the ratio of [`reachable`](UptimeStatus::reachable) / - /// (length of [urls](UptimeStatus::urls)). - /// - /// Calculates a [`success_ratio`](UptimeStatus::success_ratio) (as [u8]) from that, - /// by multiplying with 100, then flooring. - /// - /// If the [`success_ratio`](UptimeStatus::success_ratio) is greater than or equal to the - /// [`success_ratio_target`](UptimeStatus::success_ratio_target), the [`UptimeStatus`] will be - /// considered a success. - /// - /// In the special case that no URLs to check for have been provided, the check will be - /// considered a success, but the [`success_ratio`](UptimeStatus::success_ratio) will be `0`. - /// - /// Note: does not check for networking, use [`check()`](UptimeStatus::check) for that. - pub fn calc_success(&mut self) { - // if no urls need to be checked, success without checking - if self.urls.len() == 0 { - self.success = true; - self.success_ratio = 0; - return; - } - let ratio: f32 = (self.reachable as f32) / (self.urls.len() as f32) * 100f32; - trace!("calculated success_ratio: {}", ratio); - self.success_ratio = ratio.floor() as u8; - self.success = self.success_ratio >= self.success_ratio_target; - trace!("calculated success as: {}", self.success) - } -} - -//////////////////////////////////////////////////////////////////////////////////////////////////// -impl fmt::Debug for UptimeStatus { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let mut urls: Vec<&str> = Vec::new(); - for url in &self.urls { - urls.push(url.as_str()); - } - write!(f, "{}", serde_json::to_string(self).unwrap()) - } -} - -//////////////////////////////////////////////////////////////////////////////////////////////////// -impl fmt::Display for UptimeStatus { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let mut urls: Vec<&str> = Vec::new(); - for url in &self.urls { - urls.push(url.as_str()); - } - write!(f, "{}", serde_json::to_string_pretty(self).unwrap()) - } -} - -//// PUBLIC FUNCTIONS ////////////////////////////////////////////////////////////////////////////// -/// ## Uptime monitor -/// -/// This function continuously monitors the uptime of your host/network. -/// -/// On change of status, an update will be logged at [INFO Level](log::Level::Info), containing -/// information on your current status, including timestamps of the last up/down time and durations -/// since. -pub fn continuous_uptime_monitor( - success_ratio_target: u8, - urls: Vec, - interval: u64, - timeout: u64, -) { - if urls.len() == 0 { - error!("No URLs provided. There is nothing to monitor."); - return; - } - - let interval = std::time::Duration::from_millis(interval); - let mut last_downtime: Option = None; - let mut last_uptime: Option = None; - let mut status = UptimeStatus::new(success_ratio_target, urls, timeout); - // we assume that the last status was up, so the binary shows the first status if its a - // failure. - let mut last_was_up: bool = true; - let mut last_ratio: u8 = status.success_ratio; - loop { - trace!( - ?status, - ?last_was_up, - "loop iteration for continuous uptime monitor" - ); - if !status.success { - if last_was_up { - trace!("displaying status"); - display_uptime_status("fail", last_uptime, last_downtime, &status) - } - last_downtime = Some(SystemTime::now()); - last_was_up = false; - } else if status.success_ratio < 100 { - if status.success_ratio != last_ratio { - let msg = format!( - "uptime check: not all urls are reachable ({}%)", - status.success_ratio - ); - display_uptime_status(&msg, last_uptime, last_downtime, &status) - } - last_uptime = Some(SystemTime::now()); - last_was_up = true; - } else { - if !last_was_up { - display_uptime_status("success", last_uptime, last_downtime, &status) - } - last_uptime = Some(SystemTime::now()); - last_was_up = true; - } - - last_ratio = status.success_ratio; - std::thread::sleep(interval); - status.check(); - } -} - -//// PRIVATE FUNCTIONS ///////////////////////////////////////////////////////////////////////////// -/// Displays the current status for the [continuous uptime monitor](continuous_uptime_monitor) -fn display_uptime_status( - msg: &str, - last_uptime: Option, - last_downtime: Option, - status: &UptimeStatus, -) { - // I know it's weird that this has two spaces too much, but somehow just the tabs is missing - // two spaces. - info!("uptime check: {}", msg); - info!("last uptime: {}", match_format_time(last_uptime)); - info!("last downtime: {}", match_format_time(last_downtime)); - info!( - "since downtime: {}", - match_format_duration_since(last_downtime) - ); - info!( - "since uptime: {}", - match_format_duration_since(last_uptime) - ); - debug!("\n{}", status); - info!("{}", divider!()); -} - -//////////////////////////////////////////////////////////////////////////////////////////////////// -/// Returns "None" if the given [Option] is [None](Option::None). Otherwise, returns the time stamp -/// formatted according to rfc3999. -fn match_format_time(time: Option) -> String { - match time { - Some(time) => format_rfc3339(time).to_string(), - None => String::from("None"), - } -} - -//////////////////////////////////////////////////////////////////////////////////////////////////// -/// Returns "None" if the given [Option] is [None](Option::None). Otherwise, returns duration since -/// that time in a human readable format. -fn match_format_duration_since(time: Option) -> String { - match time { - Some(time) => format_duration( - SystemTime::now() - .duration_since(time) - .expect("could not calculate elapsed time"), - ) - .to_string(), - None => String::from("None"), - } -} diff --git a/members/libpt-py/.gitignore b/members/libpt-py/.gitignore new file mode 100644 index 0000000..c8f0442 --- /dev/null +++ b/members/libpt-py/.gitignore @@ -0,0 +1,72 @@ +/target + +# Byte-compiled / optimized / DLL files +__pycache__/ +.pytest_cache/ +*.py[cod] + +# C extensions +*.so + +# Distribution / packaging +.Python +.venv/ +env/ +bin/ +build/ +develop-eggs/ +dist/ +eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +include/ +man/ +venv/ +*.egg-info/ +.installed.cfg +*.egg + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt +pip-selfcheck.json + +# Unit test / coverage reports +htmlcov/ +.tox/ +.coverage +.cache +nosetests.xml +coverage.xml + +# Translations +*.mo + +# Mr Developer +.mr.developer.cfg +.project +.pydevproject + +# Rope +.ropeproject + +# Django stuff: +*.log +*.pot + +.DS_Store + +# Sphinx documentation +docs/_build/ + +# PyCharm +.idea/ + +# VSCode +.vscode/ + +# Pyenv +.python-version diff --git a/members/libpt-py/Cargo.toml b/members/libpt-py/Cargo.toml new file mode 100644 index 0000000..3398d38 --- /dev/null +++ b/members/libpt-py/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "libpt-py" +version.workspace = true +edition.workspace = true + +[package.metadata.maturin] +name = "libpt" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +libpt = { version = "0.4.0-alpha.1", path = "../.." } +pyo3 = { version = "0.19.0", features = ["full"] } +anyhow.workspace = true + +[features] +default = ["log", "core", "full"] +core = [] +full = ["default", "core", "log", "bintols"] +log = ["libpt/log"] +bintols = ["libpt/bintols", "log"] diff --git a/members/libpt-py/pyproject.toml b/members/libpt-py/pyproject.toml new file mode 100644 index 0000000..0b1145a --- /dev/null +++ b/members/libpt-py/pyproject.toml @@ -0,0 +1,16 @@ +[build-system] +requires = ["maturin>=1.4,<2.0"] +build-backend = "maturin" + +[project] +name = "libpt" +requires-python = ">=3.8" +classifiers = [ + "Programming Language :: Rust", + "Programming Language :: Python :: Implementation :: CPython", + "Programming Language :: Python :: Implementation :: PyPy", +] +dynamic = ["version"] + +[tool.maturin] +features = ["pyo3/extension-module"] diff --git a/members/libpt-py/src/bintols/mod.rs b/members/libpt-py/src/bintols/mod.rs new file mode 100644 index 0000000..ea0403f --- /dev/null +++ b/members/libpt-py/src/bintols/mod.rs @@ -0,0 +1,56 @@ +use pyo3::prelude::*; + +use libpt::bintols as origin; + +mod display { + use pyo3::prelude::*; + + use libpt::bintols::display as origin; + + #[pyfunction] + pub fn bytes_to_bin(data: &[u8]) -> String { + origin::bytes_to_bin(data) + } + + #[pyfunction] + pub fn byte_bit_display(data: usize) -> String { + origin::byte_bit_display(data) + } + + #[pyfunction] + pub fn humanbytes(total: u128) -> String { + origin::humanbytes(total) + } + + /// implement a python module in Rust + pub fn submodule(py: Python, parent: &PyModule) -> PyResult<()> { + let module = PyModule::new(py, "display")?; + + module.add_function(wrap_pyfunction!(bytes_to_bin, module)?)?; + module.add_function(wrap_pyfunction!(byte_bit_display, module)?)?; + module.add_function(wrap_pyfunction!(humanbytes, module)?)?; + + parent.add_submodule(module)?; + Ok(()) + } +} + +/// implement a python module in Rust +pub fn submodule(py: Python, parent: &PyModule) -> PyResult<()> { + let module = PyModule::new(py, "bintols")?; + + // binary constants + module.add("KIBI", origin::KIBI)?; + module.add("MEBI", origin::MEBI)?; + module.add("GIBI", origin::GIBI)?; + module.add("TEBI", origin::TEBI)?; + module.add("PEBI", origin::PEBI)?; + module.add("EXBI", origin::EXBI)?; + module.add("ZEBI", origin::ZEBI)?; + module.add("YOBI", origin::YOBI)?; + + display::submodule(py, module)?; + + parent.add_submodule(module)?; + Ok(()) +} diff --git a/members/libpt-py/src/core/mod.rs b/members/libpt-py/src/core/mod.rs new file mode 100644 index 0000000..901d86f --- /dev/null +++ b/members/libpt-py/src/core/mod.rs @@ -0,0 +1,11 @@ +use pyo3::prelude::*; + +mod printing; + +/// implement a python module in Rust +pub fn submodule(py: Python, parent: &PyModule) -> PyResult<()> { + let module = PyModule::new(py, "core")?; + printing::submodule(py, module)?; + parent.add_submodule(module)?; + Ok(()) +} diff --git a/members/libpt-py/src/core/printing.rs b/members/libpt-py/src/core/printing.rs new file mode 100644 index 0000000..146451c --- /dev/null +++ b/members/libpt-py/src/core/printing.rs @@ -0,0 +1,24 @@ +use pyo3::prelude::*; + +use libpt::core::printing as origin; + +/// Quickly get a one line visual divider +#[pyfunction] +pub fn divider() -> String { + origin::divider() +} + +/// Quickly print a one line visual divider +#[pyfunction] +pub fn print_divider() { + origin::print_divider() +} + +/// implement a python module in Rust +pub fn submodule(py: Python, parent: &PyModule) -> PyResult<()> { + let module = PyModule::new(py, "printing")?; + module.add_function(wrap_pyfunction!(divider, module)?)?; + module.add_function(wrap_pyfunction!(print_divider, module)?)?; + parent.add_submodule(module)?; + Ok(()) +} diff --git a/members/libpt-py/src/lib.rs b/members/libpt-py/src/lib.rs new file mode 100644 index 0000000..36463b0 --- /dev/null +++ b/members/libpt-py/src/lib.rs @@ -0,0 +1,30 @@ +//! Python bindings for [`libpt`](libpt) + +#[cfg(feature = "bintols")] +mod bintols; +#[cfg(feature = "core")] +mod core; +#[cfg(feature = "log")] +mod log; + +use pyo3::prelude::*; + +/// return the version of libpt +#[pyfunction] +fn version() -> String { + env!("CARGO_PKG_VERSION").to_string() +} + +/// implement a python module in Rust +#[pymodule] +#[pyo3(name = "libpt")] +fn libpt_py(py: Python, m: &PyModule) -> PyResult<()> { + m.add_function(wrap_pyfunction!(version, m)?)?; + #[cfg(feature = "core")] + core::submodule(py, m)?; + #[cfg(feature = "log")] + log::submodule(py, m)?; + #[cfg(feature = "bintols")] + bintols::submodule(py, m)?; + Ok(()) +} diff --git a/members/libpt-py/src/log/mod.rs b/members/libpt-py/src/log/mod.rs new file mode 100644 index 0000000..ff47c92 --- /dev/null +++ b/members/libpt-py/src/log/mod.rs @@ -0,0 +1,81 @@ +use std::path::PathBuf; + +use pyo3::prelude::*; + +use libpt::log as origin; + +#[derive(Clone)] +#[pyclass] +pub enum Level { + Error, + Warn, + Info, + Debug, + Trace, +} + +impl From for origin::Level { + fn from(value: Level) -> Self { + match value { + Level::Error => origin::Level::ERROR, + Level::Warn => origin::Level::WARN, + Level::Info => origin::Level::INFO, + Level::Debug => origin::Level::DEBUG, + Level::Trace => origin::Level::TRACE, + } + } +} + +#[pyclass] +pub struct Logger { + inner: origin::Logger, +} + +impl From for Logger { + fn from(inner: origin::Logger) -> Self { + Self { inner } + } +} + +#[pymethods] +impl Logger { + #[new] + pub fn build( + log_dir: Option, + max_level: Option, + uptime: Option, + ) -> anyhow::Result { + // concert our wrapper type + let max_level = max_level.map(origin::Level::from); + Ok(origin::Logger::build(log_dir, max_level, uptime.unwrap_or(false))?.into()) + } + + /// ## logging at [`Level::ERROR`] + pub fn error(&self, printable: String) { + self.inner.error(printable) + } + /// ## logging at [`Level::WARN`] + pub fn warn(&self, printable: String) { + self.inner.warn(printable) + } + /// ## logging at [`Level::INFO`] + pub fn info(&self, printable: String) { + self.inner.info(printable) + } + /// ## logging at [`Level::DEBUG`] + pub fn debug(&self, printable: String) { + self.inner.debug(printable) + } + /// ## logging at [`Level::StringRACE`] + pub fn trace(&self, printable: String) { + self.inner.trace(printable) + } +} + +/// implement a python module in Rust +pub fn submodule(py: Python, parent: &PyModule) -> PyResult<()> { + let module = PyModule::new(py, "log")?; + module.add_class::()?; + parent.add_submodule(module)?; + Ok(()) +} diff --git a/members/libpt-py/src/net/mod.rs b/members/libpt-py/src/net/mod.rs new file mode 100644 index 0000000..e69de29 diff --git a/scripts/release.sh b/scripts/release.sh index af1d8da..dd7fa41 100755 --- a/scripts/release.sh +++ b/scripts/release.sh @@ -7,7 +7,7 @@ BODY=" $(git log $(git describe --tags --abbrev=0)..HEAD --pretty="- %s" --oneline --decorate) " USER=PlexSheep -git tag "v$NEW_VERSION-test" || echo "could not tag" +git tag "v$NEW_VERSION" || echo "could not tag" curl -X 'POST' \ 'https://git.cscherr.de/api/v1/repos/PlexSheep/pt/releases' \ -H 'accept: application/json' \ diff --git a/src/ccc/mod.rs b/src/ccc/mod.rs deleted file mode 100644 index b12d116..0000000 --- a/src/ccc/mod.rs +++ /dev/null @@ -1,104 +0,0 @@ -//! # Executable for the math/compute submodule -//! -//! Calculate Calculations with your Computer! -//! -//! This command line tool allows you to input a mathematical expression. It will then process the -//! expression. - -//// ATTRIBUTES //////////////////////////////////////////////////////////////////////////////////// -// we want docs -#![warn(missing_docs)] -#![warn(rustdoc::missing_crate_level_docs)] -// we want Debug everywhere. -#![warn(missing_debug_implementations)] -// enable clippy's extra lints, the pedantic version -#![warn(clippy::pedantic)] - -//// IMPORTS /////////////////////////////////////////////////////////////////////////////////////// - -use libpt::log::*; - -use clap::Parser; -use clap_verbosity_flag::{InfoLevel, Verbosity}; - -//// TYPES ///////////////////////////////////////////////////////////////////////////////////////// - -//// CONSTANTS ///////////////////////////////////////////////////////////////////////////////////// -/// short about section displayed in help -const ABOUT_ROOT: &'static str = r##" -Calculate Calculations with your Computer - - This commandline tool allows you to calculate complex mathematical expressions right in your - shell. -"##; -/// longer about section displayed in help, is combined with [the short help](ABOUT_ROOT) -static LONG_ABOUT_ROOT: &'static str = r##" - - libpt is a personal general purpose library, offering this executable, a python module and a - dynamic library. -"##; - -//// STATICS /////////////////////////////////////////////////////////////////////////////////////// -/// defines CLI interface -#[derive(Debug, Clone, Parser)] -#[command( - author, - version, - about = ABOUT_ROOT, - long_about = format!("{}{}", ABOUT_ROOT ,LONG_ABOUT_ROOT), - help_template = -r#"libpt: {version}{about-section}Author: -{author-with-newline} -{usage-heading} {usage}{all-args}{tab}"# - )] -pub struct Cli { - // clap_verbosity_flag seems to make this a global option implicitly - /// set a verbosity, multiple allowed (f.e. -vvv) - #[command(flatten)] - pub verbose: Verbosity, - - /// show logger meta - #[arg(short, long, global = true)] - pub log_meta: bool, - - /// your exporession(s) - #[clap(trailing_var_arg = true)] - pub expression: Vec, -} - -//// MACROS //////////////////////////////////////////////////////////////////////////////////////// - -//// ENUMS ///////////////////////////////////////////////////////////////////////////////////////// - -//// STRUCTS /////////////////////////////////////////////////////////////////////////////////////// - -//// IMPLEMENTATION //////////////////////////////////////////////////////////////////////////////// - -//// PUBLIC FUNCTIONS ////////////////////////////////////////////////////////////////////////////// - -//// PRIVATE FUNCTIONS ///////////////////////////////////////////////////////////////////////////// -fn main() { - let cli = Cli::parse(); - let ll: Level = match cli.verbose.log_level().unwrap().as_str() { - "TRACE" => Level::TRACE, - "DEBUG" => Level::DEBUG, - "INFO" => Level::INFO, - "WARN" => Level::WARN, - "ERROR" => Level::ERROR, - _ => { - eprintln!("'{}' is not a valid loglevel", cli.verbose.to_string()); - std::process::exit(1); - } - }; - if cli.log_meta { - Logger::init(None, Some(ll), false).expect("could not initialize Logger"); - } else { - // less verbose version - Logger::init_mini(Some(ll)).expect("could not initialize Logger"); - } - let mut expr: String = String::new(); - for part in cli.expression { - expr += ∂ - } -} -//////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/hedu/mod.rs b/src/hedu/mod.rs deleted file mode 100644 index d8473c6..0000000 --- a/src/hedu/mod.rs +++ /dev/null @@ -1,174 +0,0 @@ -//! # Executable for the hedu submodule -//! -//! Dump data to a fancy format. - -//// ATTRIBUTES //////////////////////////////////////////////////////////////////////////////////// -// we want docs -#![warn(missing_docs)] -#![warn(rustdoc::missing_crate_level_docs)] -// we want Debug everywhere. -#![warn(missing_debug_implementations)] -// enable clippy's extra lints, the pedantic version -#![warn(clippy::pedantic)] - -//// IMPORTS /////////////////////////////////////////////////////////////////////////////////////// - -use libpt::{bintols::hedu::*, log::*}; - -use clap::Parser; -use clap_verbosity_flag::{InfoLevel, Verbosity}; - -use std::{fs::File, io::IsTerminal, path::PathBuf}; - -//// TYPES ///////////////////////////////////////////////////////////////////////////////////////// - -//// CONSTANTS ///////////////////////////////////////////////////////////////////////////////////// -/// short about section displayed in help -const ABOUT_ROOT: &'static str = r##" -Dumps data in fancy formats. -"##; -/// longer about section displayed in help, is combined with [the short help](ABOUT_ROOT) -static LONG_ABOUT_ROOT: &'static str = r##" - - libpt is a personal general purpose library, offering this executable, a python module and a - dynamic library. -"##; - -//// STATICS /////////////////////////////////////////////////////////////////////////////////////// - -//// MACROS //////////////////////////////////////////////////////////////////////////////////////// - -//// ENUMS ///////////////////////////////////////////////////////////////////////////////////////// - -//// STRUCTS /////////////////////////////////////////////////////////////////////////////////////// -/// defines CLI interface -#[derive(Debug, Clone, Parser)] -#[command( - author, - version, - about = ABOUT_ROOT, - long_about = format!("{}{}", ABOUT_ROOT ,LONG_ABOUT_ROOT), - help_template = -r#"{about-section} -{usage-heading} {usage} -{all-args}{tab} - -libpt: {version} -Author: {author-with-newline} -"# - )] -pub struct Cli { - // clap_verbosity_flag seems to make this a global option implicitly - /// set a verbosity, multiple allowed (f.e. -vvv) - #[command(flatten)] - pub verbose: Verbosity, - - /// show additional logging meta data - #[arg(long)] - pub meta: bool, - - /// show character representation - #[arg(short, long)] - pub chars: bool, - - /// skip first N bytes - #[arg(short, long, default_value_t = 0)] - pub skip: usize, - - /// only interpret N bytes (end after N) - #[arg(short, long, default_value_t = 0)] - pub limit: usize, - - /// show identical lines - #[arg(short = 'i', long)] - pub show_identical: bool, - - /// a data source, probably a file. - /// - /// If left empty or set as "-", the program will read from stdin. - // TODO: take many sources #60 - pub data_source: Vec, -} - -//// IMPLEMENTATION //////////////////////////////////////////////////////////////////////////////// - -//// PUBLIC FUNCTIONS ////////////////////////////////////////////////////////////////////////////// - -//// PRIVATE FUNCTIONS ///////////////////////////////////////////////////////////////////////////// -fn main() { - let mut cli = cli_parse(); - let mut sources: Vec> = Vec::new(); - if cli.data_source.len() > 0 && cli.data_source[0] != "-" { - for data_source in &cli.data_source { - let data_source: PathBuf = PathBuf::from(data_source); - if data_source.is_dir() { - warn!("Not a file {:?}, skipping", data_source); - // std::process::exit(1); - continue; - } - trace!("Trying to open '{:?}'", data_source); - match File::open(&data_source) { - Ok(file) => sources.push(Box::new(file)), - Err(err) => { - error!("Could not open '{:?}': {err}", data_source); - std::process::exit(1); - } - }; - } - } else { - trace!("Trying to open stdin"); - let stdin = std::io::stdin(); - if stdin.is_terminal() { - warn!("Refusing to dump from interactive terminal"); - std::process::exit(2) - } - // just for the little header - cli.data_source = Vec::new(); - cli.data_source.push(format!("stdin")); - sources.push(Box::new(stdin)); - } - for (i, source) in sources.iter_mut().enumerate() { - let mut config = Hedu::new(cli.chars, cli.skip, cli.show_identical, cli.limit); - // FIXME: find a better way to get the file name - // Currently, skipped sources make an extra newline here. - match config.chars { - false => { - println!("{:─^59}", format!(" {} ", cli.data_source[i])); - } - true => { - println!("{:─^80}", format!(" {} ", cli.data_source[i])); - } - } - match config.dump(&mut **source) { - Ok(_) => (), - Err(err) => { - error!("Could not dump data of file: {err}"); - std::process::exit(3); - } - } - if i < cli.data_source.len() - 1 { - config.newline(); - } - } -} -//////////////////////////////////////////////////////////////////////////////////////////////////// -fn cli_parse() -> Cli { - let cli = Cli::parse(); - let ll: Level = match cli.verbose.log_level().unwrap().as_str() { - "TRACE" => Level::TRACE, - "DEBUG" => Level::DEBUG, - "INFO" => Level::INFO, - "WARN" => Level::WARN, - "ERROR" => Level::ERROR, - _ => { - unreachable!(); - } - }; - if cli.meta { - Logger::init(None, Some(ll), false).expect("could not initialize Logger"); - } else { - // less verbose version - Logger::init_mini(Some(ll)).expect("could not initialize Logger"); - } - return cli; -} diff --git a/src/lib.rs b/src/lib.rs index 8899a30..7809945 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,13 +8,9 @@ #[cfg(feature = "bintols")] pub use libpt_bintols as bintols; -#[cfg(feature = "ccc")] -pub use libpt_ccc as ccc; #[cfg(feature = "core")] pub use libpt_core as core; #[cfg(feature = "log")] pub use libpt_log as log; -#[cfg(feature = "math")] -pub use libpt_math as math; -#[cfg(feature = "net")] -pub use libpt_net as net; +#[cfg(feature = "py")] +pub use libpt_py as py;