happy_cracking/crypto/
strtools.rs1use anyhow::Result;
2use clap::Subcommand;
3use umt_rust::string::umt_reverse_string;
4
5#[derive(Subcommand)]
6pub enum StrToolsAction {
7 #[command(about = "Reverse a string")]
8 Reverse {
9 #[arg(help = "Input text")]
10 input: String,
11 },
12 #[command(about = "Show ASCII/Unicode code points for each character")]
13 Ord {
14 #[arg(help = "Input text")]
15 input: String,
16 },
17 #[command(about = "Convert space-separated code points to characters")]
18 Chr {
19 #[arg(help = "Space-separated code points (e.g. \"72 101 108 108 111\")")]
20 input: String,
21 },
22}
23
24pub fn run(action: StrToolsAction) -> Result<()> {
25 match action {
26 StrToolsAction::Reverse { input } => {
27 println!("{}", reverse(&input));
28 }
29 StrToolsAction::Ord { input } => {
30 println!("{}", ord(&input));
31 }
32 StrToolsAction::Chr { input } => {
33 println!("{}", chr(&input)?);
34 }
35 }
36 Ok(())
37}
38
39pub fn reverse(input: &str) -> String {
41 umt_reverse_string(input)
42}
43
44pub fn ord(input: &str) -> String {
46 if input.is_empty() {
47 return String::new();
48 }
49
50 let mut out = String::with_capacity(input.len() * 10);
54 let mut first = true;
55
56 for c in input.chars() {
57 if !first {
58 out.push(' ');
59 }
60 first = false;
61
62 out.push(c);
63 out.push('=');
64
65 let mut n = c as u32;
66 if n == 0 {
67 out.push('0');
68 } else {
69 let mut buf = [0u8; 10];
70 let mut i = 10;
71 while n > 0 {
72 i -= 1;
73 buf[i] = (n % 10) as u8 + b'0';
74 n /= 10;
75 }
76 out.push_str(unsafe { std::str::from_utf8_unchecked(&buf[i..]) });
78 }
79 }
80
81 out
82}
83
84pub fn chr(input: &str) -> Result<String> {
86 if input.is_empty() {
87 return Ok(String::new());
88 }
89
90 input
91 .split_whitespace()
92 .map(|s| {
93 let n: u32 = s
94 .parse()
95 .map_err(|_| anyhow::anyhow!("Invalid code point: {}", s))?;
96 char::from_u32(n).ok_or_else(|| anyhow::anyhow!("Invalid Unicode code point: {}", n))
97 })
98 .collect()
99}