datagen-rs 0.1.0

A random data generator written in rust
Documentation
use crate::schema::transform::Transform;
#[cfg(feature = "schema")]
use schemars::JsonSchema;
#[cfg(feature = "serialize")]
use serde::{Deserialize, Serialize};

#[derive(Debug, Clone)]
#[cfg_attr(feature = "schema", derive(JsonSchema))]
#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "serialize", serde(rename_all = "camelCase"))]
pub struct Reference {
    pub reference: String,
    pub except: Option<Vec<StringOrNumber>>,
    pub keep_all: Option<bool>,
    pub transform: Option<Vec<Transform>>,
}

#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "schema", derive(JsonSchema))]
#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "serialize", serde(untagged, deny_unknown_fields))]
pub enum StringOrNumber {
    String(String),
    Number(f64),
}

#[cfg(feature = "map-schema")]
pub mod generate {
    use crate::generate::current_schema::CurrentSchemaRef;
    use crate::generate::generated_schema::generate::IntoGeneratedArc;
    use crate::generate::generated_schema::GeneratedSchema;
    use crate::schema::reference::{Reference, StringOrNumber};
    use crate::schema::transform::Transform;
    use crate::util::types::Result;
    use rand::prelude::SliceRandom;
    use std::sync::Arc;

    impl IntoGeneratedArc for Reference {
        fn into_generated_arc(self, schema: CurrentSchemaRef) -> Result<Arc<GeneratedSchema>> {
            let mut reference = self.reference;
            if !reference.starts_with("ref:") {
                reference = format!("ref:{reference}");
            }

            let resolved = schema.resolve_ref(reference)?;
            let Some(except) = self.except else {
                return resolved.into_random();
            };

            let Some(resolved) = resolved.into_vec() else {
                return Ok(Arc::new(GeneratedSchema::None));
            };

            let except = except
                .into_iter()
                .map(|x| match x {
                    StringOrNumber::String(string) => {
                        Ok(schema.resolve_ref(string)?.into_vec().unwrap_or(vec![]))
                    }
                    StringOrNumber::Number(number) => {
                        Ok(vec![Arc::new(GeneratedSchema::Number(number.into()))])
                    }
                })
                .collect::<Result<Vec<_>>>()?
                .into_iter()
                .flatten()
                .collect::<Vec<_>>();

            let resolved = resolved
                .iter()
                .filter(|x| !except.contains(x))
                .cloned()
                .collect::<Vec<_>>();

            Ok(if self.keep_all.unwrap_or(false) {
                Arc::new(GeneratedSchema::Array(resolved))
            } else if let Some(resolved) = resolved.choose(&mut rand::thread_rng()) {
                resolved.clone()
            } else {
                Arc::new(GeneratedSchema::None)
            })
        }

        fn get_transform(&self) -> Option<Vec<Transform>> {
            self.transform.clone()
        }
    }
}