Initial commit
This commit is contained in:
parent
366e52b76d
commit
ec9089ebc5
7
Cargo.lock
generated
7
Cargo.lock
generated
|
@ -1147,6 +1147,12 @@ dependencies = [
|
|||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "data-encoding"
|
||||
version = "2.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2"
|
||||
|
||||
[[package]]
|
||||
name = "deranged"
|
||||
version = "0.3.11"
|
||||
|
@ -3044,6 +3050,7 @@ dependencies = [
|
|||
"chrono-tz 0.8.6",
|
||||
"crossterm",
|
||||
"csv",
|
||||
"data-encoding",
|
||||
"deunicode",
|
||||
"dialoguer",
|
||||
"digest",
|
||||
|
|
|
@ -102,6 +102,7 @@ v_htmlescape = { workspace = true }
|
|||
wax = { workspace = true }
|
||||
which = { workspace = true }
|
||||
unicode-width = { workspace = true }
|
||||
data-encoding = { version = "2.6.0", features = ["alloc"] }
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
winreg = { workspace = true }
|
||||
|
|
|
@ -179,6 +179,8 @@ pub fn add_shell_command_context(mut engine_state: EngineState) -> EngineState {
|
|||
Char,
|
||||
Decode,
|
||||
Encode,
|
||||
EncodeBase,
|
||||
DecodeBase,
|
||||
DecodeBase64,
|
||||
EncodeBase64,
|
||||
DetectColumns,
|
||||
|
|
76
crates/nu-command/src/strings/base/decode.rs
Normal file
76
crates/nu-command/src/strings/base/decode.rs
Normal file
|
@ -0,0 +1,76 @@
|
|||
use nu_engine::command_prelude::*;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct DecodeBase;
|
||||
|
||||
impl Command for DecodeBase {
|
||||
fn name(&self) -> &str {
|
||||
"decode base"
|
||||
}
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("decode base")
|
||||
.input_output_types(vec![(Type::String, Type::Binary)])
|
||||
.allow_variants_without_examples(true)
|
||||
.required("encoding", SyntaxShape::String, "encoding to use")
|
||||
.category(Category::Formats)
|
||||
}
|
||||
|
||||
fn usage(&self) -> &str {
|
||||
"Decode a value."
|
||||
}
|
||||
|
||||
fn extra_usage(&self) -> &str {
|
||||
"TODO"
|
||||
}
|
||||
|
||||
fn examples(&self) -> Vec<Example> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn is_const(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn run(
|
||||
&self,
|
||||
engine_state: &EngineState,
|
||||
stack: &mut Stack,
|
||||
call: &Call,
|
||||
input: PipelineData,
|
||||
) -> Result<PipelineData, ShellError> {
|
||||
let name: String = call.req(engine_state, stack, 0)?;
|
||||
|
||||
decode(&name, call.span(), input)
|
||||
}
|
||||
|
||||
fn run_const(
|
||||
&self,
|
||||
working_set: &StateWorkingSet,
|
||||
call: &Call,
|
||||
input: PipelineData,
|
||||
) -> Result<PipelineData, ShellError> {
|
||||
let name: String = call.req_const(working_set, 0)?;
|
||||
|
||||
decode(&name, call.span(), input)
|
||||
}
|
||||
}
|
||||
|
||||
fn decode(name: &str, call_span: Span, input: PipelineData) -> Result<PipelineData, ShellError> {
|
||||
let encoding = super::encoding(&name, call_span, call_span)?;
|
||||
let metadata = input.metadata();
|
||||
let (input_str, input_span) = super::get_string(input, call_span)?;
|
||||
let output = encoding.decode(input_str.as_bytes()).unwrap();
|
||||
|
||||
Ok(Value::binary(output, call_span).into_pipeline_data_with_metadata(metadata))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_examples() {
|
||||
crate::test_examples(DecodeBase)
|
||||
}
|
||||
}
|
79
crates/nu-command/src/strings/base/encode.rs
Normal file
79
crates/nu-command/src/strings/base/encode.rs
Normal file
|
@ -0,0 +1,79 @@
|
|||
use nu_engine::command_prelude::*;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct EncodeBase;
|
||||
|
||||
impl Command for EncodeBase {
|
||||
fn name(&self) -> &str {
|
||||
"encode base"
|
||||
}
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("encode base")
|
||||
.input_output_types(vec![
|
||||
(Type::String, Type::String),
|
||||
(Type::Binary, Type::String),
|
||||
])
|
||||
.allow_variants_without_examples(true)
|
||||
.required("encoding", SyntaxShape::String, "encoding to use")
|
||||
.category(Category::Formats)
|
||||
}
|
||||
|
||||
fn usage(&self) -> &str {
|
||||
"Encode a value."
|
||||
}
|
||||
|
||||
fn extra_usage(&self) -> &str {
|
||||
"TODO"
|
||||
}
|
||||
|
||||
fn examples(&self) -> Vec<Example> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn is_const(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn run(
|
||||
&self,
|
||||
engine_state: &EngineState,
|
||||
stack: &mut Stack,
|
||||
call: &Call,
|
||||
input: PipelineData,
|
||||
) -> Result<PipelineData, ShellError> {
|
||||
let name: String = call.req(engine_state, stack, 0)?;
|
||||
|
||||
encode(&name, call.span(), input)
|
||||
}
|
||||
|
||||
fn run_const(
|
||||
&self,
|
||||
working_set: &StateWorkingSet,
|
||||
call: &Call,
|
||||
input: PipelineData,
|
||||
) -> Result<PipelineData, ShellError> {
|
||||
let name: String = call.req_const(working_set, 0)?;
|
||||
|
||||
encode(&name, call.span(), input)
|
||||
}
|
||||
}
|
||||
|
||||
fn encode(name: &str, call_span: Span, input: PipelineData) -> Result<PipelineData, ShellError> {
|
||||
let encoding = super::encoding(name, call_span, call_span)?;
|
||||
let metadata = input.metadata();
|
||||
let (input_bytes, input_span) = super::get_binary(input, call_span)?;
|
||||
let output = encoding.encode(&input_bytes);
|
||||
|
||||
Ok(Value::string(output, call_span).into_pipeline_data_with_metadata(metadata))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_examples() {
|
||||
crate::test_examples(EncodeBase)
|
||||
}
|
||||
}
|
88
crates/nu-command/src/strings/base/mod.rs
Normal file
88
crates/nu-command/src/strings/base/mod.rs
Normal file
|
@ -0,0 +1,88 @@
|
|||
use nu_protocol::{PipelineData, ShellError, Span, Value};
|
||||
|
||||
mod decode;
|
||||
mod encode;
|
||||
|
||||
pub use decode::DecodeBase;
|
||||
pub use encode::EncodeBase;
|
||||
|
||||
pub fn encoding(
|
||||
name: &str,
|
||||
val_span: Span,
|
||||
call_span: Span,
|
||||
) -> Result<data_encoding::Encoding, ShellError> {
|
||||
match name {
|
||||
"base32" => Ok(data_encoding::BASE32),
|
||||
"base32hex" => Ok(data_encoding::BASE32HEX),
|
||||
"base32hex_nopad" => Ok(data_encoding::BASE32HEX_NOPAD),
|
||||
"base32_dnscurve" => Ok(data_encoding::BASE32_DNSCURVE),
|
||||
"base32_dnssec" => Ok(data_encoding::BASE32_DNSSEC),
|
||||
"base32_nopad" => Ok(data_encoding::BASE32_NOPAD),
|
||||
"base64" => Ok(data_encoding::BASE64),
|
||||
"base64url" => Ok(data_encoding::BASE64URL),
|
||||
"base64url_nopad" => Ok(data_encoding::BASE64URL_NOPAD),
|
||||
"base64_mime" => Ok(data_encoding::BASE64_MIME),
|
||||
"base64_mime_permissive" => Ok(data_encoding::BASE64_MIME_PERMISSIVE),
|
||||
"base64_nopad" => Ok(data_encoding::BASE64_NOPAD),
|
||||
"hexlower" => Ok(data_encoding::HEXLOWER),
|
||||
"hexlower_permissive" => Ok(data_encoding::HEXLOWER_PERMISSIVE),
|
||||
"hexupper" => Ok(data_encoding::HEXUPPER),
|
||||
"hexupper_permissive" => Ok(data_encoding::HEXUPPER_PERMISSIVE),
|
||||
_ => Err(ShellError::IncorrectValue {
|
||||
msg: format!("Encoding '{name}' not found"),
|
||||
val_span,
|
||||
call_span,
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_string(input: PipelineData, call_span: Span) -> Result<(String, Span), ShellError> {
|
||||
match input {
|
||||
PipelineData::Value(val, ..) => {
|
||||
let span = val.span();
|
||||
match val {
|
||||
Value::String { val, .. } => Ok((val, span)),
|
||||
|
||||
_ => {
|
||||
todo!("Invalid type")
|
||||
}
|
||||
}
|
||||
}
|
||||
PipelineData::ListStream(..) => {
|
||||
todo!()
|
||||
}
|
||||
PipelineData::ByteStream(stream, ..) => {
|
||||
let span = stream.span();
|
||||
Ok((stream.into_string()?, span))
|
||||
}
|
||||
PipelineData::Empty => {
|
||||
todo!("Can't have empty data");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_binary(input: PipelineData, call_span: Span) -> Result<(Vec<u8>, Span), ShellError> {
|
||||
match input {
|
||||
PipelineData::Value(val, ..) => {
|
||||
let span = val.span();
|
||||
match val {
|
||||
Value::Binary { val, .. } => Ok((val, span)),
|
||||
Value::String { val, .. } => Ok((val.into_bytes(), span)),
|
||||
|
||||
_ => {
|
||||
todo!("Invalid type")
|
||||
}
|
||||
}
|
||||
}
|
||||
PipelineData::ListStream(..) => {
|
||||
todo!()
|
||||
}
|
||||
PipelineData::ByteStream(stream, ..) => {
|
||||
let span = stream.span();
|
||||
Ok((stream.into_bytes()?, span))
|
||||
}
|
||||
PipelineData::Empty => {
|
||||
todo!("Can't have empty data");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,3 +1,4 @@
|
|||
mod base;
|
||||
mod char_;
|
||||
mod detect_columns;
|
||||
mod encode_decode;
|
||||
|
@ -7,6 +8,7 @@ mod parse;
|
|||
mod split;
|
||||
mod str_;
|
||||
|
||||
pub use base::{DecodeBase, EncodeBase};
|
||||
pub use char_::Char;
|
||||
pub use detect_columns::*;
|
||||
pub use encode_decode::*;
|
||||
|
|
Loading…
Reference in New Issue
Block a user