rs-macros 0.1.0

Rust macros for generating JSON schemas
Documentation
use rs_macros::JsonSchemaOneOf;
use serde::{Deserialize, Serialize};

// Example using the macro - this should generate the same JsonSchema impl as your manual one
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchemaOneOf)]
#[serde(rename_all = "camelCase")]
pub enum MessageType {
    MessageOne,
    MessageTwo,
    MessageThree,
}

// Example without rename_all (keeps PascalCase)
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchemaOneOf)]
pub enum StatusType {
    Active,
    Inactive,
    Pending,
}

// Example with snake_case
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchemaOneOf)]
#[serde(rename_all = "camelCase")]
pub enum EventType {
    UserLogin,
    UserLogout,
    DataUpdate,
}

#[cfg(test)]
mod tests {
    use super::*;
    use schemars::gen::SchemaGenerator;

    #[test]
    fn test_message_type_schema() {
        let mut gen = SchemaGenerator::default();
        let schema = MessageType::json_schema(&mut gen);

        // Verify it's a oneOf schema
        if let schemars::schema::Schema::Object(obj) = schema {
            let one_of = obj.subschemas.one_of.as_ref().unwrap();
            assert_eq!(one_of.len(), 3);

            // Check that const values are camelCase
            for (i, variant_schema) in one_of.iter().enumerate() {
                if let schemars::schema::Schema::Object(variant_obj) = variant_schema {
                    let const_val = variant_obj.const_value.as_ref().unwrap();
                    match i {
                        0 => assert_eq!(const_val.as_str().unwrap(), "messageOne"),
                        1 => assert_eq!(const_val.as_str().unwrap(), "messageTwo"),
                        2 => assert_eq!(const_val.as_str().unwrap(), "messageThree"),
                        _ => panic!("Unexpected variant"),
                    }
                }
            }
        } else {
            panic!("Expected object schema");
        }
    }

    #[test]
    fn test_status_type_schema() {
        let mut gen = SchemaGenerator::default();
        let schema = StatusType::json_schema(&mut gen);

        // Verify PascalCase is preserved when no rename_all
        if let schemars::schema::Schema::Object(obj) = schema {
            let one_of = obj.subschemas.one_of.as_ref().unwrap();
            assert_eq!(one_of.len(), 3);
        }
    }

    #[test]
    fn test_event_type_schema() {
        let mut gen = SchemaGenerator::default();
        let schema = EventType::json_schema(&mut gen);

        // Verify snake_case conversion
        if let schemars::schema::Schema::Object(obj) = schema {
            let one_of = obj.subschemas.one_of.as_ref().unwrap();
            assert_eq!(one_of.len(), 3);

            // Check that const values are snake_case
            for (i, variant_schema) in one_of.iter().enumerate() {
                if let schemars::schema::Schema::Object(variant_obj) = variant_schema {
                    let const_val = variant_obj.const_value.as_ref().unwrap();
                    match i {
                        0 => assert_eq!(const_val.as_str().unwrap(), "userLogin"),
                        1 => assert_eq!(const_val.as_str().unwrap(), "userLogout"),
                        2 => assert_eq!(const_val.as_str().unwrap(), "dataUpdate"),
                        _ => panic!("Unexpected variant"),
                    }
                }
            }
        }
    }
}

fn main() {
    // This is just to ensure the code compiles and runs
    let message = MessageType::MessageOne;
    println!("Created message: {:?}", message);

    let status = StatusType::Active;
    println!("Created status: {:?}", status);

    let event = EventType::UserLogin;
    println!("Created event: {:?}", event);
}