Range refactor (#12405)

# Description
Currently, `Range` is a struct with a `from`, `to`, and `incr` field,
which are all type `Value`. This PR changes `Range` to be an enum over
`IntRange` and `FloatRange` for better type safety / stronger compile
time guarantees.

Fixes: #11778 Fixes: #11777 Fixes: #11776 Fixes: #11775 Fixes: #11774
Fixes: #11773 Fixes: #11769.

# User-Facing Changes
Hopefully none, besides bug fixes.

Although, the `serde` representation might have changed.
This commit is contained in:
Ian Manske
2024-04-06 14:04:56 +00:00
committed by GitHub
parent 75fedcc8dd
commit 7a7d43344e
27 changed files with 1126 additions and 798 deletions

View File

@ -6,10 +6,7 @@ use crate::{
TestCustomValue,
},
};
use nu_protocol::{
ast::RangeInclusion, engine::Closure, record, CustomValue, IntoSpanned, Range, ShellError,
Span, Value,
};
use nu_protocol::{engine::Closure, record, CustomValue, IntoSpanned, ShellError, Span, Value};
use std::sync::Arc;
#[test]
@ -60,50 +57,6 @@ fn add_source_in_at_root() -> Result<(), ShellError> {
Ok(())
}
fn check_range_custom_values(
val: &Value,
mut f: impl FnMut(&str, &dyn CustomValue) -> Result<(), ShellError>,
) -> Result<(), ShellError> {
let range = val.as_range()?;
for (name, val) in [
("from", &range.from),
("incr", &range.incr),
("to", &range.to),
] {
let custom_value = val
.as_custom_value()
.unwrap_or_else(|_| panic!("{name} not custom value"));
f(name, custom_value)?;
}
Ok(())
}
#[test]
fn add_source_in_nested_range() -> Result<(), ShellError> {
let orig_custom_val = Value::test_custom_value(Box::new(test_plugin_custom_value()));
let mut val = Value::test_range(Range {
from: orig_custom_val.clone(),
incr: orig_custom_val.clone(),
to: orig_custom_val.clone(),
inclusion: RangeInclusion::Inclusive,
});
let source = Arc::new(PluginSource::new_fake("foo"));
PluginCustomValue::add_source_in(&mut val, &source)?;
check_range_custom_values(&val, |name, custom_value| {
let plugin_custom_value: &PluginCustomValue = custom_value
.as_any()
.downcast_ref()
.unwrap_or_else(|| panic!("{name} not PluginCustomValue"));
assert_eq!(
Some(Arc::as_ptr(&source)),
plugin_custom_value.source.as_ref().map(Arc::as_ptr),
"{name} source not set correctly"
);
Ok(())
})
}
fn check_record_custom_values(
val: &Value,
keys: &[&str],
@ -292,31 +245,6 @@ fn serialize_in_root() -> Result<(), ShellError> {
Ok(())
}
#[test]
fn serialize_in_range() -> Result<(), ShellError> {
let orig_custom_val = Value::test_custom_value(Box::new(TestCustomValue(-1)));
let mut val = Value::test_range(Range {
from: orig_custom_val.clone(),
incr: orig_custom_val.clone(),
to: orig_custom_val.clone(),
inclusion: RangeInclusion::Inclusive,
});
PluginCustomValue::serialize_custom_values_in(&mut val)?;
check_range_custom_values(&val, |name, custom_value| {
let plugin_custom_value: &PluginCustomValue = custom_value
.as_any()
.downcast_ref()
.unwrap_or_else(|| panic!("{name} not PluginCustomValue"));
assert_eq!(
"TestCustomValue",
plugin_custom_value.name(),
"{name} name not set correctly"
);
Ok(())
})
}
#[test]
fn serialize_in_record() -> Result<(), ShellError> {
let orig_custom_val = Value::test_custom_value(Box::new(TestCustomValue(32)));
@ -400,31 +328,6 @@ fn deserialize_in_root() -> Result<(), ShellError> {
Ok(())
}
#[test]
fn deserialize_in_range() -> Result<(), ShellError> {
let orig_custom_val = Value::test_custom_value(Box::new(test_plugin_custom_value()));
let mut val = Value::test_range(Range {
from: orig_custom_val.clone(),
incr: orig_custom_val.clone(),
to: orig_custom_val.clone(),
inclusion: RangeInclusion::Inclusive,
});
PluginCustomValue::deserialize_custom_values_in(&mut val)?;
check_range_custom_values(&val, |name, custom_value| {
let test_custom_value: &TestCustomValue = custom_value
.as_any()
.downcast_ref()
.unwrap_or_else(|| panic!("{name} not TestCustomValue"));
assert_eq!(
expected_test_custom_value(),
*test_custom_value,
"{name} not deserialized correctly"
);
Ok(())
})
}
#[test]
fn deserialize_in_record() -> Result<(), ShellError> {
let orig_custom_val = Value::test_custom_value(Box::new(test_plugin_custom_value()));

View File

@ -33,7 +33,7 @@ where
#[test]
fn find_custom_values() {
use crate::protocol::test_util::test_plugin_custom_value;
use nu_protocol::{ast::RangeInclusion, engine::Closure, record, LazyRecord, Range, Span};
use nu_protocol::{engine::Closure, record, LazyRecord, Span};
#[derive(Debug, Clone)]
struct Lazy;
@ -73,12 +73,6 @@ fn find_custom_values() {
captures: vec![(0, cv.clone()), (1, Value::test_string("foo"))]
}
),
"range" => Value::test_range(Range {
from: cv.clone(),
incr: cv.clone(),
to: cv.clone(),
inclusion: RangeInclusion::Inclusive
}),
"lazy" => Value::test_lazy_record(Box::new(Lazy)),
});
@ -89,7 +83,7 @@ fn find_custom_values() {
Ok(())
})
.expect("error");
assert_eq!(7, found, "found in value");
assert_eq!(4, found, "found in value");
// Try it on bare custom value too
found = 0;