mirror of
https://github.com/nushell/nushell.git
synced 2025-08-09 10:45:41 +02:00
Protocol: debug_assert!() Span to reflect a valid slice (#6806)
Also enforce this by #[non_exhaustive] span such that going forward we cannot, in debug builds (1), construct invalid spans. The motivation for this stems from #6431 where I've seen crashes due to invalid slice indexing. My hope is this will mitigate such senarios 1. https://github.com/nushell/nushell/pull/6431#issuecomment-1278147241 # Description (description of your pull request here) # Tests Make sure you've done the following: - [ ] Add tests that cover your changes, either in the command examples, the crate/tests folder, or in the /tests folder. - [ ] Try to think about corner cases and various ways how your changes could break. Cover them with tests. - [ ] If adding tests is not possible, please document in the PR body a minimal example with steps on how to reproduce so one can verify your change works. Make sure you've run and fixed any issues with these commands: - [x] `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - [ ] `cargo clippy --workspace --features=extra -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect` to check that you're using the standard code style - [ ] `cargo test --workspace --features=extra` to check that all the tests pass # Documentation - [ ] If your PR touches a user-facing nushell feature then make sure that there is an entry in the documentation (https://github.com/nushell/nushell.github.io) for the feature, and update it if necessary.
This commit is contained in:
committed by
GitHub
parent
e6cf18ea43
commit
850ecf648a
@ -53,7 +53,7 @@ impl Default for HashableValue {
|
||||
fn default() -> Self {
|
||||
HashableValue::Bool {
|
||||
val: false,
|
||||
span: Span { start: 0, end: 0 },
|
||||
span: Span::unknown(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -214,7 +214,7 @@ mod test {
|
||||
];
|
||||
for (val, expect_hashable_val) in values.into_iter() {
|
||||
assert_eq!(
|
||||
HashableValue::from_value(val, Span { start: 0, end: 0 }).unwrap(),
|
||||
HashableValue::from_value(val, Span::unknown()).unwrap(),
|
||||
expect_hashable_val
|
||||
);
|
||||
}
|
||||
@ -245,7 +245,7 @@ mod test {
|
||||
},
|
||||
];
|
||||
for v in values {
|
||||
assert!(HashableValue::from_value(v, Span { start: 0, end: 0 }).is_err())
|
||||
assert!(HashableValue::from_value(v, Span::unknown()).is_err())
|
||||
}
|
||||
}
|
||||
|
||||
@ -266,7 +266,7 @@ mod test {
|
||||
for val in values.into_iter() {
|
||||
let expected_val = val.clone();
|
||||
assert_eq!(
|
||||
HashableValue::from_value(val, Span { start: 0, end: 0 })
|
||||
HashableValue::from_value(val, Span::unknown())
|
||||
.unwrap()
|
||||
.into_value(),
|
||||
expected_val
|
||||
@ -279,14 +279,11 @@ mod test {
|
||||
assert_eq!(
|
||||
HashableValue::Bool {
|
||||
val: true,
|
||||
span: Span { start: 0, end: 1 }
|
||||
span: Span::new(0, 1)
|
||||
},
|
||||
HashableValue::Bool {
|
||||
val: true,
|
||||
span: Span {
|
||||
start: 90,
|
||||
end: 1000
|
||||
}
|
||||
span: Span::new(90, 1000)
|
||||
}
|
||||
)
|
||||
}
|
||||
@ -299,7 +296,7 @@ mod test {
|
||||
assert!(set.contains(&HashableValue::Bool { val: true, span }));
|
||||
|
||||
// hashable value doesn't care about span.
|
||||
let diff_span = Span { start: 1, end: 2 };
|
||||
let diff_span = Span::new(1, 2);
|
||||
set.insert(HashableValue::Bool {
|
||||
val: true,
|
||||
span: diff_span,
|
||||
|
@ -502,7 +502,7 @@ mod test {
|
||||
|
||||
#[test]
|
||||
fn turns_ns_to_duration() {
|
||||
let span = Span::test_data();
|
||||
let span = Span::new(0, 2);
|
||||
let word = Value::test_string("3ns");
|
||||
let expected = Value::Duration { val: 3, span };
|
||||
let convert_duration = None;
|
||||
@ -513,7 +513,7 @@ mod test {
|
||||
|
||||
#[test]
|
||||
fn turns_us_to_duration() {
|
||||
let span = Span::test_data();
|
||||
let span = Span::new(0, 2);
|
||||
let word = Value::test_string("4us");
|
||||
let expected = Value::Duration {
|
||||
val: 4 * 1000,
|
||||
@ -527,7 +527,7 @@ mod test {
|
||||
|
||||
#[test]
|
||||
fn turns_ms_to_duration() {
|
||||
let span = Span::test_data();
|
||||
let span = Span::new(0, 2);
|
||||
let word = Value::test_string("5ms");
|
||||
let expected = Value::Duration {
|
||||
val: 5 * 1000 * 1000,
|
||||
@ -541,7 +541,7 @@ mod test {
|
||||
|
||||
#[test]
|
||||
fn turns_sec_to_duration() {
|
||||
let span = Span::test_data();
|
||||
let span = Span::new(0, 3);
|
||||
let word = Value::test_string("1sec");
|
||||
let expected = Value::Duration {
|
||||
val: 1000 * 1000 * 1000,
|
||||
@ -555,7 +555,7 @@ mod test {
|
||||
|
||||
#[test]
|
||||
fn turns_min_to_duration() {
|
||||
let span = Span::test_data();
|
||||
let span = Span::new(0, 3);
|
||||
let word = Value::test_string("7min");
|
||||
let expected = Value::Duration {
|
||||
val: 7 * 60 * 1000 * 1000 * 1000,
|
||||
@ -569,7 +569,7 @@ mod test {
|
||||
|
||||
#[test]
|
||||
fn turns_hr_to_duration() {
|
||||
let span = Span::test_data();
|
||||
let span = Span::new(0, 3);
|
||||
let word = Value::test_string("42hr");
|
||||
let expected = Value::Duration {
|
||||
val: 42 * 60 * 60 * 1000 * 1000 * 1000,
|
||||
@ -583,7 +583,7 @@ mod test {
|
||||
|
||||
#[test]
|
||||
fn turns_day_to_duration() {
|
||||
let span = Span::test_data();
|
||||
let span = Span::new(0, 5);
|
||||
let word = Value::test_string("123day");
|
||||
let expected = Value::Duration {
|
||||
val: 123 * 24 * 60 * 60 * 1000 * 1000 * 1000,
|
||||
@ -597,7 +597,7 @@ mod test {
|
||||
|
||||
#[test]
|
||||
fn turns_wk_to_duration() {
|
||||
let span = Span::test_data();
|
||||
let span = Span::new(0, 2);
|
||||
let word = Value::test_string("3wk");
|
||||
let expected = Value::Duration {
|
||||
val: 3 * 7 * 24 * 60 * 60 * 1000 * 1000 * 1000,
|
||||
|
@ -108,10 +108,7 @@ fn make_error(value: &Value, throw_span: Option<Span>) -> Option<ShellError> {
|
||||
) => Some(ShellError::GenericError(
|
||||
message,
|
||||
label_text,
|
||||
Some(Span {
|
||||
start: start as usize,
|
||||
end: end as usize,
|
||||
}),
|
||||
Some(Span::new(start as usize, end as usize)),
|
||||
None,
|
||||
Vec::new(),
|
||||
)),
|
||||
|
@ -39,7 +39,7 @@ impl Display for DataFrameValue {
|
||||
impl Default for DataFrameValue {
|
||||
fn default() -> Self {
|
||||
Self(Value::Nothing {
|
||||
span: Span { start: 0, end: 0 },
|
||||
span: Span::unknown(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -64,7 +64,7 @@ impl Command for ConfigEnv {
|
||||
|
||||
let args = vec![Spanned {
|
||||
item: nu_config.to_string_lossy().to_string(),
|
||||
span: Span { start: 0, end: 0 },
|
||||
span: Span::unknown(),
|
||||
}];
|
||||
|
||||
let command = ExternalCommand {
|
||||
|
@ -64,7 +64,7 @@ impl Command for ConfigNu {
|
||||
|
||||
let args = vec![Spanned {
|
||||
item: nu_config.to_string_lossy().to_string(),
|
||||
span: Span { start: 0, end: 0 },
|
||||
span: Span::unknown(),
|
||||
}];
|
||||
|
||||
let command = ExternalCommand {
|
||||
|
@ -518,7 +518,7 @@ pub(crate) fn dir_entry_dict(
|
||||
|
||||
if md.is_dir() {
|
||||
if du {
|
||||
let params = DirBuilder::new(Span { start: 0, end: 2 }, None, false, None, false);
|
||||
let params = DirBuilder::new(Span::new(0, 2), None, false, None, false);
|
||||
let dir_size = DirInfo::new(filename, ¶ms, None, ctrl_c).get_size();
|
||||
|
||||
vals.push(Value::Filesize {
|
||||
|
@ -199,18 +199,18 @@ fn rm(
|
||||
));
|
||||
}
|
||||
|
||||
let targets_span = Span {
|
||||
start: targets
|
||||
let targets_span = Span::new(
|
||||
targets
|
||||
.iter()
|
||||
.map(|x| x.span.start)
|
||||
.min()
|
||||
.expect("targets were empty"),
|
||||
end: targets
|
||||
targets
|
||||
.iter()
|
||||
.map(|x| x.span.end)
|
||||
.max()
|
||||
.expect("targets were empty"),
|
||||
};
|
||||
);
|
||||
|
||||
let path = current_dir(engine_state, stack)?;
|
||||
|
||||
|
@ -154,7 +154,7 @@ fn item_mapper_by_col(cols: Vec<String>) -> impl Fn(crate::ItemMapperState) -> c
|
||||
|
||||
let col_vals = Value::List {
|
||||
vals: item_column_values,
|
||||
span: Span { start: 0, end: 0 },
|
||||
span: Span::unknown(),
|
||||
};
|
||||
|
||||
crate::ValueCounter::new_vals_to_compare(ms.item, ms.flag_ignore_case, col_vals)
|
||||
|
@ -166,19 +166,13 @@ fn convert_row_column_to_span(row: usize, col: usize, contents: &str) -> Span {
|
||||
cur_col = 0;
|
||||
}
|
||||
if cur_row >= row && cur_col >= col {
|
||||
return Span {
|
||||
start: offset,
|
||||
end: offset,
|
||||
};
|
||||
return Span::new(offset, offset);
|
||||
} else {
|
||||
cur_col += 1;
|
||||
}
|
||||
}
|
||||
|
||||
Span {
|
||||
start: contents.len(),
|
||||
end: contents.len(),
|
||||
}
|
||||
Span::new(contents.len(), contents.len())
|
||||
}
|
||||
|
||||
fn convert_string_to_value(string_input: String, span: Span) -> Result<Value, ShellError> {
|
||||
|
@ -420,11 +420,11 @@ fn display(help: &str, engine_state: &EngineState, stack: &mut Stack, span: Span
|
||||
&Call::new(span),
|
||||
Value::String {
|
||||
val: item.to_string(),
|
||||
span: Span { start: 0, end: 0 },
|
||||
span: Span::unknown(),
|
||||
}
|
||||
.into_pipeline_data(),
|
||||
) {
|
||||
let result = output.into_value(Span { start: 0, end: 0 });
|
||||
let result = output.into_value(Span::unknown());
|
||||
match result.as_string() {
|
||||
Ok(s) => {
|
||||
build.push_str(&s);
|
||||
|
@ -152,18 +152,12 @@ fn extract_formatting_operations(input: String, span_start: usize) -> Vec<Format
|
||||
if column_need_eval {
|
||||
output.push(FormatOperation::ValueNeedEval(
|
||||
column_name.clone(),
|
||||
Span {
|
||||
start: span_start + column_span_start,
|
||||
end: span_start + column_span_end,
|
||||
},
|
||||
Span::new(span_start + column_span_start, span_start + column_span_end),
|
||||
));
|
||||
} else {
|
||||
output.push(FormatOperation::ValueFromColumn(
|
||||
column_name.clone(),
|
||||
Span {
|
||||
start: span_start + column_span_start,
|
||||
end: span_start + column_span_end,
|
||||
},
|
||||
Span::new(span_start + column_span_start, span_start + column_span_end),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user