lang: Handle IDL parsing for multidimensional  arrays
@@ -135,6 +135,17 @@ impl std::str::FromStr for IdlType {
fn from_str(s: &str) -> Result<Self, Self::Err> {
let mut s = s.to_string();
+ fn array_from_str(inner: &str) -> IdlType {
+ match inner.strip_suffix(']') {
+ None => {
+ let (raw_type, raw_length) = inner.rsplit_once(';').unwrap();
+ let ty = IdlType::from_str(raw_type).unwrap();
+ let len = raw_length.replace("_", "").parse::<usize>().unwrap();
+ IdlType::Array(Box::new(ty), len)
+ }
+ Some(nested_inner) => array_from_str(&nested_inner[1..]),
+ }
+ }
s.retain(|c| !c.is_whitespace());
let r = match s.as_str() {
"bool" => IdlType::Bool,
@@ -153,22 +164,13 @@ impl std::str::FromStr for IdlType {
"Pubkey" => IdlType::PublicKey,
_ => match s.to_string().strip_prefix("Option<") {
None => match s.to_string().strip_prefix("Vec<") {
- None => match s.to_string().strip_prefix('[') {
- None => IdlType::Defined(s.to_string()),
- Some(inner) => {
- let inner = &inner[..inner.len() - 1];
- let mut parts = inner.split(';');
- let ty = IdlType::from_str(parts.next().unwrap()).unwrap();
- let len = parts
- .next()
- .unwrap()
- .replace("_", "")
- .parse::<usize>()
- .unwrap();
- assert!(parts.next().is_none());
- IdlType::Array(Box::new(ty), len)
+ None => {
+ if s.to_string().starts_with('[') {
+ array_from_str(&s)
+ } else {
+ IdlType::Defined(s.to_string())
+ }
}
- },
Some(inner) => {
let inner_ty = Self::from_str(
inner
@@ -199,3 +201,49 @@ pub struct IdlErrorCode {
#[serde(skip_serializing_if = "Option::is_none", default)]
pub msg: Option<String>,
}
+
+#[cfg(test)]
+mod tests {
+ use crate::idl::IdlType;
+ use std::str::FromStr;
+
+ #[test]
+ fn multidimensional_array() {
+ assert_eq!(
+ IdlType::from_str("[[u8;16];32]").unwrap(),
+ IdlType::Array(Box::new(IdlType::Array(Box::new(IdlType::U8), 16)), 32)
+ );
+ }
+
+ #[test]
+ fn array() {
+ assert_eq!(
+ IdlType::from_str("[Pubkey;16]").unwrap(),
+ IdlType::Array(Box::new(IdlType::PublicKey), 16)
+ );
+ }
+
+ #[test]
+ fn array_with_underscored_length() {
+ assert_eq!(
+ IdlType::from_str("[u8;50_000]").unwrap(),
+ IdlType::Array(Box::new(IdlType::U8), 50000)
+ );
+ }
+
+ #[test]
+ fn option() {
+ assert_eq!(
+ IdlType::from_str("Option<bool>").unwrap(),
+ IdlType::Option(Box::new(IdlType::Bool))
+ )
+ }
+
+ #[test]
+ fn vector() {
+ assert_eq!(
+ IdlType::from_str("Vec<bool>").unwrap(),
+ IdlType::Vec(Box::new(IdlType::Bool))
+ )
+ }
+}
