rust/hg-core/src/utils.rs
author Rapha?l Gom?s <rgomes@octobus.net>
Tue, 05 Nov 2024 15:21:09 +0100
branchstable
changeset 52186 e6a44bc91bc2
parent 51151 aba622c7dc7e
child 52280 f4aede0f01af
permissions -rw-r--r--
rust-update: make `update_from_null` respect `worker.numcpu` config option This was overlooked in the original series. This is important for tests (because we run many at once), and for the occasional end user that wants to keep their CPU usage in check. A future series should clean up this `worker` parameter tunelling business by rewriting the config in Rust, but doing so on stable would be a very bad idea.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
42751
4b3b27d567d5 rust-docstrings: add missing module docstrings
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42748
diff changeset
     1
// utils module
4b3b27d567d5 rust-docstrings: add missing module docstrings
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42748
diff changeset
     2
//
4b3b27d567d5 rust-docstrings: add missing module docstrings
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42748
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: 42748
diff changeset
     4
//
4b3b27d567d5 rust-docstrings: add missing module docstrings
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42748
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: 42748
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: 42748
diff changeset
     7
4b3b27d567d5 rust-docstrings: add missing module docstrings
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42748
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: 42748
diff changeset
     9
46445
ca3f73cc3cf4 rhg: Simplify CommandError based on its use
Simon Sapin <simon.sapin@octobus.net>
parents: 46090
diff changeset
    10
use crate::errors::{HgError, IoErrorContext};
44268
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44265
diff changeset
    11
use crate::utils::hg_path::HgPath;
46586
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46505
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: 46505
diff changeset
    13
use im_rc::ordmap::OrdMap;
51151
aba622c7dc7e rust: add a utility function to merge ordered fallible iterators
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 50412
diff changeset
    14
use itertools::EitherOrBoth;
aba622c7dc7e rust: add a utility function to merge ordered fallible iterators
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 50412
diff changeset
    15
use itertools::Itertools;
46614
a069639783a0 rhg: Check .hg/requires for absence of required features
Simon Sapin <simon.sapin@octobus.net>
parents: 46601
diff changeset
    16
use std::cell::Cell;
51151
aba622c7dc7e rust: add a utility function to merge ordered fallible iterators
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 50412
diff changeset
    17
use std::cmp::Ordering;
46614
a069639783a0 rhg: Check .hg/requires for absence of required features
Simon Sapin <simon.sapin@octobus.net>
parents: 46601
diff changeset
    18
use std::fmt;
44268
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44265
diff changeset
    19
use std::{io::Write, ops::Deref};
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44265
diff changeset
    20
50214
8e0d823ef182 testing: introduce util function to synchronize concurrent commands on files
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48417
diff changeset
    21
pub mod debug;
42437
9609430d3625 rust-filepatterns: use bytes instead of String
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    22
pub mod files;
42956
3fe40dd6355d rust-hgpath: add HgPath and HgPathBuf structs to encapsulate handling of paths
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42863
diff changeset
    23
pub mod hg_path;
44265
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;
42437
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: 42956
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: 42956
diff changeset
    27
///
191a461d6be6 rust-utils: add util to find a slice in another slice
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42956
diff changeset
    28
/// # Examples
191a461d6be6 rust-utils: add util to find a slice in another slice
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42956
diff changeset
    29
///
191a461d6be6 rust-utils: add util to find a slice in another slice
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42956
diff changeset
    30
/// ```
191a461d6be6 rust-utils: add util to find a slice in another slice
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42956
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: 42956
diff changeset
    32
///
191a461d6be6 rust-utils: add util to find a slice in another slice
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42956
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: 42956
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: 42956
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: 42956
diff changeset
    36
/// ```
191a461d6be6 rust-utils: add util to find a slice in another slice
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42956
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: 42956
diff changeset
    38
where
191a461d6be6 rust-utils: add util to find a slice in another slice
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42956
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: 42956
diff changeset
    40
{
191a461d6be6 rust-utils: add util to find a slice in another slice
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42956
diff changeset
    41
    slice
191a461d6be6 rust-utils: add util to find a slice in another slice
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42956
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: 42956
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: 42956
diff changeset
    44
}
191a461d6be6 rust-utils: add util to find a slice in another slice
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42956
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()
42841
ce6797ef6eab rust: apply more formatting fixes
Yuya Nishihara <yuya@tcha.org>
parents: 42799
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
/// ```
42437
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() {
42437
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;
47949
696abab107b4 rust: Generalize the `trim_end_newlines` utility of byte strings
Simon Sapin <simon.sapin@octobus.net>
parents: 46742
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: 46742
diff changeset
    77
    fn trim_start_matches(&self, f: impl FnMut(u8) -> bool) -> &Self;
42437
9609430d3625 rust-filepatterns: use bytes instead of String
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    78
    fn trim(&self) -> &Self;
42863
62eabdf91f85 rustfilepatterns: refactor the pattern of removing a prefix from a &[u8]
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 42841
diff changeset
    79
    fn drop_prefix(&self, needle: &Self) -> Option<&Self>;
46505
a25033eb43b5 rhg: add limited support for the `config` sub-command
Simon Sapin <simon.sapin@octobus.net>
parents: 46483
diff changeset
    80
    fn split_2(&self, separator: u8) -> Option<(&[u8], &[u8])>;
47961
4d2a5ca060e3 rust: Add a Filelog struct that wraps Revlog
Simon Sapin <simon.sapin@octobus.net>
parents: 47949
diff changeset
    81
    fn split_2_by_slice(&self, separator: &[u8]) -> Option<(&[u8], &[u8])>;
42437
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
47949
696abab107b4 rust: Generalize the `trim_end_newlines` utility of byte strings
Simon Sapin <simon.sapin@octobus.net>
parents: 46742
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: 46742
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: 46742
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: 46742
diff changeset
    87
    }
42437
9609430d3625 rust-filepatterns: use bytes instead of String
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    88
47949
696abab107b4 rust: Generalize the `trim_end_newlines` utility of byte strings
Simon Sapin <simon.sapin@octobus.net>
parents: 46742
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: 46742
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: 46742
diff changeset
    91
    }
696abab107b4 rust: Generalize the `trim_end_newlines` utility of byte strings
Simon Sapin <simon.sapin@octobus.net>
parents: 46742
diff changeset
    92
