DataGovClient

Struct DataGovClient 

Source
pub struct DataGovClient { /* private fields */ }
Expand description

Async client for exploring data.gov datasets.

DataGovClient layers ergonomic helpers on top of the lower-level data_gov_ckan::CkanClient. In addition to search and metadata lookups it handles download destinations, progress reporting, and colour-aware output that matches the data-gov CLI defaults.

Implementations§

Source§

impl DataGovClient

Source

pub fn new() -> Result<Self>

Create a new DataGov client with default configuration

Examples found in repository?
examples/demo.rs (line 10)
5async fn main() -> Result<(), Box<dyn Error>> {
6    println!("🇺🇸 Data.gov Rust Client Demo");
7    println!("================================\n");
8
9    // Create a client
10    let client = DataGovClient::new()?;
11
12    // 1. Search for datasets
13    println!("🔍 Searching for 'climate' datasets...");
14    let search_results = client.search("climate", Some(5), None, None, None).await?;
15
16    println!("Found {} results:\n", search_results.count.unwrap_or(0));
17
18    if let Some(results) = &search_results.results {
19        for (i, dataset) in results.iter().enumerate() {
20            println!(
21                "{}. {} ({})",
22                i + 1,
23                dataset.title.as_deref().unwrap_or(&dataset.name),
24                dataset.name
25            );
26
27            // Show resource count
28            let resources = DataGovClient::get_downloadable_resources(dataset);
29            println!("   📁 {} downloadable resources", resources.len());
30
31            if let Some(notes) = &dataset.notes {
32                let truncated = if notes.len() > 100 {
33                    format!("{}...", &notes[..100])
34                } else {
35                    notes.clone()
36                };
37                println!("   📄 {}", truncated);
38            }
39            println!();
40        }
41    }
42
43    // 2. Get organizations
44    println!("🏛️  Listing government organizations...");
45    let orgs = client.list_organizations(Some(10)).await?;
46    println!("Found {} organizations:", orgs.len());
47    for (i, org) in orgs.iter().enumerate().take(5) {
48        println!("  {}. {}", i + 1, org);
49    }
50    println!();
51
52    // 3. Autocomplete example
53    println!("🔍 Autocomplete for 'energy'...");
54    let suggestions = client.autocomplete_datasets("energy", Some(5)).await?;
55    println!("Suggestions:");
56    for suggestion in suggestions {
57        println!("  • {}", suggestion);
58    }
59    println!();
60
61    println!("✅ Demo completed! Try the interactive REPL with:");
62    println!("   data-gov");
63    println!();
64    println!("Example CLI commands:");
65    println!("  data-gov search \"climate data\"");
66    println!("  data-gov show consumer-complaint-database");
67    println!("  data-gov download consumer-complaint-database 0");
68    println!("  data-gov list organizations");
69    println!("  data-gov --help");
70
71    Ok(())
72}
Source

pub fn with_config(config: DataGovConfig) -> Result<Self>

Create a new DataGov client with custom configuration

Source

pub async fn search( &self, query: &str, limit: Option<i32>, offset: Option<i32>, organization: Option<&str>, format: Option<&str>, ) -> Result<PackageSearchResult>

Search for datasets on data.gov.

§Arguments
  • query - Search terms (searches titles, descriptions, tags)
  • limit - Maximum number of results (default: 10, max: 1000)
  • offset - Number of results to skip for pagination (default: 0)
  • organization - Filter by organization name (optional)
  • format - Filter by resource format (optional, e.g., “CSV”, “JSON”)
§Examples

Basic search:

let client = DataGovClient::new()?;
let results = client.search("climate data", Some(20), None, None, None).await?;

Search with filters:

