From patchwork Wed Jan 15 21:56:43 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: D7870: rust-utils: add `Escaped` trait From: phabricator X-Patchwork-Id: 44390 Message-Id: <7ec27f25177248e0a29f1acba526052b@localhost.localdomain> To: Phabricator Cc: mercurial-devel@mercurial-scm.org Date: Wed, 15 Jan 2020 21:56:43 +0000 Alphare retitled this revision from "rust-utils: add `PrettyPrint` trait" to "rust-utils: add `Escaped` trait". Alphare updated this revision to Diff 19320. REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D7870?vs=19262&id=19320 BRANCH default CHANGES SINCE LAST ACTION https://phab.mercurial-scm.org/D7870/new/ REVISION DETAIL https://phab.mercurial-scm.org/D7870 AFFECTED FILES rust/hg-core/src/utils.rs CHANGE DETAILS To: Alphare, #hg-reviewers, kevincox Cc: durin42, kevincox, mercurial-devel 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,57 @@ } } } + +pub trait Escaped { + /// Return bytes escaped for display to the user + fn escaped_bytes(&self) -> Vec; +} + +impl Escaped for u8 { + fn escaped_bytes(&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) => { + write!(acc, "\\x{:x}", self).unwrap(); + } + c => { + acc.push(*c); + } + } + acc + } +} + +impl<'a, T: Escaped> Escaped for &'a [T] { + fn escaped_bytes(&self) -> Vec { + self.iter().fold(vec![], |mut acc, item| { + acc.extend(item.escaped_bytes()); + acc + }) + } +} + +impl Escaped for Vec { + fn escaped_bytes(&self) -> Vec { + self.deref().escaped_bytes() + } +} + +impl<'a> Escaped for &'a HgPath { + fn escaped_bytes(&self) -> Vec { + self.as_bytes().escaped_bytes() + } +}