From f42080c90a0bf9ef0b9cb2fcf65146c34b19ba38 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Mon, 10 Nov 2025 09:07:05 +0200 Subject: [PATCH] feat: make factory lib --- Cargo.toml | 4 +++- cipher-factory/Cargo.toml | 17 +++++++++++++++++ cipher-factory/src/algorithm.rs | 30 ++++++++++++++++++++++++++++++ cipher-factory/src/lib.rs | 5 +++++ cipher-factory/src/operation.rs | 6 ++++++ cipher-factory/src/output.rs | 27 +++++++++++++++++++++++++++ cli/Cargo.toml | 3 ++- cli/src/args.rs | 18 +++--------------- cli/src/cipher.rs | 13 ------------- cli/src/main.rs | 16 ++++------------ cli/src/output.rs | 14 -------------- 11 files changed, 97 insertions(+), 56 deletions(-) create mode 100644 cipher-factory/Cargo.toml create mode 100644 cipher-factory/src/algorithm.rs create mode 100644 cipher-factory/src/lib.rs create mode 100644 cipher-factory/src/operation.rs create mode 100644 cipher-factory/src/output.rs delete mode 100644 cli/src/cipher.rs delete mode 100644 cli/src/output.rs diff --git a/Cargo.toml b/Cargo.toml index 4efd94b..8ffe235 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,12 +1,14 @@ [workspace] resolver = "2" -members = ["aes", "cipher-core", "cli", "des"] +members = ["aes", "cipher-core", "cipher-factory", "cli", "des"] [workspace.dependencies] aes = { path = "aes" } color-eyre = "0.6" cipher-core = { path = "cipher-core" } +cipher-factory = { path = "cipher-factory" } claims = "0.8" +clap = { version = "4.5", features = ["derive"] } des = { path = "des" } rand = "0.9" rstest = "0.26" diff --git a/cipher-factory/Cargo.toml b/cipher-factory/Cargo.toml new file mode 100644 index 0000000..4ba0ac1 --- /dev/null +++ b/cipher-factory/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "cipher-factory" +version = "0.1.0" +edition = "2024" + +[dependencies] +aes.workspace = true +cipher-core.workspace = true +clap = { workspace = true, optional = true } +des.workspace = true + +[features] +default = [] +clap = ["dep:clap"] + +[lints] +workspace = true diff --git a/cipher-factory/src/algorithm.rs b/cipher-factory/src/algorithm.rs new file mode 100644 index 0000000..9f7ddf6 --- /dev/null +++ b/cipher-factory/src/algorithm.rs @@ -0,0 +1,30 @@ +use cipher_core::{BlockCipher, InputBlock}; +use des::Des; +use std::fmt::Display; + +#[cfg_attr(feature = "clap", derive(clap::ValueEnum))] +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum Algorithm { + Des, + Aes, +} + +impl Algorithm { + #[must_use] + pub fn get_cipher(&self, key: &impl InputBlock) -> impl BlockCipher { + match self { + Self::Des => Des::from_key(key.as_bytes()), + Self::Aes => todo!("Must implement AES first"), + } + } +} + +impl Display for Algorithm { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let s = match self { + Self::Des => "Des", + Self::Aes => "Aes", + }; + f.write_str(s) + } +} diff --git a/cipher-factory/src/lib.rs b/cipher-factory/src/lib.rs new file mode 100644 index 0000000..2cee782 --- /dev/null +++ b/cipher-factory/src/lib.rs @@ -0,0 +1,5 @@ +mod algorithm; +mod operation; +mod output; + +pub use {algorithm::Algorithm, operation::OperationChoice, output::OutputFormat}; diff --git a/cipher-factory/src/operation.rs b/cipher-factory/src/operation.rs new file mode 100644 index 0000000..76d2279 --- /dev/null +++ b/cipher-factory/src/operation.rs @@ -0,0 +1,6 @@ +#[cfg_attr(feature = "clap", derive(clap::ValueEnum))] +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum OperationChoice { + Encrypt, + Decrypt, +} diff --git a/cipher-factory/src/output.rs b/cipher-factory/src/output.rs new file mode 100644 index 0000000..6d66a95 --- /dev/null +++ b/cipher-factory/src/output.rs @@ -0,0 +1,27 @@ +use cipher_core::Output; + +#[cfg_attr(feature = "clap", derive(clap::ValueEnum))] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)] +pub enum OutputFormat { + /// Binary output + Binary, + /// Octal output + Octal, + /// Decimal output + #[default] + Hex, + /// Text output (ASCII) + Text, +} + +impl OutputFormat { + #[must_use] + pub fn to_string(&self, value: &Output) -> String { + match self { + Self::Binary => format!("{value:064b}"), + Self::Octal => format!("{value:022o}"), + Self::Hex => format!("{value:016X}"), + Self::Text => format!("{value}"), + } + } +} diff --git a/cli/Cargo.toml b/cli/Cargo.toml index 45d57b5..477eab9 100644 --- a/cli/Cargo.toml +++ b/cli/Cargo.toml @@ -7,7 +7,8 @@ edition = "2024" [dependencies] aes.workspace = true cipher-core.workspace = true -clap = { version = "4.5", features = ["derive"] } +cipher-factory = { workspace = true, features = ["clap"] } +clap.workspace = true color-eyre.workspace = true des.workspace = true thiserror.workspace = true diff --git a/cli/src/args.rs b/cli/src/args.rs index 8a0f178..40d94d6 100644 --- a/cli/src/args.rs +++ b/cli/src/args.rs @@ -1,5 +1,5 @@ -use crate::output::OutputFormat; -use clap::{Parser, ValueEnum}; +use cipher_factory::{Algorithm, OperationChoice, OutputFormat}; +use clap::Parser; use des::Block64; use std::str::FromStr; @@ -12,7 +12,7 @@ pub struct Args { /// Encryption algorithm #[arg(short, long)] - pub algorithm: AlgorithmChoice, + pub algorithm: Algorithm, /// Key used for encryption/decryption. Can be a string or a path to a file #[arg(short, long, value_parser = Block64::from_str, required = true)] @@ -26,15 +26,3 @@ pub struct Args { #[arg(short = 'f', long)] pub output_format: Option, } - -#[derive(Debug, Clone, Copy, ValueEnum)] -pub enum AlgorithmChoice { - Des, - Aes, -} - -#[derive(Debug, Clone, Copy, ValueEnum)] -pub enum OperationChoice { - Encrypt, - Decrypt, -} diff --git a/cli/src/cipher.rs b/cli/src/cipher.rs deleted file mode 100644 index 4061fa0..0000000 --- a/cli/src/cipher.rs +++ /dev/null @@ -1,13 +0,0 @@ -use crate::args::AlgorithmChoice; -use cipher_core::{BlockCipher, InputBlock}; -use des::Des; - -impl AlgorithmChoice { - #[must_use] - pub fn get_cipher(&self, key: &impl InputBlock) -> impl BlockCipher { - match self { - Self::Des => Des::from_key(key.as_bytes()), - Self::Aes => todo!("Must implement AES first"), - } - } -} diff --git a/cli/src/main.rs b/cli/src/main.rs index cab70de..8548557 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -1,12 +1,8 @@ mod args; -mod cipher; -mod output; -use crate::{ - args::{Args, OperationChoice}, - output::OutputFormat, -}; +use crate::args::Args; use cipher_core::BlockCipher; +use cipher_factory::OperationChoice; use clap::Parser; fn main() -> color_eyre::Result<()> { @@ -28,12 +24,8 @@ fn main() -> color_eyre::Result<()> { OperationChoice::Decrypt => { let cipher = algorithm.get_cipher(&key); let plaintext = cipher.decrypt(&text.to_be_bytes())?; - match output_format.unwrap_or_default() { - OutputFormat::Binary => println!("{plaintext:064b}"), - OutputFormat::Octal => println!("{plaintext:022o}"), - OutputFormat::Hex => println!("{plaintext:016X}"), - OutputFormat::Text => println!("{plaintext}"), - } + let output = output_format.unwrap_or_default().to_string(&plaintext); + println!("{output}"); } } Ok(()) diff --git a/cli/src/output.rs b/cli/src/output.rs deleted file mode 100644 index 34fd07b..0000000 --- a/cli/src/output.rs +++ /dev/null @@ -1,14 +0,0 @@ -use clap::ValueEnum; - -#[derive(Debug, Clone, Default, ValueEnum)] -pub enum OutputFormat { - /// Binary output - Binary, - /// Octal output - Octal, - /// Decimal output - #[default] - Hex, - /// Text output (ASCII) - Text, -}