Last unwraps (#1160)

* Work through most of the last unwraps

* Finish removing unwraps
This commit is contained in:
Jonathan Turner 2020-01-04 19:44:17 +13:00 committed by GitHub
parent 6dceabf389
commit 77d856fd53
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 188 additions and 86 deletions

View File

@ -45,13 +45,13 @@ steps:
- bash: RUSTFLAGS="-D warnings" cargo test --all --features=stable
condition: eq(variables['style'], 'unflagged')
displayName: Run tests
- bash: RUSTFLAGS="-D warnings" cargo clippy --all --features=stable
- bash: RUSTFLAGS="-D warnings" cargo clippy --all --features=stable -- -D clippy::result_unwrap_used -D clippy::option_unwrap_used
condition: eq(variables['style'], 'unflagged')
displayName: Check clippy lints
- bash: NUSHELL_ENABLE_ALL_FLAGS=1 RUSTFLAGS="-D warnings" cargo test --all --features=stable
condition: eq(variables['style'], 'canary')
displayName: Run tests
- bash: NUSHELL_ENABLE_ALL_FLAGS=1 RUSTFLAGS="-D warnings" cargo clippy --all --features=stable
- bash: NUSHELL_ENABLE_ALL_FLAGS=1 RUSTFLAGS="-D warnings" cargo clippy --all --features=stable -- -D clippy::result_unwrap_used -D clippy::option_unwrap_used
condition: eq(variables['style'], 'canary')
displayName: Check clippy lints
- bash: cargo fmt --all -- --check

34
Cargo.lock generated
View File

@ -1817,6 +1817,15 @@ version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae91b68aebc4ddb91978b11a1b02ddd8602a05ec19002801c5666000e05e0f83"
[[package]]
name = "lock_api"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e57b3997725d2b60dbec1297f6c2e2957cc383db1cebd6be812163f969c7d586"
dependencies = [
"scopeguard",
]
[[package]]
name = "log"
version = "0.4.8"
@ -2170,6 +2179,7 @@ dependencies = [
"num-bigint",
"num-traits 0.2.10",
"onig_sys",
"parking_lot",
"pin-utils",
"pretty-hex",
"pretty_assertions",
@ -2720,6 +2730,30 @@ dependencies = [
"winapi 0.3.8",
]
[[package]]
name = "parking_lot"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "92e98c49ab0b7ce5b222f2cc9193fc4efe11c6d0bd4f648e374684a6857b1cfc"
dependencies = [
"lock_api",
"parking_lot_core",
]
[[package]]
name = "parking_lot_core"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7582838484df45743c8434fbff785e8edf260c28748353d44bc0da32e0ceabf1"
dependencies = [
"cfg-if",
"cloudabi",
"libc",
"redox_syscall",
"smallvec",
"winapi 0.3.8",
]
[[package]]
name = "path-slash"
version = "0.1.1"

View File

@ -123,6 +123,7 @@ umask = "0.1"
futures-util = "0.3.1"
termcolor = "1.0.5"
natural = "0.3.0"
parking_lot = "0.10.0"
clipboard = {version = "0.5", optional = true }
ptree = {version = "0.2" }

View File

@ -34,8 +34,20 @@ impl PrettyDebug for Unit {
fn convert_number_to_u64(number: &Number) -> u64 {
match number {
Number::Int(big_int) => big_int.to_u64().unwrap(),
Number::Decimal(big_decimal) => big_decimal.to_u64().unwrap(),
Number::Int(big_int) => {
if let Some(x) = big_int.to_u64() {
x
} else {
unreachable!("Internal error: convert_number_to_u64 given incompatible number")
}
}
Number::Decimal(big_decimal) => {
if let Some(x) = big_decimal.to_u64() {
x
} else {
unreachable!("Internal error: convert_number_to_u64 given incompatible number")
}
}
}
}

View File

@ -235,7 +235,7 @@ impl PrettyDebug for Type {
(b::kind("table") + b::space() + b::keyword("of")).group()
+ b::space()
+ (if group.len() == 1 {
let (doc, _) = group.into_iter().nth(0).unwrap();
let (doc, _) = group.into_iter().collect::<Vec<_>>()[0].clone();
DebugDocBuilder::from_doc(doc)
} else {
b::intersperse(

View File

@ -64,7 +64,11 @@ impl From<BigDecimal> for Primitive {
impl From<f64> for Primitive {
fn from(float: f64) -> Primitive {
Primitive::Decimal(BigDecimal::from_f64(float).unwrap())
if let Some(f) = BigDecimal::from_f64(float) {
Primitive::Decimal(f)
} else {
unreachable!("Internal error: protocol did not use f64-compatible decimal")
}
}
}

View File

@ -100,13 +100,7 @@ pub fn autoview(
let first = &input[0];
let mut host = context.host.clone();
let mut host = match host.lock() {
Err(err) => {
errln!("Unexpected error acquiring host lock: {:?}", err);
return;
}
Ok(val) => val
};
let mut host = host.lock();
crate::cli::print_err(first.value.expect_error(), &*host, &context.source);
return;

View File

@ -196,7 +196,13 @@ pub(crate) async fn run_external_command(
})?;
let file = futures::io::AllowStdIo::new(stdout);
let stream = Framed::new(file, LinesCodec {});
let stream = stream.map(move |line| line.unwrap().into_value(&name_tag));
let stream = stream.map(move |line| {
if let Ok(line) = line {
line.into_value(&name_tag)
} else {
panic!("Internal error: could not read lines of text from stdin")
}
});
Ok(ClassifiedInputStream::from_input_stream(
stream.boxed() as BoxStream<'static, Value>
))

View File

@ -124,7 +124,7 @@ pub(crate) async fn run_internal_command(
}
CommandAction::EnterShell(location) => {
context.shell_manager.insert_at_current(Box::new(
FilesystemShell::with_location(location, context.registry().clone()).unwrap(),
FilesystemShell::with_location(location, context.registry().clone()),
))?;
}
CommandAction::PreviousShell => {

View File

@ -63,7 +63,7 @@ impl CallInfoExt for CallInfo {
#[derive(Getters)]
#[get = "pub(crate)"]
pub struct CommandArgs {
pub host: Arc<Mutex<Box<dyn Host>>>,
pub host: Arc<parking_lot::Mutex<Box<dyn Host>>>,
pub ctrl_c: Arc<AtomicBool>,
pub shell_manager: ShellManager,
pub call_info: UnevaluatedCallInfo,
@ -73,7 +73,7 @@ pub struct CommandArgs {
#[derive(Getters, Clone)]
#[get = "pub(crate)"]
pub struct RawCommandArgs {
pub host: Arc<Mutex<Box<dyn Host>>>,
pub host: Arc<parking_lot::Mutex<Box<dyn Host>>>,
pub ctrl_c: Arc<AtomicBool>,
pub shell_manager: ShellManager,
pub call_info: UnevaluatedCallInfo,
@ -219,7 +219,7 @@ pub struct RunnablePerItemContext {
pub struct RunnableContext {
pub input: InputStream,
pub shell_manager: ShellManager,
pub host: Arc<Mutex<Box<dyn Host>>>,
pub host: Arc<parking_lot::Mutex<Box<dyn Host>>>,
pub source: Text,
pub ctrl_c: Arc<AtomicBool>,
pub commands: CommandRegistry,
@ -286,7 +286,7 @@ impl Deref for EvaluatedWholeStreamCommandArgs {
impl EvaluatedWholeStreamCommandArgs {
pub fn new(
host: Arc<Mutex<dyn Host>>,
host: Arc<parking_lot::Mutex<dyn Host>>,
ctrl_c: Arc<AtomicBool>,
shell_manager: ShellManager,
call_info: CallInfo,
@ -335,7 +335,7 @@ impl Deref for EvaluatedFilterCommandArgs {
impl EvaluatedFilterCommandArgs {
pub fn new(
host: Arc<Mutex<dyn Host>>,
host: Arc<parking_lot::Mutex<dyn Host>>,
ctrl_c: Arc<AtomicBool>,
shell_manager: ShellManager,
call_info: CallInfo,
@ -354,7 +354,7 @@ impl EvaluatedFilterCommandArgs {
#[derive(Getters, new)]
#[get = "pub(crate)"]
pub struct EvaluatedCommandArgs {
pub host: Arc<Mutex<dyn Host>>,
pub host: Arc<parking_lot::Mutex<dyn Host>>,
pub ctrl_c: Arc<AtomicBool>,
pub shell_manager: ShellManager,
pub call_info: CallInfo,
@ -555,7 +555,7 @@ impl WholeStreamCommand for FnFilterCommand {
input,
} = args;
let host: Arc<Mutex<dyn Host>> = host.clone();
let host: Arc<parking_lot::Mutex<dyn Host>> = host.clone();
let registry: CommandRegistry = registry.clone();
let func = self.func;

View File

@ -51,31 +51,49 @@ impl WholeStreamCommand for FromYML {
}
}
fn convert_yaml_value_to_nu_value(v: &serde_yaml::Value, tag: impl Into<Tag>) -> Value {
fn convert_yaml_value_to_nu_value(
v: &serde_yaml::Value,
tag: impl Into<Tag>,
) -> Result<Value, ShellError> {
let tag = tag.into();
match v {
Ok(match v {
serde_yaml::Value::Bool(b) => UntaggedValue::boolean(*b).into_value(tag),
serde_yaml::Value::Number(n) if n.is_i64() => {
UntaggedValue::int(n.as_i64().unwrap()).into_value(tag)
UntaggedValue::int(n.as_i64().ok_or_else(|| {
ShellError::labeled_error(
"Expected a compatible number",
"expected a compatible number",
&tag,
)
})?)
.into_value(tag)
}
serde_yaml::Value::Number(n) if n.is_f64() => {
UntaggedValue::decimal(n.as_f64().unwrap()).into_value(tag)
UntaggedValue::decimal(n.as_f64().ok_or_else(|| {
ShellError::labeled_error(
"Expected a compatible number",
"expected a compatible number",
&tag,
)
})?)
.into_value(tag)
}
serde_yaml::Value::String(s) => UntaggedValue::string(s).into_value(tag),
serde_yaml::Value::Sequence(a) => UntaggedValue::Table(
a.iter()
serde_yaml::Value::Sequence(a) => {
let result: Result<Vec<Value>, ShellError> = a
.iter()
.map(|x| convert_yaml_value_to_nu_value(x, &tag))
.collect(),
)
.into_value(tag),
.collect();
UntaggedValue::Table(result?).into_value(tag)
}
serde_yaml::Value::Mapping(t) => {
let mut collected = TaggedDictBuilder::new(&tag);
for (k, v) in t.iter() {
match k {
serde_yaml::Value::String(k) => {
collected.insert_value(k.clone(), convert_yaml_value_to_nu_value(v, &tag));
collected.insert_value(k.clone(), convert_yaml_value_to_nu_value(v, &tag)?);
}
_ => unimplemented!("Unknown key type"),
}
@ -85,12 +103,19 @@ fn convert_yaml_value_to_nu_value(v: &serde_yaml::Value, tag: impl Into<Tag>) ->
}
serde_yaml::Value::Null => UntaggedValue::Primitive(Primitive::Nothing).into_value(tag),
x => unimplemented!("Unsupported yaml case: {:?}", x),
}
})
}
pub fn from_yaml_string_to_value(s: String, tag: impl Into<Tag>) -> serde_yaml::Result<Value> {
let v: serde_yaml::Value = serde_yaml::from_str(&s)?;
Ok(convert_yaml_value_to_nu_value(&v, tag))
pub fn from_yaml_string_to_value(s: String, tag: impl Into<Tag>) -> Result<Value, ShellError> {
let tag = tag.into();
let v: serde_yaml::Value = serde_yaml::from_str(&s).map_err(|x| {
ShellError::labeled_error(
format!("Could not load yaml: {}", x),
"could not load yaml from text",
&tag,
)
})?;
Ok(convert_yaml_value_to_nu_value(&v, tag)?)
}
fn from_yaml(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {

View File

@ -53,7 +53,7 @@ fn table(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream,
let input: Vec<Value> = args.input.into_vec().await;
if input.len() > 0 {
let mut host = host.lock().unwrap();
let mut host = host.lock();
let view = TableView::from_list(&input, start_number);
if let Some(view) = view {

View File

@ -49,7 +49,15 @@ pub fn value_to_bson_value(v: &Value) -> Result<Bson, ShellError> {
UntaggedValue::Primitive(Primitive::Date(d)) => Bson::UtcDatetime(*d),
UntaggedValue::Primitive(Primitive::EndOfStream) => Bson::Null,
UntaggedValue::Primitive(Primitive::BeginningOfStream) => Bson::Null,
UntaggedValue::Primitive(Primitive::Decimal(d)) => Bson::FloatingPoint(d.to_f64().unwrap()),
UntaggedValue::Primitive(Primitive::Decimal(d)) => {
Bson::FloatingPoint(d.to_f64().ok_or_else(|| {
ShellError::labeled_error(
"Could not convert value to decimal",
"could not convert to decimal",
&v.tag,
)
})?)
}
UntaggedValue::Primitive(Primitive::Int(i)) => {
Bson::I64(i.tagged(&v.tag).coerce_into("converting to BSON")?)
}
@ -145,9 +153,9 @@ fn object_value_to_bson(o: &Dictionary) -> Result<Bson, ShellError> {
let bst = get_binary_subtype(tagged_binary_subtype_value);
let bin: Result<Vec<u8>, _> = tagged_bin_value.try_into();
match bst {
Err(_) => generic_object_value_to_bson(o),
Ok(v) => Ok(Bson::Binary(v, bin.unwrap())),
match (bin, bst) {
(Ok(bin), Ok(v)) => Ok(Bson::Binary(v, bin)),
_ => generic_object_value_to_bson(o),
}
}
_ => generic_object_value_to_bson(o),

View File

@ -98,8 +98,17 @@ pub fn value_to_json_value(v: &Value) -> Result<serde_json::Value, ShellError> {
UntaggedValue::Primitive(Primitive::Binary(b)) => serde_json::Value::Array(
b.iter()
.map(|x| {
serde_json::Value::Number(serde_json::Number::from_f64(*x as f64).unwrap())
serde_json::Number::from_f64(*x as f64).ok_or_else(|| {
ShellError::labeled_error(
"Can not convert number from floating point",
"can not convert to number",
&v.tag,
)
})
})
.collect::<Result<Vec<serde_json::Number>, ShellError>>()?
.into_iter()
.map(serde_json::Value::Number)
.collect(),
),
UntaggedValue::Row(o) => {

View File

@ -31,16 +31,34 @@ pub fn value_to_yaml_value(v: &Value) -> Result<serde_yaml::Value, ShellError> {
Ok(match &v.value {
UntaggedValue::Primitive(Primitive::Boolean(b)) => serde_yaml::Value::Bool(*b),
UntaggedValue::Primitive(Primitive::Bytes(b)) => {
serde_yaml::Value::Number(serde_yaml::Number::from(b.to_f64().unwrap()))
}
UntaggedValue::Primitive(Primitive::Duration(secs)) => {
serde_yaml::Value::Number(serde_yaml::Number::from(secs.to_f64().unwrap()))
serde_yaml::Value::Number(serde_yaml::Number::from(b.to_f64().ok_or_else(|| {
ShellError::labeled_error(
"Could not convert to bytes",
"could not convert to bytes",
&v.tag,
)
})?))
}
UntaggedValue::Primitive(Primitive::Duration(secs)) => serde_yaml::Value::Number(
serde_yaml::Number::from(secs.to_f64().ok_or_else(|| {
ShellError::labeled_error(
"Could not convert to duration",
"could not convert to duration",
&v.tag,
)
})?),
),
UntaggedValue::Primitive(Primitive::Date(d)) => serde_yaml::Value::String(d.to_string()),
UntaggedValue::Primitive(Primitive::EndOfStream) => serde_yaml::Value::Null,
UntaggedValue::Primitive(Primitive::BeginningOfStream) => serde_yaml::Value::Null,
UntaggedValue::Primitive(Primitive::Decimal(f)) => {
serde_yaml::Value::Number(serde_yaml::Number::from(f.to_f64().unwrap()))
serde_yaml::Value::Number(serde_yaml::Number::from(f.to_f64().ok_or_else(|| {
ShellError::labeled_error(
"Could not convert to decimal",
"could not convert to decimal",
&v.tag,
)
})?))
}
UntaggedValue::Primitive(Primitive::Int(i)) => {
serde_yaml::Value::Number(serde_yaml::Number::from(CoerceInto::<i64>::coerce_into(

View File

@ -107,7 +107,7 @@ impl CommandRegistry {
#[derive(Clone)]
pub struct Context {
pub registry: CommandRegistry,
pub host: Arc<Mutex<Box<dyn Host>>>,
pub host: Arc<parking_lot::Mutex<Box<dyn Host>>>,
pub current_errors: Arc<Mutex<Vec<ShellError>>>,
pub ctrl_c: Arc<AtomicBool>,
pub(crate) shell_manager: ShellManager,
@ -133,7 +133,9 @@ impl Context {
let registry = CommandRegistry::new();
Ok(Context {
registry: registry.clone(),
host: Arc::new(Mutex::new(Box::new(crate::env::host::BasicHost))),
host: Arc::new(parking_lot::Mutex::new(Box::new(
crate::env::host::BasicHost,
))),
current_errors: Arc::new(Mutex::new(vec![])),
ctrl_c: Arc::new(AtomicBool::new(false)),
shell_manager: ShellManager::basic(registry)?,
@ -161,14 +163,7 @@ impl Context {
);
result = false;
}
(_, Err(err)) => {
errln!(
"Unexpected error attempting to acquire the lock of the current errors: {:?}",
err
);
result = false;
}
(Ok(mut errors), Ok(host)) => {
(Ok(mut errors), host) => {
if errors.len() > 0 {
let error = errors[0].clone();
*errors = vec![];
@ -188,13 +183,8 @@ impl Context {
&mut self,
block: impl FnOnce(&mut dyn Host) -> T,
) -> Result<T, ShellError> {
if let Ok(mut host) = self.host.lock() {
let mut host = self.host.lock();
Ok(block(&mut *host))
} else {
Err(ShellError::untagged_runtime_error(
"Internal error: could not lock host in with_host",
))
}
}
pub(crate) fn with_errors<T>(

16
src/env/host.rs vendored
View File

@ -4,8 +4,8 @@ use nu_errors::ShellError;
use std::fmt::Debug;
pub trait Host: Debug + Send {
fn out_terminal(&self) -> Box<term::StdoutTerminal>;
fn err_terminal(&self) -> Box<term::StderrTerminal>;
fn out_terminal(&self) -> Option<Box<term::StdoutTerminal>>;
fn err_terminal(&self) -> Option<Box<term::StderrTerminal>>;
fn out_termcolor(&self) -> termcolor::StandardStream;
fn err_termcolor(&self) -> termcolor::StandardStream;
@ -17,11 +17,11 @@ pub trait Host: Debug + Send {
}
impl Host for Box<dyn Host> {
fn out_terminal(&self) -> Box<term::StdoutTerminal> {
fn out_terminal(&self) -> Option<Box<term::StdoutTerminal>> {
(**self).out_terminal()
}
fn err_terminal(&self) -> Box<term::StderrTerminal> {
fn err_terminal(&self) -> Option<Box<term::StderrTerminal>> {
(**self).err_terminal()
}
@ -50,12 +50,12 @@ impl Host for Box<dyn Host> {
pub struct BasicHost;
impl Host for BasicHost {
fn out_terminal(&self) -> Box<term::StdoutTerminal> {
term::stdout().unwrap()
fn out_terminal(&self) -> Option<Box<term::StdoutTerminal>> {
term::stdout()
}
fn err_terminal(&self) -> Box<term::StderrTerminal> {
term::stderr().unwrap()
fn err_terminal(&self) -> Option<Box<term::StderrTerminal>> {
term::stderr()
}
fn stdout(&mut self, out: &str) {

View File

@ -326,13 +326,16 @@ impl RenderView for TableView {
let mut table = Table::new();
let table_mode = crate::data::config::config(Tag::unknown())?
.get("table_mode")
.map(|s| match s.as_string().unwrap().as_ref() {
"light" => TableMode::Light,
let table_mode = crate::data::config::config(Tag::unknown());
let table_mode = if let Some(s) = table_mode?.get("table_mode") {
match s.as_string() {
Ok(typ) if typ == "light" => TableMode::Light,
_ => TableMode::Normal,
})
.unwrap_or(TableMode::Normal);
}
} else {
TableMode::Normal
};
match table_mode {
TableMode::Light => {
@ -376,7 +379,8 @@ impl RenderView for TableView {
));
}
table.print_term(&mut *host.out_terminal()).map_err(|_| ShellError::untagged_runtime_error("Internal error: could not print to terminal (for unix systems check to make sure TERM is set)"))?;
table.print_term(&mut *host.out_terminal().ok_or_else(|| ShellError::untagged_runtime_error("Could not open terminal for output"))?)
.map_err(|_| ShellError::untagged_runtime_error("Internal error: could not print to terminal (for unix systems check to make sure TERM is set)"))?;
Ok(())
}

View File

@ -99,7 +99,7 @@ pub(crate) use num_traits::cast::ToPrimitive;
pub(crate) use serde::Deserialize;
pub(crate) use std::collections::VecDeque;
pub(crate) use std::future::Future;
pub(crate) use std::sync::{Arc, Mutex};
pub(crate) use std::sync::Arc;
pub(crate) use itertools::Itertools;

View File

@ -59,12 +59,9 @@ impl FilesystemShell {
})
}
pub fn with_location(
path: String,
commands: CommandRegistry,
) -> Result<FilesystemShell, std::io::Error> {
pub fn with_location(path: String, commands: CommandRegistry) -> FilesystemShell {
let last_path = path.clone();
Ok(FilesystemShell {
FilesystemShell {
path,
last_path,
completer: NuCompleter {
@ -72,7 +69,7 @@ impl FilesystemShell {
commands,
},
hinter: HistoryHinter {},
})
}
}
}