use crate::StrictEq;
use derive_more::{Constructor, Index, IndexMut, IntoIterator};
use serde::{Deserialize, Serialize};
use std::{borrow::Cow, collections::HashMap, iter::FromIterator};
#[derive(
Constructor,
Clone,
Debug,
Eq,
PartialEq,
Index,
IndexMut,
IntoIterator,
Serialize,
Deserialize,
)]
pub struct CodeBlock<'a> {
pub language: Option<Cow<'a, str>>,
pub metadata: HashMap<Cow<'a, str>, Cow<'a, str>>,
#[index]
#[index_mut]
#[into_iterator(owned, ref, ref_mut)]
pub lines: Vec<Cow<'a, str>>,
}
impl<'a> CodeBlock<'a> {
pub fn from_lines<I: IntoIterator<Item = L>, L: Into<Cow<'a, str>>>(
iter: I,
) -> Self {
Self {
language: None,
metadata: HashMap::new(),
lines: iter.into_iter().map(Into::into).collect(),
}
}
}
impl CodeBlock<'_> {
pub fn to_borrowed(&self) -> CodeBlock {
use self::Cow::*;
CodeBlock {
language: self.language.as_ref().map(|x| {
Cow::Borrowed(match x {
Borrowed(x) => *x,
Owned(x) => x.as_str(),
})
}),
metadata: self
.metadata
.iter()
.map(|(key, value)| {
let key = Cow::Borrowed(match key {
Borrowed(x) => *x,
Owned(x) => x.as_str(),
});
let value = Cow::Borrowed(match value {
Borrowed(x) => *x,
Owned(x) => x.as_str(),
});
(key, value)
})
.collect(),
lines: self
.lines
.iter()
.map(|x| {
Cow::Borrowed(match x {
Borrowed(x) => *x,
Owned(x) => x.as_str(),
})
})
.collect(),
}
}
pub fn into_owned(self) -> CodeBlock<'static> {
CodeBlock {
language: self.language.map(|x| Cow::from(x.into_owned())),
metadata: self
.metadata
.into_iter()
.map(|(key, value)| {
(Cow::from(key.into_owned()), Cow::from(value.into_owned()))
})
.collect(),
lines: self
.lines
.into_iter()
.map(|x| Cow::from(x.into_owned()))
.collect(),
}
}
}
impl<'a> FromIterator<&'a str> for CodeBlock<'a> {
fn from_iter<I: IntoIterator<Item = &'a str>>(iter: I) -> Self {
Self::from_lines(iter)
}
}
impl FromIterator<String> for CodeBlock<'static> {
fn from_iter<I: IntoIterator<Item = String>>(iter: I) -> Self {
Self::from_lines(iter)
}
}
impl<'a> FromIterator<Cow<'a, str>> for CodeBlock<'a> {
fn from_iter<I: IntoIterator<Item = Cow<'a, str>>>(iter: I) -> Self {
Self::from_lines(iter)
}
}
impl<'a> StrictEq for CodeBlock<'a> {
fn strict_eq(&self, other: &Self) -> bool {
self == other
}
}