From c0171c098611c44725092aa7f6639bcfafd5bfd0 Mon Sep 17 00:00:00 2001 From: Lu Baumann Date: Sun, 2 Jul 2023 23:04:56 +0200 Subject: [PATCH] added comments and cleaned code --- src/consts.rs | 8 +++++++- src/main.rs | 42 ++++++++++++++++-------------------------- 2 files changed, 23 insertions(+), 27 deletions(-) diff --git a/src/consts.rs b/src/consts.rs index a9d807b..033c85a 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -1,3 +1,5 @@ +//! Constant values + use std::process::exit; use lazy_static::lazy_static; @@ -30,6 +32,8 @@ If -e is in effect, the following sequences are recognized: \0NNN byte with octal value NNN (1 to 3 digits) \xHH byte with hexadecimal value HH (1 to 2 digits) "#; + +/// Special characters, that can be replaced without further logic pub const SIMPLE_SPECIAL_SEQUENCES: [(&str, &str); 8] = [ (r#"\a"#, "\x07"), (r#"\b"#, "\x08"), @@ -41,6 +45,7 @@ pub const SIMPLE_SPECIAL_SEQUENCES: [(&str, &str); 8] = [ (r#"\v"#, "\x0b"), ]; lazy_static! { + // \NNN or \0NNN with N in octal pub static ref OCTAL_REGEX: Regex = Regex::new(r#"\\(?:([1-7][0-7]{0,2}|0[0-7]{0,3}))"#) .map_or_else( |e| { @@ -52,7 +57,8 @@ lazy_static! { }, |v| v ); - pub static ref HEX_REGEX: Regex = Regex::new(r#"\\x([0-9A-F]{0,2})"#).map_or_else( + // \xFF with F in octal + pub static ref HEX_REGEX: Regex = Regex::new(r#"\\x([0-9A-F]{1,2})"#).map_or_else( |e| { eprintln!( "programming error: cannot compile regex pattern for hex regex match: {}", diff --git a/src/main.rs b/src/main.rs index f6d8fea..3599cdc 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,5 @@ +//! Basic rewrite of the echo GNU core utility, maintaining compatability + use std::{ env::args, io::{self, Write}, @@ -8,6 +10,7 @@ mod consts; use crate::consts::{HELP_DIALOG, HEX_REGEX, OCTAL_REGEX, SIMPLE_SPECIAL_SEQUENCES, VERSION}; +/// Settings to be read from cli struct Settings { trailing_newline: bool, interpret_backslash_escapes: bool, @@ -22,6 +25,7 @@ impl Default for Settings { } } +/// Replaces escaped octal representations with corresponding characters fn replace_octal(string: String) -> String { let mut res = string; while let Some(captures) = OCTAL_REGEX.captures( @@ -29,19 +33,12 @@ fn replace_octal(string: String) -> String { &res.clone(), ) { if let (Some(entire_match), Some(capture)) = (captures.get(0), captures.get(1)) { - let mut contents = capture.as_str(); - if contents.is_empty() { - contents = "0" // GNU echo interprets \0 as \00 - } res = format!( - "{}{}", + "{}{}{}", &res[..entire_match.start()], - OCTAL_REGEX.replace( - &res[entire_match.start()..], - &u8::from_str_radix(contents, 8) - .map_or_else(|_| 255 as char, |v| v as char) - .to_string(), - ) + &u8::from_str_radix(capture.as_str(), 8) + .map_or_else(|_| 255 as char, |v| v as char), + &res[entire_match.end()..], ); } else { println!("error matching octal regex. aborting"); @@ -51,29 +48,20 @@ fn replace_octal(string: String) -> String { res } +/// Replaces escaped hex representations with corresponding characters fn replace_hex(string: String) -> String { let mut res = string; - let mut search_at = 0; - while let Some(captures) = HEX_REGEX.captures_at( + while let Some(captures) = HEX_REGEX.captures( #[allow(clippy::redundant_clone)] &res.clone(), - search_at, ) { if let (Some(entire_match), Some(capture)) = (captures.get(0), captures.get(1)) { - let contents = capture.as_str(); - if contents.is_empty() { - search_at = entire_match.end(); - continue; // GNU echo does not interpret \x - } res = format!( - "{}{}", + "{}{}{}", &res[..entire_match.start()], - HEX_REGEX.replace( - &res[entire_match.start()..], - &u8::from_str_radix(contents, 16) - .map_or_else(|_| 255 as char, |v| v as char) - .to_string(), - ) + &u8::from_str_radix(capture.as_str(), 16) + .map_or_else(|_| 255 as char, |v| v as char), + &res[entire_match.end()..], ); } else { println!("error matching hex regex. aborting"); @@ -83,6 +71,7 @@ fn replace_hex(string: String) -> String { res } +/// Format passed argument based on settings fn format_arg(arg: String, settings: &mut Settings) -> String { if settings.interpret_backslash_escapes { let mut res = arg; @@ -116,6 +105,7 @@ fn format_arg(arg: String, settings: &mut Settings) -> String { } } +/// Write string to stdout as unicode characters fn write_as_unicode(string: String) { let stdout = io::stdout(); if let Err(e) = stdout.lock().write_all(