lib.rs 19 KB

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