rust/hg-core/src/utils.rs
author Arseniy Alekseyev <aalekseyev@janestreet.com>
Wed, 15 Nov 2023 18:41:33 +0000
changeset 51151 aba622c7dc7e
parent 50412 331a3cbe1c9e
child 52186 e6a44bc91bc2
permissions -rw-r--r--
rust: add a utility function to merge ordered fallible iterators Adding a function merge_join_results_by, a version of itertools::merge_join_by that works on "fallible" iterators (iterators that can produce errors)
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
14b57943ae6d rust: fix thread cap (for real this time)
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50252
diff changeset
   545
/// threads makes `status` slower for each additional thread.
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
}