mirror of
https://github.com/nushell/nushell.git
synced 2025-02-08 22:51:42 +01:00
added check for endian-ness, added a bytes and skip (#3375)
This commit is contained in:
parent
e82fbb7bcf
commit
cc4616f25b
@ -11,6 +11,8 @@ pub struct SubCommand;
|
|||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
pub struct Arguments {
|
pub struct Arguments {
|
||||||
pub rest: Vec<ColumnPath>,
|
pub rest: Vec<ColumnPath>,
|
||||||
|
pub skip: Option<Value>,
|
||||||
|
pub bytes: Option<Value>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WholeStreamCommand for SubCommand {
|
impl WholeStreamCommand for SubCommand {
|
||||||
@ -19,10 +21,23 @@ impl WholeStreamCommand for SubCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
Signature::build("into binary").rest(
|
Signature::build("into binary")
|
||||||
|
.rest(
|
||||||
SyntaxShape::ColumnPath,
|
SyntaxShape::ColumnPath,
|
||||||
"column paths to convert to binary (for table input)",
|
"column paths to convert to binary (for table input)",
|
||||||
)
|
)
|
||||||
|
.named(
|
||||||
|
"skip",
|
||||||
|
SyntaxShape::Int,
|
||||||
|
"skip x number of bytes",
|
||||||
|
Some('s'),
|
||||||
|
)
|
||||||
|
.named(
|
||||||
|
"bytes",
|
||||||
|
SyntaxShape::Int,
|
||||||
|
"show y number of bytes",
|
||||||
|
Some('b'),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn usage(&self) -> &str {
|
fn usage(&self) -> &str {
|
||||||
@ -47,6 +62,30 @@ impl WholeStreamCommand for SubCommand {
|
|||||||
)
|
)
|
||||||
.into()]),
|
.into()]),
|
||||||
},
|
},
|
||||||
|
Example {
|
||||||
|
description: "convert string to a nushell binary primitive",
|
||||||
|
example:
|
||||||
|
"echo 'This is a string that is exactly 52 characters long.' | into binary --skip 10",
|
||||||
|
result: Some(vec![UntaggedValue::binary(
|
||||||
|
"string that is exactly 52 characters long."
|
||||||
|
.to_string()
|
||||||
|
.as_bytes()
|
||||||
|
.to_vec(),
|
||||||
|
)
|
||||||
|
.into()]),
|
||||||
|
},
|
||||||
|
Example {
|
||||||
|
description: "convert string to a nushell binary primitive",
|
||||||
|
example:
|
||||||
|
"echo 'This is a string that is exactly 52 characters long.' | into binary --skip 10 --bytes 10",
|
||||||
|
result: Some(vec![UntaggedValue::binary(
|
||||||
|
"string tha"
|
||||||
|
.to_string()
|
||||||
|
.as_bytes()
|
||||||
|
.to_vec(),
|
||||||
|
)
|
||||||
|
.into()]),
|
||||||
|
},
|
||||||
Example {
|
Example {
|
||||||
description: "convert a number to a nushell binary primitive",
|
description: "convert a number to a nushell binary primitive",
|
||||||
example: "echo 1 | into binary",
|
example: "echo 1 | into binary",
|
||||||
@ -83,18 +122,27 @@ impl WholeStreamCommand for SubCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn into_binary(args: CommandArgs) -> Result<ActionStream, ShellError> {
|
fn into_binary(args: CommandArgs) -> Result<ActionStream, ShellError> {
|
||||||
let (Arguments { rest: column_paths }, input) = args.process()?;
|
let (
|
||||||
|
Arguments {
|
||||||
|
rest: column_paths,
|
||||||
|
skip,
|
||||||
|
bytes,
|
||||||
|
},
|
||||||
|
input,
|
||||||
|
) = args.process()?;
|
||||||
|
|
||||||
Ok(input
|
Ok(input
|
||||||
.map(move |v| {
|
.map(move |v| {
|
||||||
if column_paths.is_empty() {
|
if column_paths.is_empty() {
|
||||||
ReturnSuccess::value(action(&v, v.tag())?)
|
ReturnSuccess::value(action(&v, v.tag(), &skip, &bytes)?)
|
||||||
} else {
|
} else {
|
||||||
let mut ret = v;
|
let mut ret = v;
|
||||||
for path in &column_paths {
|
for path in &column_paths {
|
||||||
|
let skip_clone = skip.clone();
|
||||||
|
let bytes_clone = bytes.clone();
|
||||||
ret = ret.swap_data_by_column_path(
|
ret = ret.swap_data_by_column_path(
|
||||||
path,
|
path,
|
||||||
Box::new(move |old| action(old, old.tag())),
|
Box::new(move |old| action(old, old.tag(), &skip_clone, &bytes_clone)),
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,16 +152,49 @@ fn into_binary(args: CommandArgs) -> Result<ActionStream, ShellError> {
|
|||||||
.to_action_stream())
|
.to_action_stream())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn action(input: &Value, tag: impl Into<Tag>) -> Result<Value, ShellError> {
|
pub fn bigint_to_endian(n: &BigInt) -> Vec<u8> {
|
||||||
|
if cfg!(target_endian = "little") {
|
||||||
|
// eprintln!("Little Endian");
|
||||||
|
n.to_bytes_le().1
|
||||||
|
} else {
|
||||||
|
// eprintln!("Big Endian");
|
||||||
|
n.to_bytes_be().1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn action(
|
||||||
|
input: &Value,
|
||||||
|
tag: impl Into<Tag>,
|
||||||
|
skip: &Option<Value>,
|
||||||
|
bytes: &Option<Value>,
|
||||||
|
) -> Result<Value, ShellError> {
|
||||||
let tag = tag.into();
|
let tag = tag.into();
|
||||||
|
let skip_bytes = match skip {
|
||||||
|
Some(s) => s.as_usize().unwrap_or(0),
|
||||||
|
None => 0usize,
|
||||||
|
};
|
||||||
|
|
||||||
|
let num_bytes = match bytes {
|
||||||
|
Some(b) => b.as_usize().unwrap_or(0),
|
||||||
|
None => 0usize,
|
||||||
|
};
|
||||||
|
|
||||||
match &input.value {
|
match &input.value {
|
||||||
UntaggedValue::Primitive(prim) => Ok(UntaggedValue::binary(match prim {
|
UntaggedValue::Primitive(prim) => Ok(UntaggedValue::binary(match prim {
|
||||||
Primitive::Binary(b) => b.to_vec(),
|
Primitive::Binary(b) => {
|
||||||
// TODO: Several places here we use Little Endian. We should probably
|
if num_bytes == 0usize {
|
||||||
// query the host to determine if it's Big Endian or Little Endian
|
b.to_vec().into_iter().skip(skip_bytes).collect()
|
||||||
Primitive::Int(n_ref) => n_ref.to_bytes_le().1,
|
} else {
|
||||||
|
b.to_vec()
|
||||||
|
.into_iter()
|
||||||
|
.skip(skip_bytes)
|
||||||
|
.take(num_bytes)
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Primitive::Int(n_ref) => bigint_to_endian(n_ref),
|
||||||
Primitive::Decimal(dec) => match dec.to_bigint() {
|
Primitive::Decimal(dec) => match dec.to_bigint() {
|
||||||
Some(n) => n.to_bytes_le().1,
|
Some(n) => bigint_to_endian(&n),
|
||||||
None => {
|
None => {
|
||||||
return Err(ShellError::unimplemented(
|
return Err(ShellError::unimplemented(
|
||||||
"failed to convert decimal to int",
|
"failed to convert decimal to int",
|
||||||
@ -121,17 +202,35 @@ pub fn action(input: &Value, tag: impl Into<Tag>) -> Result<Value, ShellError> {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
Primitive::Filesize(a_filesize) => match a_filesize.to_bigint() {
|
Primitive::Filesize(a_filesize) => match a_filesize.to_bigint() {
|
||||||
Some(n) => n.to_bytes_le().1,
|
Some(n) => bigint_to_endian(&n),
|
||||||
None => {
|
None => {
|
||||||
return Err(ShellError::unimplemented(
|
return Err(ShellError::unimplemented(
|
||||||
"failed to convert filesize to bigint",
|
"failed to convert filesize to bigint",
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Primitive::String(a_string) => a_string.as_bytes().to_vec(),
|
Primitive::String(a_string) => {
|
||||||
|
// a_string.as_bytes().to_vec()
|
||||||
|
if num_bytes == 0usize {
|
||||||
|
a_string
|
||||||
|
.as_bytes()
|
||||||
|
.to_vec()
|
||||||
|
.into_iter()
|
||||||
|
.skip(skip_bytes)
|
||||||
|
.collect()
|
||||||
|
} else {
|
||||||
|
a_string
|
||||||
|
.as_bytes()
|
||||||
|
.to_vec()
|
||||||
|
.into_iter()
|
||||||
|
.skip(skip_bytes)
|
||||||
|
.take(num_bytes)
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
}
|
||||||
Primitive::Boolean(a_bool) => match a_bool {
|
Primitive::Boolean(a_bool) => match a_bool {
|
||||||
false => BigInt::from(0).to_bytes_le().1,
|
false => bigint_to_endian(&BigInt::from(0)),
|
||||||
true => BigInt::from(1).to_bytes_le().1,
|
true => bigint_to_endian(&BigInt::from(1)),
|
||||||
},
|
},
|
||||||
Primitive::Date(a_date) => a_date.format("%c").to_string().as_bytes().to_vec(),
|
Primitive::Date(a_date) => a_date.format("%c").to_string().as_bytes().to_vec(),
|
||||||
Primitive::FilePath(a_filepath) => a_filepath
|
Primitive::FilePath(a_filepath) => a_filepath
|
||||||
|
Loading…
Reference in New Issue
Block a user