diff --git a/Cargo.lock b/Cargo.lock index 971d896add..501c3f79fa 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -128,6 +128,21 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c58ec36aac5066d5ca17df51b3e70279f5670a72102f5752cb7e7c856adfc70" +[[package]] +name = "capnp" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae9b8a7119420b5279ddc2b4ee553ee15bcf4605df6135a26f03ffe153bee97c" + +[[package]] +name = "capnpc" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b47bce811162518b5c38f746ed584bd2922ae7bb560ef64f230d2e4ee0d111fe" +dependencies = [ + "capnp", +] + [[package]] name = "cc" version = "1.0.71" @@ -163,6 +178,28 @@ dependencies = [ "chrono", ] +[[package]] +name = "chrono-tz" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64c01c1c607d25c71bbaa67c113d6c6b36c434744b4fd66691d711b5b1bc0c8b" +dependencies = [ + "chrono", + "chrono-tz-build", + "phf", +] + +[[package]] +name = "chrono-tz-build" +version = "0.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db058d493fb2f65f41861bfed7e3fe6335264a9f0f92710cab5bdf01fef09069" +dependencies = [ + "parse-zoneinfo", + "phf", + "phf_codegen", +] + [[package]] name = "console" version = "0.15.0" @@ -622,6 +659,8 @@ version = "0.1.0" dependencies = [ "bytesize", "chrono", + "chrono-humanize", + "chrono-tz", "dialoguer", "glob", "lscolors", @@ -629,6 +668,7 @@ dependencies = [ "nu-json", "nu-parser", "nu-path", + "nu-plugin", "nu-protocol", "nu-table", "nu-term-grid", @@ -636,6 +676,7 @@ dependencies = [ "sysinfo", "terminal_size", "thiserror", + "titlecase", "trash", "unicode-segmentation", ] @@ -669,6 +710,7 @@ name = "nu-parser" version = "0.1.0" dependencies = [ "miette", + "nu-plugin", "nu-protocol", "thiserror", ] @@ -681,6 +723,15 @@ dependencies = [ "dunce", ] +[[package]] +name = "nu-plugin" +version = "0.1.0" +dependencies = [ + "capnp", + "capnpc", + "nu-protocol", +] + [[package]] name = "nu-protocol" version = "0.1.0" @@ -801,6 +852,54 @@ dependencies = [ "winapi", ] +[[package]] +name = "parse-zoneinfo" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c705f256449c60da65e11ff6626e0c16a0a0b96aaa348de61376b249bc340f41" +dependencies = [ + "regex", +] + +[[package]] +name = "phf" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9fc3db1018c4b59d7d582a739436478b6035138b6aecbce989fc91c3e98409f" +dependencies = [ + "phf_shared", +] + +[[package]] +name = "phf_codegen" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb1c3a8bc4dd4e5cfce29b44ffc14bedd2ee294559a294e2a4d4c9e9a6a13cd" +dependencies = [ + "phf_generator", + "phf_shared", +] + +[[package]] +name = "phf_generator" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6" +dependencies = [ + "phf_shared", + "rand", +] + +[[package]] +name = "phf_shared" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" +dependencies = [ + "siphasher", + "uncased", +] + [[package]] name = "ppv-lite86" version = "0.2.15" @@ -1096,6 +1195,12 @@ dependencies = [ "libc", ] +[[package]] +name = "siphasher" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "533494a8f9b724d33625ab53c6c4800f7cc445895924a8ef649222dcb76e938b" + [[package]] name = "sized-chunks" version = "0.6.5" @@ -1263,6 +1368,16 @@ dependencies = [ "winapi", ] +[[package]] +name = "titlecase" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f565e410cfc24c2f2a89960b023ca192689d7f77d3f8d4f4af50c2d8affe1117" +dependencies = [ + "lazy_static", + "regex", +] + [[package]] name = "trash" version = "1.3.0" @@ -1278,6 +1393,15 @@ version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b63708a265f51345575b27fe43f9500ad611579e764c79edbc2037b1121959ec" +[[package]] +name = "uncased" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5baeed7327e25054889b9bd4f975f32e5f4c5d434042d59ab6cd4142c0a76ed0" +dependencies = [ + "version_check", +] + [[package]] name = "unicode-linebreak" version = "0.1.2" diff --git a/Cargo.toml b/Cargo.toml index d08ad421b5..973fae44cc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,14 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [workspace] -members = ["crates/nu-cli", "crates/nu-engine", "crates/nu-parser", "crates/nu-command", "crates/nu-protocol"] +members = [ + "crates/nu-cli", + "crates/nu-engine", + "crates/nu-parser", + "crates/nu-command", + "crates/nu-protocol", + "crates/nu-plugin", +] [dependencies] reedline = { git = "https://github.com/nushell/reedline", branch = "main" } diff --git a/crates/nu-command/Cargo.toml b/crates/nu-command/Cargo.toml index 1a805e4c6a..99d13d33c3 100644 --- a/crates/nu-command/Cargo.toml +++ b/crates/nu-command/Cargo.toml @@ -13,6 +13,7 @@ nu-protocol = { path = "../nu-protocol" } nu-table = { path = "../nu-table" } nu-term-grid = { path = "../nu-term-grid" } nu-parser = { path = "../nu-parser" } +nu-plugin = { path = "../nu-plugin" } trash = { version = "1.3.0", optional = true } unicode-segmentation = "1.8.0" @@ -22,11 +23,14 @@ glob = "0.3.0" thiserror = "1.0.29" sysinfo = "0.20.4" chrono = { version = "0.4.19", features = ["serde"] } +chrono-humanize = "0.2.1" +chrono-tz = "0.6.0" terminal_size = "0.1.17" lscolors = { version = "0.8.0", features = ["crossterm"] } bytesize = "1.1.0" dialoguer = "0.9.0" rayon = "1.5.1" +titlecase = "1.1.0" [features] trash-support = ["trash"] diff --git a/crates/nu-command/src/core_commands/echo.rs b/crates/nu-command/src/core_commands/echo.rs new file mode 100644 index 0000000000..af0c994893 --- /dev/null +++ b/crates/nu-command/src/core_commands/echo.rs @@ -0,0 +1,66 @@ +use nu_engine::CallExt; +use nu_protocol::ast::Call; +use nu_protocol::engine::{Command, EngineState, Stack}; +use nu_protocol::{ + Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Value, ValueStream, +}; + +#[derive(Clone)] +pub struct Echo; + +impl Command for Echo { + fn name(&self) -> &str { + "echo" + } + + fn usage(&self) -> &str { + "Echo the arguments back to the user." + } + + fn signature(&self) -> Signature { + Signature::build("echo").rest("rest", SyntaxShape::Any, "the values to echo") + } + + fn run( + &self, + engine_state: &EngineState, + stack: &mut Stack, + call: &Call, + _input: PipelineData, + ) -> Result { + call.rest(engine_state, stack, 0).map(|to_be_echoed| { + PipelineData::Stream(ValueStream::from_stream( + to_be_echoed.into_iter(), + engine_state.ctrlc.clone(), + )) + }) + } + + fn examples(&self) -> Vec { + vec![ + Example { + description: "Put a hello message in the pipeline", + example: "echo 'hello'", + result: Some(Value::List { + vals: vec![Value::test_string("hello")], + span: Span::new(0, 0), + }), + }, + Example { + description: "Print the value of the special '$nu' variable", + example: "echo $nu", + result: None, + }, + ] + } +} + +#[cfg(test)] +mod test { + #[test] + fn test_examples() { + use super::Echo; + use crate::test_examples; + test_examples(Echo {}) + } +} diff --git a/crates/nu-command/src/core_commands/mod.rs b/crates/nu-command/src/core_commands/mod.rs index a124ffcf18..626ac16cda 100644 --- a/crates/nu-command/src/core_commands/mod.rs +++ b/crates/nu-command/src/core_commands/mod.rs @@ -1,6 +1,7 @@ mod alias; mod def; mod do_; +mod echo; mod export_def; mod for_; mod help; @@ -8,12 +9,15 @@ mod hide; mod if_; mod let_; mod module; +mod register; +mod run_plugin; mod source; mod use_; pub use alias::Alias; pub use def::Def; pub use do_::Do; +pub use echo::Echo; pub use export_def::ExportDef; pub use for_::For; pub use help::Help; @@ -21,5 +25,7 @@ pub use hide::Hide; pub use if_::If; pub use let_::Let; pub use module::Module; +pub use register::Register; +pub use run_plugin::RunPlugin; pub use source::Source; pub use use_::Use; diff --git a/crates/nu-command/src/core_commands/register.rs b/crates/nu-command/src/core_commands/register.rs new file mode 100644 index 0000000000..9578e717e0 --- /dev/null +++ b/crates/nu-command/src/core_commands/register.rs @@ -0,0 +1,34 @@ +use nu_protocol::ast::Call; +use nu_protocol::engine::{Command, EngineState, Stack}; +use nu_protocol::{PipelineData, Signature, SyntaxShape}; + +#[derive(Clone)] +pub struct Register; + +impl Command for Register { + fn name(&self) -> &str { + "register" + } + + fn usage(&self) -> &str { + "Register a plugin" + } + + fn signature(&self) -> nu_protocol::Signature { + Signature::build("register").required( + "plugin", + SyntaxShape::Filepath, + "location of bin for plugin", + ) + } + + fn run( + &self, + _engine_state: &EngineState, + _stack: &mut Stack, + _call: &Call, + _input: PipelineData, + ) -> Result { + Ok(PipelineData::new()) + } +} diff --git a/crates/nu-command/src/core_commands/run_plugin.rs b/crates/nu-command/src/core_commands/run_plugin.rs new file mode 100644 index 0000000000..c8b448fb02 --- /dev/null +++ b/crates/nu-command/src/core_commands/run_plugin.rs @@ -0,0 +1,30 @@ +use nu_protocol::ast::Call; +use nu_protocol::engine::{Command, EngineState, Stack}; +use nu_protocol::{PipelineData, Signature}; + +#[derive(Clone)] +pub struct RunPlugin; + +impl Command for RunPlugin { + fn name(&self) -> &str { + "run_plugin" + } + + fn usage(&self) -> &str { + "test for plugin encoding" + } + + fn signature(&self) -> nu_protocol::Signature { + Signature::build("run_plugin") + } + + fn run( + &self, + _context: &EngineState, + _stack: &mut Stack, + _call: &Call, + _input: PipelineData, + ) -> Result { + Ok(PipelineData::new()) + } +} diff --git a/crates/nu-command/src/core_commands/use_.rs b/crates/nu-command/src/core_commands/use_.rs index 27635687d5..3b899c96ef 100644 --- a/crates/nu-command/src/core_commands/use_.rs +++ b/crates/nu-command/src/core_commands/use_.rs @@ -15,7 +15,7 @@ impl Command for Use { } fn signature(&self) -> nu_protocol::Signature { - Signature::build("use").required("pattern", SyntaxShape::String, "import pattern") + Signature::build("use").rest("pattern", SyntaxShape::String, "import pattern parts") } fn run( diff --git a/crates/nu-command/src/date/command.rs b/crates/nu-command/src/date/command.rs new file mode 100644 index 0000000000..3206b3b7c2 --- /dev/null +++ b/crates/nu-command/src/date/command.rs @@ -0,0 +1,47 @@ +use nu_engine::get_full_help; +use nu_protocol::{ + ast::Call, + engine::{Command, EngineState, Stack}, + IntoPipelineData, PipelineData, ShellError, Signature, Value, +}; + +#[derive(Clone)] +pub struct Date; + +impl Command for Date { + fn name(&self) -> &str { + "date" + } + + fn signature(&self) -> Signature { + Signature::build("date") + } + + fn usage(&self) -> &str { + "date" + } + + fn run( + &self, + engine_state: &EngineState, + stack: &mut Stack, + call: &Call, + _input: PipelineData, + ) -> Result { + date(engine_state, stack, call) + } +} + +fn date( + engine_state: &EngineState, + _stack: &mut Stack, + call: &Call, +) -> Result { + let head = call.head; + + Ok(Value::String { + val: get_full_help(&Date.signature(), &Date.examples(), engine_state), + span: head, + } + .into_pipeline_data()) +} diff --git a/crates/nu-command/src/date/format.rs b/crates/nu-command/src/date/format.rs new file mode 100644 index 0000000000..abee6653d4 --- /dev/null +++ b/crates/nu-command/src/date/format.rs @@ -0,0 +1,116 @@ +use chrono::Local; +use nu_engine::CallExt; +use nu_protocol::{ + ast::Call, + engine::{Command, EngineState, Stack}, + Example, PipelineData, Signature, Span, Spanned, SyntaxShape, Value, +}; + +use super::utils::{parse_date_from_string, unsupported_input_error}; + +#[derive(Clone)] +pub struct SubCommand; + +impl Command for SubCommand { + fn name(&self) -> &str { + "date format" + } + + fn signature(&self) -> Signature { + Signature::build("date format").required( + "format string", + SyntaxShape::String, + "the desired date format", + ) + } + + fn usage(&self) -> &str { + "Format a given date using the given format string." + } + + fn run( + &self, + engine_state: &EngineState, + stack: &mut Stack, + call: &Call, + input: PipelineData, + ) -> Result { + let head = call.head; + let formatter: Spanned = call.req(engine_state, stack, 0)?; + input.map( + move |value| format_helper(value, &formatter, head), + engine_state.ctrlc.clone(), + ) + } + + fn examples(&self) -> Vec { + vec![ + Example { + description: "Format a given date using the given format string.", + example: "date format '%Y-%m-%d'", + result: Some(Value::String { + val: Local::now().format("%Y-%m-%d").to_string(), + span: Span::unknown(), + }), + }, + Example { + description: "Format a given date using the given format string.", + example: r#"date format "%Y-%m-%d %H:%M:%S""#, + result: Some(Value::String { + val: Local::now().format("%Y-%m-%d %H:%M:%S").to_string(), + span: Span::unknown(), + }), + }, + Example { + description: "Format a given date using the given format string.", + example: r#""2021-10-22 20:00:12 +01:00" | date format "%Y-%m-%d""#, + result: Some(Value::String { + val: "2021-10-22".into(), + span: Span::unknown(), + }), + }, + ] + } +} + +fn format_helper(value: Value, formatter: &Spanned, span: Span) -> Value { + match value { + Value::Date { val, span: _ } => Value::String { + val: val.format(formatter.item.as_str()).to_string(), + span, + }, + Value::String { val, span: _ } => { + let dt = parse_date_from_string(val); + match dt { + Ok(x) => Value::String { + val: x.format(formatter.item.as_str()).to_string(), + span, + }, + Err(e) => e, + } + } + Value::Nothing { span: _ } => { + let dt = Local::now(); + Value::String { + val: dt + .with_timezone(dt.offset()) + .format(formatter.item.as_str()) + .to_string(), + span, + } + } + _ => unsupported_input_error(), + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_examples() { + use crate::test_examples; + + test_examples(SubCommand {}) + } +} diff --git a/crates/nu-command/src/date/humanize.rs b/crates/nu-command/src/date/humanize.rs new file mode 100644 index 0000000000..52abbd6538 --- /dev/null +++ b/crates/nu-command/src/date/humanize.rs @@ -0,0 +1,99 @@ +use crate::date::utils::parse_date_from_string; +use chrono::{DateTime, FixedOffset, Local}; +use chrono_humanize::HumanTime; +use nu_protocol::ast::Call; +use nu_protocol::engine::{Command, EngineState, Stack}; +use nu_protocol::{Example, PipelineData, ShellError, Signature, Span, Value}; +#[derive(Clone)] +pub struct SubCommand; + +impl Command for SubCommand { + fn name(&self) -> &str { + "date humanize" + } + + fn signature(&self) -> Signature { + Signature::build("date humanize") + } + + fn usage(&self) -> &str { + "Print a 'humanized' format for the date, relative to now." + } + + fn run( + &self, + engine_state: &EngineState, + _stack: &mut Stack, + call: &Call, + input: PipelineData, + ) -> Result { + let head = call.head; + input.map(move |value| helper(value, head), engine_state.ctrlc.clone()) + } + + fn examples(&self) -> Vec { + vec![ + Example { + description: "Print a 'humanized' format for the date, relative to now.", + example: "date humanize", + result: Some(Value::String { + val: "now".to_string(), + span: Span::unknown(), + }), + }, + Example { + description: "Print a 'humanized' format for the date, relative to now.", + example: r#""2021-10-22 20:00:12 +01:00" | date humanize"#, + result: None, + }, + ] + } +} + +fn helper(value: Value, head: Span) -> Value { + match value { + Value::Nothing { span: _ } => { + let dt = Local::now(); + Value::String { + val: humanize_date(dt.with_timezone(dt.offset())), + span: head, + } + } + Value::String { val, span: _ } => { + let dt = parse_date_from_string(val); + match dt { + Ok(x) => Value::String { + val: humanize_date(x), + span: head, + }, + Err(e) => e, + } + } + Value::Date { val, span: _ } => Value::String { + val: humanize_date(val), + span: head, + }, + _ => Value::Error { + error: ShellError::UnsupportedInput( + String::from("Date cannot be parsed / date format is not supported"), + Span::unknown(), + ), + }, + } +} + +fn humanize_date(dt: DateTime) -> String { + HumanTime::from(dt).to_string() +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_examples() { + use crate::test_examples; + + test_examples(SubCommand {}) + } +} diff --git a/crates/nu-command/src/date/list_timezone.rs b/crates/nu-command/src/date/list_timezone.rs new file mode 100644 index 0000000000..7e4ba8ee77 --- /dev/null +++ b/crates/nu-command/src/date/list_timezone.rs @@ -0,0 +1,44 @@ +use chrono_tz::TZ_VARIANTS; +use nu_protocol::ast::Call; +use nu_protocol::engine::{Command, EngineState, Stack}; +use nu_protocol::{IntoInterruptiblePipelineData, PipelineData, Signature, Value}; + +#[derive(Clone)] +pub struct SubCommand; + +impl Command for SubCommand { + fn name(&self) -> &str { + "date list-timezone" + } + + fn signature(&self) -> Signature { + Signature::build("date list-timezone") + } + + fn usage(&self) -> &str { + "List supported time zones." + } + + fn run( + &self, + engine_state: &EngineState, + _stack: &mut Stack, + call: &Call, + _input: PipelineData, + ) -> Result { + let span = call.head; + + Ok(TZ_VARIANTS + .iter() + .map(move |x| { + let cols = vec!["timezone".into()]; + let vals = vec![Value::String { + val: x.name().to_string(), + span, + }]; + Value::Record { cols, vals, span } + }) + .into_iter() + .into_pipeline_data(engine_state.ctrlc.clone())) + } +} diff --git a/crates/nu-command/src/date/mod.rs b/crates/nu-command/src/date/mod.rs new file mode 100644 index 0000000000..0f0d33198b --- /dev/null +++ b/crates/nu-command/src/date/mod.rs @@ -0,0 +1,17 @@ +mod command; +mod format; +mod humanize; +mod list_timezone; +mod now; +mod parser; +mod to_table; +mod to_timezone; +mod utils; + +pub use command::Date; +pub use format::SubCommand as DateFormat; +pub use humanize::SubCommand as DateHumanize; +pub use list_timezone::SubCommand as DateListTimezones; +pub use now::SubCommand as DateNow; +pub use to_table::SubCommand as DateToTable; +pub use to_timezone::SubCommand as DateToTimezone; diff --git a/crates/nu-command/src/date/now.rs b/crates/nu-command/src/date/now.rs new file mode 100644 index 0000000000..dbd0f081f3 --- /dev/null +++ b/crates/nu-command/src/date/now.rs @@ -0,0 +1,36 @@ +use chrono::Local; +use nu_protocol::ast::Call; +use nu_protocol::engine::{Command, EngineState, Stack}; +use nu_protocol::{IntoPipelineData, PipelineData, Signature, Value}; +#[derive(Clone)] +pub struct SubCommand; + +impl Command for SubCommand { + fn name(&self) -> &str { + "date now" + } + + fn signature(&self) -> Signature { + Signature::build("date now") + } + + fn usage(&self) -> &str { + "Get the current date." + } + + fn run( + &self, + _engine_state: &EngineState, + _stack: &mut Stack, + call: &Call, + _input: PipelineData, + ) -> Result { + let head = call.head; + let dt = Local::now(); + Ok(Value::Date { + val: dt.with_timezone(dt.offset()), + span: head, + } + .into_pipeline_data()) + } +} diff --git a/crates/nu-command/src/date/parser.rs b/crates/nu-command/src/date/parser.rs new file mode 100644 index 0000000000..d2d1f3a851 --- /dev/null +++ b/crates/nu-command/src/date/parser.rs @@ -0,0 +1,107 @@ +// Modified from chrono::format::scan + +use chrono::{DateTime, FixedOffset, Local, Offset, TimeZone}; +use chrono_tz::Tz; +use titlecase::titlecase; + +#[derive(Debug, Clone, PartialEq, Eq, Copy)] +pub enum ParseErrorKind { + /// Given field is out of permitted range. + OutOfRange, + + /// The input string has some invalid character sequence for given formatting items. + Invalid, + + /// The input string has been prematurely ended. + TooShort, +} + +pub fn datetime_in_timezone( + dt: &DateTime, + s: &str, +) -> Result, ParseErrorKind> { + match timezone_offset_internal(s, true, true) { + Ok(offset) => match FixedOffset::east_opt(offset) { + Some(offset) => Ok(dt.with_timezone(&offset)), + None => Err(ParseErrorKind::OutOfRange), + }, + Err(ParseErrorKind::Invalid) => { + if s.to_lowercase() == "local" { + Ok(dt.with_timezone(Local::now().offset())) + } else { + let tz: Tz = parse_timezone_internal(s)?; + let offset = tz.offset_from_utc_datetime(&dt.naive_utc()).fix(); + Ok(dt.with_timezone(&offset)) + } + } + Err(e) => Err(e), + } +} + +fn parse_timezone_internal(s: &str) -> Result { + if let Ok(tz) = s.parse() { + Ok(tz) + } else if let Ok(tz) = titlecase(s).parse() { + Ok(tz) + } else if let Ok(tz) = s.to_uppercase().parse() { + Ok(tz) + } else { + Err(ParseErrorKind::Invalid) + } +} + +fn timezone_offset_internal( + mut s: &str, + consume_colon: bool, + allow_missing_minutes: bool, +) -> Result { + fn digits(s: &str) -> Result<(u8, u8), ParseErrorKind> { + let b = s.as_bytes(); + if b.len() < 2 { + Err(ParseErrorKind::TooShort) + } else { + Ok((b[0], b[1])) + } + } + let negative = match s.as_bytes().first() { + Some(&b'+') => false, + Some(&b'-') => true, + Some(_) => return Err(ParseErrorKind::Invalid), + None => return Err(ParseErrorKind::TooShort), + }; + s = &s[1..]; + + // hours (00--99) + let hours = match digits(s)? { + (h1 @ b'0'..=b'9', h2 @ b'0'..=b'9') => i32::from((h1 - b'0') * 10 + (h2 - b'0')), + _ => return Err(ParseErrorKind::Invalid), + }; + s = &s[2..]; + + // colons (and possibly other separators) + if consume_colon { + s = s.trim_start_matches(|c: char| c == ':' || c.is_whitespace()); + } + + // minutes (00--59) + // if the next two items are digits then we have to add minutes + let minutes = if let Ok(ds) = digits(s) { + match ds { + (m1 @ b'0'..=b'5', m2 @ b'0'..=b'9') => i32::from((m1 - b'0') * 10 + (m2 - b'0')), + (b'6'..=b'9', b'0'..=b'9') => return Err(ParseErrorKind::OutOfRange), + _ => return Err(ParseErrorKind::Invalid), + } + } else if allow_missing_minutes { + 0 + } else { + return Err(ParseErrorKind::TooShort); + }; + match s.len() { + len if len >= 2 => &s[2..], + len if len == 0 => s, + _ => return Err(ParseErrorKind::TooShort), + }; + + let seconds = hours * 3600 + minutes * 60; + Ok(if negative { -seconds } else { seconds }) +} diff --git a/crates/nu-command/src/date/to_table.rs b/crates/nu-command/src/date/to_table.rs new file mode 100644 index 0000000000..91bd59af4a --- /dev/null +++ b/crates/nu-command/src/date/to_table.rs @@ -0,0 +1,163 @@ +use crate::date::utils::{parse_date_from_string, unsupported_input_error}; +use chrono::{DateTime, Datelike, FixedOffset, Local, Timelike}; +use nu_protocol::ast::Call; +use nu_protocol::engine::{Command, EngineState, Stack}; +use nu_protocol::{Example, PipelineData, Signature, Span, Value}; + +#[derive(Clone)] +pub struct SubCommand; + +impl Command for SubCommand { + fn name(&self) -> &str { + "date to-table" + } + + fn signature(&self) -> Signature { + Signature::build("date to-table") + } + + fn usage(&self) -> &str { + "Print the date in a structured table." + } + + fn run( + &self, + engine_state: &EngineState, + _stack: &mut Stack, + call: &Call, + input: PipelineData, + ) -> Result { + let head = call.head; + input.map(move |value| helper(value, head), engine_state.ctrlc.clone()) + } + + fn examples(&self) -> Vec { + vec![ + Example { + description: "Print the date in a structured table.", + example: "date to-table", + result: None, + }, + Example { + description: "Print the date in a structured table.", + example: "date now | date to-table", + result: None, + }, + Example { + description: "Print the date in a structured table.", + example: " '2020-04-12 22:10:57 +0200' | date to-table", + result: { + let span = Span::unknown(); + let cols = vec![ + "year".into(), + "month".into(), + "day".into(), + "hour".into(), + "minute".into(), + "second".into(), + "timezone".into(), + ]; + let vals = vec![ + Value::Int { val: 2020, span }, + Value::Int { val: 4, span }, + Value::Int { val: 12, span }, + Value::Int { val: 22, span }, + Value::Int { val: 10, span }, + Value::Int { val: 57, span }, + Value::String { + val: "+02:00".to_string(), + span, + }, + ]; + Some(Value::List { + vals: vec![Value::Record { cols, vals, span }], + span, + }) + }, + }, + ] + } +} + +fn parse_date_into_table(date: Result, Value>, head: Span) -> Value { + let cols = vec![ + "year".into(), + "month".into(), + "day".into(), + "hour".into(), + "minute".into(), + "second".into(), + "timezone".into(), + ]; + match date { + Ok(x) => { + let vals = vec![ + Value::Int { + val: x.year() as i64, + span: head, + }, + Value::Int { + val: x.month() as i64, + span: head, + }, + Value::Int { + val: x.day() as i64, + span: head, + }, + Value::Int { + val: x.hour() as i64, + span: head, + }, + Value::Int { + val: x.minute() as i64, + span: head, + }, + Value::Int { + val: x.second() as i64, + span: head, + }, + Value::String { + val: x.offset().to_string(), + span: head, + }, + ]; + Value::List { + vals: vec![Value::Record { + cols, + vals, + span: head, + }], + span: head, + } + } + Err(e) => e, + } +} + +fn helper(val: Value, head: Span) -> Value { + match val { + Value::String { val, span: _ } => { + let date = parse_date_from_string(val); + parse_date_into_table(date, head) + } + Value::Nothing { span: _ } => { + let now = Local::now(); + let n = now.with_timezone(now.offset()); + parse_date_into_table(Ok(n), head) + } + Value::Date { val, span: _ } => parse_date_into_table(Ok(val), head), + _ => unsupported_input_error(), + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_examples() { + use crate::test_examples; + + test_examples(SubCommand {}) + } +} diff --git a/crates/nu-command/src/date/to_timezone.rs b/crates/nu-command/src/date/to_timezone.rs new file mode 100644 index 0000000000..0b3d508389 --- /dev/null +++ b/crates/nu-command/src/date/to_timezone.rs @@ -0,0 +1,129 @@ +use super::parser::datetime_in_timezone; +use crate::date::utils::{parse_date_from_string, unsupported_input_error}; +use chrono::{DateTime, Local}; +use nu_engine::CallExt; +use nu_protocol::ast::Call; +use nu_protocol::engine::{Command, EngineState, Stack}; +use nu_protocol::{ + Example, PipelineData, ShellError, Signature, Span, Spanned, SyntaxShape, Value, +}; + +use chrono::{FixedOffset, TimeZone}; + +#[derive(Clone)] +pub struct SubCommand; + +impl Command for SubCommand { + fn name(&self) -> &str { + "date to-timezone" + } + + fn signature(&self) -> Signature { + Signature::build("date to-timezone").required( + "time zone", + SyntaxShape::String, + "time zone description", + ) + } + + fn usage(&self) -> &str { + "Convert a date to a given time zone." + } + + fn extra_usage(&self) -> &str { + "Use 'date list-timezone' to list all supported time zones." + } + + fn run( + &self, + engine_state: &EngineState, + stack: &mut Stack, + call: &Call, + input: PipelineData, + ) -> Result { + let head = call.head; + let timezone: Spanned = call.req(engine_state, stack, 0)?; + + //Ok(PipelineData::new()) + input.map( + move |value| helper(value, head, &timezone), + engine_state.ctrlc.clone(), + ) + } + + fn examples(&self) -> Vec { + vec![ + Example { + description: "Get the current date in UTC+05:00", + example: "date now | date to-timezone +0500", + result: None, + }, + Example { + description: "Get the current local date", + example: "date now | date to-timezone local", + result: None, + }, + Example { + description: "Get the current date in Hawaii", + example: "date now | date to-timezone US/Hawaii", + result: None, + }, + Example { + description: "Get the current date in Hawaii", + example: r#""2020-10-10 10:00:00 +02:00" | date to-timezone "+0500""#, + // result: None + // The following should be the result of the test, but it fails. Cannot figure it out why. + result: { + let dt = FixedOffset::east(5 * 3600) + .ymd(2020, 10, 10) + .and_hms(13, 00, 00); + + Some(Value::Date { + val: dt, + span: Span::unknown(), + }) + }, + }, + ] + } +} + +fn helper(value: Value, head: Span, timezone: &Spanned) -> Value { + match value { + Value::Date { val, span: _ } => _to_timezone(val, timezone, head), + Value::String { val, span: _ } => { + let time = parse_date_from_string(val); + match time { + Ok(dt) => _to_timezone(dt, timezone, head), + Err(e) => e, + } + } + + Value::Nothing { span: _ } => { + let dt = Local::now(); + _to_timezone(dt.with_timezone(dt.offset()), timezone, head) + } + _ => unsupported_input_error(), + } +} + +fn _to_timezone(dt: DateTime, timezone: &Spanned, span: Span) -> Value { + match datetime_in_timezone(&dt, timezone.item.as_str()) { + Ok(dt) => Value::Date { val: dt, span }, + Err(_) => Value::Error { + error: ShellError::UnsupportedInput(String::from("invalid time zone"), Span::unknown()), + }, + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_examples() { + use crate::test_examples; + + test_examples(SubCommand {}) + } +} diff --git a/crates/nu-command/src/date/utils.rs b/crates/nu-command/src/date/utils.rs new file mode 100644 index 0000000000..d1320766fc --- /dev/null +++ b/crates/nu-command/src/date/utils.rs @@ -0,0 +1,43 @@ +use chrono::{DateTime, FixedOffset}; +use nu_protocol::{ShellError, Span, Value}; + +pub fn unsupported_input_error() -> Value { + Value::Error { + error: ShellError::UnsupportedInput( + String::from( + "Only dates with timezones are supported. The following formats are allowed \n + * %Y-%m-%d %H:%M:%S %z -- 2020-04-12 22:10:57 +02:00 \n + * %Y-%m-%d %H:%M:%S%.6f %z -- 2020-04-12 22:10:57.213231 +02:00 \n + * rfc3339 -- 2020-04-12T22:10:57+02:00 \n + * rfc2822 -- Tue, 1 Jul 2003 10:52:37 +0200", + ), + Span::unknown(), + ), + } +} + +pub fn parse_date_from_string(input: String) -> Result, Value> { + let datetime = DateTime::parse_from_str(&input, "%Y-%m-%d %H:%M:%S %z"); // "2020-04-12 22:10:57 +02:00"; + match datetime { + Ok(x) => Ok(x), + Err(_) => { + let datetime = DateTime::parse_from_str(&input, "%Y-%m-%d %H:%M:%S%.6f %z"); // "2020-04-12 22:10:57.213231 +02:00"; + match datetime { + Ok(x) => Ok(x), + Err(_) => { + let datetime = DateTime::parse_from_rfc3339(&input); // "2020-04-12T22:10:57+02:00"; + match datetime { + Ok(x) => Ok(x), + Err(_) => { + let datetime = DateTime::parse_from_rfc2822(&input); // "Tue, 1 Jul 2003 10:52:37 +0200"; + match datetime { + Ok(x) => Ok(x), + Err(_) => Err(unsupported_input_error()), + } + } + } + } + } + } + } +} diff --git a/crates/nu-command/src/default_context.rs b/crates/nu-command/src/default_context.rs index 452c33f7c7..3d41f27355 100644 --- a/crates/nu-command/src/default_context.rs +++ b/crates/nu-command/src/default_context.rs @@ -27,9 +27,17 @@ pub fn create_default_context() -> EngineState { BuildString, Cd, Cp, + Date, + DateFormat, + DateHumanize, + DateListTimezones, + DateNow, + DateToTable, + DateToTimezone, Def, Do, Each, + Echo, ExportDef, External, First, @@ -54,13 +62,21 @@ pub fn create_default_context() -> EngineState { Math, MathAbs, MathAvg, + MathMax, + MathMin, + MathProduct, + MathRound, + MathSqrt, + MathSum, Mkdir, Module, Mv, ParEach, Ps, + Register, Range, Rm, + RunPlugin, Select, Size, Split, @@ -74,7 +90,8 @@ pub fn create_default_context() -> EngineState { Touch, Use, Where, - Wrap + Wrap, + Zip ); // This is a WIP proof of concept @@ -82,16 +99,6 @@ pub fn create_default_context() -> EngineState { let sig = Signature::build("exit"); working_set.add_decl(sig.predeclare()); - let sig = Signature::build("vars"); - working_set.add_decl(sig.predeclare()); - let sig = Signature::build("decls"); - working_set.add_decl(sig.predeclare()); - let sig = Signature::build("blocks"); - working_set.add_decl(sig.predeclare()); - let sig = Signature::build("stack"); - working_set.add_decl(sig.predeclare()); - let sig = Signature::build("contents"); - working_set.add_decl(sig.predeclare()); working_set.render() }; diff --git a/crates/nu-command/src/example_test.rs b/crates/nu-command/src/example_test.rs index f5879d5c96..f842dc2db8 100644 --- a/crates/nu-command/src/example_test.rs +++ b/crates/nu-command/src/example_test.rs @@ -7,7 +7,7 @@ use nu_protocol::{ use crate::To; -use super::{From, Into, Math, Split}; +use super::{Date, From, Into, Math, Split}; pub fn test_examples(cmd: impl Command + 'static) { let examples = cmd.examples(); @@ -22,6 +22,7 @@ pub fn test_examples(cmd: impl Command + 'static) { working_set.add_decl(Box::new(Into)); working_set.add_decl(Box::new(Split)); working_set.add_decl(Box::new(Math)); + working_set.add_decl(Box::new(Date)); // Adding the command that is being tested to the working set working_set.add_decl(Box::new(cmd)); diff --git a/crates/nu-command/src/filters/each.rs b/crates/nu-command/src/filters/each.rs index 5d5413aff5..1e7574e1a4 100644 --- a/crates/nu-command/src/filters/each.rs +++ b/crates/nu-command/src/filters/each.rs @@ -73,40 +73,9 @@ impl Command for Each { let span = call.head; match input { - PipelineData::Value(Value::Range { val, .. }) => Ok(val - .into_range_iter()? - .enumerate() - .map(move |(idx, x)| { - if let Some(var) = block.signature.get_positional(0) { - if let Some(var_id) = &var.var_id { - if numbered { - stack.add_var( - *var_id, - Value::Record { - cols: vec!["index".into(), "item".into()], - vals: vec![ - Value::Int { - val: idx as i64, - span, - }, - x, - ], - span, - }, - ); - } else { - stack.add_var(*var_id, x); - } - } - } - - match eval_block(&engine_state, &mut stack, &block, PipelineData::new()) { - Ok(v) => v.into_value(), - Err(error) => Value::Error { error }, - } - }) - .into_pipeline_data(ctrlc)), - PipelineData::Value(Value::List { vals: val, .. }) => Ok(val + PipelineData::Value(Value::Range { .. }) + | PipelineData::Value(Value::List { .. }) + | PipelineData::Stream { .. } => Ok(input .into_iter() .enumerate() .map(move |(idx, x)| { @@ -139,38 +108,6 @@ impl Command for Each { } }) .into_pipeline_data(ctrlc)), - PipelineData::Stream(stream) => Ok(stream - .enumerate() - .map(move |(idx, x)| { - if let Some(var) = block.signature.get_positional(0) { - if let Some(var_id) = &var.var_id { - if numbered { - stack.add_var( - *var_id, - Value::Record { - cols: vec!["index".into(), "item".into()], - vals: vec![ - Value::Int { - val: idx as i64, - span, - }, - x, - ], - span, - }, - ); - } else { - stack.add_var(*var_id, x); - } - } - } - - match eval_block(&engine_state, &mut stack, &block, PipelineData::new()) { - Ok(v) => v.into_value(), - Err(error) => Value::Error { error }, - } - }) - .into_pipeline_data(ctrlc)), PipelineData::Value(Value::Record { cols, vals, .. }) => { let mut output_cols = vec![]; let mut output_vals = vec![]; diff --git a/crates/nu-command/src/filters/mod.rs b/crates/nu-command/src/filters/mod.rs index 34796069de..ff1af74cc7 100644 --- a/crates/nu-command/src/filters/mod.rs +++ b/crates/nu-command/src/filters/mod.rs @@ -9,6 +9,7 @@ mod range; mod select; mod where_; mod wrap; +mod zip; pub use each::Each; pub use first::First; @@ -21,3 +22,4 @@ pub use range::Range; pub use select::Select; pub use where_::Where; pub use wrap::Wrap; +pub use zip::Zip; diff --git a/crates/nu-command/src/filters/zip.rs b/crates/nu-command/src/filters/zip.rs new file mode 100644 index 0000000000..49b082e76f --- /dev/null +++ b/crates/nu-command/src/filters/zip.rs @@ -0,0 +1,65 @@ +use nu_engine::CallExt; +use nu_protocol::ast::Call; +use nu_protocol::engine::{Command, EngineState, Stack}; +use nu_protocol::{ + Example, IntoInterruptiblePipelineData, IntoPipelineData, PipelineData, Signature, SyntaxShape, + Value, +}; + +#[derive(Clone)] +pub struct Zip; + +impl Command for Zip { + fn name(&self) -> &str { + "zip" + } + + fn usage(&self) -> &str { + "Combine a stream with the input" + } + + fn signature(&self) -> nu_protocol::Signature { + Signature::build("zip").required("other", SyntaxShape::Any, "the other input") + } + + fn examples(&self) -> Vec { + vec![Example { + example: "1..3 | zip 4..6", + description: "Zip multiple streams and get one of the results", + result: None, + }] + } + + fn run( + &self, + engine_state: &EngineState, + stack: &mut Stack, + call: &Call, + input: PipelineData, + ) -> Result { + let other: Value = call.req(engine_state, stack, 0)?; + let head = call.head; + let ctrlc = engine_state.ctrlc.clone(); + + Ok(input + .into_iter() + .zip(other.into_pipeline_data().into_iter()) + .map(move |(x, y)| Value::List { + vals: vec![x, y], + span: head, + }) + .into_pipeline_data(ctrlc)) + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_examples() { + use crate::test_examples; + + test_examples(Zip {}) + } +} diff --git a/crates/nu-command/src/lib.rs b/crates/nu-command/src/lib.rs index 151c6076cf..667d99be09 100644 --- a/crates/nu-command/src/lib.rs +++ b/crates/nu-command/src/lib.rs @@ -1,5 +1,6 @@ mod conversions; mod core_commands; +mod date; mod default_context; mod env; mod example_test; @@ -14,6 +15,7 @@ mod viewers; pub use conversions::*; pub use core_commands::*; +pub use date::*; pub use default_context::*; pub use env::*; pub use example_test::test_examples; diff --git a/crates/nu-command/src/math/avg.rs b/crates/nu-command/src/math/avg.rs index 384d3493a5..f7de5be527 100644 --- a/crates/nu-command/src/math/avg.rs +++ b/crates/nu-command/src/math/avg.rs @@ -50,6 +50,7 @@ pub fn average(values: &[Value], head: &Span) -> Result { span: Span::unknown(), }, values.to_vec(), + *head, )?; match total { Value::Filesize { val, span } => Ok(Value::Filesize { diff --git a/crates/nu-command/src/math/max.rs b/crates/nu-command/src/math/max.rs new file mode 100644 index 0000000000..81d146502b --- /dev/null +++ b/crates/nu-command/src/math/max.rs @@ -0,0 +1,57 @@ +use crate::math::reducers::{reducer_for, Reduce}; +use crate::math::utils::run_with_function; +use nu_protocol::ast::Call; +use nu_protocol::engine::{Command, EngineState, Stack}; +use nu_protocol::{Example, PipelineData, ShellError, Signature, Span, Value}; + +#[derive(Clone)] +pub struct SubCommand; + +impl Command for SubCommand { + fn name(&self) -> &str { + "math max" + } + + fn signature(&self) -> Signature { + Signature::build("math max") + } + + fn usage(&self) -> &str { + "Finds the maximum within a list of numbers or tables" + } + + fn run( + &self, + _engine_state: &EngineState, + _stack: &mut Stack, + call: &Call, + input: PipelineData, + ) -> Result { + run_with_function(call, input, maximum) + } + + fn examples(&self) -> Vec { + vec![Example { + description: "Find the maximum of list of numbers", + example: "[-50 100 25] | math max", + result: Some(Value::test_int(100)), + }] + } +} + +pub fn maximum(values: &[Value], head: &Span) -> Result { + let max_func = reducer_for(Reduce::Maximum); + max_func(Value::nothing(), values.to_vec(), *head) +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_examples() { + use crate::test_examples; + + test_examples(SubCommand {}) + } +} diff --git a/crates/nu-command/src/math/min.rs b/crates/nu-command/src/math/min.rs new file mode 100644 index 0000000000..b232d13074 --- /dev/null +++ b/crates/nu-command/src/math/min.rs @@ -0,0 +1,57 @@ +use crate::math::reducers::{reducer_for, Reduce}; +use crate::math::utils::run_with_function; +use nu_protocol::ast::Call; +use nu_protocol::engine::{Command, EngineState, Stack}; +use nu_protocol::{Example, PipelineData, ShellError, Signature, Span, Value}; + +#[derive(Clone)] +pub struct SubCommand; + +impl Command for SubCommand { + fn name(&self) -> &str { + "math min" + } + + fn signature(&self) -> Signature { + Signature::build("math min") + } + + fn usage(&self) -> &str { + "Finds the minimum within a list of numbers or tables" + } + + fn run( + &self, + _engine_state: &EngineState, + _stack: &mut Stack, + call: &Call, + input: PipelineData, + ) -> Result { + run_with_function(call, input, minimum) + } + + fn examples(&self) -> Vec { + vec![Example { + description: "Get the minimum of a list of numbers", + example: "[-50 100 25] | math min", + result: Some(Value::test_int(-50)), + }] + } +} + +pub fn minimum(values: &[Value], head: &Span) -> Result { + let min_func = reducer_for(Reduce::Minimum); + min_func(Value::nothing(), values.to_vec(), *head) +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_examples() { + use crate::test_examples; + + test_examples(SubCommand {}) + } +} diff --git a/crates/nu-command/src/math/mod.rs b/crates/nu-command/src/math/mod.rs index c3f4a42934..66eff72d82 100644 --- a/crates/nu-command/src/math/mod.rs +++ b/crates/nu-command/src/math/mod.rs @@ -1,9 +1,21 @@ mod abs; mod avg; pub mod command; +mod max; +mod min; +mod product; mod reducers; +mod round; +mod sqrt; +mod sum; mod utils; pub use abs::SubCommand as MathAbs; pub use avg::SubCommand as MathAvg; pub use command::MathCommand as Math; +pub use max::SubCommand as MathMax; +pub use min::SubCommand as MathMin; +pub use product::SubCommand as MathProduct; +pub use round::SubCommand as MathRound; +pub use sqrt::SubCommand as MathSqrt; +pub use sum::SubCommand as MathSum; diff --git a/crates/nu-command/src/math/product.rs b/crates/nu-command/src/math/product.rs new file mode 100644 index 0000000000..150f0fff79 --- /dev/null +++ b/crates/nu-command/src/math/product.rs @@ -0,0 +1,58 @@ +use crate::math::reducers::{reducer_for, Reduce}; +use crate::math::utils::run_with_function; +use nu_protocol::ast::Call; +use nu_protocol::engine::{Command, EngineState, Stack}; +use nu_protocol::{Example, PipelineData, ShellError, Signature, Span, Value}; + +#[derive(Clone)] +pub struct SubCommand; + +impl Command for SubCommand { + fn name(&self) -> &str { + "math product" + } + + fn signature(&self) -> Signature { + Signature::build("math product") + } + + fn usage(&self) -> &str { + "Finds the product of a list of numbers or tables" + } + + fn run( + &self, + _engine_state: &EngineState, + _stack: &mut Stack, + call: &Call, + input: PipelineData, + ) -> Result { + run_with_function(call, input, product) + } + + fn examples(&self) -> Vec { + vec![Example { + description: "Get the product of a list of numbers", + example: "[2 3 3 4] | math product", + result: Some(Value::test_int(72)), + }] + } +} + +/// Calculate product of given values +pub fn product(values: &[Value], head: &Span) -> Result { + let product_func = reducer_for(Reduce::Product); + product_func(Value::nothing(), values.to_vec(), *head) +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_examples() { + use crate::test_examples; + + test_examples(SubCommand {}) + } +} diff --git a/crates/nu-command/src/math/reducers.rs b/crates/nu-command/src/math/reducers.rs index 2339fd97f8..400b2baa0c 100644 --- a/crates/nu-command/src/math/reducers.rs +++ b/crates/nu-command/src/math/reducers.rs @@ -1,19 +1,75 @@ use nu_protocol::{ShellError, Span, Value}; +use std::cmp::Ordering; #[allow(dead_code)] pub enum Reduce { Summation, + Product, + Minimum, + Maximum, } -pub fn reducer_for( - command: Reduce, -) -> Box) -> Result + Send + Sync + 'static> { +pub type ReducerFunction = + Box, Span) -> Result + Send + Sync + 'static>; + +pub fn reducer_for(command: Reduce) -> ReducerFunction { match command { - Reduce::Summation => Box::new(|_, values| sum(values)), + Reduce::Summation => Box::new(|_, values, head| sum(values, head)), + Reduce::Product => Box::new(|_, values, head| product(values, head)), + Reduce::Minimum => Box::new(|_, values, head| min(values, head)), + Reduce::Maximum => Box::new(|_, values, head| max(values, head)), } } -pub fn sum(data: Vec) -> Result { +pub fn max(data: Vec, head: Span) -> Result { + let mut biggest = data + .first() + .ok_or_else(|| ShellError::UnsupportedInput("Empty input".to_string(), Span::unknown()))? + .clone(); + + for value in &data { + if let Some(result) = value.partial_cmp(&biggest) { + if result == Ordering::Greater { + biggest = value.clone(); + } + } else { + return Err(ShellError::OperatorMismatch { + op_span: head, + lhs_ty: biggest.get_type(), + lhs_span: biggest.span()?, + rhs_ty: value.get_type(), + rhs_span: value.span()?, + }); + } + } + Ok(biggest) +} + +pub fn min(data: Vec, head: Span) -> Result { + let mut smallest = data + .first() + .ok_or_else(|| ShellError::UnsupportedInput("Empty input".to_string(), Span::unknown()))? + .clone(); + + for value in &data { + if let Some(result) = value.partial_cmp(&smallest) { + if result == Ordering::Less { + smallest = value.clone(); + } + } else { + return Err(ShellError::OperatorMismatch { + op_span: head, + lhs_ty: smallest.get_type(), + lhs_span: smallest.span()?, + rhs_ty: value.get_type(), + rhs_span: value.span()?, + }); + } + } + Ok(smallest) +} + +pub fn sum(data: Vec, head: Span) -> Result { let initial_value = data.get(0); let mut acc = match initial_value { @@ -42,7 +98,7 @@ pub fn sum(data: Vec) -> Result { | Value::Float { .. } | Value::Filesize { .. } | Value::Duration { .. } => { - let new_value = acc.add(acc.span().unwrap_or_else(|_| Span::unknown()), value); + let new_value = acc.add(head, value); if new_value.is_err() { return new_value; } @@ -58,3 +114,39 @@ pub fn sum(data: Vec) -> Result { } Ok(acc) } + +pub fn product(data: Vec, head: Span) -> Result { + let initial_value = data.get(0); + + let mut acc = match initial_value { + Some(Value::Int { span, .. }) | Some(Value::Float { span, .. }) => Ok(Value::Int { + val: 1, + span: *span, + }), + None => Err(ShellError::UnsupportedInput( + "Empty input".to_string(), + Span::unknown(), + )), + _ => Ok(Value::nothing()), + }?; + + for value in &data { + match value { + Value::Int { .. } | Value::Float { .. } => { + let new_value = acc.mul(head, value); + if new_value.is_err() { + return new_value; + } + acc = new_value.expect("This should never trigger") + } + other => { + return Err(ShellError::UnsupportedInput( + "Attempted to compute the product of a value that cannot be multiplied" + .to_string(), + other.span().unwrap_or_else(|_| Span::unknown()), + )); + } + } + } + Ok(acc) +} diff --git a/crates/nu-command/src/math/round.rs b/crates/nu-command/src/math/round.rs new file mode 100644 index 0000000000..b83c1f8ee1 --- /dev/null +++ b/crates/nu-command/src/math/round.rs @@ -0,0 +1,110 @@ +use nu_engine::CallExt; +use nu_protocol::ast::Call; +use nu_protocol::engine::{Command, EngineState, Stack}; +use nu_protocol::{Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Value}; + +#[derive(Clone)] +pub struct SubCommand; + +impl Command for SubCommand { + fn name(&self) -> &str { + "math round" + } + + fn signature(&self) -> Signature { + Signature::build("math round").named( + "precision", + SyntaxShape::Number, + "digits of precision", + Some('p'), + ) + } + + fn usage(&self) -> &str { + "Applies the round function to a list of numbers" + } + + fn run( + &self, + engine_state: &EngineState, + stack: &mut Stack, + call: &Call, + input: PipelineData, + ) -> Result { + let precision_param: Option = call.get_flag(engine_state, stack, "precision")?; + let head = call.head; + input.map( + move |value| operate(value, head, precision_param), + engine_state.ctrlc.clone(), + ) + } + + fn examples(&self) -> Vec { + vec![ + Example { + description: "Apply the round function to a list of numbers", + example: "[1.5 2.3 -3.1] | math round", + result: Some(Value::List { + vals: vec![Value::test_int(2), Value::test_int(2), Value::test_int(-3)], + span: Span::unknown(), + }), + }, + Example { + description: "Apply the round function with precision specified", + example: "[1.555 2.333 -3.111] | math round -p 2", + result: Some(Value::List { + vals: vec![ + Value::Float { + val: 1.56, + span: Span::unknown(), + }, + Value::Float { + val: 2.33, + span: Span::unknown(), + }, + Value::Float { + val: -3.11, + span: Span::unknown(), + }, + ], + span: Span::unknown(), + }), + }, + ] + } +} + +fn operate(value: Value, head: Span, precision: Option) -> Value { + match value { + Value::Float { val, span } => match precision { + Some(precision_number) => Value::Float { + val: ((val * ((10_f64).powf(precision_number as f64))).round() + / (10_f64).powf(precision_number as f64)), + span, + }, + None => Value::Int { + val: val.round() as i64, + span, + }, + }, + Value::Int { .. } => value, + other => Value::Error { + error: ShellError::UnsupportedInput( + String::from("Only numerical values are supported"), + other.span().unwrap_or(head), + ), + }, + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_examples() { + use crate::test_examples; + + test_examples(SubCommand {}) + } +} diff --git a/crates/nu-command/src/math/sqrt.rs b/crates/nu-command/src/math/sqrt.rs new file mode 100644 index 0000000000..70ce9492f1 --- /dev/null +++ b/crates/nu-command/src/math/sqrt.rs @@ -0,0 +1,91 @@ +use nu_protocol::ast::Call; +use nu_protocol::engine::{Command, EngineState, Stack}; +use nu_protocol::{Example, PipelineData, ShellError, Signature, Span, Value}; + +#[derive(Clone)] +pub struct SubCommand; + +impl Command for SubCommand { + fn name(&self) -> &str { + "math sqrt" + } + + fn signature(&self) -> Signature { + Signature::build("math sqrt") + } + + fn usage(&self) -> &str { + "Applies the square root function to a list of numbers" + } + + fn run( + &self, + engine_state: &EngineState, + _stack: &mut Stack, + call: &Call, + input: PipelineData, + ) -> Result { + let head = call.head; + input.map( + move |value| operate(value, head), + engine_state.ctrlc.clone(), + ) + } + + fn examples(&self) -> Vec { + vec![Example { + description: "Apply the square root function to a list of numbers", + example: "[9 16] | math sqrt", + result: Some(Value::List { + vals: vec![Value::test_int(3), Value::test_int(4)], + span: Span::unknown(), + }), + }] + } +} + +fn operate(value: Value, head: Span) -> Value { + match value { + Value::Int { val, span } => { + let squared = (val as f64).sqrt(); + if squared.is_nan() { + return error_negative_sqrt(span); + } + Value::Float { val: squared, span } + } + Value::Float { val, span } => { + let squared = val.sqrt(); + if squared.is_nan() { + return error_negative_sqrt(span); + } + Value::Float { val: squared, span } + } + other => Value::Error { + error: ShellError::UnsupportedInput( + String::from("Only numerical values are supported"), + other.span().unwrap_or(head), + ), + }, + } +} + +fn error_negative_sqrt(span: Span) -> Value { + Value::Error { + error: ShellError::UnsupportedInput( + String::from("Can't square root a negative number"), + span, + ), + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_examples() { + use crate::test_examples; + + test_examples(SubCommand {}) + } +} diff --git a/crates/nu-command/src/math/sum.rs b/crates/nu-command/src/math/sum.rs new file mode 100644 index 0000000000..c749d09d71 --- /dev/null +++ b/crates/nu-command/src/math/sum.rs @@ -0,0 +1,64 @@ +use crate::math::reducers::{reducer_for, Reduce}; +use crate::math::utils::run_with_function; +use nu_protocol::ast::Call; +use nu_protocol::engine::{Command, EngineState, Stack}; +use nu_protocol::{Example, PipelineData, ShellError, Signature, Span, Value}; + +#[derive(Clone)] +pub struct SubCommand; + +impl Command for SubCommand { + fn name(&self) -> &str { + "math sum" + } + + fn signature(&self) -> Signature { + Signature::build("math sum") + } + + fn usage(&self) -> &str { + "Finds the sum of a list of numbers or tables" + } + + fn run( + &self, + _engine_state: &EngineState, + _stack: &mut Stack, + call: &Call, + input: PipelineData, + ) -> Result { + run_with_function(call, input, summation) + } + + fn examples(&self) -> Vec { + vec![ + Example { + description: "Sum a list of numbers", + example: "[1 2 3] | math sum", + result: Some(Value::test_int(6)), + }, + Example { + description: "Get the disk usage for the current directory", + example: "ls | get size | math sum", + result: None, + }, + ] + } +} + +pub fn summation(values: &[Value], head: &Span) -> Result { + let sum_func = reducer_for(Reduce::Summation); + sum_func(Value::nothing(), values.to_vec(), *head) +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_examples() { + use crate::test_examples; + + test_examples(SubCommand {}) + } +} diff --git a/crates/nu-engine/src/eval.rs b/crates/nu-engine/src/eval.rs index 396eab3839..9b000df58e 100644 --- a/crates/nu-engine/src/eval.rs +++ b/crates/nu-engine/src/eval.rs @@ -371,12 +371,12 @@ pub fn eval_block( } pub fn eval_variable( - _engine_state: &EngineState, + engine_state: &EngineState, stack: &Stack, var_id: VarId, span: Span, ) -> Result { - if var_id == 0 { + if var_id == nu_protocol::NU_VARIABLE_ID { // $nu let mut output_cols = vec![]; let mut output_vals = vec![]; @@ -425,6 +425,71 @@ pub fn eval_variable( output_vals.push(Value::String { val: cwd, span }) } + Ok(Value::Record { + cols: output_cols, + vals: output_vals, + span, + }) + } else if var_id == nu_protocol::SCOPE_VARIABLE_ID { + let mut output_cols = vec![]; + let mut output_vals = vec![]; + + let mut vars = vec![]; + let mut commands = vec![]; + let mut aliases = vec![]; + let mut modules = vec![]; + + for frame in &engine_state.scope { + for var in &frame.vars { + vars.push(Value::String { + val: String::from_utf8_lossy(var.0).to_string(), + span, + }); + } + + for command in &frame.decls { + commands.push(Value::String { + val: String::from_utf8_lossy(command.0).to_string(), + span, + }); + } + + for alias in &frame.aliases { + aliases.push(Value::String { + val: String::from_utf8_lossy(alias.0).to_string(), + span, + }); + } + + for module in &frame.modules { + modules.push(Value::String { + val: String::from_utf8_lossy(module.0).to_string(), + span, + }); + } + } + + output_cols.push("vars".to_string()); + output_vals.push(Value::List { vals: vars, span }); + + output_cols.push("commands".to_string()); + output_vals.push(Value::List { + vals: commands, + span, + }); + + output_cols.push("aliases".to_string()); + output_vals.push(Value::List { + vals: aliases, + span, + }); + + output_cols.push("modules".to_string()); + output_vals.push(Value::List { + vals: modules, + span, + }); + Ok(Value::Record { cols: output_cols, vals: output_vals, diff --git a/crates/nu-parser/Cargo.toml b/crates/nu-parser/Cargo.toml index 96dd9444a5..2dc4d6dc27 100644 --- a/crates/nu-parser/Cargo.toml +++ b/crates/nu-parser/Cargo.toml @@ -7,3 +7,4 @@ edition = "2018" miette = "3.0.0" thiserror = "1.0.29" nu-protocol = { path = "../nu-protocol"} +nu-plugin = { path = "../nu-plugin"} diff --git a/crates/nu-parser/src/errors.rs b/crates/nu-parser/src/errors.rs index 36412e9a7b..e3e44b793f 100644 --- a/crates/nu-parser/src/errors.rs +++ b/crates/nu-parser/src/errors.rs @@ -93,9 +93,9 @@ pub enum ParseError { )] UnknownCommand(#[label = "unknown command"] Span), - #[error("Non-UTF8 code.")] + #[error("Non-UTF8 string.")] #[diagnostic(code(nu::parser::non_utf8), url(docsrs))] - NonUtf8(#[label = "non-UTF8 code"] Span), + NonUtf8(#[label = "non-UTF8 string"] Span), #[error("The `{0}` command doesn't have flag `{1}`.")] #[diagnostic(code(nu::parser::unknown_flag), url(docsrs))] @@ -171,7 +171,19 @@ pub enum ParseError { #[diagnostic(code(nu::parser::missing_import_pattern), url(docsrs))] MissingImportPattern(#[label = "needs an import pattern"] Span), + #[error("Wrong import pattern structure.")] + #[diagnostic(code(nu::parser::missing_import_pattern), url(docsrs))] + WrongImportPattern(#[label = "invalid import pattern structure"] Span), + #[error("Module export not found.")] #[diagnostic(code(nu::parser::export_not_found), url(docsrs))] ExportNotFound(#[label = "could not find imports"] Span), + + #[error("File not found")] + #[diagnostic(code(nu::parser::export_not_found), url(docsrs))] + FileNotFound(String), + + #[error("Plugin error")] + #[diagnostic(code(nu::parser::export_not_found), url(docsrs))] + PluginError(String), } diff --git a/crates/nu-parser/src/lib.rs b/crates/nu-parser/src/lib.rs index 8fc5e559c8..dc5534c9e6 100644 --- a/crates/nu-parser/src/lib.rs +++ b/crates/nu-parser/src/lib.rs @@ -11,6 +11,6 @@ pub use flatten::{flatten_block, FlatShape}; pub use lex::{lex, Token, TokenContents}; pub use lite_parse::{lite_parse, LiteBlock}; pub use parse_keywords::{ - parse_alias, parse_def, parse_def_predecl, parse_let, parse_module, parse_use, + parse_alias, parse_def, parse_def_predecl, parse_let, parse_module, parse_plugin, parse_use, }; pub use parser::{find_captures_in_expr, parse, Import, VarDecl}; diff --git a/crates/nu-parser/src/parse_keywords.rs b/crates/nu-parser/src/parse_keywords.rs index b086ed223f..200fb9d7c5 100644 --- a/crates/nu-parser/src/parse_keywords.rs +++ b/crates/nu-parser/src/parse_keywords.rs @@ -1,5 +1,6 @@ +use nu_plugin::plugin::{get_signature, PluginDeclaration}; use nu_protocol::{ - ast::{Block, Call, Expr, Expression, ImportPatternMember, Pipeline, Statement}, + ast::{Block, Call, Expr, Expression, ImportPattern, ImportPatternMember, Pipeline, Statement}, engine::StateWorkingSet, span, DeclId, Span, SyntaxShape, Type, }; @@ -218,8 +219,6 @@ pub fn parse_alias( let replacement = spans[3..].to_vec(); - //println!("{:?} {:?}", alias_name, replacement); - working_set.add_alias(alias_name, replacement); } @@ -309,6 +308,88 @@ pub fn parse_export( } } +pub fn parse_module_block( + working_set: &mut StateWorkingSet, + span: Span, +) -> (Block, Option) { + let mut error = None; + + working_set.enter_scope(); + + let source = working_set.get_span_contents(span); + + let (output, err) = lex(source, span.start, &[], &[]); + error = error.or(err); + + let (output, err) = lite_parse(&output); + error = error.or(err); + + for pipeline in &output.block { + if pipeline.commands.len() == 1 { + parse_def_predecl(working_set, &pipeline.commands[0].parts); + } + } + + let mut exports: Vec<(Vec, DeclId)> = vec![]; + + let block: Block = output + .block + .iter() + .map(|pipeline| { + if pipeline.commands.len() == 1 { + // this one here is doing parse_statement() equivalent + // let (stmt, err) = parse_statement(working_set, &pipeline.commands[0].parts); + let name = working_set.get_span_contents(pipeline.commands[0].parts[0]); + + let (stmt, err) = match name { + b"def" => { + let (stmt, err) = parse_def(working_set, &pipeline.commands[0].parts); + + (stmt, err) + } + b"export" => { + let (stmt, err) = parse_export(working_set, &pipeline.commands[0].parts); + + if err.is_none() { + let decl_name = + // parts[2] is safe since it's checked in parse_export already + working_set.get_span_contents(pipeline.commands[0].parts[2]); + + let decl_id = working_set + .find_decl(decl_name) + .expect("internal error: failed to find added declaration"); + + exports.push((decl_name.into(), decl_id)); + } + + (stmt, err) + } + _ => ( + garbage_statement(&pipeline.commands[0].parts), + Some(ParseError::Expected( + "def or export keyword".into(), + pipeline.commands[0].parts[0], + )), + ), + }; + + if error.is_none() { + error = err; + } + + stmt + } else { + error = Some(ParseError::Expected("not a pipeline".into(), span)); + garbage_statement(&[span]) + } + }) + .into(); + + working_set.exit_scope(); + + (block.with_exports(exports), error) +} + pub fn parse_module( working_set: &mut StateWorkingSet, spans: &[Span], @@ -359,91 +440,9 @@ pub fn parse_module( let block_span = Span { start, end }; - let source = working_set.get_span_contents(block_span); - - let (output, err) = lex(source, start, &[], &[]); + let (block, err) = parse_module_block(working_set, block_span); error = error.or(err); - working_set.enter_scope(); - - // Do we need block parameters? - - let (output, err) = lite_parse(&output); - error = error.or(err); - - // We probably don't need $it - - // we're doing parse_block() equivalent - // let (mut output, err) = parse_block(working_set, &output, false); - - for pipeline in &output.block { - if pipeline.commands.len() == 1 { - parse_def_predecl(working_set, &pipeline.commands[0].parts); - } - } - - let mut exports: Vec<(Vec, DeclId)> = vec![]; - - let block: Block = output - .block - .iter() - .map(|pipeline| { - if pipeline.commands.len() == 1 { - // this one here is doing parse_statement() equivalent - // let (stmt, err) = parse_statement(working_set, &pipeline.commands[0].parts); - let name = working_set.get_span_contents(pipeline.commands[0].parts[0]); - - let (stmt, err) = match name { - // TODO: Here we can add other stuff that's allowed for modules - b"def" => { - let (stmt, err) = parse_def(working_set, &pipeline.commands[0].parts); - - (stmt, err) - } - b"export" => { - let (stmt, err) = - parse_export(working_set, &pipeline.commands[0].parts); - - if err.is_none() { - let decl_name = - // parts[2] is safe since it's checked in parse_def already - working_set.get_span_contents(pipeline.commands[0].parts[2]); - - let decl_id = working_set - .find_decl(decl_name) - .expect("internal error: failed to find added declaration"); - - exports.push((decl_name.into(), decl_id)); - } - - (stmt, err) - } - _ => ( - garbage_statement(&pipeline.commands[0].parts), - Some(ParseError::Expected( - // TODO: Fill in more keywords as they come - "def or export keyword".into(), - pipeline.commands[0].parts[0], - )), - ), - }; - - if error.is_none() { - error = err; - } - - stmt - } else { - error = Some(ParseError::Expected("not a pipeline".into(), block_span)); - garbage_statement(spans) - } - }) - .into(); - - let block = block.with_exports(exports); - - working_set.exit_scope(); - let block_id = working_set.add_module(&module_name, block); let block_expr = Expression { @@ -492,27 +491,76 @@ pub fn parse_use( let bytes = working_set.get_span_contents(spans[0]); if bytes == b"use" && spans.len() >= 2 { - let (module_name_expr, err) = parse_string(working_set, spans[1]); + let mut import_pattern_exprs: Vec = vec![]; + for span in spans[1..].iter() { + let (expr, err) = parse_string(working_set, *span); + import_pattern_exprs.push(expr); + error = error.or(err); + } + + // TODO: Add checking for importing too long import patterns, e.g.: + // > use spam foo non existent names here do not throw error + let (import_pattern, err) = parse_import_pattern(working_set, &spans[1..]); error = error.or(err); - let (import_pattern, err) = parse_import_pattern(working_set, spans[1]); - error = error.or(err); + let (import_pattern, exports) = + if let Some(block_id) = working_set.find_module(&import_pattern.head) { + ( + import_pattern, + working_set.get_block(block_id).exports.clone(), + ) + } else { + // TODO: Do not close over when loading module from file + // It could be a file + if let Ok(module_filename) = String::from_utf8(import_pattern.head) { + let module_path = Path::new(&module_filename); + let module_name = if let Some(stem) = module_path.file_stem() { + stem.to_string_lossy().to_string() + } else { + return ( + garbage_statement(spans), + Some(ParseError::ModuleNotFound(spans[1])), + ); + }; - let exports = if let Some(block_id) = working_set.find_module(&import_pattern.head) { - working_set.get_block(block_id).exports.clone() - } else { - return ( - garbage_statement(spans), - Some(ParseError::ModuleNotFound(spans[1])), - ); - }; + if let Ok(contents) = std::fs::read(module_path) { + let span_start = working_set.next_span_start(); + working_set.add_file(module_filename, &contents); + let span_end = working_set.next_span_start(); + + let (block, err) = + parse_module_block(working_set, Span::new(span_start, span_end)); + error = error.or(err); + + let block_id = working_set.add_module(&module_name, block); + + ( + ImportPattern { + head: module_name.into(), + members: import_pattern.members, + }, + working_set.get_block(block_id).exports.clone(), + ) + } else { + return ( + garbage_statement(spans), + Some(ParseError::ModuleNotFound(spans[1])), + ); + } + } else { + return ( + garbage_statement(spans), + Some(ParseError::NonUtf8(spans[1])), + ); + } + }; let exports = if import_pattern.members.is_empty() { exports .into_iter() .map(|(name, id)| { let mut new_name = import_pattern.head.to_vec(); - new_name.push(b'.'); + new_name.push(b' '); new_name.extend(&name); (new_name, id) }) @@ -562,7 +610,7 @@ pub fn parse_use( let call = Box::new(Call { head: spans[0], decl_id: use_decl_id, - positional: vec![module_name_expr], + positional: import_pattern_exprs, named: vec![], }); @@ -597,20 +645,23 @@ pub fn parse_hide( let (name_expr, err) = parse_string(working_set, spans[1]); error = error.or(err); - let (import_pattern, err) = parse_import_pattern(working_set, spans[1]); + let (import_pattern, err) = parse_import_pattern(working_set, &spans[1..]); error = error.or(err); - let exported_names: Vec> = + let (is_module, exported_names): (bool, Vec>) = if let Some(block_id) = working_set.find_module(&import_pattern.head) { - working_set - .get_block(block_id) - .exports - .iter() - .map(|(name, _)| name.clone()) - .collect() + ( + true, + working_set + .get_block(block_id) + .exports + .iter() + .map(|(name, _)| name.clone()) + .collect(), + ) } else if import_pattern.members.is_empty() { // The pattern head can be e.g. a function name, not just a module - vec![import_pattern.head.clone()] + (false, vec![import_pattern.head.clone()]) } else { return ( garbage_statement(spans), @@ -620,14 +671,26 @@ pub fn parse_hide( // This kind of inverts the import pattern matching found in parse_use() let names_to_hide = if import_pattern.members.is_empty() { - exported_names + if is_module { + exported_names + .into_iter() + .map(|name| { + let mut new_name = import_pattern.head.to_vec(); + new_name.push(b' '); + new_name.extend(&name); + new_name + }) + .collect() + } else { + exported_names + } } else { match &import_pattern.members[0] { ImportPatternMember::Glob { .. } => exported_names .into_iter() .map(|name| { let mut new_name = import_pattern.head.to_vec(); - new_name.push(b'.'); + new_name.push(b' '); new_name.extend(&name); new_name }) @@ -638,7 +701,7 @@ pub fn parse_hide( .filter(|n| n == name) .map(|n| { let mut new_name = import_pattern.head.to_vec(); - new_name.push(b'.'); + new_name.push(b' '); new_name.extend(&n); new_name }) @@ -659,7 +722,7 @@ pub fn parse_hide( .filter_map(|n| if n == name { Some(n.clone()) } else { None }) .map(|n| { let mut new_name = import_pattern.head.to_vec(); - new_name.push(b'.'); + new_name.push(b' '); new_name.extend(n); new_name }) @@ -678,6 +741,8 @@ pub fn parse_hide( }; for name in names_to_hide { + // TODO: `use spam; use spam foo; hide foo` will hide both `foo` and `spam foo` since + // they point to the same DeclId. Do we want to keep it that way? if working_set.hide_decl(&name).is_none() { error = error.or_else(|| Some(ParseError::UnknownCommand(spans[1]))); } @@ -833,6 +898,11 @@ pub fn parse_source( ); } } + } else { + return ( + garbage_statement(spans), + Some(ParseError::NonUtf8(spans[1])), + ); } } return ( @@ -854,3 +924,87 @@ pub fn parse_source( )), ) } + +pub fn parse_plugin( + working_set: &mut StateWorkingSet, + spans: &[Span], +) -> (Statement, Option) { + let name = working_set.get_span_contents(spans[0]); + + if name != b"register" { + return ( + garbage_statement(spans), + Some(ParseError::UnknownState( + "internal error: Wrong call name for parse plugin function".into(), + span(spans), + )), + ); + } + + if let Some(decl_id) = working_set.find_decl(b"register") { + let (call, call_span, mut err) = + parse_internal_call(working_set, spans[0], &spans[1..], decl_id); + + let error = { + match spans.len() { + 1 => Some(ParseError::MissingPositional( + "plugin location".into(), + spans[0], + )), + 2 => { + let name_expr = working_set.get_span_contents(spans[1]); + if let Ok(filename) = String::from_utf8(name_expr.to_vec()) { + let source_file = Path::new(&filename); + + if source_file.exists() & source_file.is_file() { + // get signature from plugin + match get_signature(source_file) { + Err(err) => Some(ParseError::PluginError(format!("{}", err))), + Ok(signature) => { + // create plugin command declaration (need struct impl Command) + // store declaration in working set + let plugin_decl = PluginDeclaration::new(filename, signature); + working_set.add_decl(Box::new(plugin_decl)); + + None + } + } + } else { + Some(ParseError::FileNotFound(filename)) + } + } else { + Some(ParseError::NonUtf8(spans[1])) + } + } + _ => { + let span = spans[2..].iter().fold(spans[2], |acc, next| Span { + start: acc.start, + end: next.end, + }); + + Some(ParseError::ExtraPositional(span)) + } + } + }; + + err = error.or(err); + + ( + Statement::Pipeline(Pipeline::from_vec(vec![Expression { + expr: Expr::Call(call), + span: call_span, + ty: Type::Unknown, + custom_completion: None, + }])), + err, + ) + } else { + ( + garbage_statement(spans), + Some(ParseError::UnknownState( + "internal error: Register declaration not found".into(), + span(spans), + )), + ) + } +} diff --git a/crates/nu-parser/src/parser.rs b/crates/nu-parser/src/parser.rs index 14a437d8e0..25be7f6d79 100644 --- a/crates/nu-parser/src/parser.rs +++ b/crates/nu-parser/src/parser.rs @@ -15,7 +15,8 @@ use nu_protocol::{ }; use crate::parse_keywords::{ - parse_alias, parse_def, parse_def_predecl, parse_hide, parse_let, parse_module, parse_use, + parse_alias, parse_def, parse_def_predecl, parse_hide, parse_let, parse_module, parse_plugin, + parse_use, }; #[derive(Debug, Clone)] @@ -39,6 +40,26 @@ fn is_identifier_byte(b: u8) -> bool { b != b'.' && b != b'[' && b != b'(' && b != b'{' } +fn is_math_expression_byte(b: u8) -> bool { + b == b'0' + || b == b'1' + || b == b'2' + || b == b'3' + || b == b'4' + || b == b'5' + || b == b'6' + || b == b'7' + || b == b'8' + || b == b'9' + || b == b'(' + || b == b'{' + || b == b'[' + || b == b'$' + || b == b'"' + || b == b'\'' + || b == b'-' +} + fn is_identifier(bytes: &[u8]) -> bool { bytes.iter().all(|x| is_identifier_byte(*x)) } @@ -595,7 +616,16 @@ pub fn parse_call( spans: &[Span], expand_aliases: bool, ) -> (Expression, Option) { - // assume spans.len() > 0? + if spans.is_empty() { + return ( + garbage(Span::unknown()), + Some(ParseError::UnknownState( + "Encountered command with zero spans".into(), + span(spans), + )), + ); + } + let mut pos = 0; let mut shorthand = vec![]; @@ -613,104 +643,82 @@ pub fn parse_call( if pos == spans.len() { return ( - Expression::garbage(span(spans)), + garbage(span(spans)), Some(ParseError::UnknownCommand(spans[0])), ); } - let name = working_set.get_span_contents(spans[pos]); - let cmd_start = pos; + let mut name_spans = vec![]; - if expand_aliases { - if let Some(expansion) = working_set.find_alias(name) { - let orig_span = spans[pos]; - //let mut spans = spans.to_vec(); - let mut new_spans: Vec = vec![]; - new_spans.extend(&spans[0..pos]); - new_spans.extend(expansion); - if spans.len() > pos { - new_spans.extend(&spans[(pos + 1)..]); - } + for word_span in spans[cmd_start..].iter() { + // Find the longest group of words that could form a command + let bytes = working_set.get_span_contents(*word_span); - let (result, err) = parse_expression(working_set, &new_spans, false); + if is_math_expression_byte(bytes[0]) { + break; + } - let expression = match result { - Expression { - expr: Expr::Call(mut call), - span, - ty, - custom_completion: None, - } => { - call.head = orig_span; + name_spans.push(*word_span); + + let name = working_set.get_span_contents(span(&name_spans)); + + if expand_aliases { + // If the word is an alias, expand it and re-parse the expression + if let Some(expansion) = working_set.find_alias(name) { + let orig_span = spans[pos]; + let mut new_spans: Vec = vec![]; + new_spans.extend(&spans[0..pos]); + new_spans.extend(expansion); + if spans.len() > pos { + new_spans.extend(&spans[(pos + 1)..]); + } + + let (result, err) = parse_expression(working_set, &new_spans, false); + + let expression = match result { Expression { - expr: Expr::Call(call), + expr: Expr::Call(mut call), span, ty, custom_completion: None, - } - } - x => x, - }; - - return (expression, err); - } - } - - pos += 1; - - if let Some(mut decl_id) = working_set.find_decl(name) { - let mut name = name.to_vec(); - while pos < spans.len() { - // look to see if it's a subcommand - let mut new_name = name.to_vec(); - new_name.push(b' '); - new_name.extend(working_set.get_span_contents(spans[pos])); - - if expand_aliases { - if let Some(expansion) = working_set.find_alias(&new_name) { - let orig_span = span(&spans[cmd_start..pos + 1]); - //let mut spans = spans.to_vec(); - let mut new_spans: Vec = vec![]; - new_spans.extend(&spans[0..cmd_start]); - new_spans.extend(expansion); - if spans.len() > pos { - new_spans.extend(&spans[(pos + 1)..]); - } - - let (result, err) = parse_expression(working_set, &new_spans, false); - - let expression = match result { + } => { + call.head = orig_span; Expression { - expr: Expr::Call(mut call), + expr: Expr::Call(call), span, ty, custom_completion: None, - } => { - call.head = orig_span; - Expression { - expr: Expr::Call(call), - span, - ty, - custom_completion: None, - } } - x => x, - }; + } + x => x, + }; - return (expression, err); - } + return (expression, err); } - - if let Some(did) = working_set.find_decl(&new_name) { - decl_id = did; - } else { - break; - } - name = new_name; - pos += 1; } + pos += 1; + } + + let name = working_set.get_span_contents(span(&name_spans)); + let mut maybe_decl_id = working_set.find_decl(name); + + while maybe_decl_id.is_none() { + // Find the longest command match + if name_spans.len() <= 1 { + // Keep the first word even if it does not match -- could be external command + break; + } + + name_spans.pop(); + pos -= 1; + + let name = working_set.get_span_contents(span(&name_spans)); + maybe_decl_id = working_set.find_decl(name); + } + + if let Some(decl_id) = maybe_decl_id { // Before the internal parsing we check if there is no let or alias declarations // that are missing their name, e.g.: let = 1 or alias = 2 if spans.len() > 1 { @@ -718,7 +726,7 @@ pub fn parse_call( if test_equal == [b'='] { return ( - garbage(Span::new(0, 0)), + garbage(Span::unknown()), Some(ParseError::UnknownState( "Incomplete statement".into(), span(spans), @@ -728,8 +736,12 @@ pub fn parse_call( } // parse internal command - let (call, _, err) = - parse_internal_call(working_set, span(&spans[0..pos]), &spans[pos..], decl_id); + let (call, _, err) = parse_internal_call( + working_set, + span(&spans[cmd_start..pos]), + &spans[pos..], + decl_id, + ); ( Expression { expr: Expr::Call(call), @@ -748,6 +760,8 @@ pub fn parse_call( return (range_expr, range_err); } } + + // Otherwise, try external command parse_external_call(working_set, spans) } } @@ -1185,7 +1199,17 @@ pub fn parse_variable_expr( } else if contents == b"$nu" { return ( Expression { - expr: Expr::Var(0), + expr: Expr::Var(nu_protocol::NU_VARIABLE_ID), + span, + ty: Type::Unknown, + custom_completion: None, + }, + None, + ); + } else if contents == b"$scope" { + return ( + Expression { + expr: Expr::Var(nu_protocol::SCOPE_VARIABLE_ID), span, ty: Type::Unknown, custom_completion: None, @@ -1703,40 +1727,36 @@ pub fn parse_type(_working_set: &StateWorkingSet, bytes: &[u8]) -> Type { pub fn parse_import_pattern( working_set: &mut StateWorkingSet, - span: Span, + spans: &[Span], ) -> (ImportPattern, Option) { - let source = working_set.get_span_contents(span); let mut error = None; - let (tokens, err) = lex(source, span.start, &[], &[b'.']); - error = error.or(err); - - if tokens.is_empty() { + let head = if let Some(head_span) = spans.get(0) { + working_set.get_span_contents(*head_span).to_vec() + } else { return ( ImportPattern { head: vec![], members: vec![], }, - Some(ParseError::MissingImportPattern(span)), + Some(ParseError::WrongImportPattern(span(spans))), ); - } + }; - let head = working_set.get_span_contents(tokens[0].span).to_vec(); - - if let Some(tail) = tokens.get(2) { + if let Some(tail_span) = spans.get(1) { // FIXME: expand this to handle deeper imports once we support module imports - let tail_span = tail.span; - let tail = working_set.get_span_contents(tail.span); + let tail = working_set.get_span_contents(*tail_span); if tail == b"*" { ( ImportPattern { head, - members: vec![ImportPatternMember::Glob { span: tail_span }], + members: vec![ImportPatternMember::Glob { span: *tail_span }], }, error, ) } else if tail.starts_with(b"[") { - let (result, err) = parse_list_expression(working_set, tail_span, &SyntaxShape::String); + let (result, err) = + parse_list_expression(working_set, *tail_span, &SyntaxShape::String); error = error.or(err); let mut output = vec![]; @@ -1773,7 +1793,7 @@ pub fn parse_import_pattern( head, members: vec![ImportPatternMember::Name { name: tail.to_vec(), - span: tail_span, + span: *tail_span, }], }, error, @@ -2945,10 +2965,10 @@ pub fn parse_expression( ) -> (Expression, Option) { let bytes = working_set.get_span_contents(spans[0]); - match bytes[0] { - b'0' | b'1' | b'2' | b'3' | b'4' | b'5' | b'6' | b'7' | b'8' | b'9' | b'(' | b'{' - | b'[' | b'$' | b'"' | b'\'' | b'-' => parse_math_expression(working_set, spans, None), - _ => parse_call(working_set, spans, expand_aliases), + if is_math_expression_byte(bytes[0]) { + parse_math_expression(working_set, spans, None) + } else { + parse_call(working_set, spans, expand_aliases) } } @@ -2987,6 +3007,7 @@ pub fn parse_statement( Some(ParseError::UnexpectedKeyword("export".into(), spans[0])), ), b"hide" => parse_hide(working_set, spans), + b"register" => parse_plugin(working_set, spans), _ => { let (expr, err) = parse_expression(working_set, spans, true); (Statement::Pipeline(Pipeline::from_vec(vec![expr])), err) diff --git a/crates/nu-plugin/Cargo.toml b/crates/nu-plugin/Cargo.toml new file mode 100644 index 0000000000..cb5346eab7 --- /dev/null +++ b/crates/nu-plugin/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "nu-plugin" +version = "0.1.0" +edition = "2018" + +[dependencies] +capnp = "0.14.3" +nu-protocol = { path = "../nu-protocol" } + +[build-dependencies] +capnpc = "0.14.3" + + diff --git a/crates/nu-plugin/schema/plugin.capnp b/crates/nu-plugin/schema/plugin.capnp new file mode 100644 index 0000000000..8992bc0f99 --- /dev/null +++ b/crates/nu-plugin/schema/plugin.capnp @@ -0,0 +1,132 @@ +@0xb299d30dc02d72bc; +# Schema representing all the structs that are used to comunicate with +# the plugins. +# This schema, together with the command capnp proto is used to generate +# the rust file that defines the serialization/deserialization objects +# required to comunicate with the plugins created for nushell +# +# If you modify the schema remember to compile it to generate the corresponding +# rust file and place that file into the main nu-plugin folder. +# After compiling, you may need to run cargo fmt on the file so it passes the CI + +# Generic structs used as helpers for the encoding +struct Option(T) { + union { + none @0 :Void; + some @1 :T; + } +} + +struct Err(T) { + union { + err @0 :Text; + ok @1 :T; + } +} + +struct Map(Key, Value) { + struct Entry { + key @0 :Key; + value @1 :Value; + } + entries @0 :List(Entry); +} + +# Main plugin structures +struct Span { + start @0 :UInt64; + end @1 :UInt64; +} + +# Resulting value from plugin +struct Value { + span @0: Span; + + union { + void @1 :Void; + bool @2 :Bool; + int @3 :Int64; + float @4 :Float64; + string @5 :Text; + list @6 :List(Value); + } +} + +# Structs required to define the plugin signature +struct Signature { + name @0 :Text; + usage @1 :Text; + extraUsage @2 :Text; + requiredPositional @3 :List(Argument); + optionalPositional @4 :List(Argument); + rest @5 :Option(Argument); + named @6 :List(Flag); + isFilter @7 :Bool; +} + +struct Flag { + long @0 :Text; + short @1 :Option(Text); + arg @2 :Shape; + required @3 :Bool; + desc @4 :Text; +} + +struct Argument { + name @0 :Text; + desc @1 :Text; + shape @2 :Shape; +} + +# If we require more complex signatures for the plugins this could be +# changed to a union +enum Shape { + none @0; + any @1; + string @2; + number @3; + int @4; + boolean @5; +} + +# The next structs define the call information sent to th plugin +struct Expression { + union { + garbage @0 :Void; + bool @1 :Bool; + int @2 :Int64; + float @3 :Float64; + string @4 :Text; + list @5 :List(Expression); + # The expression list can be exteded based on the user need + # If a plugin requires something from the expression object, it + # will need to be added to this list + } +} + +struct Call { + head @0: Span; + positional @1 :List(Expression); + named @2 :Map(Text, Option(Expression)); +} + +struct CallInfo { + call @0: Call; + input @1: Value; +} + +# Main communication structs with the plugin +struct PluginCall { + union { + signature @0 :Void; + callInfo @1 :CallInfo; + } +} + +struct PluginResponse { + union { + error @0 :Text; + signature @1 :Signature; + value @2 :Value; + } +} diff --git a/crates/nu-plugin/src/lib.rs b/crates/nu-plugin/src/lib.rs new file mode 100644 index 0000000000..ff33a46384 --- /dev/null +++ b/crates/nu-plugin/src/lib.rs @@ -0,0 +1,6 @@ +pub mod plugin; +pub mod plugin_call; +pub mod plugin_capnp; +pub mod serializers; + +pub use plugin::{serve_plugin, Plugin}; diff --git a/crates/nu-plugin/src/plugin.rs b/crates/nu-plugin/src/plugin.rs new file mode 100644 index 0000000000..672c648463 --- /dev/null +++ b/crates/nu-plugin/src/plugin.rs @@ -0,0 +1,262 @@ +use crate::plugin_call::{self, decode_call, encode_response}; +use std::io::BufReader; +use std::process::{Command as CommandSys, Stdio}; +use std::{fmt::Display, path::Path}; + +use nu_protocol::engine::{Command, EngineState, Stack}; +use nu_protocol::{ast::Call, Signature, Value}; +use nu_protocol::{PipelineData, ShellError}; + +const OUTPUT_BUFFER_SIZE: usize = 8192; + +#[derive(Debug)] +pub struct CallInfo { + pub call: Call, + pub input: Value, +} + +// Information sent to the plugin +#[derive(Debug)] +pub enum PluginCall { + Signature, + CallInfo(Box), +} + +// Information received from the plugin +#[derive(Debug)] +pub enum PluginResponse { + Error(String), + Signature(Box), + Value(Box), +} + +#[derive(Debug)] +pub enum PluginError { + MissingSignature, + UnableToGetStdout, + UnableToSpawn(String), + EncodingError(String), + DecodingError(String), +} + +impl Display for PluginError { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + match self { + PluginError::MissingSignature => write!(f, "missing signature in plugin"), + PluginError::UnableToGetStdout => write!(f, "couldn't get stdout from child process"), + PluginError::UnableToSpawn(err) => { + write!(f, "error in spawned child process: {}", err) + } + PluginError::EncodingError(err) => { + write!(f, "error while encoding: {}", err) + } + PluginError::DecodingError(err) => { + write!(f, "error while decoding: {}", err) + } + } + } +} + +pub fn get_signature(path: &Path) -> Result, PluginError> { + let mut plugin_cmd = create_command(path); + + // Both stdout and stdin are piped so we can get the information from the plugin + plugin_cmd.stdout(Stdio::piped()); + plugin_cmd.stdin(Stdio::piped()); + + match plugin_cmd.spawn() { + Err(err) => Err(PluginError::UnableToSpawn(format!("{}", err))), + Ok(mut child) => { + // Create message to plugin to indicate that signature is required and + // send call to plugin asking for signature + if let Some(mut stdin_writer) = child.stdin.take() { + plugin_call::encode_call(&PluginCall::Signature, &mut stdin_writer)? + } + + // deserialize response from plugin to extract the signature + let signature = if let Some(stdout_reader) = child.stdout.take() { + let mut buf_read = BufReader::with_capacity(OUTPUT_BUFFER_SIZE, stdout_reader); + let response = plugin_call::decode_response(&mut buf_read)?; + + match response { + PluginResponse::Signature(sign) => Ok(sign), + PluginResponse::Error(msg) => Err(PluginError::DecodingError(msg)), + _ => Err(PluginError::DecodingError("signature not found".into())), + } + } else { + Err(PluginError::UnableToGetStdout) + }?; + + match child.wait() { + Err(err) => Err(PluginError::UnableToSpawn(format!("{}", err))), + Ok(_) => Ok(signature), + } + } + } +} + +fn create_command(path: &Path) -> CommandSys { + //TODO. The selection of shell could be modifiable from the config file. + if cfg!(windows) { + let mut process = CommandSys::new("cmd"); + process.arg("/c"); + process.arg(path); + + process + } else { + let mut process = CommandSys::new("sh"); + process.arg("-c").arg(path); + + process + } +} + +#[derive(Debug, Clone)] +pub struct PluginDeclaration { + name: String, + signature: Box, + filename: String, +} + +impl PluginDeclaration { + pub fn new(filename: String, signature: Box) -> Self { + Self { + name: signature.name.clone(), + signature, + filename, + } + } +} + +impl Command for PluginDeclaration { + fn name(&self) -> &str { + &self.name + } + + fn signature(&self) -> Signature { + self.signature.as_ref().clone() + } + + fn usage(&self) -> &str { + "plugin name plus arguments" + } + + fn run( + &self, + _engine_state: &EngineState, + _stack: &mut Stack, + call: &Call, + input: PipelineData, + ) -> Result { + // Call the command with self path + // Decode information from plugin + // Create PipelineData + let source_file = Path::new(&self.filename); + let mut plugin_cmd = create_command(source_file); + + // Both stdout and stdin are piped so we can get the information from the plugin + plugin_cmd.stdout(Stdio::piped()); + plugin_cmd.stdin(Stdio::piped()); + + match plugin_cmd.spawn() { + Err(err) => Err(ShellError::PluginError(format!("{}", err))), + Ok(mut child) => { + let input = match input { + PipelineData::Value(value) => value, + PipelineData::Stream(stream) => { + let values = stream.collect::>(); + + Value::List { + vals: values, + span: call.head, + } + } + }; + + // PluginCall information + let plugin_call = PluginCall::CallInfo(Box::new(CallInfo { + call: call.clone(), + input, + })); + + // Create message to plugin to indicate that signature is required and + // send call to plugin asking for signature + if let Some(mut stdin_writer) = child.stdin.take() { + plugin_call::encode_call(&plugin_call, &mut stdin_writer) + .map_err(|err| ShellError::PluginError(err.to_string()))? + } + + // Deserialize response from plugin to extract the resulting value + let pipeline_data = if let Some(stdout_reader) = child.stdout.take() { + let mut buf_read = BufReader::with_capacity(OUTPUT_BUFFER_SIZE, stdout_reader); + let response = plugin_call::decode_response(&mut buf_read) + .map_err(|err| ShellError::PluginError(err.to_string()))?; + + match response { + PluginResponse::Value(value) => { + Ok(PipelineData::Value(value.as_ref().clone())) + } + PluginResponse::Error(msg) => Err(PluginError::DecodingError(msg)), + _ => Err(PluginError::DecodingError( + "result value from plugin not found".into(), + )), + } + } else { + Err(PluginError::UnableToGetStdout) + } + .map_err(|err| ShellError::PluginError(err.to_string()))?; + + match child.wait() { + Err(err) => Err(ShellError::PluginError(format!("{}", err))), + Ok(_) => Ok(pipeline_data), + } + } + } + } + + fn is_plugin(&self) -> bool { + true + } +} + +/// The `Plugin` trait defines the API which plugins use to "hook" into nushell. +pub trait Plugin { + fn signature(&self) -> Signature; + fn run(&self, call: &Call, input: &Value) -> Result; +} + +// Function used in the plugin definition for the communication protocol between +// nushell and the external plugin. +// If you want to create a new plugin you have to use this function as the main +// entry point for the plugin +pub fn serve_plugin(plugin: &mut impl Plugin) { + let mut stdin_buf = BufReader::with_capacity(OUTPUT_BUFFER_SIZE, std::io::stdin()); + let plugin_call = decode_call(&mut stdin_buf); + + match plugin_call { + Err(err) => { + let response = PluginResponse::Error(err.to_string()); + encode_response(&response, &mut std::io::stdout()).expect("Error encoding response"); + } + Ok(plugin_call) => { + match plugin_call { + // Sending the signature back to nushell to create the declaration definition + PluginCall::Signature => { + let response = PluginResponse::Signature(Box::new(plugin.signature())); + encode_response(&response, &mut std::io::stdout()) + .expect("Error encoding response"); + } + PluginCall::CallInfo(call_info) => { + let value = plugin.run(&call_info.call, &call_info.input); + + let response = match value { + Ok(value) => PluginResponse::Value(Box::new(value)), + Err(err) => PluginResponse::Error(err.to_string()), + }; + encode_response(&response, &mut std::io::stdout()) + .expect("Error encoding response"); + } + } + } + } +} diff --git a/crates/nu-plugin/src/plugin_call.rs b/crates/nu-plugin/src/plugin_call.rs new file mode 100644 index 0000000000..40c6c295e1 --- /dev/null +++ b/crates/nu-plugin/src/plugin_call.rs @@ -0,0 +1,335 @@ +use crate::plugin::{CallInfo, PluginCall, PluginError, PluginResponse}; +use crate::plugin_capnp::{plugin_call, plugin_response}; +use crate::serializers::{call, signature, value}; +use capnp::serialize_packed; + +pub fn encode_call( + plugin_call: &PluginCall, + writer: &mut impl std::io::Write, +) -> Result<(), PluginError> { + let mut message = ::capnp::message::Builder::new_default(); + + let mut builder = message.init_root::(); + + match &plugin_call { + PluginCall::Signature => builder.set_signature(()), + PluginCall::CallInfo(call_info) => { + let mut call_info_builder = builder.reborrow().init_call_info(); + + // Serializing argument information from the call + let call_builder = call_info_builder + .reborrow() + .get_call() + .map_err(|e| PluginError::EncodingError(e.to_string()))?; + + call::serialize_call(&call_info.call, call_builder) + .map_err(|e| PluginError::EncodingError(e.to_string()))?; + + // Serializing the input value from the call info + let value_builder = call_info_builder + .reborrow() + .get_input() + .map_err(|e| PluginError::EncodingError(e.to_string()))?; + + value::serialize_value(&call_info.input, value_builder); + } + }; + + serialize_packed::write_message(writer, &message) + .map_err(|e| PluginError::EncodingError(e.to_string())) +} + +pub fn decode_call(reader: &mut impl std::io::BufRead) -> Result { + let message_reader = + serialize_packed::read_message(reader, ::capnp::message::ReaderOptions::new()).unwrap(); + + let reader = message_reader + .get_root::() + .map_err(|e| PluginError::DecodingError(e.to_string()))?; + + match reader.which() { + Err(capnp::NotInSchema(_)) => Err(PluginError::DecodingError("value not in schema".into())), + Ok(plugin_call::Signature(())) => Ok(PluginCall::Signature), + Ok(plugin_call::CallInfo(reader)) => { + let reader = reader.map_err(|e| PluginError::DecodingError(e.to_string()))?; + + let call_reader = reader + .get_call() + .map_err(|e| PluginError::DecodingError(e.to_string()))?; + + let call = call::deserialize_call(call_reader) + .map_err(|e| PluginError::DecodingError(e.to_string()))?; + + let input_reader = reader + .get_input() + .map_err(|e| PluginError::DecodingError(e.to_string()))?; + + let input = value::deserialize_value(input_reader) + .map_err(|e| PluginError::DecodingError(e.to_string()))?; + + Ok(PluginCall::CallInfo(Box::new(CallInfo { call, input }))) + } + } +} + +pub fn encode_response( + plugin_response: &PluginResponse, + writer: &mut impl std::io::Write, +) -> Result<(), PluginError> { + let mut message = ::capnp::message::Builder::new_default(); + + let mut builder = message.init_root::(); + + match &plugin_response { + PluginResponse::Error(msg) => builder.reborrow().set_error(msg.as_str()), + PluginResponse::Signature(sign) => { + let signature_builder = builder.reborrow().init_signature(); + signature::serialize_signature(sign, signature_builder) + } + PluginResponse::Value(val) => { + let value_builder = builder.reborrow().init_value(); + value::serialize_value(val, value_builder); + } + }; + + serialize_packed::write_message(writer, &message) + .map_err(|e| PluginError::EncodingError(e.to_string())) +} + +pub fn decode_response(reader: &mut impl std::io::BufRead) -> Result { + let message_reader = + serialize_packed::read_message(reader, ::capnp::message::ReaderOptions::new()).unwrap(); + + let reader = message_reader + .get_root::() + .map_err(|e| PluginError::DecodingError(e.to_string()))?; + + match reader.which() { + Err(capnp::NotInSchema(_)) => Err(PluginError::DecodingError("value not in schema".into())), + Ok(plugin_response::Error(reader)) => { + let msg = reader.map_err(|e| PluginError::DecodingError(e.to_string()))?; + + Ok(PluginResponse::Error(msg.to_string())) + } + Ok(plugin_response::Signature(reader)) => { + let reader = reader.map_err(|e| PluginError::DecodingError(e.to_string()))?; + let sign = signature::deserialize_signature(reader) + .map_err(|e| PluginError::DecodingError(e.to_string()))?; + + Ok(PluginResponse::Signature(Box::new(sign))) + } + Ok(plugin_response::Value(reader)) => { + let reader = reader.map_err(|e| PluginError::DecodingError(e.to_string()))?; + let val = value::deserialize_value(reader) + .map_err(|e| PluginError::DecodingError(e.to_string()))?; + + Ok(PluginResponse::Value(Box::new(val))) + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::plugin::{PluginCall, PluginResponse}; + use nu_protocol::{ + ast::{Call, Expr, Expression}, + Signature, Span, Spanned, SyntaxShape, Value, + }; + + fn compare_expressions(lhs: &Expression, rhs: &Expression) { + match (&lhs.expr, &rhs.expr) { + (Expr::Bool(a), Expr::Bool(b)) => assert_eq!(a, b), + (Expr::Int(a), Expr::Int(b)) => assert_eq!(a, b), + (Expr::Float(a), Expr::Float(b)) => assert!((a - b).abs() < f64::EPSILON), + (Expr::String(a), Expr::String(b)) => assert_eq!(a, b), + _ => panic!("not matching values"), + } + } + + #[test] + fn callinfo_round_trip_signature() { + let plugin_call = PluginCall::Signature; + + let mut buffer: Vec = Vec::new(); + encode_call(&plugin_call, &mut buffer).expect("unable to serialize message"); + let returned = decode_call(&mut buffer.as_slice()).expect("unable to deserialize message"); + + match returned { + PluginCall::Signature => {} + PluginCall::CallInfo(_) => panic!("decoded into wrong value"), + } + } + + #[test] + fn callinfo_round_trip_callinfo() { + let input = Value::Bool { + val: false, + span: Span { start: 1, end: 20 }, + }; + + let call = Call { + decl_id: 1, + head: Span { start: 0, end: 10 }, + positional: vec![ + Expression { + expr: Expr::Float(1.0), + span: Span { start: 0, end: 10 }, + ty: nu_protocol::Type::Float, + custom_completion: None, + }, + Expression { + expr: Expr::String("something".into()), + span: Span { start: 0, end: 10 }, + ty: nu_protocol::Type::Float, + custom_completion: None, + }, + ], + named: vec![( + Spanned { + item: "name".to_string(), + span: Span { start: 0, end: 10 }, + }, + Some(Expression { + expr: Expr::Float(1.0), + span: Span { start: 0, end: 10 }, + ty: nu_protocol::Type::Float, + custom_completion: None, + }), + )], + }; + + let plugin_call = PluginCall::CallInfo(Box::new(CallInfo { + call: call.clone(), + input: input.clone(), + })); + + let mut buffer: Vec = Vec::new(); + encode_call(&plugin_call, &mut buffer).expect("unable to serialize message"); + let returned = decode_call(&mut buffer.as_slice()).expect("unable to deserialize message"); + + match returned { + PluginCall::Signature => panic!("returned wrong call type"), + PluginCall::CallInfo(call_info) => { + assert_eq!(input, call_info.input); + assert_eq!(call.head, call_info.call.head); + assert_eq!(call.positional.len(), call_info.call.positional.len()); + + call.positional + .iter() + .zip(call_info.call.positional.iter()) + .for_each(|(lhs, rhs)| compare_expressions(lhs, rhs)); + + call.named + .iter() + .zip(call_info.call.named.iter()) + .for_each(|(lhs, rhs)| { + // Comparing the keys + assert_eq!(lhs.0.item, rhs.0.item); + + match (&lhs.1, &rhs.1) { + (None, None) => {} + (Some(a), Some(b)) => compare_expressions(a, b), + _ => panic!("not matching values"), + } + }); + } + } + } + + #[test] + fn response_round_trip_signature() { + let signature = Signature::build("nu-plugin") + .required("first", SyntaxShape::String, "first required") + .required("second", SyntaxShape::Int, "second required") + .required_named("first_named", SyntaxShape::String, "first named", Some('f')) + .required_named( + "second_named", + SyntaxShape::String, + "second named", + Some('s'), + ) + .rest("remaining", SyntaxShape::Int, "remaining"); + + let response = PluginResponse::Signature(Box::new(signature.clone())); + + let mut buffer: Vec = Vec::new(); + encode_response(&response, &mut buffer).expect("unable to serialize message"); + let returned = + decode_response(&mut buffer.as_slice()).expect("unable to deserialize message"); + + match returned { + PluginResponse::Error(_) => panic!("returned wrong call type"), + PluginResponse::Value(_) => panic!("returned wrong call type"), + PluginResponse::Signature(returned_signature) => { + assert_eq!(signature.name, returned_signature.name); + assert_eq!(signature.usage, returned_signature.usage); + assert_eq!(signature.extra_usage, returned_signature.extra_usage); + assert_eq!(signature.is_filter, returned_signature.is_filter); + + signature + .required_positional + .iter() + .zip(returned_signature.required_positional.iter()) + .for_each(|(lhs, rhs)| assert_eq!(lhs, rhs)); + + signature + .optional_positional + .iter() + .zip(returned_signature.optional_positional.iter()) + .for_each(|(lhs, rhs)| assert_eq!(lhs, rhs)); + + signature + .named + .iter() + .zip(returned_signature.named.iter()) + .for_each(|(lhs, rhs)| assert_eq!(lhs, rhs)); + + assert_eq!( + signature.rest_positional, + returned_signature.rest_positional, + ); + } + } + } + + #[test] + fn response_round_trip_value() { + let value = Value::Int { + val: 10, + span: Span { start: 2, end: 30 }, + }; + + let response = PluginResponse::Value(Box::new(value.clone())); + + let mut buffer: Vec = Vec::new(); + encode_response(&response, &mut buffer).expect("unable to serialize message"); + let returned = + decode_response(&mut buffer.as_slice()).expect("unable to deserialize message"); + + match returned { + PluginResponse::Error(_) => panic!("returned wrong call type"), + PluginResponse::Signature(_) => panic!("returned wrong call type"), + PluginResponse::Value(returned_value) => { + assert_eq!(&value, returned_value.as_ref()) + } + } + } + + #[test] + fn response_round_trip_error() { + let message = "some error".to_string(); + let response = PluginResponse::Error(message.clone()); + + let mut buffer: Vec = Vec::new(); + encode_response(&response, &mut buffer).expect("unable to serialize message"); + let returned = + decode_response(&mut buffer.as_slice()).expect("unable to deserialize message"); + + match returned { + PluginResponse::Error(msg) => assert_eq!(message, msg), + PluginResponse::Signature(_) => panic!("returned wrong call type"), + PluginResponse::Value(_) => panic!("returned wrong call type"), + } + } +} diff --git a/crates/nu-plugin/src/plugin_capnp.rs b/crates/nu-plugin/src/plugin_capnp.rs new file mode 100644 index 0000000000..cd49bad6e0 --- /dev/null +++ b/crates/nu-plugin/src/plugin_capnp.rs @@ -0,0 +1,4179 @@ +// @generated by the capnpc-rust plugin to the Cap'n Proto schema compiler. +// DO NOT EDIT. +// source: plugin.capnp + +pub mod option { + /* T */ + pub use self::Which::{None, Some}; + + #[derive(Copy, Clone)] + pub struct Owned { + _phantom: ::core::marker::PhantomData, + } + impl<'a, T> ::capnp::traits::Owned<'a> for Owned + where + T: for<'c> ::capnp::traits::Owned<'c>, + { + type Reader = Reader<'a, T>; + type Builder = Builder<'a, T>; + } + impl<'a, T> ::capnp::traits::OwnedStruct<'a> for Owned + where + T: for<'c> ::capnp::traits::Owned<'c>, + { + type Reader = Reader<'a, T>; + type Builder = Builder<'a, T>; + } + impl ::capnp::traits::Pipelined for Owned + where + T: for<'c> ::capnp::traits::Owned<'c>, + { + type Pipeline = Pipeline; + } + + #[derive(Clone, Copy)] + pub struct Reader<'a, T> + where + T: for<'c> ::capnp::traits::Owned<'c>, + { + reader: ::capnp::private::layout::StructReader<'a>, + _phantom: ::core::marker::PhantomData, + } + + impl<'a, T> ::capnp::traits::HasTypeId for Reader<'a, T> + where + T: for<'c> ::capnp::traits::Owned<'c>, + { + #[inline] + fn type_id() -> u64 { + _private::TYPE_ID + } + } + impl<'a, T> ::capnp::traits::FromStructReader<'a> for Reader<'a, T> + where + T: for<'c> ::capnp::traits::Owned<'c>, + { + fn new(reader: ::capnp::private::layout::StructReader<'a>) -> Reader<'a, T> { + Reader { + reader, + _phantom: ::core::marker::PhantomData, + } + } + } + + impl<'a, T> ::capnp::traits::FromPointerReader<'a> for Reader<'a, T> + where + T: for<'c> ::capnp::traits::Owned<'c>, + { + fn get_from_pointer( + reader: &::capnp::private::layout::PointerReader<'a>, + default: ::core::option::Option<&'a [capnp::Word]>, + ) -> ::capnp::Result> { + ::core::result::Result::Ok(::capnp::traits::FromStructReader::new( + reader.get_struct(default)?, + )) + } + } + + impl<'a, T> ::capnp::traits::IntoInternalStructReader<'a> for Reader<'a, T> + where + T: for<'c> ::capnp::traits::Owned<'c>, + { + fn into_internal_struct_reader(self) -> ::capnp::private::layout::StructReader<'a> { + self.reader + } + } + + impl<'a, T> ::capnp::traits::Imbue<'a> for Reader<'a, T> + where + T: for<'c> ::capnp::traits::Owned<'c>, + { + fn imbue(&mut self, cap_table: &'a ::capnp::private::layout::CapTable) { + self.reader + .imbue(::capnp::private::layout::CapTableReader::Plain(cap_table)) + } + } + + impl<'a, T> Reader<'a, T> + where + T: for<'c> ::capnp::traits::Owned<'c>, + { + pub fn reborrow(&self) -> Reader<'_, T> { + Reader { ..*self } + } + + pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> { + self.reader.total_size() + } + pub fn has_some(&self) -> bool { + if self.reader.get_data_field::(0) != 1 { + return false; + } + !self.reader.get_pointer_field(0).is_null() + } + #[inline] + pub fn which(self) -> ::core::result::Result, ::capnp::NotInSchema> { + match self.reader.get_data_field::(0) { + 0 => ::core::result::Result::Ok(None(())), + 1 => ::core::result::Result::Ok(Some( + ::capnp::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(0), + ::core::option::Option::None, + ), + )), + x => ::core::result::Result::Err(::capnp::NotInSchema(x)), + } + } + } + + pub struct Builder<'a, T> + where + T: for<'c> ::capnp::traits::Owned<'c>, + { + builder: ::capnp::private::layout::StructBuilder<'a>, + _phantom: ::core::marker::PhantomData, + } + impl<'a, T> ::capnp::traits::HasStructSize for Builder<'a, T> + where + T: for<'c> ::capnp::traits::Owned<'c>, + { + #[inline] + fn struct_size() -> ::capnp::private::layout::StructSize { + _private::STRUCT_SIZE + } + } + impl<'a, T> ::capnp::traits::HasTypeId for Builder<'a, T> + where + T: for<'c> ::capnp::traits::Owned<'c>, + { + #[inline] + fn type_id() -> u64 { + _private::TYPE_ID + } + } + impl<'a, T> ::capnp::traits::FromStructBuilder<'a> for Builder<'a, T> + where + T: for<'c> ::capnp::traits::Owned<'c>, + { + fn new(builder: ::capnp::private::layout::StructBuilder<'a>) -> Builder<'a, T> { + Builder { + builder, + _phantom: ::core::marker::PhantomData, + } + } + } + + impl<'a, T> ::capnp::traits::ImbueMut<'a> for Builder<'a, T> + where + T: for<'c> ::capnp::traits::Owned<'c>, + { + fn imbue_mut(&mut self, cap_table: &'a mut ::capnp::private::layout::CapTable) { + self.builder + .imbue(::capnp::private::layout::CapTableBuilder::Plain(cap_table)) + } + } + + impl<'a, T> ::capnp::traits::FromPointerBuilder<'a> for Builder<'a, T> + where + T: for<'c> ::capnp::traits::Owned<'c>, + { + fn init_pointer( + builder: ::capnp::private::layout::PointerBuilder<'a>, + _size: u32, + ) -> Builder<'a, T> { + ::capnp::traits::FromStructBuilder::new(builder.init_struct(_private::STRUCT_SIZE)) + } + fn get_from_pointer( + builder: ::capnp::private::layout::PointerBuilder<'a>, + default: ::core::option::Option<&'a [capnp::Word]>, + ) -> ::capnp::Result> { + ::core::result::Result::Ok(::capnp::traits::FromStructBuilder::new( + builder.get_struct(_private::STRUCT_SIZE, default)?, + )) + } + } + + impl<'a, T> ::capnp::traits::SetPointerBuilder for Reader<'a, T> + where + T: for<'c> ::capnp::traits::Owned<'c>, + { + fn set_pointer_builder<'b>( + pointer: ::capnp::private::layout::PointerBuilder<'b>, + value: Reader<'a, T>, + canonicalize: bool, + ) -> ::capnp::Result<()> { + pointer.set_struct(&value.reader, canonicalize) + } + } + + impl<'a, T> Builder<'a, T> + where + T: for<'c> ::capnp::traits::Owned<'c>, + { + pub fn into_reader(self) -> Reader<'a, T> { + ::capnp::traits::FromStructReader::new(self.builder.into_reader()) + } + pub fn reborrow(&mut self) -> Builder<'_, T> { + Builder { ..*self } + } + pub fn reborrow_as_reader(&self) -> Reader<'_, T> { + ::capnp::traits::FromStructReader::new(self.builder.into_reader()) + } + + pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> { + self.builder.into_reader().total_size() + } + #[inline] + pub fn set_none(&mut self, _value: ()) { + self.builder.set_data_field::(0, 0); + } + #[inline] + pub fn initn_some(self, length: u32) -> >::Builder { + self.builder.set_data_field::(0, 1); + ::capnp::any_pointer::Builder::new(self.builder.get_pointer_field(0)).initn_as(length) + } + #[inline] + pub fn set_some( + &mut self, + value: >::Reader, + ) -> ::capnp::Result<()> { + self.builder.set_data_field::(0, 1); + ::capnp::traits::SetPointerBuilder::set_pointer_builder( + self.builder.get_pointer_field(0), + value, + false, + ) + } + #[inline] + pub fn init_some(self) -> >::Builder { + self.builder.set_data_field::(0, 1); + ::capnp::any_pointer::Builder::new(self.builder.get_pointer_field(0)).init_as() + } + pub fn has_some(&self) -> bool { + if self.builder.get_data_field::(0) != 1 { + return false; + } + !self.builder.get_pointer_field(0).is_null() + } + #[inline] + pub fn which(self) -> ::core::result::Result, ::capnp::NotInSchema> { + match self.builder.get_data_field::(0) { + 0 => ::core::result::Result::Ok(None(())), + 1 => ::core::result::Result::Ok(Some( + ::capnp::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(0), + ::core::option::Option::None, + ), + )), + x => ::core::result::Result::Err(::capnp::NotInSchema(x)), + } + } + } + + pub struct Pipeline { + _typeless: ::capnp::any_pointer::Pipeline, + _phantom: ::core::marker::PhantomData, + } + impl ::capnp::capability::FromTypelessPipeline for Pipeline { + fn new(typeless: ::capnp::any_pointer::Pipeline) -> Pipeline { + Pipeline { + _typeless: typeless, + _phantom: ::core::marker::PhantomData, + } + } + } + impl Pipeline + where + T: ::capnp::traits::Pipelined, + ::Pipeline: ::capnp::capability::FromTypelessPipeline, + { + } + mod _private { + use capnp::private::layout; + pub const STRUCT_SIZE: layout::StructSize = layout::StructSize { + data: 1, + pointers: 1, + }; + pub const TYPE_ID: u64 = 0xd0d8_5bbb_e991_4dd9; + } + pub enum Which { + None(()), + Some(A0), + } + pub type WhichReader<'a, T> = Which<::capnp::Result<>::Reader>>; + pub type WhichBuilder<'a, T> = + Which<::capnp::Result<>::Builder>>; +} + +pub mod err { + /* T */ + pub use self::Which::{Err, Ok}; + + #[derive(Copy, Clone)] + pub struct Owned { + _phantom: ::core::marker::PhantomData, + } + impl<'a, T> ::capnp::traits::Owned<'a> for Owned + where + T: for<'c> ::capnp::traits::Owned<'c>, + { + type Reader = Reader<'a, T>; + type Builder = Builder<'a, T>; + } + impl<'a, T> ::capnp::traits::OwnedStruct<'a> for Owned + where + T: for<'c> ::capnp::traits::Owned<'c>, + { + type Reader = Reader<'a, T>; + type Builder = Builder<'a, T>; + } + impl ::capnp::traits::Pipelined for Owned + where + T: for<'c> ::capnp::traits::Owned<'c>, + { + type Pipeline = Pipeline; + } + + #[derive(Clone, Copy)] + pub struct Reader<'a, T> + where + T: for<'c> ::capnp::traits::Owned<'c>, + { + reader: ::capnp::private::layout::StructReader<'a>, + _phantom: ::core::marker::PhantomData, + } + + impl<'a, T> ::capnp::traits::HasTypeId for Reader<'a, T> + where + T: for<'c> ::capnp::traits::Owned<'c>, + { + #[inline] + fn type_id() -> u64 { + _private::TYPE_ID + } + } + impl<'a, T> ::capnp::traits::FromStructReader<'a> for Reader<'a, T> + where + T: for<'c> ::capnp::traits::Owned<'c>, + { + fn new(reader: ::capnp::private::layout::StructReader<'a>) -> Reader<'a, T> { + Reader { + reader, + _phantom: ::core::marker::PhantomData, + } + } + } + + impl<'a, T> ::capnp::traits::FromPointerReader<'a> for Reader<'a, T> + where + T: for<'c> ::capnp::traits::Owned<'c>, + { + fn get_from_pointer( + reader: &::capnp::private::layout::PointerReader<'a>, + default: ::core::option::Option<&'a [capnp::Word]>, + ) -> ::capnp::Result> { + ::core::result::Result::Ok(::capnp::traits::FromStructReader::new( + reader.get_struct(default)?, + )) + } + } + + impl<'a, T> ::capnp::traits::IntoInternalStructReader<'a> for Reader<'a, T> + where + T: for<'c> ::capnp::traits::Owned<'c>, + { + fn into_internal_struct_reader(self) -> ::capnp::private::layout::StructReader<'a> { + self.reader + } + } + + impl<'a, T> ::capnp::traits::Imbue<'a> for Reader<'a, T> + where + T: for<'c> ::capnp::traits::Owned<'c>, + { + fn imbue(&mut self, cap_table: &'a ::capnp::private::layout::CapTable) { + self.reader + .imbue(::capnp::private::layout::CapTableReader::Plain(cap_table)) + } + } + + impl<'a, T> Reader<'a, T> + where + T: for<'c> ::capnp::traits::Owned<'c>, + { + pub fn reborrow(&self) -> Reader<'_, T> { + Reader { ..*self } + } + + pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> { + self.reader.total_size() + } + pub fn has_err(&self) -> bool { + if self.reader.get_data_field::(0) != 0 { + return false; + } + !self.reader.get_pointer_field(0).is_null() + } + pub fn has_ok(&self) -> bool { + if self.reader.get_data_field::(0) != 1 { + return false; + } + !self.reader.get_pointer_field(0).is_null() + } + #[inline] + pub fn which(self) -> ::core::result::Result, ::capnp::NotInSchema> { + match self.reader.get_data_field::(0) { + 0 => ::core::result::Result::Ok(Err( + ::capnp::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(0), + ::core::option::Option::None, + ), + )), + 1 => ::core::result::Result::Ok(Ok( + ::capnp::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(0), + ::core::option::Option::None, + ), + )), + x => ::core::result::Result::Err(::capnp::NotInSchema(x)), + } + } + } + + pub struct Builder<'a, T> + where + T: for<'c> ::capnp::traits::Owned<'c>, + { + builder: ::capnp::private::layout::StructBuilder<'a>, + _phantom: ::core::marker::PhantomData, + } + impl<'a, T> ::capnp::traits::HasStructSize for Builder<'a, T> + where + T: for<'c> ::capnp::traits::Owned<'c>, + { + #[inline] + fn struct_size() -> ::capnp::private::layout::StructSize { + _private::STRUCT_SIZE + } + } + impl<'a, T> ::capnp::traits::HasTypeId for Builder<'a, T> + where + T: for<'c> ::capnp::traits::Owned<'c>, + { + #[inline] + fn type_id() -> u64 { + _private::TYPE_ID + } + } + impl<'a, T> ::capnp::traits::FromStructBuilder<'a> for Builder<'a, T> + where + T: for<'c> ::capnp::traits::Owned<'c>, + { + fn new(builder: ::capnp::private::layout::StructBuilder<'a>) -> Builder<'a, T> { + Builder { + builder, + _phantom: ::core::marker::PhantomData, + } + } + } + + impl<'a, T> ::capnp::traits::ImbueMut<'a> for Builder<'a, T> + where + T: for<'c> ::capnp::traits::Owned<'c>, + { + fn imbue_mut(&mut self, cap_table: &'a mut ::capnp::private::layout::CapTable) { + self.builder + .imbue(::capnp::private::layout::CapTableBuilder::Plain(cap_table)) + } + } + + impl<'a, T> ::capnp::traits::FromPointerBuilder<'a> for Builder<'a, T> + where + T: for<'c> ::capnp::traits::Owned<'c>, + { + fn init_pointer( + builder: ::capnp::private::layout::PointerBuilder<'a>, + _size: u32, + ) -> Builder<'a, T> { + ::capnp::traits::FromStructBuilder::new(builder.init_struct(_private::STRUCT_SIZE)) + } + fn get_from_pointer( + builder: ::capnp::private::layout::PointerBuilder<'a>, + default: ::core::option::Option<&'a [capnp::Word]>, + ) -> ::capnp::Result> { + ::core::result::Result::Ok(::capnp::traits::FromStructBuilder::new( + builder.get_struct(_private::STRUCT_SIZE, default)?, + )) + } + } + + impl<'a, T> ::capnp::traits::SetPointerBuilder for Reader<'a, T> + where + T: for<'c> ::capnp::traits::Owned<'c>, + { + fn set_pointer_builder<'b>( + pointer: ::capnp::private::layout::PointerBuilder<'b>, + value: Reader<'a, T>, + canonicalize: bool, + ) -> ::capnp::Result<()> { + pointer.set_struct(&value.reader, canonicalize) + } + } + + impl<'a, T> Builder<'a, T> + where + T: for<'c> ::capnp::traits::Owned<'c>, + { + pub fn into_reader(self) -> Reader<'a, T> { + ::capnp::traits::FromStructReader::new(self.builder.into_reader()) + } + pub fn reborrow(&mut self) -> Builder<'_, T> { + Builder { ..*self } + } + pub fn reborrow_as_reader(&self) -> Reader<'_, T> { + ::capnp::traits::FromStructReader::new(self.builder.into_reader()) + } + + pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> { + self.builder.into_reader().total_size() + } + #[inline] + pub fn set_err(&mut self, value: ::capnp::text::Reader<'_>) { + self.builder.set_data_field::(0, 0); + self.builder.get_pointer_field(0).set_text(value); + } + #[inline] + pub fn init_err(self, size: u32) -> ::capnp::text::Builder<'a> { + self.builder.set_data_field::(0, 0); + self.builder.get_pointer_field(0).init_text(size) + } + pub fn has_err(&self) -> bool { + if self.builder.get_data_field::(0) != 0 { + return false; + } + !self.builder.get_pointer_field(0).is_null() + } + #[inline] + pub fn initn_ok(self, length: u32) -> >::Builder { + self.builder.set_data_field::(0, 1); + ::capnp::any_pointer::Builder::new(self.builder.get_pointer_field(0)).initn_as(length) + } + #[inline] + pub fn set_ok( + &mut self, + value: >::Reader, + ) -> ::capnp::Result<()> { + self.builder.set_data_field::(0, 1); + ::capnp::traits::SetPointerBuilder::set_pointer_builder( + self.builder.get_pointer_field(0), + value, + false, + ) + } + #[inline] + pub fn init_ok(self) -> >::Builder { + self.builder.set_data_field::(0, 1); + ::capnp::any_pointer::Builder::new(self.builder.get_pointer_field(0)).init_as() + } + pub fn has_ok(&self) -> bool { + if self.builder.get_data_field::(0) != 1 { + return false; + } + !self.builder.get_pointer_field(0).is_null() + } + #[inline] + pub fn which(self) -> ::core::result::Result, ::capnp::NotInSchema> { + match self.builder.get_data_field::(0) { + 0 => ::core::result::Result::Ok(Err( + ::capnp::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(0), + ::core::option::Option::None, + ), + )), + 1 => ::core::result::Result::Ok(Ok( + ::capnp::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(0), + ::core::option::Option::None, + ), + )), + x => ::core::result::Result::Err(::capnp::NotInSchema(x)), + } + } + } + + pub struct Pipeline { + _typeless: ::capnp::any_pointer::Pipeline, + _phantom: ::core::marker::PhantomData, + } + impl ::capnp::capability::FromTypelessPipeline for Pipeline { + fn new(typeless: ::capnp::any_pointer::Pipeline) -> Pipeline { + Pipeline { + _typeless: typeless, + _phantom: ::core::marker::PhantomData, + } + } + } + impl Pipeline + where + T: ::capnp::traits::Pipelined, + ::Pipeline: ::capnp::capability::FromTypelessPipeline, + { + } + mod _private { + use capnp::private::layout; + pub const STRUCT_SIZE: layout::StructSize = layout::StructSize { + data: 1, + pointers: 1, + }; + pub const TYPE_ID: u64 = 0xaed6_5bd3_8214_33f8; + } + pub enum Which { + Err(A0), + Ok(A1), + } + pub type WhichReader<'a, T> = Which< + ::capnp::Result<::capnp::text::Reader<'a>>, + ::capnp::Result<>::Reader>, + >; + pub type WhichBuilder<'a, T> = Which< + ::capnp::Result<::capnp::text::Builder<'a>>, + ::capnp::Result<>::Builder>, + >; +} + +pub mod map { + /* Key,Value */ + #[derive(Copy, Clone)] + pub struct Owned { + _phantom: ::core::marker::PhantomData<(Key, Value)>, + } + impl<'a, Key, Value> ::capnp::traits::Owned<'a> for Owned + where + Key: for<'c> ::capnp::traits::Owned<'c>, + Value: for<'c> ::capnp::traits::Owned<'c>, + { + type Reader = Reader<'a, Key, Value>; + type Builder = Builder<'a, Key, Value>; + } + impl<'a, Key, Value> ::capnp::traits::OwnedStruct<'a> for Owned + where + Key: for<'c> ::capnp::traits::Owned<'c>, + Value: for<'c> ::capnp::traits::Owned<'c>, + { + type Reader = Reader<'a, Key, Value>; + type Builder = Builder<'a, Key, Value>; + } + impl ::capnp::traits::Pipelined for Owned + where + Key: for<'c> ::capnp::traits::Owned<'c>, + Value: for<'c> ::capnp::traits::Owned<'c>, + { + type Pipeline = Pipeline; + } + + #[derive(Clone, Copy)] + pub struct Reader<'a, Key, Value> + where + Key: for<'c> ::capnp::traits::Owned<'c>, + Value: for<'c> ::capnp::traits::Owned<'c>, + { + reader: ::capnp::private::layout::StructReader<'a>, + _phantom: ::core::marker::PhantomData<(Key, Value)>, + } + + impl<'a, Key, Value> ::capnp::traits::HasTypeId for Reader<'a, Key, Value> + where + Key: for<'c> ::capnp::traits::Owned<'c>, + Value: for<'c> ::capnp::traits::Owned<'c>, + { + #[inline] + fn type_id() -> u64 { + _private::TYPE_ID + } + } + impl<'a, Key, Value> ::capnp::traits::FromStructReader<'a> for Reader<'a, Key, Value> + where + Key: for<'c> ::capnp::traits::Owned<'c>, + Value: for<'c> ::capnp::traits::Owned<'c>, + { + fn new(reader: ::capnp::private::layout::StructReader<'a>) -> Reader<'a, Key, Value> { + Reader { + reader, + _phantom: ::core::marker::PhantomData, + } + } + } + + impl<'a, Key, Value> ::capnp::traits::FromPointerReader<'a> for Reader<'a, Key, Value> + where + Key: for<'c> ::capnp::traits::Owned<'c>, + Value: for<'c> ::capnp::traits::Owned<'c>, + { + fn get_from_pointer( + reader: &::capnp::private::layout::PointerReader<'a>, + default: ::core::option::Option<&'a [capnp::Word]>, + ) -> ::capnp::Result> { + ::core::result::Result::Ok(::capnp::traits::FromStructReader::new( + reader.get_struct(default)?, + )) + } + } + + impl<'a, Key, Value> ::capnp::traits::IntoInternalStructReader<'a> for Reader<'a, Key, Value> + where + Key: for<'c> ::capnp::traits::Owned<'c>, + Value: for<'c> ::capnp::traits::Owned<'c>, + { + fn into_internal_struct_reader(self) -> ::capnp::private::layout::StructReader<'a> { + self.reader + } + } + + impl<'a, Key, Value> ::capnp::traits::Imbue<'a> for Reader<'a, Key, Value> + where + Key: for<'c> ::capnp::traits::Owned<'c>, + Value: for<'c> ::capnp::traits::Owned<'c>, + { + fn imbue(&mut self, cap_table: &'a ::capnp::private::layout::CapTable) { + self.reader + .imbue(::capnp::private::layout::CapTableReader::Plain(cap_table)) + } + } + + impl<'a, Key, Value> Reader<'a, Key, Value> + where + Key: for<'c> ::capnp::traits::Owned<'c>, + Value: for<'c> ::capnp::traits::Owned<'c>, + { + pub fn reborrow(&self) -> Reader<'_, Key, Value> { + Reader { ..*self } + } + + pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> { + self.reader.total_size() + } + #[inline] + pub fn get_entries( + self, + ) -> ::capnp::Result< + ::capnp::struct_list::Reader<'a, crate::plugin_capnp::map::entry::Owned>, + > { + ::capnp::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(0), + ::core::option::Option::None, + ) + } + pub fn has_entries(&self) -> bool { + !self.reader.get_pointer_field(0).is_null() + } + } + + pub struct Builder<'a, Key, Value> + where + Key: for<'c> ::capnp::traits::Owned<'c>, + Value: for<'c> ::capnp::traits::Owned<'c>, + { + builder: ::capnp::private::layout::StructBuilder<'a>, + _phantom: ::core::marker::PhantomData<(Key, Value)>, + } + impl<'a, Key, Value> ::capnp::traits::HasStructSize for Builder<'a, Key, Value> + where + Key: for<'c> ::capnp::traits::Owned<'c>, + Value: for<'c> ::capnp::traits::Owned<'c>, + { + #[inline] + fn struct_size() -> ::capnp::private::layout::StructSize { + _private::STRUCT_SIZE + } + } + impl<'a, Key, Value> ::capnp::traits::HasTypeId for Builder<'a, Key, Value> + where + Key: for<'c> ::capnp::traits::Owned<'c>, + Value: for<'c> ::capnp::traits::Owned<'c>, + { + #[inline] + fn type_id() -> u64 { + _private::TYPE_ID + } + } + impl<'a, Key, Value> ::capnp::traits::FromStructBuilder<'a> for Builder<'a, Key, Value> + where + Key: for<'c> ::capnp::traits::Owned<'c>, + Value: for<'c> ::capnp::traits::Owned<'c>, + { + fn new(builder: ::capnp::private::layout::StructBuilder<'a>) -> Builder<'a, Key, Value> { + Builder { + builder, + _phantom: ::core::marker::PhantomData, + } + } + } + + impl<'a, Key, Value> ::capnp::traits::ImbueMut<'a> for Builder<'a, Key, Value> + where + Key: for<'c> ::capnp::traits::Owned<'c>, + Value: for<'c> ::capnp::traits::Owned<'c>, + { + fn imbue_mut(&mut self, cap_table: &'a mut ::capnp::private::layout::CapTable) { + self.builder + .imbue(::capnp::private::layout::CapTableBuilder::Plain(cap_table)) + } + } + + impl<'a, Key, Value> ::capnp::traits::FromPointerBuilder<'a> for Builder<'a, Key, Value> + where + Key: for<'c> ::capnp::traits::Owned<'c>, + Value: for<'c> ::capnp::traits::Owned<'c>, + { + fn init_pointer( + builder: ::capnp::private::layout::PointerBuilder<'a>, + _size: u32, + ) -> Builder<'a, Key, Value> { + ::capnp::traits::FromStructBuilder::new(builder.init_struct(_private::STRUCT_SIZE)) + } + fn get_from_pointer( + builder: ::capnp::private::layout::PointerBuilder<'a>, + default: ::core::option::Option<&'a [capnp::Word]>, + ) -> ::capnp::Result> { + ::core::result::Result::Ok(::capnp::traits::FromStructBuilder::new( + builder.get_struct(_private::STRUCT_SIZE, default)?, + )) + } + } + + impl<'a, Key, Value> ::capnp::traits::SetPointerBuilder for Reader<'a, Key, Value> + where + Key: for<'c> ::capnp::traits::Owned<'c>, + Value: for<'c> ::capnp::traits::Owned<'c>, + { + fn set_pointer_builder<'b>( + pointer: ::capnp::private::layout::PointerBuilder<'b>, + value: Reader<'a, Key, Value>, + canonicalize: bool, + ) -> ::capnp::Result<()> { + pointer.set_struct(&value.reader, canonicalize) + } + } + + impl<'a, Key, Value> Builder<'a, Key, Value> + where + Key: for<'c> ::capnp::traits::Owned<'c>, + Value: for<'c> ::capnp::traits::Owned<'c>, + { + pub fn into_reader(self) -> Reader<'a, Key, Value> { + ::capnp::traits::FromStructReader::new(self.builder.into_reader()) + } + pub fn reborrow(&mut self) -> Builder<'_, Key, Value> { + Builder { ..*self } + } + pub fn reborrow_as_reader(&self) -> Reader<'_, Key, Value> { + ::capnp::traits::FromStructReader::new(self.builder.into_reader()) + } + + pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> { + self.builder.into_reader().total_size() + } + #[inline] + pub fn get_entries( + self, + ) -> ::capnp::Result< + ::capnp::struct_list::Builder<'a, crate::plugin_capnp::map::entry::Owned>, + > { + ::capnp::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(0), + ::core::option::Option::None, + ) + } + #[inline] + pub fn set_entries( + &mut self, + value: ::capnp::struct_list::Reader< + 'a, + crate::plugin_capnp::map::entry::Owned, + >, + ) -> ::capnp::Result<()> { + ::capnp::traits::SetPointerBuilder::set_pointer_builder( + self.builder.get_pointer_field(0), + value, + false, + ) + } + #[inline] + pub fn init_entries( + self, + size: u32, + ) -> ::capnp::struct_list::Builder<'a, crate::plugin_capnp::map::entry::Owned> + { + ::capnp::traits::FromPointerBuilder::init_pointer( + self.builder.get_pointer_field(0), + size, + ) + } + pub fn has_entries(&self) -> bool { + !self.builder.get_pointer_field(0).is_null() + } + } + + pub struct Pipeline { + _typeless: ::capnp::any_pointer::Pipeline, + _phantom: ::core::marker::PhantomData<(Key, Value)>, + } + impl ::capnp::capability::FromTypelessPipeline for Pipeline { + fn new(typeless: ::capnp::any_pointer::Pipeline) -> Pipeline { + Pipeline { + _typeless: typeless, + _phantom: ::core::marker::PhantomData, + } + } + } + impl Pipeline + where + Key: ::capnp::traits::Pipelined, + ::Pipeline: ::capnp::capability::FromTypelessPipeline, + Value: ::capnp::traits::Pipelined, + ::Pipeline: ::capnp::capability::FromTypelessPipeline, + { + } + mod _private { + use capnp::private::layout; + pub const STRUCT_SIZE: layout::StructSize = layout::StructSize { + data: 0, + pointers: 1, + }; + pub const TYPE_ID: u64 = 0x9783_acc1_0be0_6fce; + } + + pub mod entry { + /* Key,Value */ + #[derive(Copy, Clone)] + pub struct Owned { + _phantom: ::core::marker::PhantomData<(Key, Value)>, + } + impl<'a, Key, Value> ::capnp::traits::Owned<'a> for Owned + where + Key: for<'c> ::capnp::traits::Owned<'c>, + Value: for<'c> ::capnp::traits::Owned<'c>, + { + type Reader = Reader<'a, Key, Value>; + type Builder = Builder<'a, Key, Value>; + } + impl<'a, Key, Value> ::capnp::traits::OwnedStruct<'a> for Owned + where + Key: for<'c> ::capnp::traits::Owned<'c>, + Value: for<'c> ::capnp::traits::Owned<'c>, + { + type Reader = Reader<'a, Key, Value>; + type Builder = Builder<'a, Key, Value>; + } + impl ::capnp::traits::Pipelined for Owned + where + Key: for<'c> ::capnp::traits::Owned<'c>, + Value: for<'c> ::capnp::traits::Owned<'c>, + { + type Pipeline = Pipeline; + } + + #[derive(Clone, Copy)] + pub struct Reader<'a, Key, Value> + where + Key: for<'c> ::capnp::traits::Owned<'c>, + Value: for<'c> ::capnp::traits::Owned<'c>, + { + reader: ::capnp::private::layout::StructReader<'a>, + _phantom: ::core::marker::PhantomData<(Key, Value)>, + } + + impl<'a, Key, Value> ::capnp::traits::HasTypeId for Reader<'a, Key, Value> + where + Key: for<'c> ::capnp::traits::Owned<'c>, + Value: for<'c> ::capnp::traits::Owned<'c>, + { + #[inline] + fn type_id() -> u64 { + _private::TYPE_ID + } + } + impl<'a, Key, Value> ::capnp::traits::FromStructReader<'a> for Reader<'a, Key, Value> + where + Key: for<'c> ::capnp::traits::Owned<'c>, + Value: for<'c> ::capnp::traits::Owned<'c>, + { + fn new(reader: ::capnp::private::layout::StructReader<'a>) -> Reader<'a, Key, Value> { + Reader { + reader, + _phantom: ::core::marker::PhantomData, + } + } + } + + impl<'a, Key, Value> ::capnp::traits::FromPointerReader<'a> for Reader<'a, Key, Value> + where + Key: for<'c> ::capnp::traits::Owned<'c>, + Value: for<'c> ::capnp::traits::Owned<'c>, + { + fn get_from_pointer( + reader: &::capnp::private::layout::PointerReader<'a>, + default: ::core::option::Option<&'a [capnp::Word]>, + ) -> ::capnp::Result> { + ::core::result::Result::Ok(::capnp::traits::FromStructReader::new( + reader.get_struct(default)?, + )) + } + } + + impl<'a, Key, Value> ::capnp::traits::IntoInternalStructReader<'a> for Reader<'a, Key, Value> + where + Key: for<'c> ::capnp::traits::Owned<'c>, + Value: for<'c> ::capnp::traits::Owned<'c>, + { + fn into_internal_struct_reader(self) -> ::capnp::private::layout::StructReader<'a> { + self.reader + } + } + + impl<'a, Key, Value> ::capnp::traits::Imbue<'a> for Reader<'a, Key, Value> + where + Key: for<'c> ::capnp::traits::Owned<'c>, + Value: for<'c> ::capnp::traits::Owned<'c>, + { + fn imbue(&mut self, cap_table: &'a ::capnp::private::layout::CapTable) { + self.reader + .imbue(::capnp::private::layout::CapTableReader::Plain(cap_table)) + } + } + + impl<'a, Key, Value> Reader<'a, Key, Value> + where + Key: for<'c> ::capnp::traits::Owned<'c>, + Value: for<'c> ::capnp::traits::Owned<'c>, + { + pub fn reborrow(&self) -> Reader<'_, Key, Value> { + Reader { ..*self } + } + + pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> { + self.reader.total_size() + } + #[inline] + pub fn get_key(self) -> ::capnp::Result<>::Reader> { + ::capnp::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(0), + ::core::option::Option::None, + ) + } + pub fn has_key(&self) -> bool { + !self.reader.get_pointer_field(0).is_null() + } + #[inline] + pub fn get_value( + self, + ) -> ::capnp::Result<>::Reader> { + ::capnp::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(1), + ::core::option::Option::None, + ) + } + pub fn has_value(&self) -> bool { + !self.reader.get_pointer_field(1).is_null() + } + } + + pub struct Builder<'a, Key, Value> + where + Key: for<'c> ::capnp::traits::Owned<'c>, + Value: for<'c> ::capnp::traits::Owned<'c>, + { + builder: ::capnp::private::layout::StructBuilder<'a>, + _phantom: ::core::marker::PhantomData<(Key, Value)>, + } + impl<'a, Key, Value> ::capnp::traits::HasStructSize for Builder<'a, Key, Value> + where + Key: for<'c> ::capnp::traits::Owned<'c>, + Value: for<'c> ::capnp::traits::Owned<'c>, + { + #[inline] + fn struct_size() -> ::capnp::private::layout::StructSize { + _private::STRUCT_SIZE + } + } + impl<'a, Key, Value> ::capnp::traits::HasTypeId for Builder<'a, Key, Value> + where + Key: for<'c> ::capnp::traits::Owned<'c>, + Value: for<'c> ::capnp::traits::Owned<'c>, + { + #[inline] + fn type_id() -> u64 { + _private::TYPE_ID + } + } + impl<'a, Key, Value> ::capnp::traits::FromStructBuilder<'a> for Builder<'a, Key, Value> + where + Key: for<'c> ::capnp::traits::Owned<'c>, + Value: for<'c> ::capnp::traits::Owned<'c>, + { + fn new( + builder: ::capnp::private::layout::StructBuilder<'a>, + ) -> Builder<'a, Key, Value> { + Builder { + builder, + _phantom: ::core::marker::PhantomData, + } + } + } + + impl<'a, Key, Value> ::capnp::traits::ImbueMut<'a> for Builder<'a, Key, Value> + where + Key: for<'c> ::capnp::traits::Owned<'c>, + Value: for<'c> ::capnp::traits::Owned<'c>, + { + fn imbue_mut(&mut self, cap_table: &'a mut ::capnp::private::layout::CapTable) { + self.builder + .imbue(::capnp::private::layout::CapTableBuilder::Plain(cap_table)) + } + } + + impl<'a, Key, Value> ::capnp::traits::FromPointerBuilder<'a> for Builder<'a, Key, Value> + where + Key: for<'c> ::capnp::traits::Owned<'c>, + Value: for<'c> ::capnp::traits::Owned<'c>, + { + fn init_pointer( + builder: ::capnp::private::layout::PointerBuilder<'a>, + _size: u32, + ) -> Builder<'a, Key, Value> { + ::capnp::traits::FromStructBuilder::new(builder.init_struct(_private::STRUCT_SIZE)) + } + fn get_from_pointer( + builder: ::capnp::private::layout::PointerBuilder<'a>, + default: ::core::option::Option<&'a [capnp::Word]>, + ) -> ::capnp::Result> { + ::core::result::Result::Ok(::capnp::traits::FromStructBuilder::new( + builder.get_struct(_private::STRUCT_SIZE, default)?, + )) + } + } + + impl<'a, Key, Value> ::capnp::traits::SetPointerBuilder for Reader<'a, Key, Value> + where + Key: for<'c> ::capnp::traits::Owned<'c>, + Value: for<'c> ::capnp::traits::Owned<'c>, + { + fn set_pointer_builder<'b>( + pointer: ::capnp::private::layout::PointerBuilder<'b>, + value: Reader<'a, Key, Value>, + canonicalize: bool, + ) -> ::capnp::Result<()> { + pointer.set_struct(&value.reader, canonicalize) + } + } + + impl<'a, Key, Value> Builder<'a, Key, Value> + where + Key: for<'c> ::capnp::traits::Owned<'c>, + Value: for<'c> ::capnp::traits::Owned<'c>, + { + pub fn into_reader(self) -> Reader<'a, Key, Value> { + ::capnp::traits::FromStructReader::new(self.builder.into_reader()) + } + pub fn reborrow(&mut self) -> Builder<'_, Key, Value> { + Builder { ..*self } + } + pub fn reborrow_as_reader(&self) -> Reader<'_, Key, Value> { + ::capnp::traits::FromStructReader::new(self.builder.into_reader()) + } + + pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> { + self.builder.into_reader().total_size() + } + #[inline] + pub fn get_key(self) -> ::capnp::Result<>::Builder> { + ::capnp::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(0), + ::core::option::Option::None, + ) + } + #[inline] + pub fn initn_key(self, length: u32) -> >::Builder { + ::capnp::any_pointer::Builder::new(self.builder.get_pointer_field(0)) + .initn_as(length) + } + #[inline] + pub fn set_key( + &mut self, + value: >::Reader, + ) -> ::capnp::Result<()> { + ::capnp::traits::SetPointerBuilder::set_pointer_builder( + self.builder.get_pointer_field(0), + value, + false, + ) + } + #[inline] + pub fn init_key(self) -> >::Builder { + ::capnp::any_pointer::Builder::new(self.builder.get_pointer_field(0)).init_as() + } + pub fn has_key(&self) -> bool { + !self.builder.get_pointer_field(0).is_null() + } + #[inline] + pub fn get_value( + self, + ) -> ::capnp::Result<>::Builder> { + ::capnp::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(1), + ::core::option::Option::None, + ) + } + #[inline] + pub fn initn_value( + self, + length: u32, + ) -> >::Builder { + ::capnp::any_pointer::Builder::new(self.builder.get_pointer_field(1)) + .initn_as(length) + } + #[inline] + pub fn set_value( + &mut self, + value: >::Reader, + ) -> ::capnp::Result<()> { + ::capnp::traits::SetPointerBuilder::set_pointer_builder( + self.builder.get_pointer_field(1), + value, + false, + ) + } + #[inline] + pub fn init_value(self) -> >::Builder { + ::capnp::any_pointer::Builder::new(self.builder.get_pointer_field(1)).init_as() + } + pub fn has_value(&self) -> bool { + !self.builder.get_pointer_field(1).is_null() + } + } + + pub struct Pipeline { + _typeless: ::capnp::any_pointer::Pipeline, + _phantom: ::core::marker::PhantomData<(Key, Value)>, + } + impl ::capnp::capability::FromTypelessPipeline for Pipeline { + fn new(typeless: ::capnp::any_pointer::Pipeline) -> Pipeline { + Pipeline { + _typeless: typeless, + _phantom: ::core::marker::PhantomData, + } + } + } + impl Pipeline + where + Key: ::capnp::traits::Pipelined, + ::Pipeline: + ::capnp::capability::FromTypelessPipeline, + Value: ::capnp::traits::Pipelined, + ::Pipeline: + ::capnp::capability::FromTypelessPipeline, + { + pub fn get_key(&self) -> ::Pipeline { + ::capnp::capability::FromTypelessPipeline::new(self._typeless.get_pointer_field(0)) + } + pub fn get_value(&self) -> ::Pipeline { + ::capnp::capability::FromTypelessPipeline::new(self._typeless.get_pointer_field(1)) + } + } + mod _private { + use capnp::private::layout; + pub const STRUCT_SIZE: layout::StructSize = layout::StructSize { + data: 0, + pointers: 2, + }; + pub const TYPE_ID: u64 = 0xde4c_62ad_0c9f_67c3; + } + } +} + +pub mod span { + #[derive(Copy, Clone)] + pub struct Owned(()); + impl<'a> ::capnp::traits::Owned<'a> for Owned { + type Reader = Reader<'a>; + type Builder = Builder<'a>; + } + impl<'a> ::capnp::traits::OwnedStruct<'a> for Owned { + type Reader = Reader<'a>; + type Builder = Builder<'a>; + } + impl ::capnp::traits::Pipelined for Owned { + type Pipeline = Pipeline; + } + + #[derive(Clone, Copy)] + pub struct Reader<'a> { + reader: ::capnp::private::layout::StructReader<'a>, + } + + impl<'a> ::capnp::traits::HasTypeId for Reader<'a> { + #[inline] + fn type_id() -> u64 { + _private::TYPE_ID + } + } + impl<'a> ::capnp::traits::FromStructReader<'a> for Reader<'a> { + fn new(reader: ::capnp::private::layout::StructReader<'a>) -> Reader<'a> { + Reader { reader } + } + } + + impl<'a> ::capnp::traits::FromPointerReader<'a> for Reader<'a> { + fn get_from_pointer( + reader: &::capnp::private::layout::PointerReader<'a>, + default: ::core::option::Option<&'a [capnp::Word]>, + ) -> ::capnp::Result> { + ::core::result::Result::Ok(::capnp::traits::FromStructReader::new( + reader.get_struct(default)?, + )) + } + } + + impl<'a> ::capnp::traits::IntoInternalStructReader<'a> for Reader<'a> { + fn into_internal_struct_reader(self) -> ::capnp::private::layout::StructReader<'a> { + self.reader + } + } + + impl<'a> ::capnp::traits::Imbue<'a> for Reader<'a> { + fn imbue(&mut self, cap_table: &'a ::capnp::private::layout::CapTable) { + self.reader + .imbue(::capnp::private::layout::CapTableReader::Plain(cap_table)) + } + } + + impl<'a> Reader<'a> { + pub fn reborrow(&self) -> Reader<'_> { + Reader { ..*self } + } + + pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> { + self.reader.total_size() + } + #[inline] + pub fn get_start(self) -> u64 { + self.reader.get_data_field::(0) + } + #[inline] + pub fn get_end(self) -> u64 { + self.reader.get_data_field::(1) + } + } + + pub struct Builder<'a> { + builder: ::capnp::private::layout::StructBuilder<'a>, + } + impl<'a> ::capnp::traits::HasStructSize for Builder<'a> { + #[inline] + fn struct_size() -> ::capnp::private::layout::StructSize { + _private::STRUCT_SIZE + } + } + impl<'a> ::capnp::traits::HasTypeId for Builder<'a> { + #[inline] + fn type_id() -> u64 { + _private::TYPE_ID + } + } + impl<'a> ::capnp::traits::FromStructBuilder<'a> for Builder<'a> { + fn new(builder: ::capnp::private::layout::StructBuilder<'a>) -> Builder<'a> { + Builder { builder } + } + } + + impl<'a> ::capnp::traits::ImbueMut<'a> for Builder<'a> { + fn imbue_mut(&mut self, cap_table: &'a mut ::capnp::private::layout::CapTable) { + self.builder + .imbue(::capnp::private::layout::CapTableBuilder::Plain(cap_table)) + } + } + + impl<'a> ::capnp::traits::FromPointerBuilder<'a> for Builder<'a> { + fn init_pointer( + builder: ::capnp::private::layout::PointerBuilder<'a>, + _size: u32, + ) -> Builder<'a> { + ::capnp::traits::FromStructBuilder::new(builder.init_struct(_private::STRUCT_SIZE)) + } + fn get_from_pointer( + builder: ::capnp::private::layout::PointerBuilder<'a>, + default: ::core::option::Option<&'a [capnp::Word]>, + ) -> ::capnp::Result> { + ::core::result::Result::Ok(::capnp::traits::FromStructBuilder::new( + builder.get_struct(_private::STRUCT_SIZE, default)?, + )) + } + } + + impl<'a> ::capnp::traits::SetPointerBuilder for Reader<'a> { + fn set_pointer_builder<'b>( + pointer: ::capnp::private::layout::PointerBuilder<'b>, + value: Reader<'a>, + canonicalize: bool, + ) -> ::capnp::Result<()> { + pointer.set_struct(&value.reader, canonicalize) + } + } + + impl<'a> Builder<'a> { + pub fn into_reader(self) -> Reader<'a> { + ::capnp::traits::FromStructReader::new(self.builder.into_reader()) + } + pub fn reborrow(&mut self) -> Builder<'_> { + Builder { ..*self } + } + pub fn reborrow_as_reader(&self) -> Reader<'_> { + ::capnp::traits::FromStructReader::new(self.builder.into_reader()) + } + + pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> { + self.builder.into_reader().total_size() + } + #[inline] + pub fn get_start(self) -> u64 { + self.builder.get_data_field::(0) + } + #[inline] + pub fn set_start(&mut self, value: u64) { + self.builder.set_data_field::(0, value); + } + #[inline] + pub fn get_end(self) -> u64 { + self.builder.get_data_field::(1) + } + #[inline] + pub fn set_end(&mut self, value: u64) { + self.builder.set_data_field::(1, value); + } + } + + pub struct Pipeline { + _typeless: ::capnp::any_pointer::Pipeline, + } + impl ::capnp::capability::FromTypelessPipeline for Pipeline { + fn new(typeless: ::capnp::any_pointer::Pipeline) -> Pipeline { + Pipeline { + _typeless: typeless, + } + } + } + impl Pipeline {} + mod _private { + use capnp::private::layout; + pub const STRUCT_SIZE: layout::StructSize = layout::StructSize { + data: 2, + pointers: 0, + }; + pub const TYPE_ID: u64 = 0xe8b6_78b5_d953_4593; + } +} + +pub mod value { + pub use self::Which::{Bool, Float, Int, List, String, Void}; + + #[derive(Copy, Clone)] + pub struct Owned(()); + impl<'a> ::capnp::traits::Owned<'a> for Owned { + type Reader = Reader<'a>; + type Builder = Builder<'a>; + } + impl<'a> ::capnp::traits::OwnedStruct<'a> for Owned { + type Reader = Reader<'a>; + type Builder = Builder<'a>; + } + impl ::capnp::traits::Pipelined for Owned { + type Pipeline = Pipeline; + } + + #[derive(Clone, Copy)] + pub struct Reader<'a> { + reader: ::capnp::private::layout::StructReader<'a>, + } + + impl<'a> ::capnp::traits::HasTypeId for Reader<'a> { + #[inline] + fn type_id() -> u64 { + _private::TYPE_ID + } + } + impl<'a> ::capnp::traits::FromStructReader<'a> for Reader<'a> { + fn new(reader: ::capnp::private::layout::StructReader<'a>) -> Reader<'a> { + Reader { reader } + } + } + + impl<'a> ::capnp::traits::FromPointerReader<'a> for Reader<'a> { + fn get_from_pointer( + reader: &::capnp::private::layout::PointerReader<'a>, + default: ::core::option::Option<&'a [capnp::Word]>, + ) -> ::capnp::Result> { + ::core::result::Result::Ok(::capnp::traits::FromStructReader::new( + reader.get_struct(default)?, + )) + } + } + + impl<'a> ::capnp::traits::IntoInternalStructReader<'a> for Reader<'a> { + fn into_internal_struct_reader(self) -> ::capnp::private::layout::StructReader<'a> { + self.reader + } + } + + impl<'a> ::capnp::traits::Imbue<'a> for Reader<'a> { + fn imbue(&mut self, cap_table: &'a ::capnp::private::layout::CapTable) { + self.reader + .imbue(::capnp::private::layout::CapTableReader::Plain(cap_table)) + } + } + + impl<'a> Reader<'a> { + pub fn reborrow(&self) -> Reader<'_> { + Reader { ..*self } + } + + pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> { + self.reader.total_size() + } + #[inline] + pub fn get_span(self) -> ::capnp::Result> { + ::capnp::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(0), + ::core::option::Option::None, + ) + } + pub fn has_span(&self) -> bool { + !self.reader.get_pointer_field(0).is_null() + } + pub fn has_string(&self) -> bool { + if self.reader.get_data_field::(0) != 4 { + return false; + } + !self.reader.get_pointer_field(1).is_null() + } + pub fn has_list(&self) -> bool { + if self.reader.get_data_field::(0) != 5 { + return false; + } + !self.reader.get_pointer_field(1).is_null() + } + #[inline] + pub fn which(self) -> ::core::result::Result, ::capnp::NotInSchema> { + match self.reader.get_data_field::(0) { + 0 => ::core::result::Result::Ok(Void(())), + 1 => ::core::result::Result::Ok(Bool(self.reader.get_bool_field(16))), + 2 => ::core::result::Result::Ok(Int(self.reader.get_data_field::(1))), + 3 => ::core::result::Result::Ok(Float(self.reader.get_data_field::(1))), + 4 => ::core::result::Result::Ok(String( + ::capnp::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(1), + ::core::option::Option::None, + ), + )), + 5 => ::core::result::Result::Ok(List( + ::capnp::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(1), + ::core::option::Option::None, + ), + )), + x => ::core::result::Result::Err(::capnp::NotInSchema(x)), + } + } + } + + pub struct Builder<'a> { + builder: ::capnp::private::layout::StructBuilder<'a>, + } + impl<'a> ::capnp::traits::HasStructSize for Builder<'a> { + #[inline] + fn struct_size() -> ::capnp::private::layout::StructSize { + _private::STRUCT_SIZE + } + } + impl<'a> ::capnp::traits::HasTypeId for Builder<'a> { + #[inline] + fn type_id() -> u64 { + _private::TYPE_ID + } + } + impl<'a> ::capnp::traits::FromStructBuilder<'a> for Builder<'a> { + fn new(builder: ::capnp::private::layout::StructBuilder<'a>) -> Builder<'a> { + Builder { builder } + } + } + + impl<'a> ::capnp::traits::ImbueMut<'a> for Builder<'a> { + fn imbue_mut(&mut self, cap_table: &'a mut ::capnp::private::layout::CapTable) { + self.builder + .imbue(::capnp::private::layout::CapTableBuilder::Plain(cap_table)) + } + } + + impl<'a> ::capnp::traits::FromPointerBuilder<'a> for Builder<'a> { + fn init_pointer( + builder: ::capnp::private::layout::PointerBuilder<'a>, + _size: u32, + ) -> Builder<'a> { + ::capnp::traits::FromStructBuilder::new(builder.init_struct(_private::STRUCT_SIZE)) + } + fn get_from_pointer( + builder: ::capnp::private::layout::PointerBuilder<'a>, + default: ::core::option::Option<&'a [capnp::Word]>, + ) -> ::capnp::Result> { + ::core::result::Result::Ok(::capnp::traits::FromStructBuilder::new( + builder.get_struct(_private::STRUCT_SIZE, default)?, + )) + } + } + + impl<'a> ::capnp::traits::SetPointerBuilder for Reader<'a> { + fn set_pointer_builder<'b>( + pointer: ::capnp::private::layout::PointerBuilder<'b>, + value: Reader<'a>, + canonicalize: bool, + ) -> ::capnp::Result<()> { + pointer.set_struct(&value.reader, canonicalize) + } + } + + impl<'a> Builder<'a> { + pub fn into_reader(self) -> Reader<'a> { + ::capnp::traits::FromStructReader::new(self.builder.into_reader()) + } + pub fn reborrow(&mut self) -> Builder<'_> { + Builder { ..*self } + } + pub fn reborrow_as_reader(&self) -> Reader<'_> { + ::capnp::traits::FromStructReader::new(self.builder.into_reader()) + } + + pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> { + self.builder.into_reader().total_size() + } + #[inline] + pub fn get_span(self) -> ::capnp::Result> { + ::capnp::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(0), + ::core::option::Option::None, + ) + } + #[inline] + pub fn set_span( + &mut self, + value: crate::plugin_capnp::span::Reader<'_>, + ) -> ::capnp::Result<()> { + ::capnp::traits::SetPointerBuilder::set_pointer_builder( + self.builder.get_pointer_field(0), + value, + false, + ) + } + #[inline] + pub fn init_span(self) -> crate::plugin_capnp::span::Builder<'a> { + ::capnp::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(0), 0) + } + pub fn has_span(&self) -> bool { + !self.builder.get_pointer_field(0).is_null() + } + #[inline] + pub fn set_void(&mut self, _value: ()) { + self.builder.set_data_field::(0, 0); + } + #[inline] + pub fn set_bool(&mut self, value: bool) { + self.builder.set_data_field::(0, 1); + self.builder.set_bool_field(16, value); + } + #[inline] + pub fn set_int(&mut self, value: i64) { + self.builder.set_data_field::(0, 2); + self.builder.set_data_field::(1, value); + } + #[inline] + pub fn set_float(&mut self, value: f64) { + self.builder.set_data_field::(0, 3); + self.builder.set_data_field::(1, value); + } + #[inline] + pub fn set_string(&mut self, value: ::capnp::text::Reader<'_>) { + self.builder.set_data_field::(0, 4); + self.builder.get_pointer_field(1).set_text(value); + } + #[inline] + pub fn init_string(self, size: u32) -> ::capnp::text::Builder<'a> { + self.builder.set_data_field::(0, 4); + self.builder.get_pointer_field(1).init_text(size) + } + pub fn has_string(&self) -> bool { + if self.builder.get_data_field::(0) != 4 { + return false; + } + !self.builder.get_pointer_field(1).is_null() + } + #[inline] + pub fn set_list( + &mut self, + value: ::capnp::struct_list::Reader<'a, crate::plugin_capnp::value::Owned>, + ) -> ::capnp::Result<()> { + self.builder.set_data_field::(0, 5); + ::capnp::traits::SetPointerBuilder::set_pointer_builder( + self.builder.get_pointer_field(1), + value, + false, + ) + } + #[inline] + pub fn init_list( + self, + size: u32, + ) -> ::capnp::struct_list::Builder<'a, crate::plugin_capnp::value::Owned> { + self.builder.set_data_field::(0, 5); + ::capnp::traits::FromPointerBuilder::init_pointer( + self.builder.get_pointer_field(1), + size, + ) + } + pub fn has_list(&self) -> bool { + if self.builder.get_data_field::(0) != 5 { + return false; + } + !self.builder.get_pointer_field(1).is_null() + } + #[inline] + pub fn which(self) -> ::core::result::Result, ::capnp::NotInSchema> { + match self.builder.get_data_field::(0) { + 0 => ::core::result::Result::Ok(Void(())), + 1 => ::core::result::Result::Ok(Bool(self.builder.get_bool_field(16))), + 2 => ::core::result::Result::Ok(Int(self.builder.get_data_field::(1))), + 3 => ::core::result::Result::Ok(Float(self.builder.get_data_field::(1))), + 4 => ::core::result::Result::Ok(String( + ::capnp::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(1), + ::core::option::Option::None, + ), + )), + 5 => ::core::result::Result::Ok(List( + ::capnp::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(1), + ::core::option::Option::None, + ), + )), + x => ::core::result::Result::Err(::capnp::NotInSchema(x)), + } + } + } + + pub struct Pipeline { + _typeless: ::capnp::any_pointer::Pipeline, + } + impl ::capnp::capability::FromTypelessPipeline for Pipeline { + fn new(typeless: ::capnp::any_pointer::Pipeline) -> Pipeline { + Pipeline { + _typeless: typeless, + } + } + } + impl Pipeline { + pub fn get_span(&self) -> crate::plugin_capnp::span::Pipeline { + ::capnp::capability::FromTypelessPipeline::new(self._typeless.get_pointer_field(0)) + } + } + mod _private { + use capnp::private::layout; + pub const STRUCT_SIZE: layout::StructSize = layout::StructSize { + data: 2, + pointers: 2, + }; + pub const TYPE_ID: u64 = 0x92a0_59fb_5627_86a8; + } + pub enum Which { + Void(()), + Bool(bool), + Int(i64), + Float(f64), + String(A0), + List(A1), + } + pub type WhichReader<'a> = Which< + ::capnp::Result<::capnp::text::Reader<'a>>, + ::capnp::Result<::capnp::struct_list::Reader<'a, crate::plugin_capnp::value::Owned>>, + >; + pub type WhichBuilder<'a> = Which< + ::capnp::Result<::capnp::text::Builder<'a>>, + ::capnp::Result<::capnp::struct_list::Builder<'a, crate::plugin_capnp::value::Owned>>, + >; +} + +pub mod signature { + #[derive(Copy, Clone)] + pub struct Owned(()); + impl<'a> ::capnp::traits::Owned<'a> for Owned { + type Reader = Reader<'a>; + type Builder = Builder<'a>; + } + impl<'a> ::capnp::traits::OwnedStruct<'a> for Owned { + type Reader = Reader<'a>; + type Builder = Builder<'a>; + } + impl ::capnp::traits::Pipelined for Owned { + type Pipeline = Pipeline; + } + + #[derive(Clone, Copy)] + pub struct Reader<'a> { + reader: ::capnp::private::layout::StructReader<'a>, + } + + impl<'a> ::capnp::traits::HasTypeId for Reader<'a> { + #[inline] + fn type_id() -> u64 { + _private::TYPE_ID + } + } + impl<'a> ::capnp::traits::FromStructReader<'a> for Reader<'a> { + fn new(reader: ::capnp::private::layout::StructReader<'a>) -> Reader<'a> { + Reader { reader } + } + } + + impl<'a> ::capnp::traits::FromPointerReader<'a> for Reader<'a> { + fn get_from_pointer( + reader: &::capnp::private::layout::PointerReader<'a>, + default: ::core::option::Option<&'a [capnp::Word]>, + ) -> ::capnp::Result> { + ::core::result::Result::Ok(::capnp::traits::FromStructReader::new( + reader.get_struct(default)?, + )) + } + } + + impl<'a> ::capnp::traits::IntoInternalStructReader<'a> for Reader<'a> { + fn into_internal_struct_reader(self) -> ::capnp::private::layout::StructReader<'a> { + self.reader + } + } + + impl<'a> ::capnp::traits::Imbue<'a> for Reader<'a> { + fn imbue(&mut self, cap_table: &'a ::capnp::private::layout::CapTable) { + self.reader + .imbue(::capnp::private::layout::CapTableReader::Plain(cap_table)) + } + } + + impl<'a> Reader<'a> { + pub fn reborrow(&self) -> Reader<'_> { + Reader { ..*self } + } + + pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> { + self.reader.total_size() + } + #[inline] + pub fn get_name(self) -> ::capnp::Result<::capnp::text::Reader<'a>> { + ::capnp::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(0), + ::core::option::Option::None, + ) + } + pub fn has_name(&self) -> bool { + !self.reader.get_pointer_field(0).is_null() + } + #[inline] + pub fn get_usage(self) -> ::capnp::Result<::capnp::text::Reader<'a>> { + ::capnp::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(1), + ::core::option::Option::None, + ) + } + pub fn has_usage(&self) -> bool { + !self.reader.get_pointer_field(1).is_null() + } + #[inline] + pub fn get_extra_usage(self) -> ::capnp::Result<::capnp::text::Reader<'a>> { + ::capnp::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(2), + ::core::option::Option::None, + ) + } + pub fn has_extra_usage(&self) -> bool { + !self.reader.get_pointer_field(2).is_null() + } + #[inline] + pub fn get_required_positional( + self, + ) -> ::capnp::Result<::capnp::struct_list::Reader<'a, crate::plugin_capnp::argument::Owned>> + { + ::capnp::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(3), + ::core::option::Option::None, + ) + } + pub fn has_required_positional(&self) -> bool { + !self.reader.get_pointer_field(3).is_null() + } + #[inline] + pub fn get_optional_positional( + self, + ) -> ::capnp::Result<::capnp::struct_list::Reader<'a, crate::plugin_capnp::argument::Owned>> + { + ::capnp::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(4), + ::core::option::Option::None, + ) + } + pub fn has_optional_positional(&self) -> bool { + !self.reader.get_pointer_field(4).is_null() + } + #[inline] + pub fn get_rest( + self, + ) -> ::capnp::Result< + crate::plugin_capnp::option::Reader<'a, crate::plugin_capnp::argument::Owned>, + > { + ::capnp::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(5), + ::core::option::Option::None, + ) + } + pub fn has_rest(&self) -> bool { + !self.reader.get_pointer_field(5).is_null() + } + #[inline] + pub fn get_named( + self, + ) -> ::capnp::Result<::capnp::struct_list::Reader<'a, crate::plugin_capnp::flag::Owned>> + { + ::capnp::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(6), + ::core::option::Option::None, + ) + } + pub fn has_named(&self) -> bool { + !self.reader.get_pointer_field(6).is_null() + } + #[inline] + pub fn get_is_filter(self) -> bool { + self.reader.get_bool_field(0) + } + } + + pub struct Builder<'a> { + builder: ::capnp::private::layout::StructBuilder<'a>, + } + impl<'a> ::capnp::traits::HasStructSize for Builder<'a> { + #[inline] + fn struct_size() -> ::capnp::private::layout::StructSize { + _private::STRUCT_SIZE + } + } + impl<'a> ::capnp::traits::HasTypeId for Builder<'a> { + #[inline] + fn type_id() -> u64 { + _private::TYPE_ID + } + } + impl<'a> ::capnp::traits::FromStructBuilder<'a> for Builder<'a> { + fn new(builder: ::capnp::private::layout::StructBuilder<'a>) -> Builder<'a> { + Builder { builder } + } + } + + impl<'a> ::capnp::traits::ImbueMut<'a> for Builder<'a> { + fn imbue_mut(&mut self, cap_table: &'a mut ::capnp::private::layout::CapTable) { + self.builder + .imbue(::capnp::private::layout::CapTableBuilder::Plain(cap_table)) + } + } + + impl<'a> ::capnp::traits::FromPointerBuilder<'a> for Builder<'a> { + fn init_pointer( + builder: ::capnp::private::layout::PointerBuilder<'a>, + _size: u32, + ) -> Builder<'a> { + ::capnp::traits::FromStructBuilder::new(builder.init_struct(_private::STRUCT_SIZE)) + } + fn get_from_pointer( + builder: ::capnp::private::layout::PointerBuilder<'a>, + default: ::core::option::Option<&'a [capnp::Word]>, + ) -> ::capnp::Result> { + ::core::result::Result::Ok(::capnp::traits::FromStructBuilder::new( + builder.get_struct(_private::STRUCT_SIZE, default)?, + )) + } + } + + impl<'a> ::capnp::traits::SetPointerBuilder for Reader<'a> { + fn set_pointer_builder<'b>( + pointer: ::capnp::private::layout::PointerBuilder<'b>, + value: Reader<'a>, + canonicalize: bool, + ) -> ::capnp::Result<()> { + pointer.set_struct(&value.reader, canonicalize) + } + } + + impl<'a> Builder<'a> { + pub fn into_reader(self) -> Reader<'a> { + ::capnp::traits::FromStructReader::new(self.builder.into_reader()) + } + pub fn reborrow(&mut self) -> Builder<'_> { + Builder { ..*self } + } + pub fn reborrow_as_reader(&self) -> Reader<'_> { + ::capnp::traits::FromStructReader::new(self.builder.into_reader()) + } + + pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> { + self.builder.into_reader().total_size() + } + #[inline] + pub fn get_name(self) -> ::capnp::Result<::capnp::text::Builder<'a>> { + ::capnp::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(0), + ::core::option::Option::None, + ) + } + #[inline] + pub fn set_name(&mut self, value: ::capnp::text::Reader<'_>) { + self.builder.get_pointer_field(0).set_text(value); + } + #[inline] + pub fn init_name(self, size: u32) -> ::capnp::text::Builder<'a> { + self.builder.get_pointer_field(0).init_text(size) + } + pub fn has_name(&self) -> bool { + !self.builder.get_pointer_field(0).is_null() + } + #[inline] + pub fn get_usage(self) -> ::capnp::Result<::capnp::text::Builder<'a>> { + ::capnp::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(1), + ::core::option::Option::None, + ) + } + #[inline] + pub fn set_usage(&mut self, value: ::capnp::text::Reader<'_>) { + self.builder.get_pointer_field(1).set_text(value); + } + #[inline] + pub fn init_usage(self, size: u32) -> ::capnp::text::Builder<'a> { + self.builder.get_pointer_field(1).init_text(size) + } + pub fn has_usage(&self) -> bool { + !self.builder.get_pointer_field(1).is_null() + } + #[inline] + pub fn get_extra_usage(self) -> ::capnp::Result<::capnp::text::Builder<'a>> { + ::capnp::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(2), + ::core::option::Option::None, + ) + } + #[inline] + pub fn set_extra_usage(&mut self, value: ::capnp::text::Reader<'_>) { + self.builder.get_pointer_field(2).set_text(value); + } + #[inline] + pub fn init_extra_usage(self, size: u32) -> ::capnp::text::Builder<'a> { + self.builder.get_pointer_field(2).init_text(size) + } + pub fn has_extra_usage(&self) -> bool { + !self.builder.get_pointer_field(2).is_null() + } + #[inline] + pub fn get_required_positional( + self, + ) -> ::capnp::Result<::capnp::struct_list::Builder<'a, crate::plugin_capnp::argument::Owned>> + { + ::capnp::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(3), + ::core::option::Option::None, + ) + } + #[inline] + pub fn set_required_positional( + &mut self, + value: ::capnp::struct_list::Reader<'a, crate::plugin_capnp::argument::Owned>, + ) -> ::capnp::Result<()> { + ::capnp::traits::SetPointerBuilder::set_pointer_builder( + self.builder.get_pointer_field(3), + value, + false, + ) + } + #[inline] + pub fn init_required_positional( + self, + size: u32, + ) -> ::capnp::struct_list::Builder<'a, crate::plugin_capnp::argument::Owned> { + ::capnp::traits::FromPointerBuilder::init_pointer( + self.builder.get_pointer_field(3), + size, + ) + } + pub fn has_required_positional(&self) -> bool { + !self.builder.get_pointer_field(3).is_null() + } + #[inline] + pub fn get_optional_positional( + self, + ) -> ::capnp::Result<::capnp::struct_list::Builder<'a, crate::plugin_capnp::argument::Owned>> + { + ::capnp::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(4), + ::core::option::Option::None, + ) + } + #[inline] + pub fn set_optional_positional( + &mut self, + value: ::capnp::struct_list::Reader<'a, crate::plugin_capnp::argument::Owned>, + ) -> ::capnp::Result<()> { + ::capnp::traits::SetPointerBuilder::set_pointer_builder( + self.builder.get_pointer_field(4), + value, + false, + ) + } + #[inline] + pub fn init_optional_positional( + self, + size: u32, + ) -> ::capnp::struct_list::Builder<'a, crate::plugin_capnp::argument::Owned> { + ::capnp::traits::FromPointerBuilder::init_pointer( + self.builder.get_pointer_field(4), + size, + ) + } + pub fn has_optional_positional(&self) -> bool { + !self.builder.get_pointer_field(4).is_null() + } + #[inline] + pub fn get_rest( + self, + ) -> ::capnp::Result< + crate::plugin_capnp::option::Builder<'a, crate::plugin_capnp::argument::Owned>, + > { + ::capnp::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(5), + ::core::option::Option::None, + ) + } + #[inline] + pub fn set_rest( + &mut self, + value: crate::plugin_capnp::option::Reader<'_, crate::plugin_capnp::argument::Owned>, + ) -> ::capnp::Result<()> { + as ::capnp::traits::SetPointerBuilder>::set_pointer_builder(self.builder.get_pointer_field(5), value, false) + } + #[inline] + pub fn init_rest( + self, + ) -> crate::plugin_capnp::option::Builder<'a, crate::plugin_capnp::argument::Owned> + { + ::capnp::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(5), 0) + } + pub fn has_rest(&self) -> bool { + !self.builder.get_pointer_field(5).is_null() + } + #[inline] + pub fn get_named( + self, + ) -> ::capnp::Result<::capnp::struct_list::Builder<'a, crate::plugin_capnp::flag::Owned>> + { + ::capnp::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(6), + ::core::option::Option::None, + ) + } + #[inline] + pub fn set_named( + &mut self, + value: ::capnp::struct_list::Reader<'a, crate::plugin_capnp::flag::Owned>, + ) -> ::capnp::Result<()> { + ::capnp::traits::SetPointerBuilder::set_pointer_builder( + self.builder.get_pointer_field(6), + value, + false, + ) + } + #[inline] + pub fn init_named( + self, + size: u32, + ) -> ::capnp::struct_list::Builder<'a, crate::plugin_capnp::flag::Owned> { + ::capnp::traits::FromPointerBuilder::init_pointer( + self.builder.get_pointer_field(6), + size, + ) + } + pub fn has_named(&self) -> bool { + !self.builder.get_pointer_field(6).is_null() + } + #[inline] + pub fn get_is_filter(self) -> bool { + self.builder.get_bool_field(0) + } + #[inline] + pub fn set_is_filter(&mut self, value: bool) { + self.builder.set_bool_field(0, value); + } + } + + pub struct Pipeline { + _typeless: ::capnp::any_pointer::Pipeline, + } + impl ::capnp::capability::FromTypelessPipeline for Pipeline { + fn new(typeless: ::capnp::any_pointer::Pipeline) -> Pipeline { + Pipeline { + _typeless: typeless, + } + } + } + impl Pipeline { + pub fn get_rest( + &self, + ) -> crate::plugin_capnp::option::Pipeline { + ::capnp::capability::FromTypelessPipeline::new(self._typeless.get_pointer_field(5)) + } + } + mod _private { + use capnp::private::layout; + pub const STRUCT_SIZE: layout::StructSize = layout::StructSize { + data: 1, + pointers: 7, + }; + pub const TYPE_ID: u64 = 0xec96_eeb4_8cb7_90fa; + } +} + +pub mod flag { + #[derive(Copy, Clone)] + pub struct Owned(()); + impl<'a> ::capnp::traits::Owned<'a> for Owned { + type Reader = Reader<'a>; + type Builder = Builder<'a>; + } + impl<'a> ::capnp::traits::OwnedStruct<'a> for Owned { + type Reader = Reader<'a>; + type Builder = Builder<'a>; + } + impl ::capnp::traits::Pipelined for Owned { + type Pipeline = Pipeline; + } + + #[derive(Clone, Copy)] + pub struct Reader<'a> { + reader: ::capnp::private::layout::StructReader<'a>, + } + + impl<'a> ::capnp::traits::HasTypeId for Reader<'a> { + #[inline] + fn type_id() -> u64 { + _private::TYPE_ID + } + } + impl<'a> ::capnp::traits::FromStructReader<'a> for Reader<'a> { + fn new(reader: ::capnp::private::layout::StructReader<'a>) -> Reader<'a> { + Reader { reader } + } + } + + impl<'a> ::capnp::traits::FromPointerReader<'a> for Reader<'a> { + fn get_from_pointer( + reader: &::capnp::private::layout::PointerReader<'a>, + default: ::core::option::Option<&'a [capnp::Word]>, + ) -> ::capnp::Result> { + ::core::result::Result::Ok(::capnp::traits::FromStructReader::new( + reader.get_struct(default)?, + )) + } + } + + impl<'a> ::capnp::traits::IntoInternalStructReader<'a> for Reader<'a> { + fn into_internal_struct_reader(self) -> ::capnp::private::layout::StructReader<'a> { + self.reader + } + } + + impl<'a> ::capnp::traits::Imbue<'a> for Reader<'a> { + fn imbue(&mut self, cap_table: &'a ::capnp::private::layout::CapTable) { + self.reader + .imbue(::capnp::private::layout::CapTableReader::Plain(cap_table)) + } + } + + impl<'a> Reader<'a> { + pub fn reborrow(&self) -> Reader<'_> { + Reader { ..*self } + } + + pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> { + self.reader.total_size() + } + #[inline] + pub fn get_long(self) -> ::capnp::Result<::capnp::text::Reader<'a>> { + ::capnp::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(0), + ::core::option::Option::None, + ) + } + pub fn has_long(&self) -> bool { + !self.reader.get_pointer_field(0).is_null() + } + #[inline] + pub fn get_short( + self, + ) -> ::capnp::Result> + { + ::capnp::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(1), + ::core::option::Option::None, + ) + } + pub fn has_short(&self) -> bool { + !self.reader.get_pointer_field(1).is_null() + } + #[inline] + pub fn get_arg( + self, + ) -> ::core::result::Result { + ::capnp::traits::FromU16::from_u16(self.reader.get_data_field::(0)) + } + #[inline] + pub fn get_required(self) -> bool { + self.reader.get_bool_field(16) + } + #[inline] + pub fn get_desc(self) -> ::capnp::Result<::capnp::text::Reader<'a>> { + ::capnp::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(2), + ::core::option::Option::None, + ) + } + pub fn has_desc(&self) -> bool { + !self.reader.get_pointer_field(2).is_null() + } + } + + pub struct Builder<'a> { + builder: ::capnp::private::layout::StructBuilder<'a>, + } + impl<'a> ::capnp::traits::HasStructSize for Builder<'a> { + #[inline] + fn struct_size() -> ::capnp::private::layout::StructSize { + _private::STRUCT_SIZE + } + } + impl<'a> ::capnp::traits::HasTypeId for Builder<'a> { + #[inline] + fn type_id() -> u64 { + _private::TYPE_ID + } + } + impl<'a> ::capnp::traits::FromStructBuilder<'a> for Builder<'a> { + fn new(builder: ::capnp::private::layout::StructBuilder<'a>) -> Builder<'a> { + Builder { builder } + } + } + + impl<'a> ::capnp::traits::ImbueMut<'a> for Builder<'a> { + fn imbue_mut(&mut self, cap_table: &'a mut ::capnp::private::layout::CapTable) { + self.builder + .imbue(::capnp::private::layout::CapTableBuilder::Plain(cap_table)) + } + } + + impl<'a> ::capnp::traits::FromPointerBuilder<'a> for Builder<'a> { + fn init_pointer( + builder: ::capnp::private::layout::PointerBuilder<'a>, + _size: u32, + ) -> Builder<'a> { + ::capnp::traits::FromStructBuilder::new(builder.init_struct(_private::STRUCT_SIZE)) + } + fn get_from_pointer( + builder: ::capnp::private::layout::PointerBuilder<'a>, + default: ::core::option::Option<&'a [capnp::Word]>, + ) -> ::capnp::Result> { + ::core::result::Result::Ok(::capnp::traits::FromStructBuilder::new( + builder.get_struct(_private::STRUCT_SIZE, default)?, + )) + } + } + + impl<'a> ::capnp::traits::SetPointerBuilder for Reader<'a> { + fn set_pointer_builder<'b>( + pointer: ::capnp::private::layout::PointerBuilder<'b>, + value: Reader<'a>, + canonicalize: bool, + ) -> ::capnp::Result<()> { + pointer.set_struct(&value.reader, canonicalize) + } + } + + impl<'a> Builder<'a> { + pub fn into_reader(self) -> Reader<'a> { + ::capnp::traits::FromStructReader::new(self.builder.into_reader()) + } + pub fn reborrow(&mut self) -> Builder<'_> { + Builder { ..*self } + } + pub fn reborrow_as_reader(&self) -> Reader<'_> { + ::capnp::traits::FromStructReader::new(self.builder.into_reader()) + } + + pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> { + self.builder.into_reader().total_size() + } + #[inline] + pub fn get_long(self) -> ::capnp::Result<::capnp::text::Builder<'a>> { + ::capnp::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(0), + ::core::option::Option::None, + ) + } + #[inline] + pub fn set_long(&mut self, value: ::capnp::text::Reader<'_>) { + self.builder.get_pointer_field(0).set_text(value); + } + #[inline] + pub fn init_long(self, size: u32) -> ::capnp::text::Builder<'a> { + self.builder.get_pointer_field(0).init_text(size) + } + pub fn has_long(&self) -> bool { + !self.builder.get_pointer_field(0).is_null() + } + #[inline] + pub fn get_short( + self, + ) -> ::capnp::Result> + { + ::capnp::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(1), + ::core::option::Option::None, + ) + } + #[inline] + pub fn set_short( + &mut self, + value: crate::plugin_capnp::option::Reader<'_, ::capnp::text::Owned>, + ) -> ::capnp::Result<()> { + as ::capnp::traits::SetPointerBuilder>::set_pointer_builder(self.builder.get_pointer_field(1), value, false) + } + #[inline] + pub fn init_short(self) -> crate::plugin_capnp::option::Builder<'a, ::capnp::text::Owned> { + ::capnp::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(1), 0) + } + pub fn has_short(&self) -> bool { + !self.builder.get_pointer_field(1).is_null() + } + #[inline] + pub fn get_arg( + self, + ) -> ::core::result::Result { + ::capnp::traits::FromU16::from_u16(self.builder.get_data_field::(0)) + } + #[inline] + pub fn set_arg(&mut self, value: crate::plugin_capnp::Shape) { + self.builder.set_data_field::(0, value as u16) + } + #[inline] + pub fn get_required(self) -> bool { + self.builder.get_bool_field(16) + } + #[inline] + pub fn set_required(&mut self, value: bool) { + self.builder.set_bool_field(16, value); + } + #[inline] + pub fn get_desc(self) -> ::capnp::Result<::capnp::text::Builder<'a>> { + ::capnp::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(2), + ::core::option::Option::None, + ) + } + #[inline] + pub fn set_desc(&mut self, value: ::capnp::text::Reader<'_>) { + self.builder.get_pointer_field(2).set_text(value); + } + #[inline] + pub fn init_desc(self, size: u32) -> ::capnp::text::Builder<'a> { + self.builder.get_pointer_field(2).init_text(size) + } + pub fn has_desc(&self) -> bool { + !self.builder.get_pointer_field(2).is_null() + } + } + + pub struct Pipeline { + _typeless: ::capnp::any_pointer::Pipeline, + } + impl ::capnp::capability::FromTypelessPipeline for Pipeline { + fn new(typeless: ::capnp::any_pointer::Pipeline) -> Pipeline { + Pipeline { + _typeless: typeless, + } + } + } + impl Pipeline { + pub fn get_short(&self) -> crate::plugin_capnp::option::Pipeline<::capnp::text::Owned> { + ::capnp::capability::FromTypelessPipeline::new(self._typeless.get_pointer_field(1)) + } + } + mod _private { + use capnp::private::layout; + pub const STRUCT_SIZE: layout::StructSize = layout::StructSize { + data: 1, + pointers: 3, + }; + pub const TYPE_ID: u64 = 0xc3e5_b612_6800_e050; + } +} + +pub mod argument { + #[derive(Copy, Clone)] + pub struct Owned(()); + impl<'a> ::capnp::traits::Owned<'a> for Owned { + type Reader = Reader<'a>; + type Builder = Builder<'a>; + } + impl<'a> ::capnp::traits::OwnedStruct<'a> for Owned { + type Reader = Reader<'a>; + type Builder = Builder<'a>; + } + impl ::capnp::traits::Pipelined for Owned { + type Pipeline = Pipeline; + } + + #[derive(Clone, Copy)] + pub struct Reader<'a> { + reader: ::capnp::private::layout::StructReader<'a>, + } + + impl<'a> ::capnp::traits::HasTypeId for Reader<'a> { + #[inline] + fn type_id() -> u64 { + _private::TYPE_ID + } + } + impl<'a> ::capnp::traits::FromStructReader<'a> for Reader<'a> { + fn new(reader: ::capnp::private::layout::StructReader<'a>) -> Reader<'a> { + Reader { reader } + } + } + + impl<'a> ::capnp::traits::FromPointerReader<'a> for Reader<'a> { + fn get_from_pointer( + reader: &::capnp::private::layout::PointerReader<'a>, + default: ::core::option::Option<&'a [capnp::Word]>, + ) -> ::capnp::Result> { + ::core::result::Result::Ok(::capnp::traits::FromStructReader::new( + reader.get_struct(default)?, + )) + } + } + + impl<'a> ::capnp::traits::IntoInternalStructReader<'a> for Reader<'a> { + fn into_internal_struct_reader(self) -> ::capnp::private::layout::StructReader<'a> { + self.reader + } + } + + impl<'a> ::capnp::traits::Imbue<'a> for Reader<'a> { + fn imbue(&mut self, cap_table: &'a ::capnp::private::layout::CapTable) { + self.reader + .imbue(::capnp::private::layout::CapTableReader::Plain(cap_table)) + } + } + + impl<'a> Reader<'a> { + pub fn reborrow(&self) -> Reader<'_> { + Reader { ..*self } + } + + pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> { + self.reader.total_size() + } + #[inline] + pub fn get_name(self) -> ::capnp::Result<::capnp::text::Reader<'a>> { + ::capnp::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(0), + ::core::option::Option::None, + ) + } + pub fn has_name(&self) -> bool { + !self.reader.get_pointer_field(0).is_null() + } + #[inline] + pub fn get_desc(self) -> ::capnp::Result<::capnp::text::Reader<'a>> { + ::capnp::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(1), + ::core::option::Option::None, + ) + } + pub fn has_desc(&self) -> bool { + !self.reader.get_pointer_field(1).is_null() + } + #[inline] + pub fn get_shape( + self, + ) -> ::core::result::Result { + ::capnp::traits::FromU16::from_u16(self.reader.get_data_field::(0)) + } + } + + pub struct Builder<'a> { + builder: ::capnp::private::layout::StructBuilder<'a>, + } + impl<'a> ::capnp::traits::HasStructSize for Builder<'a> { + #[inline] + fn struct_size() -> ::capnp::private::layout::StructSize { + _private::STRUCT_SIZE + } + } + impl<'a> ::capnp::traits::HasTypeId for Builder<'a> { + #[inline] + fn type_id() -> u64 { + _private::TYPE_ID + } + } + impl<'a> ::capnp::traits::FromStructBuilder<'a> for Builder<'a> { + fn new(builder: ::capnp::private::layout::StructBuilder<'a>) -> Builder<'a> { + Builder { builder } + } + } + + impl<'a> ::capnp::traits::ImbueMut<'a> for Builder<'a> { + fn imbue_mut(&mut self, cap_table: &'a mut ::capnp::private::layout::CapTable) { + self.builder + .imbue(::capnp::private::layout::CapTableBuilder::Plain(cap_table)) + } + } + + impl<'a> ::capnp::traits::FromPointerBuilder<'a> for Builder<'a> { + fn init_pointer( + builder: ::capnp::private::layout::PointerBuilder<'a>, + _size: u32, + ) -> Builder<'a> { + ::capnp::traits::FromStructBuilder::new(builder.init_struct(_private::STRUCT_SIZE)) + } + fn get_from_pointer( + builder: ::capnp::private::layout::PointerBuilder<'a>, + default: ::core::option::Option<&'a [capnp::Word]>, + ) -> ::capnp::Result> { + ::core::result::Result::Ok(::capnp::traits::FromStructBuilder::new( + builder.get_struct(_private::STRUCT_SIZE, default)?, + )) + } + } + + impl<'a> ::capnp::traits::SetPointerBuilder for Reader<'a> { + fn set_pointer_builder<'b>( + pointer: ::capnp::private::layout::PointerBuilder<'b>, + value: Reader<'a>, + canonicalize: bool, + ) -> ::capnp::Result<()> { + pointer.set_struct(&value.reader, canonicalize) + } + } + + impl<'a> Builder<'a> { + pub fn into_reader(self) -> Reader<'a> { + ::capnp::traits::FromStructReader::new(self.builder.into_reader()) + } + pub fn reborrow(&mut self) -> Builder<'_> { + Builder { ..*self } + } + pub fn reborrow_as_reader(&self) -> Reader<'_> { + ::capnp::traits::FromStructReader::new(self.builder.into_reader()) + } + + pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> { + self.builder.into_reader().total_size() + } + #[inline] + pub fn get_name(self) -> ::capnp::Result<::capnp::text::Builder<'a>> { + ::capnp::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(0), + ::core::option::Option::None, + ) + } + #[inline] + pub fn set_name(&mut self, value: ::capnp::text::Reader<'_>) { + self.builder.get_pointer_field(0).set_text(value); + } + #[inline] + pub fn init_name(self, size: u32) -> ::capnp::text::Builder<'a> { + self.builder.get_pointer_field(0).init_text(size) + } + pub fn has_name(&self) -> bool { + !self.builder.get_pointer_field(0).is_null() + } + #[inline] + pub fn get_desc(self) -> ::capnp::Result<::capnp::text::Builder<'a>> { + ::capnp::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(1), + ::core::option::Option::None, + ) + } + #[inline] + pub fn set_desc(&mut self, value: ::capnp::text::Reader<'_>) { + self.builder.get_pointer_field(1).set_text(value); + } + #[inline] + pub fn init_desc(self, size: u32) -> ::capnp::text::Builder<'a> { + self.builder.get_pointer_field(1).init_text(size) + } + pub fn has_desc(&self) -> bool { + !self.builder.get_pointer_field(1).is_null() + } + #[inline] + pub fn get_shape( + self, + ) -> ::core::result::Result { + ::capnp::traits::FromU16::from_u16(self.builder.get_data_field::(0)) + } + #[inline] + pub fn set_shape(&mut self, value: crate::plugin_capnp::Shape) { + self.builder.set_data_field::(0, value as u16) + } + } + + pub struct Pipeline { + _typeless: ::capnp::any_pointer::Pipeline, + } + impl ::capnp::capability::FromTypelessPipeline for Pipeline { + fn new(typeless: ::capnp::any_pointer::Pipeline) -> Pipeline { + Pipeline { + _typeless: typeless, + } + } + } + impl Pipeline {} + mod _private { + use capnp::private::layout; + pub const STRUCT_SIZE: layout::StructSize = layout::StructSize { + data: 1, + pointers: 2, + }; + pub const TYPE_ID: u64 = 0xe49c_3d71_859d_47e9; + } +} + +#[repr(u16)] +#[derive(Clone, Copy, Debug, PartialEq)] +pub enum Shape { + None = 0, + Any = 1, + String = 2, + Number = 3, + Int = 4, + Boolean = 5, +} +impl ::capnp::traits::FromU16 for Shape { + #[inline] + fn from_u16(value: u16) -> ::core::result::Result { + match value { + 0 => ::core::result::Result::Ok(Shape::None), + 1 => ::core::result::Result::Ok(Shape::Any), + 2 => ::core::result::Result::Ok(Shape::String), + 3 => ::core::result::Result::Ok(Shape::Number), + 4 => ::core::result::Result::Ok(Shape::Int), + 5 => ::core::result::Result::Ok(Shape::Boolean), + n => ::core::result::Result::Err(::capnp::NotInSchema(n)), + } + } +} +impl ::capnp::traits::ToU16 for Shape { + #[inline] + fn to_u16(self) -> u16 { + self as u16 + } +} +impl ::capnp::traits::HasTypeId for Shape { + #[inline] + fn type_id() -> u64 { + 0xaa46_1154_9e24_a910u64 + } +} + +pub mod expression { + pub use self::Which::{Bool, Float, Garbage, Int, List, String}; + + #[derive(Copy, Clone)] + pub struct Owned(()); + impl<'a> ::capnp::traits::Owned<'a> for Owned { + type Reader = Reader<'a>; + type Builder = Builder<'a>; + } + impl<'a> ::capnp::traits::OwnedStruct<'a> for Owned { + type Reader = Reader<'a>; + type Builder = Builder<'a>; + } + impl ::capnp::traits::Pipelined for Owned { + type Pipeline = Pipeline; + } + + #[derive(Clone, Copy)] + pub struct Reader<'a> { + reader: ::capnp::private::layout::StructReader<'a>, + } + + impl<'a> ::capnp::traits::HasTypeId for Reader<'a> { + #[inline] + fn type_id() -> u64 { + _private::TYPE_ID + } + } + impl<'a> ::capnp::traits::FromStructReader<'a> for Reader<'a> { + fn new(reader: ::capnp::private::layout::StructReader<'a>) -> Reader<'a> { + Reader { reader } + } + } + + impl<'a> ::capnp::traits::FromPointerReader<'a> for Reader<'a> { + fn get_from_pointer( + reader: &::capnp::private::layout::PointerReader<'a>, + default: ::core::option::Option<&'a [capnp::Word]>, + ) -> ::capnp::Result> { + ::core::result::Result::Ok(::capnp::traits::FromStructReader::new( + reader.get_struct(default)?, + )) + } + } + + impl<'a> ::capnp::traits::IntoInternalStructReader<'a> for Reader<'a> { + fn into_internal_struct_reader(self) -> ::capnp::private::layout::StructReader<'a> { + self.reader + } + } + + impl<'a> ::capnp::traits::Imbue<'a> for Reader<'a> { + fn imbue(&mut self, cap_table: &'a ::capnp::private::layout::CapTable) { + self.reader + .imbue(::capnp::private::layout::CapTableReader::Plain(cap_table)) + } + } + + impl<'a> Reader<'a> { + pub fn reborrow(&self) -> Reader<'_> { + Reader { ..*self } + } + + pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> { + self.reader.total_size() + } + pub fn has_string(&self) -> bool { + if self.reader.get_data_field::(0) != 4 { + return false; + } + !self.reader.get_pointer_field(0).is_null() + } + pub fn has_list(&self) -> bool { + if self.reader.get_data_field::(0) != 5 { + return false; + } + !self.reader.get_pointer_field(0).is_null() + } + #[inline] + pub fn which(self) -> ::core::result::Result, ::capnp::NotInSchema> { + match self.reader.get_data_field::(0) { + 0 => ::core::result::Result::Ok(Garbage(())), + 1 => ::core::result::Result::Ok(Bool(self.reader.get_bool_field(16))), + 2 => ::core::result::Result::Ok(Int(self.reader.get_data_field::(1))), + 3 => ::core::result::Result::Ok(Float(self.reader.get_data_field::(1))), + 4 => ::core::result::Result::Ok(String( + ::capnp::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(0), + ::core::option::Option::None, + ), + )), + 5 => ::core::result::Result::Ok(List( + ::capnp::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(0), + ::core::option::Option::None, + ), + )), + x => ::core::result::Result::Err(::capnp::NotInSchema(x)), + } + } + } + + pub struct Builder<'a> { + builder: ::capnp::private::layout::StructBuilder<'a>, + } + impl<'a> ::capnp::traits::HasStructSize for Builder<'a> { + #[inline] + fn struct_size() -> ::capnp::private::layout::StructSize { + _private::STRUCT_SIZE + } + } + impl<'a> ::capnp::traits::HasTypeId for Builder<'a> { + #[inline] + fn type_id() -> u64 { + _private::TYPE_ID + } + } + impl<'a> ::capnp::traits::FromStructBuilder<'a> for Builder<'a> { + fn new(builder: ::capnp::private::layout::StructBuilder<'a>) -> Builder<'a> { + Builder { builder } + } + } + + impl<'a> ::capnp::traits::ImbueMut<'a> for Builder<'a> { + fn imbue_mut(&mut self, cap_table: &'a mut ::capnp::private::layout::CapTable) { + self.builder + .imbue(::capnp::private::layout::CapTableBuilder::Plain(cap_table)) + } + } + + impl<'a> ::capnp::traits::FromPointerBuilder<'a> for Builder<'a> { + fn init_pointer( + builder: ::capnp::private::layout::PointerBuilder<'a>, + _size: u32, + ) -> Builder<'a> { + ::capnp::traits::FromStructBuilder::new(builder.init_struct(_private::STRUCT_SIZE)) + } + fn get_from_pointer( + builder: ::capnp::private::layout::PointerBuilder<'a>, + default: ::core::option::Option<&'a [capnp::Word]>, + ) -> ::capnp::Result> { + ::core::result::Result::Ok(::capnp::traits::FromStructBuilder::new( + builder.get_struct(_private::STRUCT_SIZE, default)?, + )) + } + } + + impl<'a> ::capnp::traits::SetPointerBuilder for Reader<'a> { + fn set_pointer_builder<'b>( + pointer: ::capnp::private::layout::PointerBuilder<'b>, + value: Reader<'a>, + canonicalize: bool, + ) -> ::capnp::Result<()> { + pointer.set_struct(&value.reader, canonicalize) + } + } + + impl<'a> Builder<'a> { + pub fn into_reader(self) -> Reader<'a> { + ::capnp::traits::FromStructReader::new(self.builder.into_reader()) + } + pub fn reborrow(&mut self) -> Builder<'_> { + Builder { ..*self } + } + pub fn reborrow_as_reader(&self) -> Reader<'_> { + ::capnp::traits::FromStructReader::new(self.builder.into_reader()) + } + + pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> { + self.builder.into_reader().total_size() + } + #[inline] + pub fn set_garbage(&mut self, _value: ()) { + self.builder.set_data_field::(0, 0); + } + #[inline] + pub fn set_bool(&mut self, value: bool) { + self.builder.set_data_field::(0, 1); + self.builder.set_bool_field(16, value); + } + #[inline] + pub fn set_int(&mut self, value: i64) { + self.builder.set_data_field::(0, 2); + self.builder.set_data_field::(1, value); + } + #[inline] + pub fn set_float(&mut self, value: f64) { + self.builder.set_data_field::(0, 3); + self.builder.set_data_field::(1, value); + } + #[inline] + pub fn set_string(&mut self, value: ::capnp::text::Reader<'_>) { + self.builder.set_data_field::(0, 4); + self.builder.get_pointer_field(0).set_text(value); + } + #[inline] + pub fn init_string(self, size: u32) -> ::capnp::text::Builder<'a> { + self.builder.set_data_field::(0, 4); + self.builder.get_pointer_field(0).init_text(size) + } + pub fn has_string(&self) -> bool { + if self.builder.get_data_field::(0) != 4 { + return false; + } + !self.builder.get_pointer_field(0).is_null() + } + #[inline] + pub fn set_list( + &mut self, + value: ::capnp::struct_list::Reader<'a, crate::plugin_capnp::expression::Owned>, + ) -> ::capnp::Result<()> { + self.builder.set_data_field::(0, 5); + ::capnp::traits::SetPointerBuilder::set_pointer_builder( + self.builder.get_pointer_field(0), + value, + false, + ) + } + #[inline] + pub fn init_list( + self, + size: u32, + ) -> ::capnp::struct_list::Builder<'a, crate::plugin_capnp::expression::Owned> { + self.builder.set_data_field::(0, 5); + ::capnp::traits::FromPointerBuilder::init_pointer( + self.builder.get_pointer_field(0), + size, + ) + } + pub fn has_list(&self) -> bool { + if self.builder.get_data_field::(0) != 5 { + return false; + } + !self.builder.get_pointer_field(0).is_null() + } + #[inline] + pub fn which(self) -> ::core::result::Result, ::capnp::NotInSchema> { + match self.builder.get_data_field::(0) { + 0 => ::core::result::Result::Ok(Garbage(())), + 1 => ::core::result::Result::Ok(Bool(self.builder.get_bool_field(16))), + 2 => ::core::result::Result::Ok(Int(self.builder.get_data_field::(1))), + 3 => ::core::result::Result::Ok(Float(self.builder.get_data_field::(1))), + 4 => ::core::result::Result::Ok(String( + ::capnp::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(0), + ::core::option::Option::None, + ), + )), + 5 => ::core::result::Result::Ok(List( + ::capnp::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(0), + ::core::option::Option::None, + ), + )), + x => ::core::result::Result::Err(::capnp::NotInSchema(x)), + } + } + } + + pub struct Pipeline { + _typeless: ::capnp::any_pointer::Pipeline, + } + impl ::capnp::capability::FromTypelessPipeline for Pipeline { + fn new(typeless: ::capnp::any_pointer::Pipeline) -> Pipeline { + Pipeline { + _typeless: typeless, + } + } + } + impl Pipeline {} + mod _private { + use capnp::private::layout; + pub const STRUCT_SIZE: layout::StructSize = layout::StructSize { + data: 2, + pointers: 1, + }; + pub const TYPE_ID: u64 = 0xb831_c4c2_80ed_4dbb; + } + pub enum Which { + Garbage(()), + Bool(bool), + Int(i64), + Float(f64), + String(A0), + List(A1), + } + pub type WhichReader<'a> = Which< + ::capnp::Result<::capnp::text::Reader<'a>>, + ::capnp::Result<::capnp::struct_list::Reader<'a, crate::plugin_capnp::expression::Owned>>, + >; + pub type WhichBuilder<'a> = Which< + ::capnp::Result<::capnp::text::Builder<'a>>, + ::capnp::Result<::capnp::struct_list::Builder<'a, crate::plugin_capnp::expression::Owned>>, + >; +} + +pub mod call { + #[derive(Copy, Clone)] + pub struct Owned(()); + impl<'a> ::capnp::traits::Owned<'a> for Owned { + type Reader = Reader<'a>; + type Builder = Builder<'a>; + } + impl<'a> ::capnp::traits::OwnedStruct<'a> for Owned { + type Reader = Reader<'a>; + type Builder = Builder<'a>; + } + impl ::capnp::traits::Pipelined for Owned { + type Pipeline = Pipeline; + } + + #[derive(Clone, Copy)] + pub struct Reader<'a> { + reader: ::capnp::private::layout::StructReader<'a>, + } + + impl<'a> ::capnp::traits::HasTypeId for Reader<'a> { + #[inline] + fn type_id() -> u64 { + _private::TYPE_ID + } + } + impl<'a> ::capnp::traits::FromStructReader<'a> for Reader<'a> { + fn new(reader: ::capnp::private::layout::StructReader<'a>) -> Reader<'a> { + Reader { reader } + } + } + + impl<'a> ::capnp::traits::FromPointerReader<'a> for Reader<'a> { + fn get_from_pointer( + reader: &::capnp::private::layout::PointerReader<'a>, + default: ::core::option::Option<&'a [capnp::Word]>, + ) -> ::capnp::Result> { + ::core::result::Result::Ok(::capnp::traits::FromStructReader::new( + reader.get_struct(default)?, + )) + } + } + + impl<'a> ::capnp::traits::IntoInternalStructReader<'a> for Reader<'a> { + fn into_internal_struct_reader(self) -> ::capnp::private::layout::StructReader<'a> { + self.reader + } + } + + impl<'a> ::capnp::traits::Imbue<'a> for Reader<'a> { + fn imbue(&mut self, cap_table: &'a ::capnp::private::layout::CapTable) { + self.reader + .imbue(::capnp::private::layout::CapTableReader::Plain(cap_table)) + } + } + + impl<'a> Reader<'a> { + pub fn reborrow(&self) -> Reader<'_> { + Reader { ..*self } + } + + pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> { + self.reader.total_size() + } + #[inline] + pub fn get_head(self) -> ::capnp::Result> { + ::capnp::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(0), + ::core::option::Option::None, + ) + } + pub fn has_head(&self) -> bool { + !self.reader.get_pointer_field(0).is_null() + } + #[inline] + pub fn get_positional( + self, + ) -> ::capnp::Result<::capnp::struct_list::Reader<'a, crate::plugin_capnp::expression::Owned>> + { + ::capnp::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(1), + ::core::option::Option::None, + ) + } + pub fn has_positional(&self) -> bool { + !self.reader.get_pointer_field(1).is_null() + } + #[inline] + pub fn get_named( + self, + ) -> ::capnp::Result< + crate::plugin_capnp::map::Reader< + 'a, + ::capnp::text::Owned, + crate::plugin_capnp::option::Owned, + >, + > { + ::capnp::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(2), + ::core::option::Option::None, + ) + } + pub fn has_named(&self) -> bool { + !self.reader.get_pointer_field(2).is_null() + } + } + + pub struct Builder<'a> { + builder: ::capnp::private::layout::StructBuilder<'a>, + } + impl<'a> ::capnp::traits::HasStructSize for Builder<'a> { + #[inline] + fn struct_size() -> ::capnp::private::layout::StructSize { + _private::STRUCT_SIZE + } + } + impl<'a> ::capnp::traits::HasTypeId for Builder<'a> { + #[inline] + fn type_id() -> u64 { + _private::TYPE_ID + } + } + impl<'a> ::capnp::traits::FromStructBuilder<'a> for Builder<'a> { + fn new(builder: ::capnp::private::layout::StructBuilder<'a>) -> Builder<'a> { + Builder { builder } + } + } + + impl<'a> ::capnp::traits::ImbueMut<'a> for Builder<'a> { + fn imbue_mut(&mut self, cap_table: &'a mut ::capnp::private::layout::CapTable) { + self.builder + .imbue(::capnp::private::layout::CapTableBuilder::Plain(cap_table)) + } + } + + impl<'a> ::capnp::traits::FromPointerBuilder<'a> for Builder<'a> { + fn init_pointer( + builder: ::capnp::private::layout::PointerBuilder<'a>, + _size: u32, + ) -> Builder<'a> { + ::capnp::traits::FromStructBuilder::new(builder.init_struct(_private::STRUCT_SIZE)) + } + fn get_from_pointer( + builder: ::capnp::private::layout::PointerBuilder<'a>, + default: ::core::option::Option<&'a [capnp::Word]>, + ) -> ::capnp::Result> { + ::core::result::Result::Ok(::capnp::traits::FromStructBuilder::new( + builder.get_struct(_private::STRUCT_SIZE, default)?, + )) + } + } + + impl<'a> ::capnp::traits::SetPointerBuilder for Reader<'a> { + fn set_pointer_builder<'b>( + pointer: ::capnp::private::layout::PointerBuilder<'b>, + value: Reader<'a>, + canonicalize: bool, + ) -> ::capnp::Result<()> { + pointer.set_struct(&value.reader, canonicalize) + } + } + + impl<'a> Builder<'a> { + pub fn into_reader(self) -> Reader<'a> { + ::capnp::traits::FromStructReader::new(self.builder.into_reader()) + } + pub fn reborrow(&mut self) -> Builder<'_> { + Builder { ..*self } + } + pub fn reborrow_as_reader(&self) -> Reader<'_> { + ::capnp::traits::FromStructReader::new(self.builder.into_reader()) + } + + pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> { + self.builder.into_reader().total_size() + } + #[inline] + pub fn get_head(self) -> ::capnp::Result> { + ::capnp::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(0), + ::core::option::Option::None, + ) + } + #[inline] + pub fn set_head( + &mut self, + value: crate::plugin_capnp::span::Reader<'_>, + ) -> ::capnp::Result<()> { + ::capnp::traits::SetPointerBuilder::set_pointer_builder( + self.builder.get_pointer_field(0), + value, + false, + ) + } + #[inline] + pub fn init_head(self) -> crate::plugin_capnp::span::Builder<'a> { + ::capnp::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(0), 0) + } + pub fn has_head(&self) -> bool { + !self.builder.get_pointer_field(0).is_null() + } + #[inline] + pub fn get_positional( + self, + ) -> ::capnp::Result< + ::capnp::struct_list::Builder<'a, crate::plugin_capnp::expression::Owned>, + > { + ::capnp::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(1), + ::core::option::Option::None, + ) + } + #[inline] + pub fn set_positional( + &mut self, + value: ::capnp::struct_list::Reader<'a, crate::plugin_capnp::expression::Owned>, + ) -> ::capnp::Result<()> { + ::capnp::traits::SetPointerBuilder::set_pointer_builder( + self.builder.get_pointer_field(1), + value, + false, + ) + } + #[inline] + pub fn init_positional( + self, + size: u32, + ) -> ::capnp::struct_list::Builder<'a, crate::plugin_capnp::expression::Owned> { + ::capnp::traits::FromPointerBuilder::init_pointer( + self.builder.get_pointer_field(1), + size, + ) + } + pub fn has_positional(&self) -> bool { + !self.builder.get_pointer_field(1).is_null() + } + #[inline] + pub fn get_named( + self, + ) -> ::capnp::Result< + crate::plugin_capnp::map::Builder< + 'a, + ::capnp::text::Owned, + crate::plugin_capnp::option::Owned, + >, + > { + ::capnp::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(2), + ::core::option::Option::None, + ) + } + #[inline] + pub fn set_named( + &mut self, + value: crate::plugin_capnp::map::Reader< + '_, + ::capnp::text::Owned, + crate::plugin_capnp::option::Owned, + >, + ) -> ::capnp::Result<()> { + , + > as ::capnp::traits::SetPointerBuilder>::set_pointer_builder( + self.builder.get_pointer_field(2), + value, + false, + ) + } + #[inline] + pub fn init_named( + self, + ) -> crate::plugin_capnp::map::Builder< + 'a, + ::capnp::text::Owned, + crate::plugin_capnp::option::Owned, + > { + ::capnp::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(2), 0) + } + pub fn has_named(&self) -> bool { + !self.builder.get_pointer_field(2).is_null() + } + } + + pub struct Pipeline { + _typeless: ::capnp::any_pointer::Pipeline, + } + impl ::capnp::capability::FromTypelessPipeline for Pipeline { + fn new(typeless: ::capnp::any_pointer::Pipeline) -> Pipeline { + Pipeline { + _typeless: typeless, + } + } + } + impl Pipeline { + pub fn get_head(&self) -> crate::plugin_capnp::span::Pipeline { + ::capnp::capability::FromTypelessPipeline::new(self._typeless.get_pointer_field(0)) + } + pub fn get_named( + &self, + ) -> crate::plugin_capnp::map::Pipeline< + ::capnp::text::Owned, + crate::plugin_capnp::option::Owned, + > { + ::capnp::capability::FromTypelessPipeline::new(self._typeless.get_pointer_field(2)) + } + } + mod _private { + use capnp::private::layout; + pub const STRUCT_SIZE: layout::StructSize = layout::StructSize { + data: 0, + pointers: 3, + }; + pub const TYPE_ID: u64 = 0xf5e6_e69c_460f_37d8; + } +} + +pub mod call_info { + #[derive(Copy, Clone)] + pub struct Owned(()); + impl<'a> ::capnp::traits::Owned<'a> for Owned { + type Reader = Reader<'a>; + type Builder = Builder<'a>; + } + impl<'a> ::capnp::traits::OwnedStruct<'a> for Owned { + type Reader = Reader<'a>; + type Builder = Builder<'a>; + } + impl ::capnp::traits::Pipelined for Owned { + type Pipeline = Pipeline; + } + + #[derive(Clone, Copy)] + pub struct Reader<'a> { + reader: ::capnp::private::layout::StructReader<'a>, + } + + impl<'a> ::capnp::traits::HasTypeId for Reader<'a> { + #[inline] + fn type_id() -> u64 { + _private::TYPE_ID + } + } + impl<'a> ::capnp::traits::FromStructReader<'a> for Reader<'a> { + fn new(reader: ::capnp::private::layout::StructReader<'a>) -> Reader<'a> { + Reader { reader } + } + } + + impl<'a> ::capnp::traits::FromPointerReader<'a> for Reader<'a> { + fn get_from_pointer( + reader: &::capnp::private::layout::PointerReader<'a>, + default: ::core::option::Option<&'a [capnp::Word]>, + ) -> ::capnp::Result> { + ::core::result::Result::Ok(::capnp::traits::FromStructReader::new( + reader.get_struct(default)?, + )) + } + } + + impl<'a> ::capnp::traits::IntoInternalStructReader<'a> for Reader<'a> { + fn into_internal_struct_reader(self) -> ::capnp::private::layout::StructReader<'a> { + self.reader + } + } + + impl<'a> ::capnp::traits::Imbue<'a> for Reader<'a> { + fn imbue(&mut self, cap_table: &'a ::capnp::private::layout::CapTable) { + self.reader + .imbue(::capnp::private::layout::CapTableReader::Plain(cap_table)) + } + } + + impl<'a> Reader<'a> { + pub fn reborrow(&self) -> Reader<'_> { + Reader { ..*self } + } + + pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> { + self.reader.total_size() + } + #[inline] + pub fn get_call(self) -> ::capnp::Result> { + ::capnp::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(0), + ::core::option::Option::None, + ) + } + pub fn has_call(&self) -> bool { + !self.reader.get_pointer_field(0).is_null() + } + #[inline] + pub fn get_input(self) -> ::capnp::Result> { + ::capnp::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(1), + ::core::option::Option::None, + ) + } + pub fn has_input(&self) -> bool { + !self.reader.get_pointer_field(1).is_null() + } + } + + pub struct Builder<'a> { + builder: ::capnp::private::layout::StructBuilder<'a>, + } + impl<'a> ::capnp::traits::HasStructSize for Builder<'a> { + #[inline] + fn struct_size() -> ::capnp::private::layout::StructSize { + _private::STRUCT_SIZE + } + } + impl<'a> ::capnp::traits::HasTypeId for Builder<'a> { + #[inline] + fn type_id() -> u64 { + _private::TYPE_ID + } + } + impl<'a> ::capnp::traits::FromStructBuilder<'a> for Builder<'a> { + fn new(builder: ::capnp::private::layout::StructBuilder<'a>) -> Builder<'a> { + Builder { builder } + } + } + + impl<'a> ::capnp::traits::ImbueMut<'a> for Builder<'a> { + fn imbue_mut(&mut self, cap_table: &'a mut ::capnp::private::layout::CapTable) { + self.builder + .imbue(::capnp::private::layout::CapTableBuilder::Plain(cap_table)) + } + } + + impl<'a> ::capnp::traits::FromPointerBuilder<'a> for Builder<'a> { + fn init_pointer( + builder: ::capnp::private::layout::PointerBuilder<'a>, + _size: u32, + ) -> Builder<'a> { + ::capnp::traits::FromStructBuilder::new(builder.init_struct(_private::STRUCT_SIZE)) + } + fn get_from_pointer( + builder: ::capnp::private::layout::PointerBuilder<'a>, + default: ::core::option::Option<&'a [capnp::Word]>, + ) -> ::capnp::Result> { + ::core::result::Result::Ok(::capnp::traits::FromStructBuilder::new( + builder.get_struct(_private::STRUCT_SIZE, default)?, + )) + } + } + + impl<'a> ::capnp::traits::SetPointerBuilder for Reader<'a> { + fn set_pointer_builder<'b>( + pointer: ::capnp::private::layout::PointerBuilder<'b>, + value: Reader<'a>, + canonicalize: bool, + ) -> ::capnp::Result<()> { + pointer.set_struct(&value.reader, canonicalize) + } + } + + impl<'a> Builder<'a> { + pub fn into_reader(self) -> Reader<'a> { + ::capnp::traits::FromStructReader::new(self.builder.into_reader()) + } + pub fn reborrow(&mut self) -> Builder<'_> { + Builder { ..*self } + } + pub fn reborrow_as_reader(&self) -> Reader<'_> { + ::capnp::traits::FromStructReader::new(self.builder.into_reader()) + } + + pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> { + self.builder.into_reader().total_size() + } + #[inline] + pub fn get_call(self) -> ::capnp::Result> { + ::capnp::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(0), + ::core::option::Option::None, + ) + } + #[inline] + pub fn set_call( + &mut self, + value: crate::plugin_capnp::call::Reader<'_>, + ) -> ::capnp::Result<()> { + ::capnp::traits::SetPointerBuilder::set_pointer_builder( + self.builder.get_pointer_field(0), + value, + false, + ) + } + #[inline] + pub fn init_call(self) -> crate::plugin_capnp::call::Builder<'a> { + ::capnp::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(0), 0) + } + pub fn has_call(&self) -> bool { + !self.builder.get_pointer_field(0).is_null() + } + #[inline] + pub fn get_input(self) -> ::capnp::Result> { + ::capnp::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(1), + ::core::option::Option::None, + ) + } + #[inline] + pub fn set_input( + &mut self, + value: crate::plugin_capnp::value::Reader<'_>, + ) -> ::capnp::Result<()> { + ::capnp::traits::SetPointerBuilder::set_pointer_builder( + self.builder.get_pointer_field(1), + value, + false, + ) + } + #[inline] + pub fn init_input(self) -> crate::plugin_capnp::value::Builder<'a> { + ::capnp::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(1), 0) + } + pub fn has_input(&self) -> bool { + !self.builder.get_pointer_field(1).is_null() + } + } + + pub struct Pipeline { + _typeless: ::capnp::any_pointer::Pipeline, + } + impl ::capnp::capability::FromTypelessPipeline for Pipeline { + fn new(typeless: ::capnp::any_pointer::Pipeline) -> Pipeline { + Pipeline { + _typeless: typeless, + } + } + } + impl Pipeline { + pub fn get_call(&self) -> crate::plugin_capnp::call::Pipeline { + ::capnp::capability::FromTypelessPipeline::new(self._typeless.get_pointer_field(0)) + } + pub fn get_input(&self) -> crate::plugin_capnp::value::Pipeline { + ::capnp::capability::FromTypelessPipeline::new(self._typeless.get_pointer_field(1)) + } + } + mod _private { + use capnp::private::layout; + pub const STRUCT_SIZE: layout::StructSize = layout::StructSize { + data: 0, + pointers: 2, + }; + pub const TYPE_ID: u64 = 0x8e03_127e_9170_7d6a; + } +} + +pub mod plugin_call { + pub use self::Which::{CallInfo, Signature}; + + #[derive(Copy, Clone)] + pub struct Owned(()); + impl<'a> ::capnp::traits::Owned<'a> for Owned { + type Reader = Reader<'a>; + type Builder = Builder<'a>; + } + impl<'a> ::capnp::traits::OwnedStruct<'a> for Owned { + type Reader = Reader<'a>; + type Builder = Builder<'a>; + } + impl ::capnp::traits::Pipelined for Owned { + type Pipeline = Pipeline; + } + + #[derive(Clone, Copy)] + pub struct Reader<'a> { + reader: ::capnp::private::layout::StructReader<'a>, + } + + impl<'a> ::capnp::traits::HasTypeId for Reader<'a> { + #[inline] + fn type_id() -> u64 { + _private::TYPE_ID + } + } + impl<'a> ::capnp::traits::FromStructReader<'a> for Reader<'a> { + fn new(reader: ::capnp::private::layout::StructReader<'a>) -> Reader<'a> { + Reader { reader } + } + } + + impl<'a> ::capnp::traits::FromPointerReader<'a> for Reader<'a> { + fn get_from_pointer( + reader: &::capnp::private::layout::PointerReader<'a>, + default: ::core::option::Option<&'a [capnp::Word]>, + ) -> ::capnp::Result> { + ::core::result::Result::Ok(::capnp::traits::FromStructReader::new( + reader.get_struct(default)?, + )) + } + } + + impl<'a> ::capnp::traits::IntoInternalStructReader<'a> for Reader<'a> { + fn into_internal_struct_reader(self) -> ::capnp::private::layout::StructReader<'a> { + self.reader + } + } + + impl<'a> ::capnp::traits::Imbue<'a> for Reader<'a> { + fn imbue(&mut self, cap_table: &'a ::capnp::private::layout::CapTable) { + self.reader + .imbue(::capnp::private::layout::CapTableReader::Plain(cap_table)) + } + } + + impl<'a> Reader<'a> { + pub fn reborrow(&self) -> Reader<'_> { + Reader { ..*self } + } + + pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> { + self.reader.total_size() + } + pub fn has_call_info(&self) -> bool { + if self.reader.get_data_field::(0) != 1 { + return false; + } + !self.reader.get_pointer_field(0).is_null() + } + #[inline] + pub fn which(self) -> ::core::result::Result, ::capnp::NotInSchema> { + match self.reader.get_data_field::(0) { + 0 => ::core::result::Result::Ok(Signature(())), + 1 => ::core::result::Result::Ok(CallInfo( + ::capnp::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(0), + ::core::option::Option::None, + ), + )), + x => ::core::result::Result::Err(::capnp::NotInSchema(x)), + } + } + } + + pub struct Builder<'a> { + builder: ::capnp::private::layout::StructBuilder<'a>, + } + impl<'a> ::capnp::traits::HasStructSize for Builder<'a> { + #[inline] + fn struct_size() -> ::capnp::private::layout::StructSize { + _private::STRUCT_SIZE + } + } + impl<'a> ::capnp::traits::HasTypeId for Builder<'a> { + #[inline] + fn type_id() -> u64 { + _private::TYPE_ID + } + } + impl<'a> ::capnp::traits::FromStructBuilder<'a> for Builder<'a> { + fn new(builder: ::capnp::private::layout::StructBuilder<'a>) -> Builder<'a> { + Builder { builder } + } + } + + impl<'a> ::capnp::traits::ImbueMut<'a> for Builder<'a> { + fn imbue_mut(&mut self, cap_table: &'a mut ::capnp::private::layout::CapTable) { + self.builder + .imbue(::capnp::private::layout::CapTableBuilder::Plain(cap_table)) + } + } + + impl<'a> ::capnp::traits::FromPointerBuilder<'a> for Builder<'a> { + fn init_pointer( + builder: ::capnp::private::layout::PointerBuilder<'a>, + _size: u32, + ) -> Builder<'a> { + ::capnp::traits::FromStructBuilder::new(builder.init_struct(_private::STRUCT_SIZE)) + } + fn get_from_pointer( + builder: ::capnp::private::layout::PointerBuilder<'a>, + default: ::core::option::Option<&'a [capnp::Word]>, + ) -> ::capnp::Result> { + ::core::result::Result::Ok(::capnp::traits::FromStructBuilder::new( + builder.get_struct(_private::STRUCT_SIZE, default)?, + )) + } + } + + impl<'a> ::capnp::traits::SetPointerBuilder for Reader<'a> { + fn set_pointer_builder<'b>( + pointer: ::capnp::private::layout::PointerBuilder<'b>, + value: Reader<'a>, + canonicalize: bool, + ) -> ::capnp::Result<()> { + pointer.set_struct(&value.reader, canonicalize) + } + } + + impl<'a> Builder<'a> { + pub fn into_reader(self) -> Reader<'a> { + ::capnp::traits::FromStructReader::new(self.builder.into_reader()) + } + pub fn reborrow(&mut self) -> Builder<'_> { + Builder { ..*self } + } + pub fn reborrow_as_reader(&self) -> Reader<'_> { + ::capnp::traits::FromStructReader::new(self.builder.into_reader()) + } + + pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> { + self.builder.into_reader().total_size() + } + #[inline] + pub fn set_signature(&mut self, _value: ()) { + self.builder.set_data_field::(0, 0); + } + #[inline] + pub fn set_call_info( + &mut self, + value: crate::plugin_capnp::call_info::Reader<'_>, + ) -> ::capnp::Result<()> { + self.builder.set_data_field::(0, 1); + ::capnp::traits::SetPointerBuilder::set_pointer_builder( + self.builder.get_pointer_field(0), + value, + false, + ) + } + #[inline] + pub fn init_call_info(self) -> crate::plugin_capnp::call_info::Builder<'a> { + self.builder.set_data_field::(0, 1); + ::capnp::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(0), 0) + } + pub fn has_call_info(&self) -> bool { + if self.builder.get_data_field::(0) != 1 { + return false; + } + !self.builder.get_pointer_field(0).is_null() + } + #[inline] + pub fn which(self) -> ::core::result::Result, ::capnp::NotInSchema> { + match self.builder.get_data_field::(0) { + 0 => ::core::result::Result::Ok(Signature(())), + 1 => ::core::result::Result::Ok(CallInfo( + ::capnp::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(0), + ::core::option::Option::None, + ), + )), + x => ::core::result::Result::Err(::capnp::NotInSchema(x)), + } + } + } + + pub struct Pipeline { + _typeless: ::capnp::any_pointer::Pipeline, + } + impl ::capnp::capability::FromTypelessPipeline for Pipeline { + fn new(typeless: ::capnp::any_pointer::Pipeline) -> Pipeline { + Pipeline { + _typeless: typeless, + } + } + } + impl Pipeline {} + mod _private { + use capnp::private::layout; + pub const STRUCT_SIZE: layout::StructSize = layout::StructSize { + data: 1, + pointers: 1, + }; + pub const TYPE_ID: u64 = 0xde86_64b2_7f80_4db1; + } + pub enum Which { + Signature(()), + CallInfo(A0), + } + pub type WhichReader<'a> = Which<::capnp::Result>>; + pub type WhichBuilder<'a> = Which<::capnp::Result>>; +} + +pub mod plugin_response { + pub use self::Which::{Error, Signature, Value}; + + #[derive(Copy, Clone)] + pub struct Owned(()); + impl<'a> ::capnp::traits::Owned<'a> for Owned { + type Reader = Reader<'a>; + type Builder = Builder<'a>; + } + impl<'a> ::capnp::traits::OwnedStruct<'a> for Owned { + type Reader = Reader<'a>; + type Builder = Builder<'a>; + } + impl ::capnp::traits::Pipelined for Owned { + type Pipeline = Pipeline; + } + + #[derive(Clone, Copy)] + pub struct Reader<'a> { + reader: ::capnp::private::layout::StructReader<'a>, + } + + impl<'a> ::capnp::traits::HasTypeId for Reader<'a> { + #[inline] + fn type_id() -> u64 { + _private::TYPE_ID + } + } + impl<'a> ::capnp::traits::FromStructReader<'a> for Reader<'a> { + fn new(reader: ::capnp::private::layout::StructReader<'a>) -> Reader<'a> { + Reader { reader } + } + } + + impl<'a> ::capnp::traits::FromPointerReader<'a> for Reader<'a> { + fn get_from_pointer( + reader: &::capnp::private::layout::PointerReader<'a>, + default: ::core::option::Option<&'a [capnp::Word]>, + ) -> ::capnp::Result> { + ::core::result::Result::Ok(::capnp::traits::FromStructReader::new( + reader.get_struct(default)?, + )) + } + } + + impl<'a> ::capnp::traits::IntoInternalStructReader<'a> for Reader<'a> { + fn into_internal_struct_reader(self) -> ::capnp::private::layout::StructReader<'a> { + self.reader + } + } + + impl<'a> ::capnp::traits::Imbue<'a> for Reader<'a> { + fn imbue(&mut self, cap_table: &'a ::capnp::private::layout::CapTable) { + self.reader + .imbue(::capnp::private::layout::CapTableReader::Plain(cap_table)) + } + } + + impl<'a> Reader<'a> { + pub fn reborrow(&self) -> Reader<'_> { + Reader { ..*self } + } + + pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> { + self.reader.total_size() + } + pub fn has_error(&self) -> bool { + if self.reader.get_data_field::(0) != 0 { + return false; + } + !self.reader.get_pointer_field(0).is_null() + } + pub fn has_signature(&self) -> bool { + if self.reader.get_data_field::(0) != 1 { + return false; + } + !self.reader.get_pointer_field(0).is_null() + } + pub fn has_value(&self) -> bool { + if self.reader.get_data_field::(0) != 2 { + return false; + } + !self.reader.get_pointer_field(0).is_null() + } + #[inline] + pub fn which(self) -> ::core::result::Result, ::capnp::NotInSchema> { + match self.reader.get_data_field::(0) { + 0 => ::core::result::Result::Ok(Error( + ::capnp::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(0), + ::core::option::Option::None, + ), + )), + 1 => ::core::result::Result::Ok(Signature( + ::capnp::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(0), + ::core::option::Option::None, + ), + )), + 2 => ::core::result::Result::Ok(Value( + ::capnp::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(0), + ::core::option::Option::None, + ), + )), + x => ::core::result::Result::Err(::capnp::NotInSchema(x)), + } + } + } + + pub struct Builder<'a> { + builder: ::capnp::private::layout::StructBuilder<'a>, + } + impl<'a> ::capnp::traits::HasStructSize for Builder<'a> { + #[inline] + fn struct_size() -> ::capnp::private::layout::StructSize { + _private::STRUCT_SIZE + } + } + impl<'a> ::capnp::traits::HasTypeId for Builder<'a> { + #[inline] + fn type_id() -> u64 { + _private::TYPE_ID + } + } + impl<'a> ::capnp::traits::FromStructBuilder<'a> for Builder<'a> { + fn new(builder: ::capnp::private::layout::StructBuilder<'a>) -> Builder<'a> { + Builder { builder } + } + } + + impl<'a> ::capnp::traits::ImbueMut<'a> for Builder<'a> { + fn imbue_mut(&mut self, cap_table: &'a mut ::capnp::private::layout::CapTable) { + self.builder + .imbue(::capnp::private::layout::CapTableBuilder::Plain(cap_table)) + } + } + + impl<'a> ::capnp::traits::FromPointerBuilder<'a> for Builder<'a> { + fn init_pointer( + builder: ::capnp::private::layout::PointerBuilder<'a>, + _size: u32, + ) -> Builder<'a> { + ::capnp::traits::FromStructBuilder::new(builder.init_struct(_private::STRUCT_SIZE)) + } + fn get_from_pointer( + builder: ::capnp::private::layout::PointerBuilder<'a>, + default: ::core::option::Option<&'a [capnp::Word]>, + ) -> ::capnp::Result> { + ::core::result::Result::Ok(::capnp::traits::FromStructBuilder::new( + builder.get_struct(_private::STRUCT_SIZE, default)?, + )) + } + } + + impl<'a> ::capnp::traits::SetPointerBuilder for Reader<'a> { + fn set_pointer_builder<'b>( + pointer: ::capnp::private::layout::PointerBuilder<'b>, + value: Reader<'a>, + canonicalize: bool, + ) -> ::capnp::Result<()> { + pointer.set_struct(&value.reader, canonicalize) + } + } + + impl<'a> Builder<'a> { + pub fn into_reader(self) -> Reader<'a> { + ::capnp::traits::FromStructReader::new(self.builder.into_reader()) + } + pub fn reborrow(&mut self) -> Builder<'_> { + Builder { ..*self } + } + pub fn reborrow_as_reader(&self) -> Reader<'_> { + ::capnp::traits::FromStructReader::new(self.builder.into_reader()) + } + + pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> { + self.builder.into_reader().total_size() + } + #[inline] + pub fn set_error(&mut self, value: ::capnp::text::Reader<'_>) { + self.builder.set_data_field::(0, 0); + self.builder.get_pointer_field(0).set_text(value); + } + #[inline] + pub fn init_error(self, size: u32) -> ::capnp::text::Builder<'a> { + self.builder.set_data_field::(0, 0); + self.builder.get_pointer_field(0).init_text(size) + } + pub fn has_error(&self) -> bool { + if self.builder.get_data_field::(0) != 0 { + return false; + } + !self.builder.get_pointer_field(0).is_null() + } + #[inline] + pub fn set_signature( + &mut self, + value: crate::plugin_capnp::signature::Reader<'_>, + ) -> ::capnp::Result<()> { + self.builder.set_data_field::(0, 1); + ::capnp::traits::SetPointerBuilder::set_pointer_builder( + self.builder.get_pointer_field(0), + value, + false, + ) + } + #[inline] + pub fn init_signature(self) -> crate::plugin_capnp::signature::Builder<'a> { + self.builder.set_data_field::(0, 1); + ::capnp::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(0), 0) + } + pub fn has_signature(&self) -> bool { + if self.builder.get_data_field::(0) != 1 { + return false; + } + !self.builder.get_pointer_field(0).is_null() + } + #[inline] + pub fn set_value( + &mut self, + value: crate::plugin_capnp::value::Reader<'_>, + ) -> ::capnp::Result<()> { + self.builder.set_data_field::(0, 2); + ::capnp::traits::SetPointerBuilder::set_pointer_builder( + self.builder.get_pointer_field(0), + value, + false, + ) + } + #[inline] + pub fn init_value(self) -> crate::plugin_capnp::value::Builder<'a> { + self.builder.set_data_field::(0, 2); + ::capnp::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(0), 0) + } + pub fn has_value(&self) -> bool { + if self.builder.get_data_field::(0) != 2 { + return false; + } + !self.builder.get_pointer_field(0).is_null() + } + #[inline] + pub fn which(self) -> ::core::result::Result, ::capnp::NotInSchema> { + match self.builder.get_data_field::(0) { + 0 => ::core::result::Result::Ok(Error( + ::capnp::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(0), + ::core::option::Option::None, + ), + )), + 1 => ::core::result::Result::Ok(Signature( + ::capnp::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(0), + ::core::option::Option::None, + ), + )), + 2 => ::core::result::Result::Ok(Value( + ::capnp::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(0), + ::core::option::Option::None, + ), + )), + x => ::core::result::Result::Err(::capnp::NotInSchema(x)), + } + } + } + + pub struct Pipeline { + _typeless: ::capnp::any_pointer::Pipeline, + } + impl ::capnp::capability::FromTypelessPipeline for Pipeline { + fn new(typeless: ::capnp::any_pointer::Pipeline) -> Pipeline { + Pipeline { + _typeless: typeless, + } + } + } + impl Pipeline {} + mod _private { + use capnp::private::layout; + pub const STRUCT_SIZE: layout::StructSize = layout::StructSize { + data: 1, + pointers: 1, + }; + pub const TYPE_ID: u64 = 0xb9ba_b3c7_9388_b7db; + } + pub enum Which { + Error(A0), + Signature(A1), + Value(A2), + } + pub type WhichReader<'a> = Which< + ::capnp::Result<::capnp::text::Reader<'a>>, + ::capnp::Result>, + ::capnp::Result>, + >; + pub type WhichBuilder<'a> = Which< + ::capnp::Result<::capnp::text::Builder<'a>>, + ::capnp::Result>, + ::capnp::Result>, + >; +} diff --git a/crates/nu-plugin/src/serializers/call.rs b/crates/nu-plugin/src/serializers/call.rs new file mode 100644 index 0000000000..ab7492c4fa --- /dev/null +++ b/crates/nu-plugin/src/serializers/call.rs @@ -0,0 +1,296 @@ +use crate::plugin::PluginError; +use crate::plugin_capnp::{call, expression, option}; +use nu_protocol::{ + ast::{Call, Expr, Expression}, + Span, Spanned, Type, +}; + +pub(crate) fn serialize_call(call: &Call, mut builder: call::Builder) -> Result<(), PluginError> { + let mut head = builder.reborrow().init_head(); + head.set_start(call.head.start as u64); + head.set_end(call.head.end as u64); + + serialize_positional(&call.positional, builder.reborrow()); + serialize_named(&call.named, builder)?; + + Ok(()) +} + +fn serialize_positional(positional: &[Expression], mut builder: call::Builder) { + let mut positional_builder = builder.reborrow().init_positional(positional.len() as u32); + + for (index, expression) in positional.iter().enumerate() { + serialize_expression(expression, positional_builder.reborrow().get(index as u32)) + } +} + +fn serialize_named( + named: &[(Spanned, Option)], + mut builder: call::Builder, +) -> Result<(), PluginError> { + let mut named_builder = builder + .reborrow() + .init_named() + .init_entries(named.len() as u32); + + for (index, (key, expression)) in named.iter().enumerate() { + let mut entry_builder = named_builder.reborrow().get(index as u32); + entry_builder + .reborrow() + .set_key(key.item.as_str()) + .map_err(|e| PluginError::EncodingError(e.to_string()))?; + + let mut value_builder = entry_builder.init_value(); + match expression { + None => value_builder.set_none(()), + Some(expr) => { + let expression_builder = value_builder.init_some(); + serialize_expression(expr, expression_builder); + } + } + } + + Ok(()) +} + +fn serialize_expression(expression: &Expression, mut builder: expression::Builder) { + match &expression.expr { + Expr::Garbage => builder.set_garbage(()), + Expr::Bool(val) => builder.set_bool(*val), + Expr::Int(val) => builder.set_int(*val), + Expr::Float(val) => builder.set_float(*val), + Expr::String(val) => builder.set_string(val), + Expr::List(values) => { + let mut list_builder = builder.reborrow().init_list(values.len() as u32); + for (index, expression) in values.iter().enumerate() { + let inner_builder = list_builder.reborrow().get(index as u32); + serialize_expression(expression, inner_builder) + } + } + _ => { + // If there is the need to pass other type of argument to the plugin + // we have to define the encoding for that parameter in this match + } + } +} + +pub(crate) fn deserialize_call(reader: call::Reader) -> Result { + let head_reader = reader + .get_head() + .map_err(|e| PluginError::DecodingError(e.to_string()))?; + + let head = Span { + start: head_reader.get_start() as usize, + end: head_reader.get_end() as usize, + }; + + let positional = deserialize_positionals(head, reader)?; + let named = deserialize_named(head, reader)?; + + Ok(Call { + decl_id: 0, + head, + positional, + named, + }) +} + +fn deserialize_positionals( + span: Span, + reader: call::Reader, +) -> Result, PluginError> { + let positional_reader = reader + .get_positional() + .map_err(|e| PluginError::DecodingError(e.to_string()))?; + + positional_reader + .iter() + .map(|expression_reader| deserialize_expression(span, expression_reader)) + .collect() +} + +type NamedList = Vec<(Spanned, Option)>; + +fn deserialize_named(span: Span, reader: call::Reader) -> Result { + let named_reader = reader + .get_named() + .map_err(|e| PluginError::DecodingError(e.to_string()))?; + + let entries_list = named_reader + .get_entries() + .map_err(|e| PluginError::DecodingError(e.to_string()))?; + + let mut entries: Vec<(Spanned, Option)> = + Vec::with_capacity(entries_list.len() as usize); + + for entry_reader in entries_list { + let item = entry_reader + .get_key() + .map_err(|e| PluginError::DecodingError(e.to_string()))? + .to_string(); + + let value_reader = entry_reader + .get_value() + .map_err(|e| PluginError::DecodingError(e.to_string()))?; + + let value = match value_reader.which() { + Ok(option::None(())) => None, + Ok(option::Some(expression_reader)) => { + let expression_reader = + expression_reader.map_err(|e| PluginError::DecodingError(e.to_string()))?; + + let expression = deserialize_expression(span, expression_reader) + .map_err(|e| PluginError::DecodingError(e.to_string()))?; + + Some(expression) + } + Err(capnp::NotInSchema(_)) => None, + }; + + let key = Spanned { item, span }; + + entries.push((key, value)) + } + + Ok(entries) +} + +fn deserialize_expression( + span: Span, + reader: expression::Reader, +) -> Result { + let expr = match reader.which() { + Ok(expression::Garbage(())) => Expr::Garbage, + Ok(expression::Bool(val)) => Expr::Bool(val), + Ok(expression::Int(val)) => Expr::Int(val), + Ok(expression::Float(val)) => Expr::Float(val), + Ok(expression::String(val)) => { + let string = val + .map_err(|e| PluginError::DecodingError(e.to_string()))? + .to_string(); + + Expr::String(string) + } + Ok(expression::List(values)) => { + let values = values.map_err(|e| PluginError::DecodingError(e.to_string()))?; + + let values_list = values + .iter() + .map(|inner_reader| deserialize_expression(span, inner_reader)) + .collect::, PluginError>>()?; + + Expr::List(values_list) + } + Err(capnp::NotInSchema(_)) => Expr::Garbage, + }; + + Ok(Expression { + expr, + span, + ty: Type::Unknown, + custom_completion: None, + }) +} + +#[cfg(test)] +mod tests { + use capnp::serialize_packed; + use core::panic; + + use super::*; + use nu_protocol::{ + ast::{Call, Expr, Expression}, + Span, Spanned, + }; + + fn write_buffer(call: &Call, writer: &mut impl std::io::Write) -> Result<(), PluginError> { + let mut message = ::capnp::message::Builder::new_default(); + + let builder = message.init_root::(); + serialize_call(call, builder)?; + + serialize_packed::write_message(writer, &message) + .map_err(|e| PluginError::EncodingError(e.to_string())) + } + + fn read_buffer(reader: &mut impl std::io::BufRead) -> Result { + let message_reader = + serialize_packed::read_message(reader, ::capnp::message::ReaderOptions::new()).unwrap(); + + let reader = message_reader + .get_root::() + .map_err(|e| PluginError::DecodingError(e.to_string()))?; + + deserialize_call(reader) + } + + fn compare_expressions(lhs: &Expression, rhs: &Expression) { + match (&lhs.expr, &rhs.expr) { + (Expr::Bool(a), Expr::Bool(b)) => assert_eq!(a, b), + (Expr::Int(a), Expr::Int(b)) => assert_eq!(a, b), + (Expr::Float(a), Expr::Float(b)) => assert!((a - b).abs() < f64::EPSILON), + (Expr::String(a), Expr::String(b)) => assert_eq!(a, b), + _ => panic!("not matching values"), + } + } + + #[test] + fn call_round_trip() { + let call = Call { + decl_id: 1, + head: Span { start: 0, end: 10 }, + positional: vec![ + Expression { + expr: Expr::Float(1.0), + span: Span { start: 0, end: 10 }, + ty: nu_protocol::Type::Float, + custom_completion: None, + }, + Expression { + expr: Expr::String("something".into()), + span: Span { start: 0, end: 10 }, + ty: nu_protocol::Type::Float, + custom_completion: None, + }, + ], + named: vec![( + Spanned { + item: "name".to_string(), + span: Span { start: 0, end: 10 }, + }, + Some(Expression { + expr: Expr::Float(1.0), + span: Span { start: 0, end: 10 }, + ty: nu_protocol::Type::Float, + custom_completion: None, + }), + )], + }; + + let mut buffer: Vec = Vec::new(); + write_buffer(&call, &mut buffer).expect("unable to serialize message"); + let returned_call = read_buffer(&mut buffer.as_slice()).expect("unable to read buffer"); + + assert_eq!(call.head, returned_call.head); + assert_eq!(call.positional.len(), returned_call.positional.len()); + + call.positional + .iter() + .zip(returned_call.positional.iter()) + .for_each(|(lhs, rhs)| compare_expressions(lhs, rhs)); + + call.named + .iter() + .zip(returned_call.named.iter()) + .for_each(|(lhs, rhs)| { + // Comparing the keys + assert_eq!(lhs.0.item, rhs.0.item); + + match (&lhs.1, &rhs.1) { + (None, None) => {} + (Some(a), Some(b)) => compare_expressions(a, b), + _ => panic!("not matching values"), + } + }); + } +} diff --git a/crates/nu-plugin/src/serializers/mod.rs b/crates/nu-plugin/src/serializers/mod.rs new file mode 100644 index 0000000000..9f96435fc9 --- /dev/null +++ b/crates/nu-plugin/src/serializers/mod.rs @@ -0,0 +1,3 @@ +pub mod call; +pub mod signature; +pub mod value; diff --git a/crates/nu-plugin/src/serializers/signature.rs b/crates/nu-plugin/src/serializers/signature.rs new file mode 100644 index 0000000000..7b98281a0d --- /dev/null +++ b/crates/nu-plugin/src/serializers/signature.rs @@ -0,0 +1,313 @@ +use crate::plugin::PluginError; +use crate::plugin_capnp::{argument, flag, option, signature, Shape}; +use nu_protocol::{Flag, PositionalArg, Signature, SyntaxShape}; + +pub(crate) fn serialize_signature(signature: &Signature, mut builder: signature::Builder) { + builder.set_name(signature.name.as_str()); + builder.set_usage(signature.usage.as_str()); + builder.set_extra_usage(signature.extra_usage.as_str()); + builder.set_is_filter(signature.is_filter); + + // Serializing list of required arguments + let mut required_list = builder + .reborrow() + .init_required_positional(signature.required_positional.len() as u32); + + for (index, arg) in signature.required_positional.iter().enumerate() { + let inner_builder = required_list.reborrow().get(index as u32); + serialize_argument(arg, inner_builder) + } + + // Serializing list of optional arguments + let mut optional_list = builder + .reborrow() + .init_optional_positional(signature.optional_positional.len() as u32); + + for (index, arg) in signature.optional_positional.iter().enumerate() { + let inner_builder = optional_list.reborrow().get(index as u32); + serialize_argument(arg, inner_builder) + } + + // Serializing rest argument + let mut rest_argument = builder.reborrow().init_rest(); + match &signature.rest_positional { + None => rest_argument.set_none(()), + Some(arg) => { + let inner_builder = rest_argument.init_some(); + serialize_argument(arg, inner_builder) + } + } + + // Serializing the named arguments + let mut named_list = builder.reborrow().init_named(signature.named.len() as u32); + + for (index, arg) in signature.named.iter().enumerate() { + let inner_builder = named_list.reborrow().get(index as u32); + serialize_flag(arg, inner_builder) + } +} + +fn serialize_argument(arg: &PositionalArg, mut builder: argument::Builder) { + builder.set_name(arg.name.as_str()); + builder.set_desc(arg.desc.as_str()); + + match arg.shape { + SyntaxShape::Boolean => builder.set_shape(Shape::Boolean), + SyntaxShape::String => builder.set_shape(Shape::String), + SyntaxShape::Int => builder.set_shape(Shape::Int), + SyntaxShape::Number => builder.set_shape(Shape::Number), + _ => builder.set_shape(Shape::Any), + } +} + +fn serialize_flag(arg: &Flag, mut builder: flag::Builder) { + builder.set_long(arg.long.as_str()); + builder.set_required(arg.required); + builder.set_desc(arg.desc.as_str()); + + let mut short_builder = builder.reborrow().init_short(); + match arg.short { + None => short_builder.set_none(()), + Some(val) => { + let mut inner_builder = short_builder.reborrow().initn_some(1); + inner_builder.push_str(format!("{}", val).as_str()); + } + } + + match &arg.arg { + None => builder.set_arg(Shape::None), + Some(shape) => match shape { + SyntaxShape::Boolean => builder.set_arg(Shape::Boolean), + SyntaxShape::String => builder.set_arg(Shape::String), + SyntaxShape::Int => builder.set_arg(Shape::Int), + SyntaxShape::Number => builder.set_arg(Shape::Number), + _ => builder.set_arg(Shape::Any), + }, + } +} + +pub(crate) fn deserialize_signature(reader: signature::Reader) -> Result { + let name = reader + .get_name() + .map_err(|e| PluginError::EncodingError(e.to_string()))?; + let usage = reader + .get_usage() + .map_err(|e| PluginError::EncodingError(e.to_string()))?; + let extra_usage = reader + .get_extra_usage() + .map_err(|e| PluginError::EncodingError(e.to_string()))?; + let is_filter = reader.get_is_filter(); + + // Deserializing required arguments + let required_list = reader + .get_required_positional() + .map_err(|e| PluginError::EncodingError(e.to_string()))?; + + let required_positional = required_list + .iter() + .map(deserialize_argument) + .collect::, PluginError>>()?; + + // Deserializing optional arguments + let optional_list = reader + .get_optional_positional() + .map_err(|e| PluginError::EncodingError(e.to_string()))?; + + let optional_positional = optional_list + .iter() + .map(deserialize_argument) + .collect::, PluginError>>()?; + + // Deserializing rest arguments + let rest_option = reader + .get_rest() + .map_err(|e| PluginError::EncodingError(e.to_string()))?; + + let rest_positional = match rest_option.which() { + Err(capnp::NotInSchema(_)) => None, + Ok(option::None(())) => None, + Ok(option::Some(rest_reader)) => { + let rest_reader = rest_reader.map_err(|e| PluginError::EncodingError(e.to_string()))?; + Some(deserialize_argument(rest_reader)?) + } + }; + + // Deserializing named arguments + let named_list = reader + .get_named() + .map_err(|e| PluginError::EncodingError(e.to_string()))?; + + let named = named_list + .iter() + .map(deserialize_flag) + .collect::, PluginError>>()?; + + Ok(Signature { + name: name.to_string(), + usage: usage.to_string(), + extra_usage: extra_usage.to_string(), + required_positional, + optional_positional, + rest_positional, + named, + is_filter, + creates_scope: false, + }) +} + +fn deserialize_argument(reader: argument::Reader) -> Result { + let name = reader + .get_name() + .map_err(|e| PluginError::EncodingError(e.to_string()))?; + + let desc = reader + .get_desc() + .map_err(|e| PluginError::EncodingError(e.to_string()))?; + + let shape = reader + .get_shape() + .map_err(|e| PluginError::EncodingError(e.to_string()))?; + + let shape = match shape { + Shape::String => SyntaxShape::String, + Shape::Int => SyntaxShape::Int, + Shape::Number => SyntaxShape::Number, + Shape::Boolean => SyntaxShape::Boolean, + Shape::Any => SyntaxShape::Any, + Shape::None => SyntaxShape::Any, + }; + + Ok(PositionalArg { + name: name.to_string(), + desc: desc.to_string(), + shape, + var_id: None, + }) +} + +fn deserialize_flag(reader: flag::Reader) -> Result { + let long = reader + .get_long() + .map_err(|e| PluginError::EncodingError(e.to_string()))?; + + let desc = reader + .get_desc() + .map_err(|e| PluginError::EncodingError(e.to_string()))?; + + let required = reader.get_required(); + + let short = reader + .get_short() + .map_err(|e| PluginError::EncodingError(e.to_string()))?; + + let short = match short.which() { + Err(capnp::NotInSchema(_)) => None, + Ok(option::None(())) => None, + Ok(option::Some(reader)) => { + let reader = reader.map_err(|e| PluginError::EncodingError(e.to_string()))?; + reader.chars().next() + } + }; + + let arg = reader + .get_arg() + .map_err(|e| PluginError::EncodingError(e.to_string()))?; + + let arg = match arg { + Shape::None => None, + Shape::Any => Some(SyntaxShape::Any), + Shape::String => Some(SyntaxShape::String), + Shape::Int => Some(SyntaxShape::Int), + Shape::Number => Some(SyntaxShape::Number), + Shape::Boolean => Some(SyntaxShape::Boolean), + }; + + Ok(Flag { + long: long.to_string(), + short, + arg, + required, + desc: desc.to_string(), + var_id: None, + }) +} + +#[cfg(test)] +mod tests { + use super::*; + use capnp::serialize_packed; + use nu_protocol::{Signature, SyntaxShape}; + + pub fn write_buffer( + signature: &Signature, + writer: &mut impl std::io::Write, + ) -> Result<(), PluginError> { + let mut message = ::capnp::message::Builder::new_default(); + + let builder = message.init_root::(); + + serialize_signature(signature, builder); + + serialize_packed::write_message(writer, &message) + .map_err(|e| PluginError::EncodingError(e.to_string())) + } + + pub fn read_buffer(reader: &mut impl std::io::BufRead) -> Result { + let message_reader = + serialize_packed::read_message(reader, ::capnp::message::ReaderOptions::new()).unwrap(); + + let reader = message_reader + .get_root::() + .map_err(|e| PluginError::DecodingError(e.to_string()))?; + + deserialize_signature(reader) + } + + #[test] + fn value_round_trip() { + let signature = Signature::build("nu-plugin") + .required("first", SyntaxShape::String, "first required") + .required("second", SyntaxShape::Int, "second required") + .required_named("first_named", SyntaxShape::String, "first named", Some('f')) + .required_named( + "second_named", + SyntaxShape::String, + "second named", + Some('s'), + ) + .rest("remaining", SyntaxShape::Int, "remaining"); + + let mut buffer: Vec = Vec::new(); + write_buffer(&signature, &mut buffer).expect("unable to serialize message"); + let returned_signature = + read_buffer(&mut buffer.as_slice()).expect("unable to deserialize message"); + + assert_eq!(signature.name, returned_signature.name); + assert_eq!(signature.usage, returned_signature.usage); + assert_eq!(signature.extra_usage, returned_signature.extra_usage); + assert_eq!(signature.is_filter, returned_signature.is_filter); + + signature + .required_positional + .iter() + .zip(returned_signature.required_positional.iter()) + .for_each(|(lhs, rhs)| assert_eq!(lhs, rhs)); + + signature + .optional_positional + .iter() + .zip(returned_signature.optional_positional.iter()) + .for_each(|(lhs, rhs)| assert_eq!(lhs, rhs)); + + signature + .named + .iter() + .zip(returned_signature.named.iter()) + .for_each(|(lhs, rhs)| assert_eq!(lhs, rhs)); + + assert_eq!( + signature.rest_positional, + returned_signature.rest_positional, + ); + } +} diff --git a/crates/nu-plugin/src/serializers/value.rs b/crates/nu-plugin/src/serializers/value.rs new file mode 100644 index 0000000000..d5e1bef7d9 --- /dev/null +++ b/crates/nu-plugin/src/serializers/value.rs @@ -0,0 +1,265 @@ +use crate::plugin::PluginError; +use crate::plugin_capnp::value; +use nu_protocol::{Span, Value}; + +pub(crate) fn serialize_value(value: &Value, mut builder: value::Builder) { + let value_span = match value { + Value::Nothing { span } => { + builder.set_void(()); + *span + } + Value::Bool { val, span } => { + builder.set_bool(*val); + *span + } + Value::Int { val, span } => { + builder.set_int(*val); + *span + } + Value::Float { val, span } => { + builder.set_float(*val); + *span + } + Value::String { val, span } => { + builder.set_string(val); + *span + } + Value::List { vals, span } => { + let mut list_builder = builder.reborrow().init_list(vals.len() as u32); + for (index, value) in vals.iter().enumerate() { + let inner_builder = list_builder.reborrow().get(index as u32); + serialize_value(value, inner_builder); + } + + *span + } + _ => { + // If there is the need to pass other type of value to the plugin + // we have to define the encoding for that object in this match + Span::unknown() + } + }; + + let mut span = builder.reborrow().init_span(); + span.set_start(value_span.start as u64); + span.set_end(value_span.end as u64); +} + +pub(crate) fn deserialize_value(reader: value::Reader) -> Result { + let span_reader = reader + .get_span() + .map_err(|e| PluginError::DecodingError(e.to_string()))?; + + let span = Span { + start: span_reader.get_start() as usize, + end: span_reader.get_end() as usize, + }; + + match reader.which() { + Ok(value::Void(())) => Ok(Value::Nothing { span }), + Ok(value::Bool(val)) => Ok(Value::Bool { val, span }), + Ok(value::Int(val)) => Ok(Value::Int { val, span }), + Ok(value::Float(val)) => Ok(Value::Float { val, span }), + Ok(value::String(val)) => { + let string = val + .map_err(|e| PluginError::DecodingError(e.to_string()))? + .to_string(); + Ok(Value::String { val: string, span }) + } + Ok(value::List(vals)) => { + let values = vals.map_err(|e| PluginError::DecodingError(e.to_string()))?; + + let values_list = values + .iter() + .map(deserialize_value) + .collect::, PluginError>>()?; + + Ok(Value::List { + vals: values_list, + span, + }) + } + Err(capnp::NotInSchema(_)) => Ok(Value::Nothing { + span: Span::unknown(), + }), + } +} + +#[cfg(test)] +mod tests { + use super::*; + use capnp::serialize_packed; + use nu_protocol::{Span, Value}; + + pub fn write_buffer( + value: &Value, + writer: &mut impl std::io::Write, + ) -> Result<(), PluginError> { + let mut message = ::capnp::message::Builder::new_default(); + + let mut builder = message.init_root::(); + + serialize_value(value, builder.reborrow()); + + serialize_packed::write_message(writer, &message) + .map_err(|e| PluginError::EncodingError(e.to_string())) + } + + pub fn read_buffer(reader: &mut impl std::io::BufRead) -> Result { + let message_reader = + serialize_packed::read_message(reader, ::capnp::message::ReaderOptions::new()).unwrap(); + + let reader = message_reader + .get_root::() + .map_err(|e| PluginError::DecodingError(e.to_string()))?; + + deserialize_value(reader.reborrow()) + } + + #[test] + fn value_round_trip() { + let values = [ + Value::Bool { + val: false, + span: Span { start: 1, end: 20 }, + }, + Value::Int { + val: 10, + span: Span { start: 2, end: 30 }, + }, + Value::Float { + val: 10.0, + span: Span { start: 3, end: 40 }, + }, + Value::String { + val: "a string".into(), + span: Span { start: 4, end: 50 }, + }, + ]; + + for value in values { + let mut buffer: Vec = Vec::new(); + write_buffer(&value, &mut buffer).expect("unable to serialize message"); + let returned_value = + read_buffer(&mut buffer.as_slice()).expect("unable to deserialize message"); + + assert_eq!(value, returned_value) + } + } + + #[test] + fn value_nothing_round_trip() { + // Since nothing doesn't implement PartialOrd, we only compare that the + // encoded and decoded spans are correct + let value = Value::Nothing { + span: Span { start: 0, end: 10 }, + }; + + let mut buffer: Vec = Vec::new(); + write_buffer(&value, &mut buffer).expect("unable to serialize message"); + let returned_value = + read_buffer(&mut buffer.as_slice()).expect("unable to deserialize message"); + + assert_eq!( + value.span().expect("span"), + returned_value.span().expect("span") + ) + } + + #[test] + fn list_round_trip() { + let values = vec![ + Value::Bool { + val: false, + span: Span { start: 1, end: 20 }, + }, + Value::Int { + val: 10, + span: Span { start: 2, end: 30 }, + }, + Value::Float { + val: 10.0, + span: Span { start: 3, end: 40 }, + }, + Value::String { + val: "a string".into(), + span: Span { start: 4, end: 50 }, + }, + ]; + + let value = Value::List { + vals: values, + span: Span { start: 1, end: 10 }, + }; + + let mut buffer: Vec = Vec::new(); + write_buffer(&value, &mut buffer).expect("unable to serialize message"); + let returned_value = + read_buffer(&mut buffer.as_slice()).expect("unable to deserialize message"); + + assert_eq!( + value.span().expect("span"), + returned_value.span().expect("span") + ) + } + + #[test] + fn nested_list_round_trip() { + let inner_values = vec![ + Value::Bool { + val: false, + span: Span { start: 1, end: 20 }, + }, + Value::Int { + val: 10, + span: Span { start: 2, end: 30 }, + }, + Value::Float { + val: 10.0, + span: Span { start: 3, end: 40 }, + }, + Value::String { + val: "inner string".into(), + span: Span { start: 4, end: 50 }, + }, + ]; + + let values = vec![ + Value::Bool { + val: true, + span: Span { start: 1, end: 20 }, + }, + Value::Int { + val: 66, + span: Span { start: 2, end: 30 }, + }, + Value::Float { + val: 66.6, + span: Span { start: 3, end: 40 }, + }, + Value::String { + val: "a string".into(), + span: Span { start: 4, end: 50 }, + }, + Value::List { + vals: inner_values, + span: Span { start: 5, end: 60 }, + }, + ]; + + let value = Value::List { + vals: values, + span: Span { start: 1, end: 10 }, + }; + + let mut buffer: Vec = Vec::new(); + write_buffer(&value, &mut buffer).expect("unable to serialize message"); + let returned_value = + read_buffer(&mut buffer.as_slice()).expect("unable to deserialize message"); + + assert_eq!( + value.span().expect("span"), + returned_value.span().expect("span") + ) + } +} diff --git a/crates/nu-protocol/src/engine/engine_state.rs b/crates/nu-protocol/src/engine/engine_state.rs index 36d1fe5227..6e072ddc29 100644 --- a/crates/nu-protocol/src/engine/engine_state.rs +++ b/crates/nu-protocol/src/engine/engine_state.rs @@ -6,17 +6,6 @@ use std::{ sync::{atomic::AtomicBool, Arc}, }; -#[derive(Clone)] -pub struct EngineState { - files: im::Vector<(String, usize, usize)>, - file_contents: im::Vector<(Vec, usize, usize)>, - vars: im::Vector, - decls: im::Vector>, - blocks: im::Vector, - pub scope: im::Vector, - pub ctrlc: Option>, -} - // Tells whether a decl etc. is visible or not // TODO: When adding new exportables (env vars, aliases, etc.), parametrize the ID type with generics #[derive(Debug, Clone)] @@ -62,9 +51,9 @@ impl Visibility { pub struct ScopeFrame { pub vars: HashMap, VarId>, predecls: HashMap, DeclId>, // temporary storage for predeclarations - decls: HashMap, DeclId>, - aliases: HashMap, Vec>, - modules: HashMap, BlockId>, + pub decls: HashMap, DeclId>, + pub aliases: HashMap, Vec>, + pub modules: HashMap, BlockId>, visibility: Visibility, } @@ -91,18 +80,26 @@ impl Default for ScopeFrame { } } -impl Default for EngineState { - fn default() -> Self { - Self::new() - } +#[derive(Clone)] +pub struct EngineState { + files: im::Vector<(String, usize, usize)>, + file_contents: im::Vector<(Vec, usize, usize)>, + vars: im::Vector, + decls: im::Vector>, + blocks: im::Vector, + pub scope: im::Vector, + pub ctrlc: Option>, } +pub const NU_VARIABLE_ID: usize = 0; +pub const SCOPE_VARIABLE_ID: usize = 1; + impl EngineState { pub fn new() -> Self { Self { files: im::vector![], file_contents: im::vector![], - vars: im::vector![Type::Unknown], + vars: im::vector![Type::Unknown, Type::Unknown], decls: im::vector![], blocks: im::vector![], scope: im::vector![ScopeFrame::new()], @@ -319,6 +316,12 @@ impl EngineState { } } +impl Default for EngineState { + fn default() -> Self { + Self::new() + } +} + pub struct StateWorkingSet<'a> { pub permanent_state: &'a EngineState, pub delta: StateDelta, @@ -506,7 +509,7 @@ impl<'a> StateWorkingSet<'a> { let permanent_span_start = self.permanent_state.next_span_start(); if let Some((_, _, last)) = self.delta.file_contents.last() { - permanent_span_start + *last + *last } else { permanent_span_start } @@ -566,7 +569,7 @@ impl<'a> StateWorkingSet<'a> { if permanent_end <= span.start { for (contents, start, finish) in &self.delta.file_contents { if (span.start >= *start) && (span.end <= *finish) { - return &contents[(span.start - permanent_end)..(span.end - permanent_end)]; + return &contents[(span.start - start)..(span.end - start)]; } } } else { diff --git a/crates/nu-protocol/src/lib.rs b/crates/nu-protocol/src/lib.rs index 081a9b0b41..6a7bf45c11 100644 --- a/crates/nu-protocol/src/lib.rs +++ b/crates/nu-protocol/src/lib.rs @@ -11,6 +11,7 @@ mod ty; mod value; pub use value::Value; +pub use engine::{NU_VARIABLE_ID, SCOPE_VARIABLE_ID}; pub use example::*; pub use id::*; pub use pipeline_data::*; diff --git a/crates/nu-protocol/src/pipeline_data.rs b/crates/nu-protocol/src/pipeline_data.rs index 4e6f6f8efd..fbe8862a98 100644 --- a/crates/nu-protocol/src/pipeline_data.rs +++ b/crates/nu-protocol/src/pipeline_data.rs @@ -116,6 +116,16 @@ impl IntoIterator for PipelineData { ctrlc: None, })) } + PipelineData::Value(Value::Range { val, .. }) => match val.into_range_iter() { + Ok(val) => PipelineIterator(PipelineData::Stream(ValueStream { + stream: Box::new(val), + ctrlc: None, + })), + Err(e) => PipelineIterator(PipelineData::Stream(ValueStream { + stream: Box::new(vec![Value::Error { error: e }].into_iter()), + ctrlc: None, + })), + }, x => PipelineIterator(x), } } diff --git a/crates/nu-protocol/src/shell_error.rs b/crates/nu-protocol/src/shell_error.rs index befcd029f3..425fec37b6 100644 --- a/crates/nu-protocol/src/shell_error.rs +++ b/crates/nu-protocol/src/shell_error.rs @@ -169,6 +169,9 @@ pub enum ShellError { NoFileToBeMoved(), #[error("No file to be copied")] NoFileToBeCopied(), + + #[error("Plugin error")] + PluginError(String), } impl From for ShellError { diff --git a/crates/nu-protocol/src/value/mod.rs b/crates/nu-protocol/src/value/mod.rs index b8b2c3041a..b6ea1e2768 100644 --- a/crates/nu-protocol/src/value/mod.rs +++ b/crates/nu-protocol/src/value/mod.rs @@ -377,6 +377,9 @@ impl PartialOrd for Value { (Value::Float { val: lhs, .. }, Value::Float { val: rhs, .. }) => { compare_floats(*lhs, *rhs) } + (Value::Date { val: lhs, .. }, Value::Date { val: rhs, .. }) => { + lhs.date().to_string().partial_cmp(&rhs.date().to_string()) + } (Value::String { val: lhs, .. }, Value::String { val: rhs, .. }) => { lhs.partial_cmp(rhs) } diff --git a/src/main.rs b/src/main.rs index aecb0041aa..9dba312575 100644 --- a/src/main.rs +++ b/src/main.rs @@ -225,21 +225,6 @@ fn main() -> Result<()> { Ok(Signal::Success(s)) => { if s.trim() == "exit" { break; - } else if s.trim() == "vars" { - engine_state.print_vars(); - continue; - } else if s.trim() == "decls" { - engine_state.print_decls(); - continue; - } else if s.trim() == "blocks" { - engine_state.print_blocks(); - continue; - } else if s.trim() == "stack" { - stack.print_stack(); - continue; - } else if s.trim() == "contents" { - engine_state.print_contents(); - continue; } eval_source( diff --git a/src/tests.rs b/src/tests.rs index fa2d323065..41595e65c2 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -247,6 +247,14 @@ fn alias_2() -> TestResult { ) } +#[test] +fn alias_2_multi_word() -> TestResult { + run_test( + r#"def "foo bar" [$x $y] { $x + $y + 10 }; alias f = foo bar 33; f 100"#, + "143", + ) +} + #[test] fn block_param1() -> TestResult { run_test("[3] | each { $it + 10 } | get 0", "13") @@ -389,7 +397,7 @@ fn better_block_types() -> TestResult { #[test] fn module_imports_1() -> TestResult { run_test( - r#"module foo { export def a [] { 1 }; def b [] { 2 } }; use foo; foo.a"#, + r#"module foo { export def a [] { 1 }; def b [] { 2 } }; use foo; foo a"#, "1", ) } @@ -397,7 +405,7 @@ fn module_imports_1() -> TestResult { #[test] fn module_imports_2() -> TestResult { run_test( - r#"module foo { export def a [] { 1 }; def b [] { 2 } }; use foo.a; a"#, + r#"module foo { export def a [] { 1 }; def b [] { 2 } }; use foo a; a"#, "1", ) } @@ -405,7 +413,7 @@ fn module_imports_2() -> TestResult { #[test] fn module_imports_3() -> TestResult { run_test( - r#"module foo { export def a [] { 1 }; export def b [] { 2 } }; use foo.*; b"#, + r#"module foo { export def a [] { 1 }; export def b [] { 2 } }; use foo *; b"#, "2", ) } @@ -413,7 +421,7 @@ fn module_imports_3() -> TestResult { #[test] fn module_imports_4() -> TestResult { fail_test( - r#"module foo { export def a [] { 1 }; export def b [] { 2 } }; use foo.c"#, + r#"module foo { export def a [] { 1 }; export def b [] { 2 } }; use foo c"#, "not find import", ) } @@ -421,7 +429,7 @@ fn module_imports_4() -> TestResult { #[test] fn module_imports_5() -> TestResult { run_test( - r#"module foo { export def a [] { 1 }; def b [] { 2 }; export def c [] { 3 } }; use foo.[a, c]; c"#, + r#"module foo { export def a [] { 1 }; def b [] { 2 }; export def c [] { 3 } }; use foo [a, c]; c"#, "3", ) } @@ -429,7 +437,7 @@ fn module_imports_5() -> TestResult { #[test] fn module_import_uses_internal_command() -> TestResult { run_test( - r#"module foo { def b [] { 2 }; export def a [] { b } }; use foo; foo.a"#, + r#"module foo { def b [] { 2 }; export def a [] { b } }; use foo; foo a"#, "2", ) } @@ -491,7 +499,7 @@ fn hide_twice_not_allowed() -> TestResult { #[test] fn hides_import_1() -> TestResult { fail_test( - r#"module spam { export def foo [] { "foo" } }; use spam; hide spam.foo; foo"#, + r#"module spam { export def foo [] { "foo" } }; use spam; hide spam foo; foo"#, not_found_msg(), ) } @@ -499,7 +507,7 @@ fn hides_import_1() -> TestResult { #[test] fn hides_import_2() -> TestResult { fail_test( - r#"module spam { export def foo [] { "foo" } }; use spam; hide spam.*; foo"#, + r#"module spam { export def foo [] { "foo" } }; use spam; hide spam *; foo"#, not_found_msg(), ) } @@ -507,7 +515,7 @@ fn hides_import_2() -> TestResult { #[test] fn hides_import_3() -> TestResult { fail_test( - r#"module spam { export def foo [] { "foo" } }; use spam; hide spam.[foo]; foo"#, + r#"module spam { export def foo [] { "foo" } }; use spam; hide spam [foo]; foo"#, not_found_msg(), ) } @@ -515,7 +523,7 @@ fn hides_import_3() -> TestResult { #[test] fn hides_import_4() -> TestResult { fail_test( - r#"module spam { export def foo [] { "foo" } }; use spam.foo; hide foo; foo"#, + r#"module spam { export def foo [] { "foo" } }; use spam foo; hide foo; foo"#, not_found_msg(), ) } @@ -523,7 +531,15 @@ fn hides_import_4() -> TestResult { #[test] fn hides_import_5() -> TestResult { fail_test( - r#"module spam { export def foo [] { "foo" } }; use spam.*; hide foo; foo"#, + r#"module spam { export def foo [] { "foo" } }; use spam *; hide foo; foo"#, + not_found_msg(), + ) +} + +#[test] +fn hides_import_6() -> TestResult { + fail_test( + r#"module spam { export def foo [] { "foo" } }; use spam; hide spam; foo"#, not_found_msg(), ) } @@ -539,7 +555,7 @@ fn def_twice_should_fail() -> TestResult { #[test] fn use_import_after_hide() -> TestResult { run_test( - r#"module spam { export def foo [] { "foo" } }; use spam.foo; hide foo; use spam.foo; foo"#, + r#"module spam { export def foo [] { "foo" } }; use spam foo; hide foo; use spam foo; foo"#, "foo", ) } @@ -547,7 +563,7 @@ fn use_import_after_hide() -> TestResult { #[test] fn hide_shadowed_decl() -> TestResult { run_test( - r#"module spam { export def foo [] { "bar" } }; def foo [] { "foo" }; do { use spam.foo; hide foo; foo }"#, + r#"module spam { export def foo [] { "bar" } }; def foo [] { "foo" }; do { use spam foo; hide foo; foo }"#, "foo", ) } @@ -555,7 +571,7 @@ fn hide_shadowed_decl() -> TestResult { #[test] fn hides_all_decls_within_scope() -> TestResult { fail_test( - r#"module spam { export def foo [] { "bar" } }; def foo [] { "foo" }; use spam.foo; hide foo; foo"#, + r#"module spam { export def foo [] { "bar" } }; def foo [] { "foo" }; use spam foo; hide foo; foo"#, not_found_msg(), ) } @@ -785,3 +801,13 @@ fn long_flag() -> TestResult { fn help_works_with_missing_requirements() -> TestResult { run_test(r#"each --help | lines | length"#, "10") } + +#[test] +fn scope_variable() -> TestResult { + run_test(r"let x = 3; $scope.vars.0", "$x") +} + +#[test] +fn zip_ranges() -> TestResult { + run_test(r"1..3 | zip 4..6 | get 2.1", "6") +}