forked from extern/nushell
Begin migration away from arg serialization (#3281)
* initial implementation * Move a few commands over to new arg system * Fix char also
This commit is contained in:
parent
5fcf11fcb0
commit
09a1f5acb9
5
Cargo.lock
generated
5
Cargo.lock
generated
@ -3373,7 +3373,9 @@ dependencies = [
|
|||||||
"ansi_term 0.12.1",
|
"ansi_term 0.12.1",
|
||||||
"async-recursion",
|
"async-recursion",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
|
"bigdecimal",
|
||||||
"bytes 0.5.6",
|
"bytes 0.5.6",
|
||||||
|
"chrono",
|
||||||
"codespan-reporting",
|
"codespan-reporting",
|
||||||
"derive-new",
|
"derive-new",
|
||||||
"dirs-next",
|
"dirs-next",
|
||||||
@ -3401,6 +3403,9 @@ dependencies = [
|
|||||||
"nu-stream",
|
"nu-stream",
|
||||||
"nu-test-support",
|
"nu-test-support",
|
||||||
"nu-value-ext",
|
"nu-value-ext",
|
||||||
|
"num-bigint 0.3.2",
|
||||||
|
"num-format",
|
||||||
|
"num-traits 0.2.14",
|
||||||
"parking_lot 0.11.1",
|
"parking_lot 0.11.1",
|
||||||
"rayon",
|
"rayon",
|
||||||
"serde 1.0.124",
|
"serde 1.0.124",
|
||||||
|
@ -7,13 +7,6 @@ use nu_source::Tagged;
|
|||||||
|
|
||||||
pub struct Command;
|
pub struct Command;
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
|
||||||
struct AnsiArgs {
|
|
||||||
code: Value,
|
|
||||||
escape: Option<Tagged<String>>,
|
|
||||||
osc: Option<Tagged<String>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl WholeStreamCommand for Command {
|
impl WholeStreamCommand for Command {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"ansi"
|
"ansi"
|
||||||
@ -120,9 +113,14 @@ Format: #
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
|
fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
let (AnsiArgs { code, escape, osc }, _) = args.process()?;
|
let args = args.evaluate_once()?;
|
||||||
|
|
||||||
|
let code: Option<Result<Tagged<String>, ShellError>> = args.opt(0);
|
||||||
|
let escape: Option<Result<Tagged<String>, ShellError>> = args.get_flag("escape");
|
||||||
|
let osc: Option<Result<Tagged<String>, ShellError>> = args.get_flag("osc");
|
||||||
|
|
||||||
if let Some(e) = escape {
|
if let Some(e) = escape {
|
||||||
|
let e = e?;
|
||||||
let esc_vec: Vec<char> = e.item.chars().collect();
|
let esc_vec: Vec<char> = e.item.chars().collect();
|
||||||
if esc_vec[0] == '\\' {
|
if esc_vec[0] == '\\' {
|
||||||
return Err(ShellError::labeled_error(
|
return Err(ShellError::labeled_error(
|
||||||
@ -138,6 +136,7 @@ Format: #
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let Some(o) = osc {
|
if let Some(o) = osc {
|
||||||
|
let o = o?;
|
||||||
let osc_vec: Vec<char> = o.item.chars().collect();
|
let osc_vec: Vec<char> = o.item.chars().collect();
|
||||||
if osc_vec[0] == '\\' {
|
if osc_vec[0] == '\\' {
|
||||||
return Err(ShellError::labeled_error(
|
return Err(ShellError::labeled_error(
|
||||||
@ -155,25 +154,33 @@ Format: #
|
|||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
let code_string = code.as_string()?;
|
if let Some(code) = code {
|
||||||
let ansi_code = str_to_ansi(code_string);
|
let code = code?;
|
||||||
|
let ansi_code = str_to_ansi(&code.item);
|
||||||
|
|
||||||
if let Some(output) = ansi_code {
|
if let Some(output) = ansi_code {
|
||||||
Ok(OutputStream::one(ReturnSuccess::value(
|
Ok(OutputStream::one(ReturnSuccess::value(
|
||||||
UntaggedValue::string(output).into_value(code.tag()),
|
UntaggedValue::string(output).into_value(code.tag()),
|
||||||
)))
|
)))
|
||||||
|
} else {
|
||||||
|
Err(ShellError::labeled_error(
|
||||||
|
"Unknown ansi code",
|
||||||
|
"unknown ansi code",
|
||||||
|
code.tag(),
|
||||||
|
))
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
Err(ShellError::labeled_error(
|
Err(ShellError::labeled_error(
|
||||||
"Unknown ansi code",
|
"Expected ansi code",
|
||||||
"unknown ansi code",
|
"expect ansi code",
|
||||||
code.tag(),
|
args.call_info.name_tag.clone(),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn str_to_ansi(s: String) -> Option<String> {
|
pub fn str_to_ansi(s: &str) -> Option<String> {
|
||||||
match s.as_str() {
|
match s {
|
||||||
"g" | "green" => Some(Color::Green.prefix().to_string()),
|
"g" | "green" => Some(Color::Green.prefix().to_string()),
|
||||||
"gb" | "green_bold" => Some(Color::Green.bold().prefix().to_string()),
|
"gb" | "green_bold" => Some(Color::Green.bold().prefix().to_string()),
|
||||||
"gu" | "green_underline" => Some(Color::Green.underline().prefix().to_string()),
|
"gu" | "green_underline" => Some(Color::Green.underline().prefix().to_string()),
|
||||||
|
@ -5,11 +5,6 @@ use nu_data::value::format_leaf;
|
|||||||
use nu_engine::WholeStreamCommand;
|
use nu_engine::WholeStreamCommand;
|
||||||
use nu_protocol::{ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value};
|
use nu_protocol::{ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value};
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
|
||||||
pub struct BuildStringArgs {
|
|
||||||
rest: Vec<Value>,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct BuildString;
|
pub struct BuildString;
|
||||||
|
|
||||||
impl WholeStreamCommand for BuildString {
|
impl WholeStreamCommand for BuildString {
|
||||||
@ -28,7 +23,8 @@ impl WholeStreamCommand for BuildString {
|
|||||||
|
|
||||||
fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
|
fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
let tag = args.call_info.name_tag.clone();
|
let tag = args.call_info.name_tag.clone();
|
||||||
let (BuildStringArgs { rest }, _) = args.process()?;
|
let args = args.evaluate_once()?;
|
||||||
|
let rest: Vec<Value> = args.rest(0)?;
|
||||||
|
|
||||||
let mut output_string = String::new();
|
let mut output_string = String::new();
|
||||||
|
|
||||||
|
@ -75,7 +75,7 @@ pub fn cal(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
|||||||
let mut selected_year: i32 = current_year;
|
let mut selected_year: i32 = current_year;
|
||||||
let mut current_day_option: Option<u32> = Some(current_day);
|
let mut current_day_option: Option<u32> = Some(current_day);
|
||||||
|
|
||||||
let month_range = if let Some(full_year_value) = args.get("full-year") {
|
let month_range = if let Some(full_year_value) = args.call_info.args.get("full-year") {
|
||||||
if let Ok(year_u64) = full_year_value.as_u64() {
|
if let Ok(year_u64) = full_year_value.as_u64() {
|
||||||
selected_year = year_u64 as i32;
|
selected_year = year_u64 as i32;
|
||||||
|
|
||||||
@ -209,7 +209,7 @@ fn add_month_to_table(
|
|||||||
|
|
||||||
let month_helper = match month_helper_result {
|
let month_helper = match month_helper_result {
|
||||||
Ok(month_helper) => month_helper,
|
Ok(month_helper) => month_helper,
|
||||||
Err(()) => match args.get("full-year") {
|
Err(()) => match args.call_info.args.get("full-year") {
|
||||||
Some(full_year_value) => {
|
Some(full_year_value) => {
|
||||||
return Err(get_invalid_year_shell_error(&full_year_value.tag()))
|
return Err(get_invalid_year_shell_error(&full_year_value.tag()))
|
||||||
}
|
}
|
||||||
@ -235,7 +235,7 @@ fn add_month_to_table(
|
|||||||
|
|
||||||
let mut week_start_day = days_of_the_week[0].to_string();
|
let mut week_start_day = days_of_the_week[0].to_string();
|
||||||
|
|
||||||
if let Some(week_start_value) = args.get("week-start") {
|
if let Some(week_start_value) = args.call_info.args.get("week-start") {
|
||||||
if let Ok(day) = week_start_value.as_string() {
|
if let Ok(day) = week_start_value.as_string() {
|
||||||
if days_of_the_week.contains(&day.as_str()) {
|
if days_of_the_week.contains(&day.as_str()) {
|
||||||
week_start_day = day;
|
week_start_day = day;
|
||||||
@ -264,10 +264,10 @@ fn add_month_to_table(
|
|||||||
let mut day_number: u32 = 1;
|
let mut day_number: u32 = 1;
|
||||||
let day_limit: u32 = total_start_offset + month_helper.number_of_days_in_month;
|
let day_limit: u32 = total_start_offset + month_helper.number_of_days_in_month;
|
||||||
|
|
||||||
let should_show_year_column = args.has("year");
|
let should_show_year_column = args.has_flag("year");
|
||||||
let should_show_quarter_column = args.has("quarter");
|
let should_show_quarter_column = args.has_flag("quarter");
|
||||||
let should_show_month_column = args.has("month");
|
let should_show_month_column = args.has_flag("month");
|
||||||
let should_show_month_names = args.has("month-names");
|
let should_show_month_names = args.has_flag("month-names");
|
||||||
|
|
||||||
while day_number <= day_limit {
|
while day_number <= day_limit {
|
||||||
let mut indexmap = IndexMap::new();
|
let mut indexmap = IndexMap::new();
|
||||||
|
@ -1,18 +1,11 @@
|
|||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use nu_engine::WholeStreamCommand;
|
use nu_engine::{FromValue, WholeStreamCommand};
|
||||||
use nu_errors::ShellError;
|
use nu_errors::ShellError;
|
||||||
use nu_protocol::{ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value};
|
use nu_protocol::{ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value};
|
||||||
use nu_source::Tagged;
|
use nu_source::Tagged;
|
||||||
|
|
||||||
pub struct Char;
|
pub struct Char;
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
|
||||||
struct CharArgs {
|
|
||||||
name: Tagged<String>,
|
|
||||||
rest: Vec<Tagged<String>>,
|
|
||||||
unicode: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl WholeStreamCommand for Char {
|
impl WholeStreamCommand for Char {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"char"
|
"char"
|
||||||
@ -65,14 +58,11 @@ impl WholeStreamCommand for Char {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
|
fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
let (
|
let args = args.evaluate_once()?;
|
||||||
CharArgs {
|
|
||||||
name,
|
let name: Tagged<String> = args.req(0)?;
|
||||||
rest,
|
let rest: Vec<Value> = args.rest(1)?;
|
||||||
unicode,
|
let unicode = args.has_flag("unicode");
|
||||||
},
|
|
||||||
_,
|
|
||||||
) = args.process()?;
|
|
||||||
|
|
||||||
if unicode {
|
if unicode {
|
||||||
if !rest.is_empty() {
|
if !rest.is_empty() {
|
||||||
@ -86,6 +76,7 @@ impl WholeStreamCommand for Char {
|
|||||||
}
|
}
|
||||||
// Get the rest of the bytes
|
// Get the rest of the bytes
|
||||||
for byte_part in rest {
|
for byte_part in rest {
|
||||||
|
let byte_part: Tagged<String> = FromValue::from_value(&byte_part)?;
|
||||||
let decoded_char = string_to_unicode_char(&byte_part, &byte_part.tag);
|
let decoded_char = string_to_unicode_char(&byte_part, &byte_part.tag);
|
||||||
match decoded_char {
|
match decoded_char {
|
||||||
Ok(ch) => multi_byte.push(ch),
|
Ok(ch) => multi_byte.push(ch),
|
||||||
|
@ -6,16 +6,9 @@ use nu_errors::ShellError;
|
|||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
hir::CapturedBlock, Signature, SyntaxShape, TaggedDictBuilder, UntaggedValue, Value,
|
hir::CapturedBlock, Signature, SyntaxShape, TaggedDictBuilder, UntaggedValue, Value,
|
||||||
};
|
};
|
||||||
use nu_source::Tagged;
|
|
||||||
|
|
||||||
pub struct Each;
|
pub struct Each;
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
|
||||||
pub struct EachArgs {
|
|
||||||
block: CapturedBlock,
|
|
||||||
numbered: Tagged<bool>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl WholeStreamCommand for Each {
|
impl WholeStreamCommand for Each {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"each"
|
"each"
|
||||||
@ -110,12 +103,16 @@ pub(crate) fn make_indexed_item(index: usize, item: Value) -> Value {
|
|||||||
|
|
||||||
fn each(raw_args: CommandArgs) -> Result<OutputStream, ShellError> {
|
fn each(raw_args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
let context = Arc::new(EvaluationContext::from_args(&raw_args));
|
let context = Arc::new(EvaluationContext::from_args(&raw_args));
|
||||||
|
let args = raw_args.evaluate_once()?;
|
||||||
|
|
||||||
let (each_args, input): (EachArgs, _) = raw_args.process()?;
|
let block: CapturedBlock = args.req(0)?;
|
||||||
let block = Arc::new(Box::new(each_args.block));
|
let numbered: bool = args.has_flag("numbered");
|
||||||
|
|
||||||
if each_args.numbered.item {
|
let block = Arc::new(Box::new(block));
|
||||||
Ok(input
|
|
||||||
|
if numbered {
|
||||||
|
Ok(args
|
||||||
|
.input
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(move |input| {
|
.map(move |input| {
|
||||||
let block = block.clone();
|
let block = block.clone();
|
||||||
@ -130,7 +127,8 @@ fn each(raw_args: CommandArgs) -> Result<OutputStream, ShellError> {
|
|||||||
.flatten()
|
.flatten()
|
||||||
.to_output_stream())
|
.to_output_stream())
|
||||||
} else {
|
} else {
|
||||||
Ok(input
|
Ok(args
|
||||||
|
.input
|
||||||
.map(move |input| {
|
.map(move |input| {
|
||||||
let block = block.clone();
|
let block = block.clone();
|
||||||
let context = context.clone();
|
let context = context.clone();
|
||||||
|
@ -8,11 +8,6 @@ use nu_protocol::{
|
|||||||
|
|
||||||
pub struct Echo;
|
pub struct Echo;
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
|
||||||
pub struct EchoArgs {
|
|
||||||
pub rest: Vec<Value>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl WholeStreamCommand for Echo {
|
impl WholeStreamCommand for Echo {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"echo"
|
"echo"
|
||||||
@ -47,9 +42,10 @@ impl WholeStreamCommand for Echo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn echo(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
fn echo(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
let (args, _): (EchoArgs, _) = args.process()?;
|
let args = args.evaluate_once()?;
|
||||||
|
let rest: Vec<Value> = args.rest(0)?;
|
||||||
|
|
||||||
let stream = args.rest.into_iter().map(|i| match i.as_string() {
|
let stream = rest.into_iter().map(|i| match i.as_string() {
|
||||||
Ok(s) => OutputStream::one(Ok(ReturnSuccess::Value(
|
Ok(s) => OutputStream::one(Ok(ReturnSuccess::Value(
|
||||||
UntaggedValue::string(s).into_value(i.tag.clone()),
|
UntaggedValue::string(s).into_value(i.tag.clone()),
|
||||||
))),
|
))),
|
||||||
|
@ -9,13 +9,6 @@ use nu_protocol::{
|
|||||||
|
|
||||||
pub struct If;
|
pub struct If;
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
|
||||||
pub struct IfArgs {
|
|
||||||
condition: CapturedBlock,
|
|
||||||
then_case: CapturedBlock,
|
|
||||||
else_case: CapturedBlock,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl WholeStreamCommand for If {
|
impl WholeStreamCommand for If {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"if"
|
"if"
|
||||||
@ -67,14 +60,12 @@ fn if_command(raw_args: CommandArgs) -> Result<OutputStream, ShellError> {
|
|||||||
let tag = raw_args.call_info.name_tag.clone();
|
let tag = raw_args.call_info.name_tag.clone();
|
||||||
let context = Arc::new(EvaluationContext::from_args(&raw_args));
|
let context = Arc::new(EvaluationContext::from_args(&raw_args));
|
||||||
|
|
||||||
let (
|
let args = raw_args.evaluate_once()?;
|
||||||
IfArgs {
|
let condition: CapturedBlock = args.req(0)?;
|
||||||
condition,
|
let then_case: CapturedBlock = args.req(1)?;
|
||||||
then_case,
|
let else_case: CapturedBlock = args.req(2)?;
|
||||||
else_case,
|
let input = args.input;
|
||||||
},
|
|
||||||
input,
|
|
||||||
) = raw_args.process()?;
|
|
||||||
let cond = {
|
let cond = {
|
||||||
if condition.block.block.len() != 1 {
|
if condition.block.block.len() != 1 {
|
||||||
return Err(ShellError::labeled_error(
|
return Err(ShellError::labeled_error(
|
||||||
|
@ -7,13 +7,6 @@ use nu_source::Tagged;
|
|||||||
|
|
||||||
pub struct Let;
|
pub struct Let;
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
|
||||||
pub struct LetArgs {
|
|
||||||
pub name: Tagged<String>,
|
|
||||||
pub equals: Tagged<String>,
|
|
||||||
pub rhs: CapturedBlock,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl WholeStreamCommand for Let {
|
impl WholeStreamCommand for Let {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"let"
|
"let"
|
||||||
@ -46,8 +39,11 @@ impl WholeStreamCommand for Let {
|
|||||||
pub fn letcmd(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
pub fn letcmd(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
let tag = args.call_info.name_tag.clone();
|
let tag = args.call_info.name_tag.clone();
|
||||||
let ctx = EvaluationContext::from_args(&args);
|
let ctx = EvaluationContext::from_args(&args);
|
||||||
|
let args = args.evaluate_once()?;
|
||||||
|
|
||||||
let (LetArgs { name, rhs, .. }, _) = args.process()?;
|
//let (LetArgs { name, rhs, .. }, _) = args.process()?;
|
||||||
|
let name: Tagged<String> = args.req(0)?;
|
||||||
|
let rhs: CapturedBlock = args.req(2)?;
|
||||||
|
|
||||||
let (expr, captured) = {
|
let (expr, captured) = {
|
||||||
if rhs.block.block.len() != 1 {
|
if rhs.block.block.len() != 1 {
|
||||||
|
@ -111,99 +111,6 @@ impl Iterator for SleepIterator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// struct SleepHandler {
|
|
||||||
// shared_state: Arc<Mutex<SharedState>>,
|
|
||||||
// }
|
|
||||||
|
|
||||||
// impl SleepHandler {
|
|
||||||
// /// Create a new `SleepHandler` which will complete after the provided
|
|
||||||
// /// timeout and check for Ctrl+C periodically.
|
|
||||||
// pub fn new(duration: Duration, ctrl_c: Arc<AtomicBool>) -> Self {
|
|
||||||
// let shared_state = Arc::new(Mutex::new(SharedState {
|
|
||||||
// done: false,
|
|
||||||
// waker: None,
|
|
||||||
// }));
|
|
||||||
|
|
||||||
// // Spawn the main sleep thread
|
|
||||||
// let thread_shared_state = shared_state.clone();
|
|
||||||
// thread::spawn(move || {
|
|
||||||
// thread::sleep(duration);
|
|
||||||
// let mut shared_state = thread_shared_state.lock();
|
|
||||||
// // Signal that the timer has completed and wake up the last
|
|
||||||
// // task on which the future was polled, if one exists.
|
|
||||||
// if !shared_state.done {
|
|
||||||
// shared_state.done = true;
|
|
||||||
// if let Some(waker) = shared_state.waker.take() {
|
|
||||||
// waker.wake()
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
|
|
||||||
// // Spawn the Ctrl+C-watching polling thread
|
|
||||||
// let thread_shared_state = shared_state.clone();
|
|
||||||
// thread::spawn(move || {
|
|
||||||
// loop {
|
|
||||||
// {
|
|
||||||
// let mut shared_state = thread_shared_state.lock();
|
|
||||||
// // exit if the main thread is done
|
|
||||||
// if shared_state.done {
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// // finish the future prematurely if Ctrl+C has been pressed
|
|
||||||
// if ctrl_c.load(Ordering::SeqCst) {
|
|
||||||
// shared_state.done = true;
|
|
||||||
// if let Some(waker) = shared_state.waker.take() {
|
|
||||||
// waker.wake()
|
|
||||||
// }
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// // sleep for a short time
|
|
||||||
// thread::sleep(CTRL_C_CHECK_INTERVAL);
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
|
|
||||||
// SleepHandler { shared_state }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// struct SharedState {
|
|
||||||
// done: bool,
|
|
||||||
// }
|
|
||||||
|
|
||||||
// impl Iterator for SleepHandler {
|
|
||||||
// type Item = ();
|
|
||||||
|
|
||||||
// fn next(&mut self) -> Option<Self::Item> {
|
|
||||||
// let mut shared_state = self.shared_state.lock();
|
|
||||||
// loop {
|
|
||||||
// if shared_state.done {
|
|
||||||
// return None;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// impl Future for SleepHandler {
|
|
||||||
// type Output = ();
|
|
||||||
|
|
||||||
// fn poll(self: Pin<&mut Self>, cx: &mut std::task::Context<'_>) -> Poll<Self::Output> {
|
|
||||||
// // Look at the shared state to see if the timer has already completed.
|
|
||||||
// Poll::Ready(())
|
|
||||||
// } else {
|
|
||||||
// // Set the waker if necessary
|
|
||||||
// if shared_state
|
|
||||||
// .waker
|
|
||||||
// .as_ref()
|
|
||||||
// .map(|waker| !waker.will_wake(&cx.waker()))
|
|
||||||
// .unwrap_or(true)
|
|
||||||
// {
|
|
||||||
// shared_state.waker = Some(cx.waker().clone());
|
|
||||||
// }
|
|
||||||
// Poll::Pending
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::Sleep;
|
use super::Sleep;
|
||||||
|
@ -6,11 +6,6 @@ use nu_source::Tagged;
|
|||||||
|
|
||||||
pub struct SubCommand;
|
pub struct SubCommand;
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
|
||||||
pub struct SubCommandArgs {
|
|
||||||
separator: Option<Tagged<String>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl WholeStreamCommand for SubCommand {
|
impl WholeStreamCommand for SubCommand {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"str collect"
|
"str collect"
|
||||||
@ -43,8 +38,15 @@ impl WholeStreamCommand for SubCommand {
|
|||||||
|
|
||||||
pub fn collect(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
pub fn collect(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
let tag = args.call_info.name_tag.clone();
|
let tag = args.call_info.name_tag.clone();
|
||||||
let (SubCommandArgs { separator }, input) = args.process()?;
|
//let (SubCommandArgs { separator }, input) = args.process()?;
|
||||||
let separator = separator.map(|tagged| tagged.item).unwrap_or_default();
|
let args = args.evaluate_once()?;
|
||||||
|
let separator: Option<Result<Tagged<String>, ShellError>> = args.opt(0);
|
||||||
|
let input = args.input;
|
||||||
|
let separator = if let Some(separator) = separator {
|
||||||
|
separator?.item
|
||||||
|
} else {
|
||||||
|
"".into()
|
||||||
|
};
|
||||||
|
|
||||||
let strings: Vec<Result<String, ShellError>> = input.map(|value| value.as_string()).collect();
|
let strings: Vec<Result<String, ShellError>> = input.map(|value| value.as_string()).collect();
|
||||||
let strings: Result<Vec<_>, _> = strings.into_iter().collect::<Result<_, _>>();
|
let strings: Result<Vec<_>, _> = strings.into_iter().collect::<Result<_, _>>();
|
||||||
|
@ -4,7 +4,7 @@ use crate::primitive::get_color_config;
|
|||||||
use nu_data::value::{format_leaf, style_leaf};
|
use nu_data::value::{format_leaf, style_leaf};
|
||||||
use nu_engine::WholeStreamCommand;
|
use nu_engine::WholeStreamCommand;
|
||||||
use nu_errors::ShellError;
|
use nu_errors::ShellError;
|
||||||
use nu_protocol::{Primitive, Signature, SyntaxShape, UntaggedValue, Value};
|
use nu_protocol::{Signature, SyntaxShape, UntaggedValue, Value};
|
||||||
use nu_table::{draw_table, Alignment, StyledString, TextStyle};
|
use nu_table::{draw_table, Alignment, StyledString, TextStyle};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::sync::atomic::Ordering;
|
use std::sync::atomic::Ordering;
|
||||||
@ -169,22 +169,10 @@ fn table(configuration: TableConfiguration, args: CommandArgs) -> Result<OutputS
|
|||||||
// config.toml.... yet.
|
// config.toml.... yet.
|
||||||
let color_hm = get_color_config();
|
let color_hm = get_color_config();
|
||||||
|
|
||||||
let mut start_number = match args.get("start_number") {
|
let mut start_number = if let Some(f) = args.get_flag("start_number") {
|
||||||
Some(Value {
|
f?
|
||||||
value: UntaggedValue::Primitive(Primitive::Int(i)),
|
} else {
|
||||||
..
|
0
|
||||||
}) => {
|
|
||||||
if let Some(num) = i.to_usize() {
|
|
||||||
num
|
|
||||||
} else {
|
|
||||||
return Err(ShellError::labeled_error(
|
|
||||||
"Expected a row number",
|
|
||||||
"expected a row number",
|
|
||||||
&args.args.call_info.name_tag,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => 0,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut delay_slot = None;
|
let mut delay_slot = None;
|
||||||
|
@ -55,7 +55,7 @@ impl WholeStreamCommand for Uniq {
|
|||||||
|
|
||||||
fn uniq(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
fn uniq(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
let args = args.evaluate_once()?;
|
let args = args.evaluate_once()?;
|
||||||
let should_show_count = args.has("count");
|
let should_show_count = args.has_flag("count");
|
||||||
let input = args.input;
|
let input = args.input;
|
||||||
let uniq_values = {
|
let uniq_values = {
|
||||||
let mut counter = IndexMap::<nu_protocol::Value, usize>::new();
|
let mut counter = IndexMap::<nu_protocol::Value, usize>::new();
|
||||||
|
@ -24,7 +24,9 @@ dyn-clone = "1.0.4"
|
|||||||
ansi_term = "0.12.1"
|
ansi_term = "0.12.1"
|
||||||
async-recursion = "0.3.2"
|
async-recursion = "0.3.2"
|
||||||
async-trait = "0.1.42"
|
async-trait = "0.1.42"
|
||||||
|
bigdecimal = "0.2.0"
|
||||||
bytes = "0.5.6"
|
bytes = "0.5.6"
|
||||||
|
chrono = { version = "0.4.19", features = ["serde"] }
|
||||||
derive-new = "0.5.8"
|
derive-new = "0.5.8"
|
||||||
dirs-next = { version = "2.0.0", optional = true }
|
dirs-next = { version = "2.0.0", optional = true }
|
||||||
dunce = "1.0.1"
|
dunce = "1.0.1"
|
||||||
@ -39,6 +41,9 @@ glob = "0.3.0"
|
|||||||
indexmap = { version = "1.6.1", features = ["serde-1"] }
|
indexmap = { version = "1.6.1", features = ["serde-1"] }
|
||||||
itertools = "0.10.0"
|
itertools = "0.10.0"
|
||||||
log = "0.4.14"
|
log = "0.4.14"
|
||||||
|
num-bigint = { version = "0.3.1", features = ["serde"] }
|
||||||
|
num-format = "0.4.0"
|
||||||
|
num-traits = "0.2.14"
|
||||||
parking_lot = "0.11.1"
|
parking_lot = "0.11.1"
|
||||||
rayon = "1.5.0"
|
rayon = "1.5.0"
|
||||||
serde = { version = "1.0.123", features = ["derive"] }
|
serde = { version = "1.0.123", features = ["derive"] }
|
||||||
|
@ -3,6 +3,7 @@ use crate::env::host::Host;
|
|||||||
use crate::evaluate::scope::Scope;
|
use crate::evaluate::scope::Scope;
|
||||||
use crate::evaluation_context::EvaluationContext;
|
use crate::evaluation_context::EvaluationContext;
|
||||||
use crate::shell::shell_manager::ShellManager;
|
use crate::shell::shell_manager::ShellManager;
|
||||||
|
use crate::FromValue;
|
||||||
use crate::{call_info::UnevaluatedCallInfo, config_holder::ConfigHolder};
|
use crate::{call_info::UnevaluatedCallInfo, config_holder::ConfigHolder};
|
||||||
use derive_new::new;
|
use derive_new::new;
|
||||||
use getset::Getters;
|
use getset::Getters;
|
||||||
@ -171,11 +172,44 @@ impl EvaluatedCommandArgs {
|
|||||||
.ok_or_else(|| ShellError::unimplemented("Better error: expect_nth"))
|
.ok_or_else(|| ShellError::unimplemented("Better error: expect_nth"))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get(&self, name: &str) -> Option<&Value> {
|
pub fn get_flag<T: FromValue>(&self, name: &str) -> Option<Result<T, ShellError>> {
|
||||||
self.call_info.args.get(name)
|
self.call_info
|
||||||
|
.args
|
||||||
|
.get(name)
|
||||||
|
.map(|x| FromValue::from_value(x))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn has(&self, name: &str) -> bool {
|
pub fn has_flag(&self, name: &str) -> bool {
|
||||||
self.call_info.args.has(name)
|
self.call_info.args.has(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn req<T: FromValue>(&self, pos: usize) -> Result<T, ShellError> {
|
||||||
|
if let Some(v) = self.nth(pos) {
|
||||||
|
FromValue::from_value(v)
|
||||||
|
} else {
|
||||||
|
Err(ShellError::labeled_error(
|
||||||
|
"Position beyond end of command arguments",
|
||||||
|
"can't access beyond end of command arguments",
|
||||||
|
self.call_info.name_tag.span,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn opt<T: FromValue>(&self, pos: usize) -> Option<Result<T, ShellError>> {
|
||||||
|
if let Some(v) = self.nth(pos) {
|
||||||
|
Some(FromValue::from_value(v))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn rest<T: FromValue>(&self, starting_pos: usize) -> Result<Vec<T>, ShellError> {
|
||||||
|
let mut output = vec![];
|
||||||
|
|
||||||
|
for val in self.call_info.args.positional_iter().skip(starting_pos) {
|
||||||
|
output.push(FromValue::from_value(val)?);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(output)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
281
crates/nu-engine/src/from_value.rs
Normal file
281
crates/nu-engine/src/from_value.rs
Normal file
@ -0,0 +1,281 @@
|
|||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
use chrono::{DateTime, FixedOffset};
|
||||||
|
use nu_errors::ShellError;
|
||||||
|
use nu_protocol::{
|
||||||
|
hir::CapturedBlock, ColumnPath, Dictionary, Primitive, Range, UntaggedValue, Value,
|
||||||
|
};
|
||||||
|
use nu_source::{Tagged, TaggedItem};
|
||||||
|
|
||||||
|
pub trait FromValue: Sized {
|
||||||
|
fn from_value(v: &Value) -> Result<Self, ShellError>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromValue for Value {
|
||||||
|
fn from_value(v: &Value) -> Result<Self, ShellError> {
|
||||||
|
Ok(v.clone())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromValue for num_bigint::BigInt {
|
||||||
|
fn from_value(v: &Value) -> Result<Self, ShellError> {
|
||||||
|
match v {
|
||||||
|
Value {
|
||||||
|
value: UntaggedValue::Primitive(Primitive::Int(i)),
|
||||||
|
..
|
||||||
|
}
|
||||||
|
| Value {
|
||||||
|
value: UntaggedValue::Primitive(Primitive::Filesize(i)),
|
||||||
|
..
|
||||||
|
}
|
||||||
|
| Value {
|
||||||
|
value: UntaggedValue::Primitive(Primitive::Duration(i)),
|
||||||
|
..
|
||||||
|
} => Ok(i.clone()),
|
||||||
|
Value { tag, .. } => Err(ShellError::labeled_error(
|
||||||
|
"Can't convert to integer",
|
||||||
|
"can't convert to integer",
|
||||||
|
tag.span,
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromValue for u64 {
|
||||||
|
fn from_value(v: &Value) -> Result<Self, ShellError> {
|
||||||
|
v.as_u64()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromValue for usize {
|
||||||
|
fn from_value(v: &Value) -> Result<Self, ShellError> {
|
||||||
|
v.as_usize()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromValue for i64 {
|
||||||
|
fn from_value(v: &Value) -> Result<Self, ShellError> {
|
||||||
|
v.as_i64()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromValue for i32 {
|
||||||
|
fn from_value(v: &Value) -> Result<Self, ShellError> {
|
||||||
|
v.as_i32()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromValue for bigdecimal::BigDecimal {
|
||||||
|
fn from_value(v: &Value) -> Result<Self, ShellError> {
|
||||||
|
match v {
|
||||||
|
Value {
|
||||||
|
value: UntaggedValue::Primitive(Primitive::Decimal(d)),
|
||||||
|
..
|
||||||
|
} => Ok(d.clone()),
|
||||||
|
Value { tag, .. } => Err(ShellError::labeled_error(
|
||||||
|
"Can't convert to decimal",
|
||||||
|
"can't convert to decimal",
|
||||||
|
tag.span,
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromValue for String {
|
||||||
|
fn from_value(v: &Value) -> Result<Self, ShellError> {
|
||||||
|
match v {
|
||||||
|
Value {
|
||||||
|
value: UntaggedValue::Primitive(Primitive::String(s)),
|
||||||
|
..
|
||||||
|
} => Ok(s.clone()),
|
||||||
|
Value {
|
||||||
|
value: UntaggedValue::Primitive(Primitive::GlobPattern(s)),
|
||||||
|
..
|
||||||
|
} => Ok(s.clone()),
|
||||||
|
Value {
|
||||||
|
value: UntaggedValue::Primitive(Primitive::FilePath(p)),
|
||||||
|
..
|
||||||
|
} => Ok(p.to_string_lossy().to_string()),
|
||||||
|
Value { tag, .. } => Err(ShellError::labeled_error(
|
||||||
|
"Can't convert to string",
|
||||||
|
"can't convert to string",
|
||||||
|
tag.span,
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromValue for Tagged<String> {
|
||||||
|
fn from_value(v: &Value) -> Result<Self, ShellError> {
|
||||||
|
let tag = v.tag.clone();
|
||||||
|
v.as_string().map(|s| s.tagged(tag))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromValue for PathBuf {
|
||||||
|
fn from_value(v: &Value) -> Result<Self, ShellError> {
|
||||||
|
match v {
|
||||||
|
Value {
|
||||||
|
value: UntaggedValue::Primitive(Primitive::String(s)),
|
||||||
|
..
|
||||||
|
} => Ok(PathBuf::from(s)),
|
||||||
|
Value {
|
||||||
|
value: UntaggedValue::Primitive(Primitive::FilePath(p)),
|
||||||
|
..
|
||||||
|
} => Ok(p.clone()),
|
||||||
|
Value { tag, .. } => Err(ShellError::labeled_error(
|
||||||
|
"Can't convert to filepath",
|
||||||
|
"can't convert to filepath",
|
||||||
|
tag.span,
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromValue for ColumnPath {
|
||||||
|
fn from_value(v: &Value) -> Result<Self, ShellError> {
|
||||||
|
match v {
|
||||||
|
Value {
|
||||||
|
value: UntaggedValue::Primitive(Primitive::ColumnPath(c)),
|
||||||
|
..
|
||||||
|
} => Ok(c.clone()),
|
||||||
|
Value { tag, .. } => Err(ShellError::labeled_error(
|
||||||
|
"Can't convert to column path",
|
||||||
|
"can't convert to column path",
|
||||||
|
tag.span,
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromValue for bool {
|
||||||
|
fn from_value(v: &Value) -> Result<Self, ShellError> {
|
||||||
|
match v {
|
||||||
|
Value {
|
||||||
|
value: UntaggedValue::Primitive(Primitive::Boolean(b)),
|
||||||
|
..
|
||||||
|
} => Ok(*b),
|
||||||
|
Value { tag, .. } => Err(ShellError::labeled_error(
|
||||||
|
"Can't convert to boolean",
|
||||||
|
"can't convert to boolean",
|
||||||
|
tag.span,
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromValue for Tagged<bool> {
|
||||||
|
fn from_value(v: &Value) -> Result<Self, ShellError> {
|
||||||
|
match v {
|
||||||
|
Value {
|
||||||
|
value: UntaggedValue::Primitive(Primitive::Boolean(b)),
|
||||||
|
tag,
|
||||||
|
} => Ok((*b).tagged(tag)),
|
||||||
|
Value { tag, .. } => Err(ShellError::labeled_error(
|
||||||
|
"Can't convert to boolean",
|
||||||
|
"can't convert to boolean",
|
||||||
|
tag.span,
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromValue for DateTime<FixedOffset> {
|
||||||
|
fn from_value(v: &Value) -> Result<Self, ShellError> {
|
||||||
|
match v {
|
||||||
|
Value {
|
||||||
|
value: UntaggedValue::Primitive(Primitive::Date(d)),
|
||||||
|
..
|
||||||
|
} => Ok(*d),
|
||||||
|
Value { tag, .. } => Err(ShellError::labeled_error(
|
||||||
|
"Can't convert to date",
|
||||||
|
"can't convert to date",
|
||||||
|
tag.span,
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromValue for Range {
|
||||||
|
fn from_value(v: &Value) -> Result<Self, ShellError> {
|
||||||
|
match v {
|
||||||
|
Value {
|
||||||
|
value: UntaggedValue::Primitive(Primitive::Range(r)),
|
||||||
|
..
|
||||||
|
} => Ok((**r).clone()),
|
||||||
|
Value { tag, .. } => Err(ShellError::labeled_error(
|
||||||
|
"Can't convert to range",
|
||||||
|
"can't convert to range",
|
||||||
|
tag.span,
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromValue for Vec<u8> {
|
||||||
|
fn from_value(v: &Value) -> Result<Self, ShellError> {
|
||||||
|
match v {
|
||||||
|
Value {
|
||||||
|
value: UntaggedValue::Primitive(Primitive::Binary(b)),
|
||||||
|
..
|
||||||
|
} => Ok(b.clone()),
|
||||||
|
Value {
|
||||||
|
value: UntaggedValue::Primitive(Primitive::String(s)),
|
||||||
|
..
|
||||||
|
} => Ok(s.bytes().collect()),
|
||||||
|
Value { tag, .. } => Err(ShellError::labeled_error(
|
||||||
|
"Can't convert to binary data",
|
||||||
|
"can't convert to binary data",
|
||||||
|
tag.span,
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromValue for Dictionary {
|
||||||
|
fn from_value(v: &Value) -> Result<Self, ShellError> {
|
||||||
|
match v {
|
||||||
|
Value {
|
||||||
|
value: UntaggedValue::Row(r),
|
||||||
|
..
|
||||||
|
} => Ok(r.clone()),
|
||||||
|
Value { tag, .. } => Err(ShellError::labeled_error(
|
||||||
|
"Can't convert to row",
|
||||||
|
"can't convert to row",
|
||||||
|
tag.span,
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromValue for CapturedBlock {
|
||||||
|
fn from_value(v: &Value) -> Result<Self, ShellError> {
|
||||||
|
match v {
|
||||||
|
Value {
|
||||||
|
value: UntaggedValue::Block(b),
|
||||||
|
..
|
||||||
|
} => Ok((**b).clone()),
|
||||||
|
Value { tag, .. } => Err(ShellError::labeled_error(
|
||||||
|
"Can't convert to block",
|
||||||
|
"can't convert to block",
|
||||||
|
tag.span,
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromValue for Vec<Value> {
|
||||||
|
fn from_value(v: &Value) -> Result<Self, ShellError> {
|
||||||
|
match v {
|
||||||
|
Value {
|
||||||
|
value: UntaggedValue::Table(t),
|
||||||
|
..
|
||||||
|
} => Ok(t.clone()),
|
||||||
|
Value { tag, .. } => Err(ShellError::labeled_error(
|
||||||
|
"Can't convert to table",
|
||||||
|
"can't convert to table",
|
||||||
|
tag.span,
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -10,6 +10,7 @@ mod evaluate;
|
|||||||
mod evaluation_context;
|
mod evaluation_context;
|
||||||
mod example;
|
mod example;
|
||||||
pub mod filesystem;
|
pub mod filesystem;
|
||||||
|
mod from_value;
|
||||||
mod maybe_text_codec;
|
mod maybe_text_codec;
|
||||||
pub mod plugin;
|
pub mod plugin;
|
||||||
mod print;
|
mod print;
|
||||||
@ -36,6 +37,7 @@ pub use crate::example::Example;
|
|||||||
pub use crate::filesystem::dir_info::{DirBuilder, DirInfo, FileInfo};
|
pub use crate::filesystem::dir_info::{DirBuilder, DirInfo, FileInfo};
|
||||||
pub use crate::filesystem::filesystem_shell::FilesystemShell;
|
pub use crate::filesystem::filesystem_shell::FilesystemShell;
|
||||||
pub use crate::filesystem::path;
|
pub use crate::filesystem::path;
|
||||||
|
pub use crate::from_value::FromValue;
|
||||||
pub use crate::maybe_text_codec::{BufCodecReader, MaybeTextCodec, StringOrBinary};
|
pub use crate::maybe_text_codec::{BufCodecReader, MaybeTextCodec, StringOrBinary};
|
||||||
pub use crate::print::maybe_print_errors;
|
pub use crate::print::maybe_print_errors;
|
||||||
pub use crate::runnable_context::RunnableContext;
|
pub use crate::runnable_context::RunnableContext;
|
||||||
|
@ -71,19 +71,6 @@ impl Default for MaybeTextCodec {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// impl MaybeTextCodec {
|
|
||||||
// fn encode(&mut self, item: StringOrBinary, mut dst: &mut [u8]) {
|
|
||||||
// match item {
|
|
||||||
// StringOrBinary::String(s) => {
|
|
||||||
// dst.put(s.as_bytes());
|
|
||||||
// }
|
|
||||||
// StringOrBinary::Binary(b) => {
|
|
||||||
// dst.put(Bytes::from(b));
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
impl MaybeTextCodec {
|
impl MaybeTextCodec {
|
||||||
pub fn decode(&mut self, src: &[u8]) -> Result<Option<StringOrBinary>, ShellError> {
|
pub fn decode(&mut self, src: &[u8]) -> Result<Option<StringOrBinary>, ShellError> {
|
||||||
if src.is_empty() {
|
if src.is_empty() {
|
||||||
|
@ -429,6 +429,14 @@ impl Value {
|
|||||||
matches!(&self.value, UntaggedValue::Primitive(_))
|
matches!(&self.value, UntaggedValue::Primitive(_))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// View the Value as unsigned size, if possible
|
||||||
|
pub fn as_usize(&self) -> Result<usize, ShellError> {
|
||||||
|
match &self.value {
|
||||||
|
UntaggedValue::Primitive(primitive) => primitive.as_usize(self.tag.span),
|
||||||
|
_ => Err(ShellError::type_error("integer", self.spanned_type_name())),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// View the Value as unsigned 64-bit, if possible
|
/// View the Value as unsigned 64-bit, if possible
|
||||||
pub fn as_u64(&self) -> Result<u64, ShellError> {
|
pub fn as_u64(&self) -> Result<u64, ShellError> {
|
||||||
match &self.value {
|
match &self.value {
|
||||||
|
@ -60,6 +60,30 @@ pub enum Primitive {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Primitive {
|
impl Primitive {
|
||||||
|
/// Converts a primitive value to a u64, if possible. Uses a span to build an error if the conversion isn't possible.
|
||||||
|
pub fn as_usize(&self, span: Span) -> Result<usize, ShellError> {
|
||||||
|
match self {
|
||||||
|
Primitive::Int(int) => int.to_usize().ok_or_else(|| {
|
||||||
|
ShellError::range_error(
|
||||||
|
ExpectedRange::U64,
|
||||||
|
&format!("{}", int).spanned(span),
|
||||||
|
"converting an integer into an unsigned 64-bit integer",
|
||||||
|
)
|
||||||
|
}),
|
||||||
|
Primitive::Decimal(decimal) => decimal.to_usize().ok_or_else(|| {
|
||||||
|
ShellError::range_error(
|
||||||
|
ExpectedRange::U64,
|
||||||
|
&format!("{}", decimal).spanned(span),
|
||||||
|
"converting a decimal into an unsigned 64-bit integer",
|
||||||
|
)
|
||||||
|
}),
|
||||||
|
other => Err(ShellError::type_error(
|
||||||
|
"number",
|
||||||
|
other.type_name().spanned(span),
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Converts a primitive value to a u64, if possible. Uses a span to build an error if the conversion isn't possible.
|
/// Converts a primitive value to a u64, if possible. Uses a span to build an error if the conversion isn't possible.
|
||||||
pub fn as_u64(&self, span: Span) -> Result<u64, ShellError> {
|
pub fn as_u64(&self, span: Span) -> Result<u64, ShellError> {
|
||||||
match self {
|
match self {
|
||||||
|
Loading…
Reference in New Issue
Block a user