use serde::{Deserialize, Serialize};
use serde_json::Value;
use serde_with::skip_serializing_none;
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
#[serde(deny_unknown_fields)]
pub struct RawNotebook {
pub cells: Vec<Cell>,
pub metadata: Value,
pub nbformat: i64,
pub nbformat_minor: i64,
}
pub const ID_OPTIONAL_MAX_VERSION: i64 = 4;
impl RawNotebook {
pub fn new() -> Self {
Self {
cells: Vec::new(),
metadata: Value::Null,
nbformat: 4,
nbformat_minor: 5,
}
}
}
impl Default for RawNotebook {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
#[serde(tag = "cell_type")]
pub enum Cell {
#[serde(rename = "code")]
Code(CodeCell),
#[serde(rename = "markdown")]
Markdown(MarkdownCell),
#[serde(rename = "raw")]
Raw(RawCell),
}
#[skip_serializing_none]
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
#[serde(deny_unknown_fields)]
pub struct RawCell {
pub attachments: Option<Value>,
pub id: Option<String>,
pub metadata: Value,
pub source: SourceValue,
}
#[skip_serializing_none]
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
#[serde(deny_unknown_fields)]
pub struct MarkdownCell {
pub attachments: Option<Value>,
pub id: Option<String>,
pub metadata: Value,
pub source: SourceValue,
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
#[serde(deny_unknown_fields)]
pub struct CodeCell {
pub execution_count: Option<i64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub id: Option<String>,
pub metadata: Value,
pub outputs: Vec<Value>,
pub source: SourceValue,
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
#[serde(untagged)]
pub enum SourceValue {
String(String),
StringArray(Vec<String>),
}
#[allow(clippy::unwrap_used)]
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_cell_types() {
let empty_nb_str = r##"{
"cells": [
{
"cell_type": "code",
"execution_count": 123,
"metadata": {},
"outputs": [],
"source": [
"print(\"hello world\")",
"print(\"goodbye\")"
]
},
{
"cell_type": "raw",
"metadata": {},
"source": [
"I am a raw cell"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": "# Welcome to the documentation"
}
],
"metadata": {},
"nbformat": 4,
"nbformat_minor": 5
}"##;
let mut parsed: RawNotebook = serde_json::from_str(empty_nb_str).unwrap();
let [code, raw, Cell::Markdown(markdown)] = &mut parsed.cells[..] else {
panic!();
};
let code = code.as_codecell_mut().unwrap();
assert!(raw.as_codecell().is_none());
assert!(matches!(raw, Cell::Raw(_)));
assert!(matches!(raw.get_source(), SourceValue::StringArray(_)));
assert!(matches!(markdown.source, SourceValue::String(_)));
assert!(code.is_clear_outputs());
assert!(!code.is_clear_exec_count());
assert!(code.should_clear_output(true, true));
code.clear_counts();
code.clear_outputs();
assert!(code.is_clear_outputs());
assert!(code.is_clear_exec_count());
}
}