vimwiki_core/lang/elements/blocks/
code.rs

1use crate::StrictEq;
2use derive_more::{Constructor, Index, IndexMut, IntoIterator};
3use serde::{Deserialize, Serialize};
4use std::{borrow::Cow, collections::HashMap, iter::FromIterator};
5
6#[derive(
7    Constructor,
8    Clone,
9    Debug,
10    Eq,
11    PartialEq,
12    Index,
13    IndexMut,
14    IntoIterator,
15    Serialize,
16    Deserialize,
17)]
18pub struct CodeBlock<'a> {
19    /// Represents the language associated with the code block if it has one
20    pub language: Option<Cow<'a, str>>,
21
22    /// Represents metadata associated with the code block in the form of
23    /// key/value pairs
24    pub metadata: HashMap<Cow<'a, str>, Cow<'a, str>>,
25
26    /// Represents the lines of text contained within the code block
27    #[index]
28    #[index_mut]
29    #[into_iterator(owned, ref, ref_mut)]
30    pub lines: Vec<Cow<'a, str>>,
31}
32
33impl<'a> CodeBlock<'a> {
34    /// Constructs a code block with the provided lines using no language or metadata
35    pub fn from_lines<I: IntoIterator<Item = L>, L: Into<Cow<'a, str>>>(
36        iter: I,
37    ) -> Self {
38        Self {
39            language: None,
40            metadata: HashMap::new(),
41            lines: iter.into_iter().map(Into::into).collect(),
42        }
43    }
44}
45
46impl CodeBlock<'_> {
47    pub fn to_borrowed(&self) -> CodeBlock {
48        use self::Cow::*;
49
50        CodeBlock {
51            language: self.language.as_ref().map(|x| {
52                Cow::Borrowed(match x {
53                    Borrowed(x) => *x,
54                    Owned(x) => x.as_str(),
55                })
56            }),
57            metadata: self
58                .metadata
59                .iter()
60                .map(|(key, value)| {
61                    let key = Cow::Borrowed(match key {
62                        Borrowed(x) => *x,
63                        Owned(x) => x.as_str(),
64                    });
65                    let value = Cow::Borrowed(match value {
66                        Borrowed(x) => *x,
67                        Owned(x) => x.as_str(),
68                    });
69
70                    (key, value)
71                })
72                .collect(),
73            lines: self
74                .lines
75                .iter()
76                .map(|x| {
77                    Cow::Borrowed(match x {
78                        Borrowed(x) => *x,
79                        Owned(x) => x.as_str(),
80                    })
81                })
82                .collect(),
83        }
84    }
85
86    pub fn into_owned(self) -> CodeBlock<'static> {
87        CodeBlock {
88            language: self.language.map(|x| Cow::from(x.into_owned())),
89            metadata: self
90                .metadata
91                .into_iter()
92                .map(|(key, value)| {
93                    (Cow::from(key.into_owned()), Cow::from(value.into_owned()))
94                })
95                .collect(),
96            lines: self
97                .lines
98                .into_iter()
99                .map(|x| Cow::from(x.into_owned()))
100                .collect(),
101        }
102    }
103}
104
105impl<'a> FromIterator<&'a str> for CodeBlock<'a> {
106    /// Produces a new code block using the given iterator as the
107    /// code block's lines
108    fn from_iter<I: IntoIterator<Item = &'a str>>(iter: I) -> Self {
109        Self::from_lines(iter)
110    }
111}
112
113impl FromIterator<String> for CodeBlock<'static> {
114    /// Produces a new code block using the given iterator as the
115    /// code block's lines
116    fn from_iter<I: IntoIterator<Item = String>>(iter: I) -> Self {
117        Self::from_lines(iter)
118    }
119}
120
121impl<'a> FromIterator<Cow<'a, str>> for CodeBlock<'a> {
122    /// Produces a new code block using the given iterator as the
123    /// code block's lines
124    fn from_iter<I: IntoIterator<Item = Cow<'a, str>>>(iter: I) -> Self {
125        Self::from_lines(iter)
126    }
127}
128
129impl<'a> StrictEq for CodeBlock<'a> {
130    /// Same as PartialEq
131    fn strict_eq(&self, other: &Self) -> bool {
132        self == other
133    }
134}