Improve md5 and sha256 code (#3841)
* Refactor Hash code to simplify md5 and sha256 implementations Md5 and Sha256 (and other future digests) require less boilerplate code now. Error reporting includues the name of the hash again. * Add missing hash sha256 test
This commit is contained in:
parent
7f7af2bbaa
commit
9696e4d315
|
@ -1,40 +1,84 @@
|
||||||
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use nu_errors::ShellError;
|
use nu_errors::ShellError;
|
||||||
use nu_protocol::ShellTypeName;
|
use nu_protocol::{ColumnPath, Primitive, SyntaxShape, UntaggedValue, Value};
|
||||||
use nu_protocol::{ColumnPath, Primitive, UntaggedValue, Value};
|
use nu_protocol::{ShellTypeName, Signature};
|
||||||
use nu_source::Tag;
|
use nu_source::Tag;
|
||||||
|
|
||||||
pub fn run<D>(args: CommandArgs) -> Result<OutputStream, ShellError>
|
pub trait HashDigest: digest::Digest {
|
||||||
|
fn name() -> &'static str;
|
||||||
|
fn examples() -> Vec<Example>;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct SubCommand<D: HashDigest> {
|
||||||
|
name_string: String,
|
||||||
|
usage_string: String,
|
||||||
|
phantom: PhantomData<D>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<D: HashDigest> Default for SubCommand<D> {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
name_string: format!("hash {}", D::name()),
|
||||||
|
usage_string: format!("{} encode a value", D::name()),
|
||||||
|
phantom: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<D> WholeStreamCommand for SubCommand<D>
|
||||||
where
|
where
|
||||||
D: digest::Digest,
|
D: HashDigest + Send + Sync,
|
||||||
digest::Output<D>: core::fmt::LowerHex,
|
digest::Output<D>: core::fmt::LowerHex,
|
||||||
{
|
{
|
||||||
let column_paths: Vec<ColumnPath> = args.rest(0)?;
|
fn name(&self) -> &str {
|
||||||
|
&self.name_string
|
||||||
|
}
|
||||||
|
|
||||||
Ok(args
|
fn signature(&self) -> Signature {
|
||||||
.input
|
Signature::build(self.name()).rest(
|
||||||
.map(move |v| {
|
SyntaxShape::ColumnPath,
|
||||||
if column_paths.is_empty() {
|
format!("optionally {} encode data by column paths", D::name()),
|
||||||
action::<D>(&v, v.tag())
|
)
|
||||||
} else {
|
}
|
||||||
let mut ret = v;
|
|
||||||
|
|
||||||
for path in &column_paths {
|
fn usage(&self) -> &str {
|
||||||
ret = ret.swap_data_by_column_path(
|
&self.usage_string
|
||||||
path,
|
}
|
||||||
Box::new(move |old| action::<D>(old, old.tag())),
|
|
||||||
)?;
|
fn examples(&self) -> Vec<Example> {
|
||||||
|
D::examples()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
|
let column_paths: Vec<ColumnPath> = args.rest(0)?;
|
||||||
|
|
||||||
|
Ok(args
|
||||||
|
.input
|
||||||
|
.map(move |v| {
|
||||||
|
if column_paths.is_empty() {
|
||||||
|
action::<D>(&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::<D>(old, old.tag())),
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(ret)
|
||||||
}
|
}
|
||||||
|
})
|
||||||
Ok(ret)
|
.into_input_stream())
|
||||||
}
|
}
|
||||||
})
|
|
||||||
.into_input_stream())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn action<D>(input: &Value, tag: Tag) -> Result<Value, ShellError>
|
pub fn action<D>(input: &Value, tag: Tag) -> Result<Value, ShellError>
|
||||||
where
|
where
|
||||||
D: digest::Digest,
|
D: HashDigest,
|
||||||
digest::Output<D>: core::fmt::LowerHex,
|
digest::Output<D>: core::fmt::LowerHex,
|
||||||
{
|
{
|
||||||
match &input.value {
|
match &input.value {
|
||||||
|
@ -49,7 +93,7 @@ where
|
||||||
other => {
|
other => {
|
||||||
let got = format!("got {}", other.type_name());
|
let got = format!("got {}", other.type_name());
|
||||||
Err(ShellError::labeled_error(
|
Err(ShellError::labeled_error(
|
||||||
"value is not supported for hashing",
|
format!("value is not supported for hashing as {}", D::name()),
|
||||||
got,
|
got,
|
||||||
tag.span,
|
tag.span,
|
||||||
))
|
))
|
||||||
|
|
|
@ -1,34 +1,17 @@
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use md5::Md5;
|
use md5::Md5;
|
||||||
use nu_engine::WholeStreamCommand;
|
use nu_protocol::UntaggedValue;
|
||||||
use nu_errors::ShellError;
|
|
||||||
use nu_protocol::{Signature, SyntaxShape, UntaggedValue};
|
|
||||||
|
|
||||||
use super::generic_digest;
|
use super::generic_digest::{self, HashDigest};
|
||||||
|
|
||||||
pub struct SubCommand;
|
pub type SubCommand = generic_digest::SubCommand<Md5>;
|
||||||
|
|
||||||
impl WholeStreamCommand for SubCommand {
|
impl HashDigest for Md5 {
|
||||||
fn name(&self) -> &str {
|
fn name() -> &'static str {
|
||||||
"hash md5"
|
"md5"
|
||||||
}
|
}
|
||||||
|
|
||||||
fn signature(&self) -> Signature {
|
fn examples() -> Vec<Example> {
|
||||||
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<OutputStream, ShellError> {
|
|
||||||
generic_digest::run::<Md5>(args)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn examples(&self) -> Vec<Example> {
|
|
||||||
vec![
|
vec![
|
||||||
Example {
|
Example {
|
||||||
description: "md5 encode a string",
|
description: "md5 encode a string",
|
||||||
|
|
|
@ -1,34 +1,17 @@
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use nu_engine::WholeStreamCommand;
|
use nu_protocol::UntaggedValue;
|
||||||
use nu_errors::ShellError;
|
|
||||||
use nu_protocol::{Signature, SyntaxShape, UntaggedValue};
|
|
||||||
use sha2::Sha256;
|
use sha2::Sha256;
|
||||||
|
|
||||||
use super::generic_digest;
|
use super::generic_digest::{self, HashDigest};
|
||||||
|
|
||||||
pub struct SubCommand;
|
pub type SubCommand = generic_digest::SubCommand<Sha256>;
|
||||||
|
|
||||||
impl WholeStreamCommand for SubCommand {
|
impl HashDigest for Sha256 {
|
||||||
fn name(&self) -> &str {
|
fn name() -> &'static str {
|
||||||
"hash sha256"
|
"sha256"
|
||||||
}
|
}
|
||||||
|
|
||||||
fn signature(&self) -> Signature {
|
fn examples() -> Vec<Example> {
|
||||||
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<OutputStream, ShellError> {
|
|
||||||
generic_digest::run::<Sha256>(args)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn examples(&self) -> Vec<Example> {
|
|
||||||
vec![
|
vec![
|
||||||
Example {
|
Example {
|
||||||
description: "sha256 encode a string",
|
description: "sha256 encode a string",
|
||||||
|
|
|
@ -84,8 +84,8 @@ pub fn create_default_context(interactive: bool) -> Result<EvaluationContext, Bo
|
||||||
// Text manipulation
|
// Text manipulation
|
||||||
whole_stream_command(Hash),
|
whole_stream_command(Hash),
|
||||||
whole_stream_command(HashBase64),
|
whole_stream_command(HashBase64),
|
||||||
whole_stream_command(HashMd5),
|
whole_stream_command(HashMd5::default()),
|
||||||
whole_stream_command(HashSha256),
|
whole_stream_command(HashSha256::default()),
|
||||||
whole_stream_command(Split),
|
whole_stream_command(Split),
|
||||||
whole_stream_command(SplitColumn),
|
whole_stream_command(SplitColumn),
|
||||||
whole_stream_command(SplitRow),
|
whole_stream_command(SplitRow),
|
||||||
|
|
|
@ -96,3 +96,19 @@ fn md5_works_with_file() {
|
||||||
|
|
||||||
assert_eq!(actual.out, "4de97601d232c427977ef11db396c951");
|
assert_eq!(actual.out, "4de97601d232c427977ef11db396c951");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn sha256_works_with_file() {
|
||||||
|
let actual = nu!(
|
||||||
|
cwd: "tests/fixtures/formats", pipeline(
|
||||||
|
r#"
|
||||||
|
open sample.db | hash sha256
|
||||||
|
"#
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
actual.out,
|
||||||
|
"2f5050e7eea415c1f3d80b5d93355efd15043ec9157a2bb167a9e73f2ae651f2"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user