#![cfg_attr(feature = "json5", doc = r####"
```
use std::fs::File;
let path = "path/to/file.svg";
# let path = concat!(env!("CARGO_MANIFEST_DIR"), "/assets/doc-root-wavejson.svg");
let mut file = File::create(path)?;
wavedrom::render_json5(r##"
{ signal: [
{ name: "clk", wave: "P......" },
{ name: "bus", wave: "x.==.=x", data: ["head", "body", "tail", "data"] },
{ name: "wire", wave: "0.1..0." }
]}
"##, &mut file)?;
# <Result<(), wavedrom::RenderJson5Error>>::Ok(())
```"####)]
#![doc=include_str!("../assets/doc-root-wavejson.svg")]
#![doc=include_str!("../assets/doc-root-programatically.svg")]
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
#![cfg_attr(all(feature = "serde_json", feature = "json5", feature = "serde", feature = "skins"), deny(rustdoc::broken_intra_doc_links))]
#![deny(missing_docs)]
#[cfg(feature = "json5")]
pub use json5;
#[cfg(feature = "serde_json")]
pub use serde_json;
#[cfg(feature = "skins")]
pub mod skin;
mod color;
mod cycle_offset;
pub mod edges;
mod figure;
mod path;
mod shortcuts;
mod signal;
mod svg;
pub use figure::Figure;
pub use color::Color;
pub use cycle_offset::{CycleOffset, InCycleOffset};
pub use shortcuts::*;
pub use signal::Signal;
pub use svg::*;
pub use path::*;
pub mod markers;
#[cfg(feature = "serde")]
pub mod wavejson;
use edges::{
EdgeArrowType, EdgeVariant, LineEdgeMarkers, SharpEdgeVariant,
SplineEdgeVariant,
};
use markers::{ClockEdge, CycleEnumerationMarker, GroupMarker};
#[derive(Debug, Clone)]
pub enum FigureSection {
Signal(Signal),
Group(FigureSectionGroup),
}
#[derive(Debug, Clone)]
pub struct FigureSectionGroup(Option<String>, Vec<FigureSection>);
#[derive(Debug, Clone)]
pub struct AssembledLine<'a> {
text: &'a str,
path: AssembledSignalPath,
}
impl From<Signal> for FigureSection {
fn from(wave: Signal) -> Self {
Self::Signal(wave)
}
}
#[derive(Default, Debug)]
struct DefinitionTracker {
has_undefined: bool,
has_gaps: bool,
has_posedge_marker: bool,
has_negedge_marker: bool,
}
#[derive(Debug)]
pub struct AssembledFigure<'a> {
num_cycles: u32,
hscale: u16,
definitions: DefinitionTracker,
group_label_at_depth: Vec<bool>,
max_group_depth: u32,
header_text: Option<&'a str>,
footer_text: Option<&'a str>,
top_cycle_marker: Option<CycleEnumerationMarker>,
bottom_cycle_marker: Option<CycleEnumerationMarker>,
path_assemble_options: PathAssembleOptions,
lines: Vec<AssembledLine<'a>>,
group_markers: Vec<GroupMarker<'a>>,
line_edge_markers: LineEdgeMarkers<'a>,
}
impl<'a> AssembledFigure<'a> {
#[inline]
fn amount_labels_below(&self, depth: u32) -> u32 {
self.group_label_at_depth
.iter()
.take(depth as usize)
.filter(|x| **x)
.count() as u32
}
#[inline]
pub fn num_cycles(&self) -> u32 {
self.num_cycles
}
#[inline]
pub fn horizontal_scale(&self) -> u16 {
self.hscale
}
#[inline]
pub fn has_undefined(&self) -> bool {
self.definitions.has_undefined
}
#[inline]
pub fn has_gaps(&self) -> bool {
self.definitions.has_gaps
}
#[inline]
pub fn has_posedge_marker(&self) -> bool {
self.definitions.has_posedge_marker
}
#[inline]
pub fn has_negedge_marker(&self) -> bool {
self.definitions.has_negedge_marker
}
#[inline]
pub fn has_group_label_at_depth(&self, depth: u32) -> bool {
let Ok(depth) = usize::try_from(depth) else {
return false;
};
self.group_label_at_depth
.get(depth)
.cloned()
.unwrap_or(false)
}
#[inline]
pub fn group_nesting(&self) -> u32 {
self.max_group_depth
}
#[inline]
pub fn lines(&self) -> &[AssembledLine<'a>] {
&self.lines
}
#[inline]
pub fn group_markers(&self) -> &[GroupMarker<'a>] {
&self.group_markers
}
#[inline]
pub fn header_text(&self) -> Option<&'a str> {
self.header_text
}
#[inline]
pub fn footer_text(&self) -> Option<&'a str> {
self.footer_text
}
#[inline]
pub fn top_cycle_marker(&self) -> Option<CycleEnumerationMarker> {
self.top_cycle_marker
}
#[inline]
pub fn bottom_cycle_marker(&self) -> Option<CycleEnumerationMarker> {
self.bottom_cycle_marker
}
}
impl AssembledLine<'_> {
fn is_empty(&self) -> bool {
self.path.is_empty() && self.text.is_empty()
}
}