diff --git a/crates/nu-command/src/commands/generators/hash_/generic_digest.rs b/crates/nu-command/src/commands/generators/hash_/generic_digest.rs index 542197b7c8..df2631f8cb 100644 --- a/crates/nu-command/src/commands/generators/hash_/generic_digest.rs +++ b/crates/nu-command/src/commands/generators/hash_/generic_digest.rs @@ -1,40 +1,84 @@ +use std::marker::PhantomData; + use crate::prelude::*; use nu_errors::ShellError; -use nu_protocol::ShellTypeName; -use nu_protocol::{ColumnPath, Primitive, UntaggedValue, Value}; +use nu_protocol::{ColumnPath, Primitive, SyntaxShape, UntaggedValue, Value}; +use nu_protocol::{ShellTypeName, Signature}; use nu_source::Tag; -pub fn run(args: CommandArgs) -> Result +pub trait HashDigest: digest::Digest { + fn name() -> &'static str; + fn examples() -> Vec; +} + +pub struct SubCommand { + name_string: String, + usage_string: String, + phantom: PhantomData, +} + +impl Default for SubCommand { + fn default() -> Self { + Self { + name_string: format!("hash {}", D::name()), + usage_string: format!("{} encode a value", D::name()), + phantom: PhantomData, + } + } +} + +impl WholeStreamCommand for SubCommand where - D: digest::Digest, + D: HashDigest + Send + Sync, digest::Output: core::fmt::LowerHex, { - let column_paths: Vec = args.rest(0)?; + fn name(&self) -> &str { + &self.name_string + } - Ok(args - .input - .map(move |v| { - if column_paths.is_empty() { - action::(&v, v.tag()) - } else { - let mut ret = v; + fn signature(&self) -> Signature { + Signature::build(self.name()).rest( + SyntaxShape::ColumnPath, + format!("optionally {} encode data by column paths", D::name()), + ) + } - for path in &column_paths { - ret = ret.swap_data_by_column_path( - path, - Box::new(move |old| action::(old, old.tag())), - )?; + fn usage(&self) -> &str { + &self.usage_string + } + + fn examples(&self) -> Vec { + D::examples() + } + + fn run(&self, args: CommandArgs) -> Result { + let column_paths: Vec = args.rest(0)?; + + Ok(args + .input + .map(move |v| { + if column_paths.is_empty() { + action::(&v, v.tag()) + } else { + let mut ret = v; + + for path in &column_paths { + ret = ret.swap_data_by_column_path( + path, + Box::new(move |old| action::(old, old.tag())), + )?; + } + + Ok(ret) } - - Ok(ret) - } - }) - .into_input_stream()) + }) + .into_input_stream()) + } } pub fn action(input: &Value, tag: Tag) -> Result where - D: digest::Digest, + D: HashDigest, digest::Output: core::fmt::LowerHex, { match &input.value { @@ -49,7 +93,7 @@ where other => { let got = format!("got {}", other.type_name()); Err(ShellError::labeled_error( - "value is not supported for hashing", + format!("value is not supported for hashing as {}", D::name()), got, tag.span, )) diff --git a/crates/nu-command/src/commands/generators/hash_/md5_.rs b/crates/nu-command/src/commands/generators/hash_/md5_.rs index 33365b497f..0559e7dfc6 100644 --- a/crates/nu-command/src/commands/generators/hash_/md5_.rs +++ b/crates/nu-command/src/commands/generators/hash_/md5_.rs @@ -1,34 +1,17 @@ use crate::prelude::*; use md5::Md5; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Signature, SyntaxShape, UntaggedValue}; +use nu_protocol::UntaggedValue; -use super::generic_digest; +use super::generic_digest::{self, HashDigest}; -pub struct SubCommand; +pub type SubCommand = generic_digest::SubCommand; -impl WholeStreamCommand for SubCommand { - fn name(&self) -> &str { - "hash md5" +impl HashDigest for Md5 { + fn name() -> &'static str { + "md5" } - fn signature(&self) -> Signature { - Signature::build("hash md5").rest( - SyntaxShape::ColumnPath, - "optionally md5 encode data by column paths", - ) - } - - fn usage(&self) -> &str { - "md5 encode a value" - } - - fn run(&self, args: CommandArgs) -> Result { - generic_digest::run::(args) - } - - fn examples(&self) -> Vec { + fn examples() -> Vec { vec![ Example { description: "md5 encode a string", diff --git a/crates/nu-command/src/commands/generators/hash_/sha256_.rs b/crates/nu-command/src/commands/generators/hash_/sha256_.rs index 666afde88d..4028dfdb42 100644 --- a/crates/nu-command/src/commands/generators/hash_/sha256_.rs +++ b/crates/nu-command/src/commands/generators/hash_/sha256_.rs @@ -1,34 +1,17 @@ use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Signature, SyntaxShape, UntaggedValue}; +use nu_protocol::UntaggedValue; use sha2::Sha256; -use super::generic_digest; +use super::generic_digest::{self, HashDigest}; -pub struct SubCommand; +pub type SubCommand = generic_digest::SubCommand; -impl WholeStreamCommand for SubCommand { - fn name(&self) -> &str { - "hash sha256" +impl HashDigest for Sha256 { + fn name() -> &'static str { + "sha256" } - fn signature(&self) -> Signature { - Signature::build("hash sha256").rest( - SyntaxShape::ColumnPath, - "optionally sha256 encode data by column paths", - ) - } - - fn usage(&self) -> &str { - "sha256 encode a value" - } - - fn run(&self, args: CommandArgs) -> Result { - generic_digest::run::(args) - } - - fn examples(&self) -> Vec { + fn examples() -> Vec { vec![ Example { description: "sha256 encode a string", diff --git a/crates/nu-command/src/default_context.rs b/crates/nu-command/src/default_context.rs index e07fd4daef..bb1780cc84 100644 --- a/crates/nu-command/src/default_context.rs +++ b/crates/nu-command/src/default_context.rs @@ -84,8 +84,8 @@ pub fn create_default_context(interactive: bool) -> Result