nu_protocol/pipeline/metadata.rs
1use std::path::PathBuf;
2
3use serde::{Deserialize, Serialize};
4
5use crate::Record;
6
7/// Metadata that is valid for the whole [`PipelineData`](crate::PipelineData)
8///
9/// ## Custom Metadata
10///
11/// The `custom` field allows commands and plugins to attach arbitrary metadata to pipeline data.
12/// To avoid key collisions, it is recommended to use namespaced keys with an underscore separator:
13///
14/// - `"http_response"` - HTTP response metadata (status, headers, etc.)
15/// - `"polars_schema"` - DataFrame schema information
16/// - `"custom_plugin_field"` - Plugin-specific metadata
17///
18/// This convention helps ensure different commands and plugins don't overwrite each other's metadata.
19#[derive(Clone, Debug, Default, Deserialize, PartialEq, Serialize)]
20pub struct PipelineMetadata {
21 pub data_source: DataSource,
22 pub content_type: Option<String>,
23 #[serde(default)]
24 pub custom: Record,
25}
26
27impl PipelineMetadata {
28 pub fn with_data_source(self, data_source: DataSource) -> Self {
29 Self {
30 data_source,
31 ..self
32 }
33 }
34
35 pub fn with_content_type(self, content_type: Option<String>) -> Self {
36 Self {
37 content_type,
38 ..self
39 }
40 }
41
42 /// Transform metadata for the `collect` operation.
43 ///
44 /// After collecting a stream into a value, `FilePath` data sources are no longer meaningful
45 /// and should be converted to `None`. If all metadata fields become empty after this
46 /// transformation, returns `None` to avoid carrying around empty metadata.
47 pub fn for_collect(self) -> Option<Self> {
48 let Self {
49 data_source,
50 content_type,
51 custom,
52 } = self;
53
54 // Transform FilePath to None after collect
55 let data_source = match data_source {
56 DataSource::FilePath(_) => DataSource::None,
57 other => other,
58 };
59
60 // Return None if completely empty
61 if matches!(data_source, DataSource::None) && content_type.is_none() && custom.is_empty() {
62 None
63 } else {
64 Some(Self {
65 data_source,
66 content_type,
67 custom,
68 })
69 }
70 }
71}
72
73/// Describes where the particular [`PipelineMetadata`] originates.
74///
75/// This can either be a particular family of commands (useful so downstream commands can adjust
76/// the presentation e.g. `Ls`) or the opened file to protect against overwrite-attempts properly.
77#[derive(Clone, Debug, Default, Deserialize, PartialEq, Serialize)]
78pub enum DataSource {
79 Ls,
80 HtmlThemes,
81 FilePath(PathBuf),
82 #[default]
83 None,
84}