mirror of
https://github.com/nushell/nushell.git
synced 2025-08-09 06:45:59 +02:00
Add pipeline span to metadata
(#16014)
# Description This PR makes the span of a pipeline accessible through `metadata`, meaning it's possible to get the span of a pipeline without collecting it. Examples: ```nushell ls | metadata # => ╭────────┬────────────────────╮ # => │ │ ╭───────┬────────╮ │ # => │ span │ │ start │ 170218 │ │ # => │ │ │ end │ 170220 │ │ # => │ │ ╰───────┴────────╯ │ # => │ source │ ls │ # => ╰────────┴────────────────────╯ ``` ```nushell ls | metadata access {|meta| error make {msg: "error", label: {text: "here", span: $meta.span}} } # => Error: × error # => ╭─[entry #7:1:1] # => 1 │ ls | metadata access {|meta| # => · ─┬ # => · ╰── here # => 2 │ error make {msg: "error", label: {text: "here", span: $meta.span}} # => ╰──── ``` Here's an example that wouldn't be possible before, since you would have to use `metadata $in` to get the span, collecting the (infinite) stream ```nushell generate {|x=0| {out: 0, next: 0} } | metadata access {|meta| # do whatever with stream error make {msg: "error", label: {text: "here", span: $meta.span}} } # => Error: × error # => ╭─[entry #16:1:1] # => 1 │ generate {|x=0| {out: 0, next: 0} } | metadata access {|meta| # => · ────┬─── # => · ╰── here # => 2 │ # do whatever with stream # => ╰──── ``` I haven't done the tests or anything yet since I'm not sure how we feel about having this as part of the normal metadata, rather than a new command like `metadata span` or something. We could also have a `metadata access` like functionality for that with an optional closure argument potentially. # User-Facing Changes * The span of a pipeline is now available through `metadata` and `metadata access` without collecting a stream. # Tests + Formatting TODO # After Submitting N/A
This commit is contained in:
@ -87,10 +87,9 @@ impl Command for Metadata {
|
||||
.into_pipeline_data(),
|
||||
)
|
||||
}
|
||||
None => Ok(
|
||||
Value::record(build_metadata_record(input.metadata().as_ref(), head), head)
|
||||
.into_pipeline_data(),
|
||||
),
|
||||
None => {
|
||||
Ok(Value::record(build_metadata_record(&input, head), head).into_pipeline_data())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -116,19 +115,7 @@ fn build_metadata_record_value(
|
||||
head: Span,
|
||||
) -> Value {
|
||||
let mut record = Record::new();
|
||||
|
||||
let span = arg.span();
|
||||
record.push(
|
||||
"span",
|
||||
Value::record(
|
||||
record! {
|
||||
"start" => Value::int(span.start as i64,span),
|
||||
"end" => Value::int(span.end as i64, span),
|
||||
},
|
||||
head,
|
||||
),
|
||||
);
|
||||
|
||||
record.push("span", arg.span().into_value(head));
|
||||
Value::record(extend_record_with_metadata(record, metadata, head), head)
|
||||
}
|
||||
|
||||
|
@ -42,10 +42,7 @@ impl Command for MetadataAccess {
|
||||
// `ClosureEvalOnce` is not used as it uses `Stack::captures_to_stack` rather than
|
||||
// `Stack::captures_to_stack_preserve_out_dest`. This command shouldn't collect streams
|
||||
let mut callee_stack = caller_stack.captures_to_stack_preserve_out_dest(closure.captures);
|
||||
let metadata_record = Value::record(
|
||||
build_metadata_record(input.metadata().as_ref(), call.head),
|
||||
call.head,
|
||||
);
|
||||
let metadata_record = Value::record(build_metadata_record(&input, call.head), call.head);
|
||||
|
||||
if let Some(var_id) = block.signature.get_positional(0).and_then(|var| var.var_id) {
|
||||
callee_stack.add_var(var_id, metadata_record)
|
||||
@ -58,12 +55,10 @@ impl Command for MetadataAccess {
|
||||
fn examples(&self) -> Vec<Example> {
|
||||
vec![Example {
|
||||
description: "Access metadata and data from a stream together",
|
||||
example: r#"{foo: bar} | to json --raw | metadata access {|meta| {in: $in, meta: $meta}}"#,
|
||||
example: r#"{foo: bar} | to json --raw | metadata access {|meta| {in: $in, content: $meta.content_type}}"#,
|
||||
result: Some(Value::test_record(record! {
|
||||
"in" => Value::test_string(r#"{"foo":"bar"}"#),
|
||||
"meta" => Value::test_record(record! {
|
||||
"content_type" => Value::test_string(r#"application/json"#)
|
||||
})
|
||||
"content" => Value::test_string(r#"application/json"#)
|
||||
})),
|
||||
}]
|
||||
}
|
||||
|
@ -79,15 +79,13 @@ impl Command for MetadataSet {
|
||||
},
|
||||
Example {
|
||||
description: "Set the metadata of a file path",
|
||||
example: "'crates' | metadata set --datasource-filepath $'(pwd)/crates' | metadata",
|
||||
example: "'crates' | metadata set --datasource-filepath $'(pwd)/crates'",
|
||||
result: None,
|
||||
},
|
||||
Example {
|
||||
description: "Set the metadata of a file path",
|
||||
example: "'crates' | metadata set --content-type text/plain | metadata",
|
||||
result: Some(Value::test_record(record! {
|
||||
"content_type" => Value::test_string("text/plain"),
|
||||
})),
|
||||
example: "'crates' | metadata set --content-type text/plain | metadata | get content_type",
|
||||
result: Some(Value::test_string("text/plain")),
|
||||
},
|
||||
]
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
use nu_protocol::{DataSource, PipelineMetadata, Record, Span, Value};
|
||||
use nu_protocol::{DataSource, IntoValue, PipelineData, PipelineMetadata, Record, Span, Value};
|
||||
|
||||
pub fn extend_record_with_metadata(
|
||||
mut record: Record,
|
||||
@ -29,6 +29,10 @@ pub fn extend_record_with_metadata(
|
||||
record
|
||||
}
|
||||
|
||||
pub fn build_metadata_record(metadata: Option<&PipelineMetadata>, head: Span) -> Record {
|
||||
extend_record_with_metadata(Record::new(), metadata, head)
|
||||
pub fn build_metadata_record(pipeline: &PipelineData, head: Span) -> Record {
|
||||
let mut record = Record::new();
|
||||
if let Some(span) = pipeline.span() {
|
||||
record.insert("span", span.into_value(head));
|
||||
}
|
||||
extend_record_with_metadata(record, pipeline.metadata().as_ref(), head)
|
||||
}
|
||||
|
@ -203,6 +203,7 @@ mod test {
|
||||
|
||||
use super::*;
|
||||
|
||||
use crate::Reject;
|
||||
use crate::{Metadata, MetadataSet};
|
||||
|
||||
#[test]
|
||||
@ -221,6 +222,7 @@ mod test {
|
||||
working_set.add_decl(Box::new(FromCsv {}));
|
||||
working_set.add_decl(Box::new(Metadata {}));
|
||||
working_set.add_decl(Box::new(MetadataSet {}));
|
||||
working_set.add_decl(Box::new(Reject {}));
|
||||
|
||||
working_set.render()
|
||||
};
|
||||
@ -229,7 +231,7 @@ mod test {
|
||||
.merge_delta(delta)
|
||||
.expect("Error merging delta");
|
||||
|
||||
let cmd = r#""a,b\n1,2" | metadata set --content-type 'text/csv' --datasource-ls | from csv | metadata | $in"#;
|
||||
let cmd = r#""a,b\n1,2" | metadata set --content-type 'text/csv' --datasource-ls | from csv | metadata | reject span | $in"#;
|
||||
let result = eval_pipeline_without_terminal_expression(
|
||||
cmd,
|
||||
std::env::temp_dir().as_ref(),
|
||||
|
@ -248,6 +248,7 @@ fn convert_string_to_value_strict(string_input: &str, span: Span) -> Result<Valu
|
||||
mod test {
|
||||
use nu_cmd_lang::eval_pipeline_without_terminal_expression;
|
||||
|
||||
use crate::Reject;
|
||||
use crate::{Metadata, MetadataSet};
|
||||
|
||||
use super::*;
|
||||
@ -268,6 +269,7 @@ mod test {
|
||||
working_set.add_decl(Box::new(FromJson {}));
|
||||
working_set.add_decl(Box::new(Metadata {}));
|
||||
working_set.add_decl(Box::new(MetadataSet {}));
|
||||
working_set.add_decl(Box::new(Reject {}));
|
||||
|
||||
working_set.render()
|
||||
};
|
||||
@ -276,7 +278,7 @@ mod test {
|
||||
.merge_delta(delta)
|
||||
.expect("Error merging delta");
|
||||
|
||||
let cmd = r#"'{"a":1,"b":2}' | metadata set --content-type 'application/json' --datasource-ls | from json | metadata | $in"#;
|
||||
let cmd = r#"'{"a":1,"b":2}' | metadata set --content-type 'application/json' --datasource-ls | from json | metadata | reject span | $in"#;
|
||||
let result = eval_pipeline_without_terminal_expression(
|
||||
cmd,
|
||||
std::env::temp_dir().as_ref(),
|
||||
|
@ -514,6 +514,7 @@ fn assert_eof(input: &mut impl io::Read, span: Span) -> Result<(), ShellError> {
|
||||
mod test {
|
||||
use nu_cmd_lang::eval_pipeline_without_terminal_expression;
|
||||
|
||||
use crate::Reject;
|
||||
use crate::{Metadata, MetadataSet, ToMsgpack};
|
||||
|
||||
use super::*;
|
||||
@ -535,6 +536,7 @@ mod test {
|
||||
working_set.add_decl(Box::new(FromMsgpack {}));
|
||||
working_set.add_decl(Box::new(Metadata {}));
|
||||
working_set.add_decl(Box::new(MetadataSet {}));
|
||||
working_set.add_decl(Box::new(Reject {}));
|
||||
|
||||
working_set.render()
|
||||
};
|
||||
@ -543,7 +545,7 @@ mod test {
|
||||
.merge_delta(delta)
|
||||
.expect("Error merging delta");
|
||||
|
||||
let cmd = r#"{a: 1 b: 2} | to msgpack | metadata set --datasource-ls | from msgpack | metadata | $in"#;
|
||||
let cmd = r#"{a: 1 b: 2} | to msgpack | metadata set --datasource-ls | from msgpack | metadata | reject span | $in"#;
|
||||
let result = eval_pipeline_without_terminal_expression(
|
||||
cmd,
|
||||
std::env::temp_dir().as_ref(),
|
||||
|
@ -74,6 +74,7 @@ impl Command for FromNuon {
|
||||
mod test {
|
||||
use nu_cmd_lang::eval_pipeline_without_terminal_expression;
|
||||
|
||||
use crate::Reject;
|
||||
use crate::{Metadata, MetadataSet};
|
||||
|
||||
use super::*;
|
||||
@ -94,6 +95,7 @@ mod test {
|
||||
working_set.add_decl(Box::new(FromNuon {}));
|
||||
working_set.add_decl(Box::new(Metadata {}));
|
||||
working_set.add_decl(Box::new(MetadataSet {}));
|
||||
working_set.add_decl(Box::new(Reject {}));
|
||||
|
||||
working_set.render()
|
||||
};
|
||||
@ -102,7 +104,7 @@ mod test {
|
||||
.merge_delta(delta)
|
||||
.expect("Error merging delta");
|
||||
|
||||
let cmd = r#"'[[a, b]; [1, 2]]' | metadata set --content-type 'application/x-nuon' --datasource-ls | from nuon | metadata | $in"#;
|
||||
let cmd = r#"'[[a, b]; [1, 2]]' | metadata set --content-type 'application/x-nuon' --datasource-ls | from nuon | metadata | reject span | $in"#;
|
||||
let result = eval_pipeline_without_terminal_expression(
|
||||
cmd,
|
||||
std::env::temp_dir().as_ref(),
|
||||
|
@ -145,6 +145,7 @@ pub fn convert_string_to_value(string_input: String, span: Span) -> Result<Value
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::Reject;
|
||||
use crate::{Metadata, MetadataSet};
|
||||
|
||||
use super::*;
|
||||
@ -345,6 +346,7 @@ mod tests {
|
||||
working_set.add_decl(Box::new(FromToml {}));
|
||||
working_set.add_decl(Box::new(Metadata {}));
|
||||
working_set.add_decl(Box::new(MetadataSet {}));
|
||||
working_set.add_decl(Box::new(Reject {}));
|
||||
|
||||
working_set.render()
|
||||
};
|
||||
@ -353,7 +355,7 @@ mod tests {
|
||||
.merge_delta(delta)
|
||||
.expect("Error merging delta");
|
||||
|
||||
let cmd = r#""[a]\nb = 1\nc = 1" | metadata set --content-type 'text/x-toml' --datasource-ls | from toml | metadata | $in"#;
|
||||
let cmd = r#""[a]\nb = 1\nc = 1" | metadata set --content-type 'text/x-toml' --datasource-ls | from toml | metadata | reject span | $in"#;
|
||||
let result = eval_pipeline_without_terminal_expression(
|
||||
cmd,
|
||||
std::env::temp_dir().as_ref(),
|
||||
|
@ -160,6 +160,7 @@ fn from_tsv(
|
||||
mod test {
|
||||
use nu_cmd_lang::eval_pipeline_without_terminal_expression;
|
||||
|
||||
use crate::Reject;
|
||||
use crate::{Metadata, MetadataSet};
|
||||
|
||||
use super::*;
|
||||
@ -180,6 +181,7 @@ mod test {
|
||||
working_set.add_decl(Box::new(FromTsv {}));
|
||||
working_set.add_decl(Box::new(Metadata {}));
|
||||
working_set.add_decl(Box::new(MetadataSet {}));
|
||||
working_set.add_decl(Box::new(Reject {}));
|
||||
|
||||
working_set.render()
|
||||
};
|
||||
@ -188,7 +190,7 @@ mod test {
|
||||
.merge_delta(delta)
|
||||
.expect("Error merging delta");
|
||||
|
||||
let cmd = r#""a\tb\n1\t2" | metadata set --content-type 'text/tab-separated-values' --datasource-ls | from tsv | metadata | $in"#;
|
||||
let cmd = r#""a\tb\n1\t2" | metadata set --content-type 'text/tab-separated-values' --datasource-ls | from tsv | metadata | reject span | $in"#;
|
||||
let result = eval_pipeline_without_terminal_expression(
|
||||
cmd,
|
||||
std::env::temp_dir().as_ref(),
|
||||
|
@ -370,6 +370,7 @@ fn make_xml_error_spanned(msg: impl Into<String>, src: String, pos: TextPos) ->
|
||||
mod tests {
|
||||
use crate::Metadata;
|
||||
use crate::MetadataSet;
|
||||
use crate::Reject;
|
||||
|
||||
use super::*;
|
||||
|
||||
@ -541,6 +542,7 @@ mod tests {
|
||||
working_set.add_decl(Box::new(FromXml {}));
|
||||
working_set.add_decl(Box::new(Metadata {}));
|
||||
working_set.add_decl(Box::new(MetadataSet {}));
|
||||
working_set.add_decl(Box::new(Reject {}));
|
||||
|
||||
working_set.render()
|
||||
};
|
||||
@ -552,7 +554,7 @@ mod tests {
|
||||
let cmd = r#"'<?xml version="1.0" encoding="UTF-8"?>
|
||||
<note>
|
||||
<remember>Event</remember>
|
||||
</note>' | metadata set --content-type 'application/xml' --datasource-ls | from xml | metadata | $in"#;
|
||||
</note>' | metadata set --content-type 'application/xml' --datasource-ls | from xml | metadata | reject span | $in"#;
|
||||
let result = eval_pipeline_without_terminal_expression(
|
||||
cmd,
|
||||
std::env::temp_dir().as_ref(),
|
||||
|
@ -243,6 +243,7 @@ fn from_yaml(input: PipelineData, head: Span) -> Result<PipelineData, ShellError
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use crate::Reject;
|
||||
use crate::{Metadata, MetadataSet};
|
||||
|
||||
use super::*;
|
||||
@ -409,6 +410,7 @@ mod test {
|
||||
working_set.add_decl(Box::new(FromYaml {}));
|
||||
working_set.add_decl(Box::new(Metadata {}));
|
||||
working_set.add_decl(Box::new(MetadataSet {}));
|
||||
working_set.add_decl(Box::new(Reject {}));
|
||||
|
||||
working_set.render()
|
||||
};
|
||||
@ -417,7 +419,7 @@ mod test {
|
||||
.merge_delta(delta)
|
||||
.expect("Error merging delta");
|
||||
|
||||
let cmd = r#""a: 1\nb: 2" | metadata set --content-type 'application/yaml' --datasource-ls | from yaml | metadata | $in"#;
|
||||
let cmd = r#""a: 1\nb: 2" | metadata set --content-type 'application/yaml' --datasource-ls | from yaml | metadata | reject span | $in"#;
|
||||
let result = eval_pipeline_without_terminal_expression(
|
||||
cmd,
|
||||
std::env::temp_dir().as_ref(),
|
||||
|
@ -166,14 +166,14 @@ mod test {
|
||||
.merge_delta(delta)
|
||||
.expect("Error merging delta");
|
||||
|
||||
let cmd = "{a: 1 b: 2} | to csv | metadata | get content_type";
|
||||
let cmd = "{a: 1 b: 2} | to csv | metadata | get content_type | $in";
|
||||
let result = eval_pipeline_without_terminal_expression(
|
||||
cmd,
|
||||
std::env::temp_dir().as_ref(),
|
||||
&mut engine_state,
|
||||
);
|
||||
assert_eq!(
|
||||
Value::test_record(record!("content_type" => Value::test_string("text/csv"))),
|
||||
Value::test_string("text/csv"),
|
||||
result.expect("There should be a result")
|
||||
);
|
||||
}
|
||||
|
@ -229,14 +229,14 @@ mod test {
|
||||
.merge_delta(delta)
|
||||
.expect("Error merging delta");
|
||||
|
||||
let cmd = "{a: 1 b: 2} | to json | metadata | get content_type";
|
||||
let cmd = "{a: 1 b: 2} | to json | metadata | get content_type | $in";
|
||||
let result = eval_pipeline_without_terminal_expression(
|
||||
cmd,
|
||||
std::env::temp_dir().as_ref(),
|
||||
&mut engine_state,
|
||||
);
|
||||
assert_eq!(
|
||||
Value::test_record(record!("content_type" => Value::test_string("application/json"))),
|
||||
Value::test_string("application/json"),
|
||||
result.expect("There should be a result")
|
||||
);
|
||||
}
|
||||
|
@ -904,14 +904,14 @@ mod tests {
|
||||
.merge_delta(delta)
|
||||
.expect("Error merging delta");
|
||||
|
||||
let cmd = "{a: 1 b: 2} | to md | metadata | get content_type";
|
||||
let cmd = "{a: 1 b: 2} | to md | metadata | get content_type | $in";
|
||||
let result = eval_pipeline_without_terminal_expression(
|
||||
cmd,
|
||||
std::env::temp_dir().as_ref(),
|
||||
&mut engine_state,
|
||||
);
|
||||
assert_eq!(
|
||||
Value::test_record(record!("content_type" => Value::test_string("text/markdown"))),
|
||||
Value::test_string("text/markdown"),
|
||||
result.expect("There should be a result")
|
||||
);
|
||||
}
|
||||
|
@ -348,16 +348,14 @@ mod test {
|
||||
.merge_delta(delta)
|
||||
.expect("Error merging delta");
|
||||
|
||||
let cmd = "{a: 1 b: 2} | to msgpack | metadata | get content_type";
|
||||
let cmd = "{a: 1 b: 2} | to msgpack | metadata | get content_type | $in";
|
||||
let result = eval_pipeline_without_terminal_expression(
|
||||
cmd,
|
||||
std::env::temp_dir().as_ref(),
|
||||
&mut engine_state,
|
||||
);
|
||||
assert_eq!(
|
||||
Value::test_record(
|
||||
record!("content_type" => Value::test_string("application/x-msgpack"))
|
||||
),
|
||||
Value::test_string("application/x-msgpack"),
|
||||
result.expect("There should be a result")
|
||||
);
|
||||
}
|
||||
|
@ -143,14 +143,14 @@ mod test {
|
||||
.merge_delta(delta)
|
||||
.expect("Error merging delta");
|
||||
|
||||
let cmd = "{a: 1 b: 2} | to nuon | metadata | get content_type";
|
||||
let cmd = "{a: 1 b: 2} | to nuon | metadata | get content_type | $in";
|
||||
let result = eval_pipeline_without_terminal_expression(
|
||||
cmd,
|
||||
std::env::temp_dir().as_ref(),
|
||||
&mut engine_state,
|
||||
);
|
||||
assert_eq!(
|
||||
Value::test_record(record!("content_type" => Value::test_string("application/x-nuon"))),
|
||||
Value::test_string("application/x-nuon"),
|
||||
result.expect("There should be a result")
|
||||
);
|
||||
}
|
||||
|
@ -273,14 +273,14 @@ mod test {
|
||||
.merge_delta(delta)
|
||||
.expect("Error merging delta");
|
||||
|
||||
let cmd = "{a: 1 b: 2} | to text | metadata | get content_type";
|
||||
let cmd = "{a: 1 b: 2} | to text | metadata | get content_type | $in";
|
||||
let result = eval_pipeline_without_terminal_expression(
|
||||
cmd,
|
||||
std::env::temp_dir().as_ref(),
|
||||
&mut engine_state,
|
||||
);
|
||||
assert_eq!(
|
||||
Value::test_record(record!("content_type" => Value::test_string("text/plain"))),
|
||||
Value::test_string("text/plain"),
|
||||
result.expect("There should be a result")
|
||||
);
|
||||
}
|
||||
|
@ -132,16 +132,14 @@ mod test {
|
||||
.merge_delta(delta)
|
||||
.expect("Error merging delta");
|
||||
|
||||
let cmd = "{a: 1 b: 2} | to tsv | metadata | get content_type";
|
||||
let cmd = "{a: 1 b: 2} | to tsv | metadata | get content_type | $in";
|
||||
let result = eval_pipeline_without_terminal_expression(
|
||||
cmd,
|
||||
std::env::temp_dir().as_ref(),
|
||||
&mut engine_state,
|
||||
);
|
||||
assert_eq!(
|
||||
Value::test_record(
|
||||
record!("content_type" => Value::test_string("text/tab-separated-values"))
|
||||
),
|
||||
Value::test_string("text/tab-separated-values"),
|
||||
result.expect("There should be a result")
|
||||
);
|
||||
}
|
||||
|
@ -538,14 +538,14 @@ mod test {
|
||||
.merge_delta(delta)
|
||||
.expect("Error merging delta");
|
||||
|
||||
let cmd = "{tag: note attributes: {} content : [{tag: remember attributes: {} content : [{tag: null attributes: null content : Event}]}]} | to xml | metadata | get content_type";
|
||||
let cmd = "{tag: note attributes: {} content : [{tag: remember attributes: {} content : [{tag: null attributes: null content : Event}]}]} | to xml | metadata | get content_type | $in";
|
||||
let result = eval_pipeline_without_terminal_expression(
|
||||
cmd,
|
||||
std::env::temp_dir().as_ref(),
|
||||
&mut engine_state,
|
||||
);
|
||||
assert_eq!(
|
||||
Value::test_record(record!("content_type" => Value::test_string("application/xml"))),
|
||||
Value::test_string("application/xml"),
|
||||
result.expect("There should be a result")
|
||||
);
|
||||
}
|
||||
|
@ -233,14 +233,14 @@ mod test {
|
||||
.merge_delta(delta)
|
||||
.expect("Error merging delta");
|
||||
|
||||
let cmd = "{a: 1 b: 2} | to yaml | metadata | get content_type";
|
||||
let cmd = "{a: 1 b: 2} | to yaml | metadata | get content_type | $in";
|
||||
let result = eval_pipeline_without_terminal_expression(
|
||||
cmd,
|
||||
std::env::temp_dir().as_ref(),
|
||||
&mut engine_state,
|
||||
);
|
||||
assert_eq!(
|
||||
Value::test_record(record!("content_type" => Value::test_string("application/yaml"))),
|
||||
Value::test_string("application/yaml"),
|
||||
result.expect("There should be a result")
|
||||
);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
//! [`Span`] to point to sections of source code and the [`Spanned`] wrapper type
|
||||
use crate::SpanId;
|
||||
use crate::{IntoValue, SpanId, Value, record};
|
||||
use miette::SourceSpan;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::ops::Deref;
|
||||
@ -277,6 +277,16 @@ impl Span {
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoValue for Span {
|
||||
fn into_value(self, span: Span) -> Value {
|
||||
let record = record! {
|
||||
"start" => Value::int(self.start as i64, self),
|
||||
"end" => Value::int(self.end as i64, self),
|
||||
};
|
||||
record.into_value(span)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Span> for SourceSpan {
|
||||
fn from(s: Span) -> Self {
|
||||
Self::new(s.start.into(), s.end - s.start)
|
||||
|
Reference in New Issue
Block a user