Use Record::get instead of Value functions (#10925)

# Description
Where appropriate, this PR replaces instances of
`Value::get_data_by_key` and `Value::follow_cell_path` with
`Record::get`. This avoids some unnecessary clones and simplifies the
code in some places.
This commit is contained in:
Ian Manske
2023-11-08 20:47:37 +00:00
committed by GitHub
parent 435abadd8a
commit 59ea28cf06
17 changed files with 230 additions and 289 deletions

View File

@ -75,14 +75,17 @@ fn table_to_delimited(
.expect("can not write.");
for l in vals {
let mut row = vec![];
for desc in &merged_descriptors {
row.push(match l.to_owned().get_data_by_key(desc) {
Some(s) => to_string_tagged_value(&s, config, head, span)?,
None => String::new(),
});
// should always be true because of `find_non_record` above
if let Value::Record { val: l, .. } = l {
let mut row = vec![];
for desc in &merged_descriptors {
row.push(match l.get(desc) {
Some(s) => to_string_tagged_value(s, config, head, span)?,
None => String::new(),
});
}
wtr.write_record(&row).expect("can not write");
}
wtr.write_record(&row).expect("can not write");
}
}
writer_to_string(wtr).map_err(|_| make_conversion_error("table", span))

View File

@ -105,27 +105,24 @@ fn to_md(
}
fn fragment(input: Value, pretty: bool, config: &Config) -> String {
let headers = input.columns();
let mut out = String::new();
if headers.len() == 1 {
let markup = match headers[0].to_ascii_lowercase().as_ref() {
"h1" => "# ".to_string(),
"h2" => "## ".to_string(),
"h3" => "### ".to_string(),
"blockquote" => "> ".to_string(),
if let Value::Record { val, .. } = &input {
match val.get_index(0) {
Some((header, data)) if val.len() == 1 => {
let markup = match header.to_ascii_lowercase().as_ref() {
"h1" => "# ".to_string(),
"h2" => "## ".to_string(),
"h3" => "### ".to_string(),
"blockquote" => "> ".to_string(),
_ => return table(input.into_pipeline_data(), pretty, config),
};
_ => return table(input.into_pipeline_data(), pretty, config),
};
out.push_str(&markup);
let data = match input.get_data_by_key(&headers[0]) {
Some(v) => v,
None => input,
};
out.push_str(&data.into_string("|", config));
} else if let Value::Record { .. } = input {
out = table(input.into_pipeline_data(), pretty, config)
out.push_str(&markup);
out.push_str(&data.into_string("|", config));
}
_ => out = table(input.into_pipeline_data(), pretty, config),
}
} else {
out = input.into_string("|", config)
}
@ -164,10 +161,11 @@ fn table(input: PipelineData, pretty: bool, config: &Config) -> String {
let span = row.span();
match row.to_owned() {
Value::Record { .. } => {
Value::Record { val: row, .. } => {
for i in 0..headers.len() {
let data = row.get_data_by_key(&headers[i]);
let value_string = data
let value_string = row
.get(&headers[i])
.cloned()
.unwrap_or_else(|| Value::nothing(span))
.into_string(", ", config);
let new_column_width = value_string.len();

View File

@ -109,47 +109,50 @@ fn to_xml_entry<W: Write>(
return to_xml_text(val.as_str(), span, writer);
}
if !matches!(entry, Value::Record { .. }) {
return Err(ShellError::CantConvert {
if let Value::Record { val: record, .. } = &entry {
// If key is not found it is assumed to be nothing. This way
// user can write a tag like {tag: a content: [...]} instead
// of longer {tag: a attributes: {} content: [...]}
let tag = record
.get(COLUMN_TAG_NAME)
.cloned()
.unwrap_or_else(|| Value::nothing(Span::unknown()));
let attrs = record
.get(COLUMN_ATTRS_NAME)
.cloned()
.unwrap_or_else(|| Value::nothing(Span::unknown()));
let content = record
.get(COLUMN_CONTENT_NAME)
.cloned()
.unwrap_or_else(|| Value::nothing(Span::unknown()));
let content_span = content.span();
let tag_span = tag.span();
match (tag, attrs, content) {
(Value::Nothing { .. }, Value::Nothing { .. }, Value::String { val, .. }) => {
// Strings can not appear on top level of document
if top_level {
return Err(ShellError::CantConvert {
to_type: "XML".into(),
from_type: entry.get_type().to_string(),
span: entry_span,
help: Some("Strings can not be a root element of document".into()),
});
}
to_xml_text(val.as_str(), content_span, writer)
}
(Value::String { val: tag_name, .. }, attrs, children) => to_tag_like(
entry_span, tag_name, tag_span, attrs, children, top_level, writer,
),
_ => Ok(()),
}
} else {
Err(ShellError::CantConvert {
to_type: "XML".into(),
from_type: entry.get_type().to_string(),
span: entry_span,
help: Some("Xml entry expected to be a record".into()),
});
};
// If key is not found it is assumed to be nothing. This way
// user can write a tag like {tag: a content: [...]} instead
// of longer {tag: a attributes: {} content: [...]}
let tag = entry
.get_data_by_key(COLUMN_TAG_NAME)
.unwrap_or_else(|| Value::nothing(Span::unknown()));
let attrs = entry
.get_data_by_key(COLUMN_ATTRS_NAME)
.unwrap_or_else(|| Value::nothing(Span::unknown()));
let content = entry
.get_data_by_key(COLUMN_CONTENT_NAME)
.unwrap_or_else(|| Value::nothing(Span::unknown()));
let content_span = content.span();
let tag_span = tag.span();
match (tag, attrs, content) {
(Value::Nothing { .. }, Value::Nothing { .. }, Value::String { val, .. }) => {
// Strings can not appear on top level of document
if top_level {
return Err(ShellError::CantConvert {
to_type: "XML".into(),
from_type: entry.get_type().to_string(),
span: entry_span,
help: Some("Strings can not be a root element of document".into()),
});
}
to_xml_text(val.as_str(), content_span, writer)
}
(Value::String { val: tag_name, .. }, attrs, children) => to_tag_like(
entry_span, tag_name, tag_span, attrs, children, top_level, writer,
),
_ => Ok(()),
})
}
}