//! OTOML derive macro for simple serialization and deserialization.
//!
//! Provides a single `Otoml` derive macro that adds serialization methods:
//! - `dump_otoml()` / `load_otoml()` for text format
//! - `dump_obin()` / `load_obin()` for binary format

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

/// Implement the Otoml derive macro.
///
/// Adds four methods to the struct:
/// - `dump_otoml(&self) -> Result<String, herolib_osis::OtomlError>` - text serialization
/// - `load_otoml(s: &str) -> Result<Self, herolib_osis::OtomlError>` - text deserialization
/// - `dump_obin(&self) -> Result<Vec<u8>, herolib_osis::OtomlError>` - binary serialization
/// - `load_obin(data: &[u8]) -> Result<Self, herolib_osis::OtomlError>` - binary deserialization
pub fn impl_otoml(input: TokenStream) -> TokenStream {
    let input = parse_macro_input!(input as DeriveInput);
    let name = &input.ident;

    let expanded = quote! {
        impl #name {
            /// Serialize this struct to canonical OTOML text format.
            ///
            /// The output is deterministic:
            /// - Keys are sorted alphabetically
            /// - Nested structs become inline tables
            /// - Same data always produces identical bytes
            pub fn dump_otoml(&self) -> Result<String, herolib_osis::OtomlError> {
                herolib_osis::dump_otoml(self)
            }

            /// Deserialize an OTOML/TOML text string into this struct.
            ///
            /// Accepts any valid TOML (1.0, 1.1, or OTOML format).
            pub fn load_otoml(s: &str) -> Result<Self, herolib_osis::OtomlError> {
                herolib_osis::load_otoml(s)
            }

            /// Serialize this struct to compact OBIN binary format.
            ///
            /// The output is deterministic and compact:
            /// - Uses variable-length integer encoding
            /// - Keys are sorted for determinism
            /// - Same data always produces identical bytes
            pub fn dump_obin(&self) -> Result<Vec<u8>, herolib_osis::OtomlError> {
                herolib_osis::dump_obin(self)
            }

            /// Deserialize OBIN binary data into this struct.
            pub fn load_obin(data: &[u8]) -> Result<Self, herolib_osis::OtomlError> {
                herolib_osis::load_obin(data)
            }
        }
    };

    TokenStream::from(expanded)
}
