use std::cmp::max; #[cfg(doc)] use crate::func::*; #[cfg(doc)] use crate::rcore::*; #[cfg(doc)] use super::*; /// Represents width (concurrency/throughput) and length (time/latency). /// Use [`WithLengthAndWidth::length`] and [`WithLengthAndWidth::width`] to access them. pub struct WithLengthAndWidth { length: usize, width: usize, value: T, } /// Rendered trace that can be broken down neither in width nor in length. pub enum RenderedCommon { /// No resolutions are involved in getting the value. /// /// Usually, a result of [`Pure::pure`]. /// /// Represented as 0x0 by default. /// /// Normally, is either at the root of the trace or wrapped into [`RenderedCommon::Action`]. Empty, /// Exactly one resolution is involved in getting the value. /// /// Usually, a result of [`Traceable::trace`]. /// /// Represented as 1x1 by default. Resolution, /// Arbitrary event for [Diagnostic]s. /// /// Usually, a result of [`Diagnostic::after`]/[`Diagnostic::before`]. /// /// Represented as 0x0 by default. Event(String), /// Named action for [Diagnostic]s. /// /// Usually, a result of [`Diagnostic::wrapped`]. /// /// Represented with the same dimensions as the wrapped trace by default. Action { name: String, rendered: Box>, }, } /// Rendered trace that cannot be broken down in length. pub enum RenderedWide { /// See [`RenderedCommon`]. Common(RenderedCommon), /// Trace can be broken down in width. Wide(Vec>), } /// Rendered trace that cannot be broken down in width. pub enum RenderedLong { /// See [`RenderedCommon`]. Common(RenderedCommon), /// Trace can be broken down in length. Long(Vec>), } /// Represents an arbitrary rendered trace. pub enum RenderedAny { /// See [`RenderedCommon`]. Common(RenderedCommon), /// Trace can be broken down in width. Wide(Vec>), /// Trace can be broken down in length. Long(Vec>), } impl WithLengthAndWidth { pub fn push_into(self, vec: &mut WithLengthAndWidth>>) { vec.length += self.length; vec.width = max(vec.width, self.width); vec.value.push(self); } pub fn any(self) -> WithLengthAndWidth { self.map(RenderedWide::any) } } impl WithLengthAndWidth { pub fn push_into(self, vec: &mut WithLengthAndWidth>>) { vec.width += self.width; vec.length = max(vec.length, self.length); vec.value.push(self); } pub fn any(self) -> WithLengthAndWidth { self.map(RenderedLong::any) } } impl RenderedWide { fn any(self) -> RenderedAny { match self { Self::Common(common) => RenderedAny::Common(common), Self::Wide(vec) => RenderedAny::Wide(vec), } } } impl RenderedLong { fn any(self) -> RenderedAny { match self { Self::Common(common) => RenderedAny::Common(common), Self::Long(vec) => RenderedAny::Long(vec), } } } impl WithLengthAndWidth { pub fn map(self, f: impl FnOnce(A) -> B) -> WithLengthAndWidth { WithLengthAndWidth { length: self.length, width: self.width, value: f(self.value), } } pub fn length(&self) -> usize { self.length } pub fn width(&self) -> usize { self.width } pub fn value(&self) -> &A { &self.value } } impl Default for WithLengthAndWidth { fn default() -> Self { Self { length: 0, width: 0, value: Default::default(), } } } impl WithLengthAndWidth { pub fn wrap(self, name: &str) -> WithLengthAndWidth { WithLengthAndWidth { length: self.length, width: self.width, value: RenderedCommon::Action { name: name.into(), rendered: self.into(), }, } } } impl RenderedCommon { pub fn empty() -> WithLengthAndWidth { WithLengthAndWidth { length: 0, width: 0, value: RenderedCommon::Empty, } } pub fn resolution() -> WithLengthAndWidth { WithLengthAndWidth { length: 1, width: 1, value: RenderedCommon::Resolution, } } pub fn event(event: &str) -> WithLengthAndWidth { WithLengthAndWidth { length: 0, width: 0, value: RenderedCommon::Event(event.into()), } } } impl RenderedCommon { fn rectangles(self, vec: &mut Vec<(usize, usize)>, t: usize, c: usize) { match self { Self::Empty => {} Self::Resolution => vec.push((t, c)), Self::Event(_) => {} Self::Action { rendered, .. } => rendered.rectangles(vec, t, c), } } } impl WithLengthAndWidth { fn rectangles(self, vec: &mut Vec<(usize, usize)>, t: usize, c: usize) { match self.value { RenderedAny::Common(common) => common.rectangles(vec, t, c), RenderedAny::Wide(rendereds) => { let mut c = c; for rendered in rendereds.into_iter().map(|x| x.map(RenderedLong::any)) { let rw = rendered.width; rendered.rectangles(vec, t, c); c += 2 * rw; } } RenderedAny::Long(rendereds) => { let mut t = t; for rendered in rendereds.into_iter().map(|x| x.map(RenderedWide::any)) { let rl = rendered.length; let rw = rendered.width; rendered.rectangles(vec, t, c + (self.width - rw) / 2); t += rl; } } } } pub fn to_vec(self) -> Vec<(usize, usize)> { let mut vec = Vec::new(); self.rectangles(&mut vec, 0, 0); vec } }