mirror of
https://github.com/nushell/nushell.git
synced 2024-11-29 11:54:02 +01:00
Fix tests and add some more From
conversions
This commit is contained in:
parent
33b28ff9b3
commit
a914926001
@ -1,5 +1,5 @@
|
||||
use nu_engine::command_prelude::*;
|
||||
|
||||
use nu_protocol::format_filesize_from_conf;
|
||||
use rand::{thread_rng, RngCore};
|
||||
|
||||
#[derive(Clone)]
|
||||
@ -37,7 +37,27 @@ impl Command for SubCommand {
|
||||
call: &Call,
|
||||
_input: PipelineData,
|
||||
) -> Result<PipelineData, ShellError> {
|
||||
let length = call.req(engine_state, stack, 0)?;
|
||||
let length_val = call.req(engine_state, stack, 0)?;
|
||||
let length = match length_val {
|
||||
Value::Int { val, .. } => usize::try_from(val).map_err(|_| ShellError::InvalidValue {
|
||||
valid: "a non-negative int or filesize".into(),
|
||||
actual: val.to_string(),
|
||||
span: length_val.span(),
|
||||
}),
|
||||
Value::Filesize { val, .. } => {
|
||||
usize::try_from(val).map_err(|_| ShellError::InvalidValue {
|
||||
valid: "a non-negative int or filesize".into(),
|
||||
actual: format_filesize_from_conf(val, engine_state.get_config()),
|
||||
span: length_val.span(),
|
||||
})
|
||||
}
|
||||
val => Err(ShellError::RuntimeTypeMismatch {
|
||||
expected: Type::custom("int or filesize"),
|
||||
actual: val.get_type(),
|
||||
span: val.span(),
|
||||
}),
|
||||
}?;
|
||||
|
||||
let mut rng = thread_rng();
|
||||
|
||||
let mut out = vec![0u8; length];
|
||||
|
@ -1,5 +1,5 @@
|
||||
use nu_engine::command_prelude::*;
|
||||
|
||||
use nu_protocol::format_filesize_from_conf;
|
||||
use rand::{
|
||||
distributions::{Alphanumeric, Distribution},
|
||||
thread_rng,
|
||||
@ -73,14 +73,36 @@ fn chars(
|
||||
call: &Call,
|
||||
) -> Result<PipelineData, ShellError> {
|
||||
let span = call.head;
|
||||
let length: Option<usize> = call.get_flag(engine_state, stack, "length")?;
|
||||
let length: Option<Value> = call.get_flag(engine_state, stack, "length")?;
|
||||
let length = if let Some(length_val) = length {
|
||||
match length_val {
|
||||
Value::Int { val, .. } => usize::try_from(val).map_err(|_| ShellError::InvalidValue {
|
||||
valid: "a non-negative int or filesize".into(),
|
||||
actual: val.to_string(),
|
||||
span: length_val.span(),
|
||||
}),
|
||||
Value::Filesize { val, .. } => {
|
||||
usize::try_from(val).map_err(|_| ShellError::InvalidValue {
|
||||
valid: "a non-negative int or filesize".into(),
|
||||
actual: format_filesize_from_conf(val, engine_state.get_config()),
|
||||
span: length_val.span(),
|
||||
})
|
||||
}
|
||||
val => Err(ShellError::RuntimeTypeMismatch {
|
||||
expected: Type::custom("int or filesize"),
|
||||
actual: val.get_type(),
|
||||
span: val.span(),
|
||||
}),
|
||||
}?
|
||||
} else {
|
||||
DEFAULT_CHARS_LENGTH
|
||||
};
|
||||
|
||||
let chars_length = length.unwrap_or(DEFAULT_CHARS_LENGTH);
|
||||
let mut rng = thread_rng();
|
||||
|
||||
let random_string = Alphanumeric
|
||||
.sample_iter(&mut rng)
|
||||
.take(chars_length)
|
||||
.take(length)
|
||||
.map(char::from)
|
||||
.collect::<String>();
|
||||
|
||||
|
@ -141,7 +141,7 @@ fn reject_rows_with_list_spread() {
|
||||
let actual = nu!("let arg = [2 0]; [[name type size];[Cargo.toml file 10mb] [Cargo.lock file 10mb] [src dir 100mb]] | reject ...$arg | to nuon");
|
||||
assert_eq!(
|
||||
actual.out,
|
||||
r#"[[name, type, size]; ["Cargo.lock", file, 10000000b]]"#
|
||||
r#"[[name, type, size]; ["Cargo.lock", file, 10000000B]]"#
|
||||
);
|
||||
}
|
||||
|
||||
@ -150,7 +150,7 @@ fn reject_mixed_with_list_spread() {
|
||||
let actual = nu!("let arg = [type 2]; [[name type size];[Cargp.toml file 10mb] [ Cargo.lock file 10mb] [src dir 100mb]] | reject ...$arg | to nuon");
|
||||
assert_eq!(
|
||||
actual.out,
|
||||
r#"[[name, size]; ["Cargp.toml", 10000000b], ["Cargo.lock", 10000000b]]"#
|
||||
r#"[[name, size]; ["Cargp.toml", 10000000B], ["Cargo.lock", 10000000B]]"#
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -211,7 +211,7 @@ fn to_nuon_filesize() {
|
||||
"#
|
||||
));
|
||||
|
||||
assert_eq!(actual.out, "1024b");
|
||||
assert_eq!(actual.out, "1024B");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -86,56 +86,6 @@ impl From<Filesize> for i64 {
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<u64> for Filesize {
|
||||
type Error = <u64 as TryInto<i64>>::Error;
|
||||
|
||||
fn try_from(value: u64) -> Result<Self, Self::Error> {
|
||||
value.try_into().map(Self)
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<Filesize> for u64 {
|
||||
type Error = <i64 as TryInto<u64>>::Error;
|
||||
|
||||
fn try_from(filesize: Filesize) -> Result<Self, Self::Error> {
|
||||
filesize.0.try_into()
|
||||
}
|
||||
}
|
||||
|
||||
/// The error type returned when a checked conversion from a floating point type fails.
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Error)]
|
||||
pub struct TryFromFloatError(());
|
||||
|
||||
impl fmt::Display for TryFromFloatError {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(fmt, "out of range float type conversion attempted")
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<f64> for Filesize {
|
||||
type Error = TryFromFloatError;
|
||||
|
||||
fn try_from(value: f64) -> Result<Self, Self::Error> {
|
||||
if i64::MIN as f64 <= value && value <= i64::MAX as f64 {
|
||||
Ok(Self(value as i64))
|
||||
} else {
|
||||
Err(TryFromFloatError(()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<f32> for Filesize {
|
||||
type Error = TryFromFloatError;
|
||||
|
||||
fn try_from(value: f32) -> Result<Self, Self::Error> {
|
||||
if i64::MIN as f32 <= value && value <= i64::MAX as f32 {
|
||||
Ok(Self(value as i64))
|
||||
} else {
|
||||
Err(TryFromFloatError(()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! impl_from {
|
||||
($($ty:ty),* $(,)?) => {
|
||||
$(
|
||||
@ -160,6 +110,68 @@ macro_rules! impl_from {
|
||||
|
||||
impl_from!(u8, i8, u16, i16, u32, i32);
|
||||
|
||||
macro_rules! impl_try_from {
|
||||
($($ty:ty),* $(,)?) => {
|
||||
$(
|
||||
impl TryFrom<$ty> for Filesize {
|
||||
type Error = <$ty as TryInto<i64>>::Error;
|
||||
|
||||
#[inline]
|
||||
fn try_from(value: $ty) -> Result<Self, Self::Error> {
|
||||
value.try_into().map(Self)
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<Filesize> for $ty {
|
||||
type Error = <i64 as TryInto<$ty>>::Error;
|
||||
|
||||
#[inline]
|
||||
fn try_from(filesize: Filesize) -> Result<Self, Self::Error> {
|
||||
filesize.0.try_into()
|
||||
}
|
||||
}
|
||||
)*
|
||||
};
|
||||
}
|
||||
|
||||
impl_try_from!(u64, usize, isize);
|
||||
|
||||
/// The error type returned when a checked conversion from a floating point type fails.
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Error)]
|
||||
pub struct TryFromFloatError(());
|
||||
|
||||
impl fmt::Display for TryFromFloatError {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(fmt, "out of range float type conversion attempted")
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<f64> for Filesize {
|
||||
type Error = TryFromFloatError;
|
||||
|
||||
#[inline]
|
||||
fn try_from(value: f64) -> Result<Self, Self::Error> {
|
||||
if i64::MIN as f64 <= value && value <= i64::MAX as f64 {
|
||||
Ok(Self(value as i64))
|
||||
} else {
|
||||
Err(TryFromFloatError(()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<f32> for Filesize {
|
||||
type Error = TryFromFloatError;
|
||||
|
||||
#[inline]
|
||||
fn try_from(value: f32) -> Result<Self, Self::Error> {
|
||||
if i64::MIN as f32 <= value && value <= i64::MAX as f32 {
|
||||
Ok(Self(value as i64))
|
||||
} else {
|
||||
Err(TryFromFloatError(()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FromValue for Filesize {
|
||||
fn from_value(value: Value) -> Result<Self, ShellError> {
|
||||
value.as_filesize()
|
||||
@ -260,7 +272,7 @@ impl fmt::Display for Filesize {
|
||||
|
||||
/// All the possible filesize units for a [`Filesize`].
|
||||
///
|
||||
/// This type contains both units with metric (SI) decimal prefixes which are powers of 10 (e.g., KB = 1000 bytes)
|
||||
/// This type contains both units with metric (SI) decimal prefixes which are powers of 10 (e.g., kB = 1000 bytes)
|
||||
/// and units with binary prefixes which are powers of 2 (e.g., KiB = 1024 bytes).
|
||||
///
|
||||
/// The number of bytes in a [`FilesizeUnit`] can be obtained using
|
||||
@ -330,13 +342,13 @@ impl FilesizeUnit {
|
||||
/// ```
|
||||
/// # use nu_protocol::FilesizeUnit;
|
||||
/// assert_eq!(FilesizeUnit::B.as_str(), "B");
|
||||
/// assert_eq!(FilesizeUnit::KB.as_str(), "KB");
|
||||
/// assert_eq!(FilesizeUnit::KB.as_str(), "kB");
|
||||
/// assert_eq!(FilesizeUnit::KiB.as_str(), "KiB");
|
||||
/// ```
|
||||
pub const fn as_str(&self) -> &'static str {
|
||||
match self {
|
||||
Self::B => "B",
|
||||
Self::KB => "KB",
|
||||
Self::KB => "kB",
|
||||
Self::MB => "MB",
|
||||
Self::GB => "GB",
|
||||
Self::TB => "TB",
|
||||
@ -397,7 +409,7 @@ impl FromStr for FilesizeUnit {
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
Ok(match s {
|
||||
"B" => Self::B,
|
||||
"KB" => Self::KB,
|
||||
"kB" => Self::KB,
|
||||
"MB" => Self::MB,
|
||||
"GB" => Self::GB,
|
||||
"TB" => Self::TB,
|
||||
|
@ -154,8 +154,8 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn filesize() {
|
||||
nuon_end_to_end("1024b", Some(Value::test_filesize(1024)));
|
||||
assert_eq!(from_nuon("1kib", None).unwrap(), Value::test_filesize(1024),);
|
||||
nuon_end_to_end("1024B", Some(Value::test_filesize(1024)));
|
||||
assert_eq!(from_nuon("1kib", None).unwrap(), Value::test_filesize(1024));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -110,7 +110,7 @@ fn value_to_string(
|
||||
// Propagate existing errors
|
||||
Value::Error { error, .. } => Err(*error.clone()),
|
||||
// FIXME: make filesizes use the shortest lossless representation.
|
||||
Value::Filesize { val, .. } => Ok(format!("{}b", *val)),
|
||||
Value::Filesize { val, .. } => Ok(format!("{}B", val.get())),
|
||||
Value::Float { val, .. } => {
|
||||
// This serialises these as 'nan', 'inf' and '-inf', respectively.
|
||||
if &val.round() == val && val.is_finite() {
|
||||
|
Loading…
Reference in New Issue
Block a user