radn-rs/src/rstd/tracing/rendered.rs
2023-06-16 07:53:07 +00:00

232 lines
6.2 KiB
Rust

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<T> {
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<WithLengthAndWidth<RenderedAny>>,
},
}
/// 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<WithLengthAndWidth<RenderedLong>>),
}
/// 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<WithLengthAndWidth<RenderedWide>>),
}
/// Represents an arbitrary rendered trace.
pub enum RenderedAny {
/// See [`RenderedCommon`].
Common(RenderedCommon),
/// Trace can be broken down in width.
Wide(Vec<WithLengthAndWidth<RenderedLong>>),
/// Trace can be broken down in length.
Long(Vec<WithLengthAndWidth<RenderedWide>>),
}
impl WithLengthAndWidth<RenderedWide> {
pub fn push_into(self, vec: &mut WithLengthAndWidth<Vec<WithLengthAndWidth<RenderedWide>>>) {
vec.length += self.length;
vec.width = max(vec.width, self.width);
vec.value.push(self);
}
pub fn any(self) -> WithLengthAndWidth<RenderedAny> {
self.map(RenderedWide::any)
}
}
impl WithLengthAndWidth<RenderedLong> {
pub fn push_into(self, vec: &mut WithLengthAndWidth<Vec<WithLengthAndWidth<RenderedLong>>>) {
vec.width += self.width;
vec.length = max(vec.length, self.length);
vec.value.push(self);
}
pub fn any(self) -> WithLengthAndWidth<RenderedAny> {
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<A> WithLengthAndWidth<A> {
pub fn map<B>(self, f: impl FnOnce(A) -> B) -> WithLengthAndWidth<B> {
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<A: Default> Default for WithLengthAndWidth<A> {
fn default() -> Self {
Self {
length: 0,
width: 0,
value: Default::default(),
}
}
}
impl WithLengthAndWidth<RenderedAny> {
pub fn wrap(self, name: &str) -> WithLengthAndWidth<RenderedCommon> {
WithLengthAndWidth {
length: self.length,
width: self.width,
value: RenderedCommon::Action {
name: name.into(),
rendered: self.into(),
},
}
}
}
impl RenderedCommon {
pub fn empty() -> WithLengthAndWidth<Self> {
WithLengthAndWidth {
length: 0,
width: 0,
value: RenderedCommon::Empty,
}
}
pub fn resolution() -> WithLengthAndWidth<Self> {
WithLengthAndWidth {
length: 1,
width: 1,
value: RenderedCommon::Resolution,
}
}
pub fn event(event: &str) -> WithLengthAndWidth<Self> {
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<RenderedAny> {
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
}
}