Skip to main content

Registry

Trait Registry 

Source
pub trait Registry: Send + Sync {
    // Required methods
    fn get_versions<'a>(
        &'a self,
        name: &'a PackageName,
    ) -> Pin<Box<dyn Future<Output = Result<Vec<Box<dyn Version>>>> + Send + 'a>>;
    fn get_latest_matching<'a>(
        &'a self,
        name: &'a PackageName,
        req: &'a VersionReq,
    ) -> Pin<Box<dyn Future<Output = Result<Option<Box<dyn Version>>>> + Send + 'a>>;
    fn search<'a>(
        &'a self,
        query: &'a str,
        limit: usize,
    ) -> Pin<Box<dyn Future<Output = Result<Vec<Box<dyn Metadata>>>> + Send + 'a>>;
    fn as_any(&self) -> &dyn Any;

    // Provided methods
    fn get_versions_with<'a>(
        &'a self,
        name: &'a PackageName,
        freshness: FreshnessSettings,
    ) -> Pin<Box<dyn Future<Output = Result<Vec<Box<dyn Version>>>> + Send + 'a>> { ... }
    fn get_versions_from<'a>(
        &'a self,
        name: &'a PackageName,
        source: &'a DependencySource,
        freshness: FreshnessSettings,
    ) -> Pin<Box<dyn Future<Output = Result<Vec<Box<dyn Version>>>> + Send + 'a>> { ... }
    fn get_latest_matching_with_context<'a>(
        &'a self,
        name: &'a PackageName,
        req: &'a VersionReq,
        minimum_stability: Option<&'a str>,
    ) -> Pin<Box<dyn Future<Output = Result<Option<Box<dyn Version>>>> + Send + 'a>> { ... }
    fn get_latest_matching_from<'a>(
        &'a self,
        name: &'a PackageName,
        source: &'a DependencySource,
        req: &'a VersionReq,
        minimum_stability: Option<&'a str>,
    ) -> Pin<Box<dyn Future<Output = Result<Option<Box<dyn Version>>>> + Send + 'a>> { ... }
    fn select_latest_matching(
        &self,
        _versions: &[Box<dyn Version>],
        _req: &VersionReq,
    ) -> Option<usize> { ... }
    fn select_latest_matching_with_context(
        &self,
        versions: &[Box<dyn Version>],
        req: &VersionReq,
        minimum_stability: Option<&str>,
    ) -> Option<usize> { ... }
    fn reports_yanked(&self) -> bool { ... }
}
Expand description

Generic package registry interface.

Implementors provide access to a package registry (crates.io, npm, PyPI, etc.) with version lookup, search, and metadata retrieval capabilities.

All methods return Result<T> to allow graceful error handling. LSP handlers must never panic on registry errors.

§Type Erasure

This trait uses Box<dyn Trait> return types instead of associated types to allow runtime polymorphism and dynamic ecosystem registration.

§Examples

use deps_core::{Registry, Version, Metadata, PackageName, ConcreteVersion};
use std::any::Any;
use std::pin::Pin;

struct MyRegistry;

#[derive(Clone)]
struct MyVersion { version: ConcreteVersion }

impl Version for MyVersion {
    fn version_string(&self) -> &ConcreteVersion { &self.version }
    fn as_any(&self) -> &dyn Any { self }
}

#[derive(Clone)]
struct MyMetadata { name: PackageName, latest: ConcreteVersion }

impl Metadata for MyMetadata {
    fn name(&self) -> &PackageName { &self.name }
    fn description(&self) -> Option<&str> { None }
    fn repository(&self) -> Option<&str> { None }
    fn documentation(&self) -> Option<&str> { None }
    fn latest_version(&self) -> &ConcreteVersion { &self.latest }
    fn as_any(&self) -> &dyn Any { self }
}

impl Registry for MyRegistry {
    fn get_versions<'a>(&'a self, _name: &'a PackageName)
        -> Pin<Box<dyn std::future::Future<Output = deps_core::error::Result<Vec<Box<dyn Version>>>> + Send + 'a>>
    {
        Box::pin(async move { Ok(vec![Box::new(MyVersion { version: "1.0.0".into() }) as Box<dyn Version>]) })
    }

