constraints.rs 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752
  1. use crate::*;
  2. use syn::ext::IdentExt;
  3. use syn::parse::{Error as ParseError, Parse, ParseStream, Result as ParseResult};
  4. use syn::punctuated::Punctuated;
  5. use syn::spanned::Spanned;
  6. use syn::token::Comma;
  7. use syn::{bracketed, Expr, Ident, LitStr, Token};
  8. pub fn parse(
  9. f: &syn::Field,
  10. f_ty: Option<&Ty>,
  11. has_instruction_api: bool,
  12. ) -> ParseResult<(ConstraintGroup, ConstraintGroup)> {
  13. let mut constraints = ConstraintGroupBuilder::new(f_ty);
  14. for attr in f.attrs.iter().filter(is_account) {
  15. for c in attr.parse_args_with(Punctuated::<ConstraintToken, Comma>::parse_terminated)? {
  16. constraints.add(c)?;
  17. }
  18. }
  19. let account_constraints = constraints.build()?;
  20. let mut constraints = ConstraintGroupBuilder::new(f_ty);
  21. for attr in f.attrs.iter().filter(is_instruction) {
  22. if !has_instruction_api {
  23. return Err(ParseError::new(
  24. attr.span(),
  25. "an instruction api must be declared",
  26. ));
  27. }
  28. for c in attr.parse_args_with(Punctuated::<ConstraintToken, Comma>::parse_terminated)? {
  29. constraints.add(c)?;
  30. }
  31. }
  32. let instruction_constraints = constraints.build()?;
  33. Ok((account_constraints, instruction_constraints))
  34. }
  35. pub fn is_account(attr: &&syn::Attribute) -> bool {
  36. attr.path
  37. .get_ident()
  38. .map_or(false, |ident| ident == "account")
  39. }
  40. pub fn is_instruction(attr: &&syn::Attribute) -> bool {
  41. attr.path
  42. .get_ident()
  43. .map_or(false, |ident| ident == "instruction")
  44. }
  45. // Parses a single constraint from a parse stream for `#[account(<STREAM>)]`.
  46. pub fn parse_token(stream: ParseStream) -> ParseResult<ConstraintToken> {
  47. let is_lit = stream.peek(LitStr);
  48. if is_lit {
  49. let lit: LitStr = stream.parse()?;
  50. let c = ConstraintToken::Literal(Context::new(lit.span(), ConstraintLiteral { lit }));
  51. return Ok(c);
  52. }
  53. let ident = stream.call(Ident::parse_any)?;
  54. let kw = ident.to_string();
  55. let c = match kw.as_str() {
  56. "init" => ConstraintToken::Init(Context::new(ident.span(), ConstraintInit {})),
  57. "zero" => ConstraintToken::Zeroed(Context::new(ident.span(), ConstraintZeroed {})),
  58. "mut" => ConstraintToken::Mut(Context::new(ident.span(), ConstraintMut {})),
  59. "signer" => ConstraintToken::Signer(Context::new(ident.span(), ConstraintSigner {})),
  60. "executable" => {
  61. ConstraintToken::Executable(Context::new(ident.span(), ConstraintExecutable {}))
  62. }
  63. "mint" => {
  64. stream.parse::<Token![:]>()?;
  65. stream.parse::<Token![:]>()?;
  66. let kw = stream.call(Ident::parse_any)?.to_string();
  67. stream.parse::<Token![=]>()?;
  68. let span = ident
  69. .span()
  70. .join(stream.span())
  71. .unwrap_or_else(|| ident.span());
  72. match kw.as_str() {
  73. "authority" => ConstraintToken::MintAuthority(Context::new(
  74. span,
  75. ConstraintMintAuthority {
  76. mint_auth: stream.parse()?,
  77. },
  78. )),
  79. "decimals" => ConstraintToken::MintDecimals(Context::new(
  80. span,
  81. ConstraintMintDecimals {
  82. decimals: stream.parse()?,
  83. },
  84. )),
  85. _ => return Err(ParseError::new(ident.span(), "Invalid attribute")),
  86. }
  87. }
  88. "token" => {
  89. stream.parse::<Token![:]>()?;
  90. stream.parse::<Token![:]>()?;
  91. let kw = stream.call(Ident::parse_any)?.to_string();
  92. stream.parse::<Token![=]>()?;
  93. let span = ident
  94. .span()
  95. .join(stream.span())
  96. .unwrap_or_else(|| ident.span());
  97. match kw.as_str() {
  98. "mint" => ConstraintToken::TokenMint(Context::new(
  99. span,
  100. ConstraintTokenMint {
  101. mint: stream.parse()?,
  102. },
  103. )),
  104. "authority" => ConstraintToken::TokenAuthority(Context::new(
  105. span,
  106. ConstraintTokenAuthority {
  107. auth: stream.parse()?,
  108. },
  109. )),
  110. _ => return Err(ParseError::new(ident.span(), "Invalid attribute")),
  111. }
  112. }
  113. "bump" => {
  114. let bump = {
  115. if stream.peek(Token![=]) {
  116. stream.parse::<Token![=]>()?;
  117. Some(stream.parse()?)
  118. } else {
  119. None
  120. }
  121. };
  122. ConstraintToken::Bump(Context::new(ident.span(), ConstraintTokenBump { bump }))
  123. }
  124. _ => {
  125. stream.parse::<Token![=]>()?;
  126. let span = ident
  127. .span()
  128. .join(stream.span())
  129. .unwrap_or_else(|| ident.span());
  130. match kw.as_str() {
  131. // Deprecated since 0.11
  132. "belongs_to" => {
  133. return Err(ParseError::new(
  134. ident.span(),
  135. "belongs_to is deprecated, please use has_one",
  136. ))
  137. }
  138. "has_one" => ConstraintToken::HasOne(Context::new(
  139. span,
  140. ConstraintHasOne {
  141. join_target: stream.parse()?,
  142. },
  143. )),
  144. "owner" => ConstraintToken::Owner(Context::new(
  145. span,
  146. ConstraintOwner {
  147. owner_target: stream.parse()?,
  148. },
  149. )),
  150. "rent_exempt" => ConstraintToken::RentExempt(Context::new(
  151. span,
  152. match stream.parse::<Ident>()?.to_string().as_str() {
  153. "skip" => ConstraintRentExempt::Skip,
  154. "enforce" => ConstraintRentExempt::Enforce,
  155. _ => {
  156. return Err(ParseError::new(
  157. span,
  158. "rent_exempt must be either skip or enforce",
  159. ))
  160. }
  161. },
  162. )),
  163. "state" => ConstraintToken::State(Context::new(
  164. span,
  165. ConstraintState {
  166. program_target: stream.parse()?,
  167. },
  168. )),
  169. "payer" => ConstraintToken::Payer(Context::new(
  170. span,
  171. ConstraintPayer {
  172. target: stream.parse()?,
  173. },
  174. )),
  175. "space" => ConstraintToken::Space(Context::new(
  176. span,
  177. ConstraintSpace {
  178. space: stream.parse()?,
  179. },
  180. )),
  181. "seeds" => {
  182. let seeds;
  183. let bracket = bracketed!(seeds in stream);
  184. ConstraintToken::Seeds(Context::new(
  185. span.join(bracket.span).unwrap_or(span),
  186. ConstraintSeeds {
  187. seeds: seeds.parse_terminated(Expr::parse)?,
  188. },
  189. ))
  190. }
  191. "constraint" => ConstraintToken::Raw(Context::new(
  192. span,
  193. ConstraintRaw {
  194. raw: stream.parse()?,
  195. },
  196. )),
  197. "close" => ConstraintToken::Close(Context::new(
  198. span,
  199. ConstraintClose {
  200. sol_dest: stream.parse()?,
  201. },
  202. )),
  203. "address" => ConstraintToken::Address(Context::new(
  204. span,
  205. ConstraintAddress {
  206. address: stream.parse()?,
  207. },
  208. )),
  209. _ => return Err(ParseError::new(ident.span(), "Invalid attribute")),
  210. }
  211. }
  212. };
  213. Ok(c)
  214. }
  215. #[derive(Default)]
  216. pub struct ConstraintGroupBuilder<'ty> {
  217. pub f_ty: Option<&'ty Ty>,
  218. pub init: Option<Context<ConstraintInit>>,
  219. pub zeroed: Option<Context<ConstraintZeroed>>,
  220. pub mutable: Option<Context<ConstraintMut>>,
  221. pub signer: Option<Context<ConstraintSigner>>,
  222. pub has_one: Vec<Context<ConstraintHasOne>>,
  223. pub literal: Vec<Context<ConstraintLiteral>>,
  224. pub raw: Vec<Context<ConstraintRaw>>,
  225. pub owner: Option<Context<ConstraintOwner>>,
  226. pub rent_exempt: Option<Context<ConstraintRentExempt>>,
  227. pub seeds: Option<Context<ConstraintSeeds>>,
  228. pub executable: Option<Context<ConstraintExecutable>>,
  229. pub state: Option<Context<ConstraintState>>,
  230. pub payer: Option<Context<ConstraintPayer>>,
  231. pub space: Option<Context<ConstraintSpace>>,
  232. pub close: Option<Context<ConstraintClose>>,
  233. pub address: Option<Context<ConstraintAddress>>,
  234. pub token_mint: Option<Context<ConstraintTokenMint>>,
  235. pub token_authority: Option<Context<ConstraintTokenAuthority>>,
  236. pub mint_authority: Option<Context<ConstraintMintAuthority>>,
  237. pub mint_decimals: Option<Context<ConstraintMintDecimals>>,
  238. pub bump: Option<Context<ConstraintTokenBump>>,
  239. }
  240. impl<'ty> ConstraintGroupBuilder<'ty> {
  241. pub fn new(f_ty: Option<&'ty Ty>) -> Self {
  242. Self {
  243. f_ty,
  244. init: None,
  245. zeroed: None,
  246. mutable: None,
  247. signer: None,
  248. has_one: Vec::new(),
  249. literal: Vec::new(),
  250. raw: Vec::new(),
  251. owner: None,
  252. rent_exempt: None,
  253. seeds: None,
  254. executable: None,
  255. state: None,
  256. payer: None,
  257. space: None,
  258. close: None,
  259. address: None,
  260. token_mint: None,
  261. token_authority: None,
  262. mint_authority: None,
  263. mint_decimals: None,
  264. bump: None,
  265. }
  266. }
  267. pub fn build(mut self) -> ParseResult<ConstraintGroup> {
  268. // Init implies mutable and rent exempt.
  269. if let Some(i) = &self.init {
  270. match self.mutable {
  271. Some(m) => {
  272. return Err(ParseError::new(
  273. m.span(),
  274. "mut cannot be provided with init",
  275. ))
  276. }
  277. None => self
  278. .mutable
  279. .replace(Context::new(i.span(), ConstraintMut {})),
  280. };
  281. // Rent exempt if not explicitly skipped.
  282. if self.rent_exempt.is_none() {
  283. self.rent_exempt
  284. .replace(Context::new(i.span(), ConstraintRentExempt::Enforce));
  285. }
  286. }
  287. // Seeds.
  288. if let Some(z) = &self.zeroed {
  289. match self.mutable {
  290. Some(m) => {
  291. return Err(ParseError::new(
  292. m.span(),
  293. "mut cannot be provided with zeroed",
  294. ))
  295. }
  296. None => self
  297. .mutable
  298. .replace(Context::new(z.span(), ConstraintMut {})),
  299. };
  300. // Rent exempt if not explicitly skipped.
  301. if self.rent_exempt.is_none() {
  302. self.rent_exempt
  303. .replace(Context::new(z.span(), ConstraintRentExempt::Enforce));
  304. }
  305. }
  306. if let Some(i) = &self.seeds {
  307. if self.init.is_some() && self.payer.is_none() {
  308. return Err(ParseError::new(
  309. i.span(),
  310. "payer must be provided when creating a program derived address",
  311. ));
  312. }
  313. }
  314. // Token.
  315. if let Some(token_mint) = &self.token_mint {
  316. if self.token_authority.is_none() {
  317. return Err(ParseError::new(
  318. token_mint.span(),
  319. "token authority must be provided if token mint is",
  320. ));
  321. }
  322. if self.init.is_none() || self.seeds.is_none() {
  323. return Err(ParseError::new(
  324. token_mint.span(),
  325. "init is required for a pda token",
  326. ));
  327. }
  328. }
  329. if let Some(token_authority) = &self.token_authority {
  330. if self.token_mint.is_none() {
  331. return Err(ParseError::new(
  332. token_authority.span(),
  333. "token authority must be provided if token mint is",
  334. ));
  335. }
  336. }
  337. // Mint.
  338. if let Some(mint_decimals) = &self.mint_decimals {
  339. if self.mint_authority.is_none() {
  340. return Err(ParseError::new(
  341. mint_decimals.span(),
  342. "mint authority must be provided if mint decimals is",
  343. ));
  344. }
  345. }
  346. if let Some(mint_authority) = &self.mint_authority {
  347. if self.mint_decimals.is_none() {
  348. return Err(ParseError::new(
  349. mint_authority.span(),
  350. "mint decimals must be provided if mint authority is",
  351. ));
  352. }
  353. }
  354. // SPL Space.
  355. if self.init.is_some()
  356. && self.seeds.is_some()
  357. && self.token_mint.is_some()
  358. && (self.mint_authority.is_some() || self.token_authority.is_some())
  359. && self.space.is_some()
  360. {
  361. return Err(ParseError::new(
  362. self.space.as_ref().unwrap().span(),
  363. "space is not required for initializing an spl account",
  364. ));
  365. }
  366. let ConstraintGroupBuilder {
  367. f_ty: _,
  368. init,
  369. zeroed,
  370. mutable,
  371. signer,
  372. has_one,
  373. literal,
  374. raw,
  375. owner,
  376. rent_exempt,
  377. seeds,
  378. executable,
  379. state,
  380. payer,
  381. space,
  382. close,
  383. address,
  384. token_mint,
  385. token_authority,
  386. mint_authority,
  387. mint_decimals,
  388. bump,
  389. } = self;
  390. // Converts Option<Context<T>> -> Option<T>.
  391. macro_rules! into_inner {
  392. ($opt:ident) => {
  393. $opt.map(|c| c.into_inner())
  394. };
  395. ($opt:expr) => {
  396. $opt.map(|c| c.into_inner())
  397. };
  398. }
  399. // Converts Vec<Context<T>> - Vec<T>.
  400. macro_rules! into_inner_vec {
  401. ($opt:ident) => {
  402. $opt.into_iter().map(|c| c.into_inner()).collect()
  403. };
  404. }
  405. let (owner, pda_owner) = {
  406. if seeds.is_some() {
  407. (None, owner.map(|o| o.owner_target.clone()))
  408. } else {
  409. (owner, None)
  410. }
  411. };
  412. let is_init = init.is_some();
  413. Ok(ConstraintGroup {
  414. init: into_inner!(init),
  415. zeroed: into_inner!(zeroed),
  416. mutable: into_inner!(mutable),
  417. signer: into_inner!(signer),
  418. has_one: into_inner_vec!(has_one),
  419. literal: into_inner_vec!(literal),
  420. raw: into_inner_vec!(raw),
  421. owner: into_inner!(owner),
  422. rent_exempt: into_inner!(rent_exempt),
  423. executable: into_inner!(executable),
  424. state: into_inner!(state),
  425. close: into_inner!(close),
  426. address: into_inner!(address),
  427. seeds: seeds
  428. .map(|c| {
  429. Ok(ConstraintSeedsGroup {
  430. is_init,
  431. seeds: c.into_inner().seeds,
  432. payer: into_inner!(payer.clone()).map(|a| a.target),
  433. space: space.clone().map(|s| s.space.clone()),
  434. kind: if let Some(tm) = &token_mint {
  435. PdaKind::Token {
  436. mint: tm.clone().into_inner().mint,
  437. owner: match &token_authority {
  438. Some(a) => a.clone().into_inner().auth,
  439. None => return Err(ParseError::new(
  440. tm.span(),
  441. "authority must be provided to initialize a token program derived address"
  442. )),
  443. },
  444. }
  445. } else if let Some(d) = &mint_decimals {
  446. PdaKind::Mint {
  447. decimals: d.clone().into_inner().decimals,
  448. owner: match &mint_authority {
  449. Some(a) => a.clone().into_inner().mint_auth,
  450. None => return Err(ParseError::new(
  451. d.span(),
  452. "authority must be provided to initialize a mint program derived address"
  453. ))
  454. }
  455. }
  456. } else {
  457. PdaKind::Program {
  458. owner: pda_owner.clone(),
  459. }
  460. },
  461. bump: into_inner!(bump).map(|b| b.bump),
  462. })
  463. })
  464. .transpose()?,
  465. })
  466. }
  467. pub fn add(&mut self, c: ConstraintToken) -> ParseResult<()> {
  468. match c {
  469. ConstraintToken::Init(c) => self.add_init(c),
  470. ConstraintToken::Zeroed(c) => self.add_zeroed(c),
  471. ConstraintToken::Mut(c) => self.add_mut(c),
  472. ConstraintToken::Signer(c) => self.add_signer(c),
  473. ConstraintToken::HasOne(c) => self.add_has_one(c),
  474. ConstraintToken::Literal(c) => self.add_literal(c),
  475. ConstraintToken::Raw(c) => self.add_raw(c),
  476. ConstraintToken::Owner(c) => self.add_owner(c),
  477. ConstraintToken::RentExempt(c) => self.add_rent_exempt(c),
  478. ConstraintToken::Seeds(c) => self.add_seeds(c),
  479. ConstraintToken::Executable(c) => self.add_executable(c),
  480. ConstraintToken::State(c) => self.add_state(c),
  481. ConstraintToken::Payer(c) => self.add_payer(c),
  482. ConstraintToken::Space(c) => self.add_space(c),
  483. ConstraintToken::Close(c) => self.add_close(c),
  484. ConstraintToken::Address(c) => self.add_address(c),
  485. ConstraintToken::TokenAuthority(c) => self.add_token_authority(c),
  486. ConstraintToken::TokenMint(c) => self.add_token_mint(c),
  487. ConstraintToken::MintAuthority(c) => self.add_mint_authority(c),
  488. ConstraintToken::MintDecimals(c) => self.add_mint_decimals(c),
  489. ConstraintToken::Bump(c) => self.add_bump(c),
  490. }
  491. }
  492. fn add_init(&mut self, c: Context<ConstraintInit>) -> ParseResult<()> {
  493. if self.init.is_some() {
  494. return Err(ParseError::new(c.span(), "init already provided"));
  495. }
  496. if self.zeroed.is_some() {
  497. return Err(ParseError::new(c.span(), "zeroed already provided"));
  498. }
  499. self.init.replace(c);
  500. Ok(())
  501. }
  502. fn add_zeroed(&mut self, c: Context<ConstraintZeroed>) -> ParseResult<()> {
  503. if self.zeroed.is_some() {
  504. return Err(ParseError::new(c.span(), "zeroed already provided"));
  505. }
  506. if self.init.is_some() {
  507. return Err(ParseError::new(c.span(), "init already provided"));
  508. }
  509. self.zeroed.replace(c);
  510. Ok(())
  511. }
  512. fn add_close(&mut self, c: Context<ConstraintClose>) -> ParseResult<()> {
  513. if !matches!(self.f_ty, Some(Ty::ProgramAccount(_)))
  514. && !matches!(self.f_ty, Some(Ty::Loader(_)))
  515. {
  516. return Err(ParseError::new(
  517. c.span(),
  518. "close must be on a ProgramAccount",
  519. ));
  520. }
  521. if self.mutable.is_none() {
  522. return Err(ParseError::new(
  523. c.span(),
  524. "mut must be provided before close",
  525. ));
  526. }
  527. if self.close.is_some() {
  528. return Err(ParseError::new(c.span(), "close already provided"));
  529. }
  530. self.close.replace(c);
  531. Ok(())
  532. }
  533. fn add_address(&mut self, c: Context<ConstraintAddress>) -> ParseResult<()> {
  534. if self.address.is_some() {
  535. return Err(ParseError::new(c.span(), "address already provided"));
  536. }
  537. self.address.replace(c);
  538. Ok(())
  539. }
  540. fn add_token_mint(&mut self, c: Context<ConstraintTokenMint>) -> ParseResult<()> {
  541. if self.token_mint.is_some() {
  542. return Err(ParseError::new(c.span(), "token mint already provided"));
  543. }
  544. if self.init.is_none() {
  545. return Err(ParseError::new(
  546. c.span(),
  547. "init must be provided before token",
  548. ));
  549. }
  550. self.token_mint.replace(c);
  551. Ok(())
  552. }
  553. fn add_bump(&mut self, c: Context<ConstraintTokenBump>) -> ParseResult<()> {
  554. if self.bump.is_some() {
  555. return Err(ParseError::new(c.span(), "bump already provided"));
  556. }
  557. if self.seeds.is_none() {
  558. return Err(ParseError::new(
  559. c.span(),
  560. "seeds must be provided before bump",
  561. ));
  562. }
  563. self.bump.replace(c);
  564. Ok(())
  565. }
  566. fn add_token_authority(&mut self, c: Context<ConstraintTokenAuthority>) -> ParseResult<()> {
  567. if self.token_authority.is_some() {
  568. return Err(ParseError::new(
  569. c.span(),
  570. "token authority already provided",
  571. ));
  572. }
  573. if self.init.is_none() {
  574. return Err(ParseError::new(
  575. c.span(),
  576. "init must be provided before token authority",
  577. ));
  578. }
  579. self.token_authority.replace(c);
  580. Ok(())
  581. }
  582. fn add_mint_authority(&mut self, c: Context<ConstraintMintAuthority>) -> ParseResult<()> {
  583. if self.mint_authority.is_some() {
  584. return Err(ParseError::new(c.span(), "mint authority already provided"));
  585. }
  586. if self.init.is_none() {
  587. return Err(ParseError::new(
  588. c.span(),
  589. "init must be provided before mint authority",
  590. ));
  591. }
  592. self.mint_authority.replace(c);
  593. Ok(())
  594. }
  595. fn add_mint_decimals(&mut self, c: Context<ConstraintMintDecimals>) -> ParseResult<()> {
  596. if self.mint_decimals.is_some() {
  597. return Err(ParseError::new(c.span(), "mint decimals already provided"));
  598. }
  599. if self.init.is_none() {
  600. return Err(ParseError::new(
  601. c.span(),
  602. "init must be provided before mint decimals",
  603. ));
  604. }
  605. self.mint_decimals.replace(c);
  606. Ok(())
  607. }
  608. fn add_mut(&mut self, c: Context<ConstraintMut>) -> ParseResult<()> {
  609. if self.mutable.is_some() {
  610. return Err(ParseError::new(c.span(), "mut already provided"));
  611. }
  612. self.mutable.replace(c);
  613. Ok(())
  614. }
  615. fn add_signer(&mut self, c: Context<ConstraintSigner>) -> ParseResult<()> {
  616. if self.signer.is_some() {
  617. return Err(ParseError::new(c.span(), "signer already provided"));
  618. }
  619. self.signer.replace(c);
  620. Ok(())
  621. }
  622. fn add_has_one(&mut self, c: Context<ConstraintHasOne>) -> ParseResult<()> {
  623. if self
  624. .has_one
  625. .iter()
  626. .filter(|item| item.join_target == c.join_target)
  627. .count()
  628. > 0
  629. {
  630. return Err(ParseError::new(c.span(), "has_one target already provided"));
  631. }
  632. self.has_one.push(c);
  633. Ok(())
  634. }
  635. fn add_literal(&mut self, c: Context<ConstraintLiteral>) -> ParseResult<()> {
  636. self.literal.push(c);
  637. Ok(())
  638. }
  639. fn add_raw(&mut self, c: Context<ConstraintRaw>) -> ParseResult<()> {
  640. self.raw.push(c);
  641. Ok(())
  642. }
  643. fn add_owner(&mut self, c: Context<ConstraintOwner>) -> ParseResult<()> {
  644. if self.owner.is_some() {
  645. return Err(ParseError::new(c.span(), "owner already provided"));
  646. }
  647. self.owner.replace(c);
  648. Ok(())
  649. }
  650. fn add_rent_exempt(&mut self, c: Context<ConstraintRentExempt>) -> ParseResult<()> {
  651. if self.rent_exempt.is_some() {
  652. return Err(ParseError::new(c.span(), "rent already provided"));
  653. }
  654. self.rent_exempt.replace(c);
  655. Ok(())
  656. }
  657. fn add_seeds(&mut self, c: Context<ConstraintSeeds>) -> ParseResult<()> {
  658. if self.seeds.is_some() {
  659. return Err(ParseError::new(c.span(), "seeds already provided"));
  660. }
  661. self.seeds.replace(c);
  662. Ok(())
  663. }
  664. fn add_executable(&mut self, c: Context<ConstraintExecutable>) -> ParseResult<()> {
  665. if self.executable.is_some() {
  666. return Err(ParseError::new(c.span(), "executable already provided"));
  667. }
  668. self.executable.replace(c);
  669. Ok(())
  670. }
  671. fn add_state(&mut self, c: Context<ConstraintState>) -> ParseResult<()> {
  672. if self.state.is_some() {
  673. return Err(ParseError::new(c.span(), "state already provided"));
  674. }
  675. self.state.replace(c);
  676. Ok(())
  677. }
  678. fn add_payer(&mut self, c: Context<ConstraintPayer>) -> ParseResult<()> {
  679. if self.seeds.is_none() {
  680. return Err(ParseError::new(
  681. c.span(),
  682. "seeds must be provided before payer",
  683. ));
  684. }
  685. if self.payer.is_some() {
  686. return Err(ParseError::new(c.span(), "payer already provided"));
  687. }
  688. self.payer.replace(c);
  689. Ok(())
  690. }
  691. fn add_space(&mut self, c: Context<ConstraintSpace>) -> ParseResult<()> {
  692. if self.seeds.is_none() {
  693. return Err(ParseError::new(
  694. c.span(),
  695. "init must be provided before space",
  696. ));
  697. }
  698. if self.space.is_some() {
  699. return Err(ParseError::new(c.span(), "space already provided"));
  700. }
  701. self.space.replace(c);
  702. Ok(())
  703. }
  704. }