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§
Sourcefn get_versions<'a>(
&'a self,
name: &'a PackageName,
) -> Pin<Box<dyn Future<Output = Result<Vec<Box<dyn Version>>>> + Send + 'a>>
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
Sourcefn 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 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 namereq- Version requirement string (e.g., “^1.0”, “>=2.0”)
§Returns
Ok(Some(version))- Latest matching version foundOk(None)- No matching version foundErr(_)- Network or parsing error
Sourcefn search<'a>(
&'a self,
query: &'a str,
limit: usize,
) -> Pin<Box<dyn Future<Output = Result<Vec<Box<dyn Metadata>>>> + Send + 'a>>
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.
Provided Methods§
Sourcefn 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_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.
Sourcefn 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_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.
Sourcefn 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_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.
Sourcefn 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 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.
Sourcefn select_latest_matching(
&self,
_versions: &[Box<dyn Version>],
_req: &VersionReq,
) -> Option<usize>
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.
Sourcefn select_latest_matching_with_context(
&self,
versions: &[Box<dyn Version>],
req: &VersionReq,
minimum_stability: Option<&str>,
) -> Option<usize>
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.
Sourcefn reports_yanked(&self) -> bool
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".