omg_serde 0.1.0

Adds serde support to omg_core.
Documentation
use crate::generation::attributes::create::CreateAttributeStepSerde;
use crate::generation::attributes::distortion1d::Distortion1dStepSerde;
use crate::generation::attributes::distortion2d::Distortion2dStepSerde;
use crate::generation::attributes::generator::GeneratorStepSerde;
use crate::generation::attributes::modify::ModifyWithAttributeStepSerde;
use crate::generation::attributes::transformer::TransformAttribute2dStepSerde;
use anyhow::{Context, Result};
use omg_core::generation::step::GenerationStep;
use serde::{Deserialize, Serialize};
use std::fmt::Debug;

pub fn get_attribute_id(attribute: &str, attributes: &[String]) -> Result<usize> {
    attributes
        .iter()
        .position(|name| name.eq(attribute))
        .with_context(|| format!("Unknown attribute '{}'", attribute))
}

pub trait ToStep<T> {
    fn try_convert(self, attributes: &mut Vec<String>) -> Result<T>;
}

pub trait FromStep<T> {
    fn convert(&self, attributes: &mut Vec<String>) -> T;
}

pub fn assert_eq<R: FromStep<S> + PartialEq + Debug, S: ToStep<R>>(
    step: R,
    attributes: &mut Vec<String>,
) {
    let serde: S = (&step).convert(attributes);

    assert_eq!(serde.try_convert(attributes).unwrap(), step)
}

#[derive(new, Debug, Serialize, Deserialize)]
pub enum GenerationStepSerde {
    CreateAttribute(CreateAttributeStepSerde),
    Debug(String),
    DistortAlongX(Distortion1dStepSerde),
    DistortAlongY(Distortion1dStepSerde),
    Distortion2d(Distortion2dStepSerde),
    GeneratorAdd(GeneratorStepSerde),
    GeneratorSub(GeneratorStepSerde),
    ModifyWithAttribute(ModifyWithAttributeStepSerde),
    TransformAttribute2d(TransformAttribute2dStepSerde),
}

type S = GenerationStepSerde;
type R = GenerationStep;

impl ToStep<GenerationStep> for GenerationStepSerde {
    fn try_convert(self, attributes: &mut Vec<String>) -> Result<GenerationStep> {
        match self {
            S::CreateAttribute(step) => Ok(R::CreateAttribute(step.try_convert(attributes)?)),
            S::Debug(text) => Ok(R::Debug(text)),
            S::DistortAlongX(step) => Ok(R::DistortAlongX(step.try_convert(attributes)?)),
            S::DistortAlongY(step) => Ok(R::DistortAlongY(step.try_convert(attributes)?)),
            S::Distortion2d(step) => Ok(R::Distortion2d(step.try_convert(attributes)?)),
            S::GeneratorAdd(step) => Ok(R::GeneratorAdd(step.try_convert(attributes)?)),
            S::GeneratorSub(step) => Ok(R::GeneratorSub(step.try_convert(attributes)?)),
            S::ModifyWithAttribute(step) => {
                Ok(R::ModifyWithAttribute(step.try_convert(attributes)?))
            }
            S::TransformAttribute2d(step) => {
                Ok(R::TransformAttribute2d(step.try_convert(attributes)?))
            }
        }
    }
}

impl FromStep<GenerationStepSerde> for GenerationStep {
    fn convert(&self, attributes: &mut Vec<String>) -> GenerationStepSerde {
        match self {
            R::CreateAttribute(data) => S::CreateAttribute(data.convert(attributes)),
            R::Debug(text) => S::Debug(text.clone()),
            R::DistortAlongX(data) => S::DistortAlongX(data.convert(attributes)),
            R::DistortAlongY(data) => S::DistortAlongY(data.convert(attributes)),
            R::Distortion2d(data) => S::Distortion2d(data.convert(attributes)),
            R::GeneratorAdd(data) => S::GeneratorAdd(data.convert(attributes)),
            R::GeneratorSub(data) => S::GeneratorSub(data.convert(attributes)),
            R::ModifyWithAttribute(data) => S::ModifyWithAttribute(data.convert(attributes)),
            R::TransformAttribute2d(data) => S::TransformAttribute2d(data.convert(attributes)),
        }
    }
}