696abab107b4 rust: Generalize the `trim_end_newlines` utility of byte strings
Simon Sapin <simon.sapin@octobus.net>
parents: 46742
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: 46742
diff changeset
    94
        if let Some(last) = self.iter().rposition(|&byte| !f(byte)) {
46669
e8cd519a0a34 rhg: Ignore trailing newlines in .hg/sharedpath
Simon Sapin <simon.sapin@octobus.net>
parents: 46614
diff changeset
    95
            &self[..=last]
e8cd519a0a34 rhg: Ignore trailing newlines in .hg/sharedpath
Simon Sapin <simon.sapin@octobus.net>
parents: 46614
diff changeset
    96
        } else {
e8cd519a0a34 rhg: Ignore trailing newlines in .hg/sharedpath
Simon Sapin <simon.sapin@octobus.net>
parents: 46614
diff changeset
    97
            &[]
e8cd519a0a34 rhg: Ignore trailing newlines in .hg/sharedpath
Simon Sapin <simon.sapin@octobus.net>
parents: 46614
diff changeset
    98
        }
e8cd519a0a34 rhg: Ignore trailing newlines in .hg/sharedpath
Simon Sapin <simon.sapin@octobus.net>
parents: 46614
diff changeset
    99
    }
47949
696abab107b4 rust: Generalize the `trim_end_newlines` utility of byte strings
Simon Sapin <simon.sapin@octobus.net>
parents: 46742
diff changeset
   100
696abab107b4 rust: Generalize the `trim_end_newlines` utility of byte strings
Simon Sapin <simon.sapin@octobus.net>
parents: 46742
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: 46742
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
    }
42863
62eabdf91f85 rustfilepatterns: refactor the pattern of removing a prefix from a &[u8]
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 42841
diff changeset
   127
62eabdf91f85 rustfilepatterns: refactor the pattern of removing a prefix from a &[u8]
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 42841
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: 42841
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: 42841
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: 42841
diff changeset
   131
        } else {
62eabdf91f85 rustfilepatterns: refactor the pattern of removing a prefix from a &[u8]
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 42841
diff changeset
   132
            None
62eabdf91f85 rustfilepatterns: refactor the pattern of removing a prefix from a &[u8]
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 42841
diff changeset
   133
        }
62eabdf91f85 rustfilepatterns: refactor the pattern of removing a prefix from a &[u8]
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 42841
diff changeset
   134
    }
46505
a25033eb43b5 rhg: add limited support for the `config` sub-command
Simon Sapin <simon.sapin@octobus.net>
parents: 46483
diff changeset
   135
a25033eb43b5 rhg: add limited support for the `config` sub-command
Simon Sapin <simon.sapin@octobus.net>
parents: 46483
diff changeset
   136
    fn split_2(&self, separator: u8) -> Option<(&[u8], &[u8])> {
a25033eb43b5 rhg: add limited support for the `config` sub-command
Simon Sapin <simon.sapin@octobus.net>
parents: 46483
diff changeset
   137
        let mut iter = self.splitn(2, |&byte| byte == separator);
a25033eb43b5 rhg: add limited support for the `config` sub-command
Simon Sapin <simon.sapin@octobus.net>
parents: 46483
diff changeset
   138
        let a = iter.next()?;
a25033eb43b5 rhg: add limited support for the `config` sub-command
Simon Sapin <simon.sapin@octobus.net>
parents: 46483
diff changeset
   139
        let b = iter.next()?;
a25033eb43b5 rhg: add limited support for the `config` sub-command
Simon Sapin <simon.sapin@octobus.net>
parents: 46483
diff changeset
   140
        Some((a, b))
a25033eb43b5 rhg: add limited support for the `config` sub-command
Simon Sapin <simon.sapin@octobus.net>
parents: 46483
diff changeset
   141
    }
47961
4d2a5ca060e3 rust: Add a Filelog struct that wraps Revlog
Simon Sapin <simon.sapin@octobus.net>
parents: 47949
diff changeset
   142
4d2a5ca060e3 rust: Add a Filelog struct that wraps Revlog
Simon Sapin <simon.sapin@octobus.net>
parents: 47949
diff changeset
   143
    fn split_2_by_slice(&self, separator: &[u8]) -> Option<(&[u8], &[u8])> {
49930
e98fd81bb151 rust-clippy: fix most warnings in `hg-core`
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49929
diff changeset
   144
        find_slice_in_slice(self, separator)
e98fd81bb151 rust-clippy: fix most warnings in `hg-core`
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49929
diff changeset
   145
            .map(|pos| (&self[..pos], &self[pos + separator.len()..]))
48417
5734b03ecf3e rhg: Initial repository locking
Simon Sapin <simon.sapin@octobus.net>
parents: 47961
diff changeset
   146
    }
5734b03ecf3e rhg: Initial repository locking
Simon Sapin <simon.sapin@octobus.net>
parents: 47961
diff changeset
   147
}
5734b03ecf3e rhg: Initial repository locking
Simon Sapin <simon.sapin@octobus.net>
parents: 47961
diff changeset
   148
44268
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44265
diff changeset
   149
pub trait Escaped {
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44265
diff changeset
   150
    /// Return bytes escaped for display to the user
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44265
diff changeset
   151
    fn escaped_bytes(&self) -> Vec<u8>;
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44265
diff changeset
   152
}
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44265
diff changeset
   153
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44265
diff changeset
   154
impl Escaped for u8 {
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44265
diff changeset
   155
    fn escaped_bytes(&self) -> Vec<u8> {
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44265
diff changeset
   156
        let mut acc = vec![];
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44265
diff changeset
   157
        match self {
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44265
diff changeset
   158
            c @ b'\'' | c @ b'\\' => {
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44265
diff changeset
   159
                acc.push(b'\\');
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44265
diff changeset
   160
                acc.push(*c);
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44265
diff changeset
   161
            }
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44265
diff changeset
   162
            b'\t' => {
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44265
diff changeset
   163
                acc.extend(br"\\t");
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44265
diff changeset
   164
            }
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44265
diff changeset
   165
            b'\n' => {
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44265
diff changeset
   166
                acc.extend(br"\\n");
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44265
diff changeset
   167
            }
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44265
diff changeset
   168
            b'\r' => {
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44265
diff changeset
   169
                acc.extend(br"\\r");
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44265
diff changeset
   170
            }
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44265
diff changeset
   171
            c if (*c < b' ' || *c >= 127) => {
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44265
diff changeset
   172
                write!(acc, "\\x{:x}", self).unwrap();
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44265
diff changeset
   173
            }
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44265
diff changeset
   174
            c => {
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44265
diff changeset
   175
                acc.push(*c);
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44265
diff changeset
   176
            }
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44265
diff changeset
   177
        }
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44265
diff changeset
   178
        acc
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44265
diff changeset
   179
    }
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44265
diff changeset
   180
}
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44265
diff changeset
   181
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44265
diff changeset
   182
