1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
use serde::Serialize;

#[derive(Serialize)]
pub struct ColorScaleElem<'s>(f64, &'s str);

impl<'s> ColorScaleElem<'s> {
    pub fn new(level: f64, color: &'s str) -> Self {
        Self(level, color)
    }
}

#[derive(Serialize)]
pub enum ColorScaleName {
    Greys,
    YlGnBu,
    Greens,
    YlOrRd,
    Bluered,
    RdBu,
    Reds,
    Blues,
    Picnic,
    Rainbow,
    Portland,
    Jet,
    Hot,
    Blackbody,
    Earth,
    Electric,
    Viridis,
    Cividis,
}

#[derive(Serialize)]
#[serde(untagged)]
pub enum ColorScale<'a> {
    Name(ColorScaleName),
    Array(&'a [ColorScaleElem<'a>]),
}

pub type Any = serde_json::Value;
pub type InfoArray = Vec<serde_json::Value>;
pub type Flaglist<'a> = &'a str;
pub type Angle = f64;

struct IsEmpty<T> {
    pub data: T,
    pub is_empty: bool,
}

impl<T: serde::ser::Serialize> serde::ser::Serialize for IsEmpty<T> {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: serde::Serializer,
    {
        self.data.serialize(serializer)
    }
}

impl<T: Default> Default for IsEmpty<T> {
    fn default() -> Self {
        Self {
            data: T::default(),
            is_empty: true,
        }
    }
}

impl<T> IsEmpty<T> {
    pub fn is_empty(&self) -> bool {
        self.is_empty
    }
}

include!(concat!(env!("OUT_DIR"), "/mod.rs"));
mod error;
pub use error::Error;

pub struct Plot<'a, W, D> {
    w: W,
    graph_div: D,
    layout: &'a layout::Layout<'a>,
    config: &'a config::Config<'a>,
    ntraces: usize,
}

impl<'a, W, D> Plot<'a, W, D>
where
    W: std::io::Write,
    D: AsRef<str>,
{
    pub fn new(
        mut w: W,
        graph_div: D,
        layout: &'a layout::Layout,
        config: &'a config::Config,
    ) -> Result<Self, Error> {
        write!(w, "var data = [")?;
        Ok(Self {
            w,
            graph_div,
            layout,
            config,
            ntraces: 0,
        })
    }

    pub fn add_trace<T>(&mut self, trace: T) -> Result<(), Error>
    where
        T: serde::Serialize,
    {
        if self.ntraces > 0 {
            write!(self.w, ", ")?;
        }

        serde_json::to_writer(&mut self.w, &trace)?;
        self.ntraces += 1;

        Ok(())
    }

    pub fn finish(mut self) -> Result<(), Error> {
        writeln!(self.w, "];")?;

        write!(self.w, "var layout = ")?;
        serde_json::to_writer(&mut self.w, self.layout)?;
        writeln!(self.w, ";")?;

        write!(self.w, "var config = ")?;
        serde_json::to_writer(&mut self.w, self.config)?;
        writeln!(self.w, ";")?;

        writeln!(
            self.w,
            "Plotly.newPlot(\"{}\", data, layout, config);",
            self.graph_div.as_ref()
        )?;

        Ok(())
    }
}