mod bytes_; mod length; mod starts_with; use nu_protocol::ast::CellPath; use nu_protocol::{PipelineData, ShellError, Span, Value}; use std::sync::atomic::AtomicBool; use std::sync::Arc; pub use bytes_::Bytes; pub use length::BytesLen; pub use starts_with::BytesStartsWith; trait BytesArgument { fn take_column_paths(&mut self) -> Option>; } /// map input pipeline data, for each elements, if it's Binary, invoke relative `cmd` with `arg`. fn operate( cmd: C, mut arg: A, input: PipelineData, span: Span, ctrlc: Option>, ) -> Result where A: BytesArgument + Send + Sync + 'static, C: Fn(&[u8], &A, Span) -> Value + Send + Sync + 'static + Clone + Copy, { match arg.take_column_paths() { None => input.map( move |v| match v { Value::Binary { val, span: val_span, } => cmd(&val, &arg, val_span), other => Value::Error { error: ShellError::UnsupportedInput( format!( "Input's type is {}. This command only works with bytes.", other.get_type() ), span, ), }, }, ctrlc, ), Some(column_paths) => { let arg = Arc::new(arg); input.map( move |mut v| { for path in &column_paths { let opt = arg.clone(); let r = v.update_cell_path( &path.members, Box::new(move |old| { match old { Value::Binary {val, span: val_span} => cmd(val, &opt, *val_span), other => Value::Error { error: ShellError::UnsupportedInput( format!( "Input's type is {}. This command only works with bytes.", other.get_type() ), span, ), }}}), ); if let Err(error) = r { return Value::Error { error }; } } v }, ctrlc, ) } } }