impl<'a, T: Escaped> Escaped for &'a [T] {
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44265
diff changeset
   183
    fn escaped_bytes(&self) -> Vec<u8> {
44973
26114bd6ec60 rust: do a clippy pass
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44268
diff changeset
   184
        self.iter().flat_map(Escaped::escaped_bytes).collect()
44268
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44265
diff changeset
   185
    }
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44265
diff changeset
   186
}
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44265
diff changeset
   187
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44265
diff changeset
   188
impl<T: Escaped> Escaped for Vec<T> {
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44265
diff changeset
   189
    fn escaped_bytes(&self) -> Vec<u8> {
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44265
diff changeset
   190
        self.deref().escaped_bytes()
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44265
diff changeset
   191
    }
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44265
diff changeset
   192
}
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44265
diff changeset
   193
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44265
diff changeset
   194
impl<'a> Escaped for &'a HgPath {
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44265
diff changeset
   195
    fn escaped_bytes(&self) -> Vec<u8> {
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44265
diff changeset
   196
        self.as_bytes().escaped_bytes()
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44265
diff changeset
   197
    }
aa0fc32ece9e rust-utils: add `Escaped` trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44265
diff changeset
   198
}
46090
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents: 44973
diff changeset
   199
46601
755c31a1caf9 rhg: Add support for the blackbox extension
Simon Sapin <simon.sapin@octobus.net>
parents: 46586
diff changeset
   200
#[cfg(unix)]
755c31a1caf9 rhg: Add support for the blackbox extension
Simon Sapin <simon.sapin@octobus.net>
parents: 46586
diff changeset
   201
pub fn shell_quote(value: &[u8]) -> Vec<u8> {
49634
ec399ddf6764 rust: use `matches!` macro now that we're using Rust 1.42+
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49633
diff changeset
   202
    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: 49633
diff changeset
   203
        matches!(
ec399ddf6764 rust: use `matches!` macro now that we're using Rust 1.42+
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49633
diff changeset
   204
            byte,
ec399ddf6764 rust: use `matches!` macro now that we're using Rust 1.42+
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49633
diff changeset
   205
            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: 49633
diff changeset
   206
            | 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: 49633
diff changeset
   207
            | 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: 49633
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: 49633
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: 49633
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: 49633
diff changeset
   211
            | b'+'
ec399ddf6764 rust: use `matches!` macro now that we're using Rust 1.42+
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49633
diff changeset
   212
            | b'-'
ec399ddf6764 rust: use `matches!` macro now that we're using Rust 1.42+
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49633
diff changeset
   213
        )
46601
755c31a1caf9 rhg: Add support for the blackbox extension
Simon Sapin <simon.sapin@octobus.net>
parents: 46586
diff changeset
   214
    }) {
755c31a1caf9 rhg: Add support for the blackbox extension
Simon Sapin <simon.sapin@octobus.net>
parents: 46586
diff changeset
   215
        value.to_owned()
755c31a1caf9 rhg: Add support for the blackbox extension
Simon Sapin <simon.sapin@octobus.net>
parents: 46586
diff changeset
   216
    } else {
755c31a1caf9 rhg: Add support for the blackbox extension
Simon Sapin <simon.sapin@octobus.net>
parents: 46586
diff changeset
   217
        let mut quoted = Vec::with_capacity(value.len() + 2);
755c31a1caf9 rhg: Add support for the blackbox extension
Simon Sapin <simon.sapin@octobus.net>
parents: 46586
diff changeset
   218
        quoted.push(b'\'');
755c31a1caf9 rhg: Add support for the blackbox extension
Simon Sapin <simon.sapin@octobus.net>
parents: 46586
diff changeset
   219
        for &byte in value {
755c31a1caf9 rhg: Add support for the blackbox extension
Simon Sapin <simon.sapin@octobus.net>
parents: 46586
diff changeset
   220
            if byte == b'\'' {
755c31a1caf9 rhg: Add support for the blackbox extension
Simon Sapin <simon.sapin@octobus.net>
parents: 46586
diff changeset
   221
                quoted.push(b'\\');
755c31a1caf9 rhg: Add support for the blackbox extension
Simon Sapin <simon.sapin@octobus.net>
parents: 46586
diff changeset
   222
            }
755c31a1caf9 rhg: Add support for the blackbox extension
Simon Sapin <simon.sapin@octobus.net>
parents: 46586
diff changeset
   223
            quoted.push(byte);
755c31a1caf9 rhg: Add support for the blackbox extension
Simon Sapin <simon.sapin@octobus.net>
parents: 46586
diff changeset
   224
        }
755c31a1caf9 rhg: Add support for the blackbox extension
Simon Sapin <simon.sapin@octobus.net>
parents: 46586
diff changeset
   225
        quoted.push(b'\'');
755c31a1caf9 rhg: Add support for the blackbox extension
Simon Sapin <simon.sapin@octobus.net>
parents: 46586
diff changeset
   226
        quoted
755c31a1caf9 rhg: Add support for the blackbox extension
Simon Sapin <simon.sapin@octobus.net>
parents: 46586
diff changeset
   227
    }
755c31a1caf9 rhg: Add support for the blackbox extension
Simon Sapin <simon.sapin@octobus.net>
parents: 46586
diff changeset
   228
}
755c31a1caf9 rhg: Add support for the blackbox extension
Simon Sapin <simon.sapin@octobus.net>
parents: 46586
diff changeset
   229
46445
ca3f73cc3cf4 rhg: Simplify CommandError based on its use
Simon Sapin <simon.sapin@octobus.net>
parents: 46090
diff changeset
   230
