mod bubble;
mod category;
mod date_axis;
mod xy;
pub use bubble::{BubbleChartData, BubbleDataPoint, BubbleSeriesData};
pub use category::{
CategoryChartData, CategorySeriesData, ComboChartData, ComboSeriesData, ComboSeriesType,
};
pub use date_axis::DateAxisChartData;
pub use xy::{XyChartData, XyDataPoint, XySeriesData};
#[derive(Debug, Clone)]
pub struct Category {
pub idx: usize,
pub label: String,
pub children: Vec<Category>,
}
#[derive(Debug, Clone)]
pub struct CategoryLevel {
pub(crate) categories: Vec<Category>,
}
impl CategoryLevel {
#[must_use]
pub fn categories(&self) -> &[Category] {
&self.categories
}
pub fn iter(&self) -> std::slice::Iter<'_, Category> {
self.categories.iter()
}
#[must_use]
pub fn len(&self) -> usize {
self.categories.len()
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.categories.is_empty()
}
}
impl<'a> IntoIterator for &'a CategoryLevel {
type Item = &'a Category;
type IntoIter = std::slice::Iter<'a, Category>;
fn into_iter(self) -> Self::IntoIter {
self.categories.iter()
}
}
#[derive(Debug, Clone)]
pub struct Categories {
pub(crate) levels: Vec<CategoryLevel>,
}
impl Categories {
#[must_use]
pub fn depth(&self) -> usize {
self.levels.len()
}
#[must_use]
pub fn levels(&self) -> &[CategoryLevel] {
&self.levels
}
pub fn iter(&self) -> std::slice::Iter<'_, Category> {
if self.levels.is_empty() {
[].iter()
} else {
self.levels[0].categories.iter()
}
}
#[must_use]
pub fn flattened_labels(&self) -> Vec<Vec<String>> {
if self.levels.is_empty() {
return Vec::new();
}
let count = self.levels[0].categories.len();
let mut result = Vec::with_capacity(count);
for i in 0..count {
let mut tuple = Vec::with_capacity(self.levels.len());
for level in &self.levels {
let label = level
.categories
.get(i)
.map(|c| c.label.clone())
.unwrap_or_default();
tuple.push(label);
}
result.push(tuple);
}
result
}
}
impl<'a> IntoIterator for &'a Categories {
type Item = &'a Category;
type IntoIter = std::slice::Iter<'a, Category>;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
#[cfg(test)]
mod tests;