use super::*;
#[derive(Debug, Clone, Copy)]
pub struct DataBound<X> {
pub min: X,
pub max: X,
}
#[derive(Debug, Clone)]
pub struct RenderFrameBound {
pub ideal_num_steps: u32,
pub ideal_dash_size: f64,
pub max: f64,
pub axis: Axis,
}
#[derive(Debug, Copy, Clone)]
pub enum Axis {
X,
Y,
}
pub struct IndexRequester<'a> {
counter: &'a mut usize,
}
impl<'a> IndexRequester<'a> {
#[inline(always)]
pub fn new(counter: &'a mut usize) -> Self {
IndexRequester { counter }
}
#[inline(always)]
pub fn request(self) -> usize {
let val = *self.counter;
*self.counter += 1;
val
}
}
use tick_fmt::*;
pub mod tick_fmt {
use super::*;
pub struct DefaultTickFmt;
impl<N: Display> TickFmt<N> for DefaultTickFmt {
fn write_tick(&self, a: &mut dyn std::fmt::Write, val: &N) -> std::fmt::Result {
write!(a, "{}", val)
}
fn write_where(&self, _: &mut dyn std::fmt::Write) -> std::fmt::Result {
Ok(())
}
}
pub trait TickFmt<Num> {
fn write_tick(&self, a: &mut dyn std::fmt::Write, val: &Num) -> std::fmt::Result;
fn write_where(&self, _: &mut dyn std::fmt::Write) -> std::fmt::Result {
Ok(())
}
}
pub struct WithWhereFmt<D, F> {
ticks: D,
func: F,
}
impl<N, D: TickFmt<N>, F, J: fmt::Display> TickFmt<N> for WithWhereFmt<D, F>
where
F: Fn() -> J,
{
fn write_tick(&self, a: &mut dyn std::fmt::Write, val: &N) -> std::fmt::Result {
self.ticks.write_tick(a, val)
}
fn write_where(&self, w: &mut dyn std::fmt::Write) -> std::fmt::Result {
let j = (self.func)();
write!(w, "{}", j)
}
}
pub struct WithTickFmt<D, F> {
ticks: D,
func: F,
}
impl<N, D: TickFmt<N>, F, K: fmt::Display> TickFmt<N> for WithTickFmt<D, F>
where
F: Fn(&N) -> K,
{
fn write_tick(&self, a: &mut dyn std::fmt::Write, val: &N) -> std::fmt::Result {
let j = (self.func)(val);
write!(a, "{}", j)
}
fn write_where(&self, w: &mut dyn std::fmt::Write) -> std::fmt::Result {
self.ticks.write_where(w)
}
}
pub struct WithData<K, E> {
ticks: K,
pub data: E,
}
impl<N, K: TickFmt<N>, E> TickFmt<N> for WithData<K, E> {
fn write_tick(&self, a: &mut dyn std::fmt::Write, val: &N) -> std::fmt::Result {
self.ticks.write_tick(a, val)
}
fn write_where(&self, w: &mut dyn std::fmt::Write) -> std::fmt::Result {
self.ticks.write_where(w)
}
}
impl<X: PlotNum, I: IntoIterator<Item = X>, Fmt: TickFmt<X>> TickDistribution<I, Fmt> {
pub fn with_tick_fmt<F: Fn(&X) -> J, J: fmt::Display>(
self,
func: F,
) -> TickDistribution<I, WithTickFmt<Fmt, F>> {
TickDistribution {
iter: self.iter,
fmt: WithTickFmt {
ticks: self.fmt,
func,
},
res: self.res,
}
}
pub fn with_where_fmt<F: Fn() -> J, J: fmt::Display>(
self,
func: F,
) -> TickDistribution<I, WithWhereFmt<Fmt, F>> {
TickDistribution {
iter: self.iter,
fmt: WithWhereFmt {
ticks: self.fmt,
func,
},
res: self.res,
}
}
pub fn with_data<E>(self, data: E) -> TickDistribution<I, WithData<Fmt, E>> {
TickDistribution {
iter: self.iter,
fmt: WithData {
ticks: self.fmt,
data,
},
res: self.res,
}
}
pub fn with_fmt<J: TickFmt<I::Item>>(self, other: J) -> TickDistribution<I, J> {
TickDistribution {
iter: self.iter,
fmt: other,
res: self.res,
}
}
}
}
impl<X: PlotNum, I: IntoIterator<Item = X>, Fmt: TickFmt<X>> TickDistribution<I, Fmt> {
pub fn from_parts(it: I, fmt: Fmt, res: TickRes) -> Self {
TickDistribution { iter: it, fmt, res }
}
pub fn map<K, F: FnOnce(Self) -> K>(self, func: F) -> K {
func(self)
}
}
pub fn from_closure<N: PlotNum, It, F>(func: F) -> GenTickDistClosure<F>
where
It: TickDist<Num = N>,
F: FnOnce(&DataBound<N>, &RenderFrameBound, IndexRequester) -> It,
{
GenTickDistClosure { func }
}
pub struct GenTickDistClosure<F> {
func: F,
}
impl<N: PlotNum, Res: TickDist<Num = N>, F> TickDistGen<N> for GenTickDistClosure<F>
where
F: FnOnce(&DataBound<N>, &RenderFrameBound, IndexRequester) -> Res,
N: PlotNum,
{
type Res = Res;
fn generate(
self,
data: &ticks::DataBound<N>,
canvas: &RenderFrameBound,
req: IndexRequester,
) -> Res {
(self.func)(data, canvas, req)
}
}
pub struct TickRes {
pub dash_size: Option<f64>,
}
pub trait TickDistGen<N> {
type Res: TickDist<Num = N>;
fn generate(
self,
data: &ticks::DataBound<N>,
canvas: &RenderFrameBound,
req: IndexRequester,
) -> Self::Res;
}
pub fn gen_ticks<N: PlotNum, G: TickDistGen<N>>(
gen: G,
data: &ticks::DataBound<N>,
opt: &RenderFrameBound,
req: IndexRequester,
) -> G::Res {
gen.generate(data, opt, req)
}
pub trait TickDist {
type Num;
type It: IntoIterator<Item = Self::Num>;
type Fmt: TickFmt<Self::Num>;
fn unwrap(self) -> TickDistribution<Self::It, Self::Fmt>;
}
impl<I: IntoIterator, F: TickFmt<I::Item>> TickDist for TickDistribution<I, F> {
type Num = I::Item;
type It = I;
type Fmt = F;
fn unwrap(self) -> TickDistribution<Self::It, Self::Fmt> {
self
}
}
pub struct TickDistribution<I, F> {
pub iter: I,
pub fmt: F,
pub res: TickRes,
}
pub fn from_iter<I: IntoIterator<Item = X>, X: PlotNum + fmt::Display>(
it: I,
) -> TickDistribution<I, DefaultTickFmt> {
TickDistribution::new(it)
}
impl<X: PlotNum, I: IntoIterator<Item = X>> TickDistribution<I, DefaultTickFmt>
where
X: fmt::Display,
{
pub fn new(it: I) -> Self {
Self::from_parts(it, DefaultTickFmt, TickRes { dash_size: None })
}
}
impl<X: PlotNum, I: IntoIterator<Item = X>, Fmt: TickFmt<X>> TickDistGen<X>
for TickDistribution<I, Fmt>
{
type Res = Self;
fn generate(self, _: &ticks::DataBound<X>, _: &RenderFrameBound, _: IndexRequester) -> Self {
self
}
}