pub fn current_dir() -> Result<std::path::PathBuf, HgError> {
ca3f73cc3cf4 rhg: Simplify CommandError based on its use
Simon Sapin <simon.sapin@octobus.net>
parents: 46090
diff changeset
   231
    std::env::current_dir().map_err(|error| HgError::IoError {
ca3f73cc3cf4 rhg: Simplify CommandError based on its use
Simon Sapin <simon.sapin@octobus.net>
parents: 46090
diff changeset
   232
        error,
ca3f73cc3cf4 rhg: Simplify CommandError based on its use
Simon Sapin <simon.sapin@octobus.net>
parents: 46090
diff changeset
   233
        context: IoErrorContext::CurrentDir,
ca3f73cc3cf4 rhg: Simplify CommandError based on its use
Simon Sapin <simon.sapin@octobus.net>
parents: 46090
diff changeset
   234
    })
ca3f73cc3cf4 rhg: Simplify CommandError based on its use
Simon Sapin <simon.sapin@octobus.net>
parents: 46090
diff changeset
   235
}
46483
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46445
diff changeset
   236
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46445
diff changeset
   237
pub fn current_exe() -> Result<std::path::PathBuf, HgError> {
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46445
diff changeset
   238
    std::env::current_exe().map_err(|error| HgError::IoError {
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46445
diff changeset
   239
        error,
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46445
diff changeset
   240
        context: IoErrorContext::CurrentExe,
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46445
diff changeset
   241
    })
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46445
diff changeset
   242
}
46586
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46505
diff changeset
   243
46742
91ab5190a3de rhg: Add support for environment variables in config include paths
Simon Sapin <simon.sapin@octobus.net>
parents: 46669
diff changeset
   244
/// 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: 46669
diff changeset
   245
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: 46669
diff changeset
   246
    lazy_static::lazy_static! {
91ab5190a3de rhg: Add support for environment variables in config include paths
Simon Sapin <simon.sapin@octobus.net>
parents: 46669
diff changeset
   247
        /// 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: 46669
diff changeset
   248
        /// The `x` makes whitespace ignored.
91ab5190a3de rhg: Add support for environment variables in config include paths
Simon Sapin <simon.sapin@octobus.net>
parents: 46669
diff changeset
   249
        /// `-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: 46669
diff changeset
   250
        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: 46669
diff changeset
   251
            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: 46669
diff changeset
   252
                \$
91ab5190a3de rhg: Add support for environment variables in config include paths
Simon Sapin <simon.sapin@octobus.net>
parents: 46669
diff changeset
   253
                (?:
91ab5190a3de rhg: Add support for environment variables in config include paths
Simon Sapin <simon.sapin@octobus.net>
parents: 46669
diff changeset
   254
                    (\w+)
91ab5190a3de rhg: Add support for environment variables in config include paths
Simon Sapin <simon.sapin@octobus.net>
parents: 46669
diff changeset
   255
                    |
91ab5190a3de rhg: Add support for environment variables in config include paths
Simon Sapin <simon.sapin@octobus.net>
parents: 46669
diff changeset
   256
                    \{
91ab5190a3de rhg: Add support for environment variables in config include paths
Simon Sapin <simon.sapin@octobus.net>
parents: 46669
diff changeset
   257
                        ([^}]*)
91ab5190a3de rhg: Add support for environment variables in config include paths
Simon Sapin <simon.sapin@octobus.net>
parents: 46669
diff changeset
   258
                    \}
91ab5190a3de rhg: Add support for environment variables in config include paths
Simon Sapin <simon.sapin@octobus.net>
parents: 46669
diff changeset
   259
                )
91ab5190a3de rhg: Add support for environment variables in config include paths
Simon Sapin <simon.sapin@octobus.net>
parents: 46669
diff changeset
   260
            ").unwrap();
91ab5190a3de rhg: Add support for environment variables in config include paths
Simon Sapin <simon.sapin@octobus.net>
parents: 46669
diff changeset
   261
    }
91ab5190a3de rhg: Add support for environment variables in config include paths
Simon Sapin <simon.sapin@octobus.net>
parents: 46669
diff changeset
   262
    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: 46669
diff changeset
   263
        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: 46669
diff changeset
   264
            captures
91ab5190a3de rhg: Add support for environment variables in config include paths
Simon Sapin <simon.sapin@octobus.net>
parents: 46669
diff changeset
   265
                .get(1)
91ab5190a3de rhg: Add support for environment variables in config include paths
Simon Sapin <simon.sapin@octobus.net>
parents: 46669
diff changeset
   266
                .or_else(|| captures.get(2))
91ab5190a3de rhg: Add support for environment variables in config include paths
Simon Sapin <simon.sapin@octobus.net>
parents: 46669
diff changeset
   267
                .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: 46669
diff changeset
   268
                .as_bytes(),
91ab5190a3de rhg: Add support for environment variables in config include paths
Simon Sapin <simon.sapin@octobus.net>
parents: 46669
diff changeset
   269
        );
91ab5190a3de rhg: Add support for environment variables in config include paths
Simon Sapin <simon.sapin@octobus.net>
parents: 46669
diff changeset
   270
        std::env::var_os(var_name)
91ab5190a3de rhg: Add support for environment variables in config include paths
Simon Sapin <simon.sapin@octobus.net>
parents: 46669
diff changeset
   271
            .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: 46669
diff changeset
   272
            .unwrap_or_else(|| {
91ab5190a3de rhg: Add support for environment variables in config include paths
Simon Sapin <simon.sapin@octobus.net>
parents: 46669
diff changeset
   273
                // 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: 46669
diff changeset
   274
                // Leave the $FOO reference as-is.
91ab5190a3de rhg: Add support for environment variables in config include paths
Simon Sapin <simon.sapin@octobus.net>
parents: 46669
diff changeset
   275
                captures[0].to_owned()
91ab5190a3de rhg: Add support for environment variables in config include paths
Simon Sapin <simon.sapin@octobus.net>
parents: 46669
diff changeset
   276
            })
91ab5190a3de rhg: Add support for environment variables in config include paths
Simon Sapin <simon.sapin@octobus.net>
parents: 46669
diff changeset
   277
    })
91ab5190a3de rhg: Add support for environment variables in config include paths
Simon Sapin <simon.sapin@octobus.net>
parents: 46669
diff changeset
   278
}
91ab5190a3de rhg: Add support for environment variables in config include paths
Simon Sapin <simon.sapin@octobus.net>
parents: 46669
diff changeset
   279
91ab5190a3de rhg: Add support for environment variables in config include paths
Simon Sapin <simon.sapin@octobus.net>
parents: 46669
diff changeset
   280
#[test]
91ab5190a3de rhg: Add support for environment variables in config include paths
Simon Sapin <simon.sapin@octobus.net>
parents: 46669
diff changeset
   281
