use crate::output::{MultilineString, Output};
use indexmap::IndexMap;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(tag = "cell_type", rename_all = "lowercase")]
pub enum Cell {
Code {
source: MultilineString,
execution_count: Option<u32>,
#[serde(default)]
outputs: Vec<Output>,
#[serde(default)]
metadata: CellMetadata,
#[serde(skip_serializing_if = "Option::is_none")]
id: Option<String>,
},
Markdown {
source: MultilineString,
#[serde(default)]
metadata: CellMetadata,
#[serde(skip_serializing_if = "Option::is_none")]
id: Option<String>,
},
Raw {
source: MultilineString,
#[serde(default)]
metadata: CellMetadata,
#[serde(skip_serializing_if = "Option::is_none")]
id: Option<String>,
},
}
impl Cell {
pub fn code(source: impl Into<String>) -> Self {
Cell::Code {
source: MultilineString::from_string(source.into()),
execution_count: None,
outputs: Vec::new(),
metadata: CellMetadata::default(),
id: None,
}
}
pub fn markdown(source: impl Into<String>) -> Self {
Cell::Markdown {
source: MultilineString::from_string(source.into()),
metadata: CellMetadata::default(),
id: None,
}
}
pub fn raw(source: impl Into<String>) -> Self {
Cell::Raw {
source: MultilineString::from_string(source.into()),
metadata: CellMetadata::default(),
id: None,
}
}
pub fn source(&self) -> &MultilineString {
match self {
Cell::Code { source, .. } => source,
Cell::Markdown { source, .. } => source,
Cell::Raw { source, .. } => source,
}
}
pub fn source_string(&self) -> String {
self.source().as_string()
}
pub fn metadata(&self) -> &CellMetadata {
match self {
Cell::Code { metadata, .. } => metadata,
Cell::Markdown { metadata, .. } => metadata,
Cell::Raw { metadata, .. } => metadata,
}
}
pub fn id(&self) -> Option<&str> {
match self {
Cell::Code { id, .. } => id.as_deref(),
Cell::Markdown { id, .. } => id.as_deref(),
Cell::Raw { id, .. } => id.as_deref(),
}
}
pub fn is_code(&self) -> bool {
matches!(self, Cell::Code { .. })
}
pub fn is_markdown(&self) -> bool {
matches!(self, Cell::Markdown { .. })
}
pub fn is_raw(&self) -> bool {
matches!(self, Cell::Raw { .. })
}
pub fn outputs(&self) -> Option<&Vec<Output>> {
match self {
Cell::Code { outputs, .. } => Some(outputs),
_ => None,
}
}
pub fn execution_count(&self) -> Option<u32> {
match self {
Cell::Code {
execution_count, ..
} => *execution_count,
_ => None,
}
}
}
#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
pub struct CellMetadata {
#[serde(skip_serializing_if = "Option::is_none")]
pub tags: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub collapsed: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub scrolled: Option<ScrolledState>,
#[serde(skip_serializing_if = "Option::is_none")]
pub name: Option<String>,
#[serde(flatten)]
pub extra: IndexMap<String, serde_json::Value>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(untagged)]
pub enum ScrolledState {
Bool(bool),
String(String),
}