use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GeneratorConfig {
pub output_format: OutputFormat,
pub include_examples: bool,
pub validate_examples: bool,
pub include_type_info: bool,
pub include_cross_refs: bool,
pub max_hierarchy_depth: usize,
pub include_private: bool,
pub custom_styling: Option<String>,
}
impl GeneratorConfig {
pub fn new() -> Self {
Self {
output_format: OutputFormat::Json,
include_examples: true,
validate_examples: false, include_type_info: true,
include_cross_refs: true,
max_hierarchy_depth: 5,
include_private: false,
custom_styling: None,
}
}
pub fn with_output_format(mut self, format: OutputFormat) -> Self {
self.output_format = format;
self
}
pub fn with_validation(mut self, validate: bool) -> Self {
self.validate_examples = validate;
self
}
pub fn with_examples(mut self, include: bool) -> Self {
self.include_examples = include;
self
}
pub fn with_max_depth(mut self, depth: usize) -> Self {
self.max_hierarchy_depth = depth;
self
}
pub fn with_private_items(mut self, include: bool) -> Self {
self.include_private = include;
self
}
pub fn with_custom_styling(mut self, css: Option<String>) -> Self {
self.custom_styling = css;
self
}
pub fn with_type_info(mut self, include: bool) -> Self {
self.include_type_info = include;
self
}
pub fn with_cross_refs(mut self, include: bool) -> Self {
self.include_cross_refs = include;
self
}
}
impl Default for GeneratorConfig {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
pub enum OutputFormat {
#[default]
Json,
Html,
Markdown,
Interactive,
OpenApi,
}
impl OutputFormat {
pub fn file_extension(&self) -> &'static str {
match self {
OutputFormat::Json => "json",
OutputFormat::Html => "html",
OutputFormat::Markdown => "md",
OutputFormat::Interactive => "html",
OutputFormat::OpenApi => "yaml",
}
}
pub fn mime_type(&self) -> &'static str {
match self {
OutputFormat::Json => "application/json",
OutputFormat::Html => "text/html",
OutputFormat::Markdown => "text/markdown",
OutputFormat::Interactive => "text/html",
OutputFormat::OpenApi => "application/x-yaml",
}
}
pub fn supports_interactive(&self) -> bool {
matches!(self, OutputFormat::Html | OutputFormat::Interactive)
}
pub fn supports_syntax_highlighting(&self) -> bool {
matches!(
self,
OutputFormat::Html | OutputFormat::Interactive | OutputFormat::Markdown
)
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PlaygroundConfig {
pub wasm_enabled: bool,
pub real_time_execution: bool,
pub syntax_highlighting: bool,
pub auto_completion: bool,
pub error_highlighting: bool,
pub available_crates: Vec<String>,
pub example_count: usize,
pub trait_count: usize,
pub type_count: usize,
}
impl PlaygroundConfig {
pub fn new() -> Self {
Self {
wasm_enabled: true,
real_time_execution: true,
syntax_highlighting: true,
auto_completion: true,
error_highlighting: true,
available_crates: vec!["sklears-core".to_string()],
example_count: 0,
trait_count: 0,
type_count: 0,
}
}
pub fn with_wasm(mut self, enabled: bool) -> Self {
self.wasm_enabled = enabled;
self
}
pub fn with_real_time_execution(mut self, enabled: bool) -> Self {
self.real_time_execution = enabled;
self
}
pub fn with_syntax_highlighting(mut self, enabled: bool) -> Self {
self.syntax_highlighting = enabled;
self
}
pub fn with_auto_completion(mut self, enabled: bool) -> Self {
self.auto_completion = enabled;
self
}
pub fn with_error_highlighting(mut self, enabled: bool) -> Self {
self.error_highlighting = enabled;
self
}
pub fn with_available_crates(mut self, crates: Vec<String>) -> Self {
self.available_crates = crates;
self
}
pub fn with_stats(
mut self,
example_count: usize,
trait_count: usize,
type_count: usize,
) -> Self {
self.example_count = example_count;
self.trait_count = trait_count;
self.type_count = type_count;
self
}
}
impl Default for PlaygroundConfig {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ValidationConfig {
pub compile_check: bool,
pub runtime_check: bool,
pub timeout_ms: u64,
pub max_memory: usize,
pub lint_check: bool,
pub extra_flags: Vec<String>,
}
impl ValidationConfig {
pub fn new() -> Self {
Self {
compile_check: true,
runtime_check: false,
timeout_ms: 5000,
max_memory: 1024 * 1024 * 50, lint_check: true,
extra_flags: Vec::new(),
}
}
pub fn with_compile_check(mut self, enabled: bool) -> Self {
self.compile_check = enabled;
self
}
pub fn with_runtime_check(mut self, enabled: bool) -> Self {
self.runtime_check = enabled;
self
}
pub fn with_timeout(mut self, timeout_ms: u64) -> Self {
self.timeout_ms = timeout_ms;
self
}
pub fn with_max_memory(mut self, max_memory: usize) -> Self {
self.max_memory = max_memory;
self
}
pub fn with_lint_check(mut self, enabled: bool) -> Self {
self.lint_check = enabled;
self
}
pub fn with_extra_flags(mut self, flags: Vec<String>) -> Self {
self.extra_flags = flags;
self
}
}
impl Default for ValidationConfig {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ThemeConfig {
pub primary_color: String,
pub secondary_color: String,
pub background_color: String,
pub text_color: String,
pub code_background: String,
pub code_text_color: String,
pub font_family: String,
pub code_font_family: String,
pub dark_mode: bool,
}
impl ThemeConfig {
pub fn light_theme() -> Self {
Self {
primary_color: "#0066cc".to_string(),
secondary_color: "#ff6b35".to_string(),
background_color: "#ffffff".to_string(),
text_color: "#333333".to_string(),
code_background: "#f5f5f5".to_string(),
code_text_color: "#333333".to_string(),
font_family: "'Segoe UI', Tahoma, Geneva, Verdana, sans-serif".to_string(),
code_font_family: "'Monaco', 'Menlo', 'Ubuntu Mono', monospace".to_string(),
dark_mode: false,
}
}
pub fn dark_theme() -> Self {
Self {
primary_color: "#4da6ff".to_string(),
secondary_color: "#ff8c66".to_string(),
background_color: "#1e1e1e".to_string(),
text_color: "#d4d4d4".to_string(),
code_background: "#2d2d30".to_string(),
code_text_color: "#d4d4d4".to_string(),
font_family: "'Segoe UI', Tahoma, Geneva, Verdana, sans-serif".to_string(),
code_font_family: "'Monaco', 'Menlo', 'Ubuntu Mono', monospace".to_string(),
dark_mode: true,
}
}
pub fn to_css_variables(&self) -> String {
format!(
r#":root {{
--primary-color: {};
--secondary-color: {};
--background-color: {};
--text-color: {};
--code-background: {};
--code-text-color: {};
--font-family: {};
--code-font-family: {};
}}"#,
self.primary_color,
self.secondary_color,
self.background_color,
self.text_color,
self.code_background,
self.code_text_color,
self.font_family,
self.code_font_family
)
}
}
impl Default for ThemeConfig {
fn default() -> Self {
Self::light_theme()
}
}
#[allow(non_snake_case)]
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_generator_config_creation() {
let config = GeneratorConfig::new();
assert_eq!(config.output_format, OutputFormat::Json);
assert!(config.include_examples);
assert!(!config.validate_examples);
assert!(config.include_type_info);
assert!(config.include_cross_refs);
assert_eq!(config.max_hierarchy_depth, 5);
assert!(!config.include_private);
assert!(config.custom_styling.is_none());
}
#[test]
fn test_generator_config_builder() {
let config = GeneratorConfig::new()
.with_output_format(OutputFormat::Html)
.with_validation(true)
.with_examples(false)
.with_max_depth(10)
.with_private_items(true);
assert_eq!(config.output_format, OutputFormat::Html);
assert!(config.validate_examples);
assert!(!config.include_examples);
assert_eq!(config.max_hierarchy_depth, 10);
assert!(config.include_private);
}
#[test]
fn test_output_format_properties() {
assert_eq!(OutputFormat::Json.file_extension(), "json");
assert_eq!(OutputFormat::Html.file_extension(), "html");
assert_eq!(OutputFormat::Markdown.file_extension(), "md");
assert_eq!(OutputFormat::Interactive.file_extension(), "html");
assert_eq!(OutputFormat::OpenApi.file_extension(), "yaml");
assert_eq!(OutputFormat::Json.mime_type(), "application/json");
assert_eq!(OutputFormat::Html.mime_type(), "text/html");
assert_eq!(OutputFormat::Markdown.mime_type(), "text/markdown");
assert!(!OutputFormat::Json.supports_interactive());
assert!(OutputFormat::Html.supports_interactive());
assert!(OutputFormat::Interactive.supports_interactive());
assert!(!OutputFormat::Json.supports_syntax_highlighting());
assert!(OutputFormat::Html.supports_syntax_highlighting());
assert!(OutputFormat::Markdown.supports_syntax_highlighting());
}
#[test]
fn test_playground_config() {
let config = PlaygroundConfig::new()
.with_wasm(false)
.with_real_time_execution(false)
.with_available_crates(vec!["sklears-core".to_string(), "std".to_string()])
.with_stats(10, 5, 8);
assert!(!config.wasm_enabled);
assert!(!config.real_time_execution);
assert!(config.syntax_highlighting);
assert_eq!(config.available_crates.len(), 2);
assert_eq!(config.example_count, 10);
assert_eq!(config.trait_count, 5);
assert_eq!(config.type_count, 8);
}
#[test]
fn test_validation_config() {
let config = ValidationConfig::new()
.with_compile_check(false)
.with_runtime_check(true)
.with_timeout(10000)
.with_max_memory(1024 * 1024 * 100);
assert!(!config.compile_check);
assert!(config.runtime_check);
assert_eq!(config.timeout_ms, 10000);
assert_eq!(config.max_memory, 1024 * 1024 * 100);
assert!(config.lint_check);
}
#[test]
fn test_theme_config_light() {
let theme = ThemeConfig::light_theme();
assert_eq!(theme.primary_color, "#0066cc");
assert_eq!(theme.background_color, "#ffffff");
assert!(!theme.dark_mode);
let css = theme.to_css_variables();
assert!(css.contains("--primary-color: #0066cc"));
assert!(css.contains("--background-color: #ffffff"));
}
#[test]
fn test_theme_config_dark() {
let theme = ThemeConfig::dark_theme();
assert_eq!(theme.primary_color, "#4da6ff");
assert_eq!(theme.background_color, "#1e1e1e");
assert!(theme.dark_mode);
let css = theme.to_css_variables();
assert!(css.contains("--primary-color: #4da6ff"));
assert!(css.contains("--background-color: #1e1e1e"));
}
#[test]
fn test_config_serialization() {
let config = GeneratorConfig::new().with_output_format(OutputFormat::Html);
let serialized = serde_json::to_string(&config).unwrap_or_default();
let deserialized: GeneratorConfig =
serde_json::from_str(&serialized).expect("valid JSON operation");
assert_eq!(config.output_format, deserialized.output_format);
assert_eq!(config.include_examples, deserialized.include_examples);
}
#[test]
fn test_default_implementations() {
let _: GeneratorConfig = Default::default();
let _: OutputFormat = Default::default();
let _: PlaygroundConfig = Default::default();
let _: ValidationConfig = Default::default();
let _: ThemeConfig = Default::default();
}
}