lib.rs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502
  1. use std::str::FromStr;
  2. use anyhow::anyhow;
  3. use serde::{Deserialize, Serialize};
  4. /// IDL specification Semantic Version
  5. pub const IDL_SPEC: &str = env!("CARGO_PKG_VERSION");
  6. #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
  7. pub struct Idl {
  8. pub address: String,
  9. pub metadata: IdlMetadata,
  10. #[serde(default, skip_serializing_if = "is_default")]
  11. pub docs: Vec<String>,
  12. pub instructions: Vec<IdlInstruction>,
  13. #[serde(default, skip_serializing_if = "is_default")]
  14. pub accounts: Vec<IdlAccount>,
  15. #[serde(default, skip_serializing_if = "is_default")]
  16. pub events: Vec<IdlEvent>,
  17. #[serde(default, skip_serializing_if = "is_default")]
  18. pub errors: Vec<IdlErrorCode>,
  19. #[serde(default, skip_serializing_if = "is_default")]
  20. pub types: Vec<IdlTypeDef>,
  21. #[serde(default, skip_serializing_if = "is_default")]
  22. pub constants: Vec<IdlConst>,
  23. }
  24. #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
  25. pub struct IdlMetadata {
  26. pub name: String,
  27. pub version: String,
  28. pub spec: String,
  29. #[serde(skip_serializing_if = "is_default")]
  30. pub description: Option<String>,
  31. #[serde(skip_serializing_if = "is_default")]
  32. pub repository: Option<String>,
  33. #[serde(default, skip_serializing_if = "is_default")]
  34. pub dependencies: Vec<IdlDependency>,
  35. #[serde(skip_serializing_if = "is_default")]
  36. pub contact: Option<String>,
  37. #[serde(skip_serializing_if = "is_default")]
  38. pub deployments: Option<IdlDeployments>,
  39. }
  40. #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
  41. pub struct IdlDependency {
  42. pub name: String,
  43. pub version: String,
  44. }
  45. #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
  46. pub struct IdlDeployments {
  47. pub mainnet: Option<String>,
  48. pub testnet: Option<String>,
  49. pub devnet: Option<String>,
  50. pub localnet: Option<String>,
  51. }
  52. #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
  53. pub struct IdlInstruction {
  54. pub name: String,
  55. #[serde(default, skip_serializing_if = "is_default")]
  56. pub docs: Vec<String>,
  57. pub discriminator: IdlDiscriminator,
  58. pub accounts: Vec<IdlInstructionAccountItem>,
  59. pub args: Vec<IdlField>,
  60. #[serde(skip_serializing_if = "is_default")]
  61. pub returns: Option<IdlType>,
  62. }
  63. #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
  64. #[serde(untagged)]
  65. pub enum IdlInstructionAccountItem {
  66. Composite(IdlInstructionAccounts),
  67. Single(IdlInstructionAccount),
  68. }
  69. #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
  70. pub struct IdlInstructionAccount {
  71. pub name: String,
  72. #[serde(default, skip_serializing_if = "is_default")]
  73. pub docs: Vec<String>,
  74. #[serde(default, skip_serializing_if = "is_default")]
  75. pub writable: bool,
  76. #[serde(default, skip_serializing_if = "is_default")]
  77. pub signer: bool,
  78. #[serde(default, skip_serializing_if = "is_default")]
  79. pub optional: bool,
  80. #[serde(skip_serializing_if = "is_default")]
  81. pub address: Option<String>,
  82. #[serde(skip_serializing_if = "is_default")]
  83. pub pda: Option<IdlPda>,
  84. #[serde(default, skip_serializing_if = "is_default")]
  85. pub relations: Vec<String>,
  86. }
  87. #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
  88. pub struct IdlInstructionAccounts {
  89. pub name: String,
  90. pub accounts: Vec<IdlInstructionAccountItem>,
  91. }
  92. #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
  93. pub struct IdlPda {
  94. pub seeds: Vec<IdlSeed>,
  95. #[serde(skip_serializing_if = "is_default")]
  96. pub program: Option<IdlSeed>,
  97. }
  98. #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
  99. #[serde(tag = "kind", rename_all = "lowercase")]
  100. pub enum IdlSeed {
  101. Const(IdlSeedConst),
  102. Arg(IdlSeedArg),
  103. Account(IdlSeedAccount),
  104. }
  105. #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
  106. pub struct IdlSeedConst {
  107. pub value: Vec<u8>,
  108. }
  109. #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
  110. pub struct IdlSeedArg {
  111. pub path: String,
  112. }
  113. #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
  114. pub struct IdlSeedAccount {
  115. pub path: String,
  116. #[serde(skip_serializing_if = "is_default")]
  117. pub account: Option<String>,
  118. }
  119. #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
  120. pub struct IdlAccount {
  121. pub name: String,
  122. pub discriminator: IdlDiscriminator,
  123. }
  124. #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
  125. pub struct IdlEvent {
  126. pub name: String,
  127. pub discriminator: IdlDiscriminator,
  128. }
  129. #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
  130. pub struct IdlConst {
  131. pub name: String,
  132. #[serde(default, skip_serializing_if = "is_default")]
  133. pub docs: Vec<String>,
  134. #[serde(rename = "type")]
  135. pub ty: IdlType,
  136. pub value: String,
  137. }
  138. #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
  139. pub struct IdlErrorCode {
  140. pub code: u32,
  141. pub name: String,
  142. #[serde(skip_serializing_if = "is_default")]
  143. pub msg: Option<String>,
  144. }
  145. #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
  146. pub struct IdlField {
  147. pub name: String,
  148. #[serde(default, skip_serializing_if = "is_default")]
  149. pub docs: Vec<String>,
  150. #[serde(rename = "type")]
  151. pub ty: IdlType,
  152. }
  153. #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
  154. pub struct IdlTypeDef {
  155. pub name: String,
  156. #[serde(default, skip_serializing_if = "is_default")]
  157. pub docs: Vec<String>,
  158. #[serde(default, skip_serializing_if = "is_default")]
  159. pub serialization: IdlSerialization,
  160. #[serde(skip_serializing_if = "is_default")]
  161. pub repr: Option<IdlRepr>,
  162. #[serde(default, skip_serializing_if = "is_default")]
  163. pub generics: Vec<IdlTypeDefGeneric>,
  164. #[serde(rename = "type")]
  165. pub ty: IdlTypeDefTy,
  166. }
  167. #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
  168. #[serde(rename_all = "lowercase")]
  169. #[non_exhaustive]
  170. pub enum IdlSerialization {
  171. #[default]
  172. Borsh,
  173. Bytemuck,
  174. BytemuckUnsafe,
  175. Custom(String),
  176. }
  177. #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
  178. #[serde(tag = "kind", rename_all = "lowercase")]
  179. #[non_exhaustive]
  180. pub enum IdlRepr {
  181. Rust(IdlReprModifier),
  182. C(IdlReprModifier),
  183. Transparent,
  184. }
  185. #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
  186. pub struct IdlReprModifier {
  187. #[serde(default, skip_serializing_if = "is_default")]
  188. pub packed: bool,
  189. #[serde(skip_serializing_if = "is_default")]
  190. pub align: Option<usize>,
  191. }
  192. #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
  193. #[serde(tag = "kind", rename_all = "lowercase")]
  194. pub enum IdlTypeDefGeneric {
  195. Type {
  196. name: String,
  197. },
  198. Const {
  199. name: String,
  200. #[serde(rename = "type")]
  201. ty: String,
  202. },
  203. }
  204. #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
  205. #[serde(tag = "kind", rename_all = "lowercase")]
  206. pub enum IdlTypeDefTy {
  207. Struct {
  208. #[serde(skip_serializing_if = "is_default")]
  209. fields: Option<IdlDefinedFields>,
  210. },
  211. Enum {
  212. variants: Vec<IdlEnumVariant>,
  213. },
  214. Type {
  215. alias: IdlType,
  216. },
  217. }
  218. #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
  219. pub struct IdlEnumVariant {
  220. pub name: String,
  221. #[serde(skip_serializing_if = "is_default")]
  222. pub fields: Option<IdlDefinedFields>,
  223. }
  224. #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
  225. #[serde(untagged)]
  226. pub enum IdlDefinedFields {
  227. Named(Vec<IdlField>),
  228. Tuple(Vec<IdlType>),
  229. }
  230. #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
  231. #[serde(rename_all = "lowercase")]
  232. pub enum IdlArrayLen {
  233. Generic(String),
  234. #[serde(untagged)]
  235. Value(usize),
  236. }
  237. #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
  238. #[serde(tag = "kind", rename_all = "lowercase")]
  239. pub enum IdlGenericArg {
  240. Type {
  241. #[serde(rename = "type")]
  242. ty: IdlType,
  243. },
  244. Const {
  245. value: String,
  246. },
  247. }
  248. #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
  249. #[serde(rename_all = "lowercase")]
  250. #[non_exhaustive]
  251. pub enum IdlType {
  252. Bool,
  253. U8,
  254. I8,
  255. U16,
  256. I16,
  257. U32,
  258. I32,
  259. F32,
  260. U64,
  261. I64,
  262. F64,
  263. U128,
  264. I128,
  265. U256,
  266. I256,
  267. Bytes,
  268. String,
  269. Pubkey,
  270. Option(Box<IdlType>),
  271. Vec(Box<IdlType>),
  272. Array(Box<IdlType>, IdlArrayLen),
  273. Defined {
  274. name: String,
  275. #[serde(default, skip_serializing_if = "is_default")]
  276. generics: Vec<IdlGenericArg>,
  277. },
  278. Generic(String),
  279. }
  280. // TODO: Move to utils crate
  281. impl FromStr for IdlType {
  282. type Err = anyhow::Error;
  283. fn from_str(s: &str) -> Result<Self, Self::Err> {
  284. let mut s = s.to_owned();
  285. s.retain(|c| !c.is_whitespace());
  286. let r = match s.as_str() {
  287. "bool" => IdlType::Bool,
  288. "u8" => IdlType::U8,
  289. "i8" => IdlType::I8,
  290. "u16" => IdlType::U16,
  291. "i16" => IdlType::I16,
  292. "u32" => IdlType::U32,
  293. "i32" => IdlType::I32,
  294. "f32" => IdlType::F32,
  295. "u64" => IdlType::U64,
  296. "i64" => IdlType::I64,
  297. "f64" => IdlType::F64,
  298. "u128" => IdlType::U128,
  299. "i128" => IdlType::I128,
  300. "u256" => IdlType::U256,
  301. "i256" => IdlType::I256,
  302. "Vec<u8>" => IdlType::Bytes,
  303. "String" | "&str" | "&'staticstr" => IdlType::String,
  304. "Pubkey" => IdlType::Pubkey,
  305. _ => {
  306. if let Some(inner) = s.strip_prefix("Option<") {
  307. let inner_ty = Self::from_str(
  308. inner
  309. .strip_suffix('>')
  310. .ok_or_else(|| anyhow!("Invalid Option"))?,
  311. )?;
  312. return Ok(IdlType::Option(Box::new(inner_ty)));
  313. }
  314. if let Some(inner) = s.strip_prefix("Vec<") {
  315. let inner_ty = Self::from_str(
  316. inner
  317. .strip_suffix('>')
  318. .ok_or_else(|| anyhow!("Invalid Vec"))?,
  319. )?;
  320. return Ok(IdlType::Vec(Box::new(inner_ty)));
  321. }
  322. if s.starts_with('[') {
  323. fn array_from_str(inner: &str) -> IdlType {
  324. match inner.strip_suffix(']') {
  325. Some(nested_inner) => array_from_str(&nested_inner[1..]),
  326. None => {
  327. let (raw_type, raw_length) = inner.rsplit_once(';').unwrap();
  328. let ty = IdlType::from_str(raw_type).unwrap();
  329. let len = match raw_length.replace('_', "").parse::<usize>() {
  330. Ok(len) => IdlArrayLen::Value(len),
  331. Err(_) => IdlArrayLen::Generic(raw_length.to_owned()),
  332. };
  333. IdlType::Array(Box::new(ty), len)
  334. }
  335. }
  336. }
  337. return Ok(array_from_str(&s));
  338. }
  339. // Defined
  340. let (name, generics) = if let Some(i) = s.find('<') {
  341. (
  342. s.get(..i).unwrap().to_owned(),
  343. s.get(i + 1..)
  344. .unwrap()
  345. .strip_suffix('>')
  346. .unwrap()
  347. .split(',')
  348. .map(|g| g.trim().to_owned())
  349. .map(|g| {
  350. if g.parse::<bool>().is_ok()
  351. || g.parse::<u128>().is_ok()
  352. || g.parse::<i128>().is_ok()
  353. || g.parse::<char>().is_ok()
  354. {
  355. Ok(IdlGenericArg::Const { value: g })
  356. } else {
  357. Self::from_str(&g).map(|ty| IdlGenericArg::Type { ty })
  358. }
  359. })
  360. .collect::<Result<Vec<_>, _>>()?,
  361. )
  362. } else {
  363. (s.to_owned(), vec![])
  364. };
  365. IdlType::Defined { name, generics }
  366. }
  367. };
  368. Ok(r)
  369. }
  370. }
  371. pub type IdlDiscriminator = Vec<u8>;
  372. /// Get whether the given data is the default of its type.
  373. fn is_default<T: Default + PartialEq>(it: &T) -> bool {
  374. *it == T::default()
  375. }
  376. #[cfg(test)]
  377. mod tests {
  378. use super::*;
  379. #[test]
  380. fn option() {
  381. assert_eq!(
  382. IdlType::from_str("Option<bool>").unwrap(),
  383. IdlType::Option(Box::new(IdlType::Bool))
  384. )
  385. }
  386. #[test]
  387. fn vector() {
  388. assert_eq!(
  389. IdlType::from_str("Vec<bool>").unwrap(),
  390. IdlType::Vec(Box::new(IdlType::Bool))
  391. )
  392. }
  393. #[test]
  394. fn array() {
  395. assert_eq!(
  396. IdlType::from_str("[Pubkey; 16]").unwrap(),
  397. IdlType::Array(Box::new(IdlType::Pubkey), IdlArrayLen::Value(16))
  398. );
  399. }
  400. #[test]
  401. fn array_with_underscored_length() {
  402. assert_eq!(
  403. IdlType::from_str("[u8; 50_000]").unwrap(),
  404. IdlType::Array(Box::new(IdlType::U8), IdlArrayLen::Value(50000))
  405. );
  406. }
  407. #[test]
  408. fn multidimensional_array() {
  409. assert_eq!(
  410. IdlType::from_str("[[u8; 16]; 32]").unwrap(),
  411. IdlType::Array(
  412. Box::new(IdlType::Array(
  413. Box::new(IdlType::U8),
  414. IdlArrayLen::Value(16)
  415. )),
  416. IdlArrayLen::Value(32)
  417. )
  418. );
  419. }
  420. #[test]
  421. fn generic_array() {
  422. assert_eq!(
  423. IdlType::from_str("[u64; T]").unwrap(),
  424. IdlType::Array(Box::new(IdlType::U64), IdlArrayLen::Generic("T".into()))
  425. );
  426. }
  427. #[test]
  428. fn defined() {
  429. assert_eq!(
  430. IdlType::from_str("MyStruct").unwrap(),
  431. IdlType::Defined {
  432. name: "MyStruct".into(),
  433. generics: vec![]
  434. }
  435. )
  436. }
  437. #[test]
  438. fn defined_with_generics() {
  439. assert_eq!(
  440. IdlType::from_str("MyStruct<Pubkey, u64, 8>").unwrap(),
  441. IdlType::Defined {
  442. name: "MyStruct".into(),
  443. generics: vec![
  444. IdlGenericArg::Type {
  445. ty: IdlType::Pubkey
  446. },
  447. IdlGenericArg::Type { ty: IdlType::U64 },
  448. IdlGenericArg::Const { value: "8".into() },
  449. ],
  450. }
  451. )
  452. }
  453. }