plotly-fork 0.8.4

A plotting library powered by Plotly.js
Documentation
#[cfg(feature = "plotly_ndarray")]
use ndarray::{Array, Ix2};
use serde::Serialize;

#[cfg(feature = "plotly_ndarray")]
use crate::ndarray::ArrayTraces;

pub fn owned_string_vector<S: AsRef<str>>(s: Vec<S>) -> Vec<String> {
    s.iter()
        .map(|x| x.as_ref().to_string())
        .collect::<Vec<String>>()
}

#[derive(Serialize, Clone, Debug, PartialEq)]
#[serde(untagged)]
pub enum NumOrString {
    S(String),
    F(f64),
    I(i64),
    U(u64),
}

impl From<String> for NumOrString {
    fn from(item: String) -> Self {
        NumOrString::S(item)
    }
}

impl From<&String> for NumOrString {
    fn from(item: &String) -> Self {
        NumOrString::S(item.clone())
    }
}

impl From<&str> for NumOrString {
    fn from(item: &str) -> Self {
        NumOrString::S(item.to_string())
    }
}

impl From<f64> for NumOrString {
    fn from(item: f64) -> Self {
        NumOrString::F(item)
    }
}

impl From<f32> for NumOrString {
    fn from(item: f32) -> Self {
        NumOrString::F(item as f64)
    }
}

impl From<usize> for NumOrString {
    fn from(item: usize) -> Self {
        NumOrString::U(item as u64)
    }
}

impl From<u64> for NumOrString {
    fn from(item: u64) -> Self {
        NumOrString::U(item)
    }
}

impl From<u32> for NumOrString {
    fn from(item: u32) -> Self {
        NumOrString::U(item as u64)
    }
}

impl From<isize> for NumOrString {
    fn from(item: isize) -> Self {
        NumOrString::I(item as i64)
    }
}

impl From<i64> for NumOrString {
    fn from(item: i64) -> Self {
        NumOrString::I(item)
    }
}

impl From<i32> for NumOrString {
    fn from(item: i32) -> Self {
        NumOrString::I(item as i64)
    }
}

#[derive(Serialize, Clone, Debug, PartialEq)]
pub struct NumOrStringCollection(Vec<NumOrString>);

impl<T> From<Vec<T>> for NumOrStringCollection
where
    T: Into<NumOrString> + Clone,
{
    fn from(items: Vec<T>) -> Self {
        let mut collection: Vec<NumOrString> = Vec::with_capacity(items.len());
        for item in items.iter().cloned() {
            collection.push(item.into());
        }
        Self(collection)
    }
}

#[cfg(feature = "plotly_ndarray")]
pub fn trace_vectors_from<T>(traces_matrix: Array<T, Ix2>, array_traces: ArrayTraces) -> Vec<Vec<T>>
where
    T: Clone,
{
    let mut traces: Vec<Vec<T>> = Vec::new();
    let dim_index = usize::from(array_traces == ArrayTraces::OverColumns);
    let traces_count = traces_matrix.shape()[dim_index];
    let get_trace = |index| {
        if array_traces == ArrayTraces::OverColumns {
            traces_matrix.column(index)
        } else {
            traces_matrix.row(index)
        }
    };
    for col in 0..traces_count {
        let trace_data: Vec<T> = get_trace(col).to_vec();
        traces.push(trace_data);
    }

    traces
}

#[cfg(test)]
mod tests {
    use serde_json::{json, to_value};

    use super::*;

    #[test]
    fn test_num_or_string() {
        let x: NumOrString = "String".to_string().into();
        assert_eq!(x, NumOrString::S("String".to_string()));

        let x: NumOrString = (&"String".to_string()).into();
        assert_eq!(x, NumOrString::S("String".to_string()));

        let x: NumOrString = "&str".into();
        assert_eq!(x, NumOrString::S("&str".to_string()));

        let x: NumOrString = 100.0_f64.into();
        assert_eq!(x, NumOrString::F(100.));

        let x: NumOrString = 100.0_f32.into();
        assert_eq!(x, NumOrString::F(100.));

        let x: NumOrString = (-100_isize).into();
        assert_eq!(x, NumOrString::I(-100));

        let x: NumOrString = (-100_i64).into();
        assert_eq!(x, NumOrString::I(-100));

        let x: NumOrString = (-100_i32).into();
        assert_eq!(x, NumOrString::I(-100));

        let x: NumOrString = 100_usize.into();
        assert_eq!(x, NumOrString::U(100));

        let x: NumOrString = 100_u64.into();
        assert_eq!(x, NumOrString::U(100));

        let x: NumOrString = 100_u32.into();
        assert_eq!(x, NumOrString::U(100));
    }

    #[test]
    fn test_num_or_string_collection() {
        let x: NumOrStringCollection = vec!["&str"].into();
        let expected = NumOrStringCollection(vec![NumOrString::S("&str".to_string())]);
        assert_eq!(x, expected);

        let x: NumOrStringCollection = vec![1.].into();
        let expected = NumOrStringCollection(vec![NumOrString::F(1.)]);
        assert_eq!(x, expected);

        let x: NumOrStringCollection = vec![1_i32].into();
        let expected = NumOrStringCollection(vec![NumOrString::I(1)]);
        assert_eq!(x, expected);

        let x: NumOrStringCollection = vec![1_u32].into();
        let expected = NumOrStringCollection(vec![NumOrString::U(1)]);
        assert_eq!(x, expected);
    }

    #[test]
    #[rustfmt::skip]
    fn test_serialize_num_or_string() {
        assert_eq!(to_value(NumOrString::S("&str".to_string())).unwrap(), json!("&str"));
        assert_eq!(to_value(NumOrString::F(100.)).unwrap(), json!(100.0));
        assert_eq!(to_value(NumOrString::I(-50)).unwrap(), json!(-50));
        assert_eq!(to_value(NumOrString::U(50)).unwrap(), json!(50));
    }

    #[test]
    #[rustfmt::skip]
    fn test_serialize_num_or_string_collection() {
        assert_eq!(to_value(NumOrStringCollection(vec![NumOrString::S("&str".to_string())])).unwrap(), json!(["&str"]));
        assert_eq!(to_value(NumOrStringCollection(vec![NumOrString::F(100.)])).unwrap(), json!([100.0]));
        assert_eq!(to_value(NumOrStringCollection(vec![NumOrString::I(-50)])).unwrap(), json!([-50]));
        assert_eq!(to_value(NumOrStringCollection(vec![NumOrString::U(50)])).unwrap(), json!([50]));
    }
}