automorph-derive 0.2.0

Derive macros for automorph - Automerge-Rust struct synchronization
Documentation
#![forbid(unsafe_code)]

//! Derive macro for the Automorph trait.
//!
//! This crate provides `#[derive(Automorph)]` to automatically implement
//! bidirectional synchronization with Automerge documents.
//!
//! ## Supported Structures
//!
//! - Named structs: `struct Foo { bar: i32 }`
//! - Tuple structs (newtype): `struct Foo(Bar)`
//! - Unit structs: `struct Foo`
//! - Enums with all variant types
//!
//! ## Container Attributes
//!
//! - `#[automorph(rename_all = "...")]` - Rename all fields (camelCase, snake_case, etc.)
//! - `#[automorph(tag = "...")]` - Internal tagging for enums
//! - `#[automorph(tag = "...", content = "...")]` - Adjacent tagging for enums
//! - `#[automorph(untagged)]` - Untagged enum representation
//!
//! ## Field Attributes
//!
//! - `#[automorph(rename = "...")]` - Rename this field
//! - `#[automorph(skip)]` - Skip this field entirely
//! - `#[automorph(default)]` - Use Default if field is missing

mod attribute_parsing;
mod case_conversion;
mod enum_derive;
mod struct_derive;

use proc_macro::TokenStream;
use syn::{Data, DeriveInput, parse_macro_input};

use crate::attribute_parsing::parse_container_attrs;

/// Derive the `Automorph` trait for a struct or enum.
///
/// # Example
///
/// ```ignore
/// use automorph::Automorph;
///
/// #[derive(Automorph, Default, Clone)]
/// struct Person {
///     name: String,
///     age: u64,
/// }
/// ```
///
/// This generates an implementation that stores the struct as an Automerge Map
/// with each field as a key.
#[proc_macro_derive(Automorph, attributes(automorph))]
pub fn derive_automorph(input: TokenStream) -> TokenStream {
    let input = parse_macro_input!(input as DeriveInput);

    // Check for transparent attribute
    let container_attrs = parse_container_attrs(&input.attrs);

    match &input.data {
        Data::Struct(data) => {
            // Handle transparent newtype structs
            if container_attrs.transparent {
                struct_derive::derive_transparent_struct(&input, data)
            } else {
                struct_derive::derive_struct(&input, data)
            }
        }
        Data::Enum(data) => enum_derive::derive_enum(&input, data),
        Data::Union(_) => {
            syn::Error::new(input.ident.span(), "Automorph cannot be derived for unions")
                .to_compile_error()
                .into()
        }
    }
}