1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
#![feature(test)] #![feature(ascii_ctype)] extern crate test; use std::ascii::AsciiExt; pub fn valid_scope(scope: &str) -> bool { scope.chars().all(|ch| ch.is_ascii_graphic() || ch == ' ') } pub fn scope_match(scope_patterns: &[&str], scopesets: &[&[&str]]) -> bool { scopesets.iter().any(|scopeset| { scopeset.iter().all(|scope| { scope_patterns.iter().any(|pattern| { match pattern.chars().last() { Some('*') => scope.starts_with(pattern.trim_right_matches('*')), _ => scope == pattern, } }) }) }) } #[cfg(test)] mod tests { use super::*; use test::Bencher; mod valid_scope { use super::*; macro_rules! test_valid_scope { ($n:ident, $thing:expr, $res:expr) => { mod $n { use super::*; #[test] fn correctness() { assert_eq!($res, valid_scope($thing)); } #[bench] fn benchmark(b: &mut Bencher) { b.iter(|| valid_scope($thing)); } } } } test_valid_scope!(normal_scopes, "auth:credentials", true); test_valid_scope!(empty_scopes, "", true); test_valid_scope!(star_scopes, "queue:*", true); test_valid_scope!(scopes_with_spaces, "secrets:garbage:foo bar", true); test_valid_scope!(scopes_with_newlines, "some:garbage\nauth:credentials", false); test_valid_scope!(scopes_with_nulls, "some:garbage\0auth:credentials", false); test_valid_scope!(scopes_with_unicode, "halt:👻", false); } mod scope_match { use super::*; macro_rules! test_scope_match { ($n:ident, $patterns:expr, $scopes:expr, $res:expr) => { mod $n { use super::*; #[test] fn correctness() { assert_eq!($res, scope_match($patterns, $scopes)); } #[bench] fn benchmark(b: &mut Bencher) { b.iter(|| scope_match($patterns, $scopes)); } } } } test_scope_match!(single_exact_match, &["foo:bar"], &[&["foo:bar"]], true); test_scope_match!(empty_scopeset, &["foo:bar"], &[&[""]], false); test_scope_match!(prefix, &["foo:*"], &[&["foo:bar"]], true); test_scope_match!(star_in_middle, &["foo:*:bing"], &[&["foo:bar:bing"]], false); test_scope_match!(star_at_beginning, &["*:bar"], &[&["foo:bar"]], false); test_scope_match!(no_star_prefix, &["foo:"], &[&["foo:bar"]], false); test_scope_match!(star_but_not_prefix, &["foo:bar:*"], &[&["bar:bing"]], false); test_scope_match!(star_but_not_prefix_partial, &["bar:*"], &[&["foo:bar:bing"]], false); test_scope_match!(disjunction_strings, &["bar:*"], &[&["foo:x"], &["bar:x"]], true); test_scope_match!(conjunction, &["bar:*", "foo:x"], &[&["foo:x", "bar:y"]], true); test_scope_match!(empty_pattern, &[""], &[&["foo:bar"]], false); test_scope_match!(empty_patterns, &[], &[&["foo:bar"]], false); test_scope_match!(bare_star, &["*"], &[&["foo:bar", "bar:bing"]], true); test_scope_match!(empty_scopeset_conjunction, &["foo:bar"], &[&[]], true); test_scope_match!(empty_scopeset_disjunction, &["foo:bar"], &[], false); } }