let results = client.search("energy", Some(10), None, Some("doe-gov"), Some("CSV")).await?;
Examples found in repository?
examples/demo.rs (line 14)
5async fn main() -> Result<(), Box<dyn Error>> {
6    println!("🇺🇸 Data.gov Rust Client Demo");
7    println!("================================\n");
8
9    // Create a client
10    let client = DataGovClient::new()?;
11
12    // 1. Search for datasets
13    println!("🔍 Searching for 'climate' datasets...");
14    let search_results = client.search("climate", Some(5), None, None, None).await?;
15
16    println!("Found {} results:\n", search_results.count.unwrap_or(0));
17
18    if let Some(results) = &search_results.results {
19        for (i, dataset) in results.iter().enumerate() {
20            println!(
21                "{}. {} ({})",
22                i + 1,
23                dataset.title.as_deref().unwrap_or(&dataset.name),
24                dataset.name
25            );
26
27            // Show resource count
28            let resources = DataGovClient::get_downloadable_resources(dataset);
29            println!("   📁 {} downloadable resources", resources.len());
30
31            if let Some(notes) = &dataset.notes {
32                let truncated = if notes.len() > 100 {
33                    format!("{}...", &notes[..100])
34                } else {
35                    notes.clone()
36                };
37                println!("   📄 {}", truncated);
38            }
39            println!();
40        }
41    }
42
43    // 2. Get organizations
44    println!("🏛️  Listing government organizations...");
45    let orgs = client.list_organizations(Some(10)).await?;
46    println!("Found {} organizations:", orgs.len());
47    for (i, org) in orgs.iter().enumerate().take(5) {
48        println!("  {}. {}", i + 1, org);
49    }
50    println!();
51
52    // 3. Autocomplete example
53    println!("🔍 Autocomplete for 'energy'...");
54    let suggestions = client.autocomplete_datasets("energy", Some(5)).await?;
55    println!("Suggestions:");
56    for suggestion in suggestions {
57        println!("  • {}", suggestion);
58    }
59    println!();
60
61    println!("✅ Demo completed! Try the interactive REPL with:");
62    println!("   data-gov");
63    println!();
64    println!("Example CLI commands:");
65    println!("  data-gov search \"climate data\"");
66    println!("  data-gov show consumer-complaint-database");
67    println!("  data-gov download consumer-complaint-database 0");
68    println!("  data-gov list organizations");
69    println!("  data-gov --help");
70
71    Ok(())
72}
Source

pub async fn get_dataset(&self, dataset_id: &str) -> Result<Package>

Fetch the full package_show payload for a dataset.

Source

pub async fn autocomplete_datasets( &self, partial: &str, limit: Option<i32>, ) -> Result<Vec<String>>

Fetch dataset name suggestions for interactive prompts.

Examples found in repository?
examples/demo.rs (line 54)
5async fn main() -> Result<(), Box<dyn Error>> {
6    println!("🇺🇸 Data.gov Rust Client Demo");
7    println!("================================\n");
8
9    // Create a client
10    let client = DataGovClient::new()?;
11
12    // 1. Search for datasets
13    println!("🔍 Searching for 'climate' datasets...");
14    let search_results = client.search("climate", Some(5), None, None, None).await?;
15
16    println!("Found {} results:\n", search_results.count.unwrap_or(0));
17
18    if let Some(results) = &search_results.results {
19        for (i, dataset) in results.iter().enumerate() {
20            println!(
21                "{}. {} ({})",
22                i + 1,
23                dataset.title.as_deref().unwrap_or(&dataset.name),
24                dataset.name
25            );
26
27            // Show resource count
28            let resources = DataGovClient::get_downloadable_resources(dataset);
29            println!("   📁 {} downloadable resources", resources.len());
30
31            if let Some(notes) = &dataset.notes {
32                let truncated = if notes.len() > 100 {
33                    format!("{}...", &notes[..100])
34                } else {
35                    notes.clone()
36                };
37                println!("   📄 {}", truncated);
38            }
39            println!();
40        }
41    }
42
43    // 2. Get organizations
44    println!("🏛️  Listing government organizations...");
45    let orgs = client.list_organizations(Some(10)).await?;
46    println!("Found {} organizations:", orgs.len());
47    for (i, org) in orgs.iter().enumerate().take(5) {
48        println!("  {}. {}", i + 1, org);
49    }
50    println!();
51
52    // 3. Autocomplete example
53    println!("🔍 Autocomplete for 'energy'...");
54    let suggestions = client.autocomplete_datasets("energy", Some(5)).await?;
55    println!("Suggestions:");
56    for suggestion in suggestions {
57        println!("  • {}", suggestion);
58    }
59    println!();
60
61    println!("✅ Demo completed! Try the interactive REPL with:");
62    println!("   data-gov");
63    println!();
64    println!("Example CLI commands:");
65    println!("  data-gov search \"climate data\"");
66    println!("  data-gov show consumer-complaint-database");
67    println!("  data-gov download consumer-complaint-database 0");
68    println!("  data-gov list organizations");
69    println!("  data-gov --help");
70
71    Ok(())
72}
Source

