use serde::{Deserialize, Serialize};
use std::fmt;
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(tag = "kind", rename_all = "snake_case")]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
pub enum FileOrigin {
NotebookCell {
notebook_path: String,
cell_index: usize,
cell_id: Option<String>,
cell_type: String,
},
}
impl fmt::Display for FileOrigin {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
FileOrigin::NotebookCell {
notebook_path,
cell_index,
cell_type,
..
} => write!(f, "{notebook_path}[cell {cell_index}, {cell_type}]"),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
fn origin() -> FileOrigin {
FileOrigin::NotebookCell {
notebook_path: "notebook.ipynb".into(),
cell_index: 2,
cell_id: Some("abc123".into()),
cell_type: "markdown".into(),
}
}
#[test]
fn display_is_the_cell_qualified_label() {
assert_eq!(origin().to_string(), "notebook.ipynb[cell 2, markdown]");
}
#[test]
fn display_omits_cell_id() {
let no_id = FileOrigin::NotebookCell {
notebook_path: "notebook.ipynb".into(),
cell_index: 2,
cell_id: None,
cell_type: "markdown".into(),
};
assert_eq!(no_id.to_string(), origin().to_string());
}
#[test]
fn serde_round_trip_keeps_all_fields() {
let json = serde_json::to_string(&origin()).unwrap();
assert_eq!(
json,
r#"{"kind":"notebook_cell","notebook_path":"notebook.ipynb","cell_index":2,"cell_id":"abc123","cell_type":"markdown"}"#
);
let back: FileOrigin = serde_json::from_str(&json).unwrap();
assert_eq!(back, origin());
}
#[test]
fn serde_round_trip_without_cell_id() {
let o = FileOrigin::NotebookCell {
notebook_path: "n.ipynb".into(),
cell_index: 7,
cell_id: None,
cell_type: "code".into(),
};
let back: FileOrigin = serde_json::from_str(&serde_json::to_string(&o).unwrap()).unwrap();
assert_eq!(back, o);
}
}