Mercurial > hg
changeset 44268:aa0fc32ece9e
rust-utils: add `Escaped` trait
This will be used as a general interface for displaying things to the user.
The upcoming `IncludeMatcher` will use it to store its patterns in a
user-displayable string.
Differential Revision: https://phab.mercurial-scm.org/D7870
author | Raphaël Gomès <rgomes@octobus.net> |
---|---|
date | Tue, 14 Jan 2020 17:08:45 +0100 |
parents | 0e9ac3968b56 |
children | 48a1a974a92c |
files | rust/hg-core/src/utils.rs |
diffstat | 1 files changed, 54 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- a/rust/hg-core/src/utils.rs Tue Jan 14 17:04:32 2020 +0100 +++ b/rust/hg-core/src/utils.rs Tue Jan 14 17:08:45 2020 +0100 @@ -7,6 +7,9 @@ //! Contains useful functions, traits, structs, etc. for use in core. +use crate::utils::hg_path::HgPath; +use std::{io::Write, ops::Deref}; + pub mod files; pub mod hg_path; pub mod path_auditor; @@ -112,3 +115,54 @@ } } } + +pub trait Escaped { + /// Return bytes escaped for display to the user + fn escaped_bytes(&self) -> Vec<u8>; +} + +impl Escaped for u8 { + fn escaped_bytes(&self) -> Vec<u8> { + 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<u8> { + self.iter().flat_map(|item| item.escaped_bytes()).collect() + } +} + +impl<T: Escaped> Escaped for Vec<T> { + fn escaped_bytes(&self) -> Vec<u8> { + self.deref().escaped_bytes() + } +} + +impl<'a> Escaped for &'a HgPath { + fn escaped_bytes(&self) -> Vec<u8> { + self.as_bytes().escaped_bytes() + } +}