lib.rs 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927
  1. use codegen::accounts as accounts_codegen;
  2. use codegen::program as program_codegen;
  3. use parser::accounts as accounts_parser;
  4. use parser::program as program_parser;
  5. use proc_macro2::{Span, TokenStream};
  6. use quote::quote;
  7. use quote::ToTokens;
  8. use std::collections::HashMap;
  9. use std::ops::Deref;
  10. use syn::ext::IdentExt;
  11. use syn::parse::{Error as ParseError, Parse, ParseStream, Result as ParseResult};
  12. use syn::punctuated::Punctuated;
  13. use syn::spanned::Spanned;
  14. use syn::token::Comma;
  15. use syn::{
  16. Expr, Generics, Ident, ImplItemMethod, ItemEnum, ItemFn, ItemImpl, ItemMod, ItemStruct, LitInt,
  17. LitStr, PatType, Token, Type, TypePath,
  18. };
  19. pub mod codegen;
  20. #[cfg(feature = "hash")]
  21. pub mod hash;
  22. #[cfg(not(feature = "hash"))]
  23. pub(crate) mod hash;
  24. #[cfg(feature = "idl")]
  25. pub mod idl;
  26. pub mod parser;
  27. #[derive(Debug)]
  28. pub struct Program {
  29. pub state: Option<State>,
  30. pub ixs: Vec<Ix>,
  31. pub name: Ident,
  32. pub docs: Option<Vec<String>>,
  33. pub program_mod: ItemMod,
  34. pub fallback_fn: Option<FallbackFn>,
  35. }
  36. impl Parse for Program {
  37. fn parse(input: ParseStream) -> ParseResult<Self> {
  38. let program_mod = <ItemMod as Parse>::parse(input)?;
  39. program_parser::parse(program_mod)
  40. }
  41. }
  42. impl From<&Program> for TokenStream {
  43. fn from(program: &Program) -> Self {
  44. program_codegen::generate(program)
  45. }
  46. }
  47. impl ToTokens for Program {
  48. fn to_tokens(&self, tokens: &mut TokenStream) {
  49. tokens.extend::<TokenStream>(self.into());
  50. }
  51. }
  52. #[derive(Debug)]
  53. pub struct State {
  54. pub name: String,
  55. pub strct: ItemStruct,
  56. pub ctor_and_anchor: Option<(ImplItemMethod, Ident)>,
  57. pub impl_block_and_methods: Option<(ItemImpl, Vec<StateIx>)>,
  58. pub interfaces: Option<Vec<StateInterface>>,
  59. pub is_zero_copy: bool,
  60. }
  61. #[derive(Debug)]
  62. pub struct StateIx {
  63. pub raw_method: ImplItemMethod,
  64. pub ident: Ident,
  65. pub args: Vec<IxArg>,
  66. pub anchor_ident: Ident,
  67. // True if there exists a &self on the method.
  68. pub has_receiver: bool,
  69. }
  70. #[derive(Debug)]
  71. pub struct StateInterface {
  72. pub trait_name: String,
  73. pub methods: Vec<StateIx>,
  74. }
  75. #[derive(Debug)]
  76. pub struct Ix {
  77. pub raw_method: ItemFn,
  78. pub ident: Ident,
  79. pub docs: Option<Vec<String>>,
  80. pub args: Vec<IxArg>,
  81. pub returns: IxReturn,
  82. // The ident for the struct deriving Accounts.
  83. pub anchor_ident: Ident,
  84. }
  85. #[derive(Debug)]
  86. pub struct IxArg {
  87. pub name: Ident,
  88. pub docs: Option<Vec<String>>,
  89. pub raw_arg: PatType,
  90. }
  91. #[derive(Debug)]
  92. pub struct IxReturn {
  93. pub ty: Type,
  94. }
  95. #[derive(Debug)]
  96. pub struct FallbackFn {
  97. raw_method: ItemFn,
  98. }
  99. #[derive(Debug)]
  100. pub struct AccountsStruct {
  101. // Name of the accounts struct.
  102. pub ident: Ident,
  103. // Generics + lifetimes on the accounts struct.
  104. pub generics: Generics,
  105. // Fields on the accounts struct.
  106. pub fields: Vec<AccountField>,
  107. // Instruction data api expression.
  108. instruction_api: Option<Punctuated<Expr, Comma>>,
  109. }
  110. impl Parse for AccountsStruct {
  111. fn parse(input: ParseStream) -> ParseResult<Self> {
  112. let strct = <ItemStruct as Parse>::parse(input)?;
  113. accounts_parser::parse(&strct)
  114. }
  115. }
  116. impl From<&AccountsStruct> for TokenStream {
  117. fn from(accounts: &AccountsStruct) -> Self {
  118. accounts_codegen::generate(accounts)
  119. }
  120. }
  121. impl ToTokens for AccountsStruct {
  122. fn to_tokens(&self, tokens: &mut TokenStream) {
  123. tokens.extend::<TokenStream>(self.into());
  124. }
  125. }
  126. impl AccountsStruct {
  127. pub fn new(
  128. strct: ItemStruct,
  129. fields: Vec<AccountField>,
  130. instruction_api: Option<Punctuated<Expr, Comma>>,
  131. ) -> Self {
  132. let ident = strct.ident.clone();
  133. let generics = strct.generics;
  134. Self {
  135. ident,
  136. generics,
  137. fields,
  138. instruction_api,
  139. }
  140. }
  141. // Return value maps instruction name to type.
  142. // E.g. if we have `#[instruction(data: u64)]` then returns
  143. // { "data": "u64"}.
  144. pub fn instruction_args(&self) -> Option<HashMap<String, String>> {
  145. self.instruction_api.as_ref().map(|instruction_api| {
  146. instruction_api
  147. .iter()
  148. .map(|expr| {
  149. let arg = parser::tts_to_string(&expr);
  150. let components: Vec<&str> = arg.split(" : ").collect();
  151. assert!(components.len() == 2);
  152. (components[0].to_string(), components[1].to_string())
  153. })
  154. .collect()
  155. })
  156. }
  157. pub fn field_names(&self) -> Vec<String> {
  158. self.fields
  159. .iter()
  160. .map(|field| field.ident().to_string())
  161. .collect()
  162. }
  163. }
  164. #[allow(clippy::large_enum_variant)]
  165. #[derive(Debug)]
  166. pub enum AccountField {
  167. Field(Field),
  168. CompositeField(CompositeField),
  169. }
  170. impl AccountField {
  171. fn ident(&self) -> &Ident {
  172. match self {
  173. AccountField::Field(field) => &field.ident,
  174. AccountField::CompositeField(c_field) => &c_field.ident,
  175. }
  176. }
  177. pub fn ty_name(&self) -> Option<String> {
  178. match self {
  179. AccountField::Field(field) => match &field.ty {
  180. Ty::Account(account) => Some(parser::tts_to_string(&account.account_type_path)),
  181. Ty::ProgramAccount(account) => {
  182. Some(parser::tts_to_string(&account.account_type_path))
  183. }
  184. _ => None,
  185. },
  186. AccountField::CompositeField(field) => Some(field.symbol.clone()),
  187. }
  188. }
  189. }
  190. #[derive(Debug)]
  191. pub struct Field {
  192. pub ident: Ident,
  193. pub constraints: ConstraintGroup,
  194. pub ty: Ty,
  195. /// IDL Doc comment
  196. pub docs: Option<Vec<String>>,
  197. }
  198. impl Field {
  199. pub fn typed_ident(&self) -> proc_macro2::TokenStream {
  200. let name = &self.ident;
  201. let ty_decl = self.ty_decl();
  202. quote! {
  203. #name: #ty_decl
  204. }
  205. }
  206. pub fn ty_decl(&self) -> proc_macro2::TokenStream {
  207. let account_ty = self.account_ty();
  208. let container_ty = self.container_ty();
  209. match &self.ty {
  210. Ty::AccountInfo => quote! {
  211. AccountInfo
  212. },
  213. Ty::UncheckedAccount => quote! {
  214. UncheckedAccount
  215. },
  216. Ty::Signer => quote! {
  217. Signer
  218. },
  219. Ty::ProgramData => quote! {
  220. ProgramData
  221. },
  222. Ty::SystemAccount => quote! {
  223. SystemAccount
  224. },
  225. Ty::Account(AccountTy { boxed, .. }) => {
  226. if *boxed {
  227. quote! {
  228. Box<#container_ty<#account_ty>>
  229. }
  230. } else {
  231. quote! {
  232. #container_ty<#account_ty>
  233. }
  234. }
  235. }
  236. Ty::Sysvar(ty) => {
  237. let account = match ty {
  238. SysvarTy::Clock => quote! {Clock},
  239. SysvarTy::Rent => quote! {Rent},
  240. SysvarTy::EpochSchedule => quote! {EpochSchedule},
  241. SysvarTy::Fees => quote! {Fees},
  242. SysvarTy::RecentBlockhashes => quote! {RecentBlockhashes},
  243. SysvarTy::SlotHashes => quote! {SlotHashes},
  244. SysvarTy::SlotHistory => quote! {SlotHistory},
  245. SysvarTy::StakeHistory => quote! {StakeHistory},
  246. SysvarTy::Instructions => quote! {Instructions},
  247. SysvarTy::Rewards => quote! {Rewards},
  248. };
  249. quote! {
  250. Sysvar<#account>
  251. }
  252. }
  253. _ => quote! {
  254. #container_ty<#account_ty>
  255. },
  256. }
  257. }
  258. // TODO: remove the option once `CpiAccount` is completely removed (not
  259. // just deprecated).
  260. pub fn from_account_info(
  261. &self,
  262. kind: Option<&InitKind>,
  263. checked: bool,
  264. ) -> proc_macro2::TokenStream {
  265. let field = &self.ident;
  266. let field_str = field.to_string();
  267. let container_ty = self.container_ty();
  268. let owner_addr = match &kind {
  269. None => quote! { program_id },
  270. Some(InitKind::Program { .. }) => quote! {
  271. program_id
  272. },
  273. _ => quote! {
  274. &anchor_spl::token::ID
  275. },
  276. };
  277. match &self.ty {
  278. Ty::AccountInfo => quote! { #field.to_account_info() },
  279. Ty::UncheckedAccount => {
  280. quote! { UncheckedAccount::try_from(#field.to_account_info()) }
  281. }
  282. Ty::Account(AccountTy { boxed, .. }) => {
  283. let stream = if checked {
  284. quote! {
  285. #container_ty::try_from(
  286. &#field,
  287. ).map_err(|e| e.with_account_name(#field_str))?
  288. }
  289. } else {
  290. quote! {
  291. #container_ty::try_from_unchecked(
  292. &#field,
  293. ).map_err(|e| e.with_account_name(#field_str))?
  294. }
  295. };
  296. if *boxed {
  297. quote! {
  298. Box::new(#stream)
  299. }
  300. } else {
  301. stream
  302. }
  303. }
  304. Ty::CpiAccount(_) => {
  305. if checked {
  306. quote! {
  307. #container_ty::try_from(
  308. &#field,
  309. ).map_err(|e| e.with_account_name(#field_str))?
  310. }
  311. } else {
  312. quote! {
  313. #container_ty::try_from_unchecked(
  314. &#field,
  315. ).map_err(|e| e.with_account_name(#field_str))?
  316. }
  317. }
  318. }
  319. Ty::AccountLoader(_) => {
  320. if checked {
  321. quote! {
  322. #container_ty::try_from(
  323. &#field,
  324. ).map_err(|e| e.with_account_name(#field_str))?
  325. }
  326. } else {
  327. quote! {
  328. #container_ty::try_from_unchecked(
  329. #owner_addr,
  330. &#field,
  331. ).map_err(|e| e.with_account_name(#field_str))?
  332. }
  333. }
  334. }
  335. _ => {
  336. if checked {
  337. quote! {
  338. #container_ty::try_from(
  339. #owner_addr,
  340. &#field,
  341. ).map_err(|e| e.with_account_name(#field_str))?
  342. }
  343. } else {
  344. quote! {
  345. #container_ty::try_from_unchecked(
  346. #owner_addr,
  347. &#field,
  348. ).map_err(|e| e.with_account_name(#field_str))?
  349. }
  350. }
  351. }
  352. }
  353. }
  354. pub fn container_ty(&self) -> proc_macro2::TokenStream {
  355. match &self.ty {
  356. Ty::ProgramAccount(_) => quote! {
  357. anchor_lang::accounts::program_account::ProgramAccount
  358. },
  359. Ty::Account(_) => quote! {
  360. anchor_lang::accounts::account::Account
  361. },
  362. Ty::AccountLoader(_) => quote! {
  363. anchor_lang::accounts::account_loader::AccountLoader
  364. },
  365. Ty::Loader(_) => quote! {
  366. anchor_lang::accounts::loader::Loader
  367. },
  368. Ty::CpiAccount(_) => quote! {
  369. anchor_lang::accounts::cpi_account::CpiAccount
  370. },
  371. Ty::Sysvar(_) => quote! { anchor_lang::accounts::sysvar::Sysvar },
  372. Ty::CpiState(_) => quote! { anchor_lang::accounts::cpi_state::CpiState },
  373. Ty::ProgramState(_) => quote! { anchor_lang::accounts::state::ProgramState },
  374. Ty::Program(_) => quote! { anchor_lang::accounts::program::Program },
  375. Ty::AccountInfo => quote! {},
  376. Ty::UncheckedAccount => quote! {},
  377. Ty::Signer => quote! {},
  378. Ty::SystemAccount => quote! {},
  379. Ty::ProgramData => quote! {},
  380. }
  381. }
  382. // Returns the inner account struct type.
  383. pub fn account_ty(&self) -> proc_macro2::TokenStream {
  384. match &self.ty {
  385. Ty::AccountInfo => quote! {
  386. AccountInfo
  387. },
  388. Ty::UncheckedAccount => quote! {
  389. UncheckedAccount
  390. },
  391. Ty::Signer => quote! {
  392. Signer
  393. },
  394. Ty::SystemAccount => quote! {
  395. SystemAccount
  396. },
  397. Ty::ProgramData => quote! {
  398. ProgramData
  399. },
  400. Ty::ProgramAccount(ty) => {
  401. let ident = &ty.account_type_path;
  402. quote! {
  403. #ident
  404. }
  405. }
  406. Ty::Account(ty) => {
  407. let ident = &ty.account_type_path;
  408. quote! {
  409. #ident
  410. }
  411. }
  412. Ty::AccountLoader(ty) => {
  413. let ident = &ty.account_type_path;
  414. quote! {
  415. #ident
  416. }
  417. }
  418. Ty::Loader(ty) => {
  419. let ident = &ty.account_type_path;
  420. quote! {
  421. #ident
  422. }
  423. }
  424. Ty::CpiAccount(ty) => {
  425. let ident = &ty.account_type_path;
  426. quote! {
  427. #ident
  428. }
  429. }
  430. Ty::ProgramState(ty) => {
  431. let account = &ty.account_type_path;
  432. quote! {
  433. #account
  434. }
  435. }
  436. Ty::CpiState(ty) => {
  437. let account = &ty.account_type_path;
  438. quote! {
  439. #account
  440. }
  441. }
  442. Ty::Sysvar(ty) => match ty {
  443. SysvarTy::Clock => quote! {Clock},
  444. SysvarTy::Rent => quote! {Rent},
  445. SysvarTy::EpochSchedule => quote! {EpochSchedule},
  446. SysvarTy::Fees => quote! {Fees},
  447. SysvarTy::RecentBlockhashes => quote! {RecentBlockhashes},
  448. SysvarTy::SlotHashes => quote! {SlotHashes},
  449. SysvarTy::SlotHistory => quote! {SlotHistory},
  450. SysvarTy::StakeHistory => quote! {StakeHistory},
  451. SysvarTy::Instructions => quote! {Instructions},
  452. SysvarTy::Rewards => quote! {Rewards},
  453. },
  454. Ty::Program(ty) => {
  455. let program = &ty.account_type_path;
  456. quote! {
  457. #program
  458. }
  459. }
  460. }
  461. }
  462. }
  463. #[derive(Debug)]
  464. pub struct CompositeField {
  465. pub ident: Ident,
  466. pub constraints: ConstraintGroup,
  467. pub symbol: String,
  468. pub raw_field: syn::Field,
  469. /// IDL Doc comment
  470. pub docs: Option<Vec<String>>,
  471. }
  472. // A type of an account field.
  473. #[derive(Debug, PartialEq)]
  474. pub enum Ty {
  475. AccountInfo,
  476. UncheckedAccount,
  477. ProgramState(ProgramStateTy),
  478. CpiState(CpiStateTy),
  479. ProgramAccount(ProgramAccountTy),
  480. Loader(LoaderTy),
  481. AccountLoader(AccountLoaderTy),
  482. CpiAccount(CpiAccountTy),
  483. Sysvar(SysvarTy),
  484. Account(AccountTy),
  485. Program(ProgramTy),
  486. Signer,
  487. SystemAccount,
  488. ProgramData,
  489. }
  490. #[derive(Debug, PartialEq)]
  491. pub enum SysvarTy {
  492. Clock,
  493. Rent,
  494. EpochSchedule,
  495. Fees,
  496. RecentBlockhashes,
  497. SlotHashes,
  498. SlotHistory,
  499. StakeHistory,
  500. Instructions,
  501. Rewards,
  502. }
  503. #[derive(Debug, PartialEq)]
  504. pub struct ProgramStateTy {
  505. pub account_type_path: TypePath,
  506. }
  507. #[derive(Debug, PartialEq)]
  508. pub struct CpiStateTy {
  509. pub account_type_path: TypePath,
  510. }
  511. #[derive(Debug, PartialEq)]
  512. pub struct ProgramAccountTy {
  513. // The struct type of the account.
  514. pub account_type_path: TypePath,
  515. }
  516. #[derive(Debug, PartialEq)]
  517. pub struct CpiAccountTy {
  518. // The struct type of the account.
  519. pub account_type_path: TypePath,
  520. }
  521. #[derive(Debug, PartialEq)]
  522. pub struct AccountLoaderTy {
  523. // The struct type of the account.
  524. pub account_type_path: TypePath,
  525. }
  526. #[derive(Debug, PartialEq)]
  527. pub struct LoaderTy {
  528. // The struct type of the account.
  529. pub account_type_path: TypePath,
  530. }
  531. #[derive(Debug, PartialEq)]
  532. pub struct AccountTy {
  533. // The struct type of the account.
  534. pub account_type_path: TypePath,
  535. // True if the account has been boxed via `Box<T>`.
  536. pub boxed: bool,
  537. }
  538. #[derive(Debug, PartialEq)]
  539. pub struct ProgramTy {
  540. // The struct type of the account.
  541. pub account_type_path: TypePath,
  542. }
  543. #[derive(Debug)]
  544. pub struct Error {
  545. pub name: String,
  546. pub raw_enum: ItemEnum,
  547. pub ident: Ident,
  548. pub codes: Vec<ErrorCode>,
  549. pub args: Option<ErrorArgs>,
  550. }
  551. #[derive(Debug)]
  552. pub struct ErrorArgs {
  553. pub offset: LitInt,
  554. }
  555. impl Parse for ErrorArgs {
  556. fn parse(stream: ParseStream) -> ParseResult<Self> {
  557. let offset_span = stream.span();
  558. let offset = stream.call(Ident::parse_any)?;
  559. if offset.to_string().as_str() != "offset" {
  560. return Err(ParseError::new(offset_span, "expected keyword offset"));
  561. }
  562. stream.parse::<Token![=]>()?;
  563. Ok(ErrorArgs {
  564. offset: stream.parse()?,
  565. })
  566. }
  567. }
  568. #[derive(Debug)]
  569. pub struct ErrorCode {
  570. pub id: u32,
  571. pub ident: Ident,
  572. pub msg: Option<String>,
  573. }
  574. // All well formed constraints on a single `Accounts` field.
  575. #[derive(Debug, Default, Clone)]
  576. pub struct ConstraintGroup {
  577. init: Option<ConstraintInitGroup>,
  578. zeroed: Option<ConstraintZeroed>,
  579. mutable: Option<ConstraintMut>,
  580. signer: Option<ConstraintSigner>,
  581. owner: Option<ConstraintOwner>,
  582. rent_exempt: Option<ConstraintRentExempt>,
  583. seeds: Option<ConstraintSeedsGroup>,
  584. executable: Option<ConstraintExecutable>,
  585. state: Option<ConstraintState>,
  586. has_one: Vec<ConstraintHasOne>,
  587. literal: Vec<ConstraintLiteral>,
  588. raw: Vec<ConstraintRaw>,
  589. close: Option<ConstraintClose>,
  590. address: Option<ConstraintAddress>,
  591. associated_token: Option<ConstraintAssociatedToken>,
  592. token_account: Option<ConstraintTokenAccountGroup>,
  593. mint: Option<ConstraintTokenMintGroup>,
  594. }
  595. impl ConstraintGroup {
  596. pub fn is_zeroed(&self) -> bool {
  597. self.zeroed.is_some()
  598. }
  599. pub fn is_mutable(&self) -> bool {
  600. self.mutable.is_some()
  601. }
  602. pub fn is_signer(&self) -> bool {
  603. self.signer.is_some()
  604. }
  605. pub fn is_close(&self) -> bool {
  606. self.close.is_some()
  607. }
  608. }
  609. // A single account constraint *after* merging all tokens into a well formed
  610. // constraint. Some constraints like "seeds" are defined by multiple
  611. // tokens, so a merging phase is required.
  612. #[allow(clippy::large_enum_variant)]
  613. #[derive(Debug)]
  614. pub enum Constraint {
  615. Init(ConstraintInitGroup),
  616. Zeroed(ConstraintZeroed),
  617. Mut(ConstraintMut),
  618. Signer(ConstraintSigner),
  619. HasOne(ConstraintHasOne),
  620. Literal(ConstraintLiteral),
  621. Raw(ConstraintRaw),
  622. Owner(ConstraintOwner),
  623. RentExempt(ConstraintRentExempt),
  624. Seeds(ConstraintSeedsGroup),
  625. AssociatedToken(ConstraintAssociatedToken),
  626. Executable(ConstraintExecutable),
  627. State(ConstraintState),
  628. Close(ConstraintClose),
  629. Address(ConstraintAddress),
  630. TokenAccount(ConstraintTokenAccountGroup),
  631. Mint(ConstraintTokenMintGroup),
  632. }
  633. // Constraint token is a single keyword in a `#[account(<TOKEN>)]` attribute.
  634. #[allow(clippy::large_enum_variant)]
  635. #[derive(Debug)]
  636. pub enum ConstraintToken {
  637. Init(Context<ConstraintInit>),
  638. Zeroed(Context<ConstraintZeroed>),
  639. Mut(Context<ConstraintMut>),
  640. Signer(Context<ConstraintSigner>),
  641. HasOne(Context<ConstraintHasOne>),
  642. Literal(Context<ConstraintLiteral>),
  643. Raw(Context<ConstraintRaw>),
  644. Owner(Context<ConstraintOwner>),
  645. RentExempt(Context<ConstraintRentExempt>),
  646. Seeds(Context<ConstraintSeeds>),
  647. Executable(Context<ConstraintExecutable>),
  648. State(Context<ConstraintState>),
  649. Close(Context<ConstraintClose>),
  650. Payer(Context<ConstraintPayer>),
  651. Space(Context<ConstraintSpace>),
  652. Address(Context<ConstraintAddress>),
  653. TokenMint(Context<ConstraintTokenMint>),
  654. TokenAuthority(Context<ConstraintTokenAuthority>),
  655. AssociatedTokenMint(Context<ConstraintTokenMint>),
  656. AssociatedTokenAuthority(Context<ConstraintTokenAuthority>),
  657. MintAuthority(Context<ConstraintMintAuthority>),
  658. MintFreezeAuthority(Context<ConstraintMintFreezeAuthority>),
  659. MintDecimals(Context<ConstraintMintDecimals>),
  660. Bump(Context<ConstraintTokenBump>),
  661. ProgramSeed(Context<ConstraintProgramSeed>),
  662. }
  663. impl Parse for ConstraintToken {
  664. fn parse(stream: ParseStream) -> ParseResult<Self> {
  665. accounts_parser::constraints::parse_token(stream)
  666. }
  667. }
  668. #[derive(Debug, Clone)]
  669. pub struct ConstraintInit {
  670. pub if_needed: bool,
  671. }
  672. #[derive(Debug, Clone)]
  673. pub struct ConstraintInitIfNeeded {}
  674. #[derive(Debug, Clone)]
  675. pub struct ConstraintZeroed {}
  676. #[derive(Debug, Clone)]
  677. pub struct ConstraintMut {
  678. pub error: Option<Expr>,
  679. }
  680. #[derive(Debug, Clone)]
  681. pub struct ConstraintSigner {
  682. pub error: Option<Expr>,
  683. }
  684. #[derive(Debug, Clone)]
  685. pub struct ConstraintHasOne {
  686. pub join_target: Expr,
  687. pub error: Option<Expr>,
  688. }
  689. #[derive(Debug, Clone)]
  690. pub struct ConstraintLiteral {
  691. pub lit: LitStr,
  692. }
  693. #[derive(Debug, Clone)]
  694. pub struct ConstraintRaw {
  695. pub raw: Expr,
  696. pub error: Option<Expr>,
  697. }
  698. #[derive(Debug, Clone)]
  699. pub struct ConstraintOwner {
  700. pub owner_address: Expr,
  701. pub error: Option<Expr>,
  702. }
  703. #[derive(Debug, Clone)]
  704. pub struct ConstraintAddress {
  705. pub address: Expr,
  706. pub error: Option<Expr>,
  707. }
  708. #[derive(Debug, Clone)]
  709. pub enum ConstraintRentExempt {
  710. Enforce,
  711. Skip,
  712. }
  713. #[derive(Debug, Clone)]
  714. pub struct ConstraintInitGroup {
  715. pub if_needed: bool,
  716. pub seeds: Option<ConstraintSeedsGroup>,
  717. pub payer: Expr,
  718. pub space: Option<Expr>,
  719. pub kind: InitKind,
  720. }
  721. #[derive(Debug, Clone)]
  722. pub struct ConstraintSeedsGroup {
  723. pub is_init: bool,
  724. pub seeds: Punctuated<Expr, Token![,]>,
  725. pub bump: Option<Expr>, // None => bump was given without a target.
  726. pub program_seed: Option<Expr>, // None => use the current program's program_id.
  727. }
  728. #[derive(Debug, Clone)]
  729. pub struct ConstraintSeeds {
  730. pub seeds: Punctuated<Expr, Token![,]>,
  731. }
  732. #[derive(Debug, Clone)]
  733. pub struct ConstraintExecutable {}
  734. #[derive(Debug, Clone)]
  735. pub struct ConstraintState {
  736. pub program_target: Ident,
  737. }
  738. #[derive(Debug, Clone)]
  739. pub struct ConstraintPayer {
  740. pub target: Expr,
  741. }
  742. #[derive(Debug, Clone)]
  743. pub struct ConstraintSpace {
  744. pub space: Expr,
  745. }
  746. #[derive(Debug, Clone)]
  747. #[allow(clippy::large_enum_variant)]
  748. pub enum InitKind {
  749. Program {
  750. owner: Option<Expr>,
  751. },
  752. // Owner for token and mint represents the authority. Not to be confused
  753. // with the owner of the AccountInfo.
  754. Token {
  755. owner: Expr,
  756. mint: Expr,
  757. },
  758. AssociatedToken {
  759. owner: Expr,
  760. mint: Expr,
  761. },
  762. Mint {
  763. owner: Expr,
  764. freeze_authority: Option<Expr>,
  765. decimals: Expr,
  766. },
  767. }
  768. #[derive(Debug, Clone)]
  769. pub struct ConstraintClose {
  770. pub sol_dest: Ident,
  771. }
  772. #[derive(Debug, Clone)]
  773. pub struct ConstraintTokenMint {
  774. mint: Expr,
  775. }
  776. #[derive(Debug, Clone)]
  777. pub struct ConstraintTokenAuthority {
  778. auth: Expr,
  779. }
  780. #[derive(Debug, Clone)]
  781. pub struct ConstraintMintAuthority {
  782. mint_auth: Expr,
  783. }
  784. #[derive(Debug, Clone)]
  785. pub struct ConstraintMintFreezeAuthority {
  786. mint_freeze_auth: Expr,
  787. }
  788. #[derive(Debug, Clone)]
  789. pub struct ConstraintMintDecimals {
  790. decimals: Expr,
  791. }
  792. #[derive(Debug, Clone)]
  793. pub struct ConstraintTokenBump {
  794. bump: Option<Expr>,
  795. }
  796. #[derive(Debug, Clone)]
  797. pub struct ConstraintProgramSeed {
  798. program_seed: Expr,
  799. }
  800. #[derive(Debug, Clone)]
  801. pub struct ConstraintAssociatedToken {
  802. pub wallet: Expr,
  803. pub mint: Expr,
  804. }
  805. #[derive(Debug, Clone)]
  806. pub struct ConstraintTokenAccountGroup {
  807. pub mint: Option<Expr>,
  808. pub authority: Option<Expr>,
  809. }
  810. #[derive(Debug, Clone)]
  811. pub struct ConstraintTokenMintGroup {
  812. pub decimals: Option<Expr>,
  813. pub mint_authority: Option<Expr>,
  814. pub freeze_authority: Option<Expr>,
  815. }
  816. // Syntaxt context object for preserving metadata about the inner item.
  817. #[derive(Debug, Clone)]
  818. pub struct Context<T> {
  819. span: Span,
  820. inner: T,
  821. }
  822. impl<T> Context<T> {
  823. pub fn new(span: Span, inner: T) -> Self {
  824. Self { span, inner }
  825. }
  826. pub fn into_inner(self) -> T {
  827. self.inner
  828. }
  829. }
  830. impl<T> Deref for Context<T> {
  831. type Target = T;
  832. fn deref(&self) -> &Self::Target {
  833. &self.inner
  834. }
  835. }
  836. impl<T> Spanned for Context<T> {
  837. fn span(&self) -> Span {
  838. self.span
  839. }
  840. }