Compare commits

..

12 Commits

Author SHA1 Message Date
tmerritt bdeefdb3b6 more formatting 2026-05-03 08:50:55 -04:00
tmerritt e3b8939082 config.toml: remove excluded files for coverage report
data_to_text.rs: change from . as unrecognized character to ' '
demo.rs: improves POC display of headers
tests/primitive_formatting.rs: initial tests of bool formatting
2026-04-14 07:43:20 -04:00
tmerritt 9852ef687d April bump 2026-04-04 13:14:43 -04:00
tmerritt e7e20f1d36 applies rustfmt to cleanup
uses std::env::current_dir to find out where the tests are running from
2025-08-14 07:48:23 -04:00
tmerritt 6d51a4d3a6 Duration to String enhanced with tests
Adds checks for if a bit in a u8 is set or clear
2025-07-23 11:19:22 -04:00
tmerritt 3280123d22 Adds Duration to String for converting a duration to a human readable length of time 2025-07-23 08:54:29 -04:00
tmerritt 0b11b91fe4 update tests 2025-06-12 14:33:43 -04:00
tmerritt 703ae38814 data_to_text basic testing 2025-06-06 09:14:32 -04:00
tmerritt f93131622f Start of data_to_text family 2025-06-05 14:19:45 -04:00
tmerritt 37cc9e4fdb 100% coverage 2025-06-02 16:02:54 -04:00
tmerritt 12d738389b More number conversion code
100% coverage
2025-06-02 10:25:59 -04:00
tmerritt 60232b958f more byte conversion code and tests 2025-06-02 09:12:16 -04:00
29 changed files with 1073 additions and 435 deletions
+1 -2
View File
@@ -1,3 +1,2 @@
[alias]
coverage = "tarpaulin --out Html --skip-clean --output-dir coverage"
coverage = "tarpaulin --out Html --skip-clean --output-dir coverage --exclude-files src/bin/* --exclude-files tests/*"
+1
View File
@@ -3,6 +3,7 @@
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/tests" isTestSource="true" />
<excludeFolder url="file://$MODULE_DIR$/target" />
</content>
<orderEntry type="inheritedJdk" />
Generated
+45 -366
View File
@@ -4,154 +4,36 @@ version = 4
[[package]]
name = "adler2"
version = "2.0.0"
version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627"
[[package]]
name = "aho-corasick"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
dependencies = [
"memchr",
]
[[package]]
name = "anstream"
version = "0.6.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b"
dependencies = [
"anstyle",
"anstyle-parse",
"anstyle-query",
"anstyle-wincon",
"colorchoice",
"is_terminal_polyfill",
"utf8parse",
]
[[package]]
name = "anstyle"
version = "1.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9"
[[package]]
name = "anstyle-parse"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9"
dependencies = [
"utf8parse",
]
[[package]]
name = "anstyle-query"
version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c"
dependencies = [
"windows-sys",
]
[[package]]
name = "anstyle-wincon"
version = "3.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6680de5231bd6ee4c6191b8a1325daa282b415391ec9d3a37bd34f2060dc73fa"
dependencies = [
"anstyle",
"once_cell_polyfill",
"windows-sys",
]
checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"
[[package]]
name = "bitflags"
version = "2.9.1"
version = "2.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967"
checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3"
[[package]]
name = "cfg-if"
version = "1.0.0"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "clap"
version = "4.5.39"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fd60e63e9be68e5fb56422e397cf9baddded06dae1d2e523401542383bc72a9f"
dependencies = [
"clap_builder",
"clap_derive",
]
[[package]]
name = "clap_builder"
version = "4.5.39"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "89cc6392a1f72bbeb820d71f32108f61fdaf18bc526e1d23954168a67759ef51"
dependencies = [
"anstream",
"anstyle",
"clap_lex",
"strsim",
]
[[package]]
name = "clap_derive"
version = "4.5.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09176aae279615badda0765c0c0b3f6ed53f4709118af73cf4655d85d1530cd7"
dependencies = [
"heck",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "clap_lex"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6"
[[package]]
name = "colorchoice"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990"
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
[[package]]
name = "crc32fast"
version = "1.4.2"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3"
checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511"
dependencies = [
"cfg-if",
]
[[package]]
name = "env_logger"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4cd405aab171cb85d6735e5c8d9db038c17d3ca007a4d2c25f337935c3d90580"
dependencies = [
"humantime",
"is-terminal",
"log",
"regex",
"termcolor",
]
[[package]]
name = "errno"
version = "0.3.12"
version = "0.3.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cea14ef9355e3beab063703aa9dab15afd25f0667c341310c1e5274bb1d0da18"
checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
dependencies = [
"libc",
"windows-sys",
@@ -165,9 +47,9 @@ checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be"
[[package]]
name = "flate2"
version = "1.1.1"
version = "1.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ced92e76e966ca2fd84c8f7aa01a4aea65b0eb6648d72f7c8f3e2764a67fece"
checksum = "bfe33edd8e85a12a67454e37f8c75e730830d83e313556ab9ebf9ee7fbeb3bfb"
dependencies = [
"crc32fast",
"miniz_oxide",
@@ -175,82 +57,36 @@ dependencies = [
[[package]]
name = "getrandom"
version = "0.3.3"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4"
checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd"
dependencies = [
"cfg-if",
"libc",
"r-efi",
"wasi",
"wasip2",
]
[[package]]
name = "heck"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
[[package]]
name = "hermit-abi"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f154ce46856750ed433c8649605bf7ed2de3bc35fd9d2a9f30cddd873c80cb08"
[[package]]
name = "humantime"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b112acc8b3adf4b107a8ec20977da0273a8c386765a3ec0229bd500a1443f9f"
[[package]]
name = "is-terminal"
version = "0.4.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e04d7f318608d35d4b61ddd75cbdaee86b023ebe2bd5a66ee0915f0bf93095a9"
dependencies = [
"hermit-abi",
"libc",
"windows-sys",
]
[[package]]
name = "is_terminal_polyfill"
version = "1.70.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
[[package]]
name = "libc"
version = "0.2.172"
version = "0.2.178"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa"
checksum = "37c93d8daa9d8a012fd8ab92f088405fb202ea0b6ab73ee2482ae66af4f42091"
[[package]]
name = "linux-raw-sys"
version = "0.9.4"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12"
[[package]]
name = "log"
version = "0.4.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94"
[[package]]
name = "memchr"
version = "2.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039"
[[package]]
name = "miniz_oxide"
version = "0.8.8"
version = "0.8.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a"
checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316"
dependencies = [
"adler2",
"simd-adler32",
]
[[package]]
@@ -259,70 +95,17 @@ version = "1.21.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
[[package]]
name = "once_cell_polyfill"
version = "1.70.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad"
[[package]]
name = "proc-macro2"
version = "1.0.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
dependencies = [
"proc-macro2",
]
[[package]]
name = "r-efi"
version = "5.2.0"
version = "5.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5"
[[package]]
name = "regex"
version = "1.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
dependencies = [
"aho-corasick",
"memchr",
"regex-automata",
"regex-syntax",
]
[[package]]
name = "regex-automata"
version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f"
[[package]]
name = "rustix"
version = "1.0.7"
version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266"
checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e"
dependencies = [
"bitflags",
"errno",
@@ -332,27 +115,16 @@ dependencies = [
]
[[package]]
name = "strsim"
version = "0.11.1"
name = "simd-adler32"
version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
[[package]]
name = "syn"
version = "2.0.101"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
checksum = "e320a6c5ad31d271ad523dcf3ad13e2767ad8b1cb8f047f75a8aeaf8da139da2"
[[package]]
name = "tempfile"
version = "3.20.0"
version = "3.23.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8a64e3985349f2441a1a9ef0b853f869006c3855f2cda6862a94d26ebb9d6a1"
checksum = "2d31c77bdf42a745371d260a26ca7163f1e0924b64afa0b688e61b5a9fa02f16"
dependencies = [
"fastrand",
"getrandom",
@@ -361,133 +133,40 @@ dependencies = [
"windows-sys",
]
[[package]]
name = "termcolor"
version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755"
dependencies = [
"winapi-util",
]
[[package]]
name = "trevors_utilities"
version = "0.1.0"
version = "0.1.0-20250606"
dependencies = [
"clap",
"env_logger",
"flate2",
"tempfile",
]
[[package]]
name = "unicode-ident"
version = "1.0.18"
name = "wasip2"
version = "1.0.1+wasi-0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
[[package]]
name = "utf8parse"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
[[package]]
name = "wasi"
version = "0.14.2+wasi-0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3"
checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7"
dependencies = [
"wit-bindgen-rt",
"wit-bindgen",
]
[[package]]
name = "winapi-util"
version = "0.1.9"
name = "windows-link"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
dependencies = [
"windows-sys",
]
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
[[package]]
name = "windows-sys"
version = "0.59.0"
version = "0.61.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc"
dependencies = [
"windows-targets",
"windows-link",
]
[[package]]
name = "windows-targets"
version = "0.52.6"
name = "wit-bindgen"
version = "0.46.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_gnullvm",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
[[package]]
name = "windows_aarch64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
[[package]]
name = "windows_i686_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
[[package]]
name = "windows_i686_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
[[package]]
name = "windows_i686_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
[[package]]
name = "windows_x86_64_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
[[package]]
name = "wit-bindgen-rt"
version = "0.39.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1"
dependencies = [
"bitflags",
]
checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59"
+2 -4
View File
@@ -1,10 +1,8 @@
[package]
name = "trevors_utilities"
version = "0.1.0"
version = "0.1.0-20250606"
edition = "2024"
[dependencies]
flate2 = "1.0"
clap = { version = "4.5", features = ["derive"] }
env_logger = "0.10"
tempfile = "3.20"
tempfile = "3"
+26
View File
@@ -0,0 +1,26 @@
# Trevors Utilities
## Overview
Trevors Utilities is a collection of code that Trevor has found useful.
All code has the following criteria:
- Traits as appropriate, implemented for concrete types
- All code must have 100% code coverage to be part of a 'tagged release'
- All code must have 100% documentation coverage with examples of inputs and outputs
## Code Areas
### Number System Conversion
A variety of methods for converting numbers between systems. Functionality includes
- Joining u8 values into u16 values with low and high bytes
- Splitting u16 values into the high and low u8 values
- Swapping endianness of u16 values
- Converting an array of bool values into the equivalent value in u8 with bits in MSB order
### Test Compression
Methods for compressing and decompressing test results using deflate compression.
+1
View File
@@ -0,0 +1 @@
q
+1
View File
@@ -0,0 +1 @@
0x71 q
+1
View File
@@ -0,0 +1 @@
the quick brown fox jumped over the lazy dog
@@ -0,0 +1,3 @@
0x74 0x68 0x65 0x20 0x71 0x75 0x69 0x63 0x6b 0x20 0x62 0x72 0x6f 0x77 0x6e 0x20 the quick brown
0x66 0x6f 0x78 0x20 0x6a 0x75 0x6d 0x70 0x65 0x64 0x20 0x6f 0x76 0x65 0x72 0x20 fox jumped over
0x74 0x68 0x65 0x20 0x6c 0x61 0x7a 0x79 0x20 0x64 0x6f 0x67 the lazy dog
+54
View File
@@ -0,0 +1,54 @@
use std::time::Duration;
use trevors_utilities::data_to_text::DataToText;
use trevors_utilities::duration_to_string::duration_to_string::{duration_to_string, SECONDS_IN_DAY, SECONDS_IN_HOUR, SECONDS_IN_MINUTE};
use trevors_utilities::format_with_commas::format_with_commas;
fn demo_header(title: &str, width: Option<u8>) {
let width = width.unwrap_or(80) as usize;
let num_leading = (width - title.len() - 4) / 2;
println!("{}{}", "-".repeat(width), "");
println!("|{}{} {}|", " ".repeat(num_leading), title, " ".repeat(num_leading));
println!("{}{}", "-".repeat(width), "");
}
fn duration_to_string_demo() {
demo_header("Duration to String", None);
println!();
let options = vec![
// 4 days, 3 hours, 19 minutes, 31 seconds
(4 * SECONDS_IN_DAY) + (3 * SECONDS_IN_HOUR) + (19 * SECONDS_IN_MINUTE) + (31),
// 0 days, 0 hours, 1 minute, 0 seconds
(0 * SECONDS_IN_DAY) + (0 * SECONDS_IN_HOUR) + (1 * SECONDS_IN_MINUTE) + 0,
// 0 days, 0 hours, 0 minutes, 1 second,
1,
];
for option in options {
println!("{}s becomes {}", format_with_commas(option), duration_to_string(Duration::from_secs(option as u64), Some(false)));
println!("{}s becomes {}", format_with_commas(option), duration_to_string(Duration::from_secs(option as u64), Some(true)));
println!("{}s becomes {}", format_with_commas(option), duration_to_string(Duration::from_secs(option as u64), None));
println!("--");
}
}
fn data_to_text_demo() {
demo_header("Data To Text", None);
let options: Vec<Vec<u8>> = vec![
(0..=255).collect(),
(0..128).collect(),
(0x20..=0x7f).collect()
];
for option in options { let data = DataToText::data_to_text(option.as_slice());
println!("{}", data);
}
}
fn main() {
println!("Demos for Trevors Utilities");
println!();
println!();
duration_to_string_demo();
data_to_text_demo();
}
+10
View File
@@ -0,0 +1,10 @@
use trevors_utilities::data_to_text::DataToText;
fn main() {
let text = "q";
let displayed_hex = DataToText::data_to_text(text.as_bytes());
println!("RAW: [{text}]");
println!("FORMATTED:\n{displayed_hex}");
}
-4
View File
@@ -1,4 +0,0 @@
fn main() {
println!("Taxation is Theft");
println!("MANIFEST_DIR: {}", env!("CARGO_MANIFEST_DIR"));
}
+52
View File
@@ -0,0 +1,52 @@
pub struct DataToText {}
impl DataToText {
/// data_to_text_window
///
/// Convert a block of u8 data to text for user display skipping specified bytes
pub fn data_to_text_window(to_convert: &[u8], offset: usize, length: usize) -> String {
let convert_len = to_convert.len();
if offset >= convert_len {
return String::from("");
}
let end_of_window = offset.saturating_add(length).min(convert_len);
DataToText::data_to_text(&to_convert[offset..end_of_window])
}
/// data_to_text
///
/// Convert a block of u8 data to text for user display
pub fn data_to_text(to_convert: &[u8]) -> String {
let mut result = String::new();
let mut hex_line = String::new();
let mut ascii_line = String::new();
for (idx, byte) in to_convert.iter().enumerate() {
hex_line += &format!("0x{:02x} ", byte);
let ascii_char = if byte.is_ascii_graphic() {
*byte as char
} else {
' '
};
ascii_line.push(ascii_char);
if idx % 16 == 15 {
// Write full line
result += &format!("{:<96} {}\n", hex_line, ascii_line);
hex_line.clear();
ascii_line.clear();
}
}
// Final line if there are leftover bytes
if !hex_line.is_empty() {
result += &format!("{:<96} {}\n", hex_line, ascii_line);
}
result
}
}
@@ -0,0 +1,38 @@
use std::time::Duration;
pub const SECONDS_IN_MINUTE: u32 = 60;
pub const SECONDS_IN_HOUR: u32 = SECONDS_IN_MINUTE * 60;
pub const SECONDS_IN_DAY: u32 = SECONDS_IN_HOUR * 24;
pub fn duration_to_string(to_convert: Duration, show_zeros: Option<bool>) -> String {
const SECONDS_IN_DAY: u32 = 86400;
const SECONDS_IN_HOUR: u32 = 3600;
const SECONDS_IN_MINUTE: u32 = 60;
let should_show_zero = show_zeros.unwrap_or(false);
let mut total_seconds = to_convert.as_secs() as u32;
let mut parts = Vec::new();
let units = [
(SECONDS_IN_DAY, "day"),
(SECONDS_IN_HOUR, "hour"),
(SECONDS_IN_MINUTE, "minute"),
(1, "second"),
];
for &(unit_seconds, unit_name) in &units {
let count = total_seconds / unit_seconds;
total_seconds %= unit_seconds;
if count > 0 || should_show_zero {
let label = if count == 1 {
unit_name.to_string()
} else {
format!("{}s", unit_name)
};
parts.push(format!("{} {}", count, label));
}
}
parts.join(" ")
}
+2
View File
@@ -0,0 +1,2 @@
pub mod duration_to_string;
mod tests;
+110
View File
@@ -0,0 +1,110 @@
#[cfg(test)]
mod test {
use super::*;
use crate::duration_to_string::duration_to_string::duration_to_string;
use crate::duration_to_string::duration_to_string::*;
use std::time::Duration;
#[test]
fn multi_duration_to_string() {
let params: Vec<(&str, Duration, Option<bool>)> = vec![
("1 second", Duration::from_secs(1), Some(false)),
("4 seconds", Duration::from_secs(4), Some(false)),
("1 minute", Duration::from_secs(SECONDS_IN_MINUTE as u64),Some(false)),
("4 minutes", Duration::from_secs((SECONDS_IN_MINUTE * 4) as u64), Some(false)),
(
"1 hour",
Duration::from_secs(SECONDS_IN_HOUR as u64),
Some(false),
),
(
"4 hours",
Duration::from_secs((SECONDS_IN_HOUR * 4) as u64),
Some(false),
),
(
"4 hours 5 minutes",
Duration::from_secs((SECONDS_IN_HOUR * 4 + SECONDS_IN_MINUTE * 5) as u64),
Some(false),
),
(
"1 day",
Duration::from_secs(SECONDS_IN_DAY as u64),
Some(false),
),
(
"0 days 0 hours 0 minutes 1 second",
Duration::from_secs(1),
Some(true),
),
(
"0 days 0 hours 0 minutes 4 seconds",
Duration::from_secs(4),
Some(true),
),
(
"0 days 0 hours 1 minute 0 seconds",
Duration::from_secs(SECONDS_IN_MINUTE as u64),
Some(true),
),
(
"0 days 0 hours 4 minutes 0 seconds",
Duration::from_secs((SECONDS_IN_MINUTE * 4) as u64),
Some(true),
),
(
"0 days 1 hour 0 minutes 0 seconds",
Duration::from_secs(SECONDS_IN_HOUR as u64),
Some(true),
),
(
"0 days 4 hours 0 minutes 0 seconds",
Duration::from_secs((SECONDS_IN_HOUR * 4) as u64),
Some(true),
),
(
"0 days 4 hours 5 minutes 0 seconds",
Duration::from_secs((SECONDS_IN_HOUR * 4 + SECONDS_IN_MINUTE * 5) as u64),
Some(true),
),
(
"1 day 0 hours 0 minutes 0 seconds",
Duration::from_secs(SECONDS_IN_DAY as u64),
Some(true),
),
(
"1 day 0 hours 0 minutes 1 second",
Duration::from_secs((SECONDS_IN_DAY + 1) as u64),
Some(true),
),
("1 second", Duration::from_secs(1), None),
("4 seconds", Duration::from_secs(4), None),
(
"1 minute",
Duration::from_secs(SECONDS_IN_MINUTE as u64),
None,
),
(
"4 minutes",
Duration::from_secs((SECONDS_IN_MINUTE * 4) as u64),
None,
),
("1 hour", Duration::from_secs(SECONDS_IN_HOUR as u64), None),
(
"4 hours",
Duration::from_secs((SECONDS_IN_HOUR * 4) as u64),
None,
),
(
"4 hours 5 minutes",
Duration::from_secs((SECONDS_IN_HOUR * 4 + SECONDS_IN_MINUTE * 5) as u64),
None,
),
("1 day", Duration::from_secs(SECONDS_IN_DAY as u64), None),
];
for (expected, actual, show) in params {
assert_eq!(expected, duration_to_string(actual, show));
}
}
}
+11
View File
@@ -0,0 +1,11 @@
pub fn format_with_commas(mut num: u32) -> String {
let mut parts = Vec::new();
while num >= 1000 {
parts.push(format!("{:03}", num % 1000));
num /= 1000;
}
parts.push(num.to_string());
parts.reverse();
parts.join(",")
}
+5 -1
View File
@@ -1,2 +1,6 @@
pub mod test_loader;
pub mod data_to_text;
pub mod duration_to_string;
pub mod number_system_conversion;
pub mod test_compression;
pub mod format_with_commas;
pub mod primitive_formatting;
+132
View File
@@ -0,0 +1,132 @@
pub struct NumberSystemConversion {}
impl NumberSystemConversion {
/// byte_to_bool
///
/// Convert a u8 byte into a set of bool of the value
///
/// ex: 0xff -> true, true, true, true, true, true, true, true
/// 0xa0 -> true, false, true, false, false, false, false, false
pub fn byte_to_bool(from: u8) -> [bool; 8] {
let mut result = [false; 8];
for i in 0..8 {
// Extract the i-th bit and convert it to a boolean
result[i] = ((from >> i) & 1) != 0;
}
result
}
/// bool_to_byte
///
/// Convert a set of bool to a single byte
///
/// ex: true, true, true, true, true, true, true, true -> 0xff
/// true, false, true, false, false, false, false, false -> 0xa0
/// false, false, false, false, false, false, false, false -> 0x00
pub fn bool_to_byte(from: [bool; 8]) -> u8 {
let mut return_value = 0u8;
for i in 0..from.len() {
let new_bit = 0x1 << i;
if from[i] {
return_value |= new_bit
}
}
return_value
}
/// swap_endian_u16
///
/// Swaps endianness of a u16
///
/// ex: 0xabcd -> 0xcdab
/// 0x00ff -> 0xff00
pub fn swap_endian_u16(from: u16) -> u16 {
// shift low to high and high to low
// merge the bits to a u16
(from & 0xff) << 8 | (from & 0xff00) >> 8
}
/// Swap endian u32
///
/// Swaps endianness of a u32
///
/// ex. 0x12345678 -> 0x78563412
pub fn swap_endian_u32(from: u32) -> u32 {
let mut bytes = vec![0, 0, 0, 0];
// mask out what we want...
bytes[0] = from & 0x000000ff;
bytes[1] = (from & 0x0000ff00) >> 8;
bytes[2] = (from & 0x00ff0000) >> 16;
bytes[3] = (from & 0xff000000) >> 24;
// ...shift it into the right position
bytes[0] << 24 | bytes[1] << 16 | bytes[2] << 8 | bytes[3]
}
/// split_bytes_u16
///
/// Splits a u16 into its high and low bytes
///
/// ex: 0xabcd -> 0xab, 0xcd
/// 0x0000 -> 0x00, 0x00
/// 0xffff -> 0xff, 0xff
pub fn split_bytes_u16(from: u16) -> (u8, u8) {
let high = from.rotate_left(8) as u8;
let low = (from & 0xff) as u8;
(high, low)
}
/// join_bytes_u16
pub fn join_bytes_u16(high: u16, low: u16) -> u16 {
low | high << 8
}
/// combine_u8_to_u16
///
/// Combines a pair of u8 values into a single u16 with high
/// and low bytes specified
///
/// ex: (0xff, 0x00) -> 0x00ff
/// (0x00, 0xff) -> 0xff00
/// (0xbe, 0xef) -> 0xefbe
/// (0xef, 0xbe) -> 0xbeef
pub fn combine_u8_to_u16(low: u8, high: u8) -> u16 {
(high as u16) << 8 | low as u16
}
/// clear_high_bits
///
/// Clear the 8 MSB of the value
///
/// ex: 0xffff -> 0x00ff
/// 0xabcd -> 0x00cd
pub fn clear_high_bits(to_clear: u16) -> u16 {
to_clear & 0x00ff
}
/// clear_low_bits
///
/// Clear the 8 LSB of the value
///
/// ex: 0xffff -> 0xff00
/// 0xabcd -> 0xab00
pub fn clear_low_bits(to_clear: u16) -> u16 {
to_clear & 0xff00
}
/// is_bit_set
///
/// Checks if a specified bit is set
pub fn is_bit_set(to_check: u8, bit_to_check: u8) -> bool {
(to_check >> bit_to_check) & 0x01 == 1
}
/// is_bit_clear
///
/// Checks if a specified bit is clear
/// LSB = 0 MSB = 7
pub fn is_bit_clear(to_check: u8, bit_to_check: u8) -> bool {
(to_check >> bit_to_check) & 0x01 != 1
}
}
+11
View File
@@ -0,0 +1,11 @@
pub fn bool_to_string(b: bool) -> String {
if b {
"1".to_string()
} else {
"0".to_string()
}
}
pub fn bool_array_to_string(b: &[bool]) -> String {
b.iter().map(|b| bool_to_string(*b)).collect::<Vec<String>>().join("")
}
+76 -36
View File
@@ -1,10 +1,11 @@
use std::fs::File;
use std::io::{Read, Write};
use std::path::Path;
use flate2::Compression;
use flate2::read::DeflateDecoder;
use flate2::write::DeflateEncoder;
use tempfile::tempfile;
use std::fs::{File, OpenOptions};
use std::io;
use std::io::{Read, Write};
use std::path::Path;
use std::string::String;
pub struct TestCompression {}
@@ -16,57 +17,96 @@ impl TestCompression {
.expect("Failed to write data");
encoder.finish().expect("Failed to finish compression")
}
pub fn decompress_to_string(compressed_data: &[u8]) -> Result<String, std::io::Error> {
pub fn decompress_to_string(compressed_data: &[u8]) -> String {
let mut decoder = DeflateDecoder::new(compressed_data);
let mut decompressed = String::new();
decoder.read_to_string(&mut decompressed)?;
Ok(decompressed)
decoder
.read_to_string(&mut decompressed)
.expect("Unablew to decompress data to string");
decompressed
}
/// Load a pre-compressed test result to a string for comparison in an assert macro
pub fn load_compressed_file_to_string(source: &Path) -> String {
let mut compressed_file = File::open(&source).expect(format!("Unable to open compressed file at [{}]", source.display()).as_str());
let mut compressed_file = File::open(&source)
.expect(format!("Unable to open compressed file at [{}]", source.display()).as_str());
let mut compressed_data = Vec::new();
compressed_file.read_to_end(&mut compressed_data)
compressed_file
.read_to_end(&mut compressed_data)
.expect(format!("Unable to read compressed data from [{}]", source.display()).as_str());
TestCompression::decompress_to_string(&compressed_data).unwrap()
TestCompression::decompress_to_string(&compressed_data)
}
/// Save a str to a specified file as compressed data
pub fn save_string_as_compressed_data(source: &str, target_file: &Path) {
let mut compressed_file = File::open(&target_file).expect(format!("Unable to open target file [{}]", target_file.display()).as_str());
let mut compressed_file = OpenOptions::new()
.write(true)
.truncate(true) // optional: clear existing contents
.create(true)
.open(target_file)
.expect(&format!(
"Unable to open target file [{}] for writing",
target_file.display()
));
let compressed_data = TestCompression::compress_string(source);
compressed_file.write_all(&compressed_data).expect(format!("Unable to write compressed data to [{}]", target_file.display()).as_str());
}
compressed_file.write_all(&compressed_data).expect(&format!(
"Unable to write compressed data to [{}]",
target_file.display()
));
}
#[cfg(test)]
mod tests {
use super::*;
pub fn compress_file<P: AsRef<Path>>(source: P, destination: P) -> io::Result<()> {
// Read the source file
let mut read_buffer = String::new();
let mut read_file = File::open(&source)?;
read_file.read_to_string(&mut read_buffer)?;
#[test]
fn smoke() {
assert!(true)
// Compress the data
let compressed_data = TestCompression::compress_string(&read_buffer);
// Write the compressed data to the destination file
let mut write_file = File::create(&destination)?;
write_file.write_all(&compressed_data)?;
Ok(())
}
#[test]
fn compression_round_trip() {
let to_compress = "The quick brown fox jumps over the lazy dog.";
let compressed_text = TestCompression::compress_string(to_compress);
let decompressed_text = TestCompression::decompress_to_string(&compressed_text).unwrap();
assert_eq!(to_compress, decompressed_text);
pub fn compress_string_to_file(text: &str, target: &Path) {
let compressed_text = TestCompression::compress_string(text);
let mut writer = File::create(target).expect("Unable to create target file.");
writer
.write_all(&compressed_text)
.expect("Unable to write compressed data");
}
#[test]
fn file_compression_round_trip() {
// compress string to file...
let string_to_compress = "The quick brown fox jumps over the lazy dog.";
let compressed_string = TestCompression::compress_string(string_to_compress);
let temp_target = tempfile().unwrap();
//
// ...decompress from file...
//
// ...verify its the same.
pub fn decompress_file_to_string(source: &Path) -> String {
let mut compressed_file = File::open(source).expect("Unable to open source to compress.");
let mut compressed_data = Vec::new();
compressed_file
.read_to_end(&mut compressed_data)
.expect("Unable to read compressed data");
TestCompression::decompress_to_string(&compressed_data)
}
pub fn compress_file_to_array(file_to_compress: &Path) -> Vec<u8> {
let mut read_buffer = String::new();
let mut file = File::open(file_to_compress).unwrap();
file.read_to_string(&mut read_buffer)
.expect("Unable to read data to compress");
TestCompression::compress_string(&read_buffer)
}
pub fn decompress_file_to_array(to_decompress: &Path) -> Vec<u8> {
// println!("DECOMPRESS_FILE_TO_ARRAY--> {:?}", to_decompress);
let file = File::open(to_decompress).expect("Failed to open file");
let mut decoder = DeflateDecoder::new(file);
let mut output = Vec::new();
decoder
.read_to_end(&mut output)
.expect("Failed to decompress");
output
}
}
-15
View File
@@ -1,15 +0,0 @@
use std::path::Path;
pub fn load_test_result(base_path: &Path, suffix: String) -> String {
let full_path = format!("{}/{}", base_path.display(), suffix);
std::fs::read_to_string(full_path).unwrap()
}
pub fn load_compressed_test_result(base_path: &Path, suffix: String) -> String {
// first load the data...
// ...then decompress it...
// let raw_result = decompress_to_string(compressed_result);
// ...finally return it
String::new()
}
+1
View File
@@ -0,0 +1 @@
mod poc;
+73
View File
@@ -0,0 +1,73 @@
use trevors_utilities::data_to_text::DataToText;
fn read_bin(source: &str) -> Vec<u8> {
let full_path = format!(
"{}/resources/data_to_text/{}.bin",
std::env::current_dir()
.unwrap()
.to_str()
.unwrap()
.to_string(),
source
);
// println!("FULL PATH BIN: [{}]", full_path);
std::fs::read(full_path).unwrap()
}
fn read_display(source: &str) -> String {
let full_path = format!(
"{}/resources/data_to_text/{}.display",
std::env::current_dir()
.unwrap()
.to_str()
.unwrap()
.to_string(),
source
);
std::fs::read_to_string(full_path).unwrap()
}
#[test]
fn data_to_text() {
let data_to_display: &[u8] = &[
0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74,
0x20, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x20,
];
let expected_data: &str = "0x66 0x67 0x68 0x69 0x6a 0x6b 0x6c 0x6d 0x6e 0x6f 0x70 0x71 0x72 0x73 0x74 0x20 fghijklmnopqrst \n0x76 0x77 0x78 0x79 0x7a 0x7b 0x7c 0x7d 0x7e 0x7f 0x20 vwxyz{|}~ \n";
let actual_data = DataToText::data_to_text(data_to_display);
assert_eq!(actual_data, expected_data);
}
#[test]
fn quickbrownfoxtest() {
let test_params = vec!["quickbrownfox", "q"];
for stub in test_params {
// load the content from quickbrownfox.bin
let bin_data = read_bin(stub);
// format it for display
let formatted = DataToText::data_to_text(&bin_data);
// load the content from quickbrownfox.display
let expected = read_display(stub);
assert_eq!(formatted, expected);
}
}
#[test]
fn data_to_text_window_all() {
let bin_data = read_bin("quickbrownfox");
let formatted = DataToText::data_to_text_window(&bin_data, 0, bin_data.len());
let expected = read_display("quickbrownfox");
assert_eq!(formatted, expected);
}
#[test]
fn test_window_past_end_of_data() {
let bin_data = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06];
let formatted = DataToText::data_to_text_window(&bin_data, 10, 10);
assert_eq!(formatted, "");
}
+16
View File
@@ -0,0 +1,16 @@
use trevors_utilities::format_with_commas::format_with_commas;
#[test]
fn format_with_commas_none_needed() {
assert_eq!("0", format_with_commas(0));
}
#[test]
fn format_thousands() {
assert_eq!("1,000", format_with_commas(1000));
}
#[test]
fn format_millions() {
assert_eq!("1,000,000", format_with_commas(1000000));
}
+5
View File
@@ -0,0 +1,5 @@
mod data_to_text;
mod number_system_conversion;
mod test_compression;
mod format_with_commas;
mod primitive_formatting;
+200
View File
@@ -0,0 +1,200 @@
use std::collections::BTreeMap;
use trevors_utilities::number_system_conversion::NumberSystemConversion;
#[test]
fn byte_to_bool_and_bool_to_byte() {
// confirm a byte becomes a valid bool
// **** NOTE THAT THIS VISUALLY IS BACKWARDS AS INDEX 0 IS FIRST AND LSB IS LAST ****
let test_params: BTreeMap<u8, [bool; 8]> = BTreeMap::from([
(0xff, [true, true, true, true, true, true, true, true]),
(
0x00,
[false, false, false, false, false, false, false, false],
),
(0xa0, [false, false, false, false, false, true, false, true]),
]);
for (src, dst) in test_params {
assert_eq!(
dst,
NumberSystemConversion::byte_to_bool(src),
"Unable to convert [{}] to [{:?}]",
src,
dst
);
assert_eq!(
src,
NumberSystemConversion::bool_to_byte(dst),
"Unable to convert [{:?}] to [{}]",
dst,
src
);
assert_eq!(
src,
NumberSystemConversion::bool_to_byte(NumberSystemConversion::byte_to_bool(src))
);
}
}
#[test]
fn swap_endianness_u16() {
let test_params: Vec<(u16, u16)> = vec![
(0xabcd, 0xcdab),
(0x0000, 0x0000),
(0xffff, 0xffff),
(0x00ff, 0xff00),
];
for (src, dst) in test_params {
assert_eq!(src, NumberSystemConversion::swap_endian_u16(dst));
assert_eq!(
src,
NumberSystemConversion::swap_endian_u16(NumberSystemConversion::swap_endian_u16(src))
);
assert_eq!(dst, NumberSystemConversion::swap_endian_u16(src));
assert_eq!(
dst,
NumberSystemConversion::swap_endian_u16(NumberSystemConversion::swap_endian_u16(dst))
);
}
}
#[test]
fn swap_endinness_u32() {
let test_params: Vec<(u32, u32)> = vec![
(0xabcdef01, 0x01efcdab),
(0x12345678, 0x78563412),
(0xbadbeef0, 0xf0eedbba),
];
for (src, dst) in test_params {
assert_eq!(src, NumberSystemConversion::swap_endian_u32(dst));
assert_eq!(
src,
NumberSystemConversion::swap_endian_u32(NumberSystemConversion::swap_endian_u32(src))
);
assert_eq!(dst, NumberSystemConversion::swap_endian_u32(src));
assert_eq!(
dst,
NumberSystemConversion::swap_endian_u32(NumberSystemConversion::swap_endian_u32(dst))
);
}
}
#[test]
fn split_bytes_u16_join_bytes_u16() {
let test_params = BTreeMap::from([
(0x0000, (0x00, 0x00)),
(0xabcd, (0xab, 0xcd)),
(0xffff, (0xff, 0xff)),
(0xbeef, (0xbe, 0xef)),
]);
for (joined, (high, low)) in test_params {
assert_eq!((high, low), NumberSystemConversion::split_bytes_u16(joined));
assert_eq!(
joined,
NumberSystemConversion::join_bytes_u16(high as u16, low as u16)
);
}
}
#[test]
fn combine_u8_to_u16() {
let test_params: Vec<((u8, u8), u16)> = vec![
((0xff, 0x00), 0x00ff),
((0x00, 0xff), 0xff00),
((0xbe, 0xef), 0xefbe),
((0xef, 0xbe), 0xbeef),
];
for ((low, high), base) in test_params {
assert_eq!(base, NumberSystemConversion::combine_u8_to_u16(low, high))
}
}
#[test]
fn clear_high_bits() {
let test_params = vec![
(0b1111_1111_0101_1010, 0b0000_0000_0101_1010),
(0b1111_1111_1111_1111, 0b0000_0000_1111_1111),
(0b0000_0000_1111_1111, 0b0000_0000_1111_1111),
(0b0101_1010_1001_0110, 0b0000_0000_1001_0110),
];
for (src, dst) in test_params {
let result = NumberSystemConversion::clear_high_bits(src);
println!("Rolled {src:016b} to {result:016b} / {dst:016b}");
assert_eq!(NumberSystemConversion::clear_high_bits(src), dst);
}
}
#[test]
fn clear_low_bits() {
let test_params = vec![
(0b1111_1111_0101_1010, 0b1111_1111_0000_0000),
(0b1111_1111_1111_1111, 0b1111_1111_0000_0000),
(0b0000_0000_1111_1111, 0b0000_0000_0000_0000),
(0b0101_1010_1001_0110, 0b0101_1010_0000_0000),
];
for (src, dst) in test_params {
let result = NumberSystemConversion::clear_low_bits(src);
println!("Rolled {src:08b} to {result:08b} / {dst:08b}");
assert_eq!(NumberSystemConversion::clear_low_bits(src), dst);
}
}
#[test]
fn is_bit_set_checks() {
let params = vec![
(
0b0000_0001,
vec![true, false, false, false, false, false, false, false],
),
(
0b1111_1111,
vec![true, true, true, true, true, true, true, true],
),
(
0b1010_1010,
vec![false, true, false, true, false, true, false, true],
),
];
for (base, options) in params {
for (index, expected) in options.iter().enumerate() {
assert_eq!(
*expected,
NumberSystemConversion::is_bit_set(base, index as u8)
);
}
}
}
#[test]
fn is_bit_clear_checks() {
let params = vec![
(
0b0000_0001,
vec![false, true, true, true, true, true, true, true],
),
(
0b1111_1111,
vec![false, false, false, false, false, false, false, false],
),
(
0b1010_1010,
vec![true, false, true, false, true, false, true, false],
),
];
for (base, options) in params {
for (index, expected) in options.iter().enumerate() {
assert_eq!(
*expected,
NumberSystemConversion::is_bit_clear(base, index as u8)
);
}
}
}
+7
View File
@@ -0,0 +1,7 @@
use trevors_utilities::primitive_formatting;
#[test]
fn test_primitive_bool() {
assert_eq!("1".to_string(), primitive_formatting::bool_to_string(true));
assert_eq!("0".to_string(), primitive_formatting::bool_to_string(false));
}
+182
View File
@@ -0,0 +1,182 @@
use std::io::{Read, Write};
use tempfile::NamedTempFile;
use trevors_utilities::test_compression::TestCompression;
#[cfg(test)]
mod tests {
const SAMPLE_TEXT: &str = "The quick brown fox jumps over the lazy dog.";
use super::*;
#[test]
fn smoke() {
assert!(true)
}
#[test]
fn compression_round_trip() {
let to_compress = SAMPLE_TEXT;
let decompressed_text =
TestCompression::decompress_to_string(&TestCompression::compress_string(to_compress));
assert_eq!(to_compress, decompressed_text);
}
#[test]
fn file_compression_round_trip() {
// compress string to file...
let string_to_compress = SAMPLE_TEXT;
let compressed_string = TestCompression::compress_string(string_to_compress);
let mut temp_target = NamedTempFile::new().unwrap();
let temp_reader = temp_target.reopen();
// ...write the compressed version to a file...
temp_target
.write_all(&compressed_string)
.expect("Unable to write compressed file for test");
//
// ...decompress from file...
let mut compressed_read = Vec::new();
temp_reader
.unwrap()
.read_to_end(&mut compressed_read)
.expect("Unable to read compressed data for test");
let decompresed = TestCompression::decompress_to_string(&compressed_read);
//
// ...verify its the same.
assert_eq!(string_to_compress, decompresed);
}
#[test]
fn file_compression_reader() {
// Get the 'sample text'
let to_compress = SAMPLE_TEXT;
// ...write it to the temp file...
let mut temp_file = NamedTempFile::new().expect("Unable to get temp file for test");
temp_file
.write_all(&*TestCompression::compress_string(to_compress))
.expect("Unable to write compressed data to temp file for test");
let temp2_path = temp_file.path();
let uncompressed_text = TestCompression::load_compressed_file_to_string(temp2_path);
assert_eq!(uncompressed_text, to_compress);
}
#[test]
fn file_compression_writer() {
let to_compress = SAMPLE_TEXT;
let mut temp_file = NamedTempFile::new().expect("Unable to get temp file for test.");
TestCompression::save_string_as_compressed_data(to_compress, temp_file.path());
// read back the compressed text
let mut read_buffer = Vec::new();
temp_file
.read_to_end(&mut read_buffer)
.expect("Unable to read compressed data back.");
let decompressed_text = TestCompression::decompress_to_string(&read_buffer);
assert_eq!(decompressed_text, to_compress);
}
#[test]
fn compress_file() {
// create our test file.
let test_text = SAMPLE_TEXT;
let mut original_file = NamedTempFile::new().unwrap();
let compressed_file = NamedTempFile::new().unwrap();
original_file
.write(test_text.as_bytes())
.expect("Unable to write original file");
// run the method being tested
TestCompression::compress_file(original_file.path(), compressed_file.path())
.expect("Unable to compress temp file.");
// verify the data in the new file matches what we expect
let mut reader_file = compressed_file.reopen().unwrap();
let mut result_text = Vec::new();
reader_file
.read_to_end(&mut result_text)
.expect("Unable to read compressed data back to verify");
let decompressed_text = TestCompression::decompress_to_string(&result_text);
assert_eq!(decompressed_text, test_text);
}
#[test]
fn compress_string_to_file() {
let to_compress = SAMPLE_TEXT;
let compressed_text = TestCompression::compress_string(to_compress);
let target_file = NamedTempFile::new().unwrap();
let mut duplicate = target_file.reopen().unwrap();
TestCompression::compress_string_to_file(to_compress, target_file.path());
let mut file_contents = Vec::new();
duplicate
.read_to_end(&mut file_contents)
.expect("Unable to read compressed file.");
assert_eq!(file_contents, compressed_text);
}
#[test]
fn decompress_file_to_string() {
let to_compress = SAMPLE_TEXT;
let temp = NamedTempFile::new().unwrap();
TestCompression::compress_string_to_file(to_compress, temp.path());
let result = TestCompression::decompress_file_to_string(temp.path());
assert_eq!(to_compress, result);
}
#[test]
fn compress_file_to_array() {
let to_compress = SAMPLE_TEXT;
let mut temp_file = NamedTempFile::new().expect("Unable to get temp file for test");
temp_file.write_all(to_compress.as_bytes()).unwrap();
let result = TestCompression::compress_file_to_array(temp_file.path());
let decompressed_result = TestCompression::decompress_to_string(&result);
assert_eq!(to_compress, decompressed_result);
}
#[test]
fn compress_file_to_array_with_trailing_newline() {
let to_compress = format!("{}\n", SAMPLE_TEXT);
let mut temp_file = NamedTempFile::new().expect("Unable to get temp file for test");
temp_file.write_all(to_compress.as_bytes()).unwrap();
let result = TestCompression::compress_file_to_array(temp_file.path());
let decompressed_result = TestCompression::decompress_to_string(&result);
assert_eq!(to_compress, decompressed_result);
}
#[test]
fn decompress_to_array() {
let original_text = SAMPLE_TEXT;
let compressed_data = TestCompression::compress_string(original_text);
// Write the compressed data to a temp file
let mut temp_file = NamedTempFile::new().expect("Failed to create temp file");
temp_file
.write_all(&compressed_data)
.expect("Failed to write compressed data to file");
// Run the method under test
let decompressed_data = TestCompression::decompress_file_to_array(temp_file.path());
// Convert to string to compare
let decompressed_text =
String::from_utf8(decompressed_data).expect("Decompressed bytes were not valid UTF-8");
assert_eq!(decompressed_text, original_text);
}
#[test]
#[should_panic(expected = "No such file or directory")]
fn decompress_file_panics_on_missing_path() {
let bad_path = std::path::Path::new("/definitely/invalid/path");
TestCompression::decompress_file_to_array(bad_path);
}
}