catcolab_document_types/v2/
cell.rs

1use serde::{Deserialize, Serialize};
2use tsify::{Tsify, declare};
3use uuid::Uuid;
4
5use crate::v1;
6
7/// A cell in a notebook.
8///
9/// Unlike [`v1::NotebookCell`], stem cells (placeholders awaiting a chosen
10/// type) are no longer part of the data model.
11#[derive(PartialEq, Eq, Debug, Serialize, Deserialize, Tsify)]
12#[serde(tag = "tag")]
13#[tsify(into_wasm_abi, from_wasm_abi)]
14pub enum NotebookCell<T> {
15    #[serde(rename = "rich-text")]
16    RichText { id: Uuid, content: String },
17    #[serde(rename = "formal")]
18    Formal { id: Uuid, content: T },
19}
20
21#[declare]
22pub type Cell<T> = NotebookCell<T>;
23
24impl<T> NotebookCell<T> {
25    /// Migrate a [`v1::NotebookCell`] to v2.
26    ///
27    /// Stem cells are no longer representable, so attempting to migrate one
28    /// returns `None`. Callers are expected to drop such cells from the
29    /// containing notebook.
30    pub fn migrate_from_v1(old: v1::NotebookCell<T>) -> Option<Self> {
31        match old {
32            v1::NotebookCell::RichText { id, content } => {
33                Some(NotebookCell::RichText { id, content })
34            }
35            v1::NotebookCell::Formal { id, content } => Some(NotebookCell::Formal { id, content }),
36            v1::NotebookCell::Stem { .. } => None,
37        }
38    }
39}
40
41/// Arbitrary instances for property-based testing.
42#[cfg(feature = "property-tests")]
43pub(crate) mod arbitrary {
44    use super::*;
45    use proptest::prelude::*;
46    use uuid::Uuid;
47
48    fn arb_uuid() -> BoxedStrategy<Uuid> {
49        any::<u128>().prop_map(Uuid::from_u128).boxed()
50    }
51
52    /// Strategy for a `NotebookCell<T>` given a strategy for `T`.
53    pub fn arb_notebook_cell<T: std::fmt::Debug + 'static>(
54        arb_t: impl Strategy<Value = T> + Clone + 'static,
55    ) -> BoxedStrategy<NotebookCell<T>> {
56        prop_oneof![
57            (arb_uuid(), any::<String>())
58                .prop_map(|(id, content)| NotebookCell::RichText { id, content }),
59            (arb_uuid(), arb_t).prop_map(|(id, content)| NotebookCell::Formal { id, content }),
60        ]
61        .boxed()
62    }
63}