[][src]Crate tote

A lightweight data cache for CLI libraries

For CLIs that query a default set of information with each invocation, Tote offers a convenient way to cache data to a file for quicker subsequent CLI runs.

When Tote is used for a cache (examples below), the tote.get() call will:

  • Check that the Tote filepath exists and has been modified within the specified expiry time
  • Deserialize and return the data

If the cached data is not present or expired, Tote will:

  • Use the Fetch::fetch or AsyncFetch::fetch methods to retrieve the data
  • Serialize the data (using serde_json) and write to the Tote filepath
  • Return the newly fetched data
This example is not tested
use std::time::Duration;
use serde_derive::{Serialize, Deserialize};
use tote::{Fetch, Tote};

// Implement `serde`'s `Serialize`/`Deserialize` for you own data
// or make a NewType and `derive` so `Tote` can read and write the cached data
#[derive(Debug, Deserialize, Serialize)]
struct MyData(Vec<String>);

impl Fetch<MyData> for MyData {
    fn fetch() -> Result<MyData, Box<dyn std::error::Error>> {
        // This would likely do some I/O to fetch common data
        Ok(MyData(vec!["Larkspur".to_owned(), "Lavender".to_owned(), "Periwinkle".to_owned()]))
    }
}

fn main () -> Result<(), Box<dyn std::error::Error>> {
    // Create a Tote at the given path, with data expiry of 1 day
    let cache: Tote<MyData> = Tote::new("./colors.cache", Duration::from_secs(86400));

    // This `.get()` call will use data cached in "colors.cache" if:
    // - The file exists & has valid data
    // - The file has been modified in the past 1 day
    // Otherwise `MyData::fetch` is called to get the data and populate the cache file
    let available_colors = cache.get()?;
    println!("Colors you can use are: {:?}", available_colors);
    Ok(())
}

Feature "async"

Use async/await for fetching data with the "async" feature, which presents an AsyncFetch trait:

tote = { version = "*", features = ["async"] }
This example is not tested
use std::time::Duration;
use async_trait::async_trait;
use serde_derive::{Serialize, Deserialize};
use tote::{AsyncFetch, Tote};

// Implement `serde`'s `Serialize`/`Deserialize` for you own data
// or make a NewType and `derive` so `Tote` can read and write the cached data
#[derive(Debug, Deserialize, Serialize)]
struct MyData(Vec<String>);

#[async_trait]
impl AsyncFetch<MyData> for MyData {
    async fn fetch() -> Result<MyData, Box<dyn std::error::Error>> {
        // This would likely do some I/O to fetch common data
        Ok(MyData(vec!["Larkspur".to_owned(), "Lavender".to_owned(), "Periwinkle".to_owned()]))
    }
}

#[tokio::main]
async fn main () -> Result<(), Box<dyn std::error::Error>> {
    // Create a Tote at the given path, with data expiry of 1 day
    let cache: Tote<MyData> = Tote::new("./colors.cache", Duration::from_secs(86400));
    // This `.get().await` call will use data cached in "colors.cache" if:
    // - The file exists & has valid data
    // - The file has been modified in the past 1 day
    // Otherwise `MyData::fetch` is called to get the data and populate the cache file
    let available_colors = cache.get().await?;
    println!("Colors you can use are: {:?}", available_colors);
    Ok(())
}

Structs

Tote

Local file cache for D42 device info

Enums

ToteError

Errors that can occur during Tote operations

Traits

Fetch

A trait provided to allow Tote to fetch the data when no cache exists or cache is expired