generated from PlexSheep/baserepo
Compare commits
33 commits
a63262825e
...
edcec991dc
Author | SHA1 | Date | |
---|---|---|---|
edcec991dc | |||
|
de9ef8d841 | ||
0155465332 | |||
521ae9a193 | |||
|
15687ca0d7 | ||
441669a2c3 | |||
b2435f3963 | |||
b58dc3dc44 | |||
|
747c3e6eac | ||
5b8753c45d | |||
aa560b0e05 | |||
39a21d64e9 | |||
0515e221f9 | |||
a9cf78ee0d | |||
|
66932f70a3 | ||
3f59e99b88 | |||
b7fbef73b4 | |||
|
b3e5a99718 | ||
eaea5ac1d7 | |||
6181f2bff8 | |||
43f27493b4 | |||
c85e785802 | |||
074dcf9c0f | |||
c679bed538 | |||
3e2ecf1189 | |||
50fea61bb0 | |||
9f393f0369 | |||
|
43ac1e3fb8 | ||
6dcc45d722 | |||
6330c3da48 | |||
0de0340f4e | |||
ceb8c98715 | |||
1bdef8c493 |
50 changed files with 650 additions and 1581 deletions
22
.gitea/workflows/cargo-publish.yaml
Normal file
22
.gitea/workflows/cargo-publish.yaml
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
name: Cargo Check, Format, Fix, Test and publish
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
format:
|
||||||
|
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:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: dtolnay/rust-toolchain@stable
|
||||||
|
- run: cargo check --all-features --all-targets
|
||||||
|
- run: rustup component add rustfmt
|
||||||
|
- run: cargo fix --all-features --all-targets
|
||||||
|
- run: cargo fmt --all
|
||||||
|
- run: cargo test --all-features --all-targets
|
||||||
|
- run: cargo publish --index "https://git.cscherr.de/PlexSheep/_cargo-index.git --dry-run
|
27
.gitea/workflows/cargo.yaml
Normal file
27
.gitea/workflows/cargo.yaml
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
name: Cargo Check, Format, Fix and Test
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
format:
|
||||||
|
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:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: dtolnay/rust-toolchain@stable
|
||||||
|
- run: cargo check --all-features --all-targets
|
||||||
|
- run: rustup component add rustfmt
|
||||||
|
- run: cargo fix --all-features --all-targets
|
||||||
|
- run: cargo fmt --all
|
||||||
|
- run: cargo test --all-features --all-targets
|
||||||
|
- 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
|
||||||
|
commit_user_name: Gitea CI
|
||||||
|
commit_user_email: noreply@cscherr.de
|
||||||
|
commit_author: Gitea CI <noreply@cscherr.de>
|
||||||
|
|
120
.github/workflows/CI.yml
vendored
120
.github/workflows/CI.yml
vendored
|
@ -1,120 +0,0 @@
|
||||||
# This file is autogenerated by maturin v0.14.17
|
|
||||||
# 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: --skip-existing *
|
|
56
Cargo.toml
56
Cargo.toml
|
@ -8,20 +8,12 @@ members = [
|
||||||
"members/libpt-bin",
|
"members/libpt-bin",
|
||||||
"members/libpt-log",
|
"members/libpt-log",
|
||||||
"members/libpt-net",
|
"members/libpt-net",
|
||||||
"members/libpt-py",
|
|
||||||
"members/libpt-hedu",
|
"members/libpt-hedu",
|
||||||
]
|
]
|
||||||
default-members = [
|
default-members = [".", "members/libpt-bin", "members/libpt-core"]
|
||||||
".",
|
|
||||||
"members/libpt-bin",
|
|
||||||
"members/libpt-core",
|
|
||||||
"members/libpt-py",
|
|
||||||
"members/libpt-log",
|
|
||||||
"members/libpt-math",
|
|
||||||
]
|
|
||||||
[workspace.package]
|
[workspace.package]
|
||||||
publish = false
|
publish = true
|
||||||
version = "0.1.7"
|
version = "0.2.4"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
authors = ["Christoph J. Scherr <software@cscherr.de>"]
|
authors = ["Christoph J. Scherr <software@cscherr.de>"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
|
@ -29,15 +21,20 @@ description = "Personal multitool"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
homepage = "https://git.cscherr.de/PlexSheep/libpt"
|
homepage = "https://git.cscherr.de/PlexSheep/libpt"
|
||||||
repository = "https://git.cscherr.de/PlexSheep/libpt"
|
repository = "https://git.cscherr.de/PlexSheep/libpt"
|
||||||
keywords = ["cli", "python", "scriptable", "pyo3", "library"]
|
keywords = ["cli", "library"]
|
||||||
categories = ["command-line-utilities", "development-tools", "development-tools::ffi"]
|
categories = [
|
||||||
|
"command-line-utilities",
|
||||||
|
"development-tools",
|
||||||
|
"development-tools::ffi",
|
||||||
|
]
|
||||||
|
|
||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
pyo3 = "0.19"
|
anyhow = "1.0.79"
|
||||||
|
thiserror = "1.0.56"
|
||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "libpt"
|
name = "libpt"
|
||||||
publish = true
|
publish.workspace = true
|
||||||
version.workspace = true
|
version.workspace = true
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
authors.workspace = true
|
authors.workspace = true
|
||||||
|
@ -50,16 +47,9 @@ keywords.workspace = true
|
||||||
categories.workspace = true
|
categories.workspace = true
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["log"]
|
default = ["log", "core"]
|
||||||
all = [
|
all = ["default", "math", "log", "bintols", "net", "ccc", "hedu", "core"]
|
||||||
"default",
|
core = []
|
||||||
"math",
|
|
||||||
"log",
|
|
||||||
"bintols",
|
|
||||||
"net",
|
|
||||||
"ccc",
|
|
||||||
"hedu"
|
|
||||||
]
|
|
||||||
fw = []
|
fw = []
|
||||||
math = []
|
math = []
|
||||||
log = []
|
log = []
|
||||||
|
@ -73,16 +63,16 @@ name = "libpt"
|
||||||
crate-type = [
|
crate-type = [
|
||||||
"dylib", # .dll, .so, .dynlib
|
"dylib", # .dll, .so, .dynlib
|
||||||
"staticlib", # .lib, .a
|
"staticlib", # .lib, .a
|
||||||
"rlib"
|
"rlib",
|
||||||
]
|
]
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
libpt-bintols = { version = "0.1.7", path = "members/libpt-bintols" }
|
libpt-bintols = { path = "members/libpt-bintols" }
|
||||||
libpt-core = { version = "0.1.7", path = "members/libpt-core" }
|
libpt-core = { path = "members/libpt-core" }
|
||||||
libpt-hedu = { version = "0.1.7", path = "members/libpt-hedu" }
|
libpt-hedu = { path = "members/libpt-hedu" }
|
||||||
libpt-log = { version = "0.1.7", path = "members/libpt-log" }
|
libpt-log = { path = "members/libpt-log" }
|
||||||
libpt-math = { version = "0.1.7", path = "members/libpt-math" }
|
libpt-math = { path = "members/libpt-math" }
|
||||||
libpt-net = { version = "0.1.7", path = "members/libpt-net" }
|
libpt-ccc = { path = "members/libpt-ccc" }
|
||||||
libpt-ccc = { version = "0.1.7", path = "members/libpt-ccc" }
|
libpt-net = { path = "members/libpt-net" }
|
||||||
|
|
BIN
data/256B-zero-with-trash.img
Normal file
BIN
data/256B-zero-with-trash.img
Normal file
Binary file not shown.
BIN
data/256B-zero.img
Normal file
BIN
data/256B-zero.img
Normal file
Binary file not shown.
|
@ -19,6 +19,10 @@ categories.workspace = true
|
||||||
name = "ccc"
|
name = "ccc"
|
||||||
path = "src/ccc/mod.rs"
|
path = "src/ccc/mod.rs"
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "hedu"
|
||||||
|
path = "src/hedu/mod.rs"
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "libpt"
|
name = "libpt"
|
||||||
path = "src/main/mod.rs"
|
path = "src/main/mod.rs"
|
||||||
|
@ -27,4 +31,4 @@ path = "src/main/mod.rs"
|
||||||
clap = { version = "4.4.4", features = ["derive"] }
|
clap = { version = "4.4.4", features = ["derive"] }
|
||||||
clap-num = "1.0.2"
|
clap-num = "1.0.2"
|
||||||
clap-verbosity-flag = "2.0.1"
|
clap-verbosity-flag = "2.0.1"
|
||||||
libpt = { version = "0.1.7", path = "../..", features = ["ccc", "math", "hedu", "net"] }
|
libpt = {path = "../..", features = ["default", "ccc", "math", "hedu", "net", "log"] }
|
||||||
|
|
|
@ -15,13 +15,11 @@
|
||||||
#![warn(clippy::pedantic)]
|
#![warn(clippy::pedantic)]
|
||||||
|
|
||||||
//// IMPORTS ///////////////////////////////////////////////////////////////////////////////////////
|
//// IMPORTS ///////////////////////////////////////////////////////////////////////////////////////
|
||||||
use libpt::ccc::*;
|
|
||||||
use libpt::log::*;
|
use libpt::log::*;
|
||||||
|
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use clap_verbosity_flag::{Verbosity, InfoLevel};
|
use clap_verbosity_flag::{InfoLevel, Verbosity};
|
||||||
|
|
||||||
use std::path::PathBuf;
|
|
||||||
|
|
||||||
//// TYPES /////////////////////////////////////////////////////////////////////////////////////////
|
//// TYPES /////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
@ -64,7 +62,7 @@ pub struct Cli {
|
||||||
pub log_meta: bool,
|
pub log_meta: bool,
|
||||||
|
|
||||||
/// your exporession(s)
|
/// your exporession(s)
|
||||||
#[clap(trailing_var_arg=true)]
|
#[clap(trailing_var_arg = true)]
|
||||||
pub expression: Vec<String>,
|
pub expression: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,49 +91,14 @@ fn main() {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if cli.log_meta {
|
if cli.log_meta {
|
||||||
Logger::init_customized(
|
Logger::init(None, Some(ll)).expect("could not initialize Logger");
|
||||||
false,
|
|
||||||
PathBuf::from("/dev/null"),
|
|
||||||
true,
|
|
||||||
false,
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
ll,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
)
|
|
||||||
.expect("could not initialize Logger");
|
|
||||||
} else {
|
} else {
|
||||||
// less verbose version
|
// less verbose version
|
||||||
Logger::init_customized(
|
Logger::init_mini(Some(ll)).expect("could not initialize Logger");
|
||||||
false,
|
|
||||||
PathBuf::from("/dev/null"),
|
|
||||||
true,
|
|
||||||
false,
|
|
||||||
true,
|
|
||||||
false,
|
|
||||||
ll,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
)
|
|
||||||
.expect("could not initialize Logger");
|
|
||||||
}
|
}
|
||||||
let mut expr: String = String::new();
|
let mut expr: String = String::new();
|
||||||
for part in cli.expression {
|
for part in cli.expression {
|
||||||
expr += ∂
|
expr += ∂
|
||||||
}
|
}
|
||||||
|
|
||||||
debug!("exporssion: {}", expr);
|
|
||||||
let r = Calculator::oneshot(expr);
|
|
||||||
match r {
|
|
||||||
Ok(r) => {
|
|
||||||
println!("{r}");
|
|
||||||
}
|
|
||||||
Err(err) => {
|
|
||||||
error!("Could not compute: {err}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
151
members/libpt-bin/src/hedu/mod.rs
Normal file
151
members/libpt-bin/src/hedu/mod.rs
Normal file
|
@ -0,0 +1,151 @@
|
||||||
|
//! # 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::{hedu::*, log::*};
|
||||||
|
|
||||||
|
use clap::Parser;
|
||||||
|
use clap_verbosity_flag::{InfoLevel, Verbosity};
|
||||||
|
|
||||||
|
use std::{fs::File, io::IsTerminal};
|
||||||
|
|
||||||
|
//// 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<InfoLevel>,
|
||||||
|
|
||||||
|
/// 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.
|
||||||
|
pub data_source: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
//// IMPLEMENTATION ////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
//// PUBLIC FUNCTIONS //////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
//// PRIVATE FUNCTIONS /////////////////////////////////////////////////////////////////////////////
|
||||||
|
fn main() {
|
||||||
|
let cli = cli_parse();
|
||||||
|
let mut source: Box<dyn DataSource>;
|
||||||
|
if cli.data_source.is_some() && cli.data_source.clone().is_some_and(|val| val != "-") {
|
||||||
|
let data_source = cli.data_source.unwrap();
|
||||||
|
trace!("Trying to open '{}'", data_source);
|
||||||
|
source = match File::open(&data_source) {
|
||||||
|
Ok(file) => Box::new(file),
|
||||||
|
Err(err) => {
|
||||||
|
error!("Could not open file '{}': {err}", data_source);
|
||||||
|
std::process::exit(1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
trace!("Trying to open stdout");
|
||||||
|
let stdin = std::io::stdin();
|
||||||
|
if stdin.is_terminal() {
|
||||||
|
warn!("Refusing to dump from interactive terminal");
|
||||||
|
std::process::exit(2)
|
||||||
|
}
|
||||||
|
source = Box::new(stdin);
|
||||||
|
}
|
||||||
|
|
||||||
|
match dump(
|
||||||
|
&mut *source,
|
||||||
|
HeduConfig::new(cli.chars, cli.skip, cli.show_identical, cli.limit),
|
||||||
|
) {
|
||||||
|
Ok(_) => (),
|
||||||
|
Err(err) => {
|
||||||
|
error!("Could not dump data of file: {err}");
|
||||||
|
std::process::exit(3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
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)).expect("could not initialize Logger");
|
||||||
|
} else {
|
||||||
|
// less verbose version
|
||||||
|
Logger::init_mini(Some(ll)).expect("could not initialize Logger");
|
||||||
|
}
|
||||||
|
return cli;
|
||||||
|
}
|
|
@ -19,7 +19,7 @@ use clap::{Parser, Subcommand};
|
||||||
|
|
||||||
use clap_num::number_range;
|
use clap_num::number_range;
|
||||||
|
|
||||||
use clap_verbosity_flag::{Verbosity, InfoLevel};
|
use clap_verbosity_flag::{InfoLevel, Verbosity};
|
||||||
|
|
||||||
//// CONSTANTS /////////////////////////////////////////////////////////////////////////////////////
|
//// CONSTANTS /////////////////////////////////////////////////////////////////////////////////////
|
||||||
/// short about section displayed in help
|
/// short about section displayed in help
|
||||||
|
@ -103,13 +103,10 @@ pub enum NetCommands {
|
||||||
|
|
||||||
/// set a timeout (in ms)
|
/// set a timeout (in ms)
|
||||||
#[clap(short, long, default_value_t = 100)]
|
#[clap(short, long, default_value_t = 100)]
|
||||||
timeout: u64
|
timeout: u64,
|
||||||
|
|
||||||
},
|
},
|
||||||
/// discover hosts in your network
|
/// discover hosts in your network
|
||||||
Discover {
|
Discover {},
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -13,7 +13,6 @@
|
||||||
// enable clippy's extra lints, the pedantic version
|
// enable clippy's extra lints, the pedantic version
|
||||||
#![warn(clippy::pedantic)]
|
#![warn(clippy::pedantic)]
|
||||||
|
|
||||||
|
|
||||||
//// IMPORTS ///////////////////////////////////////////////////////////////////////////////////////
|
//// IMPORTS ///////////////////////////////////////////////////////////////////////////////////////
|
||||||
use libpt::{log::*, net::monitoring::uptime};
|
use libpt::{log::*, net::monitoring::uptime};
|
||||||
|
|
||||||
|
@ -22,11 +21,8 @@ use clap::Parser;
|
||||||
pub mod args;
|
pub mod args;
|
||||||
use args::*;
|
use args::*;
|
||||||
|
|
||||||
use std::path::PathBuf;
|
|
||||||
|
|
||||||
//// CONSTANTS /////////////////////////////////////////////////////////////////////////////////////
|
//// CONSTANTS /////////////////////////////////////////////////////////////////////////////////////
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
|
|
||||||
//// STATICS ///////////////////////////////////////////////////////////////////////////////////////
|
//// STATICS ///////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
//// MACROS ////////////////////////////////////////////////////////////////////////////////////////
|
//// MACROS ////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -53,34 +49,10 @@ pub fn main() {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if cli.log_meta {
|
if cli.log_meta {
|
||||||
Logger::init_customized(
|
Logger::init(None, Some(ll)).expect("could not initialize Logger");
|
||||||
false,
|
|
||||||
PathBuf::from("/dev/null"),
|
|
||||||
true,
|
|
||||||
false,
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
ll,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
)
|
|
||||||
.expect("could not initialize Logger");
|
|
||||||
} else {
|
} else {
|
||||||
// less verbose version
|
// less verbose version
|
||||||
Logger::init_customized(
|
Logger::init_mini(Some(ll)).expect("could not initialize Logger");
|
||||||
false,
|
|
||||||
PathBuf::from("/dev/null"),
|
|
||||||
true,
|
|
||||||
false,
|
|
||||||
true,
|
|
||||||
false,
|
|
||||||
ll,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
)
|
|
||||||
.expect("could not initialize Logger");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
trace!("started the main function");
|
trace!("started the main function");
|
||||||
|
|
|
@ -16,5 +16,5 @@ categories.workspace = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
num-traits = "0.2.16"
|
num-traits = "0.2.16"
|
||||||
libpt-core = { version = "0.1.0", path = "../libpt-core" }
|
libpt-core = { path = "../libpt-core" }
|
||||||
libpt-log = { version = "0.1.0", path = "../libpt-log" }
|
libpt-log = { path = "../libpt-log" }
|
||||||
|
|
|
@ -20,7 +20,8 @@ macro_rules! investigate_memory_layout {
|
||||||
let pointer = item as *const $t;
|
let pointer = item as *const $t;
|
||||||
let mut memory: [u8; std::mem::size_of::<$t>()] = std::mem::transmute(item.clone());
|
let mut memory: [u8; std::mem::size_of::<$t>()] = std::mem::transmute(item.clone());
|
||||||
memory.reverse();
|
memory.reverse();
|
||||||
println!("\
|
println!(
|
||||||
|
"\
|
||||||
\t{index:02x}\titem:\t\t{item:?}\n\
|
\t{index:02x}\titem:\t\t{item:?}\n\
|
||||||
\t\tpointer: \t{:X?}\n\
|
\t\tpointer: \t{:X?}\n\
|
||||||
\t\talign: \t{}\n\
|
\t\talign: \t{}\n\
|
||||||
|
|
|
@ -59,8 +59,7 @@ where
|
||||||
return format!("{:.2} Z", total.to_f64().unwrap() / ZEBI as f64);
|
return format!("{:.2} Z", total.to_f64().unwrap() / ZEBI as f64);
|
||||||
} else if YOBI <= total {
|
} else if YOBI <= total {
|
||||||
return format!("{:.2} Y", total.to_f64().unwrap() / YOBI as f64);
|
return format!("{:.2} Y", total.to_f64().unwrap() / YOBI as f64);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use libpt_bintols::*;
|
|
||||||
use libpt_bintols::display::*;
|
use libpt_bintols::display::*;
|
||||||
|
use libpt_bintols::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn btobin() {
|
fn btobin() {
|
||||||
|
@ -10,11 +10,16 @@ fn btobin() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn big_btobin() {
|
fn big_btobin() {
|
||||||
let data = [12,31,82,32,123,32,92,23,12,32,12,1,1,1];
|
let data = [12, 31, 82, 32, 123, 32, 92, 23, 12, 32, 12, 1, 1, 1];
|
||||||
let r = bytes_to_bin(&data);
|
let r = bytes_to_bin(&data);
|
||||||
assert_eq!(r, format!("0b00001100_00011111_01010010_\
|
assert_eq!(
|
||||||
|
r,
|
||||||
|
format!(
|
||||||
|
"0b00001100_00011111_01010010_\
|
||||||
00100000_01111011_00100000_01011100_00010111_00001100\n\
|
00100000_01111011_00100000_01011100_00010111_00001100\n\
|
||||||
_00100000_00001100_00000001_00000001_00000001"));
|
_00100000_00001100_00000001_00000001_00000001"
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -29,35 +34,35 @@ fn hmnbytes() {
|
||||||
assert_eq!(humanbytes(0), format!("0 B"));
|
assert_eq!(humanbytes(0), format!("0 B"));
|
||||||
assert_eq!(humanbytes(1), format!("1 B"));
|
assert_eq!(humanbytes(1), format!("1 B"));
|
||||||
|
|
||||||
assert_eq!(humanbytes(KIBI-1), format!("1023 B"));
|
assert_eq!(humanbytes(KIBI - 1), format!("1023 B"));
|
||||||
assert_eq!(humanbytes(KIBI), format!("1.00 K"));
|
assert_eq!(humanbytes(KIBI), format!("1.00 K"));
|
||||||
assert_eq!(humanbytes(KIBI+1), format!("1.00 K"));
|
assert_eq!(humanbytes(KIBI + 1), format!("1.00 K"));
|
||||||
|
|
||||||
assert_eq!(humanbytes(MEBI-1), format!("1024.00 K"));
|
assert_eq!(humanbytes(MEBI - 1), format!("1024.00 K"));
|
||||||
assert_eq!(humanbytes(MEBI), format!("1.00 M"));
|
assert_eq!(humanbytes(MEBI), format!("1.00 M"));
|
||||||
assert_eq!(humanbytes(MEBI+1), format!("1.00 M"));
|
assert_eq!(humanbytes(MEBI + 1), format!("1.00 M"));
|
||||||
|
|
||||||
assert_eq!(humanbytes(GIBI-1), format!("1024.00 M"));
|
assert_eq!(humanbytes(GIBI - 1), format!("1024.00 M"));
|
||||||
assert_eq!(humanbytes(GIBI), format!("1.00 G"));
|
assert_eq!(humanbytes(GIBI), format!("1.00 G"));
|
||||||
assert_eq!(humanbytes(GIBI+1), format!("1.00 G"));
|
assert_eq!(humanbytes(GIBI + 1), format!("1.00 G"));
|
||||||
|
|
||||||
assert_eq!(humanbytes(TEBI-1), format!("1024.00 G"));
|
assert_eq!(humanbytes(TEBI - 1), format!("1024.00 G"));
|
||||||
assert_eq!(humanbytes(TEBI), format!("1.00 T"));
|
assert_eq!(humanbytes(TEBI), format!("1.00 T"));
|
||||||
assert_eq!(humanbytes(TEBI+1), format!("1.00 T"));
|
assert_eq!(humanbytes(TEBI + 1), format!("1.00 T"));
|
||||||
|
|
||||||
assert_eq!(humanbytes(PEBI-1), format!("1024.00 T"));
|
assert_eq!(humanbytes(PEBI - 1), format!("1024.00 T"));
|
||||||
assert_eq!(humanbytes(PEBI), format!("1.00 P"));
|
assert_eq!(humanbytes(PEBI), format!("1.00 P"));
|
||||||
assert_eq!(humanbytes(PEBI+1), format!("1.00 P"));
|
assert_eq!(humanbytes(PEBI + 1), format!("1.00 P"));
|
||||||
|
|
||||||
assert_eq!(humanbytes(EXBI-1), format!("1024.00 P"));
|
assert_eq!(humanbytes(EXBI - 1), format!("1024.00 P"));
|
||||||
assert_eq!(humanbytes(EXBI), format!("1.00 E"));
|
assert_eq!(humanbytes(EXBI), format!("1.00 E"));
|
||||||
assert_eq!(humanbytes(EXBI+1), format!("1.00 E"));
|
assert_eq!(humanbytes(EXBI + 1), format!("1.00 E"));
|
||||||
|
|
||||||
assert_eq!(humanbytes(ZEBI-1), format!("1024.00 E"));
|
assert_eq!(humanbytes(ZEBI - 1), format!("1024.00 E"));
|
||||||
assert_eq!(humanbytes(ZEBI), format!("1.00 Z"));
|
assert_eq!(humanbytes(ZEBI), format!("1.00 Z"));
|
||||||
assert_eq!(humanbytes(ZEBI+1), format!("1.00 Z"));
|
assert_eq!(humanbytes(ZEBI + 1), format!("1.00 Z"));
|
||||||
|
|
||||||
assert_eq!(humanbytes(YOBI-1), format!("1024.00 Z"));
|
assert_eq!(humanbytes(YOBI - 1), format!("1024.00 Z"));
|
||||||
assert_eq!(humanbytes(YOBI), format!("1.00 Y"));
|
assert_eq!(humanbytes(YOBI), format!("1.00 Y"));
|
||||||
assert_eq!(humanbytes(YOBI+1), format!("1.00 Y"));
|
assert_eq!(humanbytes(YOBI + 1), format!("1.00 Y"));
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,6 @@ categories.workspace = true
|
||||||
[dependencies]
|
[dependencies]
|
||||||
num = "0.4.1"
|
num = "0.4.1"
|
||||||
num-traits = "0.2.16"
|
num-traits = "0.2.16"
|
||||||
libpt-core = { version = "0.1.7", path = "../libpt-core" }
|
libpt-core = { path = "../libpt-core" }
|
||||||
libpt-log = { version = "0.1.7", path = "../libpt-log" }
|
libpt-log = { path = "../libpt-log" }
|
||||||
libpt-math = { version = "0.1.7", path = "../libpt-math" }
|
libpt-math = { path = "../libpt-math" }
|
||||||
|
|
|
@ -1,225 +0,0 @@
|
||||||
//! # Results and Errors for the calculate module
|
|
||||||
//!
|
|
||||||
//! This module defines the errors and results that can be processed from any given term.
|
|
||||||
|
|
||||||
//// 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 std::fmt::Display;
|
|
||||||
pub use num_traits::PrimInt;
|
|
||||||
|
|
||||||
#[allow(unused_imports)] // we possibly want to use all log levels
|
|
||||||
use libpt_log::*;
|
|
||||||
#[allow(unused_imports)] // import more complex math stuff from there
|
|
||||||
use libpt_math;
|
|
||||||
|
|
||||||
//// TYPES /////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// Quick Result with a ccc error
|
|
||||||
pub type Result<T> = std::result::Result<T, Error>;
|
|
||||||
|
|
||||||
//// CONSTANTS /////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
//// STATICS ///////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
//// MACROS ////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
//// ENUMS /////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// ## Supported Operations
|
|
||||||
///
|
|
||||||
/// This `enum` contains all operations supported in this module.
|
|
||||||
#[non_exhaustive]
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub enum Operator {
|
|
||||||
/// Mathmatical addition
|
|
||||||
Addition,
|
|
||||||
/// Mathmatical subtraction
|
|
||||||
Subtraction,
|
|
||||||
/// Mathmatical multiplication
|
|
||||||
Multiplication,
|
|
||||||
/// Mathmatical division
|
|
||||||
Division,
|
|
||||||
/// Mathmatical modulo, finite field arithmetic
|
|
||||||
Modulo,
|
|
||||||
/// Any function, seel [`Function`]
|
|
||||||
Function(Function)
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// ## Supported Functions
|
|
||||||
///
|
|
||||||
/// This `enum` contains all functions supported in this module.
|
|
||||||
///
|
|
||||||
/// A function has a name followed by braces directly afterwards.
|
|
||||||
/// A function may have 0 to 31 Arguments.
|
|
||||||
///
|
|
||||||
/// Example: `sqrt(19)`, `floor(19.9)`
|
|
||||||
#[non_exhaustive]
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub enum Function {
|
|
||||||
/// Draw the mathmatical root, attribute n is the nth root
|
|
||||||
Root(u16),
|
|
||||||
/// round up
|
|
||||||
Floor,
|
|
||||||
/// round down
|
|
||||||
Ceil,
|
|
||||||
/// round to nearest integer
|
|
||||||
/// (commercial rounding)
|
|
||||||
Round,
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// Top Level Error Type
|
|
||||||
///
|
|
||||||
/// Contains many variants of other errors, that can occur when using the crate.
|
|
||||||
#[non_exhaustive]
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub enum Error {
|
|
||||||
/// The term has bad syntax
|
|
||||||
SyntaxError(String)
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// Represents some kind of computed value
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub enum Value {
|
|
||||||
/// Variable value
|
|
||||||
Variable(VarVal),
|
|
||||||
/// Numerical value
|
|
||||||
Numerical(NumVal),
|
|
||||||
/// Complex number value
|
|
||||||
Complex(ComplVal),
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Represents some kind of numeric value
|
|
||||||
#[non_exhaustive]
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub enum NumVal {
|
|
||||||
/// Value > 0
|
|
||||||
Signed(i128),
|
|
||||||
/// Value can be negative
|
|
||||||
Unsigned(u128),
|
|
||||||
/// Value is not an integer
|
|
||||||
Float(f64)
|
|
||||||
}
|
|
||||||
|
|
||||||
//// STRUCTS ///////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// Represents a Value with at least one variable,
|
|
||||||
///
|
|
||||||
/// currently not implemented
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct VarVal {
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// Represents a Value with a complex number,
|
|
||||||
///
|
|
||||||
/// currently not implemented
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct ComplVal {
|
|
||||||
}
|
|
||||||
|
|
||||||
//// IMPLEMENTATION ////////////////////////////////////////////////////////////////////////////////
|
|
||||||
impl<T: num_traits::PrimInt> From<T> for NumVal where
|
|
||||||
u128: TryFrom<T>,
|
|
||||||
u128: TryFrom<T> {
|
|
||||||
fn from(value: T) -> Self {
|
|
||||||
if T::min_value().is_zero() {
|
|
||||||
// unsigned data types
|
|
||||||
// `u128` is the largest unsigned datatype, any other type will fit.
|
|
||||||
NumVal::Unsigned(value.to_u128().unwrap())
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// signed data types
|
|
||||||
// `i128` is the largest unsigned datatype, any other type will fit.
|
|
||||||
NumVal::Signed(value.to_i128().unwrap())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// Display Errors with a nice little reason
|
|
||||||
impl Display for Error {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
||||||
match self {
|
|
||||||
Self::SyntaxError(reason) => {
|
|
||||||
write!(f, "Syntax Error: {}", reason)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
impl<T: PrimInt> From<T> for Value where
|
|
||||||
u128: TryFrom<T>,
|
|
||||||
u128: TryFrom<T> {
|
|
||||||
fn from(value: T) -> Self {
|
|
||||||
NumVal::from(value).into()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
impl From<NumVal> for Value {
|
|
||||||
fn from(value: NumVal) -> Self {
|
|
||||||
Value::Numerical(value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
impl Display for Value {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
||||||
match self {
|
|
||||||
Value::Numerical(val) => {
|
|
||||||
write!(f, "{}", val)
|
|
||||||
}
|
|
||||||
Value::Complex(val) => {
|
|
||||||
write!(f, "{}", val)
|
|
||||||
}
|
|
||||||
Value::Variable(val) => {
|
|
||||||
write!(f, "{}", val)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
impl Display for NumVal {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
||||||
match self {
|
|
||||||
NumVal::Float(val) => {
|
|
||||||
write!(f, "{val}")
|
|
||||||
}
|
|
||||||
NumVal::Signed(val) => {
|
|
||||||
write!(f, "{val}")
|
|
||||||
}
|
|
||||||
NumVal::Unsigned(val) => {
|
|
||||||
write!(f, "{val}")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
impl Display for ComplVal {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
||||||
write!(f, "")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
impl Display for VarVal {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
||||||
write!(f, "")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//// PUBLIC FUNCTIONS //////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
//// PRIVATE FUNCTIONS /////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
@ -19,14 +19,7 @@
|
||||||
#![warn(clippy::pedantic)]
|
#![warn(clippy::pedantic)]
|
||||||
|
|
||||||
//// IMPORTS ///////////////////////////////////////////////////////////////////////////////////////
|
//// IMPORTS ///////////////////////////////////////////////////////////////////////////////////////
|
||||||
pub mod base;
|
use libpt_log;
|
||||||
pub use base::{Error, Result, Value};
|
|
||||||
pub mod term;
|
|
||||||
pub use term::*;
|
|
||||||
|
|
||||||
#[allow(unused_imports)] // we possibly want to use all log levels
|
|
||||||
use libpt_log::*;
|
|
||||||
#[allow(unused_imports)] // import more complex math stuff from there
|
|
||||||
use libpt_math;
|
use libpt_math;
|
||||||
|
|
||||||
//// TYPES /////////////////////////////////////////////////////////////////////////////////////////
|
//// TYPES /////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -40,44 +33,8 @@ use libpt_math;
|
||||||
//// ENUMS /////////////////////////////////////////////////////////////////////////////////////////
|
//// ENUMS /////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
//// STRUCTS ///////////////////////////////////////////////////////////////////////////////////////
|
//// STRUCTS ///////////////////////////////////////////////////////////////////////////////////////
|
||||||
/// ## A Calculator struct
|
|
||||||
///
|
|
||||||
/// This struct does not do anything at the moment, but aims to be the target for high level
|
|
||||||
/// control. Instead of using the [`Calculator`], you could just use the [`Term`] struct for
|
|
||||||
/// lower level control.
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct Calculator;
|
|
||||||
|
|
||||||
//// IMPLEMENTATION ////////////////////////////////////////////////////////////////////////////////
|
//// IMPLEMENTATION ////////////////////////////////////////////////////////////////////////////////
|
||||||
impl Calculator {
|
|
||||||
/// Do a single calculation without doing anything else
|
|
||||||
pub fn oneshot(t: String) -> Result<Value> {
|
|
||||||
trace!(orig=t, "parsing original string to Term");
|
|
||||||
let t = Term::new(t)?;
|
|
||||||
trace!("term has been parsed, starting Calculation");
|
|
||||||
debug!("parsed term: {t:#?}");
|
|
||||||
Self::calc(t)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// ## Calculate a [`Term`]
|
|
||||||
///
|
|
||||||
/// This method makes use of the
|
|
||||||
/// [shunting yard algorithm](https://en.wikipedia.org/wiki/Shunting_yard_algorithm) to
|
|
||||||
/// Calculate the final value of any term.
|
|
||||||
///
|
|
||||||
/// This method only processes a single term at a time, without caching.
|
|
||||||
pub fn calc(mut t: Term) -> Result<Value> {
|
|
||||||
trace!("Calculating term {t:?}");
|
|
||||||
t.prepare()?;
|
|
||||||
t.process()?;
|
|
||||||
if t.result.is_none() {
|
|
||||||
let reason = format!("Term was processed but no result was assigned.");
|
|
||||||
// FIXME: unfitting error type
|
|
||||||
return Err(Error::SyntaxError(reason))
|
|
||||||
}
|
|
||||||
return t.result.unwrap()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//// PUBLIC FUNCTIONS //////////////////////////////////////////////////////////////////////////////
|
//// PUBLIC FUNCTIONS //////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
|
@ -1,223 +0,0 @@
|
||||||
//! # A term that can be the input for calculation
|
|
||||||
//!
|
|
||||||
//! Short description
|
|
||||||
//!
|
|
||||||
//! Details
|
|
||||||
//!
|
|
||||||
//! ## Section 1
|
|
||||||
//!
|
|
||||||
//! ## Section 2
|
|
||||||
|
|
||||||
//// 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::collections::VecDeque;
|
|
||||||
|
|
||||||
//// IMPORTS ///////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
pub use super::{Error, Result, Value, base::{self, *}};
|
|
||||||
#[allow(unused_imports)] // we possibly want to use all log levels
|
|
||||||
use libpt_log::*;
|
|
||||||
#[allow(unused_imports)] // import more complex math stuff from there
|
|
||||||
use libpt_math;
|
|
||||||
|
|
||||||
//// TYPES /////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
//// CONSTANTS /////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
//// STATICS ///////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
//// MACROS ////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
//// ENUMS /////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// ## Parsed value to be calculated
|
|
||||||
///
|
|
||||||
/// This enum represents anything that goes to the output queue of [`Term::prepare()`] and will
|
|
||||||
/// then be used to actually calculate something in [`Term::process()`].
|
|
||||||
#[derive(Debug)]
|
|
||||||
enum Token {
|
|
||||||
/// Some kind of operator
|
|
||||||
#[allow(unused)] // tmp
|
|
||||||
Operator(Operator),
|
|
||||||
/// A concrete value that we can calculate something with. May be a constant, integer, float,
|
|
||||||
/// etc.
|
|
||||||
/// The Token has a value that can be used in calculation
|
|
||||||
Value(super::base::Value),
|
|
||||||
/// A variable of some kind that will be present in the result
|
|
||||||
#[allow(unused)] // tmp
|
|
||||||
Variable(char),
|
|
||||||
}
|
|
||||||
//// STRUCTS ///////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// ## Term that can be calculated
|
|
||||||
///
|
|
||||||
/// Represents a signular term, that can be calculated. Terms will be evaluated by the [`Term::prepare`]
|
|
||||||
/// function, afterwards calculated (as much as possible) in the [`Term::process`] function.
|
|
||||||
///
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct Term {
|
|
||||||
/// the original expression to calculate
|
|
||||||
pub original: String,
|
|
||||||
/// the filtered text of the expression, only with relevant information
|
|
||||||
pub text: String,
|
|
||||||
/// the calculated result, may be of diffrent types, see [`crate::math::calculator::result`].
|
|
||||||
pub result: Option<Result<Value>>,
|
|
||||||
/////////////////////////////////////
|
|
||||||
///// internal values following /////
|
|
||||||
/////////////////////////////////////
|
|
||||||
#[allow(unused)] // tmp
|
|
||||||
operator_stack: Vec<Operator>,
|
|
||||||
output_queue: VecDeque<Token>
|
|
||||||
}
|
|
||||||
|
|
||||||
//// IMPLEMENTATION ////////////////////////////////////////////////////////////////////////////////
|
|
||||||
impl Term {
|
|
||||||
/// Build a new term from an expression
|
|
||||||
///
|
|
||||||
/// Invalid terms will result in an [`Err`].
|
|
||||||
pub fn new(orig: String) -> Result<Term> {
|
|
||||||
return Ok(
|
|
||||||
Term {
|
|
||||||
original: orig,
|
|
||||||
text: String::new(), // will be initialized in `prepare()`
|
|
||||||
result: None,
|
|
||||||
operator_stack: Vec::new(),
|
|
||||||
output_queue: VecDeque::new()
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Prepare the term for the processing.
|
|
||||||
pub fn prepare(&mut self) -> Result<()> {
|
|
||||||
trace!("preparing term: {:#?}", self);
|
|
||||||
self.text = Self::filter(&self.original)?;
|
|
||||||
|
|
||||||
// Storage for unfinished tokens
|
|
||||||
let _unfinished_chars: Vec<char> = Vec::new();
|
|
||||||
|
|
||||||
for (_index, c) in self.original.chars().enumerate() {
|
|
||||||
// this will be a mess, but it has to be before i can sort the mess.
|
|
||||||
match c {
|
|
||||||
// TODO: make function to check if character is an operator, use it
|
|
||||||
_ => {
|
|
||||||
let reason = format!("The meaning of '{c}' could not be identified.");
|
|
||||||
warn!(reason);
|
|
||||||
return Err(Error::SyntaxError(reason));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Process a prepared term, calculating it's result
|
|
||||||
pub fn process(&mut self) -> Result<()> {
|
|
||||||
debug!("processing term: {:#?}", self);
|
|
||||||
debug!("queue: {:#?}", self.output_queue);
|
|
||||||
// TODO: process RPN and set result
|
|
||||||
self.result = Some(Ok(19.into()));
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Convert a character into a token
|
|
||||||
///
|
|
||||||
/// Returns: A tuple with a [`Token`] and a [`bool`]. If the bool is false, the [`Token`] is
|
|
||||||
/// marked as "incomplete", meaning that the character cannot be used yet.
|
|
||||||
#[allow(unused)] // tmp
|
|
||||||
fn to_tok(_s: Vec<char>) -> Result<Token> {
|
|
||||||
Ok(19.into())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// only leave relevant chars for calculation
|
|
||||||
// TODO: make function to check if character is an operator, use it
|
|
||||||
fn filter(s: &str) -> Result<String> {
|
|
||||||
// pre checks
|
|
||||||
// NOTE: Apperently, "alphanumeric" in Rust is a pretty broad term.
|
|
||||||
// Even CJK characters or Japanese Kana are allowed:
|
|
||||||
// - 'さ' alphanumeric
|
|
||||||
// - '数' alphanumeric
|
|
||||||
// - '学' alphanumeric
|
|
||||||
// - '+' not alphanumeric
|
|
||||||
for c in s.chars() {
|
|
||||||
#[cfg(debug_assertions)] {
|
|
||||||
debug!("filter checks for '{c}':
|
|
||||||
alphanumeric: {}
|
|
||||||
allowed special: {}
|
|
||||||
EXCEPT IF
|
|
||||||
ascii control: {}
|
|
||||||
",
|
|
||||||
!c.is_alphanumeric(),
|
|
||||||
!Self::is_allowed_special_c(&c),
|
|
||||||
c.is_ascii_control(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
if
|
|
||||||
(
|
|
||||||
!c.is_alphanumeric() ||
|
|
||||||
!Self::is_allowed_special_c(&c)
|
|
||||||
)
|
|
||||||
&&
|
|
||||||
(
|
|
||||||
c.is_ascii_control()
|
|
||||||
)
|
|
||||||
{
|
|
||||||
// TODO: allow any unicode char to be a variable
|
|
||||||
let reason = format!("'{c}' is not a valid character, only alphanumeric, punctuation, operators are allowed.");
|
|
||||||
warn!(reason);
|
|
||||||
return Err(Error::SyntaxError(reason));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// filter out single chars
|
|
||||||
let mut filtered = String::new();
|
|
||||||
for c in s.chars() {
|
|
||||||
if !Self::is_ignore(&c) {
|
|
||||||
filtered.push(c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Ok(filtered)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// check if we should ignore this character
|
|
||||||
fn is_ignore(c: &char) -> bool {
|
|
||||||
match *c {
|
|
||||||
' ' => true,
|
|
||||||
_ => false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// allowed special chars
|
|
||||||
fn is_allowed_special_c(c: &char) -> bool {
|
|
||||||
match *c {
|
|
||||||
'+' | '-' | '*' | '/' | '%' => true,
|
|
||||||
_ => false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// Helper methods for Tokens
|
|
||||||
impl Token { }
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
impl<T> From<T> for Token where
|
|
||||||
T: Into<Value>,
|
|
||||||
T: PrimInt,
|
|
||||||
u128: TryFrom<T>
|
|
||||||
{
|
|
||||||
fn from(value: T) -> Self {
|
|
||||||
Token::Value(base::Value::from(value))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//// PUBLIC FUNCTIONS //////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
//// PRIVATE FUNCTIONS /////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
@ -13,3 +13,6 @@ keywords.workspace = true
|
||||||
categories.workspace = true
|
categories.workspace = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
anyhow = "1.0.79"
|
||||||
|
cucumber = "0.20.2"
|
||||||
|
libpt-log = {path = "../libpt-log" }
|
||||||
|
|
|
@ -10,11 +10,9 @@
|
||||||
// we want docs
|
// we want docs
|
||||||
#![warn(missing_docs)]
|
#![warn(missing_docs)]
|
||||||
#![warn(rustdoc::missing_crate_level_docs)]
|
#![warn(rustdoc::missing_crate_level_docs)]
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// we want Debug everywhere.
|
// we want Debug everywhere.
|
||||||
#![warn(missing_debug_implementations)]
|
#![warn(missing_debug_implementations)]
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// enable clippy's extra lints, the pedantic version
|
// enable clippy's extra lints, the pedantic version
|
||||||
#![warn(clippy::pedantic)]
|
#![warn(clippy::pedantic)]
|
||||||
|
|
|
@ -6,11 +6,9 @@
|
||||||
// we want docs
|
// we want docs
|
||||||
#![warn(missing_docs)]
|
#![warn(missing_docs)]
|
||||||
#![warn(rustdoc::missing_crate_level_docs)]
|
#![warn(rustdoc::missing_crate_level_docs)]
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// we want Debug everywhere.
|
// we want Debug everywhere.
|
||||||
#![warn(missing_debug_implementations)]
|
#![warn(missing_debug_implementations)]
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// enable clippy's extra lints, the pedantic version
|
// enable clippy's extra lints, the pedantic version
|
||||||
#![warn(clippy::pedantic)]
|
#![warn(clippy::pedantic)]
|
||||||
|
|
|
@ -15,3 +15,7 @@ categories.workspace = true
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
anyhow = { workspace = true }
|
||||||
|
thiserror = { workspace = true }
|
||||||
|
libpt-log = {path = "../libpt-log" }
|
||||||
|
libpt-bintols = {path = "../libpt-bintols" }
|
||||||
|
|
|
@ -4,3 +4,175 @@
|
||||||
//! module.
|
//! module.
|
||||||
//!
|
//!
|
||||||
//! This crate is currently empty.
|
//! This crate is currently empty.
|
||||||
|
|
||||||
|
use anyhow::{bail, Result};
|
||||||
|
use libpt_bintols::display::{bytes_to_bin, humanbytes};
|
||||||
|
use libpt_log::{debug, error, info, trace, warn};
|
||||||
|
use std::io::{prelude::*, BufReader, Read, SeekFrom};
|
||||||
|
|
||||||
|
const BYTES_PER_LINE: usize = 16;
|
||||||
|
const LINE_SEP_HORIZ: char = '─';
|
||||||
|
const LINE_SEP_VERT: char = '│';
|
||||||
|
|
||||||
|
pub struct HeduConfig {
|
||||||
|
pub chars: bool,
|
||||||
|
pub skip: usize,
|
||||||
|
pub show_identical: bool,
|
||||||
|
pub limit: usize,
|
||||||
|
stop: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl HeduConfig {
|
||||||
|
pub fn new(chars: bool, skip: usize, show_identical: bool, limit: usize) -> Self {
|
||||||
|
HeduConfig {
|
||||||
|
chars,
|
||||||
|
skip,
|
||||||
|
show_identical,
|
||||||
|
limit: limit,
|
||||||
|
stop: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn dump(data: &mut dyn DataSource, mut config: HeduConfig) -> Result<()> {
|
||||||
|
// prepare some variables
|
||||||
|
let mut buf: [[u8; BYTES_PER_LINE]; 2] = [[0; BYTES_PER_LINE]; 2];
|
||||||
|
let mut alt_buf = 0usize;
|
||||||
|
let mut byte_counter: usize = 0;
|
||||||
|
let mut len: usize;
|
||||||
|
|
||||||
|
// skip a given number of bytes
|
||||||
|
if config.skip > 0 {
|
||||||
|
data.skip(config.skip)?;
|
||||||
|
byte_counter += config.skip;
|
||||||
|
debug!("Skipped {}", humanbytes(config.skip));
|
||||||
|
}
|
||||||
|
|
||||||
|
// print the head
|
||||||
|
print!("DATA IDX {LINE_SEP_VERT} DATA AS HEX");
|
||||||
|
if config.chars {
|
||||||
|
print!("{:width$} {LINE_SEP_VERT} FOO", "", width = 37);
|
||||||
|
}
|
||||||
|
println!();
|
||||||
|
if config.chars {
|
||||||
|
println!("{}", format!("{LINE_SEP_HORIZ}").repeat(80));
|
||||||
|
} else {
|
||||||
|
println!("{}", format!("{LINE_SEP_HORIZ}").repeat(59));
|
||||||
|
}
|
||||||
|
|
||||||
|
// data dump loop
|
||||||
|
len = rd_data(data, &mut buf, &mut alt_buf, &mut byte_counter, &mut config).unwrap();
|
||||||
|
while len > 0 {
|
||||||
|
print!("{:08X} {LINE_SEP_VERT} ", byte_counter);
|
||||||
|
for i in 0..len {
|
||||||
|
if i as usize % BYTES_PER_LINE == BYTES_PER_LINE / 2 {
|
||||||
|
print!(" ");
|
||||||
|
}
|
||||||
|
print!("{:02X} ", buf[alt_buf][i]);
|
||||||
|
}
|
||||||
|
if len == BYTES_PER_LINE / 2 {
|
||||||
|
print!(" ")
|
||||||
|
}
|
||||||
|
for i in 0..(BYTES_PER_LINE - len) {
|
||||||
|
if i as usize % BYTES_PER_LINE == BYTES_PER_LINE / 2 {
|
||||||
|
print!(" ");
|
||||||
|
}
|
||||||
|
print!(" ");
|
||||||
|
}
|
||||||
|
if config.chars {
|
||||||
|
print!("{LINE_SEP_VERT} |");
|
||||||
|
for i in 0..len {
|
||||||
|
print!("{}", mask_chars(buf[alt_buf][i] as char));
|
||||||
|
}
|
||||||
|
print!("|");
|
||||||
|
}
|
||||||
|
println!();
|
||||||
|
|
||||||
|
// loop breaker logic
|
||||||
|
if config.stop {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// after line logic
|
||||||
|
len = rd_data(data, &mut buf, &mut alt_buf, &mut byte_counter, &mut config).unwrap();
|
||||||
|
alt_buf ^= 1; // toggle the alt buf
|
||||||
|
if buf[0] == buf[1] && len == BYTES_PER_LINE && !config.show_identical {
|
||||||
|
trace!(buf = format!("{:?}", buf), "found a duplicating line");
|
||||||
|
let start_line = byte_counter;
|
||||||
|
while buf[0] == buf[1] && len == BYTES_PER_LINE {
|
||||||
|
len =
|
||||||
|
rd_data(data, &mut buf, &mut alt_buf, &mut byte_counter, &mut config).unwrap();
|
||||||
|
byte_counter += BYTES_PER_LINE;
|
||||||
|
}
|
||||||
|
println!(
|
||||||
|
"^^^^^^^^ {LINE_SEP_VERT} (repeats {} lines)",
|
||||||
|
byte_counter - start_line
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// switch to the second half of the buf, the original half is stored the old buffer
|
||||||
|
// We detect duplicate lines with this
|
||||||
|
alt_buf ^= 1; // toggle the alt buf
|
||||||
|
}
|
||||||
|
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 '<27>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn rd_data(
|
||||||
|
data: &mut dyn DataSource,
|
||||||
|
buf: &mut [[u8; BYTES_PER_LINE]; 2],
|
||||||
|
alt_buf: &mut usize,
|
||||||
|
byte_counter: &mut usize,
|
||||||
|
config: &mut HeduConfig,
|
||||||
|
) -> Result<usize> {
|
||||||
|
match data.read(&mut buf[*alt_buf]) {
|
||||||
|
Ok(mut len) => {
|
||||||
|
*byte_counter += len; // FIXME: incremented too early! dump always starts at 0x10
|
||||||
|
if config.limit != 0 && *byte_counter >= config.limit {
|
||||||
|
trace!(
|
||||||
|
byte_counter,
|
||||||
|
limit = config.limit,
|
||||||
|
len,
|
||||||
|
nlen = (config.limit % BYTES_PER_LINE),
|
||||||
|
"byte counter is farther than limit"
|
||||||
|
);
|
||||||
|
len = config.limit % BYTES_PER_LINE;
|
||||||
|
config.stop = true;
|
||||||
|
}
|
||||||
|
return Ok(len);
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
error!("error while reading data: {err}");
|
||||||
|
bail!(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -16,7 +16,8 @@ categories.workspace = true
|
||||||
tracing = "0.1.37"
|
tracing = "0.1.37"
|
||||||
tracing-appender = "0.2.2"
|
tracing-appender = "0.2.2"
|
||||||
tracing-subscriber = "0.3.17"
|
tracing-subscriber = "0.3.17"
|
||||||
pyo3 = {workspace = true}
|
anyhow = { workspace = true }
|
||||||
|
thiserror = { workspace = true }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
gag = "1.0.0"
|
gag = "1.0.0"
|
||||||
|
|
|
@ -12,12 +12,11 @@
|
||||||
#![warn(clippy::pedantic)]
|
#![warn(clippy::pedantic)]
|
||||||
|
|
||||||
//// IMPORTS ///////////////////////////////////////////////////////////////////////////////////////
|
//// IMPORTS ///////////////////////////////////////////////////////////////////////////////////////
|
||||||
use pyo3::{exceptions::PyException, PyErr};
|
use anyhow;
|
||||||
|
use thiserror::Error;
|
||||||
use tracing::subscriber::SetGlobalDefaultError;
|
use tracing::subscriber::SetGlobalDefaultError;
|
||||||
|
|
||||||
//// TYPES /////////////////////////////////////////////////////////////////////////////////////////
|
//// TYPES /////////////////////////////////////////////////////////////////////////////////////////
|
||||||
/// a quick alias for a result with a [`Error`]
|
|
||||||
pub type Result<T> = std::result::Result<T, Error>;
|
|
||||||
|
|
||||||
//// CONSTANTS /////////////////////////////////////////////////////////////////////////////////////
|
//// CONSTANTS /////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
@ -27,12 +26,16 @@ pub type Result<T> = std::result::Result<T, Error>;
|
||||||
|
|
||||||
//// ENUMS /////////////////////////////////////////////////////////////////////////////////////////
|
//// ENUMS /////////////////////////////////////////////////////////////////////////////////////////
|
||||||
/// ## Errors for the [Logger](super::Logger)
|
/// ## Errors for the [Logger](super::Logger)
|
||||||
|
#[derive(Error)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
/// Bad IO operation
|
/// Bad IO operation
|
||||||
|
#[error("Bad IO operation")]
|
||||||
IO(std::io::Error),
|
IO(std::io::Error),
|
||||||
/// Various errors raised when the messenger is used in a wrong way
|
/// Various errors raised when the messenger is used in a wrong way
|
||||||
|
#[error("Bad usage")]
|
||||||
Usage(String),
|
Usage(String),
|
||||||
/// Could not assign logger as the global default
|
/// Could not assign logger as the global default
|
||||||
|
#[error("Could not assign as global default")] // TODO: make this more clear
|
||||||
SetGlobalDefaultFail(SetGlobalDefaultError),
|
SetGlobalDefaultFail(SetGlobalDefaultError),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,19 +55,6 @@ impl From<SetGlobalDefaultError> for Error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
impl Into<PyErr> for Error {
|
|
||||||
fn into(self) -> PyErr {
|
|
||||||
match self {
|
|
||||||
Error::IO(err) => PyException::new_err(format!("LoggerError: IO {err:?}")),
|
|
||||||
Error::Usage(err) => PyException::new_err(format!("LoggerError: Usage {err}")),
|
|
||||||
Error::SetGlobalDefaultFail(err) => {
|
|
||||||
PyException::new_err(format!("LoggerError: SetGlobalDefaultFail {err}"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
impl std::fmt::Debug for Error {
|
impl std::fmt::Debug for Error {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
@ -76,18 +66,6 @@ impl std::fmt::Debug for Error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
impl std::fmt::Display for Error {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
||||||
match self {
|
|
||||||
Error::IO(e) => write!(f, "IO Error {e}"),
|
|
||||||
Error::Usage(e) => write!(f, "Usage Error {e}"),
|
|
||||||
Error::SetGlobalDefaultFail(e) => write!(f, "SetGlobalDefaultFail {e}"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//// PUBLIC FUNCTIONS //////////////////////////////////////////////////////////////////////////////
|
//// PUBLIC FUNCTIONS //////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
//// PRIVATE FUNCTIONS /////////////////////////////////////////////////////////////////////////////
|
//// PRIVATE FUNCTIONS /////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
//// IMPORTS ///////////////////////////////////////////////////////////////////////////////////////
|
//// IMPORTS ///////////////////////////////////////////////////////////////////////////////////////
|
||||||
use std::{
|
use std::{
|
||||||
fmt,
|
fmt,
|
||||||
|
ops::Deref,
|
||||||
path::PathBuf,
|
path::PathBuf,
|
||||||
sync::atomic::{AtomicBool, Ordering},
|
sync::atomic::{AtomicBool, Ordering},
|
||||||
};
|
};
|
||||||
|
@ -27,10 +28,20 @@ pub mod error;
|
||||||
use error::*;
|
use error::*;
|
||||||
|
|
||||||
pub use tracing::{debug, error, info, trace, warn, Level};
|
pub use tracing::{debug, error, info, trace, warn, Level};
|
||||||
use tracing_appender;
|
use tracing_appender::{
|
||||||
use tracing_subscriber::{prelude::*, fmt::format::FmtSpan};
|
self,
|
||||||
|
non_blocking::{NonBlocking, WorkerGuard},
|
||||||
|
};
|
||||||
|
use tracing_subscriber::{
|
||||||
|
fmt::{
|
||||||
|
format::FmtSpan,
|
||||||
|
time::{self, FormatTime},
|
||||||
|
},
|
||||||
|
prelude::*,
|
||||||
|
};
|
||||||
|
|
||||||
|
use anyhow::{bail, Result};
|
||||||
|
|
||||||
use pyo3::prelude::*;
|
|
||||||
//// CONSTANTS /////////////////////////////////////////////////////////////////////////////////////
|
//// CONSTANTS /////////////////////////////////////////////////////////////////////////////////////
|
||||||
/// The log level used when none is specified
|
/// The log level used when none is specified
|
||||||
pub const DEFAULT_LOG_LEVEL: Level = Level::INFO;
|
pub const DEFAULT_LOG_LEVEL: Level = Level::INFO;
|
||||||
|
@ -47,8 +58,7 @@ static INITIALIZED: AtomicBool = AtomicBool::new(false);
|
||||||
///
|
///
|
||||||
/// This struct exists mainly for the python module, so that we can use the same logger with both
|
/// This struct exists mainly for the python module, so that we can use the same logger with both
|
||||||
/// python and rust.
|
/// python and rust.
|
||||||
#[pyclass]
|
pub struct Logger;
|
||||||
pub struct Logger {}
|
|
||||||
|
|
||||||
//// IMPLEMENTATION ////////////////////////////////////////////////////////////////////////////////
|
//// IMPLEMENTATION ////////////////////////////////////////////////////////////////////////////////
|
||||||
/// ## Main implementation
|
/// ## Main implementation
|
||||||
|
@ -77,6 +87,33 @@ impl Logger {
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// ## initializes the logger
|
||||||
|
///
|
||||||
|
/// Will enable the logger to be used. This is a version that shows less information,
|
||||||
|
/// 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<Level>) -> Result<()> {
|
||||||
|
Self::init_customized(
|
||||||
|
false,
|
||||||
|
PathBuf::from(DEFAULT_LOG_DIR),
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
max_level.unwrap_or(DEFAULT_LOG_LEVEL),
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,58 +131,99 @@ impl Logger {
|
||||||
display_thread_ids: bool,
|
display_thread_ids: bool,
|
||||||
display_thread_names: bool,
|
display_thread_names: bool,
|
||||||
display_line_number: bool,
|
display_line_number: bool,
|
||||||
|
pretty: bool,
|
||||||
|
show_time: bool,
|
||||||
|
uptime: bool, // uptime instead of system time
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
// only init if no init has been performed yet
|
// only init if no init has been performed yet
|
||||||
if INITIALIZED.load(Ordering::Relaxed) {
|
if INITIALIZED.load(Ordering::Relaxed) {
|
||||||
warn!("trying to reinitialize the logger, ignoring");
|
warn!("trying to reinitialize the logger, ignoring");
|
||||||
return Err(Error::Usage(format!("logging is already initialized")));
|
bail!(Error::Usage(format!("logging is already initialized")));
|
||||||
} else {
|
}
|
||||||
let filter = tracing_subscriber::filter::FilterFn::new(|_metadata| {
|
let subscriber = tracing_subscriber::fmt::Subscriber::builder()
|
||||||
// let mut filter = false;
|
|
||||||
//
|
|
||||||
// // if it's this lib, continue
|
|
||||||
// filter |= metadata.target().contains(env!("CARGO_PKG_NAME"));
|
|
||||||
// filter |= metadata.target().contains("libpt");
|
|
||||||
//
|
|
||||||
// // if it's another crate, only show above debug
|
|
||||||
// filter |= metadata.level() > &Level::DEBUG;
|
|
||||||
//
|
|
||||||
// filter
|
|
||||||
// FIXME: Make the filter customizable with sane defaults. Don't block the
|
|
||||||
// executing crate.
|
|
||||||
true
|
|
||||||
});
|
|
||||||
|
|
||||||
let basic_subscriber = tracing_subscriber::fmt::Subscriber::builder()
|
|
||||||
// subscriber configuration
|
|
||||||
.with_ansi(ansi)
|
|
||||||
.with_file(display_filename)
|
|
||||||
.with_level(display_level)
|
.with_level(display_level)
|
||||||
.with_target(display_target)
|
|
||||||
.with_max_level(max_level)
|
.with_max_level(max_level)
|
||||||
|
.with_ansi(ansi)
|
||||||
|
.with_target(display_target)
|
||||||
|
.with_file(display_filename)
|
||||||
.with_thread_ids(display_thread_ids)
|
.with_thread_ids(display_thread_ids)
|
||||||
.with_line_number(display_line_number)
|
.with_line_number(display_line_number)
|
||||||
.with_thread_names(display_thread_names)
|
.with_thread_names(display_thread_names)
|
||||||
.with_span_events(FmtSpan::FULL)
|
.with_span_events(FmtSpan::FULL);
|
||||||
//.pretty // too verbose and over multiple lines, a bit like python tracebacks
|
// I know this is hacky, but I couldn't get it any other way. I couldn't even find a
|
||||||
.finish()
|
// project that could do it any other way. You can't apply one after another, because the
|
||||||
// add layers
|
// type is changed every time. When using Box<dyn Whatever>, some methods complain about
|
||||||
.with(filter);
|
// not being in trait bounds.
|
||||||
|
// TODO: somehow find a better solution for this
|
||||||
if log_to_file {
|
match (log_to_file, show_time, pretty, uptime) {
|
||||||
let file_appender = tracing_appender::rolling::daily(log_dir, "log");
|
(true, true, true, true) => {
|
||||||
let (file_writer, _guard) = tracing_appender::non_blocking(file_appender);
|
let subscriber = subscriber
|
||||||
let layered_subscriber = basic_subscriber
|
.with_writer(new_file_appender(log_dir))
|
||||||
.with(tracing_subscriber::fmt::Layer::default().with_writer(file_writer));
|
.with_timer(time::uptime())
|
||||||
tracing::subscriber::set_global_default(layered_subscriber)?;
|
.pretty()
|
||||||
} else {
|
.finish();
|
||||||
tracing::subscriber::set_global_default(basic_subscriber)?;
|
tracing::subscriber::set_global_default(subscriber)?;
|
||||||
|
}
|
||||||
|
(true, true, true, false) => {
|
||||||
|
let subscriber = subscriber
|
||||||
|
.with_writer(new_file_appender(log_dir))
|
||||||
|
.pretty()
|
||||||
|
.finish();
|
||||||
|
tracing::subscriber::set_global_default(subscriber)?;
|
||||||
|
}
|
||||||
|
(true, false, true, _) => {
|
||||||
|
let subscriber = subscriber
|
||||||
|
.with_writer(new_file_appender(log_dir))
|
||||||
|
.without_time()
|
||||||
|
.pretty()
|
||||||
|
.finish();
|
||||||
|
tracing::subscriber::set_global_default(subscriber)?;
|
||||||
|
}
|
||||||
|
(true, true, false, true) => {
|
||||||
|
let subscriber = subscriber
|
||||||
|
.with_writer(new_file_appender(log_dir))
|
||||||
|
.with_timer(time::uptime())
|
||||||
|
.finish();
|
||||||
|
tracing::subscriber::set_global_default(subscriber)?;
|
||||||
|
}
|
||||||
|
(true, true, false, false) => {
|
||||||
|
let subscriber = subscriber.with_writer(new_file_appender(log_dir)).finish();
|
||||||
|
tracing::subscriber::set_global_default(subscriber)?;
|
||||||
|
}
|
||||||
|
(true, false, false, _) => {
|
||||||
|
let file_appender = tracing_appender::rolling::daily(log_dir.clone(), "log");
|
||||||
|
let (file_writer, _guard) = tracing_appender::non_blocking(file_appender);
|
||||||
|
let subscriber = subscriber.with_writer(file_writer).without_time().finish();
|
||||||
|
tracing::subscriber::set_global_default(subscriber)?;
|
||||||
|
}
|
||||||
|
(false, true, true, true) => {
|
||||||
|
let subscriber = subscriber.pretty().with_timer(time::uptime()).finish();
|
||||||
|
tracing::subscriber::set_global_default(subscriber)?;
|
||||||
|
}
|
||||||
|
(false, true, true, false) => {
|
||||||
|
let subscriber = subscriber.pretty().with_timer(time::uptime()).finish();
|
||||||
|
tracing::subscriber::set_global_default(subscriber)?;
|
||||||
|
}
|
||||||
|
(false, false, true, _) => {
|
||||||
|
let subscriber = subscriber.without_time().pretty().finish();
|
||||||
|
tracing::subscriber::set_global_default(subscriber)?;
|
||||||
|
}
|
||||||
|
(false, true, false, true) => {
|
||||||
|
let subscriber = subscriber.with_timer(time::uptime()).finish();
|
||||||
|
tracing::subscriber::set_global_default(subscriber)?;
|
||||||
|
}
|
||||||
|
(false, true, false, false) => {
|
||||||
|
let subscriber = subscriber.finish();
|
||||||
|
tracing::subscriber::set_global_default(subscriber)?;
|
||||||
|
}
|
||||||
|
(false, false, false, _) => {
|
||||||
|
let subscriber = subscriber.without_time().finish();
|
||||||
|
tracing::subscriber::set_global_default(subscriber)?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
INITIALIZED.store(true, Ordering::Relaxed);
|
INITIALIZED.store(true, Ordering::Relaxed);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// ## logging at [`Level::ERROR`]
|
/// ## logging at [`Level::ERROR`]
|
||||||
pub fn error<T>(&self, printable: T)
|
pub fn error<T>(&self, printable: T)
|
||||||
|
@ -184,61 +262,6 @@ impl Logger {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// ## Implementation of the python interface
|
|
||||||
#[pymethods]
|
|
||||||
impl Logger {
|
|
||||||
/// ## Python version of [`new()`](Logger::new)
|
|
||||||
#[new]
|
|
||||||
pub fn py_new() -> PyResult<Self> {
|
|
||||||
Ok(Logger::new())
|
|
||||||
}
|
|
||||||
/// ## Python version of [`init()`](Logger::init)
|
|
||||||
#[pyo3(name = "init")]
|
|
||||||
#[staticmethod]
|
|
||||||
pub fn py_init(log_dir: Option<PathBuf>, max_level: Option<String>) -> Result<()> {
|
|
||||||
Self::init(
|
|
||||||
log_dir,
|
|
||||||
match max_level {
|
|
||||||
Some(s) => match s.to_uppercase().as_str() {
|
|
||||||
"TRACE" => Some(tracing::Level::TRACE),
|
|
||||||
"DEBUG" => Some(tracing::Level::DEBUG),
|
|
||||||
"INFO" => Some(tracing::Level::INFO),
|
|
||||||
"WARN" => Some(tracing::Level::WARN),
|
|
||||||
"ERROR" => Some(tracing::Level::ERROR),
|
|
||||||
_ => return Err(Error::Usage(format!("'{s}' is not a valid log level"))),
|
|
||||||
},
|
|
||||||
None => None,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
/// ## Python version of [`error()`](Logger::error)
|
|
||||||
#[pyo3(name = "error")]
|
|
||||||
pub fn py_error(&self, printable: String) {
|
|
||||||
self.error(printable)
|
|
||||||
}
|
|
||||||
/// ## Python version of [`warn()`](Logger::warn)
|
|
||||||
#[pyo3(name = "warn")]
|
|
||||||
pub fn py_warn(&self, printable: String) {
|
|
||||||
self.warn(printable)
|
|
||||||
}
|
|
||||||
/// ## Python version of [`info()`](Logger::info)
|
|
||||||
#[pyo3(name = "info")]
|
|
||||||
pub fn py_info(&self, printable: String) {
|
|
||||||
self.info(printable)
|
|
||||||
}
|
|
||||||
/// ## Python version of [`debug()`](Logger::debug)
|
|
||||||
#[pyo3(name = "debug")]
|
|
||||||
pub fn py_debug(&self, printable: String) {
|
|
||||||
self.debug(printable)
|
|
||||||
}
|
|
||||||
/// ## Python version of [`trace()`](Logger::trace)
|
|
||||||
#[pyo3(name = "trace")]
|
|
||||||
pub fn py_trace(&self, printable: String) {
|
|
||||||
self.trace(printable)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
impl fmt::Debug for Logger {
|
impl fmt::Debug for Logger {
|
||||||
/// ## DEBUG representation for [`Logger`]
|
/// ## DEBUG representation for [`Logger`]
|
||||||
|
@ -254,4 +277,7 @@ impl fmt::Debug for Logger {
|
||||||
//// PUBLIC FUNCTIONS //////////////////////////////////////////////////////////////////////////////
|
//// PUBLIC FUNCTIONS //////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
//// PRIVATE 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;
|
||||||
|
}
|
||||||
|
|
|
@ -16,9 +16,9 @@ categories.workspace = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
humantime = "2.1.0"
|
humantime = "2.1.0"
|
||||||
libpt-core = { version = "0.1.0", path = "../libpt-core" }
|
libpt-core = { path = "../libpt-core" }
|
||||||
libpt-log = { version = "0.1.0", path = "../libpt-log" }
|
libpt-log = { path = "../libpt-log" }
|
||||||
libpt-math = { version = "0.1.0", path = "../libpt-math" }
|
libpt-math = { path = "../libpt-math" }
|
||||||
reqwest = { version = "0.11.20", features = ["blocking"] }
|
reqwest = { version = "0.11.20", features = ["blocking"] }
|
||||||
serde = { version = "1.0.188", features = ["serde_derive"] }
|
serde = { version = "1.0.188", features = ["serde_derive"] }
|
||||||
serde_json = "1.0.107"
|
serde_json = "1.0.107"
|
||||||
|
|
|
@ -10,11 +10,9 @@
|
||||||
// we want docs
|
// we want docs
|
||||||
#![warn(missing_docs)]
|
#![warn(missing_docs)]
|
||||||
#![warn(rustdoc::missing_crate_level_docs)]
|
#![warn(rustdoc::missing_crate_level_docs)]
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// we want Debug everywhere.
|
// we want Debug everywhere.
|
||||||
#![warn(missing_debug_implementations)]
|
#![warn(missing_debug_implementations)]
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// enable clippy's extra lints, the pedantic version
|
// enable clippy's extra lints, the pedantic version
|
||||||
#![warn(clippy::pedantic)]
|
#![warn(clippy::pedantic)]
|
||||||
|
|
|
@ -6,11 +6,9 @@
|
||||||
// we want docs
|
// we want docs
|
||||||
#![warn(missing_docs)]
|
#![warn(missing_docs)]
|
||||||
#![warn(rustdoc::missing_crate_level_docs)]
|
#![warn(rustdoc::missing_crate_level_docs)]
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// we want Debug everywhere.
|
// we want Debug everywhere.
|
||||||
#![warn(missing_debug_implementations)]
|
#![warn(missing_debug_implementations)]
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// enable clippy's extra lints, the pedantic version
|
// enable clippy's extra lints, the pedantic version
|
||||||
#![warn(clippy::pedantic)]
|
#![warn(clippy::pedantic)]
|
||||||
|
|
|
@ -188,7 +188,11 @@ pub fn continuous_uptime_monitor(
|
||||||
let mut last_was_up: bool = true;
|
let mut last_was_up: bool = true;
|
||||||
let mut last_ratio: u8 = status.success_ratio;
|
let mut last_ratio: u8 = status.success_ratio;
|
||||||
loop {
|
loop {
|
||||||
trace!(?status, ?last_was_up, "loop iteration for continuous uptime monitor");
|
trace!(
|
||||||
|
?status,
|
||||||
|
?last_was_up,
|
||||||
|
"loop iteration for continuous uptime monitor"
|
||||||
|
);
|
||||||
if !status.success {
|
if !status.success {
|
||||||
if last_was_up {
|
if last_was_up {
|
||||||
trace!("displaying status");
|
trace!("displaying status");
|
||||||
|
|
120
members/libpt-py/.github/workflows/CI.yml
vendored
120
members/libpt-py/.github/workflows/CI.yml
vendored
|
@ -1,120 +0,0 @@
|
||||||
# This file is autogenerated by maturin v1.1.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: --skip-existing *
|
|
72
members/libpt-py/.gitignore
vendored
72
members/libpt-py/.gitignore
vendored
|
@ -1,72 +0,0 @@
|
||||||
/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
|
|
|
@ -1,22 +0,0 @@
|
||||||
[package]
|
|
||||||
name = "libpt-py"
|
|
||||||
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
|
|
||||||
[lib]
|
|
||||||
name = "libpt_py"
|
|
||||||
crate-type = ["cdylib"]
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
libpt = { version = "0.1.7", path = "../..", features = ["all"] }
|
|
||||||
pyo3 = { workspace = true }
|
|
|
@ -1,21 +0,0 @@
|
||||||
MIT License
|
|
||||||
|
|
||||||
Copyright (c) 2023 Christoph Johannes Scherr
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
|
@ -1,76 +0,0 @@
|
||||||
# pt / libpt
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
`pt` stands for either one of "personal tool", "plex tool", "pete" or something among those lines.
|
|
||||||
It is a collection of tools that i might or might not use. The intended purpose of this repo is that
|
|
||||||
I program whatever i feel is worth having in a personal thing into it, then use it as either a lib,
|
|
||||||
crate, python module or executable.
|
|
||||||
|
|
||||||
Let's see if I make it a bloated mess or stop committing after 30 hello worlds.
|
|
||||||
|
|
||||||
#### But the name `pt` / `libpt` already exists!
|
|
||||||
|
|
||||||
So what? I don't care. Besides, there is not enough names to name everything unique.
|
|
||||||
|
|
||||||
## Dependencies
|
|
||||||
|
|
||||||
- See `cargo.toml`
|
|
||||||
- [openssl bindings for rust](https://docs.rs/openssl/latest/openssl/)
|
|
||||||
- [Python](https://www.python.org/)
|
|
||||||
- [`maturin`](https://maturin.rs) - `pip install maturin`
|
|
||||||
|
|
||||||
## Compiling & Installing from source
|
|
||||||
|
|
||||||
If you only want the rust library, you can simply build it with `cargo build`. Add it to your
|
|
||||||
project like any other local dependency.
|
|
||||||
|
|
||||||
If you want to use the python variant too, you need to compile with maturing.
|
|
||||||
|
|
||||||
- Install in `venv`: `maturin develop --release`
|
|
||||||
- Install in system: `maturin build --release && pip install target/wheels/libpt-x.x.x-*`
|
|
||||||
|
|
||||||
## Installing from [pypi](https://pypi.org)
|
|
||||||
|
|
||||||
`libpt` has been packaged for [pypi.org](https://pypi.org/project/libpt/).
|
|
||||||
|
|
||||||
You can install it with `pip install libpt`
|
|
||||||
|
|
||||||
## Installing from [crates.io](https://crates.io)
|
|
||||||
|
|
||||||
`libpt` has been packaged for [crates.io](https://crates.io/crates/libpt).
|
|
||||||
|
|
||||||
You can add the library to your project with `cargo add libpt`.
|
|
||||||
|
|
||||||
## Installing from my personal package registry
|
|
||||||
|
|
||||||
`libpt` has been packaged for [git.cscherr.de](https://git.cscherr.de).
|
|
||||||
|
|
||||||
You can add the registry to your `config.toml` and then `cargo add libpt`
|
|
||||||
|
|
||||||
[Package](https://git.cscherr.de/PlexSheep/-/packages/cargo/libpt/)
|
|
||||||
|
|
||||||
## Testing
|
|
||||||
|
|
||||||
Testing needs to be done separately for the rust and python parts:
|
|
||||||
|
|
||||||
- Rust testing with `cargo test`
|
|
||||||
- Python testing with `./scripts/pytests.sh` or `python -m unittest discover -fs tests/python`
|
|
||||||
|
|
||||||
## Documentation
|
|
||||||
|
|
||||||
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**
|
|
|
@ -1,25 +0,0 @@
|
||||||
[build-system]
|
|
||||||
requires = ["maturin>=0.14,<0.15"]
|
|
||||||
build-backend = "maturin"
|
|
||||||
|
|
||||||
[project]
|
|
||||||
name = "libpt"
|
|
||||||
readme = "README.md"
|
|
||||||
requires-python = ">=3.7"
|
|
||||||
authors = [{ name = "Christoph J. Scherr", email = "software@cscherr.de" }]
|
|
||||||
license = { file = "LICENSE" }
|
|
||||||
keywords = ["pyo3"]
|
|
||||||
classifiers = [
|
|
||||||
"Programming Language :: Rust",
|
|
||||||
"Programming Language :: Python :: Implementation :: CPython",
|
|
||||||
"Programming Language :: Python :: Implementation :: PyPy",
|
|
||||||
]
|
|
||||||
|
|
||||||
[project.urls]
|
|
||||||
Homepage = "https://git.cscherr.de/PlexSheep/libpt"
|
|
||||||
|
|
||||||
|
|
||||||
[tool.maturin]
|
|
||||||
features = ["pyo3/extension-module"]
|
|
||||||
python-source = "python"
|
|
||||||
module-name = "libpt._libpt"
|
|
|
@ -1 +0,0 @@
|
||||||
from ._libpt import *
|
|
|
@ -1,14 +0,0 @@
|
||||||
"""
|
|
||||||
# libpt python bindings
|
|
||||||
|
|
||||||
`libpt` is originally implemented in rust, but offers a python module too.
|
|
||||||
"""
|
|
||||||
from . import logger
|
|
||||||
from . import networking
|
|
||||||
from . import common
|
|
||||||
|
|
||||||
def is_loaded() -> bool:
|
|
||||||
"""
|
|
||||||
returns true if `libpt` has been loaded
|
|
||||||
"""
|
|
||||||
...
|
|
|
@ -1,7 +0,0 @@
|
||||||
"""
|
|
||||||
common functionalities
|
|
||||||
|
|
||||||
This module implements common functionality useful for many use cases, such as macros,
|
|
||||||
Formatting functions and more.
|
|
||||||
"""
|
|
||||||
from . import printing
|
|
|
@ -1,14 +0,0 @@
|
||||||
"""
|
|
||||||
tools that make printing stuff better
|
|
||||||
"""
|
|
||||||
def divider() -> str:
|
|
||||||
"""
|
|
||||||
Quickly get a one line visual divider
|
|
||||||
"""
|
|
||||||
...
|
|
||||||
|
|
||||||
def print_divider():
|
|
||||||
"""
|
|
||||||
Quickly print a one line visual divider
|
|
||||||
"""
|
|
||||||
...
|
|
|
@ -1,65 +0,0 @@
|
||||||
"""
|
|
||||||
# A specialized Logger for `libpt`
|
|
||||||
"""
|
|
||||||
|
|
||||||
""" the default log level """
|
|
||||||
DEFAULT_LOG_LEVEL = "INFO"
|
|
||||||
""" Set the value of this key as envar to set a loglevel """
|
|
||||||
LOGGER_ENV_KEY = "LIBPT_LOGLEVEL"
|
|
||||||
|
|
||||||
class Logger:
|
|
||||||
"""
|
|
||||||
`libpt` logger
|
|
||||||
|
|
||||||
Call `init` once before usage, else all logging attempts will be ignored.
|
|
||||||
"""
|
|
||||||
def __init__(self):
|
|
||||||
"""
|
|
||||||
get a new logger
|
|
||||||
"""
|
|
||||||
...
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def init():
|
|
||||||
"""
|
|
||||||
initialize the logger before the first usage
|
|
||||||
"""
|
|
||||||
...
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def init_specialized(color: bool):
|
|
||||||
"""
|
|
||||||
initialize the logger before the first usage, but with the ability to tweak things a bit
|
|
||||||
"""
|
|
||||||
...
|
|
||||||
|
|
||||||
def error(self, printable: str):
|
|
||||||
"""
|
|
||||||
log at level `error`
|
|
||||||
"""
|
|
||||||
...
|
|
||||||
|
|
||||||
def warn(self, printable: str):
|
|
||||||
"""
|
|
||||||
log at level `error`
|
|
||||||
"""
|
|
||||||
...
|
|
||||||
|
|
||||||
def info(self, printable: str):
|
|
||||||
"""
|
|
||||||
log at level `error`
|
|
||||||
"""
|
|
||||||
...
|
|
||||||
|
|
||||||
def debug(self, printable: str):
|
|
||||||
"""
|
|
||||||
log at level `error`
|
|
||||||
"""
|
|
||||||
...
|
|
||||||
|
|
||||||
def trace(self, printable: str):
|
|
||||||
"""
|
|
||||||
log at level `error`
|
|
||||||
"""
|
|
||||||
...
|
|
||||||
|
|
|
@ -1,7 +0,0 @@
|
||||||
"""
|
|
||||||
# various networking tools
|
|
||||||
|
|
||||||
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.
|
|
||||||
"""
|
|
||||||
from . import monitoring
|
|
|
@ -1,7 +0,0 @@
|
||||||
"""
|
|
||||||
# monitor your network
|
|
||||||
|
|
||||||
This module offers functions to monitor your network.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from . import uptime
|
|
|
@ -1,86 +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
|
|
||||||
"""
|
|
||||||
|
|
||||||
class UptimeStatus:
|
|
||||||
"""
|
|
||||||
Describes an uptime status
|
|
||||||
|
|
||||||
UptimeStatus describes the result of an uptime check.
|
|
||||||
"""
|
|
||||||
""" true if the [`UptimeStatus`] is considered successful"""
|
|
||||||
success: bool
|
|
||||||
""" the percentage of reachable urls out of the total urls"""
|
|
||||||
success_ratio: int
|
|
||||||
""" 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.
|
|
||||||
"""
|
|
||||||
success_ratio_target: int
|
|
||||||
""" the number of reachable [`urls`](UptimeStatus::urls) """
|
|
||||||
reachable: int
|
|
||||||
""" set a timeout (in ms) """
|
|
||||||
timeout: int
|
|
||||||
"""URL list cant be ported to python, use UptimeStatus.urls()"""
|
|
||||||
__urls: ...
|
|
||||||
|
|
||||||
def __init__(self, success_ratio_target: int, url_strs: list[str], timeout: int) -> None:
|
|
||||||
"""
|
|
||||||
create a new UptimeStatus and check it
|
|
||||||
|
|
||||||
`success_ratio_target` should never be more than 100 (it represents a success percentage)
|
|
||||||
"""
|
|
||||||
...
|
|
||||||
|
|
||||||
def check(self) -> None:
|
|
||||||
"""
|
|
||||||
checks if the stored urls
|
|
||||||
|
|
||||||
Makes the actual https requests and updates fields accordingly.
|
|
||||||
|
|
||||||
This method can block some time, as the web requests are implemented as blocking and
|
|
||||||
executed by the shared library (not in python)
|
|
||||||
"""
|
|
||||||
...
|
|
||||||
|
|
||||||
def calc_success(self) -> None:
|
|
||||||
"""
|
|
||||||
calculate the success based on the `reachable` and `total`
|
|
||||||
|
|
||||||
Calculates the ratio of [reachable]/
|
|
||||||
(length of [__urls]).
|
|
||||||
|
|
||||||
Calculates a [`success_ratio`] from that, by multiplying with 100, then flooring.
|
|
||||||
|
|
||||||
If the [`success_ratio`] is greater than or equal to the [`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`] will be `0`.
|
|
||||||
|
|
||||||
Note: does not check for networking, use [`check()`] for that.
|
|
||||||
"""
|
|
||||||
...
|
|
||||||
|
|
||||||
def urls(self) -> list[str]:
|
|
||||||
"""
|
|
||||||
get urls for python
|
|
||||||
|
|
||||||
Since [`__urls`] has no python equivalent, return the urls as a `list[str]` in
|
|
||||||
Python.
|
|
||||||
"""
|
|
||||||
...
|
|
||||||
|
|
||||||
def continuous_uptime_monitor(success_ratio_target: int, urls: list[str], interval: int, timeout: int) -> None:
|
|
||||||
"""
|
|
||||||
Uptime monitor
|
|
||||||
|
|
||||||
This function continuously monitors the uptime of your host/network.
|
|
||||||
|
|
||||||
On change of status, an update will be logged at INFO Level, containing
|
|
||||||
information on your current status, including timestamps of the last up/down time and durations
|
|
||||||
since.
|
|
||||||
"""
|
|
||||||
...
|
|
|
@ -1 +0,0 @@
|
||||||
python -m unittest discover -fs tests/python
|
|
|
@ -1,101 +0,0 @@
|
||||||
// FIXME: Using a local dependency does not work with maturin as it seems?
|
|
||||||
use libpt::{
|
|
||||||
log::*,
|
|
||||||
};
|
|
||||||
|
|
||||||
use pyo3::prelude::*;
|
|
||||||
|
|
||||||
//// PUBLIC FUNCTIONS //////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// ## Check if [`libpt`](crate) has been loaded
|
|
||||||
///
|
|
||||||
/// Always returns `true` if you can execute it.
|
|
||||||
#[pyfunction]
|
|
||||||
pub fn is_loaded() -> bool {
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
//// PRIVATE FUNCTIONS /////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// ## Python module: logger
|
|
||||||
#[pymodule]
|
|
||||||
fn py_logger(py: Python, parent: &PyModule) -> PyResult<()> {
|
|
||||||
let module = PyModule::new(py, "logger")?;
|
|
||||||
module.add_class::<Logger>()?;
|
|
||||||
|
|
||||||
parent.add_submodule(module)?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
//
|
|
||||||
// ////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// /// ## Python module: common
|
|
||||||
// #[pymodule]
|
|
||||||
// fn py_common(py: Python, parent: &PyModule) -> PyResult<()> {
|
|
||||||
// let module = PyModule::new(py, "common")?;
|
|
||||||
// py_common_printing(py, module)?;
|
|
||||||
//
|
|
||||||
// parent.add_submodule(module)?;
|
|
||||||
// Ok(())
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// ////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// /// ## Python module: common.printing
|
|
||||||
// #[pymodule]
|
|
||||||
// fn py_common_printing(py: Python, parent: &PyModule) -> PyResult<()> {
|
|
||||||
// let module = PyModule::new(py, "printing")?;
|
|
||||||
// module.add_function(wrap_pyfunction!(common::printing::divider, module)?)?;
|
|
||||||
// module.add_function(wrap_pyfunction!(common::printing::print_divider, module)?)?;
|
|
||||||
//
|
|
||||||
// parent.add_submodule(module)?;
|
|
||||||
// Ok(())
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// ////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// /// ## Python module: networking
|
|
||||||
// #[pymodule]
|
|
||||||
// fn py_networking(py: Python, parent: &PyModule) -> PyResult<()> {
|
|
||||||
// let module = PyModule::new(py, "networking")?;
|
|
||||||
// py_networking_monitoring(py, module)?;
|
|
||||||
//
|
|
||||||
// parent.add_submodule(module)?;
|
|
||||||
// Ok(())
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// ////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// /// ## Python module: networking.monitoring
|
|
||||||
// #[pymodule]
|
|
||||||
// fn py_networking_monitoring(py: Python, parent: &PyModule) -> PyResult<()> {
|
|
||||||
// let module = PyModule::new(py, "monitoring")?;
|
|
||||||
// py_networking_monitoring_uptime(py, module)?;
|
|
||||||
//
|
|
||||||
// parent.add_submodule(module)?;
|
|
||||||
// Ok(())
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// ////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// /// ## Python module: networking.monitoring.uptime
|
|
||||||
// #[pymodule]
|
|
||||||
// fn py_networking_monitoring_uptime(py: Python, parent: &PyModule) -> PyResult<()> {
|
|
||||||
// let module = PyModule::new(py, "uptime")?;
|
|
||||||
// module.add_class::<networking::monitoring::uptime::UptimeStatus>()?;
|
|
||||||
// module.add_function(wrap_pyfunction!(
|
|
||||||
// networking::monitoring::uptime::py_continuous_uptime_monitor,
|
|
||||||
// module
|
|
||||||
// )?)?;
|
|
||||||
//
|
|
||||||
// parent.add_submodule(module)?;
|
|
||||||
// Ok(())
|
|
||||||
// }
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// ## Python module: root
|
|
||||||
///
|
|
||||||
/// This function is the entry point of [`PyO3`](pyo3). This is where the main module is built.
|
|
||||||
#[pymodule]
|
|
||||||
fn _libpt(py: Python, m: &PyModule) -> PyResult<()> {
|
|
||||||
m.add_function(wrap_pyfunction!(is_loaded, m)?)?;
|
|
||||||
|
|
||||||
// load sub modules
|
|
||||||
// py_common(py, m)?;
|
|
||||||
py_logger(py, m)?;
|
|
||||||
// py_networking(py, m)?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
8
publish.sh
Executable file
8
publish.sh
Executable file
|
@ -0,0 +1,8 @@
|
||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
PKGs=(libpt-{core,math,log,net,bintols,ccc,hedu,bin,py} libpt)
|
||||||
|
for PKG in "${PKGs[@]}"; do
|
||||||
|
echo "Package: $PKG"
|
||||||
|
cargo publish --registry cscherr -p "$PKG"
|
||||||
|
cargo publish -p "$PKG"
|
||||||
|
done
|
|
@ -6,10 +6,12 @@
|
||||||
//! `pt` is a project consisting of multiple smaller crates, all bundled together in this
|
//! `pt` is a project consisting of multiple smaller crates, all bundled together in this
|
||||||
//! "main crate". Most crates will only show up if you activate their feature.
|
//! "main crate". Most crates will only show up if you activate their feature.
|
||||||
|
|
||||||
#[cfg(feature = "core")]
|
|
||||||
pub use libpt_core as core;
|
|
||||||
#[cfg(feature = "bintols")]
|
#[cfg(feature = "bintols")]
|
||||||
pub use libpt_bintols as 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 = "hedu")]
|
#[cfg(feature = "hedu")]
|
||||||
pub use libpt_hedu as hedu;
|
pub use libpt_hedu as hedu;
|
||||||
#[cfg(feature = "log")]
|
#[cfg(feature = "log")]
|
||||||
|
@ -18,5 +20,3 @@ pub use libpt_log as log;
|
||||||
pub use libpt_math as math;
|
pub use libpt_math as math;
|
||||||
#[cfg(feature = "net")]
|
#[cfg(feature = "net")]
|
||||||
pub use libpt_net as net;
|
pub use libpt_net as net;
|
||||||
#[cfg(feature = "ccc")]
|
|
||||||
pub use libpt_ccc as ccc;
|
|
||||||
|
|
Reference in a new issue