    fn get_latest_matching<'a>(&'a self, _name: &'a PackageName, _req: &'a deps_core::VersionReq)
        -> Pin<Box<dyn std::future::Future<Output = deps_core::error::Result<Option<Box<dyn Version>>>> + Send + 'a>>
    {
        Box::pin(async move { Ok(None) })
    }

    fn search<'a>(&'a self, _query: &'a str, _limit: usize)
        -> Pin<Box<dyn std::future::Future<Output = deps_core::error::Result<Vec<Box<dyn Metadata>>>> + Send + 'a>>
    {
        Box::pin(async move { Ok(vec![]) })
    }

    fn as_any(&self) -> &dyn Any { self }
}

Required Methods§

Source

fn get_versions<'a>( &'a self, name: &'a PackageName, ) -> Pin<Box<dyn Future<Output = Result<Vec<Box<dyn Version>>>> + Send + 'a>>

Fetches all available versions for a package.

Returns versions sorted newest-first. May include yanked/deprecated versions.

§Errors

Returns error if:

  • Package does not exist
  • Network request fails
  • Response parsing fails
Source

fn get_latest_matching<'a>( &'a self, name: &'a PackageName, req: &'a VersionReq, ) -> Pin<Box<dyn Future<Output = Result<Option<Box<dyn Version>>>> + Send + 'a>>

Finds the latest version matching a version requirement.

Filter with RemovalStatus::blocks_resolution, never with RemovalStatus::is_flagged. An AdvisoryDeprecated version is fully installable — excluding it turns an existing package into a false “Unknown package” (#347). Under a wildcard/empty requirement ("*"/"", see is_existence_wildcard) this is an existence check (“does this package exist / what is its newest version for display purposes”), not an upgrade recommendation: an implementation may prefer a non-yanked version but fall back to a yanked one rather than returning None when no non-yanked version exists — a yanked package still exists. deps-npm implements this fallback (mirrored by select_latest_matching’s wildcard branch on the same registry, which every caller reaching this trait method through the shared fetch loop actually goes through first); the exception never applies to a concrete requirement.

§Arguments
  • name - Package name
  • req - Version requirement string (e.g., “^1.0”, “>=2.0”)
§Returns
  • Ok(Some(version)) - Latest matching version found
  • Ok(None) - No matching version found
  • Err(_) - Network or parsing error
Source

fn search<'a>( &'a self, query: &'a str, limit: usize, ) -> Pin<Box<dyn Future<Output = Result<Vec<Box<dyn Metadata>>>> + Send + 'a>>

Searches for packages by name or keywords.

Returns up to limit results sorted by relevance/popularity.

§Errors

Returns error if network request or parsing fails.

Source

fn as_any(&self) -> &dyn Any

Downcast to concrete registry type for ecosystem-specific operations

Provided Methods§

Source

fn get_versions_with<'a>( &'a self, name: &'a PackageName, freshness: FreshnessSettings, ) -> Pin<Box<dyn Future<Output = Result<Vec<Box<dyn Version>>>> + Send + 'a>>

Like get_versions, but lets a registry that can obtain Version::published_at only through an extra request gate that request behind freshness.enabled instead of always paying for it.

Implementors overriding this method MUST keep every other aspect of get_versions’s behavior — set, order, and content of the returned versions — identical; the only difference the override may introduce is populating Version::published_at. Callers that render publish ages MUST call this method rather than get_versions: the default implementation below simply forwards to get_versions and ignores freshness, so a caller that keeps calling get_versions silently gets no freshness signal even from a registry that implements this override.

Default: forwards to get_versions, ignoring freshness. This keeps the ten registries with no extra publish-time source unchanged, and keeps FreshnessSettings — a Copy + 'static DTO — out of every Registry::new signature and the register! ecosystem-registration macro.

Source

fn get_versions_from<'a>( &'a self, name: &'a PackageName, source: &'a DependencySource, freshness: FreshnessSettings, ) -> Pin<Box<dyn Future<Output = Result<Vec<Box<dyn Version>>>> + Send + 'a>>

Like get_versions_with, but additionally carries the dependency’s resolved DependencySource, for a registry that routes a single fetch across more than one underlying index (e.g. deps-cargo’s CargoRegistry, which dispatches a DependencySource::AlternateRegistry to a private sparse index instead of crates.io).

Default: forwards to get_versions_with, ignoring source entirely. This keeps every registry with no per-dependency routing concept — every ecosystem except Cargo today — bit-identical: source is accepted and dropped, so a caller migrating to this method from get_versions_with changes no observable behavior for them.