pub async fn list_organizations( &self, limit: Option<i32>, ) -> Result<Vec<String>>

List the publisher slugs for government organizations.

Examples found in repository?
examples/demo.rs (line 45)
5async fn main() -> Result<(), Box<dyn Error>> {
6    println!("🇺🇸 Data.gov Rust Client Demo");
7    println!("================================\n");
8
9    // Create a client
10    let client = DataGovClient::new()?;
11
12    // 1. Search for datasets
13    println!("🔍 Searching for 'climate' datasets...");
14    let search_results = client.search("climate", Some(5), None, None, None).await?;
15
16    println!("Found {} results:\n", search_results.count.unwrap_or(0));
17
18    if let Some(results) = &search_results.results {
19        for (i, dataset) in results.iter().enumerate() {
20            println!(
21                "{}. {} ({})",
22                i + 1,
23                dataset.title.as_deref().unwrap_or(&dataset.name),
24                dataset.name
25            );
26
27            // Show resource count
28            let resources = DataGovClient::get_downloadable_resources(dataset);
29            println!("   📁 {} downloadable resources", resources.len());
30
31            if let Some(notes) = &dataset.notes {
32                let truncated = if notes.len() > 100 {
33                    format!("{}...", &notes[..100])
34                } else {
35                    notes.clone()
36                };
37                println!("   📄 {}", truncated);
38            }
39            println!();
40        }
41    }
42
43    // 2. Get organizations
44    println!("🏛️  Listing government organizations...");
45    let orgs = client.list_organizations(Some(10)).await?;
46    println!("Found {} organizations:", orgs.len());
47    for (i, org) in orgs.iter().enumerate().take(5) {
48        println!("  {}. {}", i + 1, org);
49    }
50    println!();
51
52    // 3. Autocomplete example
53    println!("🔍 Autocomplete for 'energy'...");
54    let suggestions = client.autocomplete_datasets("energy", Some(5)).await?;
55    println!("Suggestions:");
56    for suggestion in suggestions {
57        println!("  • {}", suggestion);
58    }
59    println!();
60
61    println!("✅ Demo completed! Try the interactive REPL with:");
62    println!("   data-gov");
63    println!();
64    println!("Example CLI commands:");
65    println!("  data-gov search \"climate data\"");
66    println!("  data-gov show consumer-complaint-database");
67    println!("  data-gov download consumer-complaint-database 0");
68    println!("  data-gov list organizations");
69    println!("  data-gov --help");
70
71    Ok(())
72}
Source

pub async fn autocomplete_organizations( &self, partial: &str, limit: Option<i32>, ) -> Result<Vec<String>>

Fetch organization name suggestions for interactive prompts.

Source

pub fn get_downloadable_resources(package: &Package) -> Vec<Resource>

Return resources that look like downloadable files.

The returned list is filtered to resources that expose a direct URL, are not marked as API endpoints, and advertise a file format.

