Preloader

Struct Preloader 

Source
pub struct Preloader<T: Send + 'static> { /* private fields */ }
Expand description

Asynchronous data preloader

Preloader is a struct for asynchronously loading and caching data. Once data loading is complete, the result is returned immediately, and the original future is executed only once even if called multiple times.

§Example

use preloader::Preloader;
let preloader: Preloader<String> = Preloader::new();

§Thread Safety

Preloader implements Send and Sync, so it can be safely used across multiple threads.

§Generic Type

  • T: The type of data to load. Must satisfy Send + 'static.

Implementations§

Source§

impl<T: Send + 'static> Preloader<T>

Source

pub fn new() -> Self

Creates a new Preloader instance.

§Returns

A new Preloader instance in the initial Idle state.

§Example
use preloader::Preloader;
let preloader: Preloader<String> = Preloader::new();
Source

pub async fn load(&self, future: impl Future<Output = T> + Send + 'static)

Starts an asynchronous task to load data.

This method can only be called in the Idle state. If loading is already in progress or completed, it does nothing and returns immediately.

§Parameters
  • future: The asynchronous task to execute. Must implement Future<Output = T> + Send + 'static.
§Example
use preloader::Preloader;
use tokio;

#[tokio::main]
async fn main() {
    let preloader = Preloader::new();
    preloader.load(async {
        // Simulate a time-consuming task
        tokio::time::sleep(tokio::time::Duration::from_millis(100)).await;
        42
    }).await;
}
Source

pub async fn get(&self) -> Result<&T, PreloaderError>

Retrieves the loaded data.

Returns an error if the data is not yet loaded. If the data is still loading, waits until loading is complete.

§Returns
  • Ok(&T): If the data was successfully loaded
  • Err(String): If the data is not loaded or an error occurred during loading
§Example
use preloader::Preloader;
use tokio;

#[tokio::main]
async fn main() {
    let preloader = Preloader::new();
    // Start loading first
    preloader.load(async { "data".to_string() }).await;
    // Retrieve data
    match preloader.get().await {
        Ok(data) => println!("Loaded data: {}", data),
        Err(e) => println!("Error: {}", e),
    }
}
Source

pub async fn take(self) -> Result<T, PreloaderError>

Takes the loaded data, consuming it.

This method consumes the loaded data, leaving None in its place. Returns an error if the data is not yet loaded. If the data is still loading, waits until loading is complete.

§Returns
  • Ok(T): If the data was successfully loaded and taken
  • Err(PreloaderError): If the data is not loaded or an error occurred during loading
§Example
use preloader::Preloader;
use tokio;

#[tokio::main]
async fn main() {
    let preloader = Preloader::new();
    // Start loading
    preloader.load(async { "data".to_string() }).await;
    // Take data, consuming the preloader
    match preloader.take().await {
        Ok(data) => println!("Taken data: {}", data),
        Err(e) => println!("Error: {}", e),
    }
    // Note: preloader is consumed and cannot be used after take()
    // The following code would not compile:
    // match preloader.try_get() { ... } // Error: use of moved value
}

Takes the loaded data, consuming the Preloader.

This method consumes the Preloader itself, ensuring it cannot be used after taking the value. Returns an error if the data is not yet loaded. If the data is still loading, waits until loading is complete.

§Returns
  • Ok(T): If the data was successfully loaded and taken
  • Err(PreloaderError): If the data is not loaded or an error occurred during loading
§Example
use preloader::Preloader;
use tokio;

#[tokio::main]
async fn main() {
    let preloader = Preloader::new();
    // Start loading
    preloader.load(async { "data".to_string() }).await;
    // Take data, consuming the preloader
    match preloader.take().await {
        Ok(data) => println!("Taken data: {}", data),
        Err(e) => println!("Error: {}", e),
    }
    // Preloader cannot be used after take() as it has been consumed
}
Source

pub unsafe fn get_unchecked(&self) -> &T

Retrieves the loaded data without checking the state.

This method is unsafe and should only be used when you are sure that the data is loaded.

§Returns
Source

pub fn try_get(&self) -> Result<&T, PreloaderError>

Attempts to retrieve the loaded data immediately.

Unlike get(), this method does not block. If the data is not yet loaded or is still loading, returns an error immediately.

§Returns
  • Ok(&T): If the data was successfully loaded
  • Err(String): If the data is not loaded or is still loading
§Example
use preloader::Preloader;
use tokio;

#[tokio::main]
async fn main() {
    let preloader = Preloader::new();
    // Try before loading
    match preloader.try_get() {
        Ok(data) => println!("Data: {}", data),
        Err(e) => println!("Not loaded yet: {}", e),
    }
    // Start loading
    preloader.load(async { "data".to_string() }).await;
    // Try while loading
    match preloader.try_get() {
        Ok(data) => println!("Data: {}", data),
        Err(e) => println!("Still loading: {}", e),
    }
}
Source

pub unsafe fn try_get_unchecked(&self) -> &T

Retrieves the loaded data without checking the state.

This method is unsafe and should only be used when you are sure that the data is loaded.

§Returns

Reference to the stored value

Source

pub fn is_loaded(&self) -> bool

Checks if the preloader has completed loading and data is available.

This method returns true if the preloader is in the Loaded state, indicating that data is ready to be accessed without blocking.

§Returns
  • true: If the data is loaded and ready for immediate access
  • false: If the data is not loaded yet or is still loading
§Example
use preloader::Preloader;
use tokio;

#[tokio::main]
async fn main() {
    let preloader = Preloader::new();
     
    // Check before loading
    assert!(!preloader.is_loaded());
     
    // Start loading
    preloader.load(async { "data".to_string() }).await;
     
    // Wait for completion
    preloader.get().await.unwrap();
     
    // Check after loading
    assert!(preloader.is_loaded());
}

Trait Implementations§

Source§

impl<T: Send + 'static> Send for Preloader<T>

Source§

impl<T: Send + 'static> Sync for Preloader<T>

Auto Trait Implementations§

§

impl<T> !Freeze for Preloader<T>

§

impl<T> !RefUnwindSafe for Preloader<T>

§

impl<T> Unpin for Preloader<T>
where T: Unpin,

§

impl<T> !UnwindSafe for Preloader<T>

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, 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, 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.