mirror of
https://github.com/facebook/sapling.git
synced 2024-10-08 15:57:43 +03:00
common: add iterhelpers
Summary: This just adds a single fn. I did not come up with a better place/name to put it, suggestions are welcome. Seems generic enough to belong at the top-level common location. I've already needed this twice, so decided to extract. Second callsite will be further in the stack. Reviewed By: StanislavGlebik Differential Revision: D24080193 fbshipit-source-id: c3e0646f263562f3eed93f1fdbab9a076729f33c
This commit is contained in:
parent
2ea25308ab
commit
081ca3e7d6
@ -252,6 +252,7 @@ members = [
|
||||
"common/async_limiter/examples/tokio_v2",
|
||||
"common/bounded_traversal",
|
||||
"common/dedupmap",
|
||||
"common/iterhelpers",
|
||||
"common/rust/caching_ext",
|
||||
"common/rust/slog_ext",
|
||||
"common/rust/sql_ext",
|
||||
|
@ -16,6 +16,7 @@ path = "test/main.rs"
|
||||
[dependencies]
|
||||
commitsync = { path = "../../../../configerator/structs/scm/mononoke/repos/commitsync" }
|
||||
context = { path = "../../server/context" }
|
||||
iterhelpers = { path = "../../common/iterhelpers" }
|
||||
metaconfig_parser = { path = "../../metaconfig/parser" }
|
||||
metaconfig_types = { path = "../../metaconfig/types" }
|
||||
mononoke_types = { path = "../../mononoke_types" }
|
||||
|
@ -11,6 +11,7 @@ use anyhow::{anyhow, Error, Result};
|
||||
use cached_config::{ConfigHandle, ConfigStore};
|
||||
use commitsync::types::{RawCommitSyncAllVersions, RawCommitSyncCurrentVersions};
|
||||
use context::CoreContext;
|
||||
use iterhelpers::get_only_item;
|
||||
use metaconfig_parser::Convert;
|
||||
use metaconfig_types::{CommitSyncConfig, CommitSyncConfigVersion};
|
||||
use mononoke_types::RepositoryId;
|
||||
@ -158,23 +159,6 @@ impl CfgrLiveCommitSyncConfig {
|
||||
.iter()
|
||||
.any(|small_repo| small_repo.repoid == repo_id.id())
|
||||
}
|
||||
|
||||
/// Return a clone of the only item in an iterator
|
||||
/// Error out otherwise
|
||||
fn get_only_item<T: Clone, I: IntoIterator<Item = T>, N: Fn() -> Error, M: Fn() -> Error>(
|
||||
items: I,
|
||||
no_items_error: N,
|
||||
many_items_error: M,
|
||||
) -> Result<T> {
|
||||
let mut iter = items.into_iter();
|
||||
let maybe_first = iter.next();
|
||||
let maybe_second = iter.next();
|
||||
match (maybe_first, maybe_second) {
|
||||
(None, None) => Err(no_items_error()),
|
||||
(Some(only_item), None) => Ok(only_item.clone()),
|
||||
(_, _) => return Err(many_items_error()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl LiveCommitSyncConfig for CfgrLiveCommitSyncConfig {
|
||||
@ -222,12 +206,12 @@ impl LiveCommitSyncConfig for CfgrLiveCommitSyncConfig {
|
||||
})
|
||||
.map(|(_, commit_sync_config)| commit_sync_config);
|
||||
|
||||
Self::get_only_item(
|
||||
let res: Result<_, Error> = get_only_item(
|
||||
interesting_top_level_configs,
|
||||
|| ErrorKind::NotPartOfAnyCommitSyncConfig(repo_id).into(),
|
||||
|| ErrorKind::PartOfMultipleCommitSyncConfigs(repo_id).into(),
|
||||
)?
|
||||
.clone()
|
||||
|| ErrorKind::NotPartOfAnyCommitSyncConfig(repo_id),
|
||||
|_, _| ErrorKind::PartOfMultipleCommitSyncConfigs(repo_id),
|
||||
);
|
||||
res?.clone()
|
||||
};
|
||||
|
||||
let commit_sync_config = raw_commit_sync_config.convert()?;
|
||||
|
10
eden/mononoke/common/iterhelpers/Cargo.toml
Normal file
10
eden/mononoke/common/iterhelpers/Cargo.toml
Normal file
@ -0,0 +1,10 @@
|
||||
[package]
|
||||
name = "iterhelpers"
|
||||
edition = "2018"
|
||||
version = "0.1.0"
|
||||
authors = ['Facebook']
|
||||
license = "GPLv2+"
|
||||
include = ["src/*.rs"]
|
||||
|
||||
[dev-dependencies]
|
||||
anyhow = "1.0"
|
74
eden/mononoke/common/iterhelpers/src/lib.rs
Normal file
74
eden/mononoke/common/iterhelpers/src/lib.rs
Normal file
@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This software may be used and distributed according to the terms of the
|
||||
* GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/// In case iterator has 0 or 2+ items, fails with errors
|
||||
/// produced by corresponding error factories
|
||||
pub fn get_only_item<T, E, N, NE, M, ME>(
|
||||
items: impl IntoIterator<Item = T>,
|
||||
no_items_error: N,
|
||||
many_items_error: M,
|
||||
) -> Result<T, E>
|
||||
where
|
||||
N: FnOnce() -> NE,
|
||||
NE: Into<E>,
|
||||
M: FnOnce(T, T) -> ME,
|
||||
ME: Into<E>,
|
||||
{
|
||||
let mut iter = items.into_iter();
|
||||
let maybe_first = iter.next();
|
||||
let maybe_second = iter.next();
|
||||
match (maybe_first, maybe_second) {
|
||||
(None, None) => Err(no_items_error().into()),
|
||||
(Some(only_item), None) => Ok(only_item),
|
||||
(Some(item1), Some(item2)) => Err(many_items_error(item1, item2).into()),
|
||||
(None, Some(_)) => panic!("iterator returns Some after None"),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use anyhow::{anyhow, Error};
|
||||
|
||||
#[test]
|
||||
fn test_success() {
|
||||
let v: Vec<u8> = vec![1];
|
||||
let r: Result<_, Error> =
|
||||
get_only_item(v, || anyhow!("no items"), |_, _| anyhow!("many items"));
|
||||
assert_eq!(r.unwrap(), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_no_items() {
|
||||
let v: Vec<u8> = vec![];
|
||||
let res: Result<_, Error> =
|
||||
get_only_item(v, || anyhow!("no items"), |_, _| anyhow!("many items"));
|
||||
assert!(res.is_err());
|
||||
assert_eq!(format!("{}", res.unwrap_err()), "no items".to_string());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_too_many_items() {
|
||||
let v: Vec<u8> = vec![1, 2, 3];
|
||||
let res: Result<_, Error> =
|
||||
get_only_item(v, || anyhow!("no items"), |_, _| anyhow!("many items"));
|
||||
assert!(res.is_err());
|
||||
assert_eq!(format!("{}", res.unwrap_err()), "many items".to_string());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_too_many_items_args() {
|
||||
let v: Vec<u8> = vec![1, 2, 3];
|
||||
let too_many_items = |i1, i2| {
|
||||
assert_eq!(i1, 1);
|
||||
assert_eq!(i2, 2);
|
||||
anyhow!("many items")
|
||||
};
|
||||
let res: Result<_, Error> = get_only_item(v, || anyhow!("no items"), too_many_items);
|
||||
assert!(res.is_err());
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user