fn test_expand_vars() {
91ab5190a3de rhg: Add support for environment variables in config include paths
Simon Sapin <simon.sapin@octobus.net>
parents: 46669
diff changeset
   282
    // 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: 46669
diff changeset
   283
    // 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: 46669
diff changeset
   284
    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: 46669
diff changeset
   285
    assert_eq!(
91ab5190a3de rhg: Add support for environment variables in config include paths
Simon Sapin <simon.sapin@octobus.net>
parents: 46669
diff changeset
   286
        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: 46669
diff changeset
   287
        &b"before/1/after"[..]
91ab5190a3de rhg: Add support for environment variables in config include paths
Simon Sapin <simon.sapin@octobus.net>
parents: 46669
diff changeset
   288
    );
91ab5190a3de rhg: Add support for environment variables in config include paths
Simon Sapin <simon.sapin@octobus.net>
parents: 46669
diff changeset
   289
    assert_eq!(
91ab5190a3de rhg: Add support for environment variables in config include paths
Simon Sapin <simon.sapin@octobus.net>
parents: 46669
diff changeset
   290
        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: 46669
diff changeset
   291
        &b"before111after"[..]
91ab5190a3de rhg: Add support for environment variables in config include paths
Simon Sapin <simon.sapin@octobus.net>
parents: 46669
diff changeset
   292
    );
91ab5190a3de rhg: Add support for environment variables in config include paths
Simon Sapin <simon.sapin@octobus.net>
parents: 46669
diff changeset
   293
    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: 46669
diff changeset
   294
    assert_eq!(expand_vars(s), &s[..]);
91ab5190a3de rhg: Add support for environment variables in config include paths
Simon Sapin <simon.sapin@octobus.net>
parents: 46669
diff changeset
   295
}
91ab5190a3de rhg: Add support for environment variables in config include paths
Simon Sapin <simon.sapin@octobus.net>
parents: 46669
diff changeset
   296
46586
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46505
diff changeset
   297
pub(crate) enum MergeResult<V> {
49934
83437ad8fe3d rust-clippy: remove redundant suffix from enum
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49930
diff changeset
   298
    Left,
83437ad8fe3d rust-clippy: remove redundant suffix from enum
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49930
diff changeset
   299
    Right,
83437ad8fe3d rust-clippy: remove redundant suffix from enum
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49930
diff changeset
   300
    New(V),
46586
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46505
diff changeset
   301
}
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46505
diff changeset
   302
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46505
diff changeset
   303
/// 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: 46505
diff changeset
   304
/// 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: 46505
diff changeset
   305
/// both.
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46505
diff changeset
   306
///
50412
331a3cbe1c9e rustdoc: fixed warnings about links
Georges Racinet <georges.racinet@octobus.net>
parents: 50321
diff changeset
   307
/// CC <https://github.com/bodil/im-rs/issues/166>
46586
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46505
diff changeset
   308
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: 46505
diff changeset
   309
    left: OrdMap<K, V>,
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46505
diff changeset
   310
    right: OrdMap<K, V>,
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46505
diff changeset
   311
    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: 46505
diff changeset
   312
) -> OrdMap<K, V>
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46505
diff changeset
   313
where
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46505
diff changeset
   314
    K: Clone + Ord,
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46505
diff changeset
   315
    V: Clone + PartialEq,
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46505
diff changeset
   316
{
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46505
diff changeset
   317
    if left.ptr_eq(&right) {
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46505
diff changeset
   318
        // 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: 46505
diff changeset
   319
        left
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46505
diff changeset
   320
    } 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: 46505
diff changeset
   321
        // 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: 46505
diff changeset
   322
        // 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: 46505
diff changeset
   323
        // 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: 46505
diff changeset
   324
        // 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: 46505
diff changeset
   325
        // `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: 46505
diff changeset
   326
        // 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: 46505
diff changeset
   327
        //
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46505
diff changeset
   328
        // 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: 46505
diff changeset
   329
        // 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: 46505
diff changeset
   330
        // `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: 46505
diff changeset
   331
        // is more efficient.
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46505
diff changeset
   332
        //
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46505
diff changeset
   333
        // 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: 46505
diff changeset
   334
        // with a large one.
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46505
diff changeset
   335
        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: 46505
diff changeset
   336
    } 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: 46505
diff changeset
   337
        // 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: 46505
diff changeset
   338
        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: 46505
diff changeset
   339
            // Also swapped in `merge` arguments:
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46505
diff changeset
   340
            match merge(key, b, a) {
49934
83437ad8fe3d rust-clippy: remove redundant suffix from enum
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49930
diff changeset
   341
                MergeResult::New(v) => MergeResult::New(v),
46586
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46505
diff changeset
   342
                // … and swap back in `merge` result:
49934
83437ad8fe3d rust-clippy: remove redundant suffix from enum
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49930
diff changeset
   343
                MergeResult::Left => MergeResult::Right,
83437ad8fe3d rust-clippy: remove redundant suffix from enum
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49930
diff changeset
   344
                MergeResult::Right => MergeResult::Left,
46586
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46505
diff changeset
   345
            }
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46505
diff changeset
   346
        })
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46505
diff changeset
   347
    } else {
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46505
diff changeset
   348
        // 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: 46505
diff changeset
   349
        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: 46505
diff changeset
   350
    }
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46505
diff changeset
   351
}
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46505
diff changeset
   352
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46505
diff changeset
   353
/// 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: 46505
diff changeset
   354
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: 46505
diff changeset
   355
    mut left: OrdMap<K, V>,
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46505
diff changeset
   356
    right: OrdMap<K, V>,
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46505
diff changeset
   357
    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: 46505
diff changeset
   358
) -> OrdMap<K, V>
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46505
diff changeset
   359
