diff --git a/rust/hg-core/src/utils.rs b/rust/hg-core/src/utils.rs --- a/rust/hg-core/src/utils.rs +++ b/rust/hg-core/src/utils.rs @@ -7,6 +7,9 @@ //! Contains useful functions, traits, structs, etc. for use in core. +use crate::utils::hg_path::HgPath; +use std::ops::Deref; + pub mod files; pub mod hg_path; pub mod path_auditor; @@ -112,3 +115,61 @@ } } } + +const HEX_DIGITS: &[u8] = b"0123456789abcdef"; + +pub trait PrettyPrint { + fn pretty_print(&self) -> Vec; +} + +impl PrettyPrint for u8 { + fn pretty_print(&self) -> Vec { + let mut acc = vec![]; + match self { + c @ b'\'' | c @ b'\\' => { + acc.push(b'\\'); + acc.push(*c); + } + b'\t' => { + acc.extend(br"\\t"); + } + b'\n' => { + acc.extend(br"\\n"); + } + b'\r' => { + acc.extend(br"\\r"); + } + c if (*c < b' ' || *c >= 127) => { + acc.push(b'\\'); + acc.push(b'x'); + acc.push(HEX_DIGITS[((*c & 0xf0) >> 4) as usize]); + acc.push(HEX_DIGITS[(*c & 0xf) as usize]); + } + c => { + acc.push(*c); + } + } + acc + } +} + +impl<'a, T: PrettyPrint> PrettyPrint for &'a [T] { + fn pretty_print(&self) -> Vec { + self.iter().fold(vec![], |mut acc, item| { + acc.extend(item.pretty_print()); + acc + }) + } +} + +impl PrettyPrint for Vec { + fn pretty_print(&self) -> Vec { + self.deref().pretty_print() + } +} + +impl<'a> PrettyPrint for &'a HgPath { + fn pretty_print(&self) -> Vec { + self.as_bytes().pretty_print() + } +}