ugly smol
This commit is contained in:
commit
d9bba7c0c6
5 changed files with 121 additions and 0 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
/target
|
7
Cargo.lock
generated
Normal file
7
Cargo.lock
generated
Normal file
|
@ -0,0 +1,7 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "urlenc"
|
||||
version = "0.1.0"
|
9
Cargo.toml
Normal file
9
Cargo.toml
Normal file
|
@ -0,0 +1,9 @@
|
|||
[package]
|
||||
name = "urlenc"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
authors = ["femsci"]
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
3
README.md
Normal file
3
README.md
Normal file
|
@ -0,0 +1,3 @@
|
|||
# urlenc
|
||||
|
||||
A quick utility for URL percent encoding and decoding
|
101
src/main.rs
Normal file
101
src/main.rs
Normal file
|
@ -0,0 +1,101 @@
|
|||
use std::{
|
||||
fs::File,
|
||||
io::{BufRead, BufReader, Read},
|
||||
};
|
||||
|
||||
fn main() {
|
||||
let decode = std::env::args().any(|f| f == "-d");
|
||||
|
||||
let mut stream: Box<dyn BufRead> = match std::env::args().last() {
|
||||
Some(x) => {
|
||||
if x == "-" {
|
||||
Box::new(BufReader::new(std::io::stdin()))
|
||||
} else {
|
||||
Box::new(BufReader::new(
|
||||
File::open(&x).expect(&format!("No file found: {}", &x)),
|
||||
))
|
||||
}
|
||||
}
|
||||
None => {
|
||||
eprintln!("No file provided!");
|
||||
std::process::exit(1);
|
||||
}
|
||||
};
|
||||
|
||||
if decode {
|
||||
url_decode_stream(&mut stream);
|
||||
} else {
|
||||
url_encode(&mut stream);
|
||||
}
|
||||
}
|
||||
|
||||
fn url_decode_stream(stream: &mut Box<dyn BufRead>) {
|
||||
let mut str = String::new();
|
||||
let mut buf = Vec::new();
|
||||
let mut val_buf: [u8; 2] = [0; 2];
|
||||
|
||||
while stream.read_until(b'%', &mut buf).expect("Cannot read data") > 0 {
|
||||
let string = String::from_utf8(buf.to_vec()).unwrap().replace('+', " ");
|
||||
|
||||
if !string.ends_with('%') {
|
||||
str.push_str(&string);
|
||||
break;
|
||||
}
|
||||
|
||||
str.push_str(string.trim_end_matches('%'));
|
||||
|
||||
stream
|
||||
.read_exact(&mut val_buf)
|
||||
.expect("Cannot retrieve value");
|
||||
|
||||
let chr = get_char(val_buf[0], val_buf[1]);
|
||||
|
||||
str.push(chr);
|
||||
|
||||
buf.clear();
|
||||
}
|
||||
|
||||
println!("{}", &str);
|
||||
}
|
||||
|
||||
fn get_char(msc: u8, lsc: u8) -> char {
|
||||
let extract_byte = |x: u8| {
|
||||
let x_chr = (x as char).to_ascii_lowercase();
|
||||
|
||||
if x_chr.is_ascii_digit() {
|
||||
(x_chr as u8) - b'0'
|
||||
} else if x_chr.is_ascii_hexdigit() {
|
||||
(x_chr as u8) - b'a' + 10
|
||||
} else {
|
||||
eprintln!("Invalid character for encoding found: {}", x_chr);
|
||||
std::process::exit(2);
|
||||
}
|
||||
};
|
||||
|
||||
let msb = extract_byte(msc);
|
||||
let lsb = extract_byte(lsc);
|
||||
|
||||
(msb * 16 + lsb) as char
|
||||
}
|
||||
|
||||
fn get_percent(chr: char) -> String {
|
||||
format!("%{:x}", chr as u8)
|
||||
}
|
||||
|
||||
fn url_encode(stream: &mut Box<dyn BufRead>) {
|
||||
let mut line = String::new();
|
||||
while stream.read_line(&mut line).expect("Cannot read data") > 0 {
|
||||
let encoded = line
|
||||
.chars()
|
||||
.map(|f| {
|
||||
if f.is_alphanumeric() || ['-', '_', '.', '~'].contains(&f) {
|
||||
f.to_string()
|
||||
} else {
|
||||
get_percent(f)
|
||||
}
|
||||
})
|
||||
.collect::<String>();
|
||||
print!("{}", &encoded);
|
||||
line.clear();
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue