comparison rust/hg-core/src/utils.rs @ 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 c18dd48cea4a
children 26114bd6ec60
comparison
equal deleted inserted replaced
44267:0e9ac3968b56 44268:aa0fc32ece9e
4 // 4 //
5 // This software may be used and distributed according to the terms of the 5 // This software may be used and distributed according to the terms of the
6 // GNU General Public License version 2 or any later version. 6 // GNU General Public License version 2 or any later version.
7 7
8 //! Contains useful functions, traits, structs, etc. for use in core. 8 //! Contains useful functions, traits, structs, etc. for use in core.
9
10 use crate::utils::hg_path::HgPath;
11 use std::{io::Write, ops::Deref};
9 12
10 pub mod files; 13 pub mod files;
11 pub mod hg_path; 14 pub mod hg_path;
12 pub mod path_auditor; 15 pub mod path_auditor;
13 16
110 } else { 113 } else {
111 None 114 None
112 } 115 }
113 } 116 }
114 } 117 }
118
119 pub trait Escaped {
120 /// Return bytes escaped for display to the user
121 fn escaped_bytes(&self) -> Vec<u8>;
122 }
123
124 impl Escaped for u8 {
125 fn escaped_bytes(&self) -> Vec<u8> {
126 let mut acc = vec![];
127 match self {
128 c @ b'\'' | c @ b'\\' => {
129 acc.push(b'\\');
130 acc.push(*c);
131 }
132 b'\t' => {
133 acc.extend(br"\\t");
134 }
135 b'\n' => {
136 acc.extend(br"\\n");
137 }
138 b'\r' => {
139 acc.extend(br"\\r");
140 }
141 c if (*c < b' ' || *c >= 127) => {
142 write!(acc, "\\x{:x}", self).unwrap();
143 }
144 c => {
145 acc.push(*c);
146 }
147 }
148 acc
149 }
150 }
151
152 impl<'a, T: Escaped> Escaped for &'a [T] {
153 fn escaped_bytes(&self) -> Vec<u8> {
154 self.iter().flat_map(|item| item.escaped_bytes()).collect()
155 }
156 }
157
158 impl<T: Escaped> Escaped for Vec<T> {
159 fn escaped_bytes(&self) -> Vec<u8> {
160 self.deref().escaped_bytes()
161 }
162 }
163
164 impl<'a> Escaped for &'a HgPath {
165 fn escaped_bytes(&self) -> Vec<u8> {
166 self.as_bytes().escaped_bytes()
167 }
168 }