Documentation Index
Fetch the complete documentation index at: https://mintlify.com/Stremio/stremio-core/llms.txt
Use this file to discover all available pages before exploring further.
The Env trait defines the interface for platform-specific operations in Stremio Core. Implementations of this trait provide access to storage, networking, analytics, and other system-level functionality.
Overview
The Env trait abstracts platform differences, allowing Stremio Core to work across:
- Web (WebAssembly)
- Desktop (Native)
- Mobile (Native)
Different platforms implement this trait to provide their specific capabilities.
Trait Definition
pub trait Env {
// Required methods
fn fetch<IN, OUT>(request: Request<IN>) -> TryEnvFuture<OUT>;
fn get_storage<T>(key: &str) -> TryEnvFuture<Option<T>>;
fn set_storage<T>(key: &str, value: Option<&T>) -> TryEnvFuture<()>;
fn exec_concurrent<F>(future: F);
fn exec_sequential<F>(future: F);
fn now() -> DateTime<Utc>;
fn flush_analytics() -> EnvFuture<'static, ()>;
fn analytics_context(ctx: &Ctx, streaming_server: &StreamingServer, path: &str) -> serde_json::Value;
// Provided methods
fn addon_transport(transport_url: &Url) -> Box<dyn AddonTransport> { ... }
fn migrate_storage_schema() -> TryEnvFuture<()> { ... }
}
Required Methods
fetch
Performs an HTTP request with serialization/deserialization.
fn fetch<
IN: Serialize + ConditionalSend + 'static,
OUT: for<'de> Deserialize<'de> + ConditionalSend + 'static,
>(
request: Request<IN>,
) -> TryEnvFuture<OUT>
Type Parameters:
IN - Request body type (must be serializable)
OUT - Response body type (must be deserializable)
Parameters:
request - HTTP request with typed body
Returns: Future resolving to the deserialized response or an EnvError
Example:
let request = Request::get("https://api.stremio.com/api/user")
.header("Authorization", format!("Bearer {}", token))
.body(())?;
let response: User = E::fetch(request).await?;
get_storage
Retrieves a value from persistent storage.
fn get_storage<T: for<'de> Deserialize<'de> + ConditionalSend + 'static>(
key: &str,
) -> TryEnvFuture<Option<T>>
Type Parameters:
T - Type of the stored value
Parameters:
Returns: Future resolving to the stored value or None if not found
Example:
let profile: Option<Profile> = E::get_storage("profile").await?;
set_storage
Stores or removes a value from persistent storage.
fn set_storage<T: Serialize>(
key: &str,
value: Option<&T>
) -> TryEnvFuture<()>
Type Parameters:
T - Type of the value to store
Parameters:
key - Storage key
value - Value to store, or None to remove
Returns: Future resolving to success or an EnvError
Example:
// Store a value
E::set_storage("profile", Some(&profile)).await?;
// Remove a value
E::set_storage::<Profile>("profile", None).await?;
exec_concurrent
Executes a future concurrently (fire and forget).
fn exec_concurrent<F: Future<Output = ()> + ConditionalSend + 'static>(
future: F
)
Type Parameters:
F - Future type that returns ()
Parameters:
future - The future to execute
Example:
E::exec_concurrent(async move {
// Background work
let _ = process_analytics().await;
});
exec_sequential
Executes a future sequentially (queued execution).
fn exec_sequential<F: Future<Output = ()> + ConditionalSend + 'static>(
future: F
)
Type Parameters:
F - Future type that returns ()
Parameters:
future - The future to execute
Example:
E::exec_sequential(async move {
// Sequential work that shouldn't be parallelized
let _ = update_storage().await;
});
now
Returns the current UTC timestamp.
fn now() -> DateTime<Utc>
Returns: Current UTC timestamp
Example:
let current_time = E::now();
flush_analytics
Flushes any pending analytics data.
fn flush_analytics() -> EnvFuture<'static, ()>
Returns: Future that completes when analytics are flushed
analytics_context
Creates analytics context for tracking.
fn analytics_context(
ctx: &Ctx,
streaming_server: &StreamingServer,
path: &str,
) -> serde_json::Value
Parameters:
ctx - Current context (profile, library, etc.)
streaming_server - Streaming server state
path - Current navigation path
Returns: JSON value with analytics context
log (Debug Only)
Logs a message (only available in debug builds).
#[cfg(debug_assertions)]
fn log(message: String)
Parameters:
Provided Methods
addon_transport
Creates an addon transport for the given URL.
fn addon_transport(transport_url: &Url) -> Box<dyn AddonTransport>
Parameters:
transport_url - URL of the addon
Returns: Boxed addon transport implementation
The default implementation supports HTTP/HTTPS transports.
migrate_storage_schema
Migrates storage schema to the latest version.
fn migrate_storage_schema() -> TryEnvFuture<()>
Returns: Future resolving to success or an EnvError
This method automatically handles schema version upgrades from v0 to the current version.
EnvError
Errors returned by Env operations.
pub enum EnvError {
Fetch(String),
AddonTransport(String),
Serde(String),
StorageUnavailable,
StorageSchemaVersionDowngrade(u32, u32),
StorageSchemaVersionUpgrade(Box<EnvError>),
StorageReadError(String),
StorageWriteError(String),
Other(String),
}
Methods:
message() -> String - Returns human-readable error message
code() -> u32 - Returns error code
Type Aliases
EnvFuture
Platform-specific future type.
// Without env-future-send feature (WASM)
pub type EnvFuture<'a, T> = LocalBoxFuture<'a, T>;
// With env-future-send feature (Native)
pub type EnvFuture<'a, T> = BoxFuture<'a, T>;
TryEnvFuture
Future that resolves to a Result.
pub type TryEnvFuture<T> = EnvFuture<'static, Result<T, EnvError>>;
ConditionalSend
Marker trait for types that are Send on native but not on WASM.
// Without env-future-send feature (WASM)
pub trait ConditionalSend {}
impl<T> ConditionalSend for T {}
// With env-future-send feature (Native)
pub trait ConditionalSend: Send {}
impl<T: Send> ConditionalSend for T {}
Implementing Env
Here’s a minimal example of implementing the Env trait:
use stremio_core::runtime::{Env, TryEnvFuture, EnvFuture, EnvError};
use chrono::{DateTime, Utc};
struct MyEnv;
impl Env for MyEnv {
fn fetch<IN, OUT>(request: Request<IN>) -> TryEnvFuture<OUT>
where
IN: Serialize + ConditionalSend + 'static,
OUT: for<'de> Deserialize<'de> + ConditionalSend + 'static,
{
async move {
// Platform-specific HTTP implementation
let response = my_http_client::request(request).await?;
Ok(response)
}.boxed_env()
}
fn get_storage<T>(key: &str) -> TryEnvFuture<Option<T>>
where
T: for<'de> Deserialize<'de> + ConditionalSend + 'static,
{
async move {
// Platform-specific storage implementation
let value = my_storage::get(key).await?;
Ok(value)
}.boxed_env()
}
// ... implement other required methods
}
See Also
- Runtime - Runtime that uses the Env trait
- Effects - Effects that may use Env operations