where
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46505
diff changeset
   360
    K: Clone + Ord,
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46505
diff changeset
   361
    V: Clone,
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46505
diff changeset
   362
{
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46505
diff changeset
   363
    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: 46505
diff changeset
   364
        match left.get(&key) {
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46505
diff changeset
   365
            None => {
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46505
diff changeset
   366
                left.insert(key, right_value);
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46505
diff changeset
   367
            }
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46505
diff changeset
   368
            Some(left_value) => match merge(&key, left_value, &right_value) {
49934
83437ad8fe3d rust-clippy: remove redundant suffix from enum
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49930
diff changeset
   369
                MergeResult::Left => {}
83437ad8fe3d rust-clippy: remove redundant suffix from enum
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49930
diff changeset
   370
                MergeResult::Right => {
46586
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46505
diff changeset
   371
                    left.insert(key, right_value);
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46505
diff changeset
   372
                }
49934
83437ad8fe3d rust-clippy: remove redundant suffix from enum
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49930
diff changeset
   373
                MergeResult::New(new_value) => {
46586
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46505
diff changeset
   374
                    left.insert(key, new_value);
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46505
diff changeset
   375
                }
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46505
diff changeset
   376
            },
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46505
diff changeset
   377
        }
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46505
diff changeset
   378
    }
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46505
diff changeset
   379
    left
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46505
diff changeset
   380
}
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46505
diff changeset
   381
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46505
diff changeset
   382
/// 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: 46505
diff changeset
   383
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: 46505
diff changeset
   384
    mut left: OrdMap<K, V>,
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46505
diff changeset
   385
    mut right: OrdMap<K, V>,
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46505
diff changeset
   386
    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: 46505
diff changeset
   387
) -> OrdMap<K, V>
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46505
diff changeset
   388
where
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46505
diff changeset
   389
    K: Clone + Ord,
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46505
diff changeset
   390
    V: Clone + PartialEq,
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46505
diff changeset
   391
{
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46505
diff changeset
   392
    // (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: 46505
diff changeset
   393
    // 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: 46505
diff changeset
   394
    //
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46505
diff changeset
   395
    // 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: 46505
diff changeset
   396
    // 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: 46505
diff changeset
   397
    // with `left_updates` only borrowing from `right` and `right_updates` from
49934
83437ad8fe3d rust-clippy: remove redundant suffix from enum
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49930
diff changeset
   398
    // `left`, and with `Cow::Owned` used for `MergeResult::New`.
46586
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46505
diff changeset
   399
    //
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46505
diff changeset
   400
    // 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: 46505
diff changeset
   401
    // 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: 46505
diff changeset
   402
    // (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: 46505
diff changeset
   403
    // 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: 46505
diff changeset
   404
    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: 46505
diff changeset
   405
    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: 46505
diff changeset
   406
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46505
diff changeset
   407
    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: 46505
diff changeset
   408
        match difference {
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46505
diff changeset
   409
            DiffItem::Add(key, value) => {
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46505
diff changeset
   410
                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: 46505
diff changeset
   411
            }
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46505
diff changeset
   412
            DiffItem::Remove(key, value) => {
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46505
diff changeset
   413
                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: 46505
diff changeset
   414
            }
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46505
diff changeset
   415
            DiffItem::Update {
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46505
diff changeset
   416
                old: (key, left_value),
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46505
diff changeset
   417
                new: (_, right_value),
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46505
diff changeset
   418
            } => match merge(key, left_value, right_value) {
49934
83437ad8fe3d rust-clippy: remove redundant suffix from enum
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49930
diff changeset
   419
                MergeResult::Left => {
46586
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46505
diff changeset
   420
                    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: 46505
diff changeset
   421
                }
49934
83437ad8fe3d rust-clippy: remove redundant suffix from enum
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49930
diff changeset
   422
                MergeResult::Right => {
46586
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46505
diff changeset
   423
                    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: 46505
diff changeset
   424
                }
49934
83437ad8fe3d rust-clippy: remove redundant suffix from enum
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49930
diff changeset
   425
                MergeResult::New(new_value) => {
46586
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46505
diff changeset
   426
                    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: 46505
diff changeset
   427
                    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: 46505
diff changeset
   428
                }
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46505
diff changeset
   429
            },
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46505
diff changeset
   430
        }
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46505
diff changeset
   431
    }
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46505
diff changeset
   432
    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: 46505
diff changeset
   433
        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: 46505
diff changeset
   434
            left.insert(key, value);
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46505
diff changeset
   435
        }
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46505
diff changeset
   436
        left
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46505
diff changeset
   437
    } else {
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46505
diff changeset
   438
        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: 46505
diff changeset
   439
            right.insert(key, value);
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46505
diff changeset
   440
        }
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46505
diff changeset
   441
        right
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46505
diff changeset
   442
    }
435d9fc72646 copies-rust: extract generic map merge logic from merge_copies_dict
Simon Sapin <simon.sapin@octobus.net>
parents: 46505
diff changeset
   443
}
46614
a069639783a0 rhg: Check .hg/requires for absence of required features
Simon Sapin <simon.sapin@octobus.net>
parents: 46601
diff changeset
   444
a069639783a0 rhg: Check .hg/requires for absence of required features
Simon Sapin <simon.sapin@octobus.net>
parents: 46601
diff changeset
   445
/// 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: 46601
diff changeset
   446
/// `separator.join(iter)`.
a069639783a0 rhg: Check .hg/requires for absence of required features
Simon Sapin <simon.sapin@octobus.net>
parents: 46601
diff changeset
   447
///
a069639783a0 rhg: Check .hg/requires for absence of required features
Simon Sapin <simon.sapin@octobus.net>
parents: 46601
diff changeset
   448
/// Formatting the return value consumes the iterator.
a069639783a0 rhg: Check .hg/requires for absence of required features
Simon Sapin <simon.sapin@octobus.net>
parents: 46601
diff changeset
   449
/// 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: 46601
diff changeset
   450
pub fn join_display(
a069639783a0 rhg: Check .hg/requires for absence of required features
Simon Sapin <simon.sapin@octobus.net>
parents: 46601
diff changeset
   451
    iter: impl IntoIterator<Item = impl fmt::Display>,
a069639783a0 rhg: Check .hg/requires for absence of required features
Simon Sapin <simon.sapin@octobus.net>
parents: 46601
diff changeset
   452
    separator: impl fmt::Display,
a069639783a0 rhg: Check .hg/requires for absence of required features
Simon Sapin <simon.sapin@octobus.net>
parents: 46601
diff changeset
   453
) -> impl fmt::Display {
a069639783a0 rhg: Check .hg/requires for absence of required features
Simon Sapin <simon.sapin@octobus.net>
parents: 46601
diff changeset
   454
    JoinDisplay {
a069639783a0 rhg: Check .hg/requires for absence of required features
Simon Sapin <simon.sapin@octobus.net>
parents: 46601
diff changeset
   455
        iter: Cell::new(Some(iter.into_iter())),
a069639783a0 rhg: Check .hg/requires for absence of required features
Simon Sapin <simon.sapin@octobus.net>
parents: 46601
diff changeset
   456
        separator,
a069639783a0 rhg: Check .hg/requires for absence of required features
Simon Sapin <simon.sapin@octobus.net>
parents: 46601
diff changeset
   457
    }
a069639783a0 rhg: Check .hg/requires for absence of required features
Simon Sapin <simon.sapin@octobus.net>
parents: 46601
diff changeset
   458
}
a069639783a0 rhg: Check .hg/requires for absence of required features
Simon Sapin <simon.sapin@octobus.net>
parents: 46601
diff changeset
   459