Examples found in repository?
examples/demo.rs (line 28)
5async fn main() -> Result<(), Box<dyn Error>> {
6    println!("🇺🇸 Data.gov Rust Client Demo");
7    println!("================================\n");
8
9    // Create a client
10    let client = DataGovClient::new()?;
11
12    // 1. Search for datasets
13    println!("🔍 Searching for 'climate' datasets...");
14    let search_results = client.search("climate", Some(5), None, None, None).await?;
15
16    println!("Found {} results:\n", search_results.count.unwrap_or(0));
17
18    if let Some(results) = &search_results.results {
19        for (i, dataset) in results.iter().enumerate() {
20            println!(
21                "{}. {} ({})",
22                i + 1,
23                dataset.title.as_deref().unwrap_or(&dataset.name),
24                dataset.name
25            );
26
27            // Show resource count
28            let resources = DataGovClient::get_downloadable_resources(dataset);
29            println!("   📁 {} downloadable resources", resources.len());
30
31            if let Some(notes) = &dataset.notes {
32                let truncated = if notes.len() > 100 {
33                    format!("{}...", &notes[..100])
34                } else {
35                    notes.clone()
36                };
37                println!("   📄 {}", truncated);
38            }
39            println!();
40        }
41    }
42
43    // 2. Get organizations
44    println!("🏛️  Listing government organizations...");
45    let orgs = client.list_organizations(Some(10)).await?;
46    println!("Found {} organizations:", orgs.len());
47    for (i, org) in orgs.iter().enumerate().take(5) {
48        println!("  {}. {}", i + 1, org);
49    }
50    println!();
51
52    // 3. Autocomplete example
53    println!("🔍 Autocomplete for 'energy'...");
54    let suggestions = client.autocomplete_datasets("energy", Some(5)).await?;
55    println!("Suggestions:");
56    for suggestion in suggestions {
57        println!("  • {}", suggestion);
58    }
59    println!();
60
61    println!("✅ Demo completed! Try the interactive REPL with:");
62    println!("   data-gov");
63    println!();
64    println!("Example CLI commands:");
65    println!("  data-gov search \"climate data\"");
66    println!("  data-gov show consumer-complaint-database");
67    println!("  data-gov download consumer-complaint-database 0");
68    println!("  data-gov list organizations");
69    println!("  data-gov --help");
70
71    Ok(())
72}
Source

pub fn get_resource_filename( resource: &Resource, fallback_name: Option<&str>, ) -> String

Pick a filesystem-friendly filename for a resource download.

Source

pub async fn download_dataset_resource( &self, resource: &Resource, dataset_name: &str, ) -> Result<PathBuf>

Download a single resource into the dataset-specific directory.

§Arguments
  • resource - The resource to download
  • dataset_name - Name of the dataset (used for subdirectory)

Returns the path where the file was saved

Source

pub async fn download_resource( &self, resource: &Resource, output_path: Option<PathBuf>, ) -> Result<PathBuf>

Download a single resource to a specific path.

§Arguments
  • resource - The resource to download
  • output_path - Where to save the file (if None, uses base download directory)

Returns the path where the file was saved

Source

pub async fn download_resources( &self, resources: &[Resource], output_dir: Option<&Path>, ) -> Vec<Result<PathBuf>>

Download multiple resources concurrently.

Returns one Result per resource so callers can inspect partial failures.

Source

pub async fn download_dataset_resources( &self, resources: &[Resource], dataset_name: &str, ) -> Vec<Result<PathBuf>>

Download multiple resources into the dataset-specific directory.

Returns one Result per resource so callers can inspect partial failures.

Source

pub async fn validate_download_dir(&self) -> Result<()>

Check if the base download directory exists and is writable

Source

pub fn download_dir(&self) -> PathBuf

Get the current base download directory

Source

pub fn ckan_client(&self) -> &CkanClient

Get the underlying CKAN client for advanced operations

Trait Implementations§

Source§

impl Debug for DataGovClient

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for DataGovClient

Source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

impl<T> ErasedDestructor for T
where T: 'static,