Callers that know which source a dependency resolved to should call this rather than get_versions_with, even against a registry with no override — the whole point is that call sites don’t need to know which registries route on source and which don’t.

Source

fn get_latest_matching_with_context<'a>( &'a self, name: &'a PackageName, req: &'a VersionReq, minimum_stability: Option<&'a str>, ) -> Pin<Box<dyn Future<Output = Result<Option<Box<dyn Version>>>> + Send + 'a>>

Like get_latest_matching, but lets a registry whose “latest matching” selection can be refined by ecosystem-specific manifest state (e.g. Composer’s minimum-stability field, #424) read it, alongside req.

minimum_stability is an opaque, ecosystem-defined string (Composer’s own stability keyword: "dev", "alpha", "beta", "RC", or "stable") rather than a shared type, mirroring get_versions_with’s FreshnessSettings precedent for “an optional extra parameter most registries ignore” — except here even the shape of the extra context is ecosystem-specific, so no shared DTO is introduced for it; only the one registry that understands the string overrides this method.

Default: forwards to get_latest_matching, ignoring minimum_stability. This keeps every registry with no manifest-level stability concept unchanged.

Source

fn get_latest_matching_from<'a>( &'a self, name: &'a PackageName, source: &'a DependencySource, req: &'a VersionReq, minimum_stability: Option<&'a str>, ) -> Pin<Box<dyn Future<Output = Result<Option<Box<dyn Version>>>> + Send + 'a>>

Like get_latest_matching_with_context, but additionally carries the dependency’s resolved DependencySource — the get_latest_matching-shaped counterpart to get_versions_from, covering the fallback path a caller takes when the list-based pick fails on a non-empty get_versions_from result (see deps_core::lsp_helpers::hover’s list_fallback_latest and deps-lsp’s background-fetch fallback for the two call sites this exists for).

Default: forwards to get_latest_matching_with_context, ignoring source — every registry with no per-dependency routing concept stays bit-identical, exactly as get_versions_from does for the list-fetching side.

Source

fn select_latest_matching( &self, _versions: &[Box<dyn Version>], _req: &VersionReq, ) -> Option<usize>

Index of the latest version in versions satisfying req, with no I/O.

Filter with RemovalStatus::blocks_resolution, never with RemovalStatus::is_flagged. An AdvisoryDeprecated version is fully installable — excluding it turns an existing package into a false “Unknown package” (#347). Under a wildcard/empty requirement (see is_existence_wildcard) this is an existence check, not an upgrade recommendation: Cargo, PyPI, Dart, npm, and Deno implement it by gating on is_existence_wildcard and delegating to select_latest_for_existence.

versions must be a newest-first list as returned by this registry’s get_versions. Returns an index rather than a reference so callers holding an owned Vec can move the chosen element out (versions.into_iter().nth(i)) — a borrow into the list would keep it frozen while get_latest_matching needs to return an owned Box<dyn Version>, and Version has no clone_box.

Default: None. Every registry reachable from the LSP fetch path overrides this so the fetch loop can obtain both “latest” and the full version list from one round trip; the default exists so test doubles that never resolve a “latest” compile unchanged.

Source

fn select_latest_matching_with_context( &self, versions: &[Box<dyn Version>], req: &VersionReq, minimum_stability: Option<&str>, ) -> Option<usize>

Like select_latest_matching, but lets a registry whose selection can be refined by ecosystem-specific manifest state (e.g. Composer’s minimum-stability field, #424) read it, alongside versions and req. See get_latest_matching_with_context for why minimum_stability is an opaque per-ecosystem string rather than a shared type.

Default: forwards to select_latest_matching, ignoring minimum_stability. This keeps every registry with no manifest-level stability concept unchanged.

Source

fn reports_yanked(&self) -> bool

Whether get_versions results carry meaningful per-version yank/deprecation data via Version::removal_status.

Default true: a registry is opted into the yanked-version diagnostic unless it explicitly says it cannot answer. This fails toward correctness — a registry whose removal_status later becomes real data starts participating automatically, by deleting its opt-out rather than by someone remembering to add an opt-in. Return false only when removal_status() is hardcoded (e.g. always RemovalStatus::Available) or otherwise cannot reflect real registry data; a true return authorizes callers to trust removal_status() on versions from this registry’s normal get_versions/ get_latest_matching results — it does not trigger any additional network request.

Dyn Compatibility§

This trait is dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety".

Implementors§