reverie-examples/strace/filter.rs (60 lines of code) (raw):

/* * Copyright (c) Facebook, Inc. and its affiliates. * * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. */ use reverie::syscalls::Sysno; use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, Deserialize, Serialize, Eq, PartialEq)] pub struct Filter { /// Inverses the match. pub inverse: bool, /// The set of syscalls to match. pub syscalls: Vec<Sysno>, } impl std::str::FromStr for Filter { type Err = String; // Must parse this: [!][?]value1[,[?]value2]... fn from_str(s: &str) -> Result<Self, Self::Err> { let (inverse, s) = match s.strip_prefix('!') { Some(s) => (true, s), None => (false, s), }; let mut syscalls = Vec::new(); for value in s.split(',') { // FIXME: Handle syscall sets, so we can use '%stat` to trace all // stat calls, for example. if value.strip_prefix('%').is_some() { return Err("filtering sets of syscall is not yet supported".into()); } let syscall: Sysno = value .parse() .map_err(|()| format!("invalid syscall name '{}'", value))?; syscalls.push(syscall); } Ok(Self { inverse, syscalls }) } } #[cfg(test)] mod tests { use super::*; #[test] fn parse_filter() { assert_eq!( "open,mmap".parse(), Ok(Filter { inverse: false, syscalls: vec![Sysno::open, Sysno::mmap] }) ); assert_eq!( "open,foobar".parse::<Filter>(), Err("invalid syscall name 'foobar'".into()) ); assert_eq!( "!read,write".parse(), Ok(Filter { inverse: true, syscalls: vec![Sysno::read, Sysno::write] }) ); } }