a069639783a0 rhg: Check .hg/requires for absence of required features
Simon Sapin <simon.sapin@octobus.net>
parents: 46601
diff changeset
   460
struct JoinDisplay<I, S> {
a069639783a0 rhg: Check .hg/requires for absence of required features
Simon Sapin <simon.sapin@octobus.net>
parents: 46601
diff changeset
   461
    iter: Cell<Option<I>>,
a069639783a0 rhg: Check .hg/requires for absence of required features
Simon Sapin <simon.sapin@octobus.net>
parents: 46601
diff changeset
   462
    separator: S,
a069639783a0 rhg: Check .hg/requires for absence of required features
Simon Sapin <simon.sapin@octobus.net>
parents: 46601
diff changeset
   463
}
a069639783a0 rhg: Check .hg/requires for absence of required features
Simon Sapin <simon.sapin@octobus.net>
parents: 46601
diff changeset
   464
a069639783a0 rhg: Check .hg/requires for absence of required features
Simon Sapin <simon.sapin@octobus.net>
parents: 46601
diff changeset
   465
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: 46601
diff changeset
   466
where
a069639783a0 rhg: Check .hg/requires for absence of required features
Simon Sapin <simon.sapin@octobus.net>
parents: 46601
diff changeset
   467
    I: Iterator<Item = T>,
a069639783a0 rhg: Check .hg/requires for absence of required features
Simon Sapin <simon.sapin@octobus.net>
parents: 46601
diff changeset
   468
    T: fmt::Display,
a069639783a0 rhg: Check .hg/requires for absence of required features
Simon Sapin <simon.sapin@octobus.net>
parents: 46601
diff changeset
   469
    S: fmt::Display,
a069639783a0 rhg: Check .hg/requires for absence of required features
Simon Sapin <simon.sapin@octobus.net>
parents: 46601
diff changeset
   470
{
a069639783a0 rhg: Check .hg/requires for absence of required features
Simon Sapin <simon.sapin@octobus.net>
parents: 46601
diff changeset
   471
    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: 46601
diff changeset
   472
        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: 46601
diff changeset
   473
            if let Some(first) = iter.next() {
a069639783a0 rhg: Check .hg/requires for absence of required features
Simon Sapin <simon.sapin@octobus.net>
parents: 46601
diff changeset
   474
                first.fmt(f)?;
a069639783a0 rhg: Check .hg/requires for absence of required features
Simon Sapin <simon.sapin@octobus.net>
parents: 46601
diff changeset
   475
            }
a069639783a0 rhg: Check .hg/requires for absence of required features
Simon Sapin <simon.sapin@octobus.net>
parents: 46601
diff changeset
   476
            for value in iter {
a069639783a0 rhg: Check .hg/requires for absence of required features
Simon Sapin <simon.sapin@octobus.net>
parents: 46601
diff changeset
   477
                self.separator.fmt(f)?;
a069639783a0 rhg: Check .hg/requires for absence of required features
Simon Sapin <simon.sapin@octobus.net>
parents: 46601
diff changeset
   478
                value.fmt(f)?;
a069639783a0 rhg: Check .hg/requires for absence of required features
Simon Sapin <simon.sapin@octobus.net>
parents: 46601
diff changeset
   479
            }
a069639783a0 rhg: Check .hg/requires for absence of required features
Simon Sapin <simon.sapin@octobus.net>
parents: 46601
diff changeset
   480
        }
a069639783a0 rhg: Check .hg/requires for absence of required features
Simon Sapin <simon.sapin@octobus.net>
parents: 46601
diff changeset
   481
        Ok(())
a069639783a0 rhg: Check .hg/requires for absence of required features
Simon Sapin <simon.sapin@octobus.net>
parents: 46601
diff changeset
   482
    }
a069639783a0 rhg: Check .hg/requires for absence of required features
Simon Sapin <simon.sapin@octobus.net>
parents: 46601
diff changeset
   483
}
49979
f5b168979626 rust: move `filter_map_results` to public util
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49934
diff changeset
   484
f5b168979626 rust: move `filter_map_results` to public util
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49934
diff changeset
   485
/// 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: 49934
diff changeset
   486
///
f5b168979626 rust: move `filter_map_results` to public util
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49934
diff changeset
   487
/// 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: 49934
diff changeset
   488
/// 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: 49934
diff changeset
   489
/// 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: 49934
diff changeset
   490
/// `Result`.
f5b168979626 rust: move `filter_map_results` to public util
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49934
diff changeset
   491
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: 49934
diff changeset
   492
    iter: I,
f5b168979626 rust: move `filter_map_results` to public util
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49934
diff changeset
   493
    f: F,
f5b168979626 rust: move `filter_map_results` to public util
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49934
diff changeset
   494
) -> impl Iterator<Item = Result<B, E>> + 'a
f5b168979626 rust: move `filter_map_results` to public util
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49934
diff changeset
   495
where
f5b168979626 rust: move `filter_map_results` to public util
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49934
diff changeset
   496
    I: Iterator<Item = Result<A, E>> + 'a,
f5b168979626 rust: move `filter_map_results` to public util
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49934
diff changeset
   497
    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: 49934
diff changeset
   498
{
f5b168979626 rust: move `filter_map_results` to public util
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49934
diff changeset
   499
    iter.filter_map(move |result| match result {
f5b168979626 rust: move `filter_map_results` to public util
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49934
diff changeset
   500
        Ok(node) => f(node).transpose(),
f5b168979626 rust: move `filter_map_results` to public util
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49934
diff changeset
   501
        Err(e) => Some(Err(e)),
f5b168979626 rust: move `filter_map_results` to public util
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49934
diff changeset
   502
    })
f5b168979626 rust: move `filter_map_results` to public util
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49934
diff changeset
   503
}
50321
14b57943ae6d rust: fix thread cap (for real this time)
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50252
diff changeset
   504
51151
aba622c7dc7e rust: add a utility function to merge ordered fallible iterators
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 50412
diff changeset
   505
/// 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: 50412
diff changeset
   506
///
aba622c7dc7e rust: add a utility function to merge ordered fallible iterators
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 50412
diff changeset
   507
/// 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: 50412
diff changeset
   508
/// 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: 50412
diff changeset
   509
/// conservative.
aba622c7dc7e rust: add a utility function to merge ordered fallible iterators
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 50412
diff changeset
   510
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: 50412
diff changeset
   511
    iter1: I1,
aba622c7dc7e rust: add a utility function to merge ordered fallible iterators
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 50412
diff changeset
   512
    iter2: I2,
aba622c7dc7e rust: add a utility function to merge ordered fallible iterators
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 50412
diff changeset
   513
    f: F,
aba622c7dc7e rust: add a utility function to merge ordered fallible iterators
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 50412
diff changeset
   514
) -> 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: 50412
diff changeset
   515
where
aba622c7dc7e rust: add a utility function to merge ordered fallible iterators
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 50412
diff changeset
   516
    I1: Iterator<Item = Result<A, E>> + 'a,
aba622c7dc7e rust: add a utility function to merge ordered fallible iterators
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 50412
diff changeset
   517
    I2: Iterator<Item = Result<B, E>> + 'a,
aba622c7dc7e rust: add a utility function to merge ordered fallible iterators
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 50412
diff changeset
   518
    F: FnMut(&A, &B) -> Ordering + 'a,
aba622c7dc7e rust: add a utility function to merge ordered fallible iterators
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 50412
diff changeset
   519
{
aba622c7dc7e rust: add a utility function to merge ordered fallible iterators
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 50412
diff changeset
   520
    let mut g = f;
aba622c7dc7e rust: add a utility function to merge ordered fallible iterators
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 50412
diff changeset
   521
    iter1
aba622c7dc7e rust: add a utility function to merge ordered fallible iterators
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 50412
diff changeset
   522
        .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: 50412
diff changeset
   523
            Err(_) => Ordering::Less,
aba622c7dc7e rust: add a utility function to merge ordered fallible iterators
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 50412
diff changeset
   524
            Ok(i1) => match i2 {
aba622c7dc7e rust: add a utility function to merge ordered fallible iterators
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 50412
diff changeset
   525
                Err(_) => Ordering::Greater,
aba622c7dc7e rust: add a utility function to merge ordered fallible iterators
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 50412
diff changeset
   526
                Ok(i2) => g(i1, i2),
aba622c7dc7e rust: add a utility function to merge ordered fallible iterators
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 50412
diff changeset
   527
            },
aba622c7dc7e rust: add a utility function to merge ordered fallible iterators
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 50412
diff changeset
   528
        })
aba622c7dc7e rust: add a utility function to merge ordered fallible iterators
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 50412
diff changeset
   529
        .map(|result| match result {
aba622c7dc7e rust: add a utility function to merge ordered fallible iterators
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 50412
diff changeset
   530
            EitherOrBoth::Left(Err(e)) => Err(e),
aba622c7dc7e rust: add a utility function to merge ordered fallible iterators
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 50412
diff changeset
   531
            EitherOrBoth::Right(Err(e)) => Err(e),
aba622c7dc7e rust: add a utility function to merge ordered fallible iterators
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 50412
diff changeset
   532
            EitherOrBoth::Both(Err(e), _) => Err(e),
aba622c7dc7e rust: add a utility function to merge ordered fallible iterators
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 50412
diff changeset
   533
            EitherOrBoth::Both(_, Err(e)) => Err(e),
aba622c7dc7e rust: add a utility function to merge ordered fallible iterators
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 50412
diff changeset
   534
            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: 50412
diff changeset
   535
            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: 50412
diff changeset
   536
            EitherOrBoth::Both(Ok(v1), Ok(v2)) => {
aba622c7dc7e rust: add a utility function to merge ordered fallible iterators
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 50412
diff changeset
   537
                Ok(EitherOrBoth::Both(v1, v2))
aba622c7dc7e rust: add a utility function to merge ordered fallible iterators
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 50412
diff changeset
   538
            }
aba622c7dc7e rust: add a utility function to merge ordered fallible iterators
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 50412
diff changeset
   539
        })
aba622c7dc7e rust: add a utility function to merge ordered fallible iterators
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 50412
diff changeset
   540
}
aba622c7dc7e rust: add a utility function to merge ordered fallible iterators
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 50412
diff changeset
   541
50321
14b57943ae6d rust: fix thread cap (for real this time)
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50252
diff changeset
   542
/// 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
   543
/// 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
   544
/// This is a stop-gap measure until we figure out why using more than 16
52186
e6a44bc91bc2 rust-update: make `update_from_null` respect `worker.numcpu` config option
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51151
diff changeset
   545
/// 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
   546
///
14b57943ae6d rust: fix thread cap (for real this time)
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50252
diff changeset
   547
/// 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
   548
///
14b57943ae6d rust: fix thread cap (for real this time)
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50252
diff changeset
   549
/// # Errors
14b57943ae6d rust: fix thread cap (for real this time)
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50252
diff changeset
   550
///
14b57943ae6d rust: fix thread cap (for real this time)
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50252
diff changeset
   551
/// 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
   552
/// 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
   553
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
   554
    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
   555
14b57943ae6d rust: fix thread cap (for real this time)
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50252
diff changeset
   556
    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
   557
        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
   558
            .map(usize::from)
14b57943ae6d rust: fix thread cap (for real this time)
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50252
diff changeset
   559
            .unwrap_or(1);
14b57943ae6d rust: fix thread cap (for real this time)
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50252
diff changeset
   560
        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
   561
        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
   562
            .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
   563
            .build_global();
14b57943ae6d rust: fix thread cap (for real this time)
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50252
diff changeset
   564
        if res.is_ok() {
14b57943ae6d rust: fix thread cap (for real this time)
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50252
diff changeset
   565
            log::trace!(
14b57943ae6d rust: fix thread cap (for real this time)
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50252
diff changeset
   566
                "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
   567
            );
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
        return res;
14b57943ae6d rust: fix thread cap (for real this time)
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50252
diff changeset
   570
    }
14b57943ae6d rust: fix thread cap (for real this time)
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50252
diff changeset
   571
    Ok(())
14b57943ae6d rust: fix thread cap (for real this time)
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50252
diff changeset
   572
}