1use crate::search::Suggestion;
4
5#[derive(Debug, Clone)]
10pub enum IdlSearchError {
11 NotFound {
12 input: String,
13 section: String,
14 suggestions: Vec<Suggestion>,
15 available: Vec<String>,
16 },
17 ParseError {
18 path: String,
19 source: String,
20 },
21 InvalidPath {
22 path: String,
23 },
24}
25
26impl std::fmt::Display for IdlSearchError {
27 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
28 match self {
29 IdlSearchError::NotFound {
30 input,
31 section,
32 suggestions,
33 available,
34 } => {
35 write!(f, "Not found: '{}' in {}", input, section)?;
36 if !suggestions.is_empty() {
37 write!(f, ". Did you mean: {}?", suggestions[0].candidate)?;
38 } else if !available.is_empty() {
39 let preview = available
40 .iter()
41 .take(5)
42 .cloned()
43 .collect::<Vec<_>>()
44 .join(", ");
45 write!(f, ". {}: {}", available_label(section), preview)?;
46 }
47 Ok(())
48 }
49 IdlSearchError::ParseError { path, source } => {
50 write!(f, "Failed to parse '{}': {}", path, source)
51 }
52 IdlSearchError::InvalidPath { path } => {
53 write!(
54 f,
55 "Invalid path '{}'. Expected a Rust path like foo::bar::Baz",
56 path
57 )
58 }
59 }
60 }
61}
62
63impl std::error::Error for IdlSearchError {}
64
65fn available_label(section: &str) -> String {
66 if section.starts_with("instruction fields") {
67 "Available instruction fields".to_string()
68 } else if section.starts_with("account fields") {
69 "Available account fields".to_string()
70 } else {
71 format!("Available {}", section)
72 }
73}