//! # anchor-parser
//!
//! [![Crates.io](https://img.shields.io/crates/v/anchor-parser.svg)](https://crates.io/crates/anchor-parser)
//! [![docs.rs](https://docs.rs/anchor-parser/badge.svg)](https://docs.rs/anchor-parser)
//! [![MIT License](https://img.shields.io/crates/l/anchor-parser.svg)](https://github.com/goni098/anchor-parser/blob/main/LICENSE)
//!
//! Generate Rust types and helpers from [Anchor](https://www.anchor-lang.com/) IDL
//! JSON files using [`solana-sdk`] types directly — no `anchor-lang` dependency required.
//!
//! # Quick start
//!
//! ```toml
//! [dependencies]
//! anchor-parser = "3.0.0"
//! ```
//!
//! Place an Anchor IDL JSON file under your crate (e.g.
//! `<crate-root>/idls/my_program.json`), then point the macro at it:
//!
//! ```ignore
//! anchor_parser::declare_program!("idls/my_program.json");
//! ```
//!
//! The generated module is named after the IDL's `metadata.name`, falling back
//! to the file name when that is absent.
//!
//! # Generated modules
//!
//! [`declare_program!`] generates a module with the following sub-modules:
//!
//! | Module | Contents |
//! |--------|----------|
//! | `accounts` | Account structs with [`AccountDeserialize`] and `from_account_data` |
//! | `events` | Event structs with `from_logs` and `from_cpi_logs` |
//! | `instructions` | Builder functions returning [`solana_sdk::instruction::Instruction`] |
//! | `types` | Shared structs, enums, and type aliases from the IDL |
//! | `constants` | Program constants with doc comments |
//! | `utils` | `Event` / `Account` wrapper enums for generic parsing |
//!
//! # Examples
//!
//! ## Deserializing accounts
//!
//! ```ignore
//! use my_program::accounts::MyAccount;
//!
//! // Deserialize from raw account data (discriminator + payload)
//! let account = MyAccount::from_account_data(&raw_bytes)?;
//!
//! // Check discriminator
//! assert_eq!(MyAccount::DISCRIMINATOR, [/* 8 bytes */]);
//! ```
//!
//! ## Parsing events
//!
//! ```ignore
//! use my_program::events::SwapEvent;
//! use my_program::utils::Event;
//!
//! // Parse events from emit! log lines
//! let events = SwapEvent::from_logs(&log_messages);
//! let all_events = Event::from_logs(&log_messages);
//!
//! // Parse events from emit_cpi! inner instruction data (bs58-encoded)
//! let events = SwapEvent::from_cpi_logs(&inner_ix_data_strings);
//! let all_events = Event::from_cpi_logs(&inner_ix_data_strings);
//! ```
//!
//! ## Building instructions
//!
//! ```ignore
//! use my_program::instructions;
//!
//! let ix = instructions::swap(
//!     &my_program::ID,
//!     &instructions::SwapAccounts { /* ... */ },
//!     amount,
//!     min_out,
//! )?;
//! ```

/// Generates a module from an Anchor IDL JSON file.
///
/// Takes the path to the IDL JSON file; relative paths are resolved by walking
/// up from `CARGO_MANIFEST_DIR`. The module is named after the IDL's
/// `metadata.name`, falling back to the file name when that is absent.
///
/// # Generated items
///
/// - `ID` — program [`Pubkey`](solana_sdk::pubkey::Pubkey)
/// - `accounts` — account structs implementing [`AccountDeserialize`]
/// - `events` — event structs with `from_logs` / `from_cpi_logs`
/// - `instructions` — builder functions returning [`Instruction`](solana_sdk::instruction::Instruction)
/// - `types` — shared structs, enums, and type aliases
/// - `constants` — program constants
/// - `utils` — `Event` / `Account` wrapper enums
///
/// # Example
///
/// ```ignore
/// // Generates a module named after the IDL's `metadata.name`.
/// anchor_parser::declare_program!("idls/my_program.json");
///
/// // Now use my_program::accounts, my_program::events, etc.
/// ```
pub use anchor_parser_macros::declare_program;

/// Trait implemented by all generated account types.
///
/// Provides a discriminator constant and a method to deserialize from raw
/// on-chain account data (discriminator prefix + serialized payload).
///
/// You generally won't need to use this trait directly — generated account
/// types also expose a convenient `from_account_data` method.
///
/// # Example
///
/// ```ignore
/// use anchor_parser::AccountDeserialize;
///
/// fn parse<T: AccountDeserialize>(data: &[u8]) -> std::io::Result<T> {
///     T::deserialize(data)
/// }
/// ```
pub trait AccountDeserialize: Sized {
    /// The discriminator bytes that prefix this account's on-chain data.
    const DISCRIMINATOR: &'static [u8];

    /// Deserialize from raw account data (including the discriminator prefix).
    ///
    /// Returns an error if the data is too short, the discriminator doesn't
    /// match, or deserialization fails.
    fn deserialize(data: &[u8]) -> Result<Self, std::io::Error>;
}

#[doc(hidden)]
pub mod __private {
    pub use solana_sdk::instruction::{AccountMeta, Instruction};
    pub use solana_sdk::pubkey::Pubkey;

    pub use borsh::{BorshDeserialize, BorshSerialize};
    pub use bytemuck::{Pod, Zeroable};

    #[inline]
    pub fn base64_decode(input: &str) -> Option<Vec<u8>> {
        use base64::Engine;
        base64::engine::general_purpose::STANDARD.decode(input).ok()
    }

    #[inline]
    pub fn bs58_decode(input: &str) -> Option<Vec<u8>> {
        bs58::decode(input).into_vec().ok()
    }

    #[inline]
    pub fn bytemuck_read<T: bytemuck::Pod>(data: &[u8]) -> T {
        bytemuck::pod_read_unaligned(data)
    }
}
