Mercurial > public > mercurial-scm > hg
view rust/hg-core/src/utils.rs @ 44142:63db6657d280
rust-nodemap: building blocks for nodetree structures
This is similar to `nodetreenode` in `revlog.c`. We give it
a higher level feeling for ease of handling in Rust context
and provide tools for tests and debugging.
The encoding choice is dictated by our ultimate goal in this
series, that is to make an append-only persistent version of
`nodetree`: the 0th Block must be adressed from other Blocks.
Differential Revision: https://phab.mercurial-scm.org/D7787
author | Georges Racinet <georges.racinet@octobus.net> |
---|---|
date | Wed, 22 Jan 2020 16:23:29 +0100 |
parents | 191a461d6be6 |
children | c18dd48cea4a |
line wrap: on
line source
// utils module // // Copyright 2019 Raphaël Gomès <rgomes@octobus.net> // // This software may be used and distributed according to the terms of the // GNU General Public License version 2 or any later version. //! Contains useful functions, traits, structs, etc. for use in core. pub mod files; pub mod hg_path; /// Useful until rust/issues/56345 is stable /// /// # Examples /// /// ``` /// use crate::hg::utils::find_slice_in_slice; /// /// let haystack = b"This is the haystack".to_vec(); /// assert_eq!(find_slice_in_slice(&haystack, b"the"), Some(8)); /// assert_eq!(find_slice_in_slice(&haystack, b"not here"), None); /// ``` pub fn find_slice_in_slice<T>(slice: &[T], needle: &[T]) -> Option<usize> where for<'a> &'a [T]: PartialEq, { slice .windows(needle.len()) .position(|window| window == needle) } /// Replaces the `from` slice with the `to` slice inside the `buf` slice. /// /// # Examples /// /// ``` /// use crate::hg::utils::replace_slice; /// let mut line = b"I hate writing tests!".to_vec(); /// replace_slice(&mut line, b"hate", b"love"); /// assert_eq!( /// line, /// b"I love writing tests!".to_vec() /// ); /// ``` pub fn replace_slice<T>(buf: &mut [T], from: &[T], to: &[T]) where T: Clone + PartialEq, { if buf.len() < from.len() || from.len() != to.len() { return; } for i in 0..=buf.len() - from.len() { if buf[i..].starts_with(from) { buf[i..(i + from.len())].clone_from_slice(to); } } } pub trait SliceExt { fn trim_end(&self) -> &Self; fn trim_start(&self) -> &Self; fn trim(&self) -> &Self; fn drop_prefix(&self, needle: &Self) -> Option<&Self>; } fn is_not_whitespace(c: &u8) -> bool { !(*c as char).is_whitespace() } impl SliceExt for [u8] { fn trim_end(&self) -> &[u8] { if let Some(last) = self.iter().rposition(is_not_whitespace) { &self[..last + 1] } else { &[] } } fn trim_start(&self) -> &[u8] { if let Some(first) = self.iter().position(is_not_whitespace) { &self[first..] } else { &[] } } /// ``` /// use hg::utils::SliceExt; /// assert_eq!( /// b" to trim ".trim(), /// b"to trim" /// ); /// assert_eq!( /// b"to trim ".trim(), /// b"to trim" /// ); /// assert_eq!( /// b" to trim".trim(), /// b"to trim" /// ); /// ``` fn trim(&self) -> &[u8] { self.trim_start().trim_end() } fn drop_prefix(&self, needle: &Self) -> Option<&Self> { if self.starts_with(needle) { Some(&self[needle.len()..]) } else { None } } }