annotate rust/hg-core/src/utils.rs @ 52316:f4aede0f01af

rust-manifest: use `memchr` crate for all byte-finding needs While writing a very dumb manifest diffing algorithm for a proof-of-concept I saw that `Manifest::find_by_path` was much slower than I was expecting. It turns out that the Rust stdlib uses slow (all is relative) code when searching for byte positions for reasons ranging from portability, SIMD API stability, nobody doing the work, etc. `memch` is much faster for these purposes, so let's use it. I was measuring ~670ms of profile time in `find_by_path`, after this patch it went down to ~230ms.
author Rapha?l Gom?s <rgomes@octobus.net>
date Tue, 12 Nov 2024 23:20:04 +0100
parents e6a44bc91bc2
children 36d39726c0af
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
42767
4b3b27d567d5 rust-docstrings: add missing module docstrings
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42764
diff changeset
1 // utils module
4b3b27d567d5 rust-docstrings: add missing module docstrings
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42764
diff changeset
2 //
4b3b27d567d5 rust-docstrings: add missing module docstrings
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42764
diff changeset
3 // Copyright 2019 Raphaël Gomès <rgomes@octobus.net>
4b3b27d567d5 rust-docstrings: add missing module docstrings
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42764
diff changeset
4 //
4b3b27d567d5 rust-docstrings: add missing module docstrings
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42764
diff changeset
5 // This software may be used and distributed according to the terms of the
4b3b27d567d5 rust-docstrings: add missing module docstrings
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42764
diff changeset
6 // GNU General Public License version 2 or any later version.
4b3b27d567d5 rust-docstrings: add missing module docstrings
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42764
diff changeset
7
4b3b27d567d5 rust-docstrings: add missing module docstrings
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42764
diff changeset
8 //! Contains useful functions, traits, structs, etc. for use in core.
4b3b27d567d5 rust-docstrings: add missing module docstrings
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42764
diff changeset
9
46513
ca3f73cc3cf4 rhg: Simplify CommandError based on its use
Simon Sapin <simon.sapin@octobus.net>
parents: 46091
diff changeset
10 use crate::errors::{HgError, IoErrorContext};
44315
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44312
diff changeset
11 use crate::utils::hg_path::HgPath;
46625
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
12 use im_rc::ordmap::DiffItem;
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
13 use im_rc::ordmap::OrdMap;
51189
aba622c7dc7e rust: add a utility function to merge ordered fallible iterators
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 50449
diff changeset
14 use itertools::EitherOrBoth;
aba622c7dc7e rust: add a utility function to merge ordered fallible iterators
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 50449
diff changeset
15 use itertools::Itertools;
46653
a069639783a0 rhg: Check .hg/requires for absence of required features
Simon Sapin <simon.sapin@octobus.net>
parents: 46640
diff changeset
16 use std::cell::Cell;
51189
aba622c7dc7e rust: add a utility function to merge ordered fallible iterators
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 50449
diff changeset
17 use std::cmp::Ordering;
46653
a069639783a0 rhg: Check .hg/requires for absence of required features
Simon Sapin <simon.sapin@octobus.net>
parents: 46640
diff changeset
18 use std::fmt;
44315
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44312
diff changeset
19 use std::{io::Write, ops::Deref};
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44312
diff changeset
20
49672
8e0d823ef182 testing: introduce util function to synchronize concurrent commands on files
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48463
diff changeset
21 pub mod debug;
42453
9609430d3625 rust-filepatterns: use bytes instead of String
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
22 pub mod files;
42959
3fe40dd6355d rust-hgpath: add HgPath and HgPathBuf structs to encapsulate handling of paths
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42869
diff changeset
23 pub mod hg_path;
44312
c18dd48cea4a rust-pathauditor: add Rust implementation of the `pathauditor`
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44079
diff changeset
24 pub mod path_auditor;
42453
9609430d3625 rust-filepatterns: use bytes instead of String
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
25
44079
191a461d6be6 rust-utils: add util to find a slice in another slice
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42959
diff changeset
26 /// Useful until rust/issues/56345 is stable
191a461d6be6 rust-utils: add util to find a slice in another slice
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42959
diff changeset
27 ///
191a461d6be6 rust-utils: add util to find a slice in another slice
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42959
diff changeset
28 /// # Examples
191a461d6be6 rust-utils: add util to find a slice in another slice
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42959
diff changeset
29 ///
191a461d6be6 rust-utils: add util to find a slice in another slice
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42959
diff changeset
30 /// ```
191a461d6be6 rust-utils: add util to find a slice in another slice
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42959
diff changeset
31 /// use crate::hg::utils::find_slice_in_slice;
191a461d6be6 rust-utils: add util to find a slice in another slice
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42959
diff changeset
32 ///
191a461d6be6 rust-utils: add util to find a slice in another slice
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42959
diff changeset
33 /// let haystack = b"This is the haystack".to_vec();
191a461d6be6 rust-utils: add util to find a slice in another slice
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42959
diff changeset
34 /// assert_eq!(find_slice_in_slice(&haystack, b"the"), Some(8));
191a461d6be6 rust-utils: add util to find a slice in another slice
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42959
diff changeset
35 /// assert_eq!(find_slice_in_slice(&haystack, b"not here"), None);
191a461d6be6 rust-utils: add util to find a slice in another slice
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42959
diff changeset
36 /// ```
191a461d6be6 rust-utils: add util to find a slice in another slice
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42959
diff changeset
37 pub fn find_slice_in_slice<T>(slice: &[T], needle: &[T]) -> Option<usize>
191a461d6be6 rust-utils: add util to find a slice in another slice
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42959
diff changeset
38 where
191a461d6be6 rust-utils: add util to find a slice in another slice
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42959
diff changeset
39 for<'a> &'a [T]: PartialEq,
191a461d6be6 rust-utils: add util to find a slice in another slice
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42959
diff changeset
40 {
191a461d6be6 rust-utils: add util to find a slice in another slice
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42959
diff changeset
41 slice
191a461d6be6 rust-utils: add util to find a slice in another slice
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42959
diff changeset
42 .windows(needle.len())
191a461d6be6 rust-utils: add util to find a slice in another slice
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42959
diff changeset
43 .position(|window| window == needle)
191a461d6be6 rust-utils: add util to find a slice in another slice
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42959
diff changeset
44 }
191a461d6be6 rust-utils: add util to find a slice in another slice
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42959
diff changeset
45
42610
5672bb73f61e rust-utils: add docstrings and doctests for utils.rs
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42609
diff changeset
46 /// Replaces the `from` slice with the `to` slice inside the `buf` slice.
5672bb73f61e rust-utils: add docstrings and doctests for utils.rs
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42609
diff changeset
47 ///
5672bb73f61e rust-utils: add docstrings and doctests for utils.rs
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42609
diff changeset
48 /// # Examples
5672bb73f61e rust-utils: add docstrings and doctests for utils.rs
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42609
diff changeset
49 ///
5672bb73f61e rust-utils: add docstrings and doctests for utils.rs
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42609
diff changeset
50 /// ```
5672bb73f61e rust-utils: add docstrings and doctests for utils.rs
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42609
diff changeset
51 /// use crate::hg::utils::replace_slice;
5672bb73f61e rust-utils: add docstrings and doctests for utils.rs
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42609
diff changeset
52 /// let mut line = b"I hate writing tests!".to_vec();
5672bb73f61e rust-utils: add docstrings and doctests for utils.rs
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42609
diff changeset
53 /// replace_slice(&mut line, b"hate", b"love");
5672bb73f61e rust-utils: add docstrings and doctests for utils.rs
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42609
diff changeset
54 /// assert_eq!(
5672bb73f61e rust-utils: add docstrings and doctests for utils.rs
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42609
diff changeset
55 /// line,
5672bb73f61e rust-utils: add docstrings and doctests for utils.rs
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42609
diff changeset
56 /// b"I love writing tests!".to_vec()
42851
ce6797ef6eab rust: apply more formatting fixes
Yuya Nishihara <yuya@tcha.org>
parents: 42815
diff changeset
57 /// );
42610
5672bb73f61e rust-utils: add docstrings and doctests for utils.rs
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42609
diff changeset
58 /// ```
42453
9609430d3625 rust-filepatterns: use bytes instead of String
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
59 pub fn replace_slice<T>(buf: &mut [T], from: &[T], to: &[T])
9609430d3625 rust-filepatterns: use bytes instead of String
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
60 where
9609430d3625 rust-filepatterns: use bytes instead of String
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
61 T: Clone + PartialEq,
9609430d3625 rust-filepatterns: use bytes instead of String
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
62 {
42611
2f760da140ee rust-utils: remove buggy assertion
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42610
diff changeset
63 if buf.len() < from.len() || from.len() != to.len() {
42453
9609430d3625 rust-filepatterns: use bytes instead of String
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
64 return;
9609430d3625 rust-filepatterns: use bytes instead of String
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
65 }
9609430d3625 rust-filepatterns: use bytes instead of String
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
66 for i in 0..=buf.len() - from.len() {
9609430d3625 rust-filepatterns: use bytes instead of String
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
67 if buf[i..].starts_with(from) {
9609430d3625 rust-filepatterns: use bytes instead of String
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
68 buf[i..(i + from.len())].clone_from_slice(to);
9609430d3625 rust-filepatterns: use bytes instead of String
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
69 }
9609430d3625 rust-filepatterns: use bytes instead of String
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
70 }
9609430d3625 rust-filepatterns: use bytes instead of String
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
71 }
9609430d3625 rust-filepatterns: use bytes instead of String
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
72
9609430d3625 rust-filepatterns: use bytes instead of String
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
73 pub trait SliceExt {
42610
5672bb73f61e rust-utils: add docstrings and doctests for utils.rs
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42609
diff changeset
74 fn trim_end(&self) -> &Self;
5672bb73f61e rust-utils: add docstrings and doctests for utils.rs
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42609
diff changeset
75 fn trim_start(&self) -> &Self;
47977
696abab107b4 rust: Generalize the `trim_end_newlines` utility of byte strings
Simon Sapin <simon.sapin@octobus.net>
parents: 46755
diff changeset
76 fn trim_end_matches(&self, f: impl FnMut(u8) -> bool) -> &Self;
696abab107b4 rust: Generalize the `trim_end_newlines` utility of byte strings
Simon Sapin <simon.sapin@octobus.net>
parents: 46755
diff changeset
77 fn trim_start_matches(&self, f: impl FnMut(u8) -> bool) -> &Self;
42453
9609430d3625 rust-filepatterns: use bytes instead of String
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
78 fn trim(&self) -> &Self;
42869
62eabdf91f85 rustfilepatterns: refactor the pattern of removing a prefix from a &[u8]
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 42851
diff changeset
79 fn drop_prefix(&self, needle: &Self) -> Option<&Self>;
46557
a25033eb43b5 rhg: add limited support for the `config` sub-command
Simon Sapin <simon.sapin@octobus.net>
parents: 46542
diff changeset
80 fn split_2(&self, separator: u8) -> Option<(&[u8], &[u8])>;
47989
4d2a5ca060e3 rust: Add a Filelog struct that wraps Revlog
Simon Sapin <simon.sapin@octobus.net>
parents: 47977
diff changeset
81 fn split_2_by_slice(&self, separator: &[u8]) -> Option<(&[u8], &[u8])>;
42453
9609430d3625 rust-filepatterns: use bytes instead of String
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
82 }
9609430d3625 rust-filepatterns: use bytes instead of String
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
83
47977
696abab107b4 rust: Generalize the `trim_end_newlines` utility of byte strings
Simon Sapin <simon.sapin@octobus.net>
parents: 46755
diff changeset
84 impl SliceExt for [u8] {
696abab107b4 rust: Generalize the `trim_end_newlines` utility of byte strings
Simon Sapin <simon.sapin@octobus.net>
parents: 46755
diff changeset
85 fn trim_end(&self) -> &[u8] {
696abab107b4 rust: Generalize the `trim_end_newlines` utility of byte strings
Simon Sapin <simon.sapin@octobus.net>
parents: 46755
diff changeset
86 self.trim_end_matches(|byte| byte.is_ascii_whitespace())
696abab107b4 rust: Generalize the `trim_end_newlines` utility of byte strings
Simon Sapin <simon.sapin@octobus.net>
parents: 46755
diff changeset
87 }
42453
9609430d3625 rust-filepatterns: use bytes instead of String
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
88
47977
696abab107b4 rust: Generalize the `trim_end_newlines` utility of byte strings
Simon Sapin <simon.sapin@octobus.net>
parents: 46755
diff changeset
89 fn trim_start(&self) -> &[u8] {
696abab107b4 rust: Generalize the `trim_end_newlines` utility of byte strings
Simon Sapin <simon.sapin@octobus.net>
parents: 46755
diff changeset
90 self.trim_start_matches(|byte| byte.is_ascii_whitespace())
696abab107b4 rust: Generalize the `trim_end_newlines` utility of byte strings
Simon Sapin <simon.sapin@octobus.net>
parents: 46755
diff changeset
91 }
696abab107b4 rust: Generalize the `trim_end_newlines` utility of byte strings
Simon Sapin <simon.sapin@octobus.net>
parents: 46755
diff changeset
92
696abab107b4 rust: Generalize the `trim_end_newlines` utility of byte strings
Simon Sapin <simon.sapin@octobus.net>
parents: 46755
diff changeset
93 fn trim_end_matches(&self, mut f: impl FnMut(u8) -> bool) -> &Self {
696abab107b4 rust: Generalize the `trim_end_newlines` utility of byte strings
Simon Sapin <simon.sapin@octobus.net>
parents: 46755
diff changeset
94 if let Some(last) = self.iter().rposition(|&byte| !f(byte)) {
46708
e8cd519a0a34 rhg: Ignore trailing newlines in .hg/sharedpath
Simon Sapin <simon.sapin@octobus.net>
parents: 46653
diff changeset
95 &self[..=last]
e8cd519a0a34 rhg: Ignore trailing newlines in .hg/sharedpath
Simon Sapin <simon.sapin@octobus.net>
parents: 46653
diff changeset
96 } else {
e8cd519a0a34 rhg: Ignore trailing newlines in .hg/sharedpath
Simon Sapin <simon.sapin@octobus.net>
parents: 46653
diff changeset
97 &[]
e8cd519a0a34 rhg: Ignore trailing newlines in .hg/sharedpath
Simon Sapin <simon.sapin@octobus.net>
parents: 46653
diff changeset
98 }
e8cd519a0a34 rhg: Ignore trailing newlines in .hg/sharedpath
Simon Sapin <simon.sapin@octobus.net>
parents: 46653
diff changeset
99 }
47977
696abab107b4 rust: Generalize the `trim_end_newlines` utility of byte strings
Simon Sapin <simon.sapin@octobus.net>
parents: 46755
diff changeset
100
696abab107b4 rust: Generalize the `trim_end_newlines` utility of byte strings
Simon Sapin <simon.sapin@octobus.net>
parents: 46755
diff changeset
101 fn trim_start_matches(&self, mut f: impl FnMut(u8) -> bool) -> &Self {
696abab107b4 rust: Generalize the `trim_end_newlines` utility of byte strings
Simon Sapin <simon.sapin@octobus.net>
parents: 46755
diff changeset
102 if let Some(first) = self.iter().position(|&byte| !f(byte)) {
42610
5672bb73f61e rust-utils: add docstrings and doctests for utils.rs
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42609
diff changeset
103 &self[first..]
5672bb73f61e rust-utils: add docstrings and doctests for utils.rs
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42609
diff changeset
104 } else {
5672bb73f61e rust-utils: add docstrings and doctests for utils.rs
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42609
diff changeset
105 &[]
5672bb73f61e rust-utils: add docstrings and doctests for utils.rs
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42609
diff changeset
106 }
5672bb73f61e rust-utils: add docstrings and doctests for utils.rs
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42609
diff changeset
107 }
5672bb73f61e rust-utils: add docstrings and doctests for utils.rs
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42609
diff changeset
108
5672bb73f61e rust-utils: add docstrings and doctests for utils.rs
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42609
diff changeset
109 /// ```
5672bb73f61e rust-utils: add docstrings and doctests for utils.rs
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42609
diff changeset
110 /// use hg::utils::SliceExt;
5672bb73f61e rust-utils: add docstrings and doctests for utils.rs
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42609
diff changeset
111 /// assert_eq!(
5672bb73f61e rust-utils: add docstrings and doctests for utils.rs
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42609
diff changeset
112 /// b" to trim ".trim(),
5672bb73f61e rust-utils: add docstrings and doctests for utils.rs
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42609
diff changeset
113 /// b"to trim"
5672bb73f61e rust-utils: add docstrings and doctests for utils.rs
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42609
diff changeset
114 /// );
5672bb73f61e rust-utils: add docstrings and doctests for utils.rs
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42609
diff changeset
115 /// assert_eq!(
5672bb73f61e rust-utils: add docstrings and doctests for utils.rs
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42609
diff changeset
116 /// b"to trim ".trim(),
5672bb73f61e rust-utils: add docstrings and doctests for utils.rs
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42609
diff changeset
117 /// b"to trim"
5672bb73f61e rust-utils: add docstrings and doctests for utils.rs
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42609
diff changeset
118 /// );
5672bb73f61e rust-utils: add docstrings and doctests for utils.rs
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42609
diff changeset
119 /// assert_eq!(
5672bb73f61e rust-utils: add docstrings and doctests for utils.rs
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42609
diff changeset
120 /// b" to trim".trim(),
5672bb73f61e rust-utils: add docstrings and doctests for utils.rs
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42609
diff changeset
121 /// b"to trim"
5672bb73f61e rust-utils: add docstrings and doctests for utils.rs
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42609
diff changeset
122 /// );
5672bb73f61e rust-utils: add docstrings and doctests for utils.rs
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42609
diff changeset
123 /// ```
5672bb73f61e rust-utils: add docstrings and doctests for utils.rs
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42609
diff changeset
124 fn trim(&self) -> &[u8] {
5672bb73f61e rust-utils: add docstrings and doctests for utils.rs
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42609
diff changeset
125 self.trim_start().trim_end()
5672bb73f61e rust-utils: add docstrings and doctests for utils.rs
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42609
diff changeset
126 }
42869
62eabdf91f85 rustfilepatterns: refactor the pattern of removing a prefix from a &[u8]
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 42851
diff changeset
127
62eabdf91f85 rustfilepatterns: refactor the pattern of removing a prefix from a &[u8]
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 42851
diff changeset
128 fn drop_prefix(&self, needle: &Self) -> Option<&Self> {
62eabdf91f85 rustfilepatterns: refactor the pattern of removing a prefix from a &[u8]
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 42851
diff changeset
129 if self.starts_with(needle) {
62eabdf91f85 rustfilepatterns: refactor the pattern of removing a prefix from a &[u8]
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 42851
diff changeset
130 Some(&self[needle.len()..])
62eabdf91f85 rustfilepatterns: refactor the pattern of removing a prefix from a &[u8]
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 42851
diff changeset
131 } else {
62eabdf91f85 rustfilepatterns: refactor the pattern of removing a prefix from a &[u8]
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 42851
diff changeset
132 None
62eabdf91f85 rustfilepatterns: refactor the pattern of removing a prefix from a &[u8]
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 42851
diff changeset
133 }
62eabdf91f85 rustfilepatterns: refactor the pattern of removing a prefix from a &[u8]
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 42851
diff changeset
134 }
46557
a25033eb43b5 rhg: add limited support for the `config` sub-command
Simon Sapin <simon.sapin@octobus.net>
parents: 46542
diff changeset
135
a25033eb43b5 rhg: add limited support for the `config` sub-command
Simon Sapin <simon.sapin@octobus.net>
parents: 46542
diff changeset
136 fn split_2(&self, separator: u8) -> Option<(&[u8], &[u8])> {
52316
f4aede0f01af rust-manifest: use `memchr` crate for all byte-finding needs
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52156
diff changeset
137 let pos = memchr::memchr(separator, self)?;
f4aede0f01af rust-manifest: use `memchr` crate for all byte-finding needs
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52156
diff changeset
138 Some((&self[..pos], &self[pos + 1..]))
46557
a25033eb43b5 rhg: add limited support for the `config` sub-command
Simon Sapin <simon.sapin@octobus.net>
parents: 46542
diff changeset
139 }
47989
4d2a5ca060e3 rust: Add a Filelog struct that wraps Revlog
Simon Sapin <simon.sapin@octobus.net>
parents: 47977
diff changeset
140
4d2a5ca060e3 rust: Add a Filelog struct that wraps Revlog
Simon Sapin <simon.sapin@octobus.net>
parents: 47977
diff changeset
141 fn split_2_by_slice(&self, separator: &[u8]) -> Option<(&[u8], &[u8])> {
50003
e98fd81bb151 rust-clippy: fix most warnings in `hg-core`
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50002
diff changeset
142 find_slice_in_slice(self, separator)
e98fd81bb151 rust-clippy: fix most warnings in `hg-core`
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50002
diff changeset
143 .map(|pos| (&self[..pos], &self[pos + separator.len()..]))
48463
5734b03ecf3e rhg: Initial repository locking
Simon Sapin <simon.sapin@octobus.net>
parents: 47989
diff changeset
144 }
5734b03ecf3e rhg: Initial repository locking
Simon Sapin <simon.sapin@octobus.net>
parents: 47989
diff changeset
145 }
5734b03ecf3e rhg: Initial repository locking
Simon Sapin <simon.sapin@octobus.net>
parents: 47989
diff changeset
146
44315
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44312
diff changeset
147 pub trait Escaped {
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44312
diff changeset
148 /// Return bytes escaped for display to the user
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44312
diff changeset
149 fn escaped_bytes(&self) -> Vec<u8>;
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44312
diff changeset
150 }
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44312
diff changeset
151
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44312
diff changeset
152 impl Escaped for u8 {
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44312
diff changeset
153 fn escaped_bytes(&self) -> Vec<u8> {
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44312
diff changeset
154 let mut acc = vec![];
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44312
diff changeset
155 match self {
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44312
diff changeset
156 c @ b'\'' | c @ b'\\' => {
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44312
diff changeset
157 acc.push(b'\\');
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44312
diff changeset
158 acc.push(*c);
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44312
diff changeset
159 }
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44312
diff changeset
160 b'\t' => {
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44312
diff changeset
161 acc.extend(br"\\t");
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44312
diff changeset
162 }
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44312
diff changeset
163 b'\n' => {
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44312
diff changeset
164 acc.extend(br"\\n");
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44312
diff changeset
165 }
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44312
diff changeset
166 b'\r' => {
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44312
diff changeset
167 acc.extend(br"\\r");
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44312
diff changeset
168 }
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44312
diff changeset
169 c if (*c < b' ' || *c >= 127) => {
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44312
diff changeset
170 write!(acc, "\\x{:x}", self).unwrap();
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44312
diff changeset
171 }
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44312
diff changeset
172 c => {
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44312
diff changeset
173 acc.push(*c);
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44312
diff changeset
174 }
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44312
diff changeset
175 }
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44312
diff changeset
176 acc
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44312
diff changeset
177 }
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44312
diff changeset
178 }
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44312
diff changeset
179
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44312
diff changeset
180 impl<'a, T: Escaped> Escaped for &'a [T] {
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44312
diff changeset
181 fn escaped_bytes(&self) -> Vec<u8> {
44998
26114bd6ec60 rust: do a clippy pass
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44315
diff changeset
182 self.iter().flat_map(Escaped::escaped_bytes).collect()
44315
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44312
diff changeset
183 }
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44312
diff changeset
184 }
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44312
diff changeset
185
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44312
diff changeset
186 impl<T: Escaped> Escaped for Vec<T> {
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44312
diff changeset
187 fn escaped_bytes(&self) -> Vec<u8> {
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44312
diff changeset
188 self.deref().escaped_bytes()
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44312
diff changeset
189 }
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44312
diff changeset
190 }
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44312
diff changeset
191
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44312
diff changeset
192 impl<'a> Escaped for &'a HgPath {
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44312
diff changeset
193 fn escaped_bytes(&self) -> Vec<u8> {
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44312
diff changeset
194 self.as_bytes().escaped_bytes()
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44312
diff changeset
195 }
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44312
diff changeset
196 }
46091
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents: 44998
diff changeset
197
46640
755c31a1caf9 rhg: Add support for the blackbox extension
Simon Sapin <simon.sapin@octobus.net>
parents: 46625
diff changeset
198 #[cfg(unix)]
755c31a1caf9 rhg: Add support for the blackbox extension
Simon Sapin <simon.sapin@octobus.net>
parents: 46625
diff changeset
199 pub fn shell_quote(value: &[u8]) -> Vec<u8> {
49752
ec399ddf6764 rust: use `matches!` macro now that we're using Rust 1.42+
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49751
diff changeset
200 if value.iter().all(|&byte| {
ec399ddf6764 rust: use `matches!` macro now that we're using Rust 1.42+
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49751
diff changeset
201 matches!(
ec399ddf6764 rust: use `matches!` macro now that we're using Rust 1.42+
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49751
diff changeset
202 byte,
ec399ddf6764 rust: use `matches!` macro now that we're using Rust 1.42+
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49751
diff changeset
203 b'a'..=b'z'
ec399ddf6764 rust: use `matches!` macro now that we're using Rust 1.42+
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49751
diff changeset
204 | b'A'..=b'Z'
ec399ddf6764 rust: use `matches!` macro now that we're using Rust 1.42+
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49751
diff changeset
205 | b'0'..=b'9'
ec399ddf6764 rust: use `matches!` macro now that we're using Rust 1.42+
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49751
diff changeset
206 | b'.'
ec399ddf6764 rust: use `matches!` macro now that we're using Rust 1.42+
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49751
diff changeset
207 | b'_'
ec399ddf6764 rust: use `matches!` macro now that we're using Rust 1.42+
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49751
diff changeset
208 | b'/'
ec399ddf6764 rust: use `matches!` macro now that we're using Rust 1.42+
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49751
diff changeset
209 | b'+'
ec399ddf6764 rust: use `matches!` macro now that we're using Rust 1.42+
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49751
diff changeset
210 | b'-'
ec399ddf6764 rust: use `matches!` macro now that we're using Rust 1.42+
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49751
diff changeset
211 )
46640
755c31a1caf9 rhg: Add support for the blackbox extension
Simon Sapin <simon.sapin@octobus.net>
parents: 46625
diff changeset
212 }) {
755c31a1caf9 rhg: Add support for the blackbox extension
Simon Sapin <simon.sapin@octobus.net>
parents: 46625
diff changeset
213 value.to_owned()
755c31a1caf9 rhg: Add support for the blackbox extension
Simon Sapin <simon.sapin@octobus.net>
parents: 46625
diff changeset
214 } else {
755c31a1caf9 rhg: Add support for the blackbox extension
Simon Sapin <simon.sapin@octobus.net>
parents: 46625
diff changeset
215 let mut quoted = Vec::with_capacity(value.len() + 2);
755c31a1caf9 rhg: Add support for the blackbox extension
Simon Sapin <simon.sapin@octobus.net>
parents: 46625
diff changeset
216 quoted.push(b'\'');
755c31a1caf9 rhg: Add support for the blackbox extension
Simon Sapin <simon.sapin@octobus.net>
parents: 46625
diff changeset
217 for &byte in value {
755c31a1caf9 rhg: Add support for the blackbox extension
Simon Sapin <simon.sapin@octobus.net>
parents: 46625
diff changeset
218 if byte == b'\'' {
755c31a1caf9 rhg: Add support for the blackbox extension
Simon Sapin <simon.sapin@octobus.net>
parents: 46625
diff changeset
219 quoted.push(b'\\');
755c31a1caf9 rhg: Add support for the blackbox extension
Simon Sapin <simon.sapin@octobus.net>
parents: 46625
diff changeset
220 }
755c31a1caf9 rhg: Add support for the blackbox extension
Simon Sapin <simon.sapin@octobus.net>
parents: 46625
diff changeset
221 quoted.push(byte);
755c31a1caf9 rhg: Add support for the blackbox extension
Simon Sapin <simon.sapin@octobus.net>
parents: 46625
diff changeset
222 }
755c31a1caf9 rhg: Add support for the blackbox extension
Simon Sapin <simon.sapin@octobus.net>
parents: 46625
diff changeset
223 quoted.push(b'\'');
755c31a1caf9 rhg: Add support for the blackbox extension
Simon Sapin <simon.sapin@octobus.net>
parents: 46625
diff changeset
224 quoted
755c31a1caf9 rhg: Add support for the blackbox extension
Simon Sapin <simon.sapin@octobus.net>
parents: 46625
diff changeset
225 }
755c31a1caf9 rhg: Add support for the blackbox extension
Simon Sapin <simon.sapin@octobus.net>
parents: 46625
diff changeset
226 }
755c31a1caf9 rhg: Add support for the blackbox extension
Simon Sapin <simon.sapin@octobus.net>
parents: 46625
diff changeset
227
46513
ca3f73cc3cf4 rhg: Simplify CommandError based on its use
Simon Sapin <simon.sapin@octobus.net>
parents: 46091
diff changeset
228 pub fn current_dir() -> Result<std::path::PathBuf, HgError> {
ca3f73cc3cf4 rhg: Simplify CommandError based on its use
Simon Sapin <simon.sapin@octobus.net>
parents: 46091
diff changeset
229 std::env::current_dir().map_err(|error| HgError::IoError {
ca3f73cc3cf4 rhg: Simplify CommandError based on its use
Simon Sapin <simon.sapin@octobus.net>
parents: 46091
diff changeset
230 error,
ca3f73cc3cf4 rhg: Simplify CommandError based on its use
Simon Sapin <simon.sapin@octobus.net>
parents: 46091
diff changeset
231 context: IoErrorContext::CurrentDir,
ca3f73cc3cf4 rhg: Simplify CommandError based on its use
Simon Sapin <simon.sapin@octobus.net>
parents: 46091
diff changeset
232 })
ca3f73cc3cf4 rhg: Simplify CommandError based on its use
Simon Sapin <simon.sapin@octobus.net>
parents: 46091
diff changeset
233 }
46542
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46513
diff changeset
234
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46513
diff changeset
235 pub fn current_exe() -> Result<std::path::PathBuf, HgError> {
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46513
diff changeset
236 std::env::current_exe().map_err(|error| HgError::IoError {
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46513
diff changeset
237 error,
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46513
diff changeset
238 context: IoErrorContext::CurrentExe,
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46513
diff changeset
239 })
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46513
diff changeset
240 }
46625
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
241
46755
91ab5190a3de rhg: Add support for environment variables in config include paths
Simon Sapin <simon.sapin@octobus.net>
parents: 46708
diff changeset
242 /// Expand `$FOO` and `${FOO}` environment variables in the given byte string
91ab5190a3de rhg: Add support for environment variables in config include paths
Simon Sapin <simon.sapin@octobus.net>
parents: 46708
diff changeset
243 pub fn expand_vars(s: &[u8]) -> std::borrow::Cow<[u8]> {
91ab5190a3de rhg: Add support for environment variables in config include paths
Simon Sapin <simon.sapin@octobus.net>
parents: 46708
diff changeset
244 lazy_static::lazy_static! {
91ab5190a3de rhg: Add support for environment variables in config include paths
Simon Sapin <simon.sapin@octobus.net>
parents: 46708
diff changeset
245 /// https://github.com/python/cpython/blob/3.9/Lib/posixpath.py#L301
91ab5190a3de rhg: Add support for environment variables in config include paths
Simon Sapin <simon.sapin@octobus.net>
parents: 46708
diff changeset
246 /// The `x` makes whitespace ignored.
91ab5190a3de rhg: Add support for environment variables in config include paths
Simon Sapin <simon.sapin@octobus.net>
parents: 46708
diff changeset
247 /// `-u` disables the Unicode flag, which makes `\w` like Python with the ASCII flag.
91ab5190a3de rhg: Add support for environment variables in config include paths
Simon Sapin <simon.sapin@octobus.net>
parents: 46708
diff changeset
248 static ref VAR_RE: regex::bytes::Regex =
91ab5190a3de rhg: Add support for environment variables in config include paths
Simon Sapin <simon.sapin@octobus.net>
parents: 46708
diff changeset
249 regex::bytes::Regex::new(r"(?x-u)
91ab5190a3de rhg: Add support for environment variables in config include paths
Simon Sapin <simon.sapin@octobus.net>
parents: 46708
diff changeset
250 \$
91ab5190a3de rhg: Add support for environment variables in config include paths
Simon Sapin <simon.sapin@octobus.net>
parents: 46708
diff changeset
251 (?:
91ab5190a3de rhg: Add support for environment variables in config include paths
Simon Sapin <simon.sapin@octobus.net>
parents: 46708
diff changeset
252 (\w+)
91ab5190a3de rhg: Add support for environment variables in config include paths
Simon Sapin <simon.sapin@octobus.net>
parents: 46708
diff changeset
253 |
91ab5190a3de rhg: Add support for environment variables in config include paths
Simon Sapin <simon.sapin@octobus.net>
parents: 46708
diff changeset
254 \{
91ab5190a3de rhg: Add support for environment variables in config include paths
Simon Sapin <simon.sapin@octobus.net>
parents: 46708
diff changeset
255 ([^}]*)
91ab5190a3de rhg: Add support for environment variables in config include paths
Simon Sapin <simon.sapin@octobus.net>
parents: 46708
diff changeset
256 \}
91ab5190a3de rhg: Add support for environment variables in config include paths
Simon Sapin <simon.sapin@octobus.net>
parents: 46708
diff changeset
257 )
91ab5190a3de rhg: Add support for environment variables in config include paths
Simon Sapin <simon.sapin@octobus.net>
parents: 46708
diff changeset
258 ").unwrap();
91ab5190a3de rhg: Add support for environment variables in config include paths
Simon Sapin <simon.sapin@octobus.net>
parents: 46708
diff changeset
259 }
91ab5190a3de rhg: Add support for environment variables in config include paths
Simon Sapin <simon.sapin@octobus.net>
parents: 46708
diff changeset
260 VAR_RE.replace_all(s, |captures: &regex::bytes::Captures| {
91ab5190a3de rhg: Add support for environment variables in config include paths
Simon Sapin <simon.sapin@octobus.net>
parents: 46708
diff changeset
261 let var_name = files::get_os_str_from_bytes(
91ab5190a3de rhg: Add support for environment variables in config include paths
Simon Sapin <simon.sapin@octobus.net>
parents: 46708
diff changeset
262 captures
91ab5190a3de rhg: Add support for environment variables in config include paths
Simon Sapin <simon.sapin@octobus.net>
parents: 46708
diff changeset
263 .get(1)
91ab5190a3de rhg: Add support for environment variables in config include paths
Simon Sapin <simon.sapin@octobus.net>
parents: 46708
diff changeset
264 .or_else(|| captures.get(2))
91ab5190a3de rhg: Add support for environment variables in config include paths
Simon Sapin <simon.sapin@octobus.net>
parents: 46708
diff changeset
265 .expect("either side of `|` must participate in match")
91ab5190a3de rhg: Add support for environment variables in config include paths
Simon Sapin <simon.sapin@octobus.net>
parents: 46708
diff changeset
266 .as_bytes(),
91ab5190a3de rhg: Add support for environment variables in config include paths
Simon Sapin <simon.sapin@octobus.net>
parents: 46708
diff changeset
267 );
91ab5190a3de rhg: Add support for environment variables in config include paths
Simon Sapin <simon.sapin@octobus.net>
parents: 46708
diff changeset
268 std::env::var_os(var_name)
91ab5190a3de rhg: Add support for environment variables in config include paths
Simon Sapin <simon.sapin@octobus.net>
parents: 46708
diff changeset
269 .map(files::get_bytes_from_os_str)
91ab5190a3de rhg: Add support for environment variables in config include paths
Simon Sapin <simon.sapin@octobus.net>
parents: 46708
diff changeset
270 .unwrap_or_else(|| {
91ab5190a3de rhg: Add support for environment variables in config include paths
Simon Sapin <simon.sapin@octobus.net>
parents: 46708
diff changeset
271 // Referencing an environment variable that does not exist.
91ab5190a3de rhg: Add support for environment variables in config include paths
Simon Sapin <simon.sapin@octobus.net>
parents: 46708
diff changeset
272 // Leave the $FOO reference as-is.
91ab5190a3de rhg: Add support for environment variables in config include paths
Simon Sapin <simon.sapin@octobus.net>
parents: 46708
diff changeset
273 captures[0].to_owned()
91ab5190a3de rhg: Add support for environment variables in config include paths
Simon Sapin <simon.sapin@octobus.net>
parents: 46708
diff changeset
274 })
91ab5190a3de rhg: Add support for environment variables in config include paths
Simon Sapin <simon.sapin@octobus.net>
parents: 46708
diff changeset
275 })
91ab5190a3de rhg: Add support for environment variables in config include paths
Simon Sapin <simon.sapin@octobus.net>
parents: 46708
diff changeset
276 }
91ab5190a3de rhg: Add support for environment variables in config include paths
Simon Sapin <simon.sapin@octobus.net>
parents: 46708
diff changeset
277
91ab5190a3de rhg: Add support for environment variables in config include paths
Simon Sapin <simon.sapin@octobus.net>
parents: 46708
diff changeset
278 #[test]
91ab5190a3de rhg: Add support for environment variables in config include paths
Simon Sapin <simon.sapin@octobus.net>
parents: 46708
diff changeset
279 fn test_expand_vars() {
91ab5190a3de rhg: Add support for environment variables in config include paths
Simon Sapin <simon.sapin@octobus.net>
parents: 46708
diff changeset
280 // Modifying process-global state in a test isn’t great,
91ab5190a3de rhg: Add support for environment variables in config include paths
Simon Sapin <simon.sapin@octobus.net>
parents: 46708
diff changeset
281 // but hopefully this won’t collide with anything.
91ab5190a3de rhg: Add support for environment variables in config include paths
Simon Sapin <simon.sapin@octobus.net>
parents: 46708
diff changeset
282 std::env::set_var("TEST_EXPAND_VAR", "1");
91ab5190a3de rhg: Add support for environment variables in config include paths
Simon Sapin <simon.sapin@octobus.net>
parents: 46708
diff changeset
283 assert_eq!(
91ab5190a3de rhg: Add support for environment variables in config include paths
Simon Sapin <simon.sapin@octobus.net>
parents: 46708
diff changeset
284 expand_vars(b"before/$TEST_EXPAND_VAR/after"),
91ab5190a3de rhg: Add support for environment variables in config include paths
Simon Sapin <simon.sapin@octobus.net>
parents: 46708
diff changeset
285 &b"before/1/after"[..]
91ab5190a3de rhg: Add support for environment variables in config include paths
Simon Sapin <simon.sapin@octobus.net>
parents: 46708
diff changeset
286 );
91ab5190a3de rhg: Add support for environment variables in config include paths
Simon Sapin <simon.sapin@octobus.net>
parents: 46708
diff changeset
287 assert_eq!(
91ab5190a3de rhg: Add support for environment variables in config include paths
Simon Sapin <simon.sapin@octobus.net>
parents: 46708
diff changeset
288 expand_vars(b"before${TEST_EXPAND_VAR}${TEST_EXPAND_VAR}${TEST_EXPAND_VAR}after"),
91ab5190a3de rhg: Add support for environment variables in config include paths
Simon Sapin <simon.sapin@octobus.net>
parents: 46708
diff changeset
289 &b"before111after"[..]
91ab5190a3de rhg: Add support for environment variables in config include paths
Simon Sapin <simon.sapin@octobus.net>
parents: 46708
diff changeset
290 );
91ab5190a3de rhg: Add support for environment variables in config include paths
Simon Sapin <simon.sapin@octobus.net>
parents: 46708
diff changeset
291 let s = b"before $SOME_LONG_NAME_THAT_WE_ASSUME_IS_NOT_AN_ACTUAL_ENV_VAR after";
91ab5190a3de rhg: Add support for environment variables in config include paths
Simon Sapin <simon.sapin@octobus.net>
parents: 46708
diff changeset
292 assert_eq!(expand_vars(s), &s[..]);
91ab5190a3de rhg: Add support for environment variables in config include paths
Simon Sapin <simon.sapin@octobus.net>
parents: 46708
diff changeset
293 }
91ab5190a3de rhg: Add support for environment variables in config include paths
Simon Sapin <simon.sapin@octobus.net>
parents: 46708
diff changeset
294
46625
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
295 pub(crate) enum MergeResult<V> {
50007
83437ad8fe3d rust-clippy: remove redundant suffix from enum
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50003
diff changeset
296 Left,
83437ad8fe3d rust-clippy: remove redundant suffix from enum
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50003
diff changeset
297 Right,
83437ad8fe3d rust-clippy: remove redundant suffix from enum
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50003
diff changeset
298 New(V),
46625
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
299 }
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
300
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
301 /// Return the union of the two given maps,
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
302 /// calling `merge(key, left_value, right_value)` to resolve keys that exist in
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
303 /// both.
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
304 ///
50449
331a3cbe1c9e rustdoc: fixed warnings about links
Georges Racinet <georges.racinet@octobus.net>
parents: 50321
diff changeset
305 /// CC <https://github.com/bodil/im-rs/issues/166>
46625
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
306 pub(crate) fn ordmap_union_with_merge<K, V>(
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
307 left: OrdMap<K, V>,
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
308 right: OrdMap<K, V>,
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
309 mut merge: impl FnMut(&K, &V, &V) -> MergeResult<V>,
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
310 ) -> OrdMap<K, V>
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
311 where
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
312 K: Clone + Ord,
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
313 V: Clone + PartialEq,
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
314 {
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
315 if left.ptr_eq(&right) {
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
316 // One of the two maps is an unmodified clone of the other
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
317 left
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
318 } else if left.len() / 2 > right.len() {
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
319 // When two maps have different sizes,
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
320 // their size difference is a lower bound on
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
321 // how many keys of the larger map are not also in the smaller map.
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
322 // This in turn is a lower bound on the number of differences in
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
323 // `OrdMap::diff` and the "amount of work" that would be done
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
324 // by `ordmap_union_with_merge_by_diff`.
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
325 //
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
326 // Here `left` is more than twice the size of `right`,
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
327 // so the number of differences is more than the total size of
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
328 // `right`. Therefore an algorithm based on iterating `right`
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
329 // is more efficient.
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
330 //
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
331 // This helps a lot when a tiny (or empty) map is merged
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
332 // with a large one.
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
333 ordmap_union_with_merge_by_iter(left, right, merge)
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
334 } else if left.len() < right.len() / 2 {
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
335 // Same as above but with `left` and `right` swapped
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
336 ordmap_union_with_merge_by_iter(right, left, |key, a, b| {
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
337 // Also swapped in `merge` arguments:
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
338 match merge(key, b, a) {
50007
83437ad8fe3d rust-clippy: remove redundant suffix from enum
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50003
diff changeset
339 MergeResult::New(v) => MergeResult::New(v),
46625
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
340 // … and swap back in `merge` result:
50007
83437ad8fe3d rust-clippy: remove redundant suffix from enum
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50003
diff changeset
341 MergeResult::Left => MergeResult::Right,
83437ad8fe3d rust-clippy: remove redundant suffix from enum
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50003
diff changeset
342 MergeResult::Right => MergeResult::Left,
46625
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
343 }
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
344 })
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
345 } else {
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
346 // For maps of similar size, use the algorithm based on `OrdMap::diff`
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
347 ordmap_union_with_merge_by_diff(left, right, merge)
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
348 }
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
349 }
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
350
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
351 /// Efficient if `right` is much smaller than `left`
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
352 fn ordmap_union_with_merge_by_iter<K, V>(
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
353 mut left: OrdMap<K, V>,
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
354 right: OrdMap<K, V>,
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
355 mut merge: impl FnMut(&K, &V, &V) -> MergeResult<V>,
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
356 ) -> OrdMap<K, V>
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
357 where
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
358 K: Clone + Ord,
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
359 V: Clone,
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
360 {
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
361 for (key, right_value) in right {
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
362 match left.get(&key) {
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
363 None => {
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
364 left.insert(key, right_value);
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
365 }
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
366 Some(left_value) => match merge(&key, left_value, &right_value) {
50007
83437ad8fe3d rust-clippy: remove redundant suffix from enum
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50003
diff changeset
367 MergeResult::Left => {}
83437ad8fe3d rust-clippy: remove redundant suffix from enum
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50003
diff changeset
368 MergeResult::Right => {
46625
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
369 left.insert(key, right_value);
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
370 }
50007
83437ad8fe3d rust-clippy: remove redundant suffix from enum
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50003
diff changeset
371 MergeResult::New(new_value) => {
46625
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
372 left.insert(key, new_value);
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
373 }
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
374 },
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
375 }
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
376 }
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
377 left
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
378 }
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
379
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
380 /// Fallback when both maps are of similar size
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
381 fn ordmap_union_with_merge_by_diff<K, V>(
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
382 mut left: OrdMap<K, V>,
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
383 mut right: OrdMap<K, V>,
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
384 mut merge: impl FnMut(&K, &V, &V) -> MergeResult<V>,
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
385 ) -> OrdMap<K, V>
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
386 where
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
387 K: Clone + Ord,
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
388 V: Clone + PartialEq,
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
389 {
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
390 // (key, value) pairs that would need to be inserted in either map
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
391 // in order to turn it into the union.
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
392 //
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
393 // TODO: if/when https://github.com/bodil/im-rs/pull/168 is accepted,
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
394 // change these from `Vec<(K, V)>` to `Vec<(&K, Cow<V>)>`
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
395 // with `left_updates` only borrowing from `right` and `right_updates` from
50007
83437ad8fe3d rust-clippy: remove redundant suffix from enum
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50003
diff changeset
396 // `left`, and with `Cow::Owned` used for `MergeResult::New`.
46625
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
397 //
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
398 // This would allow moving all `.clone()` calls to after we’ve decided
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
399 // which of `right_updates` or `left_updates` to use
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
400 // (value ones becoming `Cow::into_owned`),
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
401 // and avoid making clones we don’t end up using.
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
402 let mut left_updates = Vec::new();
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
403 let mut right_updates = Vec::new();
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
404
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
405 for difference in left.diff(&right) {
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
406 match difference {
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
407 DiffItem::Add(key, value) => {
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
408 left_updates.push((key.clone(), value.clone()))
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
409 }
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
410 DiffItem::Remove(key, value) => {
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
411 right_updates.push((key.clone(), value.clone()))
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
412 }
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
413 DiffItem::Update {
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
414 old: (key, left_value),
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
415 new: (_, right_value),
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
416 } => match merge(key, left_value, right_value) {
50007
83437ad8fe3d rust-clippy: remove redundant suffix from enum
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50003
diff changeset
417 MergeResult::Left => {
46625
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
418 right_updates.push((key.clone(), left_value.clone()))
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
419 }
50007
83437ad8fe3d rust-clippy: remove redundant suffix from enum
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50003
diff changeset
420 MergeResult::Right => {
46625
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
421 left_updates.push((key.clone(), right_value.clone()))
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
422 }
50007
83437ad8fe3d rust-clippy: remove redundant suffix from enum
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50003
diff changeset
423 MergeResult::New(new_value) => {
46625
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
424 left_updates.push((key.clone(), new_value.clone()));
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
425 right_updates.push((key.clone(), new_value))
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
426 }
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
427 },
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
428 }
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
429 }
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
430 if left_updates.len() < right_updates.len() {
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
431 for (key, value) in left_updates {
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
432 left.insert(key, value);
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
433 }
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
434 left
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
435 } else {
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
436 for (key, value) in right_updates {
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
437 right.insert(key, value);
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
438 }
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
439 right
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
440 }
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
441 }
46653
a069639783a0 rhg: Check .hg/requires for absence of required features
Simon Sapin <simon.sapin@octobus.net>
parents: 46640
diff changeset
442
a069639783a0 rhg: Check .hg/requires for absence of required features
Simon Sapin <simon.sapin@octobus.net>
parents: 46640
diff changeset
443 /// Join items of the iterable with the given separator, similar to Python’s
a069639783a0 rhg: Check .hg/requires for absence of required features
Simon Sapin <simon.sapin@octobus.net>
parents: 46640
diff changeset
444 /// `separator.join(iter)`.
a069639783a0 rhg: Check .hg/requires for absence of required features
Simon Sapin <simon.sapin@octobus.net>
parents: 46640
diff changeset
445 ///
a069639783a0 rhg: Check .hg/requires for absence of required features
Simon Sapin <simon.sapin@octobus.net>
parents: 46640
diff changeset
446 /// Formatting the return value consumes the iterator.
a069639783a0 rhg: Check .hg/requires for absence of required features
Simon Sapin <simon.sapin@octobus.net>
parents: 46640
diff changeset
447 /// Formatting it again will produce an empty string.
a069639783a0 rhg: Check .hg/requires for absence of required features
Simon Sapin <simon.sapin@octobus.net>
parents: 46640
diff changeset
448 pub fn join_display(
a069639783a0 rhg: Check .hg/requires for absence of required features
Simon Sapin <simon.sapin@octobus.net>
parents: 46640
diff changeset
449 iter: impl IntoIterator<Item = impl fmt::Display>,
a069639783a0 rhg: Check .hg/requires for absence of required features
Simon Sapin <simon.sapin@octobus.net>
parents: 46640
diff changeset
450 separator: impl fmt::Display,
a069639783a0 rhg: Check .hg/requires for absence of required features
Simon Sapin <simon.sapin@octobus.net>
parents: 46640
diff changeset
451 ) -> impl fmt::Display {
a069639783a0 rhg: Check .hg/requires for absence of required features
Simon Sapin <simon.sapin@octobus.net>
parents: 46640
diff changeset
452 JoinDisplay {
a069639783a0 rhg: Check .hg/requires for absence of required features
Simon Sapin <simon.sapin@octobus.net>
parents: 46640
diff changeset
453 iter: Cell::new(Some(iter.into_iter())),
a069639783a0 rhg: Check .hg/requires for absence of required features
Simon Sapin <simon.sapin@octobus.net>
parents: 46640
diff changeset
454 separator,
a069639783a0 rhg: Check .hg/requires for absence of required features
Simon Sapin <simon.sapin@octobus.net>
parents: 46640
diff changeset
455 }
a069639783a0 rhg: Check .hg/requires for absence of required features
Simon Sapin <simon.sapin@octobus.net>
parents: 46640
diff changeset
456 }
a069639783a0 rhg: Check .hg/requires for absence of required features
Simon Sapin <simon.sapin@octobus.net>
parents: 46640
diff changeset
457
a069639783a0 rhg: Check .hg/requires for absence of required features
Simon Sapin <simon.sapin@octobus.net>
parents: 46640
diff changeset
458 struct JoinDisplay<I, S> {
a069639783a0 rhg: Check .hg/requires for absence of required features
Simon Sapin <simon.sapin@octobus.net>
parents: 46640
diff changeset
459 iter: Cell<Option<I>>,
a069639783a0 rhg: Check .hg/requires for absence of required features
Simon Sapin <simon.sapin@octobus.net>
parents: 46640
diff changeset
460 separator: S,
a069639783a0 rhg: Check .hg/requires for absence of required features
Simon Sapin <simon.sapin@octobus.net>
parents: 46640
diff changeset
461 }
a069639783a0 rhg: Check .hg/requires for absence of required features
Simon Sapin <simon.sapin@octobus.net>
parents: 46640
diff changeset
462
a069639783a0 rhg: Check .hg/requires for absence of required features
Simon Sapin <simon.sapin@octobus.net>
parents: 46640
diff changeset
463 impl<I, T, S> fmt::Display for JoinDisplay<I, S>
a069639783a0 rhg: Check .hg/requires for absence of required features
Simon Sapin <simon.sapin@octobus.net>
parents: 46640
diff changeset
464 where
a069639783a0 rhg: Check .hg/requires for absence of required features
Simon Sapin <simon.sapin@octobus.net>
parents: 46640
diff changeset
465 I: Iterator<Item = T>,
a069639783a0 rhg: Check .hg/requires for absence of required features
Simon Sapin <simon.sapin@octobus.net>
parents: 46640
diff changeset
466 T: fmt::Display,
a069639783a0 rhg: Check .hg/requires for absence of required features
Simon Sapin <simon.sapin@octobus.net>
parents: 46640
diff changeset
467 S: fmt::Display,
a069639783a0 rhg: Check .hg/requires for absence of required features
Simon Sapin <simon.sapin@octobus.net>
parents: 46640
diff changeset
468 {
a069639783a0 rhg: Check .hg/requires for absence of required features
Simon Sapin <simon.sapin@octobus.net>
parents: 46640
diff changeset
469 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
a069639783a0 rhg: Check .hg/requires for absence of required features
Simon Sapin <simon.sapin@octobus.net>
parents: 46640
diff changeset
470 if let Some(mut iter) = self.iter.take() {
a069639783a0 rhg: Check .hg/requires for absence of required features
Simon Sapin <simon.sapin@octobus.net>
parents: 46640
diff changeset
471 if let Some(first) = iter.next() {
a069639783a0 rhg: Check .hg/requires for absence of required features
Simon Sapin <simon.sapin@octobus.net>
parents: 46640
diff changeset
472 first.fmt(f)?;
a069639783a0 rhg: Check .hg/requires for absence of required features
Simon Sapin <simon.sapin@octobus.net>
parents: 46640
diff changeset
473 }
a069639783a0 rhg: Check .hg/requires for absence of required features
Simon Sapin <simon.sapin@octobus.net>
parents: 46640
diff changeset
474 for value in iter {
a069639783a0 rhg: Check .hg/requires for absence of required features
Simon Sapin <simon.sapin@octobus.net>
parents: 46640
diff changeset
475 self.separator.fmt(f)?;
a069639783a0 rhg: Check .hg/requires for absence of required features
Simon Sapin <simon.sapin@octobus.net>
parents: 46640
diff changeset
476 value.fmt(f)?;
a069639783a0 rhg: Check .hg/requires for absence of required features
Simon Sapin <simon.sapin@octobus.net>
parents: 46640
diff changeset
477 }
a069639783a0 rhg: Check .hg/requires for absence of required features
Simon Sapin <simon.sapin@octobus.net>
parents: 46640
diff changeset
478 }
a069639783a0 rhg: Check .hg/requires for absence of required features
Simon Sapin <simon.sapin@octobus.net>
parents: 46640
diff changeset
479 Ok(())
a069639783a0 rhg: Check .hg/requires for absence of required features
Simon Sapin <simon.sapin@octobus.net>
parents: 46640
diff changeset
480 }
a069639783a0 rhg: Check .hg/requires for absence of required features
Simon Sapin <simon.sapin@octobus.net>
parents: 46640
diff changeset
481 }
50035
f5b168979626 rust: move `filter_map_results` to public util
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50007
diff changeset
482
f5b168979626 rust: move `filter_map_results` to public util
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50007
diff changeset
483 /// Like `Iterator::filter_map`, but over a fallible iterator of `Result`s.
f5b168979626 rust: move `filter_map_results` to public util
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50007
diff changeset
484 ///
f5b168979626 rust: move `filter_map_results` to public util
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50007
diff changeset
485 /// The callback is only called for incoming `Ok` values. Errors are passed
f5b168979626 rust: move `filter_map_results` to public util
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50007
diff changeset
486 /// through as-is. In order to let it use the `?` operator the callback is
f5b168979626 rust: move `filter_map_results` to public util
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50007
diff changeset
487 /// expected to return a `Result` of `Option`, instead of an `Option` of
f5b168979626 rust: move `filter_map_results` to public util
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50007
diff changeset
488 /// `Result`.
f5b168979626 rust: move `filter_map_results` to public util
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50007
diff changeset
489 pub fn filter_map_results<'a, I, F, A, B, E>(
f5b168979626 rust: move `filter_map_results` to public util
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50007
diff changeset
490 iter: I,
f5b168979626 rust: move `filter_map_results` to public util
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50007
diff changeset
491 f: F,
f5b168979626 rust: move `filter_map_results` to public util
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50007
diff changeset
492 ) -> impl Iterator<Item = Result<B, E>> + 'a
f5b168979626 rust: move `filter_map_results` to public util
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50007
diff changeset
493 where
f5b168979626 rust: move `filter_map_results` to public util
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50007
diff changeset
494 I: Iterator<Item = Result<A, E>> + 'a,
f5b168979626 rust: move `filter_map_results` to public util
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50007
diff changeset
495 F: Fn(A) -> Result<Option<B>, E> + 'a,
f5b168979626 rust: move `filter_map_results` to public util
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50007
diff changeset
496 {
f5b168979626 rust: move `filter_map_results` to public util
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50007
diff changeset
497 iter.filter_map(move |result| match result {
f5b168979626 rust: move `filter_map_results` to public util
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50007
diff changeset
498 Ok(node) => f(node).transpose(),
f5b168979626 rust: move `filter_map_results` to public util
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50007
diff changeset
499 Err(e) => Some(Err(e)),
f5b168979626 rust: move `filter_map_results` to public util
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50007
diff changeset
500 })
f5b168979626 rust: move `filter_map_results` to public util
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50007
diff changeset
501 }
50321
14b57943ae6d rust: fix thread cap (for real this time)
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50252
diff changeset
502
51189
aba622c7dc7e rust: add a utility function to merge ordered fallible iterators
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 50449
diff changeset
503 /// Like `itertools::merge_join_by`, but merges fallible iterators.
aba622c7dc7e rust: add a utility function to merge ordered fallible iterators
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 50449
diff changeset
504 ///
aba622c7dc7e rust: add a utility function to merge ordered fallible iterators
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 50449
diff changeset
505 /// The callback is only used for Ok values. Errors are passed through as-is.
aba622c7dc7e rust: add a utility function to merge ordered fallible iterators
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 50449
diff changeset
506 /// Errors compare less than Ok values, which makes the error handling
aba622c7dc7e rust: add a utility function to merge ordered fallible iterators
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 50449
diff changeset
507 /// conservative.
aba622c7dc7e rust: add a utility function to merge ordered fallible iterators
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 50449
diff changeset
508 pub fn merge_join_results_by<'a, I1, I2, F, A, B, E>(
aba622c7dc7e rust: add a utility function to merge ordered fallible iterators
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 50449
diff changeset
509 iter1: I1,
aba622c7dc7e rust: add a utility function to merge ordered fallible iterators
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 50449
diff changeset
510 iter2: I2,
aba622c7dc7e rust: add a utility function to merge ordered fallible iterators
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 50449
diff changeset
511 f: F,
aba622c7dc7e rust: add a utility function to merge ordered fallible iterators
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 50449
diff changeset
512 ) -> impl Iterator<Item = Result<EitherOrBoth<A, B>, E>> + 'a
aba622c7dc7e rust: add a utility function to merge ordered fallible iterators
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 50449
diff changeset
513 where
aba622c7dc7e rust: add a utility function to merge ordered fallible iterators
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 50449
diff changeset
514 I1: Iterator<Item = Result<A, E>> + 'a,
aba622c7dc7e rust: add a utility function to merge ordered fallible iterators
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 50449
diff changeset
515 I2: Iterator<Item = Result<B, E>> + 'a,
aba622c7dc7e rust: add a utility function to merge ordered fallible iterators
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 50449
diff changeset
516 F: FnMut(&A, &B) -> Ordering + 'a,
aba622c7dc7e rust: add a utility function to merge ordered fallible iterators
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 50449
diff changeset
517 {
aba622c7dc7e rust: add a utility function to merge ordered fallible iterators
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 50449
diff changeset
518 let mut g = f;
aba622c7dc7e rust: add a utility function to merge ordered fallible iterators
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 50449
diff changeset
519 iter1
aba622c7dc7e rust: add a utility function to merge ordered fallible iterators
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 50449
diff changeset
520 .merge_join_by(iter2, move |i1, i2| match i1 {
aba622c7dc7e rust: add a utility function to merge ordered fallible iterators
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 50449
diff changeset
521 Err(_) => Ordering::Less,
aba622c7dc7e rust: add a utility function to merge ordered fallible iterators
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 50449
diff changeset
522 Ok(i1) => match i2 {
aba622c7dc7e rust: add a utility function to merge ordered fallible iterators
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 50449
diff changeset
523 Err(_) => Ordering::Greater,
aba622c7dc7e rust: add a utility function to merge ordered fallible iterators
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 50449
diff changeset
524 Ok(i2) => g(i1, i2),
aba622c7dc7e rust: add a utility function to merge ordered fallible iterators
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 50449
diff changeset
525 },
aba622c7dc7e rust: add a utility function to merge ordered fallible iterators
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 50449
diff changeset
526 })
aba622c7dc7e rust: add a utility function to merge ordered fallible iterators
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 50449
diff changeset
527 .map(|result| match result {
aba622c7dc7e rust: add a utility function to merge ordered fallible iterators
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 50449
diff changeset
528 EitherOrBoth::Left(Err(e)) => Err(e),
aba622c7dc7e rust: add a utility function to merge ordered fallible iterators
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 50449
diff changeset
529 EitherOrBoth::Right(Err(e)) => Err(e),
aba622c7dc7e rust: add a utility function to merge ordered fallible iterators
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 50449
diff changeset
530 EitherOrBoth::Both(Err(e), _) => Err(e),
aba622c7dc7e rust: add a utility function to merge ordered fallible iterators
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 50449
diff changeset
531 EitherOrBoth::Both(_, Err(e)) => Err(e),
aba622c7dc7e rust: add a utility function to merge ordered fallible iterators
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 50449
diff changeset
532 EitherOrBoth::Left(Ok(v)) => Ok(EitherOrBoth::Left(v)),
aba622c7dc7e rust: add a utility function to merge ordered fallible iterators
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 50449
diff changeset
533 EitherOrBoth::Right(Ok(v)) => Ok(EitherOrBoth::Right(v)),
aba622c7dc7e rust: add a utility function to merge ordered fallible iterators
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 50449
diff changeset
534 EitherOrBoth::Both(Ok(v1), Ok(v2)) => {
aba622c7dc7e rust: add a utility function to merge ordered fallible iterators
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 50449
diff changeset
535 Ok(EitherOrBoth::Both(v1, v2))
aba622c7dc7e rust: add a utility function to merge ordered fallible iterators
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 50449
diff changeset
536 }
aba622c7dc7e rust: add a utility function to merge ordered fallible iterators
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 50449
diff changeset
537 })
aba622c7dc7e rust: add a utility function to merge ordered fallible iterators
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 50449
diff changeset
538 }
aba622c7dc7e rust: add a utility function to merge ordered fallible iterators
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 50449
diff changeset
539
50321
14b57943ae6d rust: fix thread cap (for real this time)
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50252
diff changeset
540 /// Force the global rayon threadpool to not exceed 16 concurrent threads
14b57943ae6d rust: fix thread cap (for real this time)
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50252
diff changeset
541 /// unless the user has specified a value.
14b57943ae6d rust: fix thread cap (for real this time)
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50252
diff changeset
542 /// This is a stop-gap measure until we figure out why using more than 16
52156
e6a44bc91bc2 rust-update: make `update_from_null` respect `worker.numcpu` config option
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51189
diff changeset
543 /// threads makes `status` and `update` slower for each additional thread.
50321
14b57943ae6d rust: fix thread cap (for real this time)
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50252
diff changeset
544 ///
14b57943ae6d rust: fix thread cap (for real this time)
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50252
diff changeset
545 /// TODO find the underlying cause and fix it, then remove this.
14b57943ae6d rust: fix thread cap (for real this time)
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50252
diff changeset
546 ///
14b57943ae6d rust: fix thread cap (for real this time)
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50252
diff changeset
547 /// # Errors
14b57943ae6d rust: fix thread cap (for real this time)
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50252
diff changeset
548 ///
14b57943ae6d rust: fix thread cap (for real this time)
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50252
diff changeset
549 /// Returns an error if the global threadpool has already been initialized if
14b57943ae6d rust: fix thread cap (for real this time)
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50252
diff changeset
550 /// we try to initialize it.
14b57943ae6d rust: fix thread cap (for real this time)
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50252
diff changeset
551 pub fn cap_default_rayon_threads() -> Result<(), rayon::ThreadPoolBuildError> {
14b57943ae6d rust: fix thread cap (for real this time)
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50252
diff changeset
552 const THREAD_CAP: usize = 16;
14b57943ae6d rust: fix thread cap (for real this time)
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50252
diff changeset
553
14b57943ae6d rust: fix thread cap (for real this time)
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50252
diff changeset
554 if std::env::var("RAYON_NUM_THREADS").is_err() {
14b57943ae6d rust: fix thread cap (for real this time)
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50252
diff changeset
555 let available_parallelism = std::thread::available_parallelism()
14b57943ae6d rust: fix thread cap (for real this time)
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50252
diff changeset
556 .map(usize::from)
14b57943ae6d rust: fix thread cap (for real this time)
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50252
diff changeset
557 .unwrap_or(1);
14b57943ae6d rust: fix thread cap (for real this time)
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50252
diff changeset
558 let new_thread_count = THREAD_CAP.min(available_parallelism);
14b57943ae6d rust: fix thread cap (for real this time)
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50252
diff changeset
559 let res = rayon::ThreadPoolBuilder::new()
14b57943ae6d rust: fix thread cap (for real this time)
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50252
diff changeset
560 .num_threads(new_thread_count)
14b57943ae6d rust: fix thread cap (for real this time)
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50252
diff changeset
561 .build_global();
14b57943ae6d rust: fix thread cap (for real this time)
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50252
diff changeset
562 if res.is_ok() {
14b57943ae6d rust: fix thread cap (for real this time)
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50252
diff changeset
563 log::trace!(
14b57943ae6d rust: fix thread cap (for real this time)
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50252
diff changeset
564 "Capped the rayon threadpool to {new_thread_count} threads",
14b57943ae6d rust: fix thread cap (for real this time)
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50252
diff changeset
565 );
14b57943ae6d rust: fix thread cap (for real this time)
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50252
diff changeset
566 }
14b57943ae6d rust: fix thread cap (for real this time)
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50252
diff changeset
567 return res;
14b57943ae6d rust: fix thread cap (for real this time)
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50252
diff changeset
568 }
14b57943ae6d rust: fix thread cap (for real this time)
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50252
diff changeset
569 Ok(())
14b57943ae6d rust: fix thread cap (for real this time)
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50252
diff changeset
570 }