diff --git a/.lock b/.lock new file mode 100644 index 00000000..e69de29b diff --git a/.nojekyll b/.nojekyll new file mode 100644 index 00000000..e69de29b diff --git a/crates.js b/crates.js new file mode 100644 index 00000000..7571f0f2 --- /dev/null +++ b/crates.js @@ -0,0 +1 @@ +window.ALL_CRATES = ["pubgrub"]; \ No newline at end of file diff --git a/help.html b/help.html new file mode 100644 index 00000000..584eb36f --- /dev/null +++ b/help.html @@ -0,0 +1,2 @@ +Help +

Rustdoc help

Back
\ No newline at end of file diff --git a/pubgrub/all.html b/pubgrub/all.html new file mode 100644 index 00000000..3463aab9 --- /dev/null +++ b/pubgrub/all.html @@ -0,0 +1,2 @@ +List of all items in this crate +

List of all items

Structs

Enums

Traits

Functions

Type Aliases

\ No newline at end of file diff --git a/pubgrub/error/enum.PubGrubError.html b/pubgrub/error/enum.PubGrubError.html new file mode 100644 index 00000000..af6f6aa0 --- /dev/null +++ b/pubgrub/error/enum.PubGrubError.html @@ -0,0 +1,75 @@ +PubGrubError in pubgrub::error - Rust +
pub enum PubGrubError<P: Package, VS: VersionSet, E: Error> {
+    NoSolution(DerivationTree<P, VS>),
+    ErrorRetrievingDependencies {
+        package: P,
+        version: VS::V,
+        source: E,
+    },
+    SelfDependency {
+        package: P,
+        version: VS::V,
+    },
+    ErrorChoosingPackageVersion(E),
+    ErrorInShouldCancel(E),
+    Failure(String),
+}
Expand description

Errors that may occur while solving dependencies.

+

Variants§

§

NoSolution(DerivationTree<P, VS>)

There is no solution for this set of dependencies.

+
§

ErrorRetrievingDependencies

Fields

§package: P

Package whose dependencies we want.

+
§version: VS::V

Version of the package for which we want the dependencies.

+
§source: E

Error raised by the implementer of +DependencyProvider.

+

Error arising when the implementer of +DependencyProvider +returned an error in the method +get_dependencies.

+
§

SelfDependency

Fields

§package: P

Package whose dependencies we want.

+
§version: VS::V

Version of the package for which we want the dependencies.

+

Error arising when the implementer of +DependencyProvider +returned a dependency on the requested package. +This technically means that the package directly depends on itself, +and is clearly some kind of mistake.

+
§

ErrorChoosingPackageVersion(E)

Error arising when the implementer of +DependencyProvider +returned an error in the method +choose_version.

+
§

ErrorInShouldCancel(E)

Error arising when the implementer of DependencyProvider +returned an error in the method should_cancel.

+
§

Failure(String)

Something unexpected happened.

+

Trait Implementations§

source§

impl<P: Debug + Package, VS: Debug + VersionSet, E: Debug + Error> Debug for PubGrubError<P, VS, E>
where + VS::V: Debug,

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<P, VS: VersionSet, E: Error> Display for PubGrubError<P, VS, E>
where + P: Display + Package,

source§

fn fmt(&self, __formatter: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<P: Package, VS: VersionSet, E> Error for PubGrubError<P, VS, E>
where + E: Error + 'static, + Self: Debug + Display,

source§

fn source(&self) -> Option<&(dyn Error + 'static)>

The lower-level source of this error, if any. Read more
1.0.0 · source§

fn description(&self) -> &str

👎Deprecated since 1.42.0: use the Display impl or to_string()
1.0.0 · source§

fn cause(&self) -> Option<&dyn Error>

👎Deprecated since 1.33.0: replaced by Error::source, which can support downcasting
source§

fn provide<'a>(&'a self, request: &mut Request<'a>)

🔬This is a nightly-only experimental API. (error_generic_member_access)
Provides type based access to context intended for error reports. Read more

Auto Trait Implementations§

§

impl<P, VS, E> RefUnwindSafe for PubGrubError<P, VS, E>
where + E: RefUnwindSafe, + P: RefUnwindSafe, + VS: RefUnwindSafe, + <VS as VersionSet>::V: RefUnwindSafe,

§

impl<P, VS, E> Send for PubGrubError<P, VS, E>
where + E: Send, + P: Sync + Send, + VS: Sync + Send, + <VS as VersionSet>::V: Sync + Send,

§

impl<P, VS, E> Sync for PubGrubError<P, VS, E>
where + E: Sync, + P: Sync + Send, + VS: Sync + Send, + <VS as VersionSet>::V: Sync + Send,

§

impl<P, VS, E> Unpin for PubGrubError<P, VS, E>
where + E: Unpin, + P: Unpin, + VS: Unpin, + <VS as VersionSet>::V: Unpin,

§

impl<P, VS, E> UnwindSafe for PubGrubError<P, VS, E>

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> ToString for T
where + T: Display + ?Sized,

source§

default fn to_string(&self) -> String

Converts the given value to a String. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

§

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

§

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.
\ No newline at end of file diff --git a/pubgrub/error/index.html b/pubgrub/error/index.html new file mode 100644 index 00000000..c09b08cc --- /dev/null +++ b/pubgrub/error/index.html @@ -0,0 +1,3 @@ +pubgrub::error - Rust +

Module pubgrub::error

source ·
Expand description

Handling pubgrub errors.

+

Enums§

  • Errors that may occur while solving dependencies.
\ No newline at end of file diff --git a/pubgrub/error/sidebar-items.js b/pubgrub/error/sidebar-items.js new file mode 100644 index 00000000..2784fed9 --- /dev/null +++ b/pubgrub/error/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"enum":["PubGrubError"]}; \ No newline at end of file diff --git a/pubgrub/index.html b/pubgrub/index.html new file mode 100644 index 00000000..8e9c0091 --- /dev/null +++ b/pubgrub/index.html @@ -0,0 +1,175 @@ +pubgrub - Rust +

Crate pubgrub

source ·
Expand description

PubGrub version solving algorithm.

+

Version solving consists in efficiently finding a set of packages and versions +that satisfy all the constraints of a given project dependencies. +In addition, when that is not possible, +we should try to provide a very human-readable and clear +explanation as to why that failed.

+

§Package and Version traits

+

All the code in this crate is manipulating packages and versions, and for this to work +we defined a Package and Version traits +that are used as bounds on most of the exposed types and functions.

+

Package identifiers needs to implement our Package trait, +which is automatic if the type already implements +Clone + Eq + Hash + Debug + Display. +So things like String will work out of the box.

+

Our Version trait requires +Clone + Ord + Debug + Display +and also the definition of two methods, +lowest() -> Self which returns the lowest version existing, +and bump(&self) -> Self which returns the next smallest version +strictly higher than the current one. +For convenience, this library already provides +two implementations of Version. +The first one is NumberVersion, basically a newtype for u32. +The second one is SemanticVersion +that implements semantic versioning rules.

+

§Basic example

+

Let’s imagine that we are building a user interface +with a menu containing dropdowns with some icons, +icons that we are also directly using in other parts of the interface. +For this scenario our direct dependencies are menu and icons, +but the complete set of dependencies looks like follows:

+
    +
  • root depends on menu and icons
  • +
  • menu depends on dropdown
  • +
  • dropdown depends on icons
  • +
  • icons has no dependency
  • +
+

We can model that scenario with this library as follows

+ +

+type NumVS = Range<NumberVersion>;
+
+let mut dependency_provider = OfflineDependencyProvider::<&str, NumVS>::new();
+
+dependency_provider.add_dependencies(
+    "root", 1, [("menu", Range::full()), ("icons", Range::full())],
+);
+dependency_provider.add_dependencies("menu", 1, [("dropdown", Range::full())]);
+dependency_provider.add_dependencies("dropdown", 1, [("icons", Range::full())]);
+dependency_provider.add_dependencies("icons", 1, []);
+
+// Run the algorithm.
+let solution = resolve(&dependency_provider, "root", 1).unwrap();
+

§DependencyProvider trait

+

In our previous example we used the +OfflineDependencyProvider, +which is a basic implementation of the DependencyProvider trait.

+

But we might want to implement the DependencyProvider +trait for our own type. +Let’s say that we will use String for packages, +and SemanticVersion for versions. +This may be done quite easily by implementing the three following functions.

+ +
type SemVS = Range<SemanticVersion>;
+
+impl DependencyProvider<String, SemVS> for MyDependencyProvider {
+    fn choose_version(&self, package: &String, range: &SemVS) -> Result<Option<SemanticVersion>, Infallible> {
+        unimplemented!()
+    }
+
+    type Priority = usize;
+    fn prioritize(&self, package: &String, range: &SemVS) -> Self::Priority {
+        unimplemented!()
+    }
+
+    fn get_dependencies(
+        &self,
+        package: &String,
+        version: &SemanticVersion,
+    ) -> Result<Dependencies<String, SemVS>, Infallible> {
+        unimplemented!()
+    }
+
+    type Err = Infallible;
+}
+

The first method +choose_version +chooses a version compatible with the provided range for a package. +The second method +prioritize +in which order different packages should be chosen. +Usually prioritizing packages +with the fewest number of compatible versions speeds up resolution. +But in general you are free to employ whatever strategy suits you best +to pick a package and a version.

+

The third method get_dependencies +aims at retrieving the dependencies of a given package at a given version. +Returns None if dependencies are unknown.

+

In a real scenario, these two methods may involve reading the file system +or doing network request, so you may want to hold a cache in your +DependencyProvider implementation. +How exactly this could be achieved is shown in CachingDependencyProvider +(see examples/caching_dependency_provider.rs). +You could also use the OfflineDependencyProvider +type defined by the crate as guidance, +but you are free to use whatever approach makes sense in your situation.

+

§Solution and error reporting

+

When everything goes well, the algorithm finds and returns the complete +set of direct and indirect dependencies satisfying all the constraints. +The packages and versions selected are returned as +SelectedDepedencies<P, V>. +But sometimes there is no solution because dependencies are incompatible. +In such cases, resolve(…) returns a +PubGrubError::NoSolution(derivation_tree), +where the provided derivation tree is a custom binary tree +containing the full chain of reasons why there is no solution.

+

All the items in the tree are called incompatibilities +and may be of two types, either “external” or “derived”. +Leaves of the tree are external incompatibilities, +and nodes are derived. +External incompatibilities have reasons that are independent +of the way this algorithm is implemented such as

+
    +
  • dependencies: “package_a” at version 1 depends on “package_b” at version 4
  • +
  • missing dependencies: dependencies of “package_a” are unknown
  • +
  • absence of version: there is no version of “package_a” in the range [3.1.0 4.0.0[
  • +
+

Derived incompatibilities are obtained during the algorithm execution by deduction, +such as if “a” depends on “b” and “b” depends on “c”, “a” depends on “c”.

+

This crate defines a Reporter trait, with an associated +Output type and a single method.

+ +
pub trait Reporter<P: Package, VS: VersionSet> {
+    type Output;
+
+    fn report(derivation_tree: &DerivationTree<P, VS>) -> Self::Output;
+}
+

Implementing a Reporter may involve a lot of heuristics +to make the output human-readable and natural. +For convenience, we provide a default implementation +DefaultStringReporter +that outputs the report as a String. +You may use it as follows:

+ +
match resolve(&dependency_provider, root_package, root_version) {
+    Ok(solution) => println!("{:?}", solution),
+    Err(PubGrubError::NoSolution(mut derivation_tree)) => {
+        derivation_tree.collapse_no_versions();
+        eprintln!("{}", DefaultStringReporter::report(&derivation_tree));
+    }
+    Err(err) => panic!("{:?}", err),
+};
+

Notice that we also used +collapse_no_versions() above. +This method simplifies the derivation tree to get rid of the +NoVersions +external incompatibilities in the derivation tree. +So instead of seeing things like this in the report:

+
Because there is no version of foo in 1.0.1 <= v < 2.0.0
+and foo 1.0.0 depends on bar 2.0.0 <= v < 3.0.0,
+foo 1.0.0 <= v < 2.0.0 depends on bar 2.0.0 <= v < 3.0.0.
+
+

you may have directly:

+
foo 1.0.0 <= v < 2.0.0 depends on bar 2.0.0 <= v < 3.0.0.
+
+

Beware though that if you are using some kind of offline mode +with a cache, you may want to know that some versions +do not exist in your cache.

+

Modules§

  • Handling pubgrub errors.
  • Trait for identifying packages. +Automatically implemented for traits implementing +Clone + Eq + Hash + Debug + Display.
  • Ranges are constraints defining sets of versions.
  • Build a report as clear as possible as to why +dependency solving failed.
  • PubGrub version solving algorithm.
  • A term is the fundamental unit of operation of the PubGrub algorithm. +It is a positive or negative expression regarding a set of versions.
  • Publicly exported type aliases.
  • Traits and implementations to create and compare versions.
  • As its name suggests, the VersionSet trait describes sets of versions.
\ No newline at end of file diff --git a/pubgrub/package/index.html b/pubgrub/package/index.html new file mode 100644 index 00000000..1f4b1471 --- /dev/null +++ b/pubgrub/package/index.html @@ -0,0 +1,7 @@ +pubgrub::package - Rust +

Module pubgrub::package

source ·
Expand description

Trait for identifying packages. +Automatically implemented for traits implementing +Clone + Eq + Hash + Debug + Display.

+

Traits§

\ No newline at end of file diff --git a/pubgrub/package/sidebar-items.js b/pubgrub/package/sidebar-items.js new file mode 100644 index 00000000..79733012 --- /dev/null +++ b/pubgrub/package/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"trait":["Package"]}; \ No newline at end of file diff --git a/pubgrub/package/trait.Package.html b/pubgrub/package/trait.Package.html new file mode 100644 index 00000000..5b4b9d02 --- /dev/null +++ b/pubgrub/package/trait.Package.html @@ -0,0 +1,7 @@ +Package in pubgrub::package - Rust +

Trait pubgrub::package::Package

source ·
pub trait Package: Clone + Eq + Hash + Debug + Display { }
Expand description

Trait for identifying packages. +Automatically implemented for types already implementing +Clone + Eq + Hash + Debug + Display.

+

Object Safety§

This trait is not object safe.

Implementors§

source§

impl<T: Clone + Eq + Hash + Debug + Display> Package for T

Automatically implement the Package trait for any type +that already implement Clone + Eq + Hash + Debug + Display.

+
\ No newline at end of file diff --git a/pubgrub/range/index.html b/pubgrub/range/index.html new file mode 100644 index 00000000..5ae466cd --- /dev/null +++ b/pubgrub/range/index.html @@ -0,0 +1,47 @@ +pubgrub::range - Rust +

Module pubgrub::range

source ·
Expand description

Ranges are constraints defining sets of versions.

+

Concretely, those constraints correspond to any set of versions +representable as the concatenation, union, and complement +of the ranges building blocks.

+

Those building blocks are:

+ +

Ranges can be created from any type that implements Ord + Clone.

+

In order to advance the solver front, comparisons of versions sets are necessary in the algorithm. +To do those comparisons between two sets S1 and S2 we use the mathematical property that S1 ⊂ S2 if and only if S1 ∩ S2 == S1. +We can thus compute an intersection and evaluate an equality to answer if S1 is a subset of S2. +But this means that the implementation of equality must be correct semantically. +In practice, if equality is derived automatically, this means sets must have unique representations.

+

By migrating from a custom representation for discrete sets in v0.2 +to a generic bounded representation for continuous sets in v0.3 +we are potentially breaking that assumption in two ways:

+
    +
  1. Minimal and maximal Unbounded values can be replaced by their equivalent if it exists.
  2. +
  3. Simplifying adjacent bounds of discrete sets cannot be detected and automated in the generic intersection code.
  4. +
+

An example for each can be given when T is u32. +First, we can have both segments S1 = (Unbounded, Included(42u32)) and S2 = (Included(0), Included(42u32)) +that represent the same segment but are structurally different. +Thus, a derived equality check would answer false to S1 == S2 while it’s true.

+

Second both segments S1 = (Included(1), Included(5)) and S2 = (Included(1), Included(3)) + (Included(4), Included(5)) are equal. +But without asking the user to provide a bump function for discrete sets, +the algorithm is not able tell that the space between the right Included(3) bound and the left Included(4) bound is empty. +Thus the algorithm is not able to reduce S2 to its canonical S1 form while computing sets operations like intersections in the generic code.

+

This is likely to lead to user facing theoretically correct but practically nonsensical ranges, +like (Unbounded, Excluded(0)) or (Excluded(6), Excluded(7)). +In general nonsensical inputs often lead to hard to track bugs. +But as far as we can tell this should work in practice. +So for now this crate only provides an implementation for continuous ranges. +With the v0.3 api the user could choose to bring back the discrete implementation from v0.2, as documented in the guide. +If doing so regularly fixes bugs seen by users, we will bring it back into the core library. +If we do not see practical bugs, or we get a formal proof that the code cannot lead to error states, then we may remove this warning.

+

Structs§

  • A Range represents multiple intervals of a continuous range of monotone increasing +values.
\ No newline at end of file diff --git a/pubgrub/range/sidebar-items.js b/pubgrub/range/sidebar-items.js new file mode 100644 index 00000000..28f90cc7 --- /dev/null +++ b/pubgrub/range/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"struct":["Range"]}; \ No newline at end of file diff --git a/pubgrub/range/struct.Range.html b/pubgrub/range/struct.Range.html new file mode 100644 index 00000000..fe5d0f1b --- /dev/null +++ b/pubgrub/range/struct.Range.html @@ -0,0 +1,76 @@ +Range in pubgrub::range - Rust +

Struct pubgrub::range::Range

source ·
pub struct Range<V> { /* private fields */ }
Expand description

A Range represents multiple intervals of a continuous range of monotone increasing +values.

+

Implementations§

source§

impl<V> Range<V>

source

pub fn empty() -> Self

Empty set of versions.

+
source

pub fn full() -> Self

Set of all possible versions

+
source

pub fn higher_than(v: impl Into<V>) -> Self

Set of all versions higher or equal to some version

+
source

pub fn strictly_higher_than(v: impl Into<V>) -> Self

Set of all versions higher to some version

+
source

pub fn strictly_lower_than(v: impl Into<V>) -> Self

Set of all versions lower to some version

+
source

pub fn lower_than(v: impl Into<V>) -> Self

Set of all versions lower or equal to some version

+
source

pub fn between(v1: impl Into<V>, v2: impl Into<V>) -> Self

Set of versions greater or equal to v1 but less than v2.

+
source§

impl<V: Clone> Range<V>

source

pub fn singleton(v: impl Into<V>) -> Self

Set containing exactly one version

+
source

pub fn complement(&self) -> Self

Returns the complement of this Range.

+
source§

impl<V: Ord> Range<V>

source

pub fn bounding_range(&self) -> Option<(Bound<&V>, Bound<&V>)>

Convert to something that can be used with +BTreeMap::range. +All versions contained in self, will be in the output, +but there may be versions in the output that are not contained in self. +Returns None if the range is empty.

+
source

pub fn contains(&self, v: &V) -> bool

Returns true if the this Range contains the specified value.

+
source

pub fn contains_many<'s, I>( + &'s self, + versions: I +) -> impl Iterator<Item = bool> + 's
where + I: Iterator<Item = &'s V> + 's, + V: 's,

Returns true if the this Range contains the specified values.

+

The versions iterator must be sorted. +Functionally equivalent to versions.map(|v| self.contains(v)). +Except it runs in O(size_of_range + len_of_versions) not O(size_of_range * len_of_versions)

+
source

pub fn from_range_bounds<R, IV>(bounds: R) -> Self
where + R: RangeBounds<IV>, + IV: Clone + Into<V>,

Construct a simple range from anything that impls RangeBounds like v1..v2.

+
source§

impl<V: Ord + Clone> Range<V>

source

pub fn union(&self, other: &Self) -> Self

Computes the union of this Range and another.

+
source

pub fn intersection(&self, other: &Self) -> Self

Computes the intersection of two sets of versions.

+
source

pub fn simplify<'v, I>(&self, versions: I) -> Self
where + I: Iterator<Item = &'v V> + 'v, + V: 'v,

Returns a simpler Range that contains the same versions

+

For every one of the Versions provided in versions the existing range and +the simplified range will agree on whether it is contained. +The simplified version may include or exclude versions that are not in versions as the implementation wishes. +For example:

+
    +
  • If all the versions are contained in the original than the range will be simplified to full.
  • +
  • If none of the versions are contained in the original than the range will be simplified to empty.
  • +
+

If versions are not sorted the correctness of this function is not guaranteed.

+

Trait Implementations§

source§

impl<V: Clone> Clone for Range<V>

source§

fn clone(&self) -> Range<V>

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl<V: Debug> Debug for Range<V>

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<V: Display + Eq> Display for Range<V>

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<V: Hash> Hash for Range<V>

source§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.3.0 · source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where + H: Hasher, + Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
source§

impl<V: PartialEq> PartialEq for Range<V>

source§

fn eq(&self, other: &Range<V>) -> bool

This method tests for self and other values to be equal, and is used +by ==.
1.0.0 · source§

fn ne(&self, other: &Rhs) -> bool

This method tests for !=. The default implementation is almost always +sufficient, and should not be overridden without very good reason.
source§

impl<T: Debug + Display + Clone + Eq + Ord> VersionSet for Range<T>

§

type V = T

Version type associated with the sets manipulated.
source§

fn empty() -> Self

Constructor for an empty set containing no version.
source§

fn singleton(v: Self::V) -> Self

Constructor for a set containing exactly one version.
source§

fn complement(&self) -> Self

Compute the complement of this set.
source§

fn intersection(&self, other: &Self) -> Self

Compute the intersection with another set.
source§

fn contains(&self, v: &Self::V) -> bool

Evaluate membership of a version in this set.
source§

fn full() -> Self

Constructor for the set containing all versions. +Automatically implemented as Self::empty().complement().
source§

fn union(&self, other: &Self) -> Self

Compute the union with another set. +Thanks to set properties, this is automatically implemented as: +self.complement().intersection(&other.complement()).complement()
source§

impl<V: Eq> Eq for Range<V>

source§

impl<V> StructuralPartialEq for Range<V>

Auto Trait Implementations§

§

impl<V> RefUnwindSafe for Range<V>
where + V: RefUnwindSafe,

§

impl<V> Send for Range<V>
where + V: Send,

§

impl<V> Sync for Range<V>
where + V: Sync,

§

impl<V> Unpin for Range<V>
where + V: Unpin,

§

impl<V> UnwindSafe for Range<V>
where + V: UnwindSafe,

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<Q, K> Equivalent<K> for Q
where + Q: Eq + ?Sized, + K: Borrow<Q> + ?Sized,

source§

fn equivalent(&self, key: &K) -> bool

Compare self to key and return true if they are equal.
§

impl<Q, K> Equivalent<K> for Q
where + Q: Eq + ?Sized, + K: Borrow<Q> + ?Sized,

§

fn equivalent(&self, key: &K) -> bool

Checks if this value is equivalent to the given key. Read more
§

impl<Q, K> Equivalent<K> for Q
where + Q: Eq + ?Sized, + K: Borrow<Q> + ?Sized,

§

fn equivalent(&self, key: &K) -> bool

Compare self to key and return true if they are equal.
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> ToOwned for T
where + T: Clone,

§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T> ToString for T
where + T: Display + ?Sized,

source§

default fn to_string(&self) -> String

Converts the given value to a String. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

§

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

§

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.
source§

impl<T> Package for T
where + T: Clone + Eq + Hash + Debug + Display,

\ No newline at end of file diff --git a/pubgrub/report/enum.DerivationTree.html b/pubgrub/report/enum.DerivationTree.html new file mode 100644 index 00000000..69995521 --- /dev/null +++ b/pubgrub/report/enum.DerivationTree.html @@ -0,0 +1,43 @@ +DerivationTree in pubgrub::report - Rust +
pub enum DerivationTree<P: Package, VS: VersionSet> {
+    External(External<P, VS>),
+    Derived(Derived<P, VS>),
+}
Expand description

Derivation tree resulting in the impossibility +to solve the dependencies of our root package.

+

Variants§

§

External(External<P, VS>)

External incompatibility.

+
§

Derived(Derived<P, VS>)

Incompatibility derived from two others.

+

Implementations§

source§

impl<P: Package, VS: VersionSet> DerivationTree<P, VS>

source

pub fn collapse_no_versions(&mut self)

Merge the NoVersions external incompatibilities +with the other one they are matched with +in a derived incompatibility. +This cleans up quite nicely the generated report. +You might want to do this if you know that the +DependencyProvider +was not run in some kind of offline mode that may not +have access to all versions existing.

+

Trait Implementations§

source§

impl<P: Clone + Package, VS: Clone + VersionSet> Clone for DerivationTree<P, VS>

source§

fn clone(&self) -> DerivationTree<P, VS>

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl<P: Debug + Package, VS: Debug + VersionSet> Debug for DerivationTree<P, VS>

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl<P, VS> RefUnwindSafe for DerivationTree<P, VS>
where + P: RefUnwindSafe, + VS: RefUnwindSafe, + <VS as VersionSet>::V: RefUnwindSafe,

§

impl<P, VS> Send for DerivationTree<P, VS>
where + P: Sync + Send, + VS: Sync + Send, + <VS as VersionSet>::V: Sync + Send,

§

impl<P, VS> Sync for DerivationTree<P, VS>
where + P: Sync + Send, + VS: Sync + Send, + <VS as VersionSet>::V: Sync + Send,

§

impl<P, VS> Unpin for DerivationTree<P, VS>
where + P: Unpin, + VS: Unpin, + <VS as VersionSet>::V: Unpin,

§

impl<P, VS> UnwindSafe for DerivationTree<P, VS>

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> ToOwned for T
where + T: Clone,

§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

§

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

§

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.
\ No newline at end of file diff --git a/pubgrub/report/enum.External.html b/pubgrub/report/enum.External.html new file mode 100644 index 00000000..255614dc --- /dev/null +++ b/pubgrub/report/enum.External.html @@ -0,0 +1,42 @@ +External in pubgrub::report - Rust +

Enum pubgrub::report::External

source ·
pub enum External<P: Package, VS: VersionSet> {
+    NotRoot(P, VS::V),
+    NoVersions(P, VS),
+    UnavailableDependencies(P, VS),
+    FromDependencyOf(P, VS, P, VS),
+}
Expand description

Incompatibilities that are not derived from others, +they have their own reason.

+

Variants§

§

NotRoot(P, VS::V)

Initial incompatibility aiming at picking the root package for the first decision.

+
§

NoVersions(P, VS)

There are no versions in the given set for this package.

+
§

UnavailableDependencies(P, VS)

Dependencies of the package are unavailable for versions in that set.

+
§

FromDependencyOf(P, VS, P, VS)

Incompatibility coming from the dependencies of a given package.

+

Trait Implementations§

source§

impl<P: Clone + Package, VS: Clone + VersionSet> Clone for External<P, VS>
where + VS::V: Clone,

source§

fn clone(&self) -> External<P, VS>

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl<P: Debug + Package, VS: Debug + VersionSet> Debug for External<P, VS>
where + VS::V: Debug,

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<P: Package, VS: VersionSet> Display for External<P, VS>

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl<P, VS> RefUnwindSafe for External<P, VS>
where + P: RefUnwindSafe, + VS: RefUnwindSafe, + <VS as VersionSet>::V: RefUnwindSafe,

§

impl<P, VS> Send for External<P, VS>
where + P: Send, + VS: Send, + <VS as VersionSet>::V: Send,

§

impl<P, VS> Sync for External<P, VS>
where + P: Sync, + VS: Sync, + <VS as VersionSet>::V: Sync,

§

impl<P, VS> Unpin for External<P, VS>
where + P: Unpin, + VS: Unpin, + <VS as VersionSet>::V: Unpin,

§

impl<P, VS> UnwindSafe for External<P, VS>
where + P: UnwindSafe, + VS: UnwindSafe, + <VS as VersionSet>::V: UnwindSafe,

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> ToOwned for T
where + T: Clone,

§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T> ToString for T
where + T: Display + ?Sized,

source§

default fn to_string(&self) -> String

Converts the given value to a String. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

§

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

§

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.
\ No newline at end of file diff --git a/pubgrub/report/index.html b/pubgrub/report/index.html new file mode 100644 index 00000000..fdc7bd6f --- /dev/null +++ b/pubgrub/report/index.html @@ -0,0 +1,6 @@ +pubgrub::report - Rust +

Module pubgrub::report

source ·
Expand description

Build a report as clear as possible as to why +dependency solving failed.

+

Structs§

Enums§

  • Derivation tree resulting in the impossibility +to solve the dependencies of our root package.
  • Incompatibilities that are not derived from others, +they have their own reason.

Traits§

\ No newline at end of file diff --git a/pubgrub/report/sidebar-items.js b/pubgrub/report/sidebar-items.js new file mode 100644 index 00000000..7659cb2a --- /dev/null +++ b/pubgrub/report/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"enum":["DerivationTree","External"],"struct":["DefaultStringReportFormatter","DefaultStringReporter","Derived"],"trait":["ReportFormatter","Reporter"]}; \ No newline at end of file diff --git a/pubgrub/report/struct.DefaultStringReportFormatter.html b/pubgrub/report/struct.DefaultStringReportFormatter.html new file mode 100644 index 00000000..d889fd85 --- /dev/null +++ b/pubgrub/report/struct.DefaultStringReportFormatter.html @@ -0,0 +1,13 @@ +DefaultStringReportFormatter in pubgrub::report - Rust +
pub struct DefaultStringReportFormatter;
Expand description

Default formatter for the default reporter.

+

Trait Implementations§

source§

impl Debug for DefaultStringReportFormatter

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl Default for DefaultStringReportFormatter

source§

fn default() -> DefaultStringReportFormatter

Returns the “default value” for a type. Read more
source§

impl<P: Package, VS: VersionSet> ReportFormatter<P, VS> for DefaultStringReportFormatter

§

type Output = String

Output type of the report.
source§

fn format_external(&self, external: &External<P, VS>) -> String

Format an External incompatibility.
source§

fn format_terms(&self, terms: &Map<P, Term<VS>>) -> Self::Output

Format terms of an incompatibility.

Auto Trait Implementations§

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

§

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

§

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.
\ No newline at end of file diff --git a/pubgrub/report/struct.DefaultStringReporter.html b/pubgrub/report/struct.DefaultStringReporter.html new file mode 100644 index 00000000..9c7e86da --- /dev/null +++ b/pubgrub/report/struct.DefaultStringReporter.html @@ -0,0 +1,18 @@ +DefaultStringReporter in pubgrub::report - Rust +
pub struct DefaultStringReporter { /* private fields */ }
Expand description

Default reporter able to generate an explanation as a String.

+

Trait Implementations§

source§

impl<P: Package, VS: VersionSet> Reporter<P, VS> for DefaultStringReporter

§

type Output = String

Output type of the report.
source§

fn report(derivation_tree: &DerivationTree<P, VS>) -> Self::Output

Generate a report from the derivation tree +describing the resolution failure using the default formatter.
source§

fn report_with_formatter( + derivation_tree: &DerivationTree<P, VS>, + formatter: &impl ReportFormatter<P, VS, Output = Self::Output> +) -> Self::Output

Generate a report from the derivation tree +describing the resolution failure using a custom formatter.

Auto Trait Implementations§

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

§

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

§

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.
\ No newline at end of file diff --git a/pubgrub/report/struct.Derived.html b/pubgrub/report/struct.Derived.html new file mode 100644 index 00000000..50dea0ea --- /dev/null +++ b/pubgrub/report/struct.Derived.html @@ -0,0 +1,41 @@ +Derived in pubgrub::report - Rust +

Struct pubgrub::report::Derived

source ·
pub struct Derived<P: Package, VS: VersionSet> {
+    pub terms: Map<P, Term<VS>>,
+    pub shared_id: Option<usize>,
+    pub cause1: Arc<DerivationTree<P, VS>>,
+    pub cause2: Arc<DerivationTree<P, VS>>,
+}
Expand description

Incompatibility derived from two others.

+

Fields§

§terms: Map<P, Term<VS>>

Terms of the incompatibility.

+
§shared_id: Option<usize>

Indicate if that incompatibility is present multiple times +in the derivation tree. +If that is the case, it has a unique id, provided in that option. +Then, we may want to only explain it once, +and refer to the explanation for the other times.

+
§cause1: Arc<DerivationTree<P, VS>>

First cause.

+
§cause2: Arc<DerivationTree<P, VS>>

Second cause.

+

Trait Implementations§

source§

impl<P: Clone + Package, VS: Clone + VersionSet> Clone for Derived<P, VS>

source§

fn clone(&self) -> Derived<P, VS>

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl<P: Debug + Package, VS: Debug + VersionSet> Debug for Derived<P, VS>

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl<P, VS> RefUnwindSafe for Derived<P, VS>
where + P: RefUnwindSafe, + VS: RefUnwindSafe, + <VS as VersionSet>::V: RefUnwindSafe,

§

impl<P, VS> Send for Derived<P, VS>
where + P: Sync + Send, + VS: Sync + Send, + <VS as VersionSet>::V: Sync + Send,

§

impl<P, VS> Sync for Derived<P, VS>
where + P: Sync + Send, + VS: Sync + Send, + <VS as VersionSet>::V: Sync + Send,

§

impl<P, VS> Unpin for Derived<P, VS>
where + P: Unpin, + VS: Unpin,

§

impl<P, VS> UnwindSafe for Derived<P, VS>

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> ToOwned for T
where + T: Clone,

§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

§

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

§

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.
\ No newline at end of file diff --git a/pubgrub/report/trait.ReportFormatter.html b/pubgrub/report/trait.ReportFormatter.html new file mode 100644 index 00000000..e18077f6 --- /dev/null +++ b/pubgrub/report/trait.ReportFormatter.html @@ -0,0 +1,12 @@ +ReportFormatter in pubgrub::report - Rust +
pub trait ReportFormatter<P: Package, VS: VersionSet> {
+    type Output;
+
+    // Required methods
+    fn format_external(&self, external: &External<P, VS>) -> Self::Output;
+    fn format_terms(&self, terms: &Map<P, Term<VS>>) -> Self::Output;
+}
Expand description

Trait for formatting outputs in the reporter.

+

Required Associated Types§

source

type Output

Output type of the report.

+

Required Methods§

source

fn format_external(&self, external: &External<P, VS>) -> Self::Output

Format an External incompatibility.

+
source

fn format_terms(&self, terms: &Map<P, Term<VS>>) -> Self::Output

Format terms of an incompatibility.

+

Implementors§

\ No newline at end of file diff --git a/pubgrub/report/trait.Reporter.html b/pubgrub/report/trait.Reporter.html new file mode 100644 index 00000000..d3d73b7c --- /dev/null +++ b/pubgrub/report/trait.Reporter.html @@ -0,0 +1,20 @@ +Reporter in pubgrub::report - Rust +

Trait pubgrub::report::Reporter

source ·
pub trait Reporter<P: Package, VS: VersionSet> {
+    type Output;
+
+    // Required methods
+    fn report(derivation_tree: &DerivationTree<P, VS>) -> Self::Output;
+    fn report_with_formatter(
+        derivation_tree: &DerivationTree<P, VS>,
+        formatter: &impl ReportFormatter<P, VS, Output = Self::Output>
+    ) -> Self::Output;
+}
Expand description

Reporter trait.

+

Required Associated Types§

source

type Output

Output type of the report.

+

Required Methods§

source

fn report(derivation_tree: &DerivationTree<P, VS>) -> Self::Output

Generate a report from the derivation tree +describing the resolution failure using the default formatter.

+
source

fn report_with_formatter( + derivation_tree: &DerivationTree<P, VS>, + formatter: &impl ReportFormatter<P, VS, Output = Self::Output> +) -> Self::Output

Generate a report from the derivation tree +describing the resolution failure using a custom formatter.

+

Object Safety§

This trait is not object safe.

Implementors§

\ No newline at end of file diff --git a/pubgrub/sidebar-items.js b/pubgrub/sidebar-items.js new file mode 100644 index 00000000..6ab208cd --- /dev/null +++ b/pubgrub/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"mod":["error","package","range","report","solver","term","type_aliases","version","version_set"]}; \ No newline at end of file diff --git a/pubgrub/solver/enum.Dependencies.html b/pubgrub/solver/enum.Dependencies.html new file mode 100644 index 00000000..6831a4fd --- /dev/null +++ b/pubgrub/solver/enum.Dependencies.html @@ -0,0 +1,30 @@ +Dependencies in pubgrub::solver - Rust +
pub enum Dependencies<P: Package, VS: VersionSet> {
+    Unknown,
+    Known(DependencyConstraints<P, VS>),
+}
Expand description

An enum used by DependencyProvider that holds information about package dependencies. +For each Package there is a set of versions allowed as a dependency.

+

Variants§

§

Unknown

Package dependencies are unavailable.

+
§

Known(DependencyConstraints<P, VS>)

Container for all available package versions.

+

Trait Implementations§

source§

impl<P: Clone + Package, VS: Clone + VersionSet> Clone for Dependencies<P, VS>

source§

fn clone(&self) -> Dependencies<P, VS>

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more

Auto Trait Implementations§

§

impl<P, VS> RefUnwindSafe for Dependencies<P, VS>
where + P: RefUnwindSafe, + VS: RefUnwindSafe,

§

impl<P, VS> Send for Dependencies<P, VS>
where + P: Send, + VS: Send,

§

impl<P, VS> Sync for Dependencies<P, VS>
where + P: Sync, + VS: Sync,

§

impl<P, VS> Unpin for Dependencies<P, VS>
where + P: Unpin, + VS: Unpin,

§

impl<P, VS> UnwindSafe for Dependencies<P, VS>
where + P: UnwindSafe, + VS: UnwindSafe,

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> ToOwned for T
where + T: Clone,

§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

§

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

§

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.
\ No newline at end of file diff --git a/pubgrub/solver/fn.resolve.html b/pubgrub/solver/fn.resolve.html new file mode 100644 index 00000000..eb1793fa --- /dev/null +++ b/pubgrub/solver/fn.resolve.html @@ -0,0 +1,8 @@ +resolve in pubgrub::solver - Rust +

Function pubgrub::solver::resolve

source ·
pub fn resolve<P: Package, VS: VersionSet, DP: DependencyProvider<P, VS>>(
+    dependency_provider: &DP,
+    package: P,
+    version: impl Into<VS::V>
+) -> Result<SelectedDependencies<P, VS::V>, PubGrubError<P, VS, DP::Err>>
Expand description

Main function of the library. +Finds a set of packages satisfying dependency bounds for a given package + version pair.

+
\ No newline at end of file diff --git a/pubgrub/solver/index.html b/pubgrub/solver/index.html new file mode 100644 index 00000000..bffccfe5 --- /dev/null +++ b/pubgrub/solver/index.html @@ -0,0 +1,47 @@ +pubgrub::solver - Rust +

Module pubgrub::solver

source ·
Expand description

PubGrub version solving algorithm.

+

It consists in efficiently finding a set of packages and versions +that satisfy all the constraints of a given project dependencies. +In addition, when that is not possible, +PubGrub tries to provide a very human-readable and clear +explanation as to why that failed. +Below is an example of explanation present in +the introductory blog post about PubGrub

+
Because dropdown >=2.0.0 depends on icons >=2.0.0 and
+  root depends on icons <2.0.0, dropdown >=2.0.0 is forbidden.
+
+And because menu >=1.1.0 depends on dropdown >=2.0.0,
+  menu >=1.1.0 is forbidden.
+
+And because menu <1.1.0 depends on dropdown >=1.0.0 <2.0.0
+  which depends on intl <4.0.0, every version of menu
+  requires intl <4.0.0.
+
+So, because root depends on both menu >=1.0.0 and intl >=5.0.0,
+  version solving failed.
+
+

The algorithm is generic and works for any type of dependency system +as long as packages (P) and versions (V) implement +the Package and Version traits. +Package is strictly equivalent and automatically generated +for any type that implement Clone + Eq + Hash + Debug + Display. +Version simply states that versions are ordered, +that there should be +a minimal lowest version (like 0.0.0 in semantic versions), +and that for any version, it is possible to compute +what the next version closest to this one is (bump). +For semantic versions, bump corresponds to +an increment of the patch number.

+

§API

+
let solution = resolve(&dependency_provider, package, version)?;
+

Where dependency_provider supplies the list of available packages and versions, +as well as the dependencies of every available package +by implementing the DependencyProvider trait. +The call to resolve for a given package at a given version +will compute the set of packages and versions needed +to satisfy the dependencies of that package and version pair. +If there is no solution, the reason will be provided as clear as possible.

+

Structs§

Enums§

Traits§

  • Trait that allows the algorithm to retrieve available packages and their dependencies. +An implementor needs to be supplied to the resolve function.

Functions§

  • Main function of the library. +Finds a set of packages satisfying dependency bounds for a given package + version pair.
\ No newline at end of file diff --git a/pubgrub/solver/sidebar-items.js b/pubgrub/solver/sidebar-items.js new file mode 100644 index 00000000..ef14e571 --- /dev/null +++ b/pubgrub/solver/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"enum":["Dependencies"],"fn":["resolve"],"struct":["OfflineDependencyProvider"],"trait":["DependencyProvider"]}; \ No newline at end of file diff --git a/pubgrub/solver/struct.OfflineDependencyProvider.html b/pubgrub/solver/struct.OfflineDependencyProvider.html new file mode 100644 index 00000000..3bebd1d6 --- /dev/null +++ b/pubgrub/solver/struct.OfflineDependencyProvider.html @@ -0,0 +1,71 @@ +OfflineDependencyProvider in pubgrub::solver - Rust +
pub struct OfflineDependencyProvider<P: Package, VS: VersionSet> { /* private fields */ }
Expand description

A basic implementation of DependencyProvider.

+

Implementations§

source§

impl<P: Package, VS: VersionSet> OfflineDependencyProvider<P, VS>

source

pub fn new() -> Self

Creates an empty OfflineDependencyProvider with no dependencies.

+
source

pub fn add_dependencies<I: IntoIterator<Item = (P, VS)>>( + &mut self, + package: P, + version: impl Into<VS::V>, + dependencies: I +)

Registers the dependencies of a package and version pair. +Dependencies must be added with a single call to +add_dependencies. +All subsequent calls to +add_dependencies for a given +package version pair will replace the dependencies by the new ones.

+

The API does not allow to add dependencies one at a time to uphold an assumption that +OfflineDependencyProvider.get_dependencies(p, v) +provides all dependencies of a given package (p) and version (v) pair.

+
source

pub fn packages(&self) -> impl Iterator<Item = &P>

Lists packages that have been saved.

+
source

pub fn versions(&self, package: &P) -> Option<impl Iterator<Item = &VS::V>>

Lists versions of saved packages in sorted order. +Returns None if no information is available regarding that package.

+

Trait Implementations§

source§

impl<P: Clone + Package, VS: Clone + VersionSet> Clone for OfflineDependencyProvider<P, VS>
where + VS::V: Clone,

source§

fn clone(&self) -> OfflineDependencyProvider<P, VS>

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl<P: Debug + Package, VS: Debug + VersionSet> Debug for OfflineDependencyProvider<P, VS>
where + VS::V: Debug,

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<P: Default + Package, VS: Default + VersionSet> Default for OfflineDependencyProvider<P, VS>
where + VS::V: Default,

source§

fn default() -> OfflineDependencyProvider<P, VS>

Returns the “default value” for a type. Read more
source§

impl<P: Package, VS: VersionSet> DependencyProvider<P, VS> for OfflineDependencyProvider<P, VS>

An implementation of DependencyProvider that +contains all dependency information available in memory. +Currently packages are picked with the fewest versions contained in the constraints first. +But, that may change in new versions if better heuristics are found. +Versions are picked with the newest versions first.

+
§

type Err = Infallible

The kind of error returned from these methods. Read more
source§

fn choose_version( + &self, + package: &P, + range: &VS +) -> Result<Option<VS::V>, Infallible>

Once the resolver has found the highest Priority package from all potential valid +packages, it needs to know what vertion of that package to use. The most common pattern +is to select the largest vertion that the range contains.
§

type Priority = Reverse<usize>

The type returned from prioritize. The resolver does not care what type this is +as long as it can pick a largest one and clone it. Read more
source§

fn prioritize(&self, package: &P, range: &VS) -> Self::Priority

Decision making +is the process of choosing the next package +and version that will be appended to the partial solution. Read more
source§

fn get_dependencies( + &self, + package: &P, + version: &VS::V +) -> Result<Dependencies<P, VS>, Infallible>

Retrieves the package dependencies. +Return Dependencies::Unknown if its dependencies are unknown.
source§

fn should_cancel(&self) -> Result<(), Self::Err>

This is called fairly regularly during the resolution, +if it returns an Err then resolution will be terminated. +This is helpful if you want to add some form of early termination like a timeout, +or you want to add some form of user feedback if things are taking a while. +If not provided the resolver will run as long as needed.

Auto Trait Implementations§

§

impl<P, VS> RefUnwindSafe for OfflineDependencyProvider<P, VS>
where + P: RefUnwindSafe, + VS: RefUnwindSafe, + <VS as VersionSet>::V: RefUnwindSafe,

§

impl<P, VS> Send for OfflineDependencyProvider<P, VS>
where + P: Send, + VS: Send, + <VS as VersionSet>::V: Send,

§

impl<P, VS> Sync for OfflineDependencyProvider<P, VS>
where + P: Sync, + VS: Sync, + <VS as VersionSet>::V: Sync,

§

impl<P, VS> Unpin for OfflineDependencyProvider<P, VS>
where + P: Unpin,

§

impl<P, VS> UnwindSafe for OfflineDependencyProvider<P, VS>

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> ToOwned for T
where + T: Clone,

§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

§

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

§

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.
\ No newline at end of file diff --git a/pubgrub/solver/trait.DependencyProvider.html b/pubgrub/solver/trait.DependencyProvider.html new file mode 100644 index 00000000..1cadd92e --- /dev/null +++ b/pubgrub/solver/trait.DependencyProvider.html @@ -0,0 +1,76 @@ +DependencyProvider in pubgrub::solver - Rust +
pub trait DependencyProvider<P: Package, VS: VersionSet> {
+    type Priority: Ord + Clone;
+    type Err: Error;
+
+    // Required methods
+    fn prioritize(&self, package: &P, range: &VS) -> Self::Priority;
+    fn choose_version(
+        &self,
+        package: &P,
+        range: &VS
+    ) -> Result<Option<VS::V>, Self::Err>;
+    fn get_dependencies(
+        &self,
+        package: &P,
+        version: &VS::V
+    ) -> Result<Dependencies<P, VS>, Self::Err>;
+
+    // Provided method
+    fn should_cancel(&self) -> Result<(), Self::Err> { ... }
+}
Expand description

Trait that allows the algorithm to retrieve available packages and their dependencies. +An implementor needs to be supplied to the resolve function.

+

Required Associated Types§

source

type Priority: Ord + Clone

The type returned from prioritize. The resolver does not care what type this is +as long as it can pick a largest one and clone it.

+

std::cmp::Reverse can be useful if you want to pick the package with +the fewest versions that match the outstanding constraint.

+
source

type Err: Error

The kind of error returned from these methods.

+

Returning this signals that resolution should fail with this error.

+

Required Methods§

source

fn prioritize(&self, package: &P, range: &VS) -> Self::Priority

Decision making +is the process of choosing the next package +and version that will be appended to the partial solution.

+

Every time such a decision must be made, the resolver looks at all the potential valid +packages that have changed, and a asks the dependency provider how important each one is. +For each one it calls prioritize with the name of the package and the current set of +acceptable versions. +The resolver will then pick the package with the highes priority from all the potential valid +packages.

+

The strategy employed to prioritize packages +cannot change the existence of a solution or not, +but can drastically change the performances of the solver, +or the properties of the solution. +The documentation of Pub (PubGrub implementation for the dart programming language) +states the following:

+
+

Pub chooses the latest matching version of the package +with the fewest versions that match the outstanding constraint. +This tends to find conflicts earlier if any exist, +since these packages will run out of versions to try more quickly. +But there’s likely room for improvement in these heuristics.

+
+

Note: the resolver may call this even when the range has not change, +if it is more efficient for the resolveres internal data structures.

+
source

fn choose_version( + &self, + package: &P, + range: &VS +) -> Result<Option<VS::V>, Self::Err>

Once the resolver has found the highest Priority package from all potential valid +packages, it needs to know what vertion of that package to use. The most common pattern +is to select the largest vertion that the range contains.

+
source

fn get_dependencies( + &self, + package: &P, + version: &VS::V +) -> Result<Dependencies<P, VS>, Self::Err>

Retrieves the package dependencies. +Return Dependencies::Unknown if its dependencies are unknown.

+

Provided Methods§

source

fn should_cancel(&self) -> Result<(), Self::Err>

This is called fairly regularly during the resolution, +if it returns an Err then resolution will be terminated. +This is helpful if you want to add some form of early termination like a timeout, +or you want to add some form of user feedback if things are taking a while. +If not provided the resolver will run as long as needed.

+

Implementors§

source§

impl<P: Package, VS: VersionSet> DependencyProvider<P, VS> for OfflineDependencyProvider<P, VS>

An implementation of DependencyProvider that +contains all dependency information available in memory. +Currently packages are picked with the fewest versions contained in the constraints first. +But, that may change in new versions if better heuristics are found. +Versions are picked with the newest versions first.

+
\ No newline at end of file diff --git a/pubgrub/term/enum.Term.html b/pubgrub/term/enum.Term.html new file mode 100644 index 00000000..85192959 --- /dev/null +++ b/pubgrub/term/enum.Term.html @@ -0,0 +1,37 @@ +Term in pubgrub::term - Rust +

Enum pubgrub::term::Term

source ·
pub enum Term<VS: VersionSet> {
+    Positive(VS),
+    Negative(VS),
+}
Expand description

A positive or negative expression regarding a set of versions.

+

Variants§

§

Positive(VS)

For example, “1.0.0 <= v < 2.0.0” is a positive expression +that is evaluated true if a version is selected +and comprised between version 1.0.0 and version 2.0.0.

+
§

Negative(VS)

The term “not v < 3.0.0” is a negative expression +that is evaluated true if a version is selected >= 3.0.0 +or if no version is selected at all.

+

Trait Implementations§

source§

impl<VS: VersionSet> AsRef<Term<VS>> for Term<VS>

source§

fn as_ref(&self) -> &Self

Converts this type into a shared reference of the (usually inferred) input type.
source§

impl<VS: Clone + VersionSet> Clone for Term<VS>

source§

fn clone(&self) -> Term<VS>

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl<VS: Debug + VersionSet> Debug for Term<VS>

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<VS: VersionSet + Display> Display for Term<VS>

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<VS: PartialEq + VersionSet> PartialEq for Term<VS>

source§

fn eq(&self, other: &Term<VS>) -> bool

This method tests for self and other values to be equal, and is used +by ==.
1.0.0 · source§

fn ne(&self, other: &Rhs) -> bool

This method tests for !=. The default implementation is almost always +sufficient, and should not be overridden without very good reason.
source§

impl<VS: Eq + VersionSet> Eq for Term<VS>

source§

impl<VS: VersionSet> StructuralPartialEq for Term<VS>

Auto Trait Implementations§

§

impl<VS> RefUnwindSafe for Term<VS>
where + VS: RefUnwindSafe,

§

impl<VS> Send for Term<VS>
where + VS: Send,

§

impl<VS> Sync for Term<VS>
where + VS: Sync,

§

impl<VS> Unpin for Term<VS>
where + VS: Unpin,

§

impl<VS> UnwindSafe for Term<VS>
where + VS: UnwindSafe,

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<Q, K> Equivalent<K> for Q
where + Q: Eq + ?Sized, + K: Borrow<Q> + ?Sized,

source§

fn equivalent(&self, key: &K) -> bool

Compare self to key and return true if they are equal.
§

impl<Q, K> Equivalent<K> for Q
where + Q: Eq + ?Sized, + K: Borrow<Q> + ?Sized,

§

fn equivalent(&self, key: &K) -> bool

Checks if this value is equivalent to the given key. Read more
§

impl<Q, K> Equivalent<K> for Q
where + Q: Eq + ?Sized, + K: Borrow<Q> + ?Sized,

§

fn equivalent(&self, key: &K) -> bool

Compare self to key and return true if they are equal.
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> ToOwned for T
where + T: Clone,

§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T> ToString for T
where + T: Display + ?Sized,

source§

default fn to_string(&self) -> String

Converts the given value to a String. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

§

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

§

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.
\ No newline at end of file diff --git a/pubgrub/term/index.html b/pubgrub/term/index.html new file mode 100644 index 00000000..dccb85fc --- /dev/null +++ b/pubgrub/term/index.html @@ -0,0 +1,4 @@ +pubgrub::term - Rust +

Module pubgrub::term

source ·
Expand description

A term is the fundamental unit of operation of the PubGrub algorithm. +It is a positive or negative expression regarding a set of versions.

+

Enums§

  • A positive or negative expression regarding a set of versions.
\ No newline at end of file diff --git a/pubgrub/term/sidebar-items.js b/pubgrub/term/sidebar-items.js new file mode 100644 index 00000000..1abde7e7 --- /dev/null +++ b/pubgrub/term/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"enum":["Term"]}; \ No newline at end of file diff --git a/pubgrub/type_aliases/index.html b/pubgrub/type_aliases/index.html new file mode 100644 index 00000000..9eb4481d --- /dev/null +++ b/pubgrub/type_aliases/index.html @@ -0,0 +1,8 @@ +pubgrub::type_aliases - Rust +

Module pubgrub::type_aliases

source ·
Expand description

Publicly exported type aliases.

+

Type Aliases§

\ No newline at end of file diff --git a/pubgrub/type_aliases/sidebar-items.js b/pubgrub/type_aliases/sidebar-items.js new file mode 100644 index 00000000..87dea147 --- /dev/null +++ b/pubgrub/type_aliases/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"type":["DependencyConstraints","Map","SelectedDependencies","Set"]}; \ No newline at end of file diff --git a/pubgrub/type_aliases/type.DependencyConstraints.html b/pubgrub/type_aliases/type.DependencyConstraints.html new file mode 100644 index 00000000..d549c8fe --- /dev/null +++ b/pubgrub/type_aliases/type.DependencyConstraints.html @@ -0,0 +1,7 @@ +DependencyConstraints in pubgrub::type_aliases - Rust +
pub type DependencyConstraints<P, VS> = Map<P, VS>;
Expand description

Holds information about all possible versions a given package can accept. +There is a difference in semantics between an empty map +inside DependencyConstraints and Dependencies::Unknown: +the former means the package has no dependency and it is a known fact, +while the latter means they could not be fetched by the DependencyProvider.

+

Aliased Type§

struct DependencyConstraints<P, VS> { /* private fields */ }
\ No newline at end of file diff --git a/pubgrub/type_aliases/type.Map.html b/pubgrub/type_aliases/type.Map.html new file mode 100644 index 00000000..c2bf5d0b --- /dev/null +++ b/pubgrub/type_aliases/type.Map.html @@ -0,0 +1,3 @@ +Map in pubgrub::type_aliases - Rust +

Type Alias pubgrub::type_aliases::Map

source ·
pub type Map<K, V> = FxHashMap<K, V>;
Expand description

Map implementation used by the library.

+

Aliased Type§

struct Map<K, V> { /* private fields */ }
\ No newline at end of file diff --git a/pubgrub/type_aliases/type.SelectedDependencies.html b/pubgrub/type_aliases/type.SelectedDependencies.html new file mode 100644 index 00000000..40d82a73 --- /dev/null +++ b/pubgrub/type_aliases/type.SelectedDependencies.html @@ -0,0 +1,4 @@ +SelectedDependencies in pubgrub::type_aliases - Rust +
pub type SelectedDependencies<P, V> = Map<P, V>;
Expand description

Concrete dependencies picked by the library during resolve +from DependencyConstraints.

+

Aliased Type§

struct SelectedDependencies<P, V> { /* private fields */ }
\ No newline at end of file diff --git a/pubgrub/type_aliases/type.Set.html b/pubgrub/type_aliases/type.Set.html new file mode 100644 index 00000000..aafa15b3 --- /dev/null +++ b/pubgrub/type_aliases/type.Set.html @@ -0,0 +1,3 @@ +Set in pubgrub::type_aliases - Rust +

Type Alias pubgrub::type_aliases::Set

source ·
pub type Set<V> = FxHashSet<V>;
Expand description

Set implementation used by the library.

+

Aliased Type§

struct Set<V> { /* private fields */ }
\ No newline at end of file diff --git a/pubgrub/version/enum.VersionParseError.html b/pubgrub/version/enum.VersionParseError.html new file mode 100644 index 00000000..71e41629 --- /dev/null +++ b/pubgrub/version/enum.VersionParseError.html @@ -0,0 +1,37 @@ +VersionParseError in pubgrub::version - Rust +
pub enum VersionParseError {
+    NotThreeParts {
+        full_version: String,
+    },
+    ParseIntError {
+        full_version: String,
+        version_part: String,
+        parse_error: String,
+    },
+}
Expand description

Error creating SemanticVersion from String.

+

Variants§

§

NotThreeParts

Fields

§full_version: String

SemanticVersion that was being parsed.

+

SemanticVersion must contain major, minor, patch versions.

+
§

ParseIntError

Fields

§full_version: String

SemanticVersion that was being parsed.

+
§version_part: String

A version part where parsing failed.

+
§parse_error: String

A specific error resulted from parsing a part of the version as u32.

+

Wrapper around ParseIntError.

+

Trait Implementations§

source§

impl Debug for VersionParseError

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl Display for VersionParseError

source§

fn fmt(&self, __formatter: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl Error for VersionParseError

1.30.0 · source§

fn source(&self) -> Option<&(dyn Error + 'static)>

The lower-level source of this error, if any. Read more
1.0.0 · source§

fn description(&self) -> &str

👎Deprecated since 1.42.0: use the Display impl or to_string()
1.0.0 · source§

fn cause(&self) -> Option<&dyn Error>

👎Deprecated since 1.33.0: replaced by Error::source, which can support downcasting
source§

fn provide<'a>(&'a self, request: &mut Request<'a>)

🔬This is a nightly-only experimental API. (error_generic_member_access)
Provides type based access to context intended for error reports. Read more
source§

impl PartialEq for VersionParseError

source§

fn eq(&self, other: &VersionParseError) -> bool

This method tests for self and other values to be equal, and is used +by ==.
1.0.0 · source§

fn ne(&self, other: &Rhs) -> bool

This method tests for !=. The default implementation is almost always +sufficient, and should not be overridden without very good reason.
source§

impl Eq for VersionParseError

source§

impl StructuralPartialEq for VersionParseError

Auto Trait Implementations§

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<Q, K> Equivalent<K> for Q
where + Q: Eq + ?Sized, + K: Borrow<Q> + ?Sized,

source§

fn equivalent(&self, key: &K) -> bool

Compare self to key and return true if they are equal.
§

impl<Q, K> Equivalent<K> for Q
where + Q: Eq + ?Sized, + K: Borrow<Q> + ?Sized,

§

fn equivalent(&self, key: &K) -> bool

Checks if this value is equivalent to the given key. Read more
§

impl<Q, K> Equivalent<K> for Q
where + Q: Eq + ?Sized, + K: Borrow<Q> + ?Sized,

§

fn equivalent(&self, key: &K) -> bool

Compare self to key and return true if they are equal.
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> ToString for T
where + T: Display + ?Sized,

source§

default fn to_string(&self) -> String

Converts the given value to a String. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

§

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

§

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.
\ No newline at end of file diff --git a/pubgrub/version/index.html b/pubgrub/version/index.html new file mode 100644 index 00000000..0319bee0 --- /dev/null +++ b/pubgrub/version/index.html @@ -0,0 +1,4 @@ +pubgrub::version - Rust +

Module pubgrub::version

source ·
Expand description

Traits and implementations to create and compare versions.

+

Structs§

Enums§

Traits§

  • Versions have a minimal version (a “0” version) +and are ordered such that every version has a next one.
\ No newline at end of file diff --git a/pubgrub/version/sidebar-items.js b/pubgrub/version/sidebar-items.js new file mode 100644 index 00000000..63ab92fe --- /dev/null +++ b/pubgrub/version/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"enum":["VersionParseError"],"struct":["NumberVersion","SemanticVersion"],"trait":["Version"]}; \ No newline at end of file diff --git a/pubgrub/version/struct.NumberVersion.html b/pubgrub/version/struct.NumberVersion.html new file mode 100644 index 00000000..487338c4 --- /dev/null +++ b/pubgrub/version/struct.NumberVersion.html @@ -0,0 +1,33 @@ +NumberVersion in pubgrub::version - Rust +
pub struct NumberVersion(pub u32);
Expand description

Simplest versions possible, just a positive number.

+

Tuple Fields§

§0: u32

Trait Implementations§

source§

impl Clone for NumberVersion

source§

fn clone(&self) -> NumberVersion

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for NumberVersion

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl Display for NumberVersion

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl From<&NumberVersion> for NumberVersion

source§

fn from(v: &NumberVersion) -> Self

Converts to this type from the input type.
source§

impl From<&u32> for NumberVersion

source§

fn from(v: &u32) -> Self

Converts to this type from the input type.
source§

impl From<NumberVersion> for u32

source§

fn from(version: NumberVersion) -> Self

Converts to this type from the input type.
source§

impl From<u32> for NumberVersion

source§

fn from(v: u32) -> Self

Converts to this type from the input type.
source§

impl Hash for NumberVersion

source§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.3.0 · source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where + H: Hasher, + Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
source§

impl Ord for NumberVersion

source§

fn cmp(&self, other: &NumberVersion) -> Ordering

This method returns an Ordering between self and other. Read more
1.21.0 · source§

fn max(self, other: Self) -> Self
where + Self: Sized,

Compares and returns the maximum of two values. Read more
1.21.0 · source§

fn min(self, other: Self) -> Self
where + Self: Sized,

Compares and returns the minimum of two values. Read more
1.50.0 · source§

fn clamp(self, min: Self, max: Self) -> Self
where + Self: Sized + PartialOrd,

Restrict a value to a certain interval. Read more
source§

impl PartialEq for NumberVersion

source§

fn eq(&self, other: &NumberVersion) -> bool

This method tests for self and other values to be equal, and is used +by ==.
1.0.0 · source§

fn ne(&self, other: &Rhs) -> bool

This method tests for !=. The default implementation is almost always +sufficient, and should not be overridden without very good reason.
source§

impl PartialOrd for NumberVersion

source§

fn partial_cmp(&self, other: &NumberVersion) -> Option<Ordering>

This method returns an ordering between self and other values if one exists. Read more
1.0.0 · source§

fn lt(&self, other: &Rhs) -> bool

This method tests less than (for self and other) and is used by the < operator. Read more
1.0.0 · source§

fn le(&self, other: &Rhs) -> bool

This method tests less than or equal to (for self and other) and is used by the <= +operator. Read more
1.0.0 · source§

fn gt(&self, other: &Rhs) -> bool

This method tests greater than (for self and other) and is used by the > operator. Read more
1.0.0 · source§

fn ge(&self, other: &Rhs) -> bool

This method tests greater than or equal to (for self and other) and is used by the >= +operator. Read more
source§

impl Version for NumberVersion

source§

fn lowest() -> Self

Returns the lowest version.
source§

fn bump(&self) -> Self

Returns the next version, the smallest strictly higher version.
source§

impl Copy for NumberVersion

source§

impl Eq for NumberVersion

source§

impl StructuralPartialEq for NumberVersion

Auto Trait Implementations§

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
§

impl<Q, K> Comparable<K> for Q
where + Q: Ord + ?Sized, + K: Borrow<Q> + ?Sized,

§

fn compare(&self, key: &K) -> Ordering

Compare self to key and return their ordering.
source§

impl<Q, K> Equivalent<K> for Q
where + Q: Eq + ?Sized, + K: Borrow<Q> + ?Sized,

source§

fn equivalent(&self, key: &K) -> bool

Compare self to key and return true if they are equal.
§

impl<Q, K> Equivalent<K> for Q
where + Q: Eq + ?Sized, + K: Borrow<Q> + ?Sized,

§

fn equivalent(&self, key: &K) -> bool

Checks if this value is equivalent to the given key. Read more
§

impl<Q, K> Equivalent<K> for Q
where + Q: Eq + ?Sized, + K: Borrow<Q> + ?Sized,

§

fn equivalent(&self, key: &K) -> bool

Compare self to key and return true if they are equal.
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> ToOwned for T
where + T: Clone,

§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T> ToString for T
where + T: Display + ?Sized,

source§

default fn to_string(&self) -> String

Converts the given value to a String. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

§

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

§

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.
source§

impl<T> Package for T
where + T: Clone + Eq + Hash + Debug + Display,

\ No newline at end of file diff --git a/pubgrub/version/struct.SemanticVersion.html b/pubgrub/version/struct.SemanticVersion.html new file mode 100644 index 00000000..73aa7952 --- /dev/null +++ b/pubgrub/version/struct.SemanticVersion.html @@ -0,0 +1,41 @@ +SemanticVersion in pubgrub::version - Rust +
pub struct SemanticVersion { /* private fields */ }
Expand description

Type for semantic versions: major.minor.patch.

+

Implementations§

source§

impl SemanticVersion

source

pub fn new(major: u32, minor: u32, patch: u32) -> Self

Create a version with “major”, “minor” and “patch” values. +version = major.minor.patch

+
source

pub fn zero() -> Self

Version 0.0.0.

+
source

pub fn one() -> Self

Version 1.0.0.

+
source

pub fn two() -> Self

Version 2.0.0.

+
source§

impl SemanticVersion

source

pub fn bump_patch(self) -> Self

Bump the patch number of a version.

+
source

pub fn bump_minor(self) -> Self

Bump the minor number of a version.

+
source

pub fn bump_major(self) -> Self

Bump the major number of a version.

+

Trait Implementations§

source§

impl Clone for SemanticVersion

source§

fn clone(&self) -> SemanticVersion

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for SemanticVersion

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl Display for SemanticVersion

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl From<&(u32, u32, u32)> for SemanticVersion

source§

fn from(tuple: &(u32, u32, u32)) -> Self

Converts to this type from the input type.
source§

impl From<&SemanticVersion> for SemanticVersion

source§

fn from(v: &SemanticVersion) -> Self

Converts to this type from the input type.
source§

impl From<(u32, u32, u32)> for SemanticVersion

source§

fn from(tuple: (u32, u32, u32)) -> Self

Converts to this type from the input type.
source§

impl From<SemanticVersion> for (u32, u32, u32)

source§

fn from(v: SemanticVersion) -> Self

Converts to this type from the input type.
source§

impl FromStr for SemanticVersion

§

type Err = VersionParseError

The associated error which can be returned from parsing.
source§

fn from_str(s: &str) -> Result<Self, Self::Err>

Parses a string s to return a value of this type. Read more
source§

impl Hash for SemanticVersion

source§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.3.0 · source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where + H: Hasher, + Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
source§

impl Ord for SemanticVersion

source§

fn cmp(&self, other: &SemanticVersion) -> Ordering

This method returns an Ordering between self and other. Read more
1.21.0 · source§

fn max(self, other: Self) -> Self
where + Self: Sized,

Compares and returns the maximum of two values. Read more
1.21.0 · source§

fn min(self, other: Self) -> Self
where + Self: Sized,

Compares and returns the minimum of two values. Read more
1.50.0 · source§

fn clamp(self, min: Self, max: Self) -> Self
where + Self: Sized + PartialOrd,

Restrict a value to a certain interval. Read more
source§

impl PartialEq for SemanticVersion

source§

fn eq(&self, other: &SemanticVersion) -> bool

This method tests for self and other values to be equal, and is used +by ==.
1.0.0 · source§

fn ne(&self, other: &Rhs) -> bool

This method tests for !=. The default implementation is almost always +sufficient, and should not be overridden without very good reason.
source§

impl PartialOrd for SemanticVersion

source§

fn partial_cmp(&self, other: &SemanticVersion) -> Option<Ordering>

This method returns an ordering between self and other values if one exists. Read more
1.0.0 · source§

fn lt(&self, other: &Rhs) -> bool

This method tests less than (for self and other) and is used by the < operator. Read more
1.0.0 · source§

fn le(&self, other: &Rhs) -> bool

This method tests less than or equal to (for self and other) and is used by the <= +operator. Read more
1.0.0 · source§

fn gt(&self, other: &Rhs) -> bool

This method tests greater than (for self and other) and is used by the > operator. Read more
1.0.0 · source§

fn ge(&self, other: &Rhs) -> bool

This method tests greater than or equal to (for self and other) and is used by the >= +operator. Read more
source§

impl Version for SemanticVersion

source§

fn lowest() -> Self

Returns the lowest version.
source§

fn bump(&self) -> Self

Returns the next version, the smallest strictly higher version.
source§

impl Copy for SemanticVersion

source§

impl Eq for SemanticVersion

source§

impl StructuralPartialEq for SemanticVersion

Auto Trait Implementations§

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
§

impl<Q, K> Comparable<K> for Q
where + Q: Ord + ?Sized, + K: Borrow<Q> + ?Sized,

§

fn compare(&self, key: &K) -> Ordering

Compare self to key and return their ordering.
source§

impl<Q, K> Equivalent<K> for Q
where + Q: Eq + ?Sized, + K: Borrow<Q> + ?Sized,

source§

fn equivalent(&self, key: &K) -> bool

Compare self to key and return true if they are equal.
§

impl<Q, K> Equivalent<K> for Q
where + Q: Eq + ?Sized, + K: Borrow<Q> + ?Sized,

§

fn equivalent(&self, key: &K) -> bool

Checks if this value is equivalent to the given key. Read more
§

impl<Q, K> Equivalent<K> for Q
where + Q: Eq + ?Sized, + K: Borrow<Q> + ?Sized,

§

fn equivalent(&self, key: &K) -> bool

Compare self to key and return true if they are equal.
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> ToOwned for T
where + T: Clone,

§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T> ToString for T
where + T: Display + ?Sized,

source§

default fn to_string(&self) -> String

Converts the given value to a String. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

§

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

§

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.
source§

impl<T> Package for T
where + T: Clone + Eq + Hash + Debug + Display,

\ No newline at end of file diff --git a/pubgrub/version/trait.Version.html b/pubgrub/version/trait.Version.html new file mode 100644 index 00000000..ccf93bd2 --- /dev/null +++ b/pubgrub/version/trait.Version.html @@ -0,0 +1,10 @@ +Version in pubgrub::version - Rust +

Trait pubgrub::version::Version

source ·
pub trait Version: Clone + Ord + Debug + Display {
+    // Required methods
+    fn lowest() -> Self;
+    fn bump(&self) -> Self;
+}
Expand description

Versions have a minimal version (a “0” version) +and are ordered such that every version has a next one.

+

Required Methods§

source

fn lowest() -> Self

Returns the lowest version.

+
source

fn bump(&self) -> Self

Returns the next version, the smallest strictly higher version.

+

Object Safety§

This trait is not object safe.

Implementors§

\ No newline at end of file diff --git a/pubgrub/version_set/index.html b/pubgrub/version_set/index.html new file mode 100644 index 00000000..f4a0d1d1 --- /dev/null +++ b/pubgrub/version_set/index.html @@ -0,0 +1,18 @@ +pubgrub::version_set - Rust +

Module pubgrub::version_set

source ·
Expand description

As its name suggests, the VersionSet trait describes sets of versions.

+

One needs to define

+
    +
  • the associate type for versions,
  • +
  • two constructors for the empty set and a singleton set,
  • +
  • the complement and intersection set operations,
  • +
  • and a function to evaluate membership of versions.
  • +
+

Two functions are automatically derived, thanks to the mathematical properties of sets. +You can overwrite those implementations, but we highly recommend that you don’t, +except if you are confident in a correct implementation that brings much performance gains.

+

It is also extremely important that the Eq trait is correctly implemented. +In particular, you can only use #[derive(Eq, PartialEq)] if Eq is strictly equivalent to the +structural equality, i.e. if version sets have canonical representations. +Such problems may arise if your implementations of complement() and intersection() do not +return canonical representations so be careful there.

+

Traits§

\ No newline at end of file diff --git a/pubgrub/version_set/sidebar-items.js b/pubgrub/version_set/sidebar-items.js new file mode 100644 index 00000000..4006fcb4 --- /dev/null +++ b/pubgrub/version_set/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"trait":["VersionSet"]}; \ No newline at end of file diff --git a/pubgrub/version_set/trait.VersionSet.html b/pubgrub/version_set/trait.VersionSet.html new file mode 100644 index 00000000..d0d54c1a --- /dev/null +++ b/pubgrub/version_set/trait.VersionSet.html @@ -0,0 +1,27 @@ +VersionSet in pubgrub::version_set - Rust +
pub trait VersionSet: Debug + Display + Clone + Eq {
+    type V: Debug + Display + Clone + Ord;
+
+    // Required methods
+    fn empty() -> Self;
+    fn singleton(v: Self::V) -> Self;
+    fn complement(&self) -> Self;
+    fn intersection(&self, other: &Self) -> Self;
+    fn contains(&self, v: &Self::V) -> bool;
+
+    // Provided methods
+    fn full() -> Self { ... }
+    fn union(&self, other: &Self) -> Self { ... }
+}
Expand description

Trait describing sets of versions.

+

Required Associated Types§

source

type V: Debug + Display + Clone + Ord

Version type associated with the sets manipulated.

+

Required Methods§

source

fn empty() -> Self

Constructor for an empty set containing no version.

+
source

fn singleton(v: Self::V) -> Self

Constructor for a set containing exactly one version.

+
source

fn complement(&self) -> Self

Compute the complement of this set.

+
source

fn intersection(&self, other: &Self) -> Self

Compute the intersection with another set.

+
source

fn contains(&self, v: &Self::V) -> bool

Evaluate membership of a version in this set.

+

Provided Methods§

source

fn full() -> Self

Constructor for the set containing all versions. +Automatically implemented as Self::empty().complement().

+
source

fn union(&self, other: &Self) -> Self

Compute the union with another set. +Thanks to set properties, this is automatically implemented as: +self.complement().intersection(&other.complement()).complement()

+

Object Safety§

This trait is not object safe.

Implementors§

source§

impl<T: Debug + Display + Clone + Eq + Ord> VersionSet for Range<T>

§

type V = T

\ No newline at end of file diff --git a/search-index.js b/search-index.js new file mode 100644 index 00000000..a6e9eafa --- /dev/null +++ b/search-index.js @@ -0,0 +1,5 @@ +var searchIndex = new Map(JSON.parse('[\ +["pubgrub",{"doc":"PubGrub version solving algorithm.","t":"CCCCCCCCCPPPPPGPNNNNNNNNNNNOOOOOKFNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNFFGFPGPPPPRRKKPNNNNNNNNNNOONNNNNNNNNNNNNMNMNNNNNNNNNNNMNMNOONNNNNNNNNNNNNNNNNNNGKRPFRPNNNNNMNNNNNNNNNMNNNNNMNHNNNNNNNNNNPPGNNNNNNNNNNNNNNNNNNNIIIIPFPFKGNNNNNNMNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNMNNNNNNNNNNNNNNNNNNNNNNOOOORKMMMNMMN","n":["error","package","range","report","solver","term","type_aliases","version","version_set","ErrorChoosingPackageVersion","ErrorInShouldCancel","ErrorRetrievingDependencies","Failure","NoSolution","PubGrubError","SelfDependency","borrow","borrow_mut","fmt","fmt","from","into","source","to_string","try_from","try_into","type_id","package","package","source","version","version","Package","Range","between","borrow","borrow_mut","bounding_range","clone","clone_into","complement","complement","contains","contains","contains_many","empty","empty","eq","equivalent","equivalent","equivalent","equivalent","fmt","fmt","from","from_range_bounds","full","full","hash","higher_than","intersection","intersection","into","lower_than","simplify","singleton","singleton","strictly_higher_than","strictly_lower_than","to_owned","to_string","try_from","try_into","type_id","union","union","DefaultStringReportFormatter","DefaultStringReporter","DerivationTree","Derived","Derived","External","External","FromDependencyOf","NoVersions","NotRoot","Output","Output","ReportFormatter","Reporter","UnavailableDependencies","borrow","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","cause1","cause2","clone","clone","clone","clone_into","clone_into","clone_into","collapse_no_versions","default","fmt","fmt","fmt","fmt","fmt","format_external","format_external","format_terms","format_terms","from","from","from","from","from","into","into","into","into","into","report","report","report_with_formatter","report_with_formatter","shared_id","terms","to_owned","to_owned","to_owned","to_string","try_from","try_from","try_from","try_from","try_from","try_into","try_into","try_into","try_into","try_into","type_id","type_id","type_id","type_id","type_id","Dependencies","DependencyProvider","Err","Known","OfflineDependencyProvider","Priority","Unknown","add_dependencies","borrow","borrow","borrow_mut","borrow_mut","choose_version","choose_version","clone","clone","clone_into","clone_into","default","fmt","from","from","get_dependencies","get_dependencies","into","into","new","packages","prioritize","prioritize","resolve","should_cancel","to_owned","to_owned","try_from","try_from","try_into","try_into","type_id","type_id","versions","Negative","Positive","Term","as_ref","borrow","borrow_mut","clone","clone_into","eq","equivalent","equivalent","equivalent","equivalent","fmt","fmt","from","into","to_owned","to_string","try_from","try_into","type_id","DependencyConstraints","Map","SelectedDependencies","Set","NotThreeParts","NumberVersion","ParseIntError","SemanticVersion","Version","VersionParseError","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","bump","bump","bump","bump_major","bump_minor","bump_patch","clone","clone","clone_into","clone_into","cmp","cmp","compare","compare","eq","eq","eq","equivalent","equivalent","equivalent","equivalent","equivalent","equivalent","equivalent","equivalent","equivalent","equivalent","equivalent","equivalent","fmt","fmt","fmt","fmt","fmt","fmt","from","from","from","from","from","from","from","from","from","from_str","hash","hash","into","into","into","lowest","lowest","lowest","new","one","partial_cmp","partial_cmp","to_owned","to_owned","to_string","to_string","to_string","try_from","try_from","try_from","try_into","try_into","try_into","two","type_id","type_id","type_id","zero","full_version","full_version","parse_error","version_part","V","VersionSet","complement","contains","empty","full","intersection","singleton","union"],"q":[[0,"pubgrub"],[9,"pubgrub::error"],[27,"pubgrub::error::PubGrubError"],[32,"pubgrub::package"],[33,"pubgrub::range"],[76,"pubgrub::report"],[155,"pubgrub::solver"],[196,"pubgrub::term"],[218,"pubgrub::type_aliases"],[222,"pubgrub::version"],[307,"pubgrub::version::VersionParseError"],[311,"pubgrub::version_set"],[320,"core::fmt"],[321,"core::fmt"],[322,"core::fmt"],[323,"alloc::string"],[324,"core::result"],[325,"core::any"],[326,"core::convert"],[327,"core::ops::range"],[328,"core::cmp"],[329,"core::clone"],[330,"core::cmp"],[331,"core::cmp"],[332,"core::hash"],[333,"core::convert"],[334,"core::cmp"]],"d":["Handling pubgrub errors.","Trait for identifying packages. Automatically implemented …","Ranges are constraints defining sets of versions.","Build a report as clear as possible as to why dependency …","PubGrub version solving algorithm.","A term is the fundamental unit of operation of the PubGrub …","Publicly exported type aliases.","Traits and implementations to create and compare versions.","As its name suggests, the VersionSet trait describes sets …","Error arising when the implementer of DependencyProvider …","Error arising when the implementer of DependencyProvider …","Error arising when the implementer of DependencyProvider …","Something unexpected happened.","There is no solution for this set of dependencies.","Errors that may occur while solving dependencies.","Error arising when the implementer of DependencyProvider …","","","","","Returns the argument unchanged.","Calls U::from(self).","","","","","","Package whose dependencies we want.","Package whose dependencies we want.","Error raised by the implementer of DependencyProvider.","Version of the package for which we want the dependencies.","Version of the package for which we want the dependencies.","Trait for identifying packages. Automatically implemented …","A Range represents multiple intervals of a continuous …","Set of versions greater or equal to v1 but less than v2.","","","Convert to something that can be used with BTreeMap::range.","","","","Returns the complement of this Range.","Returns true if the this Range contains the specified …","","Returns true if the this Range contains the specified …","Empty set of versions.","","","","","","","","","Returns the argument unchanged.","Construct a simple range from anything that impls …","","Set of all possible versions","","Set of all versions higher or equal to some version","","Computes the intersection of two sets of versions.","Calls U::from(self).","Set of all versions lower or equal to some version","Returns a simpler Range that contains the same versions","Set containing exactly one version","","Set of all versions higher to some version","Set of all versions lower to some version","","","","","","Computes the union of this Range and another.","","Default formatter for the default reporter.","Default reporter able to generate an explanation as a …","Derivation tree resulting in the impossibility to solve …","Incompatibility derived from two others.","Incompatibility derived from two others.","Incompatibilities that are not derived from others, they …","External incompatibility.","Incompatibility coming from the dependencies of a given …","There are no versions in the given set for this package.","Initial incompatibility aiming at picking the root package …","Output type of the report.","Output type of the report.","Trait for formatting outputs in the reporter.","Reporter trait.","Dependencies of the package are unavailable for versions …","","","","","","","","","","","First cause.","Second cause.","","","","","","","Merge the NoVersions external incompatibilities with the …","","","","","","","Format an External incompatibility.","","Format terms of an incompatibility.","","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Generate a report from the derivation tree describing the …","","Generate a report from the derivation tree describing the …","","Indicate if that incompatibility is present multiple times …","Terms of the incompatibility.","","","","","","","","","","","","","","","","","","","","An enum used by DependencyProvider that holds information …","Trait that allows the algorithm to retrieve available …","The kind of error returned from these methods.","Container for all available package versions.","A basic implementation of DependencyProvider.","The type returned from prioritize. The resolver does not …","Package dependencies are unavailable.","Registers the dependencies of a package and version pair. …","","","","","Once the resolver has found the highest Priority package …","","","","","","","","Returns the argument unchanged.","Returns the argument unchanged.","Retrieves the package dependencies. Return …","","Calls U::from(self).","Calls U::from(self).","Creates an empty OfflineDependencyProvider with no …","Lists packages that have been saved.","Decision making is the process of choosing the next package","","Main function of the library. Finds a set of packages …","This is called fairly regularly during the resolution, if …","","","","","","","","","Lists versions of saved packages in sorted order. Returns …","The term “not v < 3.0.0” is a negative expression that …","For example, “1.0.0 <= v < 2.0.0” is a positive …","A positive or negative expression regarding a set of …","","","","","","","","","","","","","Returns the argument unchanged.","Calls U::from(self).","","","","","","Holds information about all possible versions a given …","Map implementation used by the library.","Concrete dependencies picked by the library during resolve …","Set implementation used by the library.","SemanticVersion must contain major, minor, patch versions.","Simplest versions possible, just a positive number.","Wrapper around ParseIntError.","Type for semantic versions: major.minor.patch.","Versions have a minimal version (a “0” version) and …","Error creating SemanticVersion from String.","","","","","","","Returns the next version, the smallest strictly higher …","","","Bump the major number of a version.","Bump the minor number of a version.","Bump the patch number of a version.","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Returns the argument unchanged.","","Returns the argument unchanged.","","Returns the argument unchanged.","","","","","","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Returns the lowest version.","","","Create a version with “major”, “minor” and “patch…","Version 1.0.0.","","","","","","","","","","","","","","Version 2.0.0.","","","","Version 0.0.0.","SemanticVersion that was being parsed.","SemanticVersion that was being parsed.","A specific error resulted from parsing a part of the …","A version part where parsing failed.","Version type associated with the sets manipulated.","Trait describing sets of versions.","Compute the complement of this set.","Evaluate membership of a version in this set.","Constructor for an empty set containing no version.","Constructor for the set containing all versions. …","Compute the intersection with another set.","Constructor for a set containing exactly one version.","Compute the union with another set. Thanks to set …"],"i":[0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,53,54,53,53,54,0,0,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,0,0,0,0,28,0,28,29,29,29,55,33,0,0,29,56,28,29,30,31,56,28,29,30,31,30,30,28,29,30,28,29,30,28,31,28,29,29,30,31,33,31,33,31,56,28,29,30,31,56,28,29,30,31,55,56,55,56,30,30,28,29,30,29,56,28,29,30,31,56,28,29,30,31,56,28,29,30,31,0,0,40,42,0,40,42,36,42,36,42,36,40,36,42,36,42,36,36,36,42,36,40,36,42,36,36,36,40,36,0,40,42,36,42,36,42,36,42,36,36,34,34,0,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,0,0,0,0,49,0,49,0,0,0,46,49,47,46,49,47,45,46,47,46,46,46,46,47,46,47,46,47,46,47,46,49,47,46,46,46,46,49,49,49,49,47,47,47,47,46,46,49,49,47,47,46,46,46,46,49,47,47,47,47,46,46,47,46,49,47,45,46,47,46,46,46,47,46,47,46,49,47,46,49,47,46,49,47,46,46,49,47,46,57,58,58,58,6,0,6,6,6,6,6,6,6],"f":"````````````````{ce{}{}}0{{{b{ceg}}d}f{hj}ln}{{{b{ceg}}d}f{A`j}{A`l}{A`n}}{cc{}}3{{{b{ceg}}}{{Ab{n}}}jln}{cAd{}}{c{{Af{e}}}{}{}}0{cAh{}}```````{{eg}{{Aj{c}}}{}{{Al{c}}}{{Al{c}}}}88{{{Aj{c}}}{{Ab{{B`{{An{c}}{An{c}}}}}}}Bb}{{{Aj{c}}}{{Aj{c}}}Bd}{{ce}Bf{}{}}{{{Aj{c}}}{{Aj{c}}}{A`hBdBhBb}}2{{{Aj{c}}c}BjBb}{{{Aj{c}}e}Bj{A`hBdBhBb}{}}{{{Aj{c}}e}{{`{{Bn{}{{Bl{Bj}}}}}}}Bb{{Bn{}{{Bl{c}}}}}}{{}{{Aj{c}}}{}}{{}{{Aj{c}}}{A`hBdBhBb}}{{{Aj{c}}{Aj{c}}}BjC`}{{ce}Bj{}{}}000{{{Aj{c}}d}fA`}{{{Aj{c}}d}f{hBh}}{cc{}}{g{{Aj{c}}}Bb{Bd{Al{c}}}{{Cb{e}}}}67{{{Aj{c}}e}BfCdCf}{e{{Aj{c}}}{}{{Al{c}}}}{{{Aj{c}}{Aj{c}}}{{Aj{c}}}{A`hBdBhBb}}{{{Aj{c}}{Aj{c}}}{{Aj{c}}}{BbBd}}{ce{}{}}3{{{Aj{c}}e}{{Aj{c}}}{BbBd}{{Bn{}{{Bl{c}}}}}}{e{{Aj{c}}}Bd{{Al{c}}}}{c{{Aj{e}}}{}{A`hBdBhBb}}663{cAd{}}{c{{Af{e}}}{}{}}0{cAh{}}78```````````````6666666666``{{{Ch{ce}}}{{Ch{ce}}}{Bdj}{Bdl}}{{{Cj{ce}}}{{Cj{ce}}}{Bdj}{Bdl}}{{{Cl{ce}}}{{Cl{ce}}}{Bdj}{Bdl}}{{ce}Bf{}{}}00{{{Ch{ce}}}Bfjl}{{}Cn}{{{Ch{ce}}d}f{A`j}{A`l}}{{{Cj{ce}}d}fjl}{{{Cj{ce}}d}f{A`j}{A`l}}{{{Cl{ce}}d}f{A`j}{A`l}}{{Cnd}f}{{{Db{}{{D`{c}}}}{Cj{eg}}}c{}jl}{{Cn{Cj{ce}}}Adjl}{{{Db{}{{D`{c}}}}{Df{e{Dd{g}}}}}c{}jl}{{Cn{Df{c{Dd{e}}}}}gjl{}}{cc{}}0000{ce{}{}}0000{{{Ch{ce}}}gjl{}}0{{{Ch{ce}}i}gjl{}{{Db{ce}{{D`{g}}}}}}0``222{cAd{}}{c{{Af{e}}}{}{}}000000000{cAh{}}0000```````{{{Dh{ce}}cgi}BfjlAl{{Dj{}{{Bl{{B`{ce}}}}}}}}6666{{{E`{}{{Dl{c}}{Dn{e}}}}gi}{{Af{Abe}}}{BbBd}njl}{{{Dh{ce}}ce}{{Af{AbEb}}}jl}{{{Ed{ce}}}{{Ed{ce}}}{Bdj}{Bdl}}{{{Dh{ce}}}{{Dh{ce}}}{Bdj}{Bdl}}{{ce}Bf{}{}}0{{}{{Dh{ce}}}{Efj}{Efl}}{{{Dh{ce}}d}f{A`j}{A`l}}>>{{{E`{}{{Dl{c}}{Dn{e}}}}g}{{Af{{Ed{gi}}e}}}{BbBd}njl}{{{Dh{ce}}c}{{Af{{Ed{ce}}Eb}}}jl}??{{}{{Dh{ce}}}jl}{{{Dh{ce}}}{{`{{Bn{}{{Bl{c}}}}}}}jl}{{{E`{}{{Dl{c}}{Dn{e}}}}gi}c{BbBd}njl}{{{Dh{ce}}ce}gjl{}}{{gci}{{Af{{Eh{c}}{b{ce}}}}}jl{{E`{ce}}}Al}{{{E`{}{{Dl{c}}{Dn{e}}}}}{{Af{Bfe}}}{BbBd}n}{ce{}{}}0{c{{Af{e}}}{}{}}000{cAh{}}0{{{Dh{ce}}c}{{Ab{{`{{Bn{}{{Bl{}}}}}}}}}jl}```{{{Dd{c}}}{{Dd{c}}}l}44{{{Dd{c}}}{{Dd{c}}}{Bdl}}{{ce}Bf{}{}}{{{Dd{c}}{Dd{c}}}Bj{C`l}}{{ce}Bj{}{}}000{{{Dd{c}}d}f{lh}}{{{Dd{c}}d}f{A`l}}{cc{}};;{cAd{}};;:``````````<<<<<<{EjEj}{ElEl}{EnEn}1111099{{ElEl}F`}{{EnEn}F`}{{ce}F`{}{}}0{{ElEl}Bj}{{FbFb}Bj}{{EnEn}Bj}============{{Eld}f}0{{Fbd}f}0{{End}f}0{{{B`{FdFdFd}}}El}0>;>:>{FdEn}0{Ff{{Af{Elc}}}{}}{{Elc}BfCf}{{Enc}BfCf}{ce{}{}}00{{}Ej}{{}El}{{}En}{{FdFdFd}El}2{{ElEl}{{Ab{F`}}}}{{EnEn}{{Ab{F`}}}}66{cAd{}}00{c{{Af{e}}}{}{}}000006{cAh{}}007``````{{{l{}{{Fh{c}}}}}{{l{}{{Fh{c}}}}}{A`hBdBb}}{{{l{}{{Fh{c}}}}c}Bj{A`hBdBb}}{{}{{l{}{{Fh{c}}}}}{A`hBdBb}}0{{{l{}{{Fh{c}}}}{l{}{{Fh{c}}}}}{{l{}{{Fh{c}}}}}{A`hBdBb}}{c{{l{}{{Fh{c}}}}}{A`hBdBb}}1","c":[],"p":[[6,"PubGrubError",9],[5,"Formatter",320],[8,"Result",320],[10,"Display",320],[10,"Package",32],[10,"VersionSet",311],[10,"Error",321],[10,"Debug",320],[6,"Option",322],[5,"String",323],[6,"Result",324],[5,"TypeId",325],[5,"Range",33],[10,"Into",326],[6,"Bound",327],[1,"tuple"],[10,"Ord",328],[10,"Clone",329],[1,"unit"],[10,"Eq",328],[1,"bool"],[17,"Item"],[10,"Iterator",330],[10,"PartialEq",328],[10,"RangeBounds",327],[10,"Hash",331],[10,"Hasher",331],[6,"DerivationTree",76],[6,"External",76],[5,"Derived",76],[5,"DefaultStringReportFormatter",76],[17,"Output"],[10,"ReportFormatter",76],[6,"Term",196],[8,"Map",218],[5,"OfflineDependencyProvider",155],[10,"IntoIterator",332],[17,"Priority"],[17,"Err"],[10,"DependencyProvider",155],[6,"Infallible",326],[6,"Dependencies",155],[10,"Default",333],[8,"SelectedDependencies",218],[10,"Version",222],[5,"SemanticVersion",222],[5,"NumberVersion",222],[6,"Ordering",328],[6,"VersionParseError",222],[1,"u32"],[1,"str"],[17,"V"],[15,"ErrorRetrievingDependencies",27],[15,"SelfDependency",27],[10,"Reporter",76],[5,"DefaultStringReporter",76],[15,"NotThreeParts",307],[15,"ParseIntError",307]],"b":[[18,"impl-Display-for-PubGrubError%3CP,+VS,+E%3E"],[19,"impl-Debug-for-PubGrubError%3CP,+VS,+E%3E"],[40,"impl-VersionSet-for-Range%3CT%3E"],[41,"impl-Range%3CV%3E"],[42,"impl-Range%3CV%3E"],[43,"impl-VersionSet-for-Range%3CT%3E"],[45,"impl-Range%3CV%3E"],[46,"impl-VersionSet-for-Range%3CT%3E"],[52,"impl-Debug-for-Range%3CV%3E"],[53,"impl-Display-for-Range%3CV%3E"],[56,"impl-VersionSet-for-Range%3CT%3E"],[57,"impl-Range%3CV%3E"],[60,"impl-VersionSet-for-Range%3CT%3E"],[61,"impl-Range%3CV%3E"],[65,"impl-Range%3CV%3E"],[66,"impl-VersionSet-for-Range%3CT%3E"],[74,"impl-Range%3CV%3E"],[75,"impl-VersionSet-for-Range%3CT%3E"],[112,"impl-Display-for-External%3CP,+VS%3E"],[113,"impl-Debug-for-External%3CP,+VS%3E"],[209,"impl-Display-for-Term%3CVS%3E"],[210,"impl-Debug-for-Term%3CVS%3E"],[263,"impl-Debug-for-SemanticVersion"],[264,"impl-Display-for-SemanticVersion"],[265,"impl-Debug-for-VersionParseError"],[266,"impl-Display-for-VersionParseError"],[267,"impl-Display-for-NumberVersion"],[268,"impl-Debug-for-NumberVersion"],[269,"impl-From%3C%26(u32,+u32,+u32)%3E-for-SemanticVersion"],[270,"impl-From%3C(u32,+u32,+u32)%3E-for-SemanticVersion"],[272,"impl-From%3C%26SemanticVersion%3E-for-SemanticVersion"],[274,"impl-From%3C%26NumberVersion%3E-for-NumberVersion"],[276,"impl-From%3Cu32%3E-for-NumberVersion"],[277,"impl-From%3C%26u32%3E-for-NumberVersion"]]}]\ +]')); +if (typeof exports !== 'undefined') exports.searchIndex = searchIndex; +else if (window.initSearch) window.initSearch(searchIndex); diff --git a/settings.html b/settings.html new file mode 100644 index 00000000..05488c48 --- /dev/null +++ b/settings.html @@ -0,0 +1,2 @@ +Settings +

Rustdoc settings

Back
\ No newline at end of file diff --git a/src-files.js b/src-files.js new file mode 100644 index 00000000..438e769c --- /dev/null +++ b/src-files.js @@ -0,0 +1,4 @@ +var srcIndex = new Map(JSON.parse('[\ +["pubgrub",["",[["internal",[],["arena.rs","core.rs","incompatibility.rs","mod.rs","partial_solution.rs","small_map.rs","small_vec.rs"]]],["error.rs","lib.rs","package.rs","range.rs","report.rs","solver.rs","term.rs","type_aliases.rs","version.rs","version_set.rs"]]]\ +]')); +createSrcSidebar(); diff --git a/src/pubgrub/error.rs.html b/src/pubgrub/error.rs.html new file mode 100644 index 00000000..ca3955b4 --- /dev/null +++ b/src/pubgrub/error.rs.html @@ -0,0 +1,125 @@ +error.rs - source +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+
// SPDX-License-Identifier: MPL-2.0
+
+//! Handling pubgrub errors.
+
+use thiserror::Error;
+
+use crate::package::Package;
+use crate::report::DerivationTree;
+use crate::version_set::VersionSet;
+
+/// Errors that may occur while solving dependencies.
+#[derive(Error, Debug)]
+pub enum PubGrubError<P: Package, VS: VersionSet, E: std::error::Error> {
+    /// There is no solution for this set of dependencies.
+    #[error("No solution")]
+    NoSolution(DerivationTree<P, VS>),
+
+    /// Error arising when the implementer of
+    /// [DependencyProvider](crate::solver::DependencyProvider)
+    /// returned an error in the method
+    /// [get_dependencies](crate::solver::DependencyProvider::get_dependencies).
+    #[error("Retrieving dependencies of {package} {version} failed")]
+    ErrorRetrievingDependencies {
+        /// Package whose dependencies we want.
+        package: P,
+        /// Version of the package for which we want the dependencies.
+        version: VS::V,
+        /// Error raised by the implementer of
+        /// [DependencyProvider](crate::solver::DependencyProvider).
+        source: E,
+    },
+
+    /// Error arising when the implementer of
+    /// [DependencyProvider](crate::solver::DependencyProvider)
+    /// returned a dependency on the requested package.
+    /// This technically means that the package directly depends on itself,
+    /// and is clearly some kind of mistake.
+    #[error("{package} {version} depends on itself")]
+    SelfDependency {
+        /// Package whose dependencies we want.
+        package: P,
+        /// Version of the package for which we want the dependencies.
+        version: VS::V,
+    },
+
+    /// Error arising when the implementer of
+    /// [DependencyProvider](crate::solver::DependencyProvider)
+    /// returned an error in the method
+    /// [choose_version](crate::solver::DependencyProvider::choose_version).
+    #[error("Decision making failed")]
+    ErrorChoosingPackageVersion(E),
+
+    /// Error arising when the implementer of [DependencyProvider](crate::solver::DependencyProvider)
+    /// returned an error in the method [should_cancel](crate::solver::DependencyProvider::should_cancel).
+    #[error("We should cancel")]
+    ErrorInShouldCancel(E),
+
+    /// Something unexpected happened.
+    #[error("{0}")]
+    Failure(String),
+}
+
\ No newline at end of file diff --git a/src/pubgrub/internal/arena.rs.html b/src/pubgrub/internal/arena.rs.html new file mode 100644 index 00000000..8e5a3cba --- /dev/null +++ b/src/pubgrub/internal/arena.rs.html @@ -0,0 +1,247 @@ +arena.rs - source +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+
use std::{
+    fmt,
+    hash::{Hash, Hasher},
+    marker::PhantomData,
+    ops::{Index, Range},
+};
+
+/// The index of a value allocated in an arena that holds `T`s.
+///
+/// The Clone, Copy and other traits are defined manually because
+/// deriving them adds some additional constraints on the `T` generic type
+/// that we actually don't need since it is phantom.
+///
+/// <https://github.com/rust-lang/rust/issues/26925>
+pub struct Id<T> {
+    raw: u32,
+    _ty: PhantomData<fn() -> T>,
+}
+
+impl<T> Clone for Id<T> {
+    fn clone(&self) -> Self {
+        *self
+    }
+}
+
+impl<T> Copy for Id<T> {}
+
+impl<T> PartialEq for Id<T> {
+    fn eq(&self, other: &Id<T>) -> bool {
+        self.raw == other.raw
+    }
+}
+
+impl<T> Eq for Id<T> {}
+
+impl<T> Hash for Id<T> {
+    fn hash<H: Hasher>(&self, state: &mut H) {
+        self.raw.hash(state)
+    }
+}
+
+impl<T> fmt::Debug for Id<T> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        let mut type_name = std::any::type_name::<T>();
+        if let Some(id) = type_name.rfind(':') {
+            type_name = &type_name[id + 1..]
+        }
+        write!(f, "Id::<{}>({})", type_name, self.raw)
+    }
+}
+
+impl<T> Id<T> {
+    pub fn into_raw(self) -> usize {
+        self.raw as usize
+    }
+    fn from(n: u32) -> Self {
+        Self {
+            raw: n,
+            _ty: PhantomData,
+        }
+    }
+    pub fn range_to_iter(range: Range<Self>) -> impl Iterator<Item = Self> {
+        let start = range.start.raw;
+        let end = range.end.raw;
+        (start..end).map(Self::from)
+    }
+}
+
+/// Yet another index-based arena.
+///
+/// An arena is a kind of simple grow-only allocator, backed by a `Vec`
+/// where all items have the same lifetime, making it easier
+/// to have references between those items.
+/// They are all dropped at once when the arena is dropped.
+#[derive(Clone, PartialEq, Eq)]
+pub struct Arena<T> {
+    data: Vec<T>,
+}
+
+impl<T: fmt::Debug> fmt::Debug for Arena<T> {
+    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+        fmt.debug_struct("Arena")
+            .field("len", &self.data.len())
+            .field("data", &self.data)
+            .finish()
+    }
+}
+
+impl<T> Arena<T> {
+    pub fn new() -> Arena<T> {
+        Arena { data: Vec::new() }
+    }
+
+    pub fn alloc(&mut self, value: T) -> Id<T> {
+        let raw = self.data.len();
+        self.data.push(value);
+        Id::from(raw as u32)
+    }
+
+    pub fn alloc_iter<I: Iterator<Item = T>>(&mut self, values: I) -> Range<Id<T>> {
+        let start = Id::from(self.data.len() as u32);
+        values.for_each(|v| {
+            self.alloc(v);
+        });
+        let end = Id::from(self.data.len() as u32);
+        Range { start, end }
+    }
+}
+
+impl<T> Index<Id<T>> for Arena<T> {
+    type Output = T;
+    fn index(&self, id: Id<T>) -> &T {
+        &self.data[id.raw as usize]
+    }
+}
+
+impl<T> Index<Range<Id<T>>> for Arena<T> {
+    type Output = [T];
+    fn index(&self, id: Range<Id<T>>) -> &[T] {
+        &self.data[(id.start.raw as usize)..(id.end.raw as usize)]
+    }
+}
+
\ No newline at end of file diff --git a/src/pubgrub/internal/core.rs.html b/src/pubgrub/internal/core.rs.html new file mode 100644 index 00000000..81cb72a9 --- /dev/null +++ b/src/pubgrub/internal/core.rs.html @@ -0,0 +1,651 @@ +core.rs - source +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+
// SPDX-License-Identifier: MPL-2.0
+
+//! Core model and functions
+//! to write a functional PubGrub algorithm.
+
+use std::error::Error;
+use std::sync::Arc;
+
+use crate::error::PubGrubError;
+use crate::internal::arena::Arena;
+use crate::internal::incompatibility::{IncompId, Incompatibility, Relation};
+use crate::internal::partial_solution::SatisfierSearch::{
+    DifferentDecisionLevels, SameDecisionLevels,
+};
+use crate::internal::partial_solution::{DecisionLevel, PartialSolution};
+use crate::internal::small_vec::SmallVec;
+use crate::package::Package;
+use crate::report::DerivationTree;
+use crate::type_aliases::{DependencyConstraints, Map, Set};
+use crate::version_set::VersionSet;
+
+/// Current state of the PubGrub algorithm.
+#[derive(Clone)]
+pub struct State<P: Package, VS: VersionSet, Priority: Ord + Clone> {
+    root_package: P,
+    root_version: VS::V,
+
+    incompatibilities: Map<P, Vec<IncompId<P, VS>>>,
+
+    /// Store the ids of incompatibilities that are already contradicted.
+    /// For each one keep track of the decision level when it was found to be contradicted.
+    /// These will stay contradicted until we have backtracked beyond its associated decision level.
+    contradicted_incompatibilities: Map<IncompId<P, VS>, DecisionLevel>,
+
+    /// All incompatibilities expressing dependencies,
+    /// with common dependents merged.
+    merged_dependencies: Map<(P, P), SmallVec<IncompId<P, VS>>>,
+
+    /// Partial solution.
+    /// TODO: remove pub.
+    pub partial_solution: PartialSolution<P, VS, Priority>,
+
+    /// The store is the reference storage for all incompatibilities.
+    pub incompatibility_store: Arena<Incompatibility<P, VS>>,
+
+    /// This is a stack of work to be done in `unit_propagation`.
+    /// It can definitely be a local variable to that method, but
+    /// this way we can reuse the same allocation for better performance.
+    unit_propagation_buffer: SmallVec<P>,
+}
+
+impl<P: Package, VS: VersionSet, Priority: Ord + Clone> State<P, VS, Priority> {
+    /// Initialization of PubGrub state.
+    pub fn init(root_package: P, root_version: VS::V) -> Self {
+        let mut incompatibility_store = Arena::new();
+        let not_root_id = incompatibility_store.alloc(Incompatibility::not_root(
+            root_package.clone(),
+            root_version.clone(),
+        ));
+        let mut incompatibilities = Map::default();
+        incompatibilities.insert(root_package.clone(), vec![not_root_id]);
+        Self {
+            root_package,
+            root_version,
+            incompatibilities,
+            contradicted_incompatibilities: Map::default(),
+            partial_solution: PartialSolution::empty(),
+            incompatibility_store,
+            unit_propagation_buffer: SmallVec::Empty,
+            merged_dependencies: Map::default(),
+        }
+    }
+
+    /// Add an incompatibility to the state.
+    pub fn add_incompatibility(&mut self, incompat: Incompatibility<P, VS>) {
+        let id = self.incompatibility_store.alloc(incompat);
+        self.merge_incompatibility(id);
+    }
+
+    /// Add an incompatibility to the state.
+    pub fn add_incompatibility_from_dependencies(
+        &mut self,
+        package: P,
+        version: VS::V,
+        deps: &DependencyConstraints<P, VS>,
+    ) -> std::ops::Range<IncompId<P, VS>> {
+        // Create incompatibilities and allocate them in the store.
+        let new_incompats_id_range =
+            self.incompatibility_store
+                .alloc_iter(deps.iter().map(|dep| {
+                    Incompatibility::from_dependency(
+                        package.clone(),
+                        VS::singleton(version.clone()),
+                        dep,
+                    )
+                }));
+        // Merge the newly created incompatibilities with the older ones.
+        for id in IncompId::range_to_iter(new_incompats_id_range.clone()) {
+            self.merge_incompatibility(id);
+        }
+        new_incompats_id_range
+    }
+
+    /// Unit propagation is the core mechanism of the solving algorithm.
+    /// CF <https://github.com/dart-lang/pub/blob/master/doc/solver.md#unit-propagation>
+    pub fn unit_propagation<E: Error>(&mut self, package: P) -> Result<(), PubGrubError<P, VS, E>> {
+        self.unit_propagation_buffer.clear();
+        self.unit_propagation_buffer.push(package);
+        while let Some(current_package) = self.unit_propagation_buffer.pop() {
+            // Iterate over incompatibilities in reverse order
+            // to evaluate first the newest incompatibilities.
+            let mut conflict_id = None;
+            // We only care about incompatibilities if it contains the current package.
+            for &incompat_id in self.incompatibilities[&current_package].iter().rev() {
+                if self
+                    .contradicted_incompatibilities
+                    .contains_key(&incompat_id)
+                {
+                    continue;
+                }
+                let current_incompat = &self.incompatibility_store[incompat_id];
+                match self.partial_solution.relation(current_incompat) {
+                    // If the partial solution satisfies the incompatibility
+                    // we must perform conflict resolution.
+                    Relation::Satisfied => {
+                        log::info!(
+                            "Start conflict resolution because incompat satisfied:\n   {}",
+                            current_incompat
+                        );
+                        conflict_id = Some(incompat_id);
+                        break;
+                    }
+                    Relation::AlmostSatisfied(package_almost) => {
+                        self.unit_propagation_buffer.push(package_almost.clone());
+                        // Add (not term) to the partial solution with incompat as cause.
+                        self.partial_solution.add_derivation(
+                            package_almost,
+                            incompat_id,
+                            &self.incompatibility_store,
+                        );
+                        // With the partial solution updated, the incompatibility is now contradicted.
+                        self.contradicted_incompatibilities
+                            .insert(incompat_id, self.partial_solution.current_decision_level());
+                    }
+                    Relation::Contradicted(_) => {
+                        self.contradicted_incompatibilities
+                            .insert(incompat_id, self.partial_solution.current_decision_level());
+                    }
+                    _ => {}
+                }
+            }
+            if let Some(incompat_id) = conflict_id {
+                let (package_almost, root_cause) = self.conflict_resolution(incompat_id)?;
+                self.unit_propagation_buffer.clear();
+                self.unit_propagation_buffer.push(package_almost.clone());
+                // Add to the partial solution with incompat as cause.
+                self.partial_solution.add_derivation(
+                    package_almost,
+                    root_cause,
+                    &self.incompatibility_store,
+                );
+                // After conflict resolution and the partial solution update,
+                // the root cause incompatibility is now contradicted.
+                self.contradicted_incompatibilities
+                    .insert(root_cause, self.partial_solution.current_decision_level());
+            }
+        }
+        // If there are no more changed packages, unit propagation is done.
+        Ok(())
+    }
+
+    /// Return the root cause and the backtracked model.
+    /// CF <https://github.com/dart-lang/pub/blob/master/doc/solver.md#unit-propagation>
+    #[allow(clippy::type_complexity)]
+    fn conflict_resolution<E: Error>(
+        &mut self,
+        incompatibility: IncompId<P, VS>,
+    ) -> Result<(P, IncompId<P, VS>), PubGrubError<P, VS, E>> {
+        let mut current_incompat_id = incompatibility;
+        let mut current_incompat_changed = false;
+        loop {
+            if self.incompatibility_store[current_incompat_id]
+                .is_terminal(&self.root_package, &self.root_version)
+            {
+                return Err(PubGrubError::NoSolution(
+                    self.build_derivation_tree(current_incompat_id),
+                ));
+            } else {
+                let (package, satisfier_search_result) = self.partial_solution.satisfier_search(
+                    &self.incompatibility_store[current_incompat_id],
+                    &self.incompatibility_store,
+                );
+                match satisfier_search_result {
+                    DifferentDecisionLevels {
+                        previous_satisfier_level,
+                    } => {
+                        let package = package.clone();
+                        self.backtrack(
+                            current_incompat_id,
+                            current_incompat_changed,
+                            previous_satisfier_level,
+                        );
+                        log::info!("backtrack to {:?}", previous_satisfier_level);
+                        return Ok((package, current_incompat_id));
+                    }
+                    SameDecisionLevels { satisfier_cause } => {
+                        let prior_cause = Incompatibility::prior_cause(
+                            current_incompat_id,
+                            satisfier_cause,
+                            package,
+                            &self.incompatibility_store,
+                        );
+                        log::info!("prior cause: {}", prior_cause);
+                        current_incompat_id = self.incompatibility_store.alloc(prior_cause);
+                        current_incompat_changed = true;
+                    }
+                }
+            }
+        }
+    }
+
+    /// Backtracking.
+    fn backtrack(
+        &mut self,
+        incompat: IncompId<P, VS>,
+        incompat_changed: bool,
+        decision_level: DecisionLevel,
+    ) {
+        self.partial_solution.backtrack(decision_level);
+        // Remove contradicted incompatibilities that depend on decisions we just backtracked away.
+        self.contradicted_incompatibilities
+            .retain(|_, dl| *dl <= decision_level);
+        if incompat_changed {
+            self.merge_incompatibility(incompat);
+        }
+    }
+
+    /// Add this incompatibility into the set of all incompatibilities.
+    ///
+    /// Pub collapses identical dependencies from adjacent package versions
+    /// into individual incompatibilities.
+    /// This substantially reduces the total number of incompatibilities
+    /// and makes it much easier for Pub to reason about multiple versions of packages at once.
+    ///
+    /// For example, rather than representing
+    /// foo 1.0.0 depends on bar ^1.0.0 and
+    /// foo 1.1.0 depends on bar ^1.0.0
+    /// as two separate incompatibilities,
+    /// they are collapsed together into the single incompatibility {foo ^1.0.0, not bar ^1.0.0}
+    /// (provided that no other version of foo exists between 1.0.0 and 2.0.0).
+    /// We could collapse them into { foo (1.0.0 ∪ 1.1.0), not bar ^1.0.0 }
+    /// without having to check the existence of other versions though.
+    fn merge_incompatibility(&mut self, mut id: IncompId<P, VS>) {
+        if let Some((p1, p2)) = self.incompatibility_store[id].as_dependency() {
+            // If we are a dependency, there's a good chance we can be merged with a previous dependency
+            let deps_lookup = self
+                .merged_dependencies
+                .entry((p1.clone(), p2.clone()))
+                .or_default();
+            if let Some((past, merged)) = deps_lookup.as_mut_slice().iter_mut().find_map(|past| {
+                self.incompatibility_store[id]
+                    .merge_dependents(&self.incompatibility_store[*past])
+                    .map(|m| (past, m))
+            }) {
+                let new = self.incompatibility_store.alloc(merged);
+                for (pkg, _) in self.incompatibility_store[new].iter() {
+                    self.incompatibilities
+                        .entry(pkg.clone())
+                        .or_default()
+                        .retain(|id| id != past);
+                }
+                *past = new;
+                id = new;
+            } else {
+                deps_lookup.push(id);
+            }
+        }
+        for (pkg, term) in self.incompatibility_store[id].iter() {
+            if cfg!(debug_assertions) {
+                assert_ne!(term, &crate::term::Term::any());
+            }
+            self.incompatibilities
+                .entry(pkg.clone())
+                .or_default()
+                .push(id);
+        }
+    }
+
+    // Error reporting #########################################################
+
+    fn build_derivation_tree(&self, incompat: IncompId<P, VS>) -> DerivationTree<P, VS> {
+        let mut all_ids = Set::default();
+        let mut shared_ids = Set::default();
+        let mut stack = vec![incompat];
+        while let Some(i) = stack.pop() {
+            if let Some((id1, id2)) = self.incompatibility_store[i].causes() {
+                if all_ids.contains(&i) {
+                    shared_ids.insert(i);
+                } else {
+                    stack.push(id1);
+                    stack.push(id2);
+                }
+            }
+            all_ids.insert(i);
+        }
+        // To avoid recursion we need to generate trees in topological order.
+        // That is to say we need to ensure that the causes are processed before the incompatibility they effect.
+        // It happens to be that sorting by their ID maintains this property.
+        let mut sorted_ids = all_ids.into_iter().collect::<Vec<_>>();
+        sorted_ids.sort_unstable_by_key(|id| id.into_raw());
+        let mut precomputed = Map::default();
+        for id in sorted_ids {
+            let tree = Incompatibility::build_derivation_tree(
+                id,
+                &shared_ids,
+                &self.incompatibility_store,
+                &precomputed,
+            );
+            precomputed.insert(id, Arc::new(tree));
+        }
+        // Now the user can refer to the entire tree from its root.
+        Arc::into_inner(precomputed.remove(&incompat).unwrap()).unwrap()
+    }
+}
+
\ No newline at end of file diff --git a/src/pubgrub/internal/incompatibility.rs.html b/src/pubgrub/internal/incompatibility.rs.html new file mode 100644 index 00000000..b4280e6c --- /dev/null +++ b/src/pubgrub/internal/incompatibility.rs.html @@ -0,0 +1,691 @@ +incompatibility.rs - source +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+
// SPDX-License-Identifier: MPL-2.0
+
+//! An incompatibility is a set of terms for different packages
+//! that should never be satisfied all together.
+
+use std::fmt;
+use std::sync::Arc;
+
+use crate::internal::arena::{Arena, Id};
+use crate::internal::small_map::SmallMap;
+use crate::package::Package;
+use crate::report::{
+    DefaultStringReportFormatter, DerivationTree, Derived, External, ReportFormatter,
+};
+use crate::term::{self, Term};
+use crate::type_aliases::{Map, Set};
+use crate::version_set::VersionSet;
+
+/// An incompatibility is a set of terms for different packages
+/// that should never be satisfied all together.
+/// An incompatibility usually originates from a package dependency.
+/// For example, if package A at version 1 depends on package B
+/// at version 2, you can never have both terms `A = 1`
+/// and `not B = 2` satisfied at the same time in a partial solution.
+/// This would mean that we found a solution with package A at version 1
+/// but not with package B at version 2.
+/// Yet A at version 1 depends on B at version 2 so this is not possible.
+/// Therefore, the set `{ A = 1, not B = 2 }` is an incompatibility,
+/// defined from dependencies of A at version 1.
+///
+/// Incompatibilities can also be derived from two other incompatibilities
+/// during conflict resolution. More about all this in
+/// [PubGrub documentation](https://github.com/dart-lang/pub/blob/master/doc/solver.md#incompatibility).
+#[derive(Debug, Clone)]
+pub struct Incompatibility<P: Package, VS: VersionSet> {
+    package_terms: SmallMap<P, Term<VS>>,
+    kind: Kind<P, VS>,
+}
+
+/// Type alias of unique identifiers for incompatibilities.
+pub type IncompId<P, VS> = Id<Incompatibility<P, VS>>;
+
+#[derive(Debug, Clone)]
+enum Kind<P: Package, VS: VersionSet> {
+    /// Initial incompatibility aiming at picking the root package for the first decision.
+    NotRoot(P, VS::V),
+    /// There are no versions in the given range for this package.
+    NoVersions(P, VS),
+    /// Dependencies of the package are unavailable for versions in that range.
+    UnavailableDependencies(P, VS),
+    /// Incompatibility coming from the dependencies of a given package.
+    FromDependencyOf(P, VS, P, VS),
+    /// Derived from two causes. Stores cause ids.
+    DerivedFrom(IncompId<P, VS>, IncompId<P, VS>),
+}
+
+/// A Relation describes how a set of terms can be compared to an incompatibility.
+/// Typically, the set of terms comes from the partial solution.
+#[derive(Eq, PartialEq, Debug)]
+pub enum Relation<P: Package> {
+    /// We say that a set of terms S satisfies an incompatibility I
+    /// if S satisfies every term in I.
+    Satisfied,
+    /// We say that S contradicts I
+    /// if S contradicts at least one term in I.
+    Contradicted(P),
+    /// If S satisfies all but one of I's terms and is inconclusive for the remaining term,
+    /// we say S "almost satisfies" I and we call the remaining term the "unsatisfied term".
+    AlmostSatisfied(P),
+    /// Otherwise, we say that their relation is inconclusive.
+    Inconclusive,
+}
+
+impl<P: Package, VS: VersionSet> Incompatibility<P, VS> {
+    /// Create the initial "not Root" incompatibility.
+    pub fn not_root(package: P, version: VS::V) -> Self {
+        Self {
+            package_terms: SmallMap::One([(
+                package.clone(),
+                Term::Negative(VS::singleton(version.clone())),
+            )]),
+            kind: Kind::NotRoot(package, version),
+        }
+    }
+
+    /// Create an incompatibility to remember
+    /// that a given set does not contain any version.
+    pub fn no_versions(package: P, term: Term<VS>) -> Self {
+        let set = match &term {
+            Term::Positive(r) => r.clone(),
+            Term::Negative(_) => panic!("No version should have a positive term"),
+        };
+        Self {
+            package_terms: SmallMap::One([(package.clone(), term)]),
+            kind: Kind::NoVersions(package, set),
+        }
+    }
+
+    /// Create an incompatibility to remember
+    /// that a package version is not selectable
+    /// because its list of dependencies is unavailable.
+    pub fn unavailable_dependencies(package: P, version: VS::V) -> Self {
+        let set = VS::singleton(version);
+        Self {
+            package_terms: SmallMap::One([(package.clone(), Term::Positive(set.clone()))]),
+            kind: Kind::UnavailableDependencies(package, set),
+        }
+    }
+
+    /// Build an incompatibility from a given dependency.
+    pub fn from_dependency(package: P, versions: VS, dep: (&P, &VS)) -> Self {
+        let (p2, set2) = dep;
+        Self {
+            package_terms: if set2 == &VS::empty() {
+                SmallMap::One([(package.clone(), Term::Positive(versions.clone()))])
+            } else {
+                SmallMap::Two([
+                    (package.clone(), Term::Positive(versions.clone())),
+                    (p2.clone(), Term::Negative(set2.clone())),
+                ])
+            },
+            kind: Kind::FromDependencyOf(package, versions, p2.clone(), set2.clone()),
+        }
+    }
+
+    pub fn as_dependency(&self) -> Option<(&P, &P)> {
+        match &self.kind {
+            Kind::FromDependencyOf(p1, _, p2, _) => Some((p1, p2)),
+            _ => None,
+        }
+    }
+
+    /// Merge dependant versions with the same dependency.
+    ///
+    /// When multiple versions of a package depend on the same range of another package,
+    /// we can merge the two into a single incompatibility.
+    /// For example, if a@1 depends on b and a@2 depends on b, we can say instead
+    /// a@1 and a@b depend on b.
+    ///
+    /// It is a special case of prior cause computation where the unified package
+    /// is the common dependant in the two incompatibilities expressing dependencies.
+    pub fn merge_dependents(&self, other: &Self) -> Option<Self> {
+        // It is almost certainly a bug to call this method without checking that self is a dependency
+        debug_assert!(self.as_dependency().is_some());
+        // Check that both incompatibilities are of the shape p1 depends on p2,
+        // with the same p1 and p2.
+        let self_pkgs = self.as_dependency()?;
+        if self_pkgs != other.as_dependency()? {
+            return None;
+        }
+        let (p1, p2) = self_pkgs;
+        let dep_term = self.get(p2);
+        // The dependency range for p2 must be the same in both case
+        // to be able to merge multiple p1 ranges.
+        if dep_term != other.get(p2) {
+            return None;
+        }
+        return Some(Self::from_dependency(
+            p1.clone(),
+            self.get(p1)
+                .unwrap()
+                .unwrap_positive()
+                .union(other.get(p1).unwrap().unwrap_positive()), // It is safe to `simplify` here
+            (&p2, dep_term.map_or(&VS::empty(), |v| v.unwrap_negative())),
+        ));
+    }
+
+    /// Prior cause of two incompatibilities using the rule of resolution.
+    pub fn prior_cause(
+        incompat: Id<Self>,
+        satisfier_cause: Id<Self>,
+        package: &P,
+        incompatibility_store: &Arena<Self>,
+    ) -> Self {
+        let kind = Kind::DerivedFrom(incompat, satisfier_cause);
+        let mut package_terms = incompatibility_store[incompat].package_terms.clone();
+        let t1 = package_terms.remove(package).unwrap();
+        let satisfier_cause_terms = &incompatibility_store[satisfier_cause].package_terms;
+        package_terms.merge(
+            satisfier_cause_terms.iter().filter(|(p, _)| p != &package),
+            |t1, t2| Some(t1.intersection(t2)),
+        );
+        let term = t1.union(satisfier_cause_terms.get(package).unwrap());
+        if term != Term::any() {
+            package_terms.insert(package.clone(), term);
+        }
+        Self {
+            package_terms,
+            kind,
+        }
+    }
+
+    /// Check if an incompatibility should mark the end of the algorithm
+    /// because it satisfies the root package.
+    pub fn is_terminal(&self, root_package: &P, root_version: &VS::V) -> bool {
+        if self.package_terms.len() == 0 {
+            true
+        } else if self.package_terms.len() > 1 {
+            false
+        } else {
+            let (package, term) = self.package_terms.iter().next().unwrap();
+            (package == root_package) && term.contains(root_version)
+        }
+    }
+
+    /// Get the term related to a given package (if it exists).
+    pub fn get(&self, package: &P) -> Option<&Term<VS>> {
+        self.package_terms.get(package)
+    }
+
+    /// Iterate over packages.
+    pub fn iter(&self) -> impl Iterator<Item = (&P, &Term<VS>)> {
+        self.package_terms.iter()
+    }
+
+    // Reporting ###############################################################
+
+    /// Retrieve parent causes if of type DerivedFrom.
+    pub fn causes(&self) -> Option<(Id<Self>, Id<Self>)> {
+        match self.kind {
+            Kind::DerivedFrom(id1, id2) => Some((id1, id2)),
+            _ => None,
+        }
+    }
+
+    /// Build a derivation tree for error reporting.
+    pub fn build_derivation_tree(
+        self_id: Id<Self>,
+        shared_ids: &Set<Id<Self>>,
+        store: &Arena<Self>,
+        precomputed: &Map<Id<Self>, Arc<DerivationTree<P, VS>>>,
+    ) -> DerivationTree<P, VS> {
+        match store[self_id].kind.clone() {
+            Kind::DerivedFrom(id1, id2) => {
+                let derived = Derived {
+                    terms: store[self_id].package_terms.as_map(),
+                    shared_id: shared_ids.get(&self_id).map(|id| id.into_raw()),
+                    cause1: precomputed
+                        .get(&id1)
+                        .expect("Non-topological calls building tree")
+                        .clone(),
+                    cause2: precomputed
+                        .get(&id2)
+                        .expect("Non-topological calls building tree")
+                        .clone(),
+                };
+                DerivationTree::Derived(derived)
+            }
+            Kind::NotRoot(package, version) => {
+                DerivationTree::External(External::NotRoot(package, version))
+            }
+            Kind::NoVersions(package, set) => {
+                DerivationTree::External(External::NoVersions(package, set))
+            }
+            Kind::UnavailableDependencies(package, set) => {
+                DerivationTree::External(External::UnavailableDependencies(package, set))
+            }
+            Kind::FromDependencyOf(package, set, dep_package, dep_set) => DerivationTree::External(
+                External::FromDependencyOf(package, set, dep_package, dep_set),
+            ),
+        }
+    }
+}
+
+impl<'a, P: Package, VS: VersionSet + 'a> Incompatibility<P, VS> {
+    /// CF definition of Relation enum.
+    pub fn relation(&self, terms: impl Fn(&P) -> Option<&'a Term<VS>>) -> Relation<P> {
+        let mut relation = Relation::Satisfied;
+        for (package, incompat_term) in self.package_terms.iter() {
+            match terms(package).map(|term| incompat_term.relation_with(term)) {
+                Some(term::Relation::Satisfied) => {}
+                Some(term::Relation::Contradicted) => {
+                    return Relation::Contradicted(package.clone());
+                }
+                None | Some(term::Relation::Inconclusive) => {
+                    // If a package is not present, the intersection is the same as [Term::any].
+                    // According to the rules of satisfactions, the relation would be inconclusive.
+                    // It could also be satisfied if the incompatibility term was also [Term::any],
+                    // but we systematically remove those from incompatibilities
+                    // so we're safe on that front.
+                    if relation == Relation::Satisfied {
+                        relation = Relation::AlmostSatisfied(package.clone());
+                    } else {
+                        return Relation::Inconclusive;
+                    }
+                }
+            }
+        }
+        relation
+    }
+}
+
+impl<P: Package, VS: VersionSet> fmt::Display for Incompatibility<P, VS> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(
+            f,
+            "{}",
+            DefaultStringReportFormatter.format_terms(&self.package_terms.as_map())
+        )
+    }
+}
+
+// TESTS #######################################################################
+
+#[cfg(test)]
+pub mod tests {
+    use super::*;
+    use crate::range::Range;
+    use crate::term::tests::strategy as term_strat;
+    use crate::type_aliases::Map;
+    use proptest::prelude::*;
+
+    proptest! {
+
+        /// For any three different packages p1, p2 and p3,
+        /// for any three terms t1, t2 and t3,
+        /// if we have the two following incompatibilities:
+        ///    { p1: t1, p2: not t2 }
+        ///    { p2: t2, p3: t3 }
+        /// the rule of resolution says that we can deduce the following incompatibility:
+        ///    { p1: t1, p3: t3 }
+        #[test]
+        fn rule_of_resolution(t1 in term_strat(), t2 in term_strat(), t3 in term_strat()) {
+            let mut store = Arena::new();
+            let i1 = store.alloc(Incompatibility {
+                package_terms: SmallMap::Two([("p1", t1.clone()), ("p2", t2.negate())]),
+                kind: Kind::UnavailableDependencies("0", Range::full())
+            });
+
+            let i2 = store.alloc(Incompatibility {
+                package_terms: SmallMap::Two([("p2", t2), ("p3", t3.clone())]),
+                kind: Kind::UnavailableDependencies("0", Range::full())
+            });
+
+            let mut i3 = Map::default();
+            i3.insert("p1", t1);
+            i3.insert("p3", t3);
+
+            let i_resolution = Incompatibility::prior_cause(i1, i2, &"p2", &store);
+            assert_eq!(i_resolution.package_terms.as_map(), i3);
+        }
+
+    }
+}
+
\ No newline at end of file diff --git a/src/pubgrub/internal/mod.rs.html b/src/pubgrub/internal/mod.rs.html new file mode 100644 index 00000000..910a0888 --- /dev/null +++ b/src/pubgrub/internal/mod.rs.html @@ -0,0 +1,23 @@ +mod.rs - source +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+
// SPDX-License-Identifier: MPL-2.0
+
+//! Non exposed modules.
+
+pub mod arena;
+pub mod core;
+pub mod incompatibility;
+pub mod partial_solution;
+pub mod small_map;
+pub mod small_vec;
+
\ No newline at end of file diff --git a/src/pubgrub/internal/partial_solution.rs.html b/src/pubgrub/internal/partial_solution.rs.html new file mode 100644 index 00000000..2f902d75 --- /dev/null +++ b/src/pubgrub/internal/partial_solution.rs.html @@ -0,0 +1,1121 @@ +partial_solution.rs - source +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
+479
+480
+481
+482
+483
+484
+485
+486
+487
+488
+489
+490
+491
+492
+493
+494
+495
+496
+497
+498
+499
+500
+501
+502
+503
+504
+505
+506
+507
+508
+509
+510
+511
+512
+513
+514
+515
+516
+517
+518
+519
+520
+521
+522
+523
+524
+525
+526
+527
+528
+529
+530
+531
+532
+533
+534
+535
+536
+537
+538
+539
+540
+541
+542
+543
+544
+545
+546
+547
+548
+549
+550
+551
+552
+553
+554
+555
+556
+557
+558
+559
+
// SPDX-License-Identifier: MPL-2.0
+
+//! A Memory acts like a structured partial solution
+//! where terms are regrouped by package in a [Map](crate::type_aliases::Map).
+
+use std::fmt::Display;
+use std::hash::BuildHasherDefault;
+
+use priority_queue::PriorityQueue;
+use rustc_hash::FxHasher;
+
+use crate::internal::arena::Arena;
+use crate::internal::incompatibility::{IncompId, Incompatibility, Relation};
+use crate::internal::small_map::SmallMap;
+use crate::package::Package;
+use crate::term::Term;
+use crate::type_aliases::SelectedDependencies;
+use crate::version_set::VersionSet;
+
+use super::small_vec::SmallVec;
+
+type FnvIndexMap<K, V> = indexmap::IndexMap<K, V, BuildHasherDefault<rustc_hash::FxHasher>>;
+
+#[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq)]
+pub struct DecisionLevel(pub u32);
+
+impl DecisionLevel {
+    pub fn increment(self) -> Self {
+        Self(self.0 + 1)
+    }
+}
+
+/// The partial solution contains all package assignments,
+/// organized by package and historically ordered.
+#[derive(Clone, Debug)]
+pub struct PartialSolution<P: Package, VS: VersionSet, Priority: Ord + Clone> {
+    next_global_index: u32,
+    current_decision_level: DecisionLevel,
+    /// `package_assignments` is primarily a HashMap from a package to its
+    /// `PackageAssignments`. But it can also keep the items in an order.
+    ///  We maintain three sections in this order:
+    /// 1. `[..current_decision_level]` Are packages that have had a decision made sorted by the `decision_level`.
+    ///    This makes it very efficient to extract the solution, And to backtrack to a particular decision level.
+    /// 2. `[current_decision_level..changed_this_decision_level]` Are packages that have **not** had there assignments
+    ///    changed since the last time `prioritize` has bean called. Within this range there is no sorting.
+    /// 3. `[changed_this_decision_level..]` Containes all packages that **have** had there assignments changed since
+    ///    the last time `prioritize` has bean called. The inverse is not necessarily true, some packages in the range
+    ///    did not have a change. Within this range there is no sorting.
+    package_assignments: FnvIndexMap<P, PackageAssignments<P, VS>>,
+    /// `prioritized_potential_packages` is primarily a HashMap from a package with no desition and a positive assignment
+    /// to its `Priority`. But, it also maintains a max heap of packages by `Priority` order.
+    prioritized_potential_packages: PriorityQueue<P, Priority, BuildHasherDefault<FxHasher>>,
+    changed_this_decision_level: usize,
+}
+
+impl<P: Package, VS: VersionSet, Priority: Ord + Clone> Display
+    for PartialSolution<P, VS, Priority>
+{
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        let mut assignments: Vec<_> = self
+            .package_assignments
+            .iter()
+            .map(|(p, pa)| format!("{}: {}", p, pa))
+            .collect();
+        assignments.sort();
+        write!(
+            f,
+            "next_global_index: {}\ncurrent_decision_level: {:?}\npackage_assignements:\n{}",
+            self.next_global_index,
+            self.current_decision_level,
+            assignments.join("\t\n")
+        )
+    }
+}
+
+/// Package assignments contain the potential decision and derivations
+/// that have already been made for a given package,
+/// as well as the intersection of terms by all of these.
+#[derive(Clone, Debug)]
+struct PackageAssignments<P: Package, VS: VersionSet> {
+    smallest_decision_level: DecisionLevel,
+    highest_decision_level: DecisionLevel,
+    dated_derivations: SmallVec<DatedDerivation<P, VS>>,
+    assignments_intersection: AssignmentsIntersection<VS>,
+}
+
+impl<P: Package, VS: VersionSet> Display for PackageAssignments<P, VS> {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        let derivations: Vec<_> = self
+            .dated_derivations
+            .iter()
+            .map(|dd| dd.to_string())
+            .collect();
+        write!(
+            f,
+            "decision range: {:?}..{:?}\nderivations:\n  {}\n,assignments_intersection: {}",
+            self.smallest_decision_level,
+            self.highest_decision_level,
+            derivations.join("\n  "),
+            self.assignments_intersection
+        )
+    }
+}
+
+#[derive(Clone, Debug)]
+pub struct DatedDerivation<P: Package, VS: VersionSet> {
+    global_index: u32,
+    decision_level: DecisionLevel,
+    cause: IncompId<P, VS>,
+    accumulated_intersection: Term<VS>,
+}
+
+impl<P: Package, VS: VersionSet> Display for DatedDerivation<P, VS> {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        write!(f, "{:?}, cause: {:?}", self.decision_level, self.cause)
+    }
+}
+
+#[derive(Clone, Debug)]
+enum AssignmentsIntersection<VS: VersionSet> {
+    Decision((u32, VS::V, Term<VS>)),
+    Derivations(Term<VS>),
+}
+
+impl<VS: VersionSet> Display for AssignmentsIntersection<VS> {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        match self {
+            Self::Decision((lvl, version, _)) => {
+                write!(f, "Decision: level {}, v = {}", lvl, version)
+            }
+            Self::Derivations(term) => write!(f, "Derivations term: {}", term),
+        }
+    }
+}
+
+#[derive(Clone, Debug)]
+pub enum SatisfierSearch<P: Package, VS: VersionSet> {
+    DifferentDecisionLevels {
+        previous_satisfier_level: DecisionLevel,
+    },
+    SameDecisionLevels {
+        satisfier_cause: IncompId<P, VS>,
+    },
+}
+
+type SatisfiedMap<'i, P, VS> = SmallMap<&'i P, (Option<IncompId<P, VS>>, u32, DecisionLevel)>;
+
+impl<P: Package, VS: VersionSet, Priority: Ord + Clone> PartialSolution<P, VS, Priority> {
+    /// Initialize an empty PartialSolution.
+    pub fn empty() -> Self {
+        Self {
+            next_global_index: 0,
+            current_decision_level: DecisionLevel(0),
+            package_assignments: FnvIndexMap::default(),
+            prioritized_potential_packages: PriorityQueue::default(),
+            changed_this_decision_level: 0,
+        }
+    }
+
+    /// Add a decision.
+    pub fn add_decision(&mut self, package: P, version: VS::V) {
+        // Check that add_decision is never used in the wrong context.
+        if cfg!(debug_assertions) {
+            match self.package_assignments.get_mut(&package) {
+                None => panic!("Derivations must already exist"),
+                Some(pa) => match &pa.assignments_intersection {
+                    // Cannot be called when a decision has already been taken.
+                    AssignmentsIntersection::Decision(_) => panic!("Already existing decision"),
+                    // Cannot be called if the versions is not contained in the terms intersection.
+                    AssignmentsIntersection::Derivations(term) => {
+                        debug_assert!(
+                            term.contains(&version),
+                            "{}: {} was expected to be contained in {}",
+                            package,
+                            version,
+                            term,
+                        )
+                    }
+                },
+            }
+            assert_eq!(
+                self.changed_this_decision_level,
+                self.package_assignments.len()
+            );
+        }
+        let new_idx = self.current_decision_level.0 as usize;
+        self.current_decision_level = self.current_decision_level.increment();
+        let (old_idx, _, pa) = self
+            .package_assignments
+            .get_full_mut(&package)
+            .expect("Derivations must already exist");
+        pa.highest_decision_level = self.current_decision_level;
+        pa.assignments_intersection = AssignmentsIntersection::Decision((
+            self.next_global_index,
+            version.clone(),
+            Term::exact(version),
+        ));
+        // Maintain that the beginning of the `package_assignments` Have all decisions in sorted order.
+        if new_idx != old_idx {
+            self.package_assignments.swap_indices(new_idx, old_idx);
+        }
+        self.next_global_index += 1;
+    }
+
+    /// Add a derivation.
+    pub fn add_derivation(
+        &mut self,
+        package: P,
+        cause: IncompId<P, VS>,
+        store: &Arena<Incompatibility<P, VS>>,
+    ) {
+        use indexmap::map::Entry;
+        let mut dated_derivation = DatedDerivation {
+            global_index: self.next_global_index,
+            decision_level: self.current_decision_level,
+            cause,
+            accumulated_intersection: store[cause].get(&package).unwrap().negate(),
+        };
+        self.next_global_index += 1;
+        let pa_last_index = self.package_assignments.len().saturating_sub(1);
+        match self.package_assignments.entry(package) {
+            Entry::Occupied(mut occupied) => {
+                let idx = occupied.index();
+                let pa = occupied.get_mut();
+                pa.highest_decision_level = self.current_decision_level;
+                match &mut pa.assignments_intersection {
+                    // Check that add_derivation is never called in the wrong context.
+                    AssignmentsIntersection::Decision(_) => {
+                        panic!("add_derivation should not be called after a decision")
+                    }
+                    AssignmentsIntersection::Derivations(t) => {
+                        *t = t.intersection(&dated_derivation.accumulated_intersection);
+                        dated_derivation.accumulated_intersection = t.clone();
+                        if t.is_positive() {
+                            // we can use `swap_indices` to make `changed_this_decision_level` only go down by 1
+                            // but the copying is slower then the larger search
+                            self.changed_this_decision_level =
+                                std::cmp::min(self.changed_this_decision_level, idx);
+                        }
+                    }
+                }
+                pa.dated_derivations.push(dated_derivation);
+            }
+            Entry::Vacant(v) => {
+                let term = dated_derivation.accumulated_intersection.clone();
+                if term.is_positive() {
+                    self.changed_this_decision_level =
+                        std::cmp::min(self.changed_this_decision_level, pa_last_index);
+                }
+                v.insert(PackageAssignments {
+                    smallest_decision_level: self.current_decision_level,
+                    highest_decision_level: self.current_decision_level,
+                    dated_derivations: SmallVec::One([dated_derivation]),
+                    assignments_intersection: AssignmentsIntersection::Derivations(term),
+                });
+            }
+        }
+    }
+
+    pub fn pick_highest_priority_pkg(
+        &mut self,
+        prioritizer: impl Fn(&P, &VS) -> Priority,
+    ) -> Option<P> {
+        let check_all = self.changed_this_decision_level
+            == self.current_decision_level.0.saturating_sub(1) as usize;
+        let current_decision_level = self.current_decision_level;
+        let prioritized_potential_packages = &mut self.prioritized_potential_packages;
+        self.package_assignments
+            .get_range(self.changed_this_decision_level..)
+            .unwrap()
+            .iter()
+            .filter(|(_, pa)| {
+                // We only actually need to update the package if its Been changed
+                // since the last time we called prioritize.
+                // Which means it's highest decision level is the current decision level,
+                // or if we backtracked in the mean time.
+                check_all || pa.highest_decision_level == current_decision_level
+            })
+            .filter_map(|(p, pa)| pa.assignments_intersection.potential_package_filter(p))
+            .for_each(|(p, r)| {
+                let priority = prioritizer(p, r);
+                prioritized_potential_packages.push(p.clone(), priority);
+            });
+        self.changed_this_decision_level = self.package_assignments.len();
+        prioritized_potential_packages.pop().map(|(p, _)| p)
+    }
+
+    /// If a partial solution has, for every positive derivation,
+    /// a corresponding decision that satisfies that assignment,
+    /// it's a total solution and version solving has succeeded.
+    pub fn extract_solution(&self) -> SelectedDependencies<P, VS::V> {
+        self.package_assignments
+            .iter()
+            .take(self.current_decision_level.0 as usize)
+            .map(|(p, pa)| match &pa.assignments_intersection {
+                AssignmentsIntersection::Decision((_, v, _)) => (p.clone(), v.clone()),
+                AssignmentsIntersection::Derivations(_) => {
+                    panic!("Derivations in the Decision part")
+                }
+            })
+            .collect()
+    }
+
+    /// Backtrack the partial solution to a given decision level.
+    pub fn backtrack(&mut self, decision_level: DecisionLevel) {
+        self.current_decision_level = decision_level;
+        self.package_assignments.retain(|_p, pa| {
+            if pa.smallest_decision_level > decision_level {
+                // Remove all entries that have a smallest decision level higher than the backtrack target.
+                false
+            } else if pa.highest_decision_level <= decision_level {
+                // Do not change entries older than the backtrack decision level target.
+                true
+            } else {
+                // smallest_decision_level <= decision_level < highest_decision_level
+                //
+                // Since decision_level < highest_decision_level,
+                // We can be certain that there will be no decision in this package assignments
+                // after backtracking, because such decision would have been the last
+                // assignment and it would have the "highest_decision_level".
+
+                // Truncate the history.
+                while pa.dated_derivations.last().map(|dd| dd.decision_level) > Some(decision_level)
+                {
+                    pa.dated_derivations.pop();
+                }
+                debug_assert!(!pa.dated_derivations.is_empty());
+
+                let last = pa.dated_derivations.last().unwrap();
+
+                // Update highest_decision_level.
+                pa.highest_decision_level = last.decision_level;
+
+                // Reset the assignments intersection.
+                pa.assignments_intersection =
+                    AssignmentsIntersection::Derivations(last.accumulated_intersection.clone());
+                true
+            }
+        });
+        // Throw away all stored priority levels, And mark that they all need to be recomputed.
+        self.prioritized_potential_packages.clear();
+        self.changed_this_decision_level = self.current_decision_level.0.saturating_sub(1) as usize;
+    }
+
+    /// We can add the version to the partial solution as a decision
+    /// if it doesn't produce any conflict with the new incompatibilities.
+    /// In practice I think it can only produce a conflict if one of the dependencies
+    /// (which are used to make the new incompatibilities)
+    /// is already in the partial solution with an incompatible version.
+    pub fn add_version(
+        &mut self,
+        package: P,
+        version: VS::V,
+        new_incompatibilities: std::ops::Range<IncompId<P, VS>>,
+        store: &Arena<Incompatibility<P, VS>>,
+    ) {
+        let exact = Term::exact(version.clone());
+        let not_satisfied = |incompat: &Incompatibility<P, VS>| {
+            incompat.relation(|p| {
+                if p == &package {
+                    Some(&exact)
+                } else {
+                    self.term_intersection_for_package(p)
+                }
+            }) != Relation::Satisfied
+        };
+
+        // Check none of the dependencies (new_incompatibilities)
+        // would create a conflict (be satisfied).
+        if store[new_incompatibilities].iter().all(not_satisfied) {
+            log::info!("add_decision: {} @ {}", package, version);
+            self.add_decision(package, version);
+        } else {
+            log::info!(
+                "not adding {} @ {} because of its dependencies",
+                package,
+                version
+            );
+        }
+    }
+
+    /// Check if the terms in the partial solution satisfy the incompatibility.
+    pub fn relation(&self, incompat: &Incompatibility<P, VS>) -> Relation<P> {
+        incompat.relation(|package| self.term_intersection_for_package(package))
+    }
+
+    /// Retrieve intersection of terms related to package.
+    pub fn term_intersection_for_package(&self, package: &P) -> Option<&Term<VS>> {
+        self.package_assignments
+            .get(package)
+            .map(|pa| pa.assignments_intersection.term())
+    }
+
+    /// Figure out if the satisfier and previous satisfier are of different decision levels.
+    pub fn satisfier_search<'i>(
+        &self,
+        incompat: &'i Incompatibility<P, VS>,
+        store: &Arena<Incompatibility<P, VS>>,
+    ) -> (&'i P, SatisfierSearch<P, VS>) {
+        let satisfied_map = Self::find_satisfier(incompat, &self.package_assignments);
+        let (&satisfier_package, &(satisfier_cause, _, satisfier_decision_level)) = satisfied_map
+            .iter()
+            .max_by_key(|(_p, (_, global_index, _))| global_index)
+            .unwrap();
+        let previous_satisfier_level = Self::find_previous_satisfier(
+            incompat,
+            satisfier_package,
+            satisfied_map,
+            &self.package_assignments,
+            store,
+        );
+        let search_result = if previous_satisfier_level >= satisfier_decision_level {
+            SatisfierSearch::SameDecisionLevels {
+                satisfier_cause: satisfier_cause.unwrap(),
+            }
+        } else {
+            SatisfierSearch::DifferentDecisionLevels {
+                previous_satisfier_level,
+            }
+        };
+        (satisfier_package, search_result)
+    }
+
+    /// A satisfier is the earliest assignment in partial solution such that the incompatibility
+    /// is satisfied by the partial solution up to and including that assignment.
+    ///
+    /// Returns a map indicating for each package term, when that was first satisfied in history.
+    /// If we effectively found a satisfier, the returned map must be the same size that incompat.
+    ///
+    /// Question: This is possible since we added a "global_index" to every dated_derivation.
+    /// It would be nice if we could get rid of it, but I don't know if then it will be possible
+    /// to return a coherent previous_satisfier_level.
+    fn find_satisfier<'i>(
+        incompat: &'i Incompatibility<P, VS>,
+        package_assignments: &FnvIndexMap<P, PackageAssignments<P, VS>>,
+    ) -> SatisfiedMap<'i, P, VS> {
+        let mut satisfied = SmallMap::Empty;
+        for (package, incompat_term) in incompat.iter() {
+            let pa = package_assignments.get(package).expect("Must exist");
+            satisfied.insert(package, pa.satisfier(package, &incompat_term.negate()));
+        }
+        satisfied
+    }
+
+    /// Earliest assignment in the partial solution before satisfier
+    /// such that incompatibility is satisfied by the partial solution up to
+    /// and including that assignment plus satisfier.
+    fn find_previous_satisfier<'i>(
+        incompat: &Incompatibility<P, VS>,
+        satisfier_package: &'i P,
+        mut satisfied_map: SatisfiedMap<'i, P, VS>,
+        package_assignments: &FnvIndexMap<P, PackageAssignments<P, VS>>,
+        store: &Arena<Incompatibility<P, VS>>,
+    ) -> DecisionLevel {
+        // First, let's retrieve the previous derivations and the initial accum_term.
+        let satisfier_pa = package_assignments.get(satisfier_package).unwrap();
+        let (satisfier_cause, _gidx, _dl) = satisfied_map.get(&satisfier_package).unwrap();
+
+        let accum_term = if let &Some(cause) = satisfier_cause {
+            store[cause].get(satisfier_package).unwrap().negate()
+        } else {
+            match &satisfier_pa.assignments_intersection {
+                AssignmentsIntersection::Derivations(_) => panic!("must be a decision"),
+                AssignmentsIntersection::Decision((_, _, term)) => term.clone(),
+            }
+        };
+
+        let incompat_term = incompat
+            .get(satisfier_package)
+            .expect("satisfier package not in incompat");
+
+        satisfied_map.insert(
+            satisfier_package,
+            satisfier_pa.satisfier(
+                satisfier_package,
+                &accum_term.intersection(&incompat_term.negate()),
+            ),
+        );
+
+        // Finally, let's identify the decision level of that previous satisfier.
+        let (_, &(_, _, decision_level)) = satisfied_map
+            .iter()
+            .max_by_key(|(_p, (_, global_index, _))| global_index)
+            .unwrap();
+        decision_level.max(DecisionLevel(1))
+    }
+
+    pub fn current_decision_level(&self) -> DecisionLevel {
+        self.current_decision_level
+    }
+}
+
+impl<P: Package, VS: VersionSet> PackageAssignments<P, VS> {
+    fn satisfier(
+        &self,
+        package: &P,
+        start_term: &Term<VS>,
+    ) -> (Option<IncompId<P, VS>>, u32, DecisionLevel) {
+        let empty = Term::empty();
+        // Indicate if we found a satisfier in the list of derivations, otherwise it will be the decision.
+        let idx = self
+            .dated_derivations
+            .as_slice()
+            .partition_point(|dd| dd.accumulated_intersection.intersection(start_term) != empty);
+        if let Some(dd) = self.dated_derivations.get(idx) {
+            debug_assert_eq!(dd.accumulated_intersection.intersection(start_term), empty);
+            return (Some(dd.cause), dd.global_index, dd.decision_level);
+        }
+        // If it wasn't found in the derivations,
+        // it must be the decision which is last (if called in the right context).
+        match &self.assignments_intersection {
+            AssignmentsIntersection::Decision((global_index, _, _)) => {
+                (None, *global_index, self.highest_decision_level)
+            }
+            AssignmentsIntersection::Derivations(accumulated_intersection) => {
+                unreachable!(
+                    concat!(
+                        "while processing package {}: ",
+                        "accum_term = {} has overlap with incompat_term = {}, ",
+                        "which means the last assignment should have been a decision, ",
+                        "but instead it was a derivation. This shouldn't be possible! ",
+                        "(Maybe your Version ordering is broken?)"
+                    ),
+                    package, accumulated_intersection, start_term
+                )
+            }
+        }
+    }
+}
+
+impl<VS: VersionSet> AssignmentsIntersection<VS> {
+    /// Returns the term intersection of all assignments (decision included).
+    fn term(&self) -> &Term<VS> {
+        match self {
+            Self::Decision((_, _, term)) => term,
+            Self::Derivations(term) => term,
+        }
+    }
+
+    /// A package is a potential pick if there isn't an already
+    /// selected version (no "decision")
+    /// and if it contains at least one positive derivation term
+    /// in the partial solution.
+    fn potential_package_filter<'a, P: Package>(
+        &'a self,
+        package: &'a P,
+    ) -> Option<(&'a P, &'a VS)> {
+        match self {
+            Self::Decision(_) => None,
+            Self::Derivations(term_intersection) => {
+                if term_intersection.is_positive() {
+                    Some((package, term_intersection.unwrap_positive()))
+                } else {
+                    None
+                }
+            }
+        }
+    }
+}
+
\ No newline at end of file diff --git a/src/pubgrub/internal/small_map.rs.html b/src/pubgrub/internal/small_map.rs.html new file mode 100644 index 00000000..0575695e --- /dev/null +++ b/src/pubgrub/internal/small_map.rs.html @@ -0,0 +1,397 @@ +small_map.rs - source +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+
use crate::type_aliases::Map;
+use std::hash::Hash;
+
+#[derive(Debug, Clone)]
+pub enum SmallMap<K, V> {
+    Empty,
+    One([(K, V); 1]),
+    Two([(K, V); 2]),
+    Flexible(Map<K, V>),
+}
+
+impl<K: PartialEq + Eq + Hash, V> SmallMap<K, V> {
+    pub fn get(&self, key: &K) -> Option<&V> {
+        match self {
+            Self::Empty => None,
+            Self::One([(k, v)]) if k == key => Some(v),
+            Self::One(_) => None,
+            Self::Two([(k1, v1), _]) if key == k1 => Some(v1),
+            Self::Two([_, (k2, v2)]) if key == k2 => Some(v2),
+            Self::Two(_) => None,
+            Self::Flexible(data) => data.get(key),
+        }
+    }
+
+    pub fn get_mut(&mut self, key: &K) -> Option<&mut V> {
+        match self {
+            Self::Empty => None,
+            Self::One([(k, v)]) if k == key => Some(v),
+            Self::One(_) => None,
+            Self::Two([(k1, v1), _]) if key == k1 => Some(v1),
+            Self::Two([_, (k2, v2)]) if key == k2 => Some(v2),
+            Self::Two(_) => None,
+            Self::Flexible(data) => data.get_mut(key),
+        }
+    }
+
+    pub fn remove(&mut self, key: &K) -> Option<V> {
+        let out;
+        *self = match std::mem::take(self) {
+            Self::Empty => {
+                out = None;
+                Self::Empty
+            }
+            Self::One([(k, v)]) => {
+                if key == &k {
+                    out = Some(v);
+                    Self::Empty
+                } else {
+                    out = None;
+                    Self::One([(k, v)])
+                }
+            }
+            Self::Two([(k1, v1), (k2, v2)]) => {
+                if key == &k1 {
+                    out = Some(v1);
+                    Self::One([(k2, v2)])
+                } else if key == &k2 {
+                    out = Some(v2);
+                    Self::One([(k1, v1)])
+                } else {
+                    out = None;
+                    Self::Two([(k1, v1), (k2, v2)])
+                }
+            }
+            Self::Flexible(mut data) => {
+                out = data.remove(key);
+                Self::Flexible(data)
+            }
+        };
+        out
+    }
+
+    pub fn insert(&mut self, key: K, value: V) {
+        *self = match std::mem::take(self) {
+            Self::Empty => Self::One([(key, value)]),
+            Self::One([(k, v)]) => {
+                if key == k {
+                    Self::One([(k, value)])
+                } else {
+                    Self::Two([(k, v), (key, value)])
+                }
+            }
+            Self::Two([(k1, v1), (k2, v2)]) => {
+                if key == k1 {
+                    Self::Two([(k1, value), (k2, v2)])
+                } else if key == k2 {
+                    Self::Two([(k1, v1), (k2, value)])
+                } else {
+                    let mut data: Map<K, V> = Map::with_capacity_and_hasher(3, Default::default());
+                    data.insert(key, value);
+                    data.insert(k1, v1);
+                    data.insert(k2, v2);
+                    Self::Flexible(data)
+                }
+            }
+            Self::Flexible(mut data) => {
+                data.insert(key, value);
+                Self::Flexible(data)
+            }
+        };
+    }
+}
+
+impl<K: Clone + PartialEq + Eq + Hash, V: Clone> SmallMap<K, V> {
+    /// Merge two hash maps.
+    ///
+    /// When a key is common to both,
+    /// apply the provided function to both values.
+    /// If the result is None, remove that key from the merged map,
+    /// otherwise add the content of the Some(_).
+    pub fn merge<'a>(
+        &'a mut self,
+        map_2: impl Iterator<Item = (&'a K, &'a V)>,
+        f: impl Fn(&V, &V) -> Option<V>,
+    ) {
+        for (key, val_2) in map_2 {
+            match self.get_mut(key) {
+                None => {
+                    self.insert(key.clone(), val_2.clone());
+                }
+                Some(val_1) => match f(val_1, val_2) {
+                    None => {
+                        self.remove(key);
+                    }
+                    Some(merged_value) => *val_1 = merged_value,
+                },
+            }
+        }
+    }
+}
+
+impl<K, V> Default for SmallMap<K, V> {
+    fn default() -> Self {
+        Self::Empty
+    }
+}
+
+impl<K, V> SmallMap<K, V> {
+    pub fn len(&self) -> usize {
+        match self {
+            Self::Empty => 0,
+            Self::One(_) => 1,
+            Self::Two(_) => 2,
+            Self::Flexible(data) => data.len(),
+        }
+    }
+}
+
+impl<K: Eq + Hash + Clone, V: Clone> SmallMap<K, V> {
+    pub fn as_map(&self) -> Map<K, V> {
+        match self {
+            Self::Empty => Map::default(),
+            Self::One([(k, v)]) => {
+                let mut map = Map::with_capacity_and_hasher(1, Default::default());
+                map.insert(k.clone(), v.clone());
+                map
+            }
+            Self::Two(data) => {
+                let mut map = Map::with_capacity_and_hasher(2, Default::default());
+                for (k, v) in data {
+                    map.insert(k.clone(), v.clone());
+                }
+                map
+            }
+            Self::Flexible(data) => data.clone(),
+        }
+    }
+}
+
+enum IterSmallMap<'a, K, V> {
+    Inline(std::slice::Iter<'a, (K, V)>),
+    Map(std::collections::hash_map::Iter<'a, K, V>),
+}
+
+impl<'a, K: 'a, V: 'a> Iterator for IterSmallMap<'a, K, V> {
+    type Item = (&'a K, &'a V);
+
+    fn next(&mut self) -> Option<Self::Item> {
+        match self {
+            // False-positive, remove when stable is >=1.76 February 24
+            #[allow(clippy::map_identity)]
+            IterSmallMap::Inline(inner) => inner.next().map(|(k, v)| (k, v)),
+            IterSmallMap::Map(inner) => inner.next(),
+        }
+    }
+}
+
+impl<K, V> SmallMap<K, V> {
+    pub fn iter(&self) -> impl Iterator<Item = (&K, &V)> {
+        match self {
+            Self::Empty => IterSmallMap::Inline([].iter()),
+            Self::One(data) => IterSmallMap::Inline(data.iter()),
+            Self::Two(data) => IterSmallMap::Inline(data.iter()),
+            Self::Flexible(data) => IterSmallMap::Map(data.iter()),
+        }
+    }
+}
+
\ No newline at end of file diff --git a/src/pubgrub/internal/small_vec.rs.html b/src/pubgrub/internal/small_vec.rs.html new file mode 100644 index 00000000..4188b7bd --- /dev/null +++ b/src/pubgrub/internal/small_vec.rs.html @@ -0,0 +1,465 @@ +small_vec.rs - source +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+
use std::fmt;
+use std::hash::{Hash, Hasher};
+use std::ops::Deref;
+
+#[derive(Clone)]
+pub enum SmallVec<T> {
+    Empty,
+    One([T; 1]),
+    Two([T; 2]),
+    Flexible(Vec<T>),
+}
+
+impl<T> SmallVec<T> {
+    pub fn empty() -> Self {
+        Self::Empty
+    }
+
+    pub fn one(t: T) -> Self {
+        Self::One([t])
+    }
+
+    pub fn as_slice(&self) -> &[T] {
+        match self {
+            Self::Empty => &[],
+            Self::One(v) => v,
+            Self::Two(v) => v,
+            Self::Flexible(v) => v,
+        }
+    }
+
+    pub fn as_mut_slice(&mut self) -> &mut [T] {
+        match self {
+            Self::Empty => &mut [],
+            Self::One(v) => v,
+            Self::Two(v) => v,
+            Self::Flexible(v) => v,
+        }
+    }
+
+    pub fn push(&mut self, new: T) {
+        *self = match std::mem::take(self) {
+            Self::Empty => Self::One([new]),
+            Self::One([v1]) => Self::Two([v1, new]),
+            Self::Two([v1, v2]) => Self::Flexible(vec![v1, v2, new]),
+            Self::Flexible(mut v) => {
+                v.push(new);
+                Self::Flexible(v)
+            }
+        }
+    }
+
+    pub fn pop(&mut self) -> Option<T> {
+        match std::mem::take(self) {
+            Self::Empty => None,
+            Self::One([v1]) => {
+                *self = Self::Empty;
+                Some(v1)
+            }
+            Self::Two([v1, v2]) => {
+                *self = Self::One([v1]);
+                Some(v2)
+            }
+            Self::Flexible(mut v) => {
+                let out = v.pop();
+                *self = Self::Flexible(v);
+                out
+            }
+        }
+    }
+
+    pub fn clear(&mut self) {
+        if let Self::Flexible(mut v) = std::mem::take(self) {
+            v.clear();
+            *self = Self::Flexible(v);
+        } // else: self already eq Empty from the take
+    }
+
+    pub fn iter(&self) -> std::slice::Iter<'_, T> {
+        self.as_slice().iter()
+    }
+}
+
+impl<T> Default for SmallVec<T> {
+    fn default() -> Self {
+        Self::Empty
+    }
+}
+
+impl<T> Deref for SmallVec<T> {
+    type Target = [T];
+
+    fn deref(&self) -> &Self::Target {
+        self.as_slice()
+    }
+}
+
+impl<'a, T> IntoIterator for &'a SmallVec<T> {
+    type Item = &'a T;
+
+    type IntoIter = std::slice::Iter<'a, T>;
+
+    fn into_iter(self) -> Self::IntoIter {
+        self.iter()
+    }
+}
+
+impl<T: Eq> Eq for SmallVec<T> {}
+
+impl<T: PartialEq> PartialEq for SmallVec<T> {
+    fn eq(&self, other: &Self) -> bool {
+        self.as_slice() == other.as_slice()
+    }
+}
+
+impl<T: fmt::Debug> fmt::Debug for SmallVec<T> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        self.as_slice().fmt(f)
+    }
+}
+
+impl<T: Hash> Hash for SmallVec<T> {
+    fn hash<H: Hasher>(&self, state: &mut H) {
+        self.len().hash(state);
+        Hash::hash_slice(self.as_slice(), state);
+    }
+}
+
+#[cfg(feature = "serde")]
+impl<T: serde::Serialize> serde::Serialize for SmallVec<T> {
+    fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
+        serde::Serialize::serialize(self.as_slice(), s)
+    }
+}
+
+#[cfg(feature = "serde")]
+impl<'de, T: serde::Deserialize<'de>> serde::Deserialize<'de> for SmallVec<T> {
+    fn deserialize<D: serde::Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
+        struct SmallVecVisitor<T> {
+            marker: std::marker::PhantomData<T>,
+        }
+
+        impl<'de, T> serde::de::Visitor<'de> for SmallVecVisitor<T>
+        where
+            T: serde::Deserialize<'de>,
+        {
+            type Value = SmallVec<T>;
+
+            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+                formatter.write_str("a sequence")
+            }
+
+            fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
+            where
+                A: serde::de::SeqAccess<'de>,
+            {
+                let mut values = SmallVec::empty();
+                while let Some(value) = seq.next_element()? {
+                    values.push(value);
+                }
+                Ok(values)
+            }
+        }
+
+        let visitor = SmallVecVisitor {
+            marker: Default::default(),
+        };
+        d.deserialize_seq(visitor)
+    }
+}
+
+impl<T> IntoIterator for SmallVec<T> {
+    type Item = T;
+    type IntoIter = SmallVecIntoIter<T>;
+
+    fn into_iter(self) -> Self::IntoIter {
+        match self {
+            SmallVec::Empty => SmallVecIntoIter::Empty,
+            SmallVec::One(a) => SmallVecIntoIter::One(a.into_iter()),
+            SmallVec::Two(a) => SmallVecIntoIter::Two(a.into_iter()),
+            SmallVec::Flexible(v) => SmallVecIntoIter::Flexible(v.into_iter()),
+        }
+    }
+}
+
+pub enum SmallVecIntoIter<T> {
+    Empty,
+    One(<[T; 1] as IntoIterator>::IntoIter),
+    Two(<[T; 2] as IntoIterator>::IntoIter),
+    Flexible(<Vec<T> as IntoIterator>::IntoIter),
+}
+
+impl<T> Iterator for SmallVecIntoIter<T> {
+    type Item = T;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        match self {
+            SmallVecIntoIter::Empty => None,
+            SmallVecIntoIter::One(it) => it.next(),
+            SmallVecIntoIter::Two(it) => it.next(),
+            SmallVecIntoIter::Flexible(it) => it.next(),
+        }
+    }
+}
+
+// TESTS #######################################################################
+
+#[cfg(test)]
+pub mod tests {
+    use super::*;
+    use proptest::prelude::*;
+
+    proptest! {
+        #[test]
+        fn push_and_pop(commands: Vec<Option<u8>>) {
+            let mut v = vec![];
+            let mut sv = SmallVec::Empty;
+            for command in commands {
+                match command {
+                    Some(i) => {
+                        v.push(i);
+                        sv.push(i);
+                    }
+                    None => {
+                        assert_eq!(v.pop(), sv.pop());
+                    }
+                }
+                assert_eq!(v.as_slice(), sv.as_slice());
+            }
+        }
+    }
+}
+
\ No newline at end of file diff --git a/src/pubgrub/lib.rs.html b/src/pubgrub/lib.rs.html new file mode 100644 index 00000000..631e3097 --- /dev/null +++ b/src/pubgrub/lib.rs.html @@ -0,0 +1,473 @@ +lib.rs - source +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+
// SPDX-License-Identifier: MPL-2.0
+
+//! PubGrub version solving algorithm.
+//!
+//! Version solving consists in efficiently finding a set of packages and versions
+//! that satisfy all the constraints of a given project dependencies.
+//! In addition, when that is not possible,
+//! we should try to provide a very human-readable and clear
+//! explanation as to why that failed.
+//!
+//! # Package and Version traits
+//!
+//! All the code in this crate is manipulating packages and versions, and for this to work
+//! we defined a [Package](package::Package) and [Version](version::Version) traits
+//! that are used as bounds on most of the exposed types and functions.
+//!
+//! Package identifiers needs to implement our [Package](package::Package) trait,
+//! which is automatic if the type already implements
+//! [Clone] + [Eq] + [Hash] + [Debug] + [Display](std::fmt::Display).
+//! So things like [String] will work out of the box.
+//!
+//! Our [Version](version::Version) trait requires
+//! [Clone] + [Ord] + [Debug] + [Display](std::fmt::Display)
+//! and also the definition of two methods,
+//! [lowest() -> Self](version::Version::lowest) which returns the lowest version existing,
+//! and [bump(&self) -> Self](version::Version::bump) which returns the next smallest version
+//! strictly higher than the current one.
+//! For convenience, this library already provides
+//! two implementations of [Version](version::Version).
+//! The first one is [NumberVersion](version::NumberVersion), basically a newtype for [u32].
+//! The second one is [SemanticVersion](version::NumberVersion)
+//! that implements semantic versioning rules.
+//!
+//! # Basic example
+//!
+//! Let's imagine that we are building a user interface
+//! with a menu containing dropdowns with some icons,
+//! icons that we are also directly using in other parts of the interface.
+//! For this scenario our direct dependencies are `menu` and `icons`,
+//! but the complete set of dependencies looks like follows:
+//!
+//! - `root` depends on `menu` and `icons`
+//! - `menu` depends on `dropdown`
+//! - `dropdown` depends on `icons`
+//! - `icons` has no dependency
+//!
+//! We can model that scenario with this library as follows
+//! ```
+//! # use pubgrub::solver::{OfflineDependencyProvider, resolve};
+//! # use pubgrub::version::NumberVersion;
+//! # use pubgrub::range::Range;
+//!
+//! type NumVS = Range<NumberVersion>;
+//!
+//! let mut dependency_provider = OfflineDependencyProvider::<&str, NumVS>::new();
+//!
+//! dependency_provider.add_dependencies(
+//!     "root", 1, [("menu", Range::full()), ("icons", Range::full())],
+//! );
+//! dependency_provider.add_dependencies("menu", 1, [("dropdown", Range::full())]);
+//! dependency_provider.add_dependencies("dropdown", 1, [("icons", Range::full())]);
+//! dependency_provider.add_dependencies("icons", 1, []);
+//!
+//! // Run the algorithm.
+//! let solution = resolve(&dependency_provider, "root", 1).unwrap();
+//! ```
+//!
+//! # DependencyProvider trait
+//!
+//! In our previous example we used the
+//! [OfflineDependencyProvider](solver::OfflineDependencyProvider),
+//! which is a basic implementation of the [DependencyProvider](solver::DependencyProvider) trait.
+//!
+//! But we might want to implement the [DependencyProvider](solver::DependencyProvider)
+//! trait for our own type.
+//! Let's say that we will use [String] for packages,
+//! and [SemanticVersion](version::SemanticVersion) for versions.
+//! This may be done quite easily by implementing the three following functions.
+//! ```
+//! # use pubgrub::solver::{DependencyProvider, Dependencies};
+//! # use pubgrub::version::SemanticVersion;
+//! # use pubgrub::range::Range;
+//! # use pubgrub::type_aliases::Map;
+//! # use std::error::Error;
+//! # use std::borrow::Borrow;
+//! # use std::convert::Infallible;
+//! #
+//! # struct MyDependencyProvider;
+//! #
+//! type SemVS = Range<SemanticVersion>;
+//!
+//! impl DependencyProvider<String, SemVS> for MyDependencyProvider {
+//!     fn choose_version(&self, package: &String, range: &SemVS) -> Result<Option<SemanticVersion>, Infallible> {
+//!         unimplemented!()
+//!     }
+//!
+//!     type Priority = usize;
+//!     fn prioritize(&self, package: &String, range: &SemVS) -> Self::Priority {
+//!         unimplemented!()
+//!     }
+//!
+//!     fn get_dependencies(
+//!         &self,
+//!         package: &String,
+//!         version: &SemanticVersion,
+//!     ) -> Result<Dependencies<String, SemVS>, Infallible> {
+//!         unimplemented!()
+//!     }
+//!
+//!     type Err = Infallible;
+//! }
+//! ```
+//!
+//! The first method
+//! [choose_version](crate::solver::DependencyProvider::choose_version)
+//! chooses a version compatible with the provided range for a package.
+//! The second method
+//! [prioritize](crate::solver::DependencyProvider::prioritize)
+//! in which order different packages should be chosen.
+//! Usually prioritizing packages
+//! with the fewest number of compatible versions speeds up resolution.
+//! But in general you are free to employ whatever strategy suits you best
+//! to pick a package and a version.
+//!
+//! The third method [get_dependencies](crate::solver::DependencyProvider::get_dependencies)
+//! aims at retrieving the dependencies of a given package at a given version.
+//! Returns [None] if dependencies are unknown.
+//!
+//! In a real scenario, these two methods may involve reading the file system
+//! or doing network request, so you may want to hold a cache in your
+//! [DependencyProvider](solver::DependencyProvider) implementation.
+//! How exactly this could be achieved is shown in `CachingDependencyProvider`
+//! (see `examples/caching_dependency_provider.rs`).
+//! You could also use the [OfflineDependencyProvider](solver::OfflineDependencyProvider)
+//! type defined by the crate as guidance,
+//! but you are free to use whatever approach makes sense in your situation.
+//!
+//! # Solution and error reporting
+//!
+//! When everything goes well, the algorithm finds and returns the complete
+//! set of direct and indirect dependencies satisfying all the constraints.
+//! The packages and versions selected are returned as
+//! [SelectedDepedencies<P, V>](type_aliases::SelectedDependencies).
+//! But sometimes there is no solution because dependencies are incompatible.
+//! In such cases, [resolve(...)](solver::resolve) returns a
+//! [PubGrubError::NoSolution(derivation_tree)](error::PubGrubError::NoSolution),
+//! where the provided derivation tree is a custom binary tree
+//! containing the full chain of reasons why there is no solution.
+//!
+//! All the items in the tree are called incompatibilities
+//! and may be of two types, either "external" or "derived".
+//! Leaves of the tree are external incompatibilities,
+//! and nodes are derived.
+//! External incompatibilities have reasons that are independent
+//! of the way this algorithm is implemented such as
+//!  - dependencies: "package_a" at version 1 depends on "package_b" at version 4
+//!  - missing dependencies: dependencies of "package_a" are unknown
+//!  - absence of version: there is no version of "package_a" in the range [3.1.0  4.0.0[
+//!
+//! Derived incompatibilities are obtained during the algorithm execution by deduction,
+//! such as if "a" depends on "b" and "b" depends on "c", "a" depends on "c".
+//!
+//! This crate defines a [Reporter](crate::report::Reporter) trait, with an associated
+//! [Output](crate::report::Reporter::Output) type and a single method.
+//! ```
+//! # use pubgrub::package::Package;
+//! # use pubgrub::version_set::VersionSet;
+//! # use pubgrub::report::DerivationTree;
+//! #
+//! pub trait Reporter<P: Package, VS: VersionSet> {
+//!     type Output;
+//!
+//!     fn report(derivation_tree: &DerivationTree<P, VS>) -> Self::Output;
+//! }
+//! ```
+//! Implementing a [Reporter](crate::report::Reporter) may involve a lot of heuristics
+//! to make the output human-readable and natural.
+//! For convenience, we provide a default implementation
+//! [DefaultStringReporter](crate::report::DefaultStringReporter)
+//! that outputs the report as a [String].
+//! You may use it as follows:
+//! ```
+//! # use pubgrub::solver::{resolve, OfflineDependencyProvider};
+//! # use pubgrub::report::{DefaultStringReporter, Reporter};
+//! # use pubgrub::error::PubGrubError;
+//! # use pubgrub::version::NumberVersion;
+//! # use pubgrub::range::Range;
+//! #
+//! # type NumVS = Range<NumberVersion>;
+//! #
+//! # let dependency_provider = OfflineDependencyProvider::<&str, NumVS>::new();
+//! # let root_package = "root";
+//! # let root_version = 1;
+//! #
+//! match resolve(&dependency_provider, root_package, root_version) {
+//!     Ok(solution) => println!("{:?}", solution),
+//!     Err(PubGrubError::NoSolution(mut derivation_tree)) => {
+//!         derivation_tree.collapse_no_versions();
+//!         eprintln!("{}", DefaultStringReporter::report(&derivation_tree));
+//!     }
+//!     Err(err) => panic!("{:?}", err),
+//! };
+//! ```
+//! Notice that we also used
+//! [collapse_no_versions()](crate::report::DerivationTree::collapse_no_versions) above.
+//! This method simplifies the derivation tree to get rid of the
+//! [NoVersions](crate::report::External::NoVersions)
+//! external incompatibilities in the derivation tree.
+//! So instead of seeing things like this in the report:
+//! ```txt
+//! Because there is no version of foo in 1.0.1 <= v < 2.0.0
+//! and foo 1.0.0 depends on bar 2.0.0 <= v < 3.0.0,
+//! foo 1.0.0 <= v < 2.0.0 depends on bar 2.0.0 <= v < 3.0.0.
+//! ```
+//! you may have directly:
+//! ```txt
+//! foo 1.0.0 <= v < 2.0.0 depends on bar 2.0.0 <= v < 3.0.0.
+//! ```
+//! Beware though that if you are using some kind of offline mode
+//! with a cache, you may want to know that some versions
+//! do not exist in your cache.
+
+#![warn(missing_docs)]
+
+pub mod error;
+pub mod package;
+pub mod range;
+pub mod report;
+pub mod solver;
+pub mod term;
+pub mod type_aliases;
+pub mod version;
+pub mod version_set;
+
+mod internal;
+
\ No newline at end of file diff --git a/src/pubgrub/package.rs.html b/src/pubgrub/package.rs.html new file mode 100644 index 00000000..bc1966eb --- /dev/null +++ b/src/pubgrub/package.rs.html @@ -0,0 +1,37 @@ +package.rs - source +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+
// SPDX-License-Identifier: MPL-2.0
+
+//! Trait for identifying packages.
+//! Automatically implemented for traits implementing
+//! [Clone] + [Eq] + [Hash] + [Debug] + [Display].
+
+use std::fmt::{Debug, Display};
+use std::hash::Hash;
+
+/// Trait for identifying packages.
+/// Automatically implemented for types already implementing
+/// [Clone] + [Eq] + [Hash] + [Debug] + [Display].
+pub trait Package: Clone + Eq + Hash + Debug + Display {}
+
+/// Automatically implement the Package trait for any type
+/// that already implement [Clone] + [Eq] + [Hash] + [Debug] + [Display].
+impl<T: Clone + Eq + Hash + Debug + Display> Package for T {}
+
\ No newline at end of file diff --git a/src/pubgrub/range.rs.html b/src/pubgrub/range.rs.html new file mode 100644 index 00000000..67a00269 --- /dev/null +++ b/src/pubgrub/range.rs.html @@ -0,0 +1,1547 @@ +range.rs - source +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
+479
+480
+481
+482
+483
+484
+485
+486
+487
+488
+489
+490
+491
+492
+493
+494
+495
+496
+497
+498
+499
+500
+501
+502
+503
+504
+505
+506
+507
+508
+509
+510
+511
+512
+513
+514
+515
+516
+517
+518
+519
+520
+521
+522
+523
+524
+525
+526
+527
+528
+529
+530
+531
+532
+533
+534
+535
+536
+537
+538
+539
+540
+541
+542
+543
+544
+545
+546
+547
+548
+549
+550
+551
+552
+553
+554
+555
+556
+557
+558
+559
+560
+561
+562
+563
+564
+565
+566
+567
+568
+569
+570
+571
+572
+573
+574
+575
+576
+577
+578
+579
+580
+581
+582
+583
+584
+585
+586
+587
+588
+589
+590
+591
+592
+593
+594
+595
+596
+597
+598
+599
+600
+601
+602
+603
+604
+605
+606
+607
+608
+609
+610
+611
+612
+613
+614
+615
+616
+617
+618
+619
+620
+621
+622
+623
+624
+625
+626
+627
+628
+629
+630
+631
+632
+633
+634
+635
+636
+637
+638
+639
+640
+641
+642
+643
+644
+645
+646
+647
+648
+649
+650
+651
+652
+653
+654
+655
+656
+657
+658
+659
+660
+661
+662
+663
+664
+665
+666
+667
+668
+669
+670
+671
+672
+673
+674
+675
+676
+677
+678
+679
+680
+681
+682
+683
+684
+685
+686
+687
+688
+689
+690
+691
+692
+693
+694
+695
+696
+697
+698
+699
+700
+701
+702
+703
+704
+705
+706
+707
+708
+709
+710
+711
+712
+713
+714
+715
+716
+717
+718
+719
+720
+721
+722
+723
+724
+725
+726
+727
+728
+729
+730
+731
+732
+733
+734
+735
+736
+737
+738
+739
+740
+741
+742
+743
+744
+745
+746
+747
+748
+749
+750
+751
+752
+753
+754
+755
+756
+757
+758
+759
+760
+761
+762
+763
+764
+765
+766
+767
+768
+769
+770
+771
+772
+
// SPDX-License-Identifier: MPL-2.0
+
+//! Ranges are constraints defining sets of versions.
+//!
+//! Concretely, those constraints correspond to any set of versions
+//! representable as the concatenation, union, and complement
+//! of the ranges building blocks.
+//!
+//! Those building blocks are:
+//!  - [empty()](Range::empty): the empty set
+//!  - [full()](Range::full): the set of all possible versions
+//!  - [singleton(v)](Range::singleton): the set containing only the version v
+//!  - [higher_than(v)](Range::higher_than): the set defined by `v <= versions`
+//!  - [strictly_higher_than(v)](Range::strictly_higher_than): the set defined by `v < versions`
+//!  - [lower_than(v)](Range::lower_than): the set defined by `versions <= v`
+//!  - [strictly_lower_than(v)](Range::strictly_lower_than): the set defined by `versions < v`
+//!  - [between(v1, v2)](Range::between): the set defined by `v1 <= versions < v2`
+//!
+//! Ranges can be created from any type that implements [`Ord`] + [`Clone`].
+//!
+//! In order to advance the solver front, comparisons of versions sets are necessary in the algorithm.
+//! To do those comparisons between two sets S1 and S2 we use the mathematical property that S1 ⊂ S2 if and only if S1 ∩ S2 == S1.
+//! We can thus compute an intersection and evaluate an equality to answer if S1 is a subset of S2.
+//! But this means that the implementation of equality must be correct semantically.
+//! In practice, if equality is derived automatically, this means sets must have unique representations.
+//!
+//! By migrating from a custom representation for discrete sets in v0.2
+//! to a generic bounded representation for continuous sets in v0.3
+//! we are potentially breaking that assumption in two ways:
+//!
+//!  1. Minimal and maximal `Unbounded` values can be replaced by their equivalent if it exists.
+//!  2. Simplifying adjacent bounds of discrete sets cannot be detected and automated in the generic intersection code.
+//!
+//! An example for each can be given when `T` is `u32`.
+//! First, we can have both segments `S1 = (Unbounded, Included(42u32))` and `S2 = (Included(0), Included(42u32))`
+//! that represent the same segment but are structurally different.
+//! Thus, a derived equality check would answer `false` to `S1 == S2` while it's true.
+//!
+//! Second both segments `S1 = (Included(1), Included(5))` and `S2 = (Included(1), Included(3)) + (Included(4), Included(5))` are equal.
+//! But without asking the user to provide a `bump` function for discrete sets,
+//! the algorithm is not able tell that the space between the right `Included(3)` bound and the left `Included(4)` bound is empty.
+//! Thus the algorithm is not able to reduce S2 to its canonical S1 form while computing sets operations like intersections in the generic code.
+//!
+//! This is likely to lead to user facing theoretically correct but practically nonsensical ranges,
+//! like (Unbounded, Excluded(0)) or (Excluded(6), Excluded(7)).
+//! In general nonsensical inputs often lead to hard to track bugs.
+//! But as far as we can tell this should work in practice.
+//! So for now this crate only provides an implementation for continuous ranges.
+//! With the v0.3 api the user could choose to bring back the discrete implementation from v0.2, as documented in the guide.
+//! If doing so regularly fixes bugs seen by users, we will bring it back into the core library.
+//! If we do not see practical bugs, or we get a formal proof that the code cannot lead to error states, then we may remove this warning.
+
+use crate::{internal::small_vec::SmallVec, version_set::VersionSet};
+use std::cmp::Ordering;
+use std::ops::RangeBounds;
+use std::{
+    fmt::{Debug, Display, Formatter},
+    ops::Bound::{self, Excluded, Included, Unbounded},
+};
+
+/// A Range represents multiple intervals of a continuous range of monotone increasing
+/// values.
+#[derive(Debug, Clone, Eq, PartialEq, Hash)]
+#[cfg_attr(feature = "serde", derive(serde::Serialize))]
+#[cfg_attr(feature = "serde", serde(transparent))]
+pub struct Range<V> {
+    segments: SmallVec<Interval<V>>,
+}
+
+type Interval<V> = (Bound<V>, Bound<V>);
+
+impl<V> Range<V> {
+    /// Empty set of versions.
+    pub fn empty() -> Self {
+        Self {
+            segments: SmallVec::empty(),
+        }
+    }
+
+    /// Set of all possible versions
+    pub fn full() -> Self {
+        Self {
+            segments: SmallVec::one((Unbounded, Unbounded)),
+        }
+    }
+
+    /// Set of all versions higher or equal to some version
+    pub fn higher_than(v: impl Into<V>) -> Self {
+        Self {
+            segments: SmallVec::one((Included(v.into()), Unbounded)),
+        }
+    }
+
+    /// Set of all versions higher to some version
+    pub fn strictly_higher_than(v: impl Into<V>) -> Self {
+        Self {
+            segments: SmallVec::one((Excluded(v.into()), Unbounded)),
+        }
+    }
+
+    /// Set of all versions lower to some version
+    pub fn strictly_lower_than(v: impl Into<V>) -> Self {
+        Self {
+            segments: SmallVec::one((Unbounded, Excluded(v.into()))),
+        }
+    }
+
+    /// Set of all versions lower or equal to some version
+    pub fn lower_than(v: impl Into<V>) -> Self {
+        Self {
+            segments: SmallVec::one((Unbounded, Included(v.into()))),
+        }
+    }
+
+    /// Set of versions greater or equal to `v1` but less than `v2`.
+    pub fn between(v1: impl Into<V>, v2: impl Into<V>) -> Self {
+        Self {
+            segments: SmallVec::one((Included(v1.into()), Excluded(v2.into()))),
+        }
+    }
+}
+
+impl<V: Clone> Range<V> {
+    /// Set containing exactly one version
+    pub fn singleton(v: impl Into<V>) -> Self {
+        let v = v.into();
+        Self {
+            segments: SmallVec::one((Included(v.clone()), Included(v))),
+        }
+    }
+
+    /// Returns the complement of this Range.
+    pub fn complement(&self) -> Self {
+        match self.segments.first() {
+            // Complement of ∅ is ∞
+            None => Self::full(),
+
+            // Complement of ∞ is ∅
+            Some((Unbounded, Unbounded)) => Self::empty(),
+
+            // First high bound is +∞
+            Some((Included(v), Unbounded)) => Self::strictly_lower_than(v.clone()),
+            Some((Excluded(v), Unbounded)) => Self::lower_than(v.clone()),
+
+            Some((Unbounded, Included(v))) => {
+                Self::negate_segments(Excluded(v.clone()), &self.segments[1..])
+            }
+            Some((Unbounded, Excluded(v))) => {
+                Self::negate_segments(Included(v.clone()), &self.segments[1..])
+            }
+            Some((Included(_), Included(_)))
+            | Some((Included(_), Excluded(_)))
+            | Some((Excluded(_), Included(_)))
+            | Some((Excluded(_), Excluded(_))) => Self::negate_segments(Unbounded, &self.segments),
+        }
+    }
+
+    /// Helper function performing the negation of intervals in segments.
+    fn negate_segments(start: Bound<V>, segments: &[Interval<V>]) -> Self {
+        let mut complement_segments: SmallVec<Interval<V>> = SmallVec::empty();
+        let mut start = start;
+        for (v1, v2) in segments {
+            complement_segments.push((
+                start,
+                match v1 {
+                    Included(v) => Excluded(v.clone()),
+                    Excluded(v) => Included(v.clone()),
+                    Unbounded => unreachable!(),
+                },
+            ));
+            start = match v2 {
+                Included(v) => Excluded(v.clone()),
+                Excluded(v) => Included(v.clone()),
+                Unbounded => Unbounded,
+            }
+        }
+        if !matches!(start, Unbounded) {
+            complement_segments.push((start, Unbounded));
+        }
+
+        Self {
+            segments: complement_segments,
+        }
+    }
+}
+
+impl<V: Ord> Range<V> {
+    /// Convert to something that can be used with
+    /// [BTreeMap::range](std::collections::BTreeMap::range).
+    /// All versions contained in self, will be in the output,
+    /// but there may be versions in the output that are not contained in self.
+    /// Returns None if the range is empty.
+    pub fn bounding_range(&self) -> Option<(Bound<&V>, Bound<&V>)> {
+        self.segments.first().map(|(start, _)| {
+            let end = self
+                .segments
+                .last()
+                .expect("if there is a first element, there must be a last element");
+            (start.as_ref(), end.1.as_ref())
+        })
+    }
+
+    /// Returns true if the this Range contains the specified value.
+    pub fn contains(&self, v: &V) -> bool {
+        for segment in self.segments.iter() {
+            match within_bounds(v, segment) {
+                Ordering::Less => return false,
+                Ordering::Equal => return true,
+                Ordering::Greater => (),
+            }
+        }
+        false
+    }
+
+    /// Returns true if the this Range contains the specified values.
+    ///
+    /// The `versions` iterator must be sorted.
+    /// Functionally equivalent to `versions.map(|v| self.contains(v))`.
+    /// Except it runs in `O(size_of_range + len_of_versions)` not `O(size_of_range * len_of_versions)`
+    pub fn contains_many<'s, I>(&'s self, versions: I) -> impl Iterator<Item = bool> + 's
+    where
+        I: Iterator<Item = &'s V> + 's,
+        V: 's,
+    {
+        versions.scan(0, move |i, v| {
+            while let Some(segment) = self.segments.get(*i) {
+                match within_bounds(v, segment) {
+                    Ordering::Less => return Some(false),
+                    Ordering::Equal => return Some(true),
+                    Ordering::Greater => *i += 1,
+                }
+            }
+            Some(false)
+        })
+    }
+
+    /// Construct a simple range from anything that impls [RangeBounds] like `v1..v2`.
+    pub fn from_range_bounds<R, IV>(bounds: R) -> Self
+    where
+        R: RangeBounds<IV>,
+        IV: Clone + Into<V>,
+    {
+        let start = match bounds.start_bound() {
+            Included(v) => Included(v.clone().into()),
+            Excluded(v) => Excluded(v.clone().into()),
+            Unbounded => Unbounded,
+        };
+        let end = match bounds.end_bound() {
+            Included(v) => Included(v.clone().into()),
+            Excluded(v) => Excluded(v.clone().into()),
+            Unbounded => Unbounded,
+        };
+        if valid_segment(&start, &end) {
+            Self {
+                segments: SmallVec::one((start, end)),
+            }
+        } else {
+            Self::empty()
+        }
+    }
+
+    fn check_invariants(self) -> Self {
+        if cfg!(debug_assertions) {
+            for p in self.segments.as_slice().windows(2) {
+                match (&p[0].1, &p[1].0) {
+                    (Included(l_end), Included(r_start)) => assert!(l_end < r_start),
+                    (Included(l_end), Excluded(r_start)) => assert!(l_end < r_start),
+                    (Excluded(l_end), Included(r_start)) => assert!(l_end < r_start),
+                    (Excluded(l_end), Excluded(r_start)) => assert!(l_end <= r_start),
+                    (_, Unbounded) => panic!(),
+                    (Unbounded, _) => panic!(),
+                }
+            }
+            for (s, e) in self.segments.iter() {
+                assert!(valid_segment(s, e));
+            }
+        }
+        self
+    }
+}
+
+fn within_bounds<V: PartialOrd>(v: &V, segment: &Interval<V>) -> Ordering {
+    let below_lower_bound = match segment {
+        (Excluded(start), _) => v <= start,
+        (Included(start), _) => v < start,
+        (Unbounded, _) => false,
+    };
+    if below_lower_bound {
+        return Ordering::Less;
+    }
+    let below_upper_bound = match segment {
+        (_, Unbounded) => true,
+        (_, Included(end)) => v <= end,
+        (_, Excluded(end)) => v < end,
+    };
+    if below_upper_bound {
+        return Ordering::Equal;
+    }
+    Ordering::Greater
+}
+
+fn valid_segment<T: PartialOrd>(start: &Bound<T>, end: &Bound<T>) -> bool {
+    match (start, end) {
+        (Included(s), Included(e)) => s <= e,
+        (Included(s), Excluded(e)) => s < e,
+        (Excluded(s), Included(e)) => s < e,
+        (Excluded(s), Excluded(e)) => s < e,
+        (Unbounded, _) | (_, Unbounded) => true,
+    }
+}
+
+/// Group adjacent versions locations.
+///
+/// ```text
+/// [None, 3, 6, 7, None] -> [(3, 7)]
+/// [3, 6, 7, None] -> [(None, 7)]
+/// [3, 6, 7] -> [(None, None)]
+/// [None, 1, 4, 7, None, None, None, 8, None, 9] -> [(1, 7), (8, 8), (9, None)]
+/// ```
+fn group_adjacent_locations(
+    mut locations: impl Iterator<Item = Option<usize>>,
+) -> impl Iterator<Item = (Option<usize>, Option<usize>)> {
+    // If the first version matched, then the lower bound of that segment is not needed
+    let mut seg = locations.next().flatten().map(|ver| (None, Some(ver)));
+    std::iter::from_fn(move || {
+        for ver in locations.by_ref() {
+            if let Some(ver) = ver {
+                // As long as were still matching versions, we keep merging into the currently matching segment
+                seg = Some((seg.map_or(Some(ver), |(s, _)| s), Some(ver)));
+            } else {
+                // If we have found a version that doesn't match, then right the merge segment and prepare for a new one.
+                if seg.is_some() {
+                    return seg.take();
+                }
+            }
+        }
+        // If the last version matched, then write out the merged segment but the upper bound is not needed.
+        seg.take().map(|(s, _)| (s, None))
+    })
+}
+
+impl<V: Ord + Clone> Range<V> {
+    /// Computes the union of this `Range` and another.
+    pub fn union(&self, other: &Self) -> Self {
+        self.complement()
+            .intersection(&other.complement())
+            .complement()
+            .check_invariants()
+    }
+
+    /// Computes the intersection of two sets of versions.
+    pub fn intersection(&self, other: &Self) -> Self {
+        let mut output: SmallVec<Interval<V>> = SmallVec::empty();
+        let mut left_iter = self.segments.iter().peekable();
+        let mut right_iter = other.segments.iter().peekable();
+        // By the definition of intersection any point that is matched by the output
+        // must have a segment in each of the inputs that it matches.
+        // Therefore, every segment in the output must be the intersection of a segment from each of the inputs.
+        // It would be correct to do the "O(n^2)" thing, by computing the intersection of every segment from one input
+        // with every segment of the other input, and sorting the result.
+        // We can avoid the sorting by generating our candidate segments with an increasing `end` value.
+        while let Some(((left_start, left_end), (right_start, right_end))) =
+            left_iter.peek().zip(right_iter.peek())
+        {
+            // The next smallest `end` value is going to come from one of the inputs.
+            let left_end_is_smaller = match (left_end, right_end) {
+                (Included(l), Included(r))
+                | (Excluded(l), Excluded(r))
+                | (Excluded(l), Included(r)) => l <= r,
+
+                (Included(l), Excluded(r)) => l < r,
+                (_, Unbounded) => true,
+                (Unbounded, _) => false,
+            };
+            // Now that we are processing `end` we will never have to process any segment smaller than that.
+            // We can ensure that the input that `end` came from is larger than `end` by advancing it one step.
+            // `end` is the smaller available input, so we know the other input is already larger than `end`.
+            // Note: We can call `other_iter.next_if( == end)`, but the ends lining up is rare enough that
+            // it does not end up being faster in practice.
+            let (other_start, end) = if left_end_is_smaller {
+                left_iter.next();
+                (right_start, left_end)
+            } else {
+                right_iter.next();
+                (left_start, right_end)
+            };
+            // `start` will either come from the input `end` came from or the other input, whichever one is larger.
+            // The intersection is invalid if `start` > `end`.
+            // But, we already know that the segments in our input are valid.
+            // So we do not need to check if the `start`  from the input `end` came from is smaller then `end`.
+            // If the `other_start` is larger than end, then the intersection will be invalid.
+            if !valid_segment(other_start, end) {
+                // Note: We can call `this_iter.next_if(!valid_segment(other_start, this_end))` in a loop.
+                // But the checks make it slower for the benchmarked inputs.
+                continue;
+            }
+            let start = match (left_start, right_start) {
+                (Included(l), Included(r)) => Included(std::cmp::max(l, r)),
+                (Excluded(l), Excluded(r)) => Excluded(std::cmp::max(l, r)),
+
+                (Included(i), Excluded(e)) | (Excluded(e), Included(i)) => {
+                    if i <= e {
+                        Excluded(e)
+                    } else {
+                        Included(i)
+                    }
+                }
+                (s, Unbounded) | (Unbounded, s) => s.as_ref(),
+            };
+            // Now we clone and push a new segment.
+            // By dealing with references until now we ensure that NO cloning happens when we reject the segment.
+            output.push((start.cloned(), end.clone()))
+        }
+
+        Self { segments: output }.check_invariants()
+    }
+
+    /// Returns a simpler Range that contains the same versions
+    ///
+    /// For every one of the Versions provided in versions the existing range and
+    /// the simplified range will agree on whether it is contained.
+    /// The simplified version may include or exclude versions that are not in versions as the implementation wishes.
+    /// For example:
+    ///  - If all the versions are contained in the original than the range will be simplified to `full`.
+    ///  - If none of the versions are contained in the original than the range will be simplified to `empty`.
+    ///
+    /// If versions are not sorted the correctness of this function is not guaranteed.
+    pub fn simplify<'v, I>(&self, versions: I) -> Self
+    where
+        I: Iterator<Item = &'v V> + 'v,
+        V: 'v,
+    {
+        // Return the segment index in the range for each version in the range, None otherwise
+        let version_locations = versions.scan(0, move |i, v| {
+            while let Some(segment) = self.segments.get(*i) {
+                match within_bounds(v, segment) {
+                    Ordering::Less => return Some(None),
+                    Ordering::Equal => return Some(Some(*i)),
+                    Ordering::Greater => *i += 1,
+                }
+            }
+            Some(None)
+        });
+        let kept_segments = group_adjacent_locations(version_locations);
+        self.keep_segments(kept_segments)
+    }
+
+    /// Create a new range with a subset of segments at given location bounds.
+    ///
+    /// Each new segment is constructed from a pair of segments, taking the
+    /// start of the first and the end of the second.
+    fn keep_segments(
+        &self,
+        kept_segments: impl Iterator<Item = (Option<usize>, Option<usize>)>,
+    ) -> Range<V> {
+        let mut segments = SmallVec::Empty;
+        for (s, e) in kept_segments {
+            segments.push((
+                s.map_or(Unbounded, |s| self.segments[s].0.clone()),
+                e.map_or(Unbounded, |e| self.segments[e].1.clone()),
+            ));
+        }
+        Self { segments }.check_invariants()
+    }
+}
+
+impl<T: Debug + Display + Clone + Eq + Ord> VersionSet for Range<T> {
+    type V = T;
+
+    fn empty() -> Self {
+        Range::empty()
+    }
+
+    fn singleton(v: Self::V) -> Self {
+        Range::singleton(v)
+    }
+
+    fn complement(&self) -> Self {
+        Range::complement(self)
+    }
+
+    fn intersection(&self, other: &Self) -> Self {
+        Range::intersection(self, other)
+    }
+
+    fn contains(&self, v: &Self::V) -> bool {
+        Range::contains(self, v)
+    }
+
+    fn full() -> Self {
+        Range::full()
+    }
+
+    fn union(&self, other: &Self) -> Self {
+        Range::union(self, other)
+    }
+}
+
+// REPORT ######################################################################
+
+impl<V: Display + Eq> Display for Range<V> {
+    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
+        if self.segments.is_empty() {
+            write!(f, "∅")?;
+        } else {
+            for (idx, segment) in self.segments.iter().enumerate() {
+                if idx > 0 {
+                    write!(f, " | ")?;
+                }
+                match segment {
+                    (Unbounded, Unbounded) => write!(f, "*")?,
+                    (Unbounded, Included(v)) => write!(f, "<={v}")?,
+                    (Unbounded, Excluded(v)) => write!(f, "<{v}")?,
+                    (Included(v), Unbounded) => write!(f, ">={v}")?,
+                    (Included(v), Included(b)) => {
+                        if v == b {
+                            write!(f, "{v}")?
+                        } else {
+                            write!(f, ">={v}, <={b}")?
+                        }
+                    }
+                    (Included(v), Excluded(b)) => write!(f, ">={v}, <{b}")?,
+                    (Excluded(v), Unbounded) => write!(f, ">{v}")?,
+                    (Excluded(v), Included(b)) => write!(f, ">{v}, <={b}")?,
+                    (Excluded(v), Excluded(b)) => write!(f, ">{v}, <{b}")?,
+                };
+            }
+        }
+        Ok(())
+    }
+}
+
+// SERIALIZATION ###############################################################
+
+#[cfg(feature = "serde")]
+impl<'de, V: serde::Deserialize<'de>> serde::Deserialize<'de> for Range<V> {
+    fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
+        // This enables conversion from the "old" discrete implementation of `Range` to the new
+        // bounded one.
+        //
+        // Serialization is always performed in the new format.
+        #[derive(serde::Deserialize)]
+        #[serde(untagged)]
+        enum EitherInterval<V> {
+            B(Bound<V>, Bound<V>),
+            D(V, Option<V>),
+        }
+
+        let bounds: SmallVec<EitherInterval<V>> = serde::Deserialize::deserialize(deserializer)?;
+
+        let mut segments = SmallVec::Empty;
+        for i in bounds {
+            match i {
+                EitherInterval::B(l, r) => segments.push((l, r)),
+                EitherInterval::D(l, Some(r)) => segments.push((Included(l), Excluded(r))),
+                EitherInterval::D(l, None) => segments.push((Included(l), Unbounded)),
+            }
+        }
+
+        Ok(Range { segments })
+    }
+}
+
+// TESTS #######################################################################
+
+#[cfg(test)]
+pub mod tests {
+    use proptest::prelude::*;
+
+    use super::*;
+
+    /// Generate version sets from a random vector of deltas between bounds.
+    /// Each bound is randomly inclusive or exclusive.
+    pub fn strategy() -> impl Strategy<Value = Range<u32>> {
+        (
+            any::<bool>(),
+            prop::collection::vec(any::<(u32, bool)>(), 1..10),
+        )
+            .prop_map(|(start_unbounded, deltas)| {
+                let mut start = if start_unbounded {
+                    Some(Unbounded)
+                } else {
+                    None
+                };
+                let mut largest: u32 = 0;
+                let mut last_bound_was_inclusive = false;
+                let mut segments = SmallVec::Empty;
+                for (delta, inclusive) in deltas {
+                    // Add the offset to the current bound
+                    largest = match largest.checked_add(delta) {
+                        Some(s) => s,
+                        None => {
+                            // Skip this offset, if it would result in a too large bound.
+                            continue;
+                        }
+                    };
+
+                    let current_bound = if inclusive {
+                        Included(largest)
+                    } else {
+                        Excluded(largest)
+                    };
+
+                    // If we already have a start bound, the next offset defines the complete range.
+                    // If we don't have a start bound, we have to generate one.
+                    if let Some(start_bound) = start.take() {
+                        // If the delta from the start bound is 0, the only authorized configuration is
+                        // Included(x), Included(x)
+                        if delta == 0 && !(matches!(start_bound, Included(_)) && inclusive) {
+                            start = Some(start_bound);
+                            continue;
+                        }
+                        last_bound_was_inclusive = inclusive;
+                        segments.push((start_bound, current_bound));
+                    } else {
+                        // If the delta from the end bound of the last range is 0 and
+                        // any of the last ending or current starting bound is inclusive,
+                        // we skip the delta because they basically overlap.
+                        if delta == 0 && (last_bound_was_inclusive || inclusive) {
+                            continue;
+                        }
+                        start = Some(current_bound);
+                    }
+                }
+
+                // If we still have a start bound, but didn't have enough deltas to complete another
+                // segment, we add an unbounded upperbound.
+                if let Some(start_bound) = start {
+                    segments.push((start_bound, Unbounded));
+                }
+
+                Range { segments }.check_invariants()
+            })
+    }
+
+    fn version_strat() -> impl Strategy<Value = u32> {
+        any::<u32>()
+    }
+
+    proptest! {
+
+        // Testing negate ----------------------------------
+
+        #[test]
+        fn negate_is_different(range in strategy()) {
+            assert_ne!(range.complement(), range);
+        }
+
+        #[test]
+        fn double_negate_is_identity(range in strategy()) {
+            assert_eq!(range.complement().complement(), range);
+        }
+
+        #[test]
+        fn negate_contains_opposite(range in strategy(), version in version_strat()) {
+            assert_ne!(range.contains(&version), range.complement().contains(&version));
+        }
+
+        // Testing intersection ----------------------------
+
+        #[test]
+        fn intersection_is_symmetric(r1 in strategy(), r2 in strategy()) {
+            assert_eq!(r1.intersection(&r2), r2.intersection(&r1));
+        }
+
+        #[test]
+        fn intersection_with_any_is_identity(range in strategy()) {
+            assert_eq!(Range::full().intersection(&range), range);
+        }
+
+        #[test]
+        fn intersection_with_none_is_none(range in strategy()) {
+            assert_eq!(Range::empty().intersection(&range), Range::empty());
+        }
+
+        #[test]
+        fn intersection_is_idempotent(r1 in strategy(), r2 in strategy()) {
+            assert_eq!(r1.intersection(&r2).intersection(&r2), r1.intersection(&r2));
+        }
+
+        #[test]
+        fn intersection_is_associative(r1 in strategy(), r2 in strategy(), r3 in strategy()) {
+            assert_eq!(r1.intersection(&r2).intersection(&r3), r1.intersection(&r2.intersection(&r3)));
+        }
+
+        #[test]
+        fn intesection_of_complements_is_none(range in strategy()) {
+            assert_eq!(range.complement().intersection(&range), Range::empty());
+        }
+
+        #[test]
+        fn intesection_contains_both(r1 in strategy(), r2 in strategy(), version in version_strat()) {
+            assert_eq!(r1.intersection(&r2).contains(&version), r1.contains(&version) && r2.contains(&version));
+        }
+
+        // Testing union -----------------------------------
+
+        #[test]
+        fn union_of_complements_is_any(range in strategy()) {
+            assert_eq!(range.complement().union(&range), Range::full());
+        }
+
+        #[test]
+        fn union_contains_either(r1 in strategy(), r2 in strategy(), version in version_strat()) {
+            assert_eq!(r1.union(&r2).contains(&version), r1.contains(&version) || r2.contains(&version));
+        }
+
+        // Testing contains --------------------------------
+
+        #[test]
+        fn always_contains_exact(version in version_strat()) {
+            assert!(Range::singleton(version).contains(&version));
+        }
+
+        #[test]
+        fn contains_negation(range in strategy(), version in version_strat()) {
+            assert_ne!(range.contains(&version), range.complement().contains(&version));
+        }
+
+        #[test]
+        fn contains_intersection(range in strategy(), version in version_strat()) {
+            assert_eq!(range.contains(&version), range.intersection(&Range::singleton(version)) != Range::empty());
+        }
+
+        #[test]
+        fn contains_bounding_range(range in strategy(), version in version_strat()) {
+            if range.contains(&version) {
+                assert!(range.bounding_range().map(|b| b.contains(&version)).unwrap_or(false));
+            }
+        }
+
+        #[test]
+        fn from_range_bounds(range in any::<(Bound<u32>, Bound<u32>)>(), version in version_strat()) {
+            let rv: Range<_> = Range::from_range_bounds(range);
+            assert_eq!(range.contains(&version), rv.contains(&version));
+        }
+
+        #[test]
+        fn from_range_bounds_round_trip(range in any::<(Bound<u32>, Bound<u32>)>()) {
+            let rv: Range<u32> = Range::from_range_bounds(range);
+            let rv2: Range<u32> = rv.bounding_range().map(Range::from_range_bounds::<_, u32>).unwrap_or_else(Range::empty);
+            assert_eq!(rv, rv2);
+        }
+
+        #[test]
+        fn contains(range in strategy(), versions in proptest::collection::vec(version_strat(), ..30)) {
+            for v in versions {
+                assert_eq!(range.contains(&v), range.segments.iter().any(|s| RangeBounds::contains(s, &v)));
+            }
+        }
+
+        #[test]
+        fn contains_many(range in strategy(), mut versions in proptest::collection::vec(version_strat(), ..30)) {
+            versions.sort();
+            assert_eq!(versions.len(), range.contains_many(versions.iter()).count());
+            for (a, b) in versions.iter().zip(range.contains_many(versions.iter())) {
+                assert_eq!(range.contains(a), b);
+            }
+        }
+
+        #[test]
+        fn simplify(range in strategy(), mut versions in proptest::collection::vec(version_strat(), ..30)) {
+            versions.sort();
+            let simp = range.simplify(versions.iter());
+
+            for v in versions {
+                assert_eq!(range.contains(&v), simp.contains(&v));
+            }
+            assert!(simp.segments.len() <= range.segments.len())
+        }
+    }
+}
+
\ No newline at end of file diff --git a/src/pubgrub/report.rs.html b/src/pubgrub/report.rs.html new file mode 100644 index 00000000..25ff17c6 --- /dev/null +++ b/src/pubgrub/report.rs.html @@ -0,0 +1,1183 @@ +report.rs - source +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
+479
+480
+481
+482
+483
+484
+485
+486
+487
+488
+489
+490
+491
+492
+493
+494
+495
+496
+497
+498
+499
+500
+501
+502
+503
+504
+505
+506
+507
+508
+509
+510
+511
+512
+513
+514
+515
+516
+517
+518
+519
+520
+521
+522
+523
+524
+525
+526
+527
+528
+529
+530
+531
+532
+533
+534
+535
+536
+537
+538
+539
+540
+541
+542
+543
+544
+545
+546
+547
+548
+549
+550
+551
+552
+553
+554
+555
+556
+557
+558
+559
+560
+561
+562
+563
+564
+565
+566
+567
+568
+569
+570
+571
+572
+573
+574
+575
+576
+577
+578
+579
+580
+581
+582
+583
+584
+585
+586
+587
+588
+589
+590
+
// SPDX-License-Identifier: MPL-2.0
+
+//! Build a report as clear as possible as to why
+//! dependency solving failed.
+
+use std::fmt;
+use std::ops::Deref;
+use std::sync::Arc;
+
+use crate::package::Package;
+use crate::term::Term;
+use crate::type_aliases::Map;
+use crate::version_set::VersionSet;
+
+/// Reporter trait.
+pub trait Reporter<P: Package, VS: VersionSet> {
+    /// Output type of the report.
+    type Output;
+
+    /// Generate a report from the derivation tree
+    /// describing the resolution failure using the default formatter.
+    fn report(derivation_tree: &DerivationTree<P, VS>) -> Self::Output;
+
+    /// Generate a report from the derivation tree
+    /// describing the resolution failure using a custom formatter.
+    fn report_with_formatter(
+        derivation_tree: &DerivationTree<P, VS>,
+        formatter: &impl ReportFormatter<P, VS, Output = Self::Output>,
+    ) -> Self::Output;
+}
+
+/// Derivation tree resulting in the impossibility
+/// to solve the dependencies of our root package.
+#[derive(Debug, Clone)]
+pub enum DerivationTree<P: Package, VS: VersionSet> {
+    /// External incompatibility.
+    External(External<P, VS>),
+    /// Incompatibility derived from two others.
+    Derived(Derived<P, VS>),
+}
+
+/// Incompatibilities that are not derived from others,
+/// they have their own reason.
+#[derive(Debug, Clone)]
+pub enum External<P: Package, VS: VersionSet> {
+    /// Initial incompatibility aiming at picking the root package for the first decision.
+    NotRoot(P, VS::V),
+    /// There are no versions in the given set for this package.
+    NoVersions(P, VS),
+    /// Dependencies of the package are unavailable for versions in that set.
+    UnavailableDependencies(P, VS),
+    /// Incompatibility coming from the dependencies of a given package.
+    FromDependencyOf(P, VS, P, VS),
+}
+
+/// Incompatibility derived from two others.
+#[derive(Debug, Clone)]
+pub struct Derived<P: Package, VS: VersionSet> {
+    /// Terms of the incompatibility.
+    pub terms: Map<P, Term<VS>>,
+    /// Indicate if that incompatibility is present multiple times
+    /// in the derivation tree.
+    /// If that is the case, it has a unique id, provided in that option.
+    /// Then, we may want to only explain it once,
+    /// and refer to the explanation for the other times.
+    pub shared_id: Option<usize>,
+    /// First cause.
+    pub cause1: Arc<DerivationTree<P, VS>>,
+    /// Second cause.
+    pub cause2: Arc<DerivationTree<P, VS>>,
+}
+
+impl<P: Package, VS: VersionSet> DerivationTree<P, VS> {
+    /// Merge the [NoVersions](External::NoVersions) external incompatibilities
+    /// with the other one they are matched with
+    /// in a derived incompatibility.
+    /// This cleans up quite nicely the generated report.
+    /// You might want to do this if you know that the
+    /// [DependencyProvider](crate::solver::DependencyProvider)
+    /// was not run in some kind of offline mode that may not
+    /// have access to all versions existing.
+    pub fn collapse_no_versions(&mut self) {
+        match self {
+            DerivationTree::External(_) => {}
+            DerivationTree::Derived(derived) => {
+                match (
+                    Arc::make_mut(&mut derived.cause1),
+                    Arc::make_mut(&mut derived.cause2),
+                ) {
+                    (DerivationTree::External(External::NoVersions(p, r)), ref mut cause2) => {
+                        cause2.collapse_no_versions();
+                        *self = cause2
+                            .clone()
+                            .merge_no_versions(p.to_owned(), r.to_owned())
+                            .unwrap_or_else(|| self.to_owned());
+                    }
+                    (ref mut cause1, DerivationTree::External(External::NoVersions(p, r))) => {
+                        cause1.collapse_no_versions();
+                        *self = cause1
+                            .clone()
+                            .merge_no_versions(p.to_owned(), r.to_owned())
+                            .unwrap_or_else(|| self.to_owned());
+                    }
+                    _ => {
+                        Arc::make_mut(&mut derived.cause1).collapse_no_versions();
+                        Arc::make_mut(&mut derived.cause2).collapse_no_versions();
+                    }
+                }
+            }
+        }
+    }
+
+    fn merge_no_versions(self, package: P, set: VS) -> Option<Self> {
+        match self {
+            // TODO: take care of the Derived case.
+            // Once done, we can remove the Option.
+            DerivationTree::Derived(_) => Some(self),
+            DerivationTree::External(External::NotRoot(_, _)) => {
+                panic!("How did we end up with a NoVersions merged with a NotRoot?")
+            }
+            DerivationTree::External(External::NoVersions(_, r)) => Some(DerivationTree::External(
+                External::NoVersions(package, set.union(&r)),
+            )),
+            DerivationTree::External(External::UnavailableDependencies(_, r)) => Some(
+                DerivationTree::External(External::UnavailableDependencies(package, set.union(&r))),
+            ),
+            DerivationTree::External(External::FromDependencyOf(p1, r1, p2, r2)) => {
+                if p1 == package {
+                    Some(DerivationTree::External(External::FromDependencyOf(
+                        p1,
+                        r1.union(&set),
+                        p2,
+                        r2,
+                    )))
+                } else {
+                    Some(DerivationTree::External(External::FromDependencyOf(
+                        p1,
+                        r1,
+                        p2,
+                        r2.union(&set),
+                    )))
+                }
+            }
+        }
+    }
+}
+
+impl<P: Package, VS: VersionSet> fmt::Display for External<P, VS> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self {
+            Self::NotRoot(package, version) => {
+                write!(f, "we are solving dependencies of {} {}", package, version)
+            }
+            Self::NoVersions(package, set) => {
+                if set == &VS::full() {
+                    write!(f, "there is no available version for {}", package)
+                } else {
+                    write!(f, "there is no version of {} in {}", package, set)
+                }
+            }
+            Self::UnavailableDependencies(package, set) => {
+                if set == &VS::full() {
+                    write!(f, "dependencies of {} are unavailable", package)
+                } else {
+                    write!(
+                        f,
+                        "dependencies of {} at version {} are unavailable",
+                        package, set
+                    )
+                }
+            }
+            Self::FromDependencyOf(p, set_p, dep, set_dep) => {
+                if set_p == &VS::full() && set_dep == &VS::full() {
+                    write!(f, "{} depends on {}", p, dep)
+                } else if set_p == &VS::full() {
+                    write!(f, "{} depends on {} {}", p, dep, set_dep)
+                } else if set_dep == &VS::full() {
+                    write!(f, "{} {} depends on {}", p, set_p, dep)
+                } else {
+                    write!(f, "{} {} depends on {} {}", p, set_p, dep, set_dep)
+                }
+            }
+        }
+    }
+}
+
+/// Trait for formatting outputs in the reporter.
+pub trait ReportFormatter<P: Package, VS: VersionSet> {
+    /// Output type of the report.
+    type Output;
+
+    /// Format an [External] incompatibility.
+    fn format_external(&self, external: &External<P, VS>) -> Self::Output;
+
+    /// Format terms of an incompatibility.
+    fn format_terms(&self, terms: &Map<P, Term<VS>>) -> Self::Output;
+}
+
+/// Default formatter for the default reporter.
+#[derive(Default, Debug)]
+pub struct DefaultStringReportFormatter;
+
+impl<P: Package, VS: VersionSet> ReportFormatter<P, VS> for DefaultStringReportFormatter {
+    type Output = String;
+
+    fn format_external(&self, external: &External<P, VS>) -> String {
+        external.to_string()
+    }
+
+    fn format_terms(&self, terms: &Map<P, Term<VS>>) -> Self::Output {
+        let terms_vec: Vec<_> = terms.iter().collect();
+        match terms_vec.as_slice() {
+            [] => "version solving failed".into(),
+            // TODO: special case when that unique package is root.
+            [(package, Term::Positive(range))] => format!("{} {} is forbidden", package, range),
+            [(package, Term::Negative(range))] => format!("{} {} is mandatory", package, range),
+            [(p1, Term::Positive(r1)), (p2, Term::Negative(r2))] => {
+                self.format_external(&External::FromDependencyOf(p1, r1.clone(), p2, r2.clone()))
+            }
+            [(p1, Term::Negative(r1)), (p2, Term::Positive(r2))] => {
+                self.format_external(&External::FromDependencyOf(p2, r2.clone(), p1, r1.clone()))
+            }
+            slice => {
+                let str_terms: Vec<_> = slice.iter().map(|(p, t)| format!("{} {}", p, t)).collect();
+                str_terms.join(", ") + " are incompatible"
+            }
+        }
+    }
+}
+
+/// Default reporter able to generate an explanation as a [String].
+pub struct DefaultStringReporter {
+    /// Number of explanations already with a line reference.
+    ref_count: usize,
+    /// Shared nodes that have already been marked with a line reference.
+    /// The incompatibility ids are the keys, and the line references are the values.
+    shared_with_ref: Map<usize, usize>,
+    /// Accumulated lines of the report already generated.
+    lines: Vec<String>,
+}
+
+impl DefaultStringReporter {
+    /// Initialize the reporter.
+    fn new() -> Self {
+        Self {
+            ref_count: 0,
+            shared_with_ref: Map::default(),
+            lines: Vec::new(),
+        }
+    }
+
+    fn build_recursive<P: Package, VS: VersionSet, F: ReportFormatter<P, VS, Output = String>>(
+        &mut self,
+        derived: &Derived<P, VS>,
+        formatter: &F,
+    ) {
+        self.build_recursive_helper(derived, formatter);
+        if let Some(id) = derived.shared_id {
+            if self.shared_with_ref.get(&id).is_none() {
+                self.add_line_ref();
+                self.shared_with_ref.insert(id, self.ref_count);
+            }
+        };
+    }
+
+    fn build_recursive_helper<
+        P: Package,
+        VS: VersionSet,
+        F: ReportFormatter<P, VS, Output = String>,
+    >(
+        &mut self,
+        current: &Derived<P, VS>,
+        formatter: &F,
+    ) {
+        match (current.cause1.deref(), current.cause2.deref()) {
+            (DerivationTree::External(external1), DerivationTree::External(external2)) => {
+                // Simplest case, we just combine two external incompatibilities.
+                self.lines.push(Self::explain_both_external(
+                    external1,
+                    external2,
+                    &current.terms,
+                    formatter,
+                ));
+            }
+            (DerivationTree::Derived(derived), DerivationTree::External(external)) => {
+                // One cause is derived, so we explain this first
+                // then we add the one-line external part
+                // and finally conclude with the current incompatibility.
+                self.report_one_each(derived, external, &current.terms, formatter);
+            }
+            (DerivationTree::External(external), DerivationTree::Derived(derived)) => {
+                self.report_one_each(derived, external, &current.terms, formatter);
+            }
+            (DerivationTree::Derived(derived1), DerivationTree::Derived(derived2)) => {
+                // This is the most complex case since both causes are also derived.
+                match (
+                    self.line_ref_of(derived1.shared_id),
+                    self.line_ref_of(derived2.shared_id),
+                ) {
+                    // If both causes already have been referenced (shared_id),
+                    // the explanation simply uses those references.
+                    (Some(ref1), Some(ref2)) => self.lines.push(Self::explain_both_ref(
+                        ref1,
+                        derived1,
+                        ref2,
+                        derived2,
+                        &current.terms,
+                        formatter,
+                    )),
+                    // Otherwise, if one only has a line number reference,
+                    // we recursively call the one without reference and then
+                    // add the one with reference to conclude.
+                    (Some(ref1), None) => {
+                        self.build_recursive(derived2, formatter);
+                        self.lines.push(Self::and_explain_ref(
+                            ref1,
+                            derived1,
+                            &current.terms,
+                            formatter,
+                        ));
+                    }
+                    (None, Some(ref2)) => {
+                        self.build_recursive(derived1, formatter);
+                        self.lines.push(Self::and_explain_ref(
+                            ref2,
+                            derived2,
+                            &current.terms,
+                            formatter,
+                        ));
+                    }
+                    // Finally, if no line reference exists yet,
+                    // we call recursively the first one and then,
+                    //   - if this was a shared node, it will get a line ref
+                    //     and we can simply recall this with the current node.
+                    //   - otherwise, we add a line reference to it,
+                    //     recursively call on the second node,
+                    //     and finally conclude.
+                    (None, None) => {
+                        self.build_recursive(derived1, formatter);
+                        if derived1.shared_id.is_some() {
+                            self.lines.push("".into());
+                            self.build_recursive(current, formatter);
+                        } else {
+                            self.add_line_ref();
+                            let ref1 = self.ref_count;
+                            self.lines.push("".into());
+                            self.build_recursive(derived2, formatter);
+                            self.lines.push(Self::and_explain_ref(
+                                ref1,
+                                derived1,
+                                &current.terms,
+                                formatter,
+                            ));
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    /// Report a derived and an external incompatibility.
+    ///
+    /// The result will depend on the fact that the derived incompatibility
+    /// has already been explained or not.
+    fn report_one_each<P: Package, VS: VersionSet, F: ReportFormatter<P, VS, Output = String>>(
+        &mut self,
+        derived: &Derived<P, VS>,
+        external: &External<P, VS>,
+        current_terms: &Map<P, Term<VS>>,
+        formatter: &F,
+    ) {
+        match self.line_ref_of(derived.shared_id) {
+            Some(ref_id) => self.lines.push(Self::explain_ref_and_external(
+                ref_id,
+                derived,
+                external,
+                current_terms,
+                formatter,
+            )),
+            None => self.report_recurse_one_each(derived, external, current_terms, formatter),
+        }
+    }
+
+    /// Report one derived (without a line ref yet) and one external.
+    fn report_recurse_one_each<
+        P: Package,
+        VS: VersionSet,
+        F: ReportFormatter<P, VS, Output = String>,
+    >(
+        &mut self,
+        derived: &Derived<P, VS>,
+        external: &External<P, VS>,
+        current_terms: &Map<P, Term<VS>>,
+        formatter: &F,
+    ) {
+        match (derived.cause1.deref(), derived.cause2.deref()) {
+            // If the derived cause has itself one external prior cause,
+            // we can chain the external explanations.
+            (DerivationTree::Derived(prior_derived), DerivationTree::External(prior_external)) => {
+                self.build_recursive(prior_derived, formatter);
+                self.lines.push(Self::and_explain_prior_and_external(
+                    prior_external,
+                    external,
+                    current_terms,
+                    formatter,
+                ));
+            }
+            // If the derived cause has itself one external prior cause,
+            // we can chain the external explanations.
+            (DerivationTree::External(prior_external), DerivationTree::Derived(prior_derived)) => {
+                self.build_recursive(prior_derived, formatter);
+                self.lines.push(Self::and_explain_prior_and_external(
+                    prior_external,
+                    external,
+                    current_terms,
+                    formatter,
+                ));
+            }
+            _ => {
+                self.build_recursive(derived, formatter);
+                self.lines.push(Self::and_explain_external(
+                    external,
+                    current_terms,
+                    formatter,
+                ));
+            }
+        }
+    }
+
+    // String explanations #####################################################
+
+    /// Simplest case, we just combine two external incompatibilities.
+    fn explain_both_external<
+        P: Package,
+        VS: VersionSet,
+        F: ReportFormatter<P, VS, Output = String>,
+    >(
+        external1: &External<P, VS>,
+        external2: &External<P, VS>,
+        current_terms: &Map<P, Term<VS>>,
+        formatter: &F,
+    ) -> String {
+        // TODO: order should be chosen to make it more logical.
+        format!(
+            "Because {} and {}, {}.",
+            formatter.format_external(external1),
+            formatter.format_external(external2),
+            formatter.format_terms(current_terms)
+        )
+    }
+
+    /// Both causes have already been explained so we use their refs.
+    fn explain_both_ref<P: Package, VS: VersionSet, F: ReportFormatter<P, VS, Output = String>>(
+        ref_id1: usize,
+        derived1: &Derived<P, VS>,
+        ref_id2: usize,
+        derived2: &Derived<P, VS>,
+        current_terms: &Map<P, Term<VS>>,
+        formatter: &F,
+    ) -> String {
+        // TODO: order should be chosen to make it more logical.
+        format!(
+            "Because {} ({}) and {} ({}), {}.",
+            formatter.format_terms(&derived1.terms),
+            ref_id1,
+            formatter.format_terms(&derived2.terms),
+            ref_id2,
+            formatter.format_terms(current_terms)
+        )
+    }
+
+    /// One cause is derived (already explained so one-line),
+    /// the other is a one-line external cause,
+    /// and finally we conclude with the current incompatibility.
+    fn explain_ref_and_external<
+        P: Package,
+        VS: VersionSet,
+        F: ReportFormatter<P, VS, Output = String>,
+    >(
+        ref_id: usize,
+        derived: &Derived<P, VS>,
+        external: &External<P, VS>,
+        current_terms: &Map<P, Term<VS>>,
+        formatter: &F,
+    ) -> String {
+        // TODO: order should be chosen to make it more logical.
+        format!(
+            "Because {} ({}) and {}, {}.",
+            formatter.format_terms(&derived.terms),
+            ref_id,
+            formatter.format_external(external),
+            formatter.format_terms(current_terms)
+        )
+    }
+
+    /// Add an external cause to the chain of explanations.
+    fn and_explain_external<
+        P: Package,
+        VS: VersionSet,
+        F: ReportFormatter<P, VS, Output = String>,
+    >(
+        external: &External<P, VS>,
+        current_terms: &Map<P, Term<VS>>,
+        formatter: &F,
+    ) -> String {
+        format!(
+            "And because {}, {}.",
+            formatter.format_external(external),
+            formatter.format_terms(current_terms)
+        )
+    }
+
+    /// Add an already explained incompat to the chain of explanations.
+    fn and_explain_ref<P: Package, VS: VersionSet, F: ReportFormatter<P, VS, Output = String>>(
+        ref_id: usize,
+        derived: &Derived<P, VS>,
+        current_terms: &Map<P, Term<VS>>,
+        formatter: &F,
+    ) -> String {
+        format!(
+            "And because {} ({}), {}.",
+            formatter.format_terms(&derived.terms),
+            ref_id,
+            formatter.format_terms(current_terms)
+        )
+    }
+
+    /// Add an already explained incompat to the chain of explanations.
+    fn and_explain_prior_and_external<
+        P: Package,
+        VS: VersionSet,
+        F: ReportFormatter<P, VS, Output = String>,
+    >(
+        prior_external: &External<P, VS>,
+        external: &External<P, VS>,
+        current_terms: &Map<P, Term<VS>>,
+        formatter: &F,
+    ) -> String {
+        format!(
+            "And because {} and {}, {}.",
+            formatter.format_external(prior_external),
+            formatter.format_external(external),
+            formatter.format_terms(current_terms)
+        )
+    }
+
+    // Helper functions ########################################################
+
+    fn add_line_ref(&mut self) {
+        let new_count = self.ref_count + 1;
+        self.ref_count = new_count;
+        if let Some(line) = self.lines.last_mut() {
+            *line = format!("{} ({})", line, new_count);
+        }
+    }
+
+    fn line_ref_of(&self, shared_id: Option<usize>) -> Option<usize> {
+        shared_id.and_then(|id| self.shared_with_ref.get(&id).cloned())
+    }
+}
+
+impl<P: Package, VS: VersionSet> Reporter<P, VS> for DefaultStringReporter {
+    type Output = String;
+
+    fn report(derivation_tree: &DerivationTree<P, VS>) -> Self::Output {
+        let formatter = DefaultStringReportFormatter;
+        match derivation_tree {
+            DerivationTree::External(external) => formatter.format_external(external),
+            DerivationTree::Derived(derived) => {
+                let mut reporter = Self::new();
+                reporter.build_recursive(derived, &formatter);
+                reporter.lines.join("\n")
+            }
+        }
+    }
+
+    fn report_with_formatter(
+        derivation_tree: &DerivationTree<P, VS>,
+        formatter: &impl ReportFormatter<P, VS, Output = Self::Output>,
+    ) -> Self::Output {
+        match derivation_tree {
+            DerivationTree::External(external) => formatter.format_external(external),
+            DerivationTree::Derived(derived) => {
+                let mut reporter = Self::new();
+                reporter.build_recursive(derived, formatter);
+                reporter.lines.join("\n")
+            }
+        }
+    }
+}
+
\ No newline at end of file diff --git a/src/pubgrub/solver.rs.html b/src/pubgrub/solver.rs.html new file mode 100644 index 00000000..0790931f --- /dev/null +++ b/src/pubgrub/solver.rs.html @@ -0,0 +1,755 @@ +solver.rs - source +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+
// SPDX-License-Identifier: MPL-2.0
+
+//! PubGrub version solving algorithm.
+//!
+//! It consists in efficiently finding a set of packages and versions
+//! that satisfy all the constraints of a given project dependencies.
+//! In addition, when that is not possible,
+//! PubGrub tries to provide a very human-readable and clear
+//! explanation as to why that failed.
+//! Below is an example of explanation present in
+//! the introductory blog post about PubGrub
+//!
+//! ```txt
+//! Because dropdown >=2.0.0 depends on icons >=2.0.0 and
+//!   root depends on icons <2.0.0, dropdown >=2.0.0 is forbidden.
+//!
+//! And because menu >=1.1.0 depends on dropdown >=2.0.0,
+//!   menu >=1.1.0 is forbidden.
+//!
+//! And because menu <1.1.0 depends on dropdown >=1.0.0 <2.0.0
+//!   which depends on intl <4.0.0, every version of menu
+//!   requires intl <4.0.0.
+//!
+//! So, because root depends on both menu >=1.0.0 and intl >=5.0.0,
+//!   version solving failed.
+//! ```
+//!
+//! The algorithm is generic and works for any type of dependency system
+//! as long as packages (P) and versions (V) implement
+//! the [Package] and [Version](crate::version::Version) traits.
+//! [Package] is strictly equivalent and automatically generated
+//! for any type that implement [Clone] + [Eq] + [Hash] + [Debug] + [Display](std::fmt::Display).
+//! [Version](crate::version::Version) simply states that versions are ordered,
+//! that there should be
+//! a minimal [lowest](crate::version::Version::lowest) version (like 0.0.0 in semantic versions),
+//! and that for any version, it is possible to compute
+//! what the next version closest to this one is ([bump](crate::version::Version::bump)).
+//! For semantic versions, [bump](crate::version::Version::bump) corresponds to
+//! an increment of the patch number.
+//!
+//! ## API
+//!
+//! ```
+//! # use std::convert::Infallible;
+//! # use pubgrub::solver::{resolve, OfflineDependencyProvider};
+//! # use pubgrub::version::NumberVersion;
+//! # use pubgrub::error::PubGrubError;
+//! # use pubgrub::range::Range;
+//! #
+//! # type NumVS = Range<NumberVersion>;
+//! #
+//! # fn try_main() -> Result<(), PubGrubError<&'static str, NumVS, Infallible>> {
+//! #     let dependency_provider = OfflineDependencyProvider::<&str, NumVS>::new();
+//! #     let package = "root";
+//! #     let version = 1;
+//! let solution = resolve(&dependency_provider, package, version)?;
+//! #     Ok(())
+//! # }
+//! # fn main() {
+//! #     assert!(matches!(try_main(), Err(PubGrubError::NoSolution(_))));
+//! # }
+//! ```
+//!
+//! Where `dependency_provider` supplies the list of available packages and versions,
+//! as well as the dependencies of every available package
+//! by implementing the [DependencyProvider] trait.
+//! The call to [resolve] for a given package at a given version
+//! will compute the set of packages and versions needed
+//! to satisfy the dependencies of that package and version pair.
+//! If there is no solution, the reason will be provided as clear as possible.
+
+use std::cmp::Reverse;
+use std::collections::{BTreeMap, BTreeSet as Set};
+use std::convert::Infallible;
+use std::error::Error;
+
+use crate::error::PubGrubError;
+use crate::internal::core::State;
+use crate::internal::incompatibility::Incompatibility;
+use crate::package::Package;
+use crate::type_aliases::{DependencyConstraints, Map, SelectedDependencies};
+use crate::version_set::VersionSet;
+use log::{debug, info};
+
+/// Main function of the library.
+/// Finds a set of packages satisfying dependency bounds for a given package + version pair.
+#[allow(clippy::type_complexity)]
+pub fn resolve<P: Package, VS: VersionSet, DP: DependencyProvider<P, VS>>(
+    dependency_provider: &DP,
+    package: P,
+    version: impl Into<VS::V>,
+) -> Result<SelectedDependencies<P, VS::V>, PubGrubError<P, VS, DP::Err>> {
+    let mut state = State::init(package.clone(), version.into());
+    let mut added_dependencies: Map<P, Set<VS::V>> = Map::default();
+    let mut next = package;
+    loop {
+        dependency_provider
+            .should_cancel()
+            .map_err(|err| PubGrubError::ErrorInShouldCancel(err))?;
+
+        info!("unit_propagation: {}", &next);
+        state.unit_propagation(next)?;
+
+        debug!(
+            "Partial solution after unit propagation: {}",
+            state.partial_solution
+        );
+
+        let Some(highest_priority_pkg) = state
+            .partial_solution
+            .pick_highest_priority_pkg(|p, r| dependency_provider.prioritize(p, r))
+        else {
+            return Ok(state.partial_solution.extract_solution());
+        };
+        next = highest_priority_pkg;
+
+        let term_intersection = state
+            .partial_solution
+            .term_intersection_for_package(&next)
+            .ok_or_else(|| {
+                PubGrubError::Failure("a package was chosen but we don't have a term.".into())
+            })?;
+        let decision = dependency_provider
+            .choose_version(&next, term_intersection.unwrap_positive())
+            .map_err(PubGrubError::ErrorChoosingPackageVersion)?;
+        info!("DP chose: {} @ {:?}", next, decision);
+
+        // Pick the next compatible version.
+        let v = match decision {
+            None => {
+                let inc = Incompatibility::no_versions(next.clone(), term_intersection.clone());
+                state.add_incompatibility(inc);
+                continue;
+            }
+            Some(x) => x,
+        };
+
+        if !term_intersection.contains(&v) {
+            return Err(PubGrubError::Failure(
+                "choose_package_version picked an incompatible version".into(),
+            ));
+        }
+
+        let is_new_dependency = added_dependencies
+            .entry(next.clone())
+            .or_default()
+            .insert(v.clone());
+
+        if is_new_dependency {
+            // Retrieve that package dependencies.
+            let p = &next;
+            let dependencies = dependency_provider.get_dependencies(p, &v).map_err(|err| {
+                PubGrubError::ErrorRetrievingDependencies {
+                    package: p.clone(),
+                    version: v.clone(),
+                    source: err,
+                }
+            })?;
+
+            let known_dependencies = match dependencies {
+                Dependencies::Unknown => {
+                    state.add_incompatibility(Incompatibility::unavailable_dependencies(
+                        p.clone(),
+                        v.clone(),
+                    ));
+                    continue;
+                }
+                Dependencies::Known(x) if x.contains_key(p) => {
+                    return Err(PubGrubError::SelfDependency {
+                        package: p.clone(),
+                        version: v,
+                    });
+                }
+                Dependencies::Known(x) => x,
+            };
+
+            // Add that package and version if the dependencies are not problematic.
+            let dep_incompats = state.add_incompatibility_from_dependencies(
+                p.clone(),
+                v.clone(),
+                &known_dependencies,
+            );
+
+            state.partial_solution.add_version(
+                p.clone(),
+                v,
+                dep_incompats,
+                &state.incompatibility_store,
+            );
+        } else {
+            // `dep_incompats` are already in `incompatibilities` so we know there are not satisfied
+            // terms and can add the decision directly.
+            info!("add_decision (not first time): {} @ {}", &next, v);
+            state.partial_solution.add_decision(next.clone(), v);
+        }
+    }
+}
+
+/// An enum used by [DependencyProvider] that holds information about package dependencies.
+/// For each [Package] there is a set of versions allowed as a dependency.
+#[derive(Clone)]
+pub enum Dependencies<P: Package, VS: VersionSet> {
+    /// Package dependencies are unavailable.
+    Unknown,
+    /// Container for all available package versions.
+    Known(DependencyConstraints<P, VS>),
+}
+
+/// Trait that allows the algorithm to retrieve available packages and their dependencies.
+/// An implementor needs to be supplied to the [resolve] function.
+pub trait DependencyProvider<P: Package, VS: VersionSet> {
+    /// [Decision making](https://github.com/dart-lang/pub/blob/master/doc/solver.md#decision-making)
+    /// is the process of choosing the next package
+    /// and version that will be appended to the partial solution.
+    ///
+    /// Every time such a decision must be made, the resolver looks at all the potential valid
+    /// packages that have changed, and a asks the dependency provider how important each one is.
+    /// For each one it calls `prioritize` with the name of the package and the current set of
+    /// acceptable versions.
+    /// The resolver will then pick the package with the highes priority from all the potential valid
+    /// packages.
+    ///
+    /// The strategy employed to prioritize packages
+    /// cannot change the existence of a solution or not,
+    /// but can drastically change the performances of the solver,
+    /// or the properties of the solution.
+    /// The documentation of Pub (PubGrub implementation for the dart programming language)
+    /// states the following:
+    ///
+    /// > Pub chooses the latest matching version of the package
+    /// > with the fewest versions that match the outstanding constraint.
+    /// > This tends to find conflicts earlier if any exist,
+    /// > since these packages will run out of versions to try more quickly.
+    /// > But there's likely room for improvement in these heuristics.
+    ///
+    /// Note: the resolver may call this even when the range has not change,
+    /// if it is more efficient for the resolveres internal data structures.
+    fn prioritize(&self, package: &P, range: &VS) -> Self::Priority;
+    /// The type returned from `prioritize`. The resolver does not care what type this is
+    /// as long as it can pick a largest one and clone it.
+    ///
+    /// [std::cmp::Reverse] can be useful if you want to pick the package with
+    /// the fewest versions that match the outstanding constraint.
+    type Priority: Ord + Clone;
+
+    /// The kind of error returned from these methods.
+    ///
+    /// Returning this signals that resolution should fail with this error.
+    type Err: Error;
+
+    /// Once the resolver has found the highest `Priority` package from all potential valid
+    /// packages, it needs to know what vertion of that package to use. The most common pattern
+    /// is to select the largest vertion that the range contains.
+    fn choose_version(&self, package: &P, range: &VS) -> Result<Option<VS::V>, Self::Err>;
+
+    /// Retrieves the package dependencies.
+    /// Return [Dependencies::Unknown] if its dependencies are unknown.
+    fn get_dependencies(
+        &self,
+        package: &P,
+        version: &VS::V,
+    ) -> Result<Dependencies<P, VS>, Self::Err>;
+
+    /// This is called fairly regularly during the resolution,
+    /// if it returns an Err then resolution will be terminated.
+    /// This is helpful if you want to add some form of early termination like a timeout,
+    /// or you want to add some form of user feedback if things are taking a while.
+    /// If not provided the resolver will run as long as needed.
+    fn should_cancel(&self) -> Result<(), Self::Err> {
+        Ok(())
+    }
+}
+
+/// A basic implementation of [DependencyProvider].
+#[derive(Debug, Clone, Default)]
+#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
+#[cfg_attr(
+    feature = "serde",
+    serde(bound(
+        serialize = "VS::V: serde::Serialize, VS: serde::Serialize, P: serde::Serialize",
+        deserialize = "VS::V: serde::Deserialize<'de>, VS: serde::Deserialize<'de>, P: serde::Deserialize<'de>"
+    ))
+)]
+#[cfg_attr(feature = "serde", serde(transparent))]
+pub struct OfflineDependencyProvider<P: Package, VS: VersionSet> {
+    dependencies: Map<P, BTreeMap<VS::V, DependencyConstraints<P, VS>>>,
+}
+
+impl<P: Package, VS: VersionSet> OfflineDependencyProvider<P, VS> {
+    /// Creates an empty OfflineDependencyProvider with no dependencies.
+    pub fn new() -> Self {
+        Self {
+            dependencies: Map::default(),
+        }
+    }
+
+    /// Registers the dependencies of a package and version pair.
+    /// Dependencies must be added with a single call to
+    /// [add_dependencies](OfflineDependencyProvider::add_dependencies).
+    /// All subsequent calls to
+    /// [add_dependencies](OfflineDependencyProvider::add_dependencies) for a given
+    /// package version pair will replace the dependencies by the new ones.
+    ///
+    /// The API does not allow to add dependencies one at a time to uphold an assumption that
+    /// [OfflineDependencyProvider.get_dependencies(p, v)](OfflineDependencyProvider::get_dependencies)
+    /// provides all dependencies of a given package (p) and version (v) pair.
+    pub fn add_dependencies<I: IntoIterator<Item = (P, VS)>>(
+        &mut self,
+        package: P,
+        version: impl Into<VS::V>,
+        dependencies: I,
+    ) {
+        let package_deps = dependencies.into_iter().collect();
+        let v = version.into();
+        *self
+            .dependencies
+            .entry(package)
+            .or_default()
+            .entry(v)
+            .or_default() = package_deps;
+    }
+
+    /// Lists packages that have been saved.
+    pub fn packages(&self) -> impl Iterator<Item = &P> {
+        self.dependencies.keys()
+    }
+
+    /// Lists versions of saved packages in sorted order.
+    /// Returns [None] if no information is available regarding that package.
+    pub fn versions(&self, package: &P) -> Option<impl Iterator<Item = &VS::V>> {
+        self.dependencies.get(package).map(|k| k.keys())
+    }
+
+    /// Lists dependencies of a given package and version.
+    /// Returns [None] if no information is available regarding that package and version pair.
+    fn dependencies(&self, package: &P, version: &VS::V) -> Option<DependencyConstraints<P, VS>> {
+        self.dependencies.get(package)?.get(version).cloned()
+    }
+}
+
+/// An implementation of [DependencyProvider] that
+/// contains all dependency information available in memory.
+/// Currently packages are picked with the fewest versions contained in the constraints first.
+/// But, that may change in new versions if better heuristics are found.
+/// Versions are picked with the newest versions first.
+impl<P: Package, VS: VersionSet> DependencyProvider<P, VS> for OfflineDependencyProvider<P, VS> {
+    type Err = Infallible;
+
+    fn choose_version(&self, package: &P, range: &VS) -> Result<Option<VS::V>, Infallible> {
+        Ok(self
+            .dependencies
+            .get(package)
+            .and_then(|versions| versions.keys().rev().find(|v| range.contains(v)).cloned()))
+    }
+
+    type Priority = Reverse<usize>;
+    fn prioritize(&self, package: &P, range: &VS) -> Self::Priority {
+        Reverse(
+            self.dependencies
+                .get(package)
+                .map(|versions| versions.keys().filter(|v| range.contains(v)).count())
+                .unwrap_or(0),
+        )
+    }
+
+    fn get_dependencies(
+        &self,
+        package: &P,
+        version: &VS::V,
+    ) -> Result<Dependencies<P, VS>, Infallible> {
+        Ok(match self.dependencies(package, version) {
+            None => Dependencies::Unknown,
+            Some(dependencies) => Dependencies::Known(dependencies),
+        })
+    }
+}
+
\ No newline at end of file diff --git a/src/pubgrub/term.rs.html b/src/pubgrub/term.rs.html new file mode 100644 index 00000000..10a729cc --- /dev/null +++ b/src/pubgrub/term.rs.html @@ -0,0 +1,445 @@ +term.rs - source +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+
// SPDX-License-Identifier: MPL-2.0
+
+//! A term is the fundamental unit of operation of the PubGrub algorithm.
+//! It is a positive or negative expression regarding a set of versions.
+
+use crate::version_set::VersionSet;
+use std::fmt::{self, Display};
+
+///  A positive or negative expression regarding a set of versions.
+#[derive(Debug, Clone, Eq, PartialEq)]
+pub enum Term<VS: VersionSet> {
+    /// For example, "1.0.0 <= v < 2.0.0" is a positive expression
+    /// that is evaluated true if a version is selected
+    /// and comprised between version 1.0.0 and version 2.0.0.
+    Positive(VS),
+    /// The term "not v < 3.0.0" is a negative expression
+    /// that is evaluated true if a version is selected >= 3.0.0
+    /// or if no version is selected at all.
+    Negative(VS),
+}
+
+/// Base methods.
+impl<VS: VersionSet> Term<VS> {
+    /// A term that is always true.
+    pub(crate) fn any() -> Self {
+        Self::Negative(VS::empty())
+    }
+
+    /// A term that is never true.
+    pub(crate) fn empty() -> Self {
+        Self::Positive(VS::empty())
+    }
+
+    /// A positive term containing exactly that version.
+    pub(crate) fn exact(version: VS::V) -> Self {
+        Self::Positive(VS::singleton(version))
+    }
+
+    /// Simply check if a term is positive.
+    pub(crate) fn is_positive(&self) -> bool {
+        match self {
+            Self::Positive(_) => true,
+            Self::Negative(_) => false,
+        }
+    }
+
+    /// Negate a term.
+    /// Evaluation of a negated term always returns
+    /// the opposite of the evaluation of the original one.
+    pub(crate) fn negate(&self) -> Self {
+        match self {
+            Self::Positive(set) => Self::Negative(set.clone()),
+            Self::Negative(set) => Self::Positive(set.clone()),
+        }
+    }
+
+    /// Evaluate a term regarding a given choice of version.
+    pub(crate) fn contains(&self, v: &VS::V) -> bool {
+        match self {
+            Self::Positive(set) => set.contains(v),
+            Self::Negative(set) => !(set.contains(v)),
+        }
+    }
+
+    /// Unwrap the set contained in a positive term.
+    /// Will panic if used on a negative set.
+    pub(crate) fn unwrap_positive(&self) -> &VS {
+        match self {
+            Self::Positive(set) => set,
+            _ => panic!("Negative term cannot unwrap positive set"),
+        }
+    }
+
+    /// Unwrap the set contained in a negative term.
+    /// Will panic if used on a positive set.
+    pub(crate) fn unwrap_negative(&self) -> &VS {
+        match self {
+            Self::Negative(set) => set,
+            _ => panic!("Positive term cannot unwrap negative set"),
+        }
+    }
+}
+
+/// Set operations with terms.
+impl<VS: VersionSet> Term<VS> {
+    /// Compute the intersection of two terms.
+    /// If at least one term is positive, the intersection is also positive.
+    pub(crate) fn intersection(&self, other: &Self) -> Self {
+        match (self, other) {
+            (Self::Positive(r1), Self::Positive(r2)) => Self::Positive(r1.intersection(r2)),
+            (Self::Positive(r1), Self::Negative(r2)) => {
+                Self::Positive(r1.intersection(&r2.complement()))
+            }
+            (Self::Negative(r1), Self::Positive(r2)) => {
+                Self::Positive(r1.complement().intersection(r2))
+            }
+            (Self::Negative(r1), Self::Negative(r2)) => Self::Negative(r1.union(r2)),
+        }
+    }
+
+    /// Compute the union of two terms.
+    /// If at least one term is negative, the union is also negative.
+    pub(crate) fn union(&self, other: &Self) -> Self {
+        (self.negate().intersection(&other.negate())).negate()
+    }
+
+    /// Indicate if this term is a subset of another term.
+    /// Just like for sets, we say that t1 is a subset of t2
+    /// if and only if t1 ∩ t2 = t1.
+    #[cfg(test)]
+    pub(crate) fn subset_of(&self, other: &Self) -> bool {
+        self == &self.intersection(other)
+    }
+}
+
+/// Describe a relation between a set of terms S and another term t.
+///
+/// As a shorthand, we say that a term v
+/// satisfies or contradicts a term t if {v} satisfies or contradicts it.
+pub(crate) enum Relation {
+    /// We say that a set of terms S "satisfies" a term t
+    /// if t must be true whenever every term in S is true.
+    Satisfied,
+    /// Conversely, S "contradicts" t if t must be false
+    /// whenever every term in S is true.
+    Contradicted,
+    /// If neither of these is true we say that S is "inconclusive" for t.
+    Inconclusive,
+}
+
+/// Relation between terms.
+impl<VS: VersionSet> Term<VS> {
+    /// Check if a set of terms satisfies this term.
+    ///
+    /// We say that a set of terms S "satisfies" a term t
+    /// if t must be true whenever every term in S is true.
+    ///
+    /// It turns out that this can also be expressed with set operations:
+    ///    S satisfies t if and only if  ⋂ S ⊆ t
+    #[cfg(test)]
+    fn satisfied_by(&self, terms_intersection: &Self) -> bool {
+        terms_intersection.subset_of(self)
+    }
+
+    /// Check if a set of terms contradicts this term.
+    ///
+    /// We say that a set of terms S "contradicts" a term t
+    /// if t must be false whenever every term in S is true.
+    ///
+    /// It turns out that this can also be expressed with set operations:
+    ///    S contradicts t if and only if ⋂ S is disjoint with t
+    ///    S contradicts t if and only if  (⋂ S) ⋂ t = ∅
+    #[cfg(test)]
+    fn contradicted_by(&self, terms_intersection: &Self) -> bool {
+        terms_intersection.intersection(self) == Self::empty()
+    }
+
+    /// Check if a set of terms satisfies or contradicts a given term.
+    /// Otherwise the relation is inconclusive.
+    pub(crate) fn relation_with(&self, other_terms_intersection: &Self) -> Relation {
+        let full_intersection = self.intersection(other_terms_intersection);
+        if &full_intersection == other_terms_intersection {
+            Relation::Satisfied
+        } else if full_intersection == Self::empty() {
+            Relation::Contradicted
+        } else {
+            Relation::Inconclusive
+        }
+    }
+}
+
+impl<VS: VersionSet> AsRef<Self> for Term<VS> {
+    fn as_ref(&self) -> &Self {
+        self
+    }
+}
+
+// REPORT ######################################################################
+
+impl<VS: VersionSet + Display> Display for Term<VS> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self {
+            Self::Positive(set) => write!(f, "{}", set),
+            Self::Negative(set) => write!(f, "Not ( {} )", set),
+        }
+    }
+}
+
+// TESTS #######################################################################
+
+#[cfg(test)]
+pub mod tests {
+    use super::*;
+    use crate::range::Range;
+    use proptest::prelude::*;
+
+    pub fn strategy() -> impl Strategy<Value = Term<Range<u32>>> {
+        prop_oneof![
+            crate::range::tests::strategy().prop_map(Term::Positive),
+            crate::range::tests::strategy().prop_map(Term::Negative),
+        ]
+    }
+
+    proptest! {
+
+        // Testing relation --------------------------------
+
+        #[test]
+        fn relation_with(term1 in strategy(), term2 in strategy()) {
+            match term1.relation_with(&term2) {
+                Relation::Satisfied => assert!(term1.satisfied_by(&term2)),
+                Relation::Contradicted => assert!(term1.contradicted_by(&term2)),
+                Relation::Inconclusive => {
+                    assert!(!term1.satisfied_by(&term2));
+                    assert!(!term1.contradicted_by(&term2));
+                }
+            }
+        }
+
+    }
+}
+
\ No newline at end of file diff --git a/src/pubgrub/type_aliases.rs.html b/src/pubgrub/type_aliases.rs.html new file mode 100644 index 00000000..5f183a0c --- /dev/null +++ b/src/pubgrub/type_aliases.rs.html @@ -0,0 +1,43 @@ +type_aliases.rs - source +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+
// SPDX-License-Identifier: MPL-2.0
+
+//! Publicly exported type aliases.
+
+/// Map implementation used by the library.
+pub type Map<K, V> = rustc_hash::FxHashMap<K, V>;
+
+/// Set implementation used by the library.
+pub type Set<V> = rustc_hash::FxHashSet<V>;
+
+/// Concrete dependencies picked by the library during [resolve](crate::solver::resolve)
+/// from [DependencyConstraints].
+pub type SelectedDependencies<P, V> = Map<P, V>;
+
+/// Holds information about all possible versions a given package can accept.
+/// There is a difference in semantics between an empty map
+/// inside [DependencyConstraints] and [Dependencies::Unknown](crate::solver::Dependencies::Unknown):
+/// the former means the package has no dependency and it is a known fact,
+/// while the latter means they could not be fetched by the [DependencyProvider](crate::solver::DependencyProvider).
+pub type DependencyConstraints<P, VS> = Map<P, VS>;
+
\ No newline at end of file diff --git a/src/pubgrub/version.rs.html b/src/pubgrub/version.rs.html new file mode 100644 index 00000000..63d995eb --- /dev/null +++ b/src/pubgrub/version.rs.html @@ -0,0 +1,581 @@ +version.rs - source +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+
// SPDX-License-Identifier: MPL-2.0
+
+//! Traits and implementations to create and compare versions.
+
+use std::fmt::{self, Debug, Display};
+use std::str::FromStr;
+use thiserror::Error;
+
+/// Versions have a minimal version (a "0" version)
+/// and are ordered such that every version has a next one.
+pub trait Version: Clone + Ord + Debug + Display {
+    /// Returns the lowest version.
+    fn lowest() -> Self;
+    /// Returns the next version, the smallest strictly higher version.
+    fn bump(&self) -> Self;
+}
+
+/// Type for semantic versions: major.minor.patch.
+#[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
+pub struct SemanticVersion {
+    major: u32,
+    minor: u32,
+    patch: u32,
+}
+
+#[cfg(feature = "serde")]
+impl serde::Serialize for SemanticVersion {
+    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+    where
+        S: serde::Serializer,
+    {
+        serializer.serialize_str(&format!("{}", self))
+    }
+}
+
+#[cfg(feature = "serde")]
+impl<'de> serde::Deserialize<'de> for SemanticVersion {
+    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+    where
+        D: serde::Deserializer<'de>,
+    {
+        let s = String::deserialize(deserializer)?;
+        FromStr::from_str(&s).map_err(serde::de::Error::custom)
+    }
+}
+
+// Constructors
+impl SemanticVersion {
+    /// Create a version with "major", "minor" and "patch" values.
+    /// `version = major.minor.patch`
+    pub fn new(major: u32, minor: u32, patch: u32) -> Self {
+        Self {
+            major,
+            minor,
+            patch,
+        }
+    }
+
+    /// Version 0.0.0.
+    pub fn zero() -> Self {
+        Self::new(0, 0, 0)
+    }
+
+    /// Version 1.0.0.
+    pub fn one() -> Self {
+        Self::new(1, 0, 0)
+    }
+
+    /// Version 2.0.0.
+    pub fn two() -> Self {
+        Self::new(2, 0, 0)
+    }
+}
+
+// Convert a tuple (major, minor, patch) into a version.
+impl From<(u32, u32, u32)> for SemanticVersion {
+    fn from(tuple: (u32, u32, u32)) -> Self {
+        let (major, minor, patch) = tuple;
+        Self::new(major, minor, patch)
+    }
+}
+
+// Convert a &(major, minor, patch) into a version.
+impl From<&(u32, u32, u32)> for SemanticVersion {
+    fn from(tuple: &(u32, u32, u32)) -> Self {
+        let (major, minor, patch) = *tuple;
+        Self::new(major, minor, patch)
+    }
+}
+
+// Convert an &version into a version.
+impl From<&SemanticVersion> for SemanticVersion {
+    fn from(v: &SemanticVersion) -> Self {
+        *v
+    }
+}
+
+// Convert a version into a tuple (major, minor, patch).
+impl From<SemanticVersion> for (u32, u32, u32) {
+    fn from(v: SemanticVersion) -> Self {
+        (v.major, v.minor, v.patch)
+    }
+}
+
+// Bump versions.
+impl SemanticVersion {
+    /// Bump the patch number of a version.
+    pub fn bump_patch(self) -> Self {
+        Self::new(self.major, self.minor, self.patch + 1)
+    }
+
+    /// Bump the minor number of a version.
+    pub fn bump_minor(self) -> Self {
+        Self::new(self.major, self.minor + 1, 0)
+    }
+
+    /// Bump the major number of a version.
+    pub fn bump_major(self) -> Self {
+        Self::new(self.major + 1, 0, 0)
+    }
+}
+
+/// Error creating [SemanticVersion] from [String].
+#[derive(Error, Debug, PartialEq, Eq)]
+pub enum VersionParseError {
+    /// [SemanticVersion] must contain major, minor, patch versions.
+    #[error("version {full_version} must contain 3 numbers separated by dot")]
+    NotThreeParts {
+        /// [SemanticVersion] that was being parsed.
+        full_version: String,
+    },
+    /// Wrapper around [ParseIntError](core::num::ParseIntError).
+    #[error("cannot parse '{version_part}' in '{full_version}' as u32: {parse_error}")]
+    ParseIntError {
+        /// [SemanticVersion] that was being parsed.
+        full_version: String,
+        /// A version part where parsing failed.
+        version_part: String,
+        /// A specific error resulted from parsing a part of the version as [u32].
+        parse_error: String,
+    },
+}
+
+impl FromStr for SemanticVersion {
+    type Err = VersionParseError;
+
+    fn from_str(s: &str) -> Result<Self, Self::Err> {
+        let parse_u32 = |part: &str| {
+            part.parse::<u32>().map_err(|e| Self::Err::ParseIntError {
+                full_version: s.to_string(),
+                version_part: part.to_string(),
+                parse_error: e.to_string(),
+            })
+        };
+
+        let mut parts = s.split('.');
+        match (parts.next(), parts.next(), parts.next(), parts.next()) {
+            (Some(major), Some(minor), Some(patch), None) => {
+                let major = parse_u32(major)?;
+                let minor = parse_u32(minor)?;
+                let patch = parse_u32(patch)?;
+                Ok(Self {
+                    major,
+                    minor,
+                    patch,
+                })
+            }
+            _ => Err(Self::Err::NotThreeParts {
+                full_version: s.to_string(),
+            }),
+        }
+    }
+}
+
+#[test]
+fn from_str_for_semantic_version() {
+    let parse = |str: &str| str.parse::<SemanticVersion>();
+    assert!(parse(
+        &SemanticVersion {
+            major: 0,
+            minor: 1,
+            patch: 0
+        }
+        .to_string()
+    )
+    .is_ok());
+    assert!(parse("1.2.3").is_ok());
+    assert_eq!(
+        parse("1.abc.3"),
+        Err(VersionParseError::ParseIntError {
+            full_version: "1.abc.3".to_owned(),
+            version_part: "abc".to_owned(),
+            parse_error: "invalid digit found in string".to_owned(),
+        })
+    );
+    assert_eq!(
+        parse("1.2.-3"),
+        Err(VersionParseError::ParseIntError {
+            full_version: "1.2.-3".to_owned(),
+            version_part: "-3".to_owned(),
+            parse_error: "invalid digit found in string".to_owned(),
+        })
+    );
+    assert_eq!(
+        parse("1.2.9876543210"),
+        Err(VersionParseError::ParseIntError {
+            full_version: "1.2.9876543210".to_owned(),
+            version_part: "9876543210".to_owned(),
+            parse_error: "number too large to fit in target type".to_owned(),
+        })
+    );
+    assert_eq!(
+        parse("1.2"),
+        Err(VersionParseError::NotThreeParts {
+            full_version: "1.2".to_owned(),
+        })
+    );
+    assert_eq!(
+        parse("1.2.3."),
+        Err(VersionParseError::NotThreeParts {
+            full_version: "1.2.3.".to_owned(),
+        })
+    );
+}
+
+impl Display for SemanticVersion {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "{}.{}.{}", self.major, self.minor, self.patch)
+    }
+}
+
+// Implement Version for SemanticVersion.
+impl Version for SemanticVersion {
+    fn lowest() -> Self {
+        Self::zero()
+    }
+    fn bump(&self) -> Self {
+        self.bump_patch()
+    }
+}
+
+/// Simplest versions possible, just a positive number.
+#[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
+#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize,))]
+#[cfg_attr(feature = "serde", serde(transparent))]
+pub struct NumberVersion(pub u32);
+
+// Convert an usize into a version.
+impl From<u32> for NumberVersion {
+    fn from(v: u32) -> Self {
+        Self(v)
+    }
+}
+
+// Convert an &usize into a version.
+impl From<&u32> for NumberVersion {
+    fn from(v: &u32) -> Self {
+        Self(*v)
+    }
+}
+
+// Convert an &version into a version.
+impl From<&NumberVersion> for NumberVersion {
+    fn from(v: &NumberVersion) -> Self {
+        *v
+    }
+}
+
+// Convert a version into an usize.
+impl From<NumberVersion> for u32 {
+    fn from(version: NumberVersion) -> Self {
+        version.0
+    }
+}
+
+impl Display for NumberVersion {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "{}", self.0)
+    }
+}
+
+impl Version for NumberVersion {
+    fn lowest() -> Self {
+        Self(0)
+    }
+    fn bump(&self) -> Self {
+        Self(self.0 + 1)
+    }
+}
+
\ No newline at end of file diff --git a/src/pubgrub/version_set.rs.html b/src/pubgrub/version_set.rs.html new file mode 100644 index 00000000..22d32613 --- /dev/null +++ b/src/pubgrub/version_set.rs.html @@ -0,0 +1,123 @@ +version_set.rs - source +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+
// SPDX-License-Identifier: MPL-2.0
+
+//! As its name suggests, the [VersionSet] trait describes sets of versions.
+//!
+//! One needs to define
+//! - the associate type for versions,
+//! - two constructors for the empty set and a singleton set,
+//! - the complement and intersection set operations,
+//! - and a function to evaluate membership of versions.
+//!
+//! Two functions are automatically derived, thanks to the mathematical properties of sets.
+//! You can overwrite those implementations, but we highly recommend that you don't,
+//! except if you are confident in a correct implementation that brings much performance gains.
+//!
+//! It is also extremely important that the `Eq` trait is correctly implemented.
+//! In particular, you can only use `#[derive(Eq, PartialEq)]` if `Eq` is strictly equivalent to the
+//! structural equality, i.e. if version sets have canonical representations.
+//! Such problems may arise if your implementations of `complement()` and `intersection()` do not
+//! return canonical representations so be careful there.
+
+use std::fmt::{Debug, Display};
+
+/// Trait describing sets of versions.
+pub trait VersionSet: Debug + Display + Clone + Eq {
+    /// Version type associated with the sets manipulated.
+    type V: Debug + Display + Clone + Ord;
+
+    // Constructors
+    /// Constructor for an empty set containing no version.
+    fn empty() -> Self;
+    /// Constructor for a set containing exactly one version.
+    fn singleton(v: Self::V) -> Self;
+
+    // Operations
+    /// Compute the complement of this set.
+    fn complement(&self) -> Self;
+    /// Compute the intersection with another set.
+    fn intersection(&self, other: &Self) -> Self;
+
+    // Membership
+    /// Evaluate membership of a version in this set.
+    fn contains(&self, v: &Self::V) -> bool;
+
+    // Automatically implemented functions ###########################
+
+    /// Constructor for the set containing all versions.
+    /// Automatically implemented as `Self::empty().complement()`.
+    fn full() -> Self {
+        Self::empty().complement()
+    }
+
+    /// Compute the union with another set.
+    /// Thanks to set properties, this is automatically implemented as:
+    /// `self.complement().intersection(&other.complement()).complement()`
+    fn union(&self, other: &Self) -> Self {
+        self.complement()
+            .intersection(&other.complement())
+            .complement()
+    }
+}
+
\ No newline at end of file diff --git a/static.files/COPYRIGHT-23e9bde6c69aea69.txt b/static.files/COPYRIGHT-23e9bde6c69aea69.txt new file mode 100644 index 00000000..1447df79 --- /dev/null +++ b/static.files/COPYRIGHT-23e9bde6c69aea69.txt @@ -0,0 +1,50 @@ +# REUSE-IgnoreStart + +These documentation pages include resources by third parties. This copyright +file applies only to those resources. The following third party resources are +included, and carry their own copyright notices and license terms: + +* Fira Sans (FiraSans-Regular.woff2, FiraSans-Medium.woff2): + + Copyright (c) 2014, Mozilla Foundation https://mozilla.org/ + with Reserved Font Name Fira Sans. + + Copyright (c) 2014, Telefonica S.A. + + Licensed under the SIL Open Font License, Version 1.1. + See FiraSans-LICENSE.txt. + +* rustdoc.css, main.js, and playpen.js: + + Copyright 2015 The Rust Developers. + Licensed under the Apache License, Version 2.0 (see LICENSE-APACHE.txt) or + the MIT license (LICENSE-MIT.txt) at your option. + +* normalize.css: + + Copyright (c) Nicolas Gallagher and Jonathan Neal. + Licensed under the MIT license (see LICENSE-MIT.txt). + +* Source Code Pro (SourceCodePro-Regular.ttf.woff2, + SourceCodePro-Semibold.ttf.woff2, SourceCodePro-It.ttf.woff2): + + Copyright 2010, 2012 Adobe Systems Incorporated (http://www.adobe.com/), + with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark + of Adobe Systems Incorporated in the United States and/or other countries. + + Licensed under the SIL Open Font License, Version 1.1. + See SourceCodePro-LICENSE.txt. + +* Source Serif 4 (SourceSerif4-Regular.ttf.woff2, SourceSerif4-Bold.ttf.woff2, + SourceSerif4-It.ttf.woff2): + + Copyright 2014-2021 Adobe (http://www.adobe.com/), with Reserved Font Name + 'Source'. All Rights Reserved. Source is a trademark of Adobe in the United + States and/or other countries. + + Licensed under the SIL Open Font License, Version 1.1. + See SourceSerif4-LICENSE.md. + +This copyright file is intended to be distributed with rustdoc output. + +# REUSE-IgnoreEnd diff --git a/static.files/FiraSans-LICENSE-db4b642586e02d97.txt b/static.files/FiraSans-LICENSE-db4b642586e02d97.txt new file mode 100644 index 00000000..d7e9c149 --- /dev/null +++ b/static.files/FiraSans-LICENSE-db4b642586e02d97.txt @@ -0,0 +1,98 @@ +// REUSE-IgnoreStart + +Digitized data copyright (c) 2012-2015, The Mozilla Foundation and Telefonica S.A. +with Reserved Font Name < Fira >, + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. + +// REUSE-IgnoreEnd diff --git a/static.files/FiraSans-Medium-8f9a781e4970d388.woff2 b/static.files/FiraSans-Medium-8f9a781e4970d388.woff2 new file mode 100644 index 00000000..7a1e5fc5 Binary files /dev/null and b/static.files/FiraSans-Medium-8f9a781e4970d388.woff2 differ diff --git a/static.files/FiraSans-Regular-018c141bf0843ffd.woff2 b/static.files/FiraSans-Regular-018c141bf0843ffd.woff2 new file mode 100644 index 00000000..e766e06c Binary files /dev/null and b/static.files/FiraSans-Regular-018c141bf0843ffd.woff2 differ diff --git a/static.files/LICENSE-APACHE-b91fa81cba47b86a.txt b/static.files/LICENSE-APACHE-b91fa81cba47b86a.txt new file mode 100644 index 00000000..16fe87b0 --- /dev/null +++ b/static.files/LICENSE-APACHE-b91fa81cba47b86a.txt @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/static.files/LICENSE-MIT-65090b722b3f6c56.txt b/static.files/LICENSE-MIT-65090b722b3f6c56.txt new file mode 100644 index 00000000..31aa7938 --- /dev/null +++ b/static.files/LICENSE-MIT-65090b722b3f6c56.txt @@ -0,0 +1,23 @@ +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/static.files/NanumBarunGothic-0f09457c7a19b7c6.ttf.woff2 b/static.files/NanumBarunGothic-0f09457c7a19b7c6.ttf.woff2 new file mode 100644 index 00000000..1866ad4b Binary files /dev/null and b/static.files/NanumBarunGothic-0f09457c7a19b7c6.ttf.woff2 differ diff --git a/static.files/NanumBarunGothic-LICENSE-18c5adf4b52b4041.txt b/static.files/NanumBarunGothic-LICENSE-18c5adf4b52b4041.txt new file mode 100644 index 00000000..4b3edc29 --- /dev/null +++ b/static.files/NanumBarunGothic-LICENSE-18c5adf4b52b4041.txt @@ -0,0 +1,103 @@ +// REUSE-IgnoreStart + +Copyright (c) 2010, NAVER Corporation (https://www.navercorp.com/), + +with Reserved Font Name Nanum, Naver Nanum, NanumGothic, Naver NanumGothic, +NanumMyeongjo, Naver NanumMyeongjo, NanumBrush, Naver NanumBrush, NanumPen, +Naver NanumPen, Naver NanumGothicEco, NanumGothicEco, Naver NanumMyeongjoEco, +NanumMyeongjoEco, Naver NanumGothicLight, NanumGothicLight, NanumBarunGothic, +Naver NanumBarunGothic, NanumSquareRound, NanumBarunPen, MaruBuri + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. + +// REUSE-IgnoreEnd diff --git a/static.files/SourceCodePro-It-1cc31594bf4f1f79.ttf.woff2 b/static.files/SourceCodePro-It-1cc31594bf4f1f79.ttf.woff2 new file mode 100644 index 00000000..462c34ef Binary files /dev/null and b/static.files/SourceCodePro-It-1cc31594bf4f1f79.ttf.woff2 differ diff --git a/static.files/SourceCodePro-LICENSE-d180d465a756484a.txt b/static.files/SourceCodePro-LICENSE-d180d465a756484a.txt new file mode 100644 index 00000000..0d2941e1 --- /dev/null +++ b/static.files/SourceCodePro-LICENSE-d180d465a756484a.txt @@ -0,0 +1,97 @@ +// REUSE-IgnoreStart + +Copyright 2010, 2012 Adobe Systems Incorporated (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe Systems Incorporated in the United States and/or other countries. + +This Font Software is licensed under the SIL Open Font License, Version 1.1. + +This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. + +// REUSE-IgnoreEnd diff --git a/static.files/SourceCodePro-Regular-562dcc5011b6de7d.ttf.woff2 b/static.files/SourceCodePro-Regular-562dcc5011b6de7d.ttf.woff2 new file mode 100644 index 00000000..10b558e0 Binary files /dev/null and b/static.files/SourceCodePro-Regular-562dcc5011b6de7d.ttf.woff2 differ diff --git a/static.files/SourceCodePro-Semibold-d899c5a5c4aeb14a.ttf.woff2 b/static.files/SourceCodePro-Semibold-d899c5a5c4aeb14a.ttf.woff2 new file mode 100644 index 00000000..5ec64eef Binary files /dev/null and b/static.files/SourceCodePro-Semibold-d899c5a5c4aeb14a.ttf.woff2 differ diff --git a/static.files/SourceSerif4-Bold-a2c9cd1067f8b328.ttf.woff2 b/static.files/SourceSerif4-Bold-a2c9cd1067f8b328.ttf.woff2 new file mode 100644 index 00000000..181a07f6 Binary files /dev/null and b/static.files/SourceSerif4-Bold-a2c9cd1067f8b328.ttf.woff2 differ diff --git a/static.files/SourceSerif4-It-acdfaf1a8af734b1.ttf.woff2 b/static.files/SourceSerif4-It-acdfaf1a8af734b1.ttf.woff2 new file mode 100644 index 00000000..2ae08a7b Binary files /dev/null and b/static.files/SourceSerif4-It-acdfaf1a8af734b1.ttf.woff2 differ diff --git a/static.files/SourceSerif4-LICENSE-3bb119e13b1258b7.md b/static.files/SourceSerif4-LICENSE-3bb119e13b1258b7.md new file mode 100644 index 00000000..175fa4f4 --- /dev/null +++ b/static.files/SourceSerif4-LICENSE-3bb119e13b1258b7.md @@ -0,0 +1,98 @@ + + +Copyright 2014-2021 Adobe (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe in the United States and/or other countries. +Copyright 2014 - 2023 Adobe (http://www.adobe.com/), with Reserved Font Name ‘Source’. All Rights Reserved. Source is a trademark of Adobe in the United States and/or other countries. + +This Font Software is licensed under the SIL Open Font License, Version 1.1. + +This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. + + diff --git a/static.files/SourceSerif4-Regular-46f98efaafac5295.ttf.woff2 b/static.files/SourceSerif4-Regular-46f98efaafac5295.ttf.woff2 new file mode 100644 index 00000000..0263fc30 Binary files /dev/null and b/static.files/SourceSerif4-Regular-46f98efaafac5295.ttf.woff2 differ diff --git a/static.files/clipboard-7571035ce49a181d.svg b/static.files/clipboard-7571035ce49a181d.svg new file mode 100644 index 00000000..8adbd996 --- /dev/null +++ b/static.files/clipboard-7571035ce49a181d.svg @@ -0,0 +1 @@ + diff --git a/static.files/favicon-16x16-8b506e7a72182f1c.png b/static.files/favicon-16x16-8b506e7a72182f1c.png new file mode 100644 index 00000000..ea4b45ca Binary files /dev/null and b/static.files/favicon-16x16-8b506e7a72182f1c.png differ diff --git a/static.files/favicon-2c020d218678b618.svg b/static.files/favicon-2c020d218678b618.svg new file mode 100644 index 00000000..8b34b511 --- /dev/null +++ b/static.files/favicon-2c020d218678b618.svg @@ -0,0 +1,24 @@ + + + + + diff --git a/static.files/favicon-32x32-422f7d1d52889060.png b/static.files/favicon-32x32-422f7d1d52889060.png new file mode 100644 index 00000000..69b8613c Binary files /dev/null and b/static.files/favicon-32x32-422f7d1d52889060.png differ diff --git a/static.files/main-48f368f3872407c8.js b/static.files/main-48f368f3872407c8.js new file mode 100644 index 00000000..987fae42 --- /dev/null +++ b/static.files/main-48f368f3872407c8.js @@ -0,0 +1,11 @@ +"use strict";window.RUSTDOC_TOOLTIP_HOVER_MS=300;window.RUSTDOC_TOOLTIP_HOVER_EXIT_MS=450;function resourcePath(basename,extension){return getVar("root-path")+basename+getVar("resource-suffix")+extension}function hideMain(){addClass(document.getElementById(MAIN_ID),"hidden")}function showMain(){removeClass(document.getElementById(MAIN_ID),"hidden")}function blurHandler(event,parentElem,hideCallback){if(!parentElem.contains(document.activeElement)&&!parentElem.contains(event.relatedTarget)){hideCallback()}}window.rootPath=getVar("root-path");window.currentCrate=getVar("current-crate");function setMobileTopbar(){const mobileTopbar=document.querySelector(".mobile-topbar");const locationTitle=document.querySelector(".sidebar h2.location");if(mobileTopbar){const mobileTitle=document.createElement("h2");mobileTitle.className="location";if(hasClass(document.querySelector(".rustdoc"),"crate")){mobileTitle.innerText=`Crate ${window.currentCrate}`}else if(locationTitle){mobileTitle.innerHTML=locationTitle.innerHTML}mobileTopbar.appendChild(mobileTitle)}}function getVirtualKey(ev){if("key"in ev&&typeof ev.key!=="undefined"){return ev.key}const c=ev.charCode||ev.keyCode;if(c===27){return"Escape"}return String.fromCharCode(c)}const MAIN_ID="main-content";const SETTINGS_BUTTON_ID="settings-menu";const ALTERNATIVE_DISPLAY_ID="alternative-display";const NOT_DISPLAYED_ID="not-displayed";const HELP_BUTTON_ID="help-button";function getSettingsButton(){return document.getElementById(SETTINGS_BUTTON_ID)}function getHelpButton(){return document.getElementById(HELP_BUTTON_ID)}function getNakedUrl(){return window.location.href.split("?")[0].split("#")[0]}function insertAfter(newNode,referenceNode){referenceNode.parentNode.insertBefore(newNode,referenceNode.nextSibling)}function getOrCreateSection(id,classes){let el=document.getElementById(id);if(!el){el=document.createElement("section");el.id=id;el.className=classes;insertAfter(el,document.getElementById(MAIN_ID))}return el}function getAlternativeDisplayElem(){return getOrCreateSection(ALTERNATIVE_DISPLAY_ID,"content hidden")}function getNotDisplayedElem(){return getOrCreateSection(NOT_DISPLAYED_ID,"hidden")}function switchDisplayedElement(elemToDisplay){const el=getAlternativeDisplayElem();if(el.children.length>0){getNotDisplayedElem().appendChild(el.firstElementChild)}if(elemToDisplay===null){addClass(el,"hidden");showMain();return}el.appendChild(elemToDisplay);hideMain();removeClass(el,"hidden")}function browserSupportsHistoryApi(){return window.history&&typeof window.history.pushState==="function"}function preLoadCss(cssUrl){const link=document.createElement("link");link.href=cssUrl;link.rel="preload";link.as="style";document.getElementsByTagName("head")[0].appendChild(link)}(function(){const isHelpPage=window.location.pathname.endsWith("/help.html");function loadScript(url){const script=document.createElement("script");script.src=url;document.head.append(script)}getSettingsButton().onclick=event=>{if(event.ctrlKey||event.altKey||event.metaKey){return}window.hideAllModals(false);addClass(getSettingsButton(),"rotate");event.preventDefault();loadScript(getVar("static-root-path")+getVar("settings-js"));setTimeout(()=>{const themes=getVar("themes").split(",");for(const theme of themes){if(theme!==""){preLoadCss(getVar("root-path")+theme+".css")}}},0)};window.searchState={loadingText:"Loading search results...",input:document.getElementsByClassName("search-input")[0],outputElement:()=>{let el=document.getElementById("search");if(!el){el=document.createElement("section");el.id="search";getNotDisplayedElem().appendChild(el)}return el},title:document.title,titleBeforeSearch:document.title,timeout:null,currentTab:0,focusedByTab:[null,null,null],clearInputTimeout:()=>{if(searchState.timeout!==null){clearTimeout(searchState.timeout);searchState.timeout=null}},isDisplayed:()=>searchState.outputElement().parentElement.id===ALTERNATIVE_DISPLAY_ID,focus:()=>{searchState.input.focus()},defocus:()=>{searchState.input.blur()},showResults:search=>{if(search===null||typeof search==="undefined"){search=searchState.outputElement()}switchDisplayedElement(search);searchState.mouseMovedAfterSearch=false;document.title=searchState.title},removeQueryParameters:()=>{document.title=searchState.titleBeforeSearch;if(browserSupportsHistoryApi()){history.replaceState(null,"",getNakedUrl()+window.location.hash)}},hideResults:()=>{switchDisplayedElement(null);searchState.removeQueryParameters()},getQueryStringParams:()=>{const params={};window.location.search.substring(1).split("&").map(s=>{const pair=s.split("=").map(x=>x.replace(/\+/g," "));params[decodeURIComponent(pair[0])]=typeof pair[1]==="undefined"?null:decodeURIComponent(pair[1])});return params},setup:()=>{const search_input=searchState.input;if(!searchState.input){return}let searchLoaded=false;function loadSearch(){if(!searchLoaded){searchLoaded=true;loadScript(getVar("static-root-path")+getVar("search-js"));loadScript(resourcePath("search-index",".js"))}}search_input.addEventListener("focus",()=>{search_input.origPlaceholder=search_input.placeholder;search_input.placeholder="Type your search here.";loadSearch()});if(search_input.value!==""){loadSearch()}const params=searchState.getQueryStringParams();if(params.search!==undefined){searchState.setLoadingSearch();loadSearch()}},setLoadingSearch:()=>{const search=searchState.outputElement();search.innerHTML="

"+searchState.loadingText+"

";searchState.showResults(search)},};const toggleAllDocsId="toggle-all-docs";let savedHash="";function handleHashes(ev){if(ev!==null&&searchState.isDisplayed()&&ev.newURL){switchDisplayedElement(null);const hash=ev.newURL.slice(ev.newURL.indexOf("#")+1);if(browserSupportsHistoryApi()){history.replaceState(null,"",getNakedUrl()+window.location.search+"#"+hash)}const elem=document.getElementById(hash);if(elem){elem.scrollIntoView()}}const pageId=window.location.hash.replace(/^#/,"");if(savedHash!==pageId){savedHash=pageId;if(pageId!==""){expandSection(pageId)}}if(savedHash.startsWith("impl-")){const splitAt=savedHash.indexOf("/");if(splitAt!==-1){const implId=savedHash.slice(0,splitAt);const assocId=savedHash.slice(splitAt+1);const implElem=document.getElementById(implId);if(implElem&&implElem.parentElement.tagName==="SUMMARY"&&implElem.parentElement.parentElement.tagName==="DETAILS"){onEachLazy(implElem.parentElement.parentElement.querySelectorAll(`[id^="${assocId}"]`),item=>{const numbered=/([^-]+)-([0-9]+)/.exec(item.id);if(item.id===assocId||(numbered&&numbered[1]===assocId)){openParentDetails(item);item.scrollIntoView();setTimeout(()=>{window.location.replace("#"+item.id)},0)}})}}}}function onHashChange(ev){hideSidebar();handleHashes(ev)}function openParentDetails(elem){while(elem){if(elem.tagName==="DETAILS"){elem.open=true}elem=elem.parentNode}}function expandSection(id){openParentDetails(document.getElementById(id))}function handleEscape(ev){searchState.clearInputTimeout();searchState.hideResults();ev.preventDefault();searchState.defocus();window.hideAllModals(true)}function handleShortcut(ev){const disableShortcuts=getSettingValue("disable-shortcuts")==="true";if(ev.ctrlKey||ev.altKey||ev.metaKey||disableShortcuts){return}if(document.activeElement.tagName==="INPUT"&&document.activeElement.type!=="checkbox"&&document.activeElement.type!=="radio"){switch(getVirtualKey(ev)){case"Escape":handleEscape(ev);break}}else{switch(getVirtualKey(ev)){case"Escape":handleEscape(ev);break;case"s":case"S":ev.preventDefault();searchState.focus();break;case"+":ev.preventDefault();expandAllDocs();break;case"-":ev.preventDefault();collapseAllDocs();break;case"?":showHelp();break;default:break}}}document.addEventListener("keypress",handleShortcut);document.addEventListener("keydown",handleShortcut);function addSidebarItems(){if(!window.SIDEBAR_ITEMS){return}const sidebar=document.getElementsByClassName("sidebar-elems")[0];function block(shortty,id,longty){const filtered=window.SIDEBAR_ITEMS[shortty];if(!filtered){return}const modpath=hasClass(document.querySelector(".rustdoc"),"mod")?"../":"";const h3=document.createElement("h3");h3.innerHTML=`${longty}`;const ul=document.createElement("ul");ul.className="block "+shortty;for(const name of filtered){let path;if(shortty==="mod"){path=`${modpath}${name}/index.html`}else{path=`${modpath}${shortty}.${name}.html`}let current_page=document.location.href.toString();if(current_page.endsWith("/")){current_page+="index.html"}const link=document.createElement("a");link.href=path;if(path===current_page){link.className="current"}link.textContent=name;const li=document.createElement("li");li.appendChild(link);ul.appendChild(li)}sidebar.appendChild(h3);sidebar.appendChild(ul)}if(sidebar){block("primitive","primitives","Primitive Types");block("mod","modules","Modules");block("macro","macros","Macros");block("struct","structs","Structs");block("enum","enums","Enums");block("constant","constants","Constants");block("static","static","Statics");block("trait","traits","Traits");block("fn","functions","Functions");block("type","types","Type Aliases");block("union","unions","Unions");block("foreigntype","foreign-types","Foreign Types");block("keyword","keywords","Keywords");block("opaque","opaque-types","Opaque Types");block("attr","attributes","Attribute Macros");block("derive","derives","Derive Macros");block("traitalias","trait-aliases","Trait Aliases")}}window.register_implementors=imp=>{const implementors=document.getElementById("implementors-list");const synthetic_implementors=document.getElementById("synthetic-implementors-list");const inlined_types=new Set();const TEXT_IDX=0;const SYNTHETIC_IDX=1;const TYPES_IDX=2;if(synthetic_implementors){onEachLazy(synthetic_implementors.getElementsByClassName("impl"),el=>{const aliases=el.getAttribute("data-aliases");if(!aliases){return}aliases.split(",").forEach(alias=>{inlined_types.add(alias)})})}let currentNbImpls=implementors.getElementsByClassName("impl").length;const traitName=document.querySelector(".main-heading h1 > .trait").textContent;const baseIdName="impl-"+traitName+"-";const libs=Object.getOwnPropertyNames(imp);const script=document.querySelector("script[data-ignore-extern-crates]");const ignoreExternCrates=new Set((script?script.getAttribute("data-ignore-extern-crates"):"").split(","));for(const lib of libs){if(lib===window.currentCrate||ignoreExternCrates.has(lib)){continue}const structs=imp[lib];struct_loop:for(const struct of structs){const list=struct[SYNTHETIC_IDX]?synthetic_implementors:implementors;if(struct[SYNTHETIC_IDX]){for(const struct_type of struct[TYPES_IDX]){if(inlined_types.has(struct_type)){continue struct_loop}inlined_types.add(struct_type)}}const code=document.createElement("h3");code.innerHTML=struct[TEXT_IDX];addClass(code,"code-header");onEachLazy(code.getElementsByTagName("a"),elem=>{const href=elem.getAttribute("href");if(href&&!href.startsWith("#")&&!/^(?:[a-z+]+:)?\/\//.test(href)){elem.setAttribute("href",window.rootPath+href)}});const currentId=baseIdName+currentNbImpls;const anchor=document.createElement("a");anchor.href="#"+currentId;addClass(anchor,"anchor");const display=document.createElement("div");display.id=currentId;addClass(display,"impl");display.appendChild(anchor);display.appendChild(code);list.appendChild(display);currentNbImpls+=1}}};if(window.pending_implementors){window.register_implementors(window.pending_implementors)}window.register_type_impls=imp=>{if(!imp||!imp[window.currentCrate]){return}window.pending_type_impls=null;const idMap=new Map();let implementations=document.getElementById("implementations-list");let trait_implementations=document.getElementById("trait-implementations-list");let trait_implementations_header=document.getElementById("trait-implementations");const script=document.querySelector("script[data-self-path]");const selfPath=script?script.getAttribute("data-self-path"):null;const mainContent=document.querySelector("#main-content");const sidebarSection=document.querySelector(".sidebar section");let methods=document.querySelector(".sidebar .block.method");let associatedTypes=document.querySelector(".sidebar .block.associatedtype");let associatedConstants=document.querySelector(".sidebar .block.associatedconstant");let sidebarTraitList=document.querySelector(".sidebar .block.trait-implementation");for(const impList of imp[window.currentCrate]){const types=impList.slice(2);const text=impList[0];const isTrait=impList[1]!==0;const traitName=impList[1];if(types.indexOf(selfPath)===-1){continue}let outputList=isTrait?trait_implementations:implementations;if(outputList===null){const outputListName=isTrait?"Trait Implementations":"Implementations";const outputListId=isTrait?"trait-implementations-list":"implementations-list";const outputListHeaderId=isTrait?"trait-implementations":"implementations";const outputListHeader=document.createElement("h2");outputListHeader.id=outputListHeaderId;outputListHeader.innerText=outputListName;outputList=document.createElement("div");outputList.id=outputListId;if(isTrait){const link=document.createElement("a");link.href=`#${outputListHeaderId}`;link.innerText="Trait Implementations";const h=document.createElement("h3");h.appendChild(link);trait_implementations=outputList;trait_implementations_header=outputListHeader;sidebarSection.appendChild(h);sidebarTraitList=document.createElement("ul");sidebarTraitList.className="block trait-implementation";sidebarSection.appendChild(sidebarTraitList);mainContent.appendChild(outputListHeader);mainContent.appendChild(outputList)}else{implementations=outputList;if(trait_implementations){mainContent.insertBefore(outputListHeader,trait_implementations_header);mainContent.insertBefore(outputList,trait_implementations_header)}else{const mainContent=document.querySelector("#main-content");mainContent.appendChild(outputListHeader);mainContent.appendChild(outputList)}}}const template=document.createElement("template");template.innerHTML=text;onEachLazy(template.content.querySelectorAll("a"),elem=>{const href=elem.getAttribute("href");if(href&&!href.startsWith("#")&&!/^(?:[a-z+]+:)?\/\//.test(href)){elem.setAttribute("href",window.rootPath+href)}});onEachLazy(template.content.querySelectorAll("[id]"),el=>{let i=0;if(idMap.has(el.id)){i=idMap.get(el.id)}else if(document.getElementById(el.id)){i=1;while(document.getElementById(`${el.id}-${2 * i}`)){i=2*i}while(document.getElementById(`${el.id}-${i}`)){i+=1}}if(i!==0){const oldHref=`#${el.id}`;const newHref=`#${el.id}-${i}`;el.id=`${el.id}-${i}`;onEachLazy(template.content.querySelectorAll("a[href]"),link=>{if(link.getAttribute("href")===oldHref){link.href=newHref}})}idMap.set(el.id,i+1)});const templateAssocItems=template.content.querySelectorAll("section.tymethod, "+"section.method, section.associatedtype, section.associatedconstant");if(isTrait){const li=document.createElement("li");const a=document.createElement("a");a.href=`#${template.content.querySelector(".impl").id}`;a.textContent=traitName;li.appendChild(a);sidebarTraitList.append(li)}else{onEachLazy(templateAssocItems,item=>{let block=hasClass(item,"associatedtype")?associatedTypes:(hasClass(item,"associatedconstant")?associatedConstants:(methods));if(!block){const blockTitle=hasClass(item,"associatedtype")?"Associated Types":(hasClass(item,"associatedconstant")?"Associated Constants":("Methods"));const blockClass=hasClass(item,"associatedtype")?"associatedtype":(hasClass(item,"associatedconstant")?"associatedconstant":("method"));const blockHeader=document.createElement("h3");const blockLink=document.createElement("a");blockLink.href="#implementations";blockLink.innerText=blockTitle;blockHeader.appendChild(blockLink);block=document.createElement("ul");block.className=`block ${blockClass}`;const insertionReference=methods||sidebarTraitList;if(insertionReference){const insertionReferenceH=insertionReference.previousElementSibling;sidebarSection.insertBefore(blockHeader,insertionReferenceH);sidebarSection.insertBefore(block,insertionReferenceH)}else{sidebarSection.appendChild(blockHeader);sidebarSection.appendChild(block)}if(hasClass(item,"associatedtype")){associatedTypes=block}else if(hasClass(item,"associatedconstant")){associatedConstants=block}else{methods=block}}const li=document.createElement("li");const a=document.createElement("a");a.innerText=item.id.split("-")[0].split(".")[1];a.href=`#${item.id}`;li.appendChild(a);block.appendChild(li)})}outputList.appendChild(template.content)}for(const list of[methods,associatedTypes,associatedConstants,sidebarTraitList]){if(!list){continue}const newChildren=Array.prototype.slice.call(list.children);newChildren.sort((a,b)=>{const aI=a.innerText;const bI=b.innerText;return aIbI?1:0});list.replaceChildren(...newChildren)}};if(window.pending_type_impls){window.register_type_impls(window.pending_type_impls)}function addSidebarCrates(){if(!window.ALL_CRATES){return}const sidebarElems=document.getElementsByClassName("sidebar-elems")[0];if(!sidebarElems){return}const h3=document.createElement("h3");h3.innerHTML="Crates";const ul=document.createElement("ul");ul.className="block crate";for(const crate of window.ALL_CRATES){const link=document.createElement("a");link.href=window.rootPath+crate+"/index.html";link.textContent=crate;const li=document.createElement("li");if(window.rootPath!=="./"&&crate===window.currentCrate){li.className="current"}li.appendChild(link);ul.appendChild(li)}sidebarElems.appendChild(h3);sidebarElems.appendChild(ul)}function expandAllDocs(){const innerToggle=document.getElementById(toggleAllDocsId);removeClass(innerToggle,"will-expand");onEachLazy(document.getElementsByClassName("toggle"),e=>{if(!hasClass(e,"type-contents-toggle")&&!hasClass(e,"more-examples-toggle")){e.open=true}});innerToggle.title="collapse all docs";innerToggle.children[0].innerText="\u2212"}function collapseAllDocs(){const innerToggle=document.getElementById(toggleAllDocsId);addClass(innerToggle,"will-expand");onEachLazy(document.getElementsByClassName("toggle"),e=>{if(e.parentNode.id!=="implementations-list"||(!hasClass(e,"implementors-toggle")&&!hasClass(e,"type-contents-toggle"))){e.open=false}});innerToggle.title="expand all docs";innerToggle.children[0].innerText="+"}function toggleAllDocs(){const innerToggle=document.getElementById(toggleAllDocsId);if(!innerToggle){return}if(hasClass(innerToggle,"will-expand")){expandAllDocs()}else{collapseAllDocs()}}(function(){const toggles=document.getElementById(toggleAllDocsId);if(toggles){toggles.onclick=toggleAllDocs}const hideMethodDocs=getSettingValue("auto-hide-method-docs")==="true";const hideImplementations=getSettingValue("auto-hide-trait-implementations")==="true";const hideLargeItemContents=getSettingValue("auto-hide-large-items")!=="false";function setImplementorsTogglesOpen(id,open){const list=document.getElementById(id);if(list!==null){onEachLazy(list.getElementsByClassName("implementors-toggle"),e=>{e.open=open})}}if(hideImplementations){setImplementorsTogglesOpen("trait-implementations-list",false);setImplementorsTogglesOpen("blanket-implementations-list",false)}onEachLazy(document.getElementsByClassName("toggle"),e=>{if(!hideLargeItemContents&&hasClass(e,"type-contents-toggle")){e.open=true}if(hideMethodDocs&&hasClass(e,"method-toggle")){e.open=false}})}());window.rustdoc_add_line_numbers_to_examples=()=>{onEachLazy(document.getElementsByClassName("rust-example-rendered"),x=>{const parent=x.parentNode;const line_numbers=parent.querySelectorAll(".example-line-numbers");if(line_numbers.length>0){return}const count=x.textContent.split("\n").length;const elems=[];for(let i=0;i{onEachLazy(document.getElementsByClassName("rust-example-rendered"),x=>{const parent=x.parentNode;const line_numbers=parent.querySelectorAll(".example-line-numbers");for(const node of line_numbers){parent.removeChild(node)}})};if(getSettingValue("line-numbers")==="true"){window.rustdoc_add_line_numbers_to_examples()}function showSidebar(){window.hideAllModals(false);const sidebar=document.getElementsByClassName("sidebar")[0];addClass(sidebar,"shown")}function hideSidebar(){const sidebar=document.getElementsByClassName("sidebar")[0];removeClass(sidebar,"shown")}window.addEventListener("resize",()=>{if(window.CURRENT_TOOLTIP_ELEMENT){const base=window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE;const force_visible=base.TOOLTIP_FORCE_VISIBLE;hideTooltip(false);if(force_visible){showTooltip(base);base.TOOLTIP_FORCE_VISIBLE=true}}});const mainElem=document.getElementById(MAIN_ID);if(mainElem){mainElem.addEventListener("click",hideSidebar)}onEachLazy(document.querySelectorAll("a[href^='#']"),el=>{el.addEventListener("click",()=>{expandSection(el.hash.slice(1));hideSidebar()})});onEachLazy(document.querySelectorAll(".toggle > summary:not(.hideme)"),el=>{el.addEventListener("click",e=>{if(e.target.tagName!=="SUMMARY"&&e.target.tagName!=="A"){e.preventDefault()}})});function showTooltip(e){const notable_ty=e.getAttribute("data-notable-ty");if(!window.NOTABLE_TRAITS&¬able_ty){const data=document.getElementById("notable-traits-data");if(data){window.NOTABLE_TRAITS=JSON.parse(data.innerText)}else{throw new Error("showTooltip() called with notable without any notable traits!")}}if(window.CURRENT_TOOLTIP_ELEMENT&&window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE===e){clearTooltipHoverTimeout(window.CURRENT_TOOLTIP_ELEMENT);return}window.hideAllModals(false);const wrapper=document.createElement("div");if(notable_ty){wrapper.innerHTML="
"+window.NOTABLE_TRAITS[notable_ty]+"
"}else{if(e.getAttribute("title")!==null){e.setAttribute("data-title",e.getAttribute("title"));e.removeAttribute("title")}if(e.getAttribute("data-title")!==null){const titleContent=document.createElement("div");titleContent.className="content";titleContent.appendChild(document.createTextNode(e.getAttribute("data-title")));wrapper.appendChild(titleContent)}}wrapper.className="tooltip popover";const focusCatcher=document.createElement("div");focusCatcher.setAttribute("tabindex","0");focusCatcher.onfocus=hideTooltip;wrapper.appendChild(focusCatcher);const pos=e.getBoundingClientRect();wrapper.style.top=(pos.top+window.scrollY+pos.height)+"px";wrapper.style.left=0;wrapper.style.right="auto";wrapper.style.visibility="hidden";const body=document.getElementsByTagName("body")[0];body.appendChild(wrapper);const wrapperPos=wrapper.getBoundingClientRect();const finalPos=pos.left+window.scrollX-wrapperPos.width+24;if(finalPos>0){wrapper.style.left=finalPos+"px"}else{wrapper.style.setProperty("--popover-arrow-offset",(wrapperPos.right-pos.right+4)+"px")}wrapper.style.visibility="";window.CURRENT_TOOLTIP_ELEMENT=wrapper;window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE=e;clearTooltipHoverTimeout(window.CURRENT_TOOLTIP_ELEMENT);wrapper.onpointerenter=ev=>{if(ev.pointerType!=="mouse"){return}clearTooltipHoverTimeout(e)};wrapper.onpointerleave=ev=>{if(ev.pointerType!=="mouse"){return}if(!e.TOOLTIP_FORCE_VISIBLE&&!e.contains(ev.relatedTarget)){setTooltipHoverTimeout(e,false);addClass(wrapper,"fade-out")}}}function setTooltipHoverTimeout(element,show){clearTooltipHoverTimeout(element);if(!show&&!window.CURRENT_TOOLTIP_ELEMENT){return}if(show&&window.CURRENT_TOOLTIP_ELEMENT){return}if(window.CURRENT_TOOLTIP_ELEMENT&&window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE!==element){return}element.TOOLTIP_HOVER_TIMEOUT=setTimeout(()=>{if(show){showTooltip(element)}else if(!element.TOOLTIP_FORCE_VISIBLE){hideTooltip(false)}},show?window.RUSTDOC_TOOLTIP_HOVER_MS:window.RUSTDOC_TOOLTIP_HOVER_EXIT_MS)}function clearTooltipHoverTimeout(element){if(element.TOOLTIP_HOVER_TIMEOUT!==undefined){removeClass(window.CURRENT_TOOLTIP_ELEMENT,"fade-out");clearTimeout(element.TOOLTIP_HOVER_TIMEOUT);delete element.TOOLTIP_HOVER_TIMEOUT}}function tooltipBlurHandler(event){if(window.CURRENT_TOOLTIP_ELEMENT&&!window.CURRENT_TOOLTIP_ELEMENT.contains(document.activeElement)&&!window.CURRENT_TOOLTIP_ELEMENT.contains(event.relatedTarget)&&!window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE.contains(document.activeElement)&&!window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE.contains(event.relatedTarget)){setTimeout(()=>hideTooltip(false),0)}}function hideTooltip(focus){if(window.CURRENT_TOOLTIP_ELEMENT){if(window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE.TOOLTIP_FORCE_VISIBLE){if(focus){window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE.focus()}window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE.TOOLTIP_FORCE_VISIBLE=false}const body=document.getElementsByTagName("body")[0];body.removeChild(window.CURRENT_TOOLTIP_ELEMENT);clearTooltipHoverTimeout(window.CURRENT_TOOLTIP_ELEMENT);window.CURRENT_TOOLTIP_ELEMENT=null}}onEachLazy(document.getElementsByClassName("tooltip"),e=>{e.onclick=()=>{e.TOOLTIP_FORCE_VISIBLE=e.TOOLTIP_FORCE_VISIBLE?false:true;if(window.CURRENT_TOOLTIP_ELEMENT&&!e.TOOLTIP_FORCE_VISIBLE){hideTooltip(true)}else{showTooltip(e);window.CURRENT_TOOLTIP_ELEMENT.setAttribute("tabindex","0");window.CURRENT_TOOLTIP_ELEMENT.focus();window.CURRENT_TOOLTIP_ELEMENT.onblur=tooltipBlurHandler}return false};e.onpointerenter=ev=>{if(ev.pointerType!=="mouse"){return}setTooltipHoverTimeout(e,true)};e.onpointermove=ev=>{if(ev.pointerType!=="mouse"){return}setTooltipHoverTimeout(e,true)};e.onpointerleave=ev=>{if(ev.pointerType!=="mouse"){return}if(!e.TOOLTIP_FORCE_VISIBLE&&window.CURRENT_TOOLTIP_ELEMENT&&!window.CURRENT_TOOLTIP_ELEMENT.contains(ev.relatedTarget)){setTooltipHoverTimeout(e,false);addClass(window.CURRENT_TOOLTIP_ELEMENT,"fade-out")}}});const sidebar_menu_toggle=document.getElementsByClassName("sidebar-menu-toggle")[0];if(sidebar_menu_toggle){sidebar_menu_toggle.addEventListener("click",()=>{const sidebar=document.getElementsByClassName("sidebar")[0];if(!hasClass(sidebar,"shown")){showSidebar()}else{hideSidebar()}})}function helpBlurHandler(event){blurHandler(event,getHelpButton(),window.hidePopoverMenus)}function buildHelpMenu(){const book_info=document.createElement("span");const channel=getVar("channel");book_info.className="top";book_info.innerHTML=`You can find more information in \ +the rustdoc book.`;const shortcuts=[["?","Show this help dialog"],["S","Focus the search field"],["↑","Move up in search results"],["↓","Move down in search results"],["← / →","Switch result tab (when results focused)"],["⏎","Go to active search result"],["+","Expand all sections"],["-","Collapse all sections"],].map(x=>"
"+x[0].split(" ").map((y,index)=>((index&1)===0?""+y+"":" "+y+" ")).join("")+"
"+x[1]+"
").join("");const div_shortcuts=document.createElement("div");addClass(div_shortcuts,"shortcuts");div_shortcuts.innerHTML="

Keyboard Shortcuts

"+shortcuts+"
";const infos=[`For a full list of all search features, take a look here.`,"Prefix searches with a type followed by a colon (e.g., fn:) to \ + restrict the search to a given item kind.","Accepted kinds are: fn, mod, struct, \ + enum, trait, type, macro, \ + and const.","Search functions by type signature (e.g., vec -> usize or \ + -> vec or String, enum:Cow -> bool)","You can look for items with an exact name by putting double quotes around \ + your request: \"string\"","Look for functions that accept or return \ + slices and \ + arrays by writing \ + square brackets (e.g., -> [u8] or [] -> Option)","Look for items inside another one by searching for a path: vec::Vec",].map(x=>"

"+x+"

").join("");const div_infos=document.createElement("div");addClass(div_infos,"infos");div_infos.innerHTML="

Search Tricks

"+infos;const rustdoc_version=document.createElement("span");rustdoc_version.className="bottom";const rustdoc_version_code=document.createElement("code");rustdoc_version_code.innerText="rustdoc "+getVar("rustdoc-version");rustdoc_version.appendChild(rustdoc_version_code);const container=document.createElement("div");if(!isHelpPage){container.className="popover"}container.id="help";container.style.display="none";const side_by_side=document.createElement("div");side_by_side.className="side-by-side";side_by_side.appendChild(div_shortcuts);side_by_side.appendChild(div_infos);container.appendChild(book_info);container.appendChild(side_by_side);container.appendChild(rustdoc_version);if(isHelpPage){const help_section=document.createElement("section");help_section.appendChild(container);document.getElementById("main-content").appendChild(help_section);container.style.display="block"}else{const help_button=getHelpButton();help_button.appendChild(container);container.onblur=helpBlurHandler;help_button.onblur=helpBlurHandler;help_button.children[0].onblur=helpBlurHandler}return container}window.hideAllModals=switchFocus=>{hideSidebar();window.hidePopoverMenus();hideTooltip(switchFocus)};window.hidePopoverMenus=()=>{onEachLazy(document.querySelectorAll(".search-form .popover"),elem=>{elem.style.display="none"})};function getHelpMenu(buildNeeded){let menu=getHelpButton().querySelector(".popover");if(!menu&&buildNeeded){menu=buildHelpMenu()}return menu}function showHelp(){getHelpButton().querySelector("a").focus();const menu=getHelpMenu(true);if(menu.style.display==="none"){window.hideAllModals();menu.style.display=""}}if(isHelpPage){showHelp();document.querySelector(`#${HELP_BUTTON_ID} > a`).addEventListener("click",event=>{const target=event.target;if(target.tagName!=="A"||target.parentElement.id!==HELP_BUTTON_ID||event.ctrlKey||event.altKey||event.metaKey){return}event.preventDefault()})}else{document.querySelector(`#${HELP_BUTTON_ID} > a`).addEventListener("click",event=>{const target=event.target;if(target.tagName!=="A"||target.parentElement.id!==HELP_BUTTON_ID||event.ctrlKey||event.altKey||event.metaKey){return}event.preventDefault();const menu=getHelpMenu(true);const shouldShowHelp=menu.style.display==="none";if(shouldShowHelp){showHelp()}else{window.hidePopoverMenus()}})}setMobileTopbar();addSidebarItems();addSidebarCrates();onHashChange(null);window.addEventListener("hashchange",onHashChange);searchState.setup()}());(function(){const SIDEBAR_MIN=100;const SIDEBAR_MAX=500;const RUSTDOC_MOBILE_BREAKPOINT=700;const BODY_MIN=400;const SIDEBAR_VANISH_THRESHOLD=SIDEBAR_MIN/2;const sidebarButton=document.getElementById("sidebar-button");if(sidebarButton){sidebarButton.addEventListener("click",e=>{removeClass(document.documentElement,"hide-sidebar");updateLocalStorage("hide-sidebar","false");if(document.querySelector(".rustdoc.src")){window.rustdocToggleSrcSidebar()}e.preventDefault()})}let currentPointerId=null;let desiredSidebarSize=null;let pendingSidebarResizingFrame=false;const resizer=document.querySelector(".sidebar-resizer");const sidebar=document.querySelector(".sidebar");if(!resizer||!sidebar){return}const isSrcPage=hasClass(document.body,"src");function hideSidebar(){if(isSrcPage){window.rustdocCloseSourceSidebar();updateLocalStorage("src-sidebar-width",null);document.documentElement.style.removeProperty("--src-sidebar-width");sidebar.style.removeProperty("--src-sidebar-width");resizer.style.removeProperty("--src-sidebar-width")}else{addClass(document.documentElement,"hide-sidebar");updateLocalStorage("hide-sidebar","true");updateLocalStorage("desktop-sidebar-width",null);document.documentElement.style.removeProperty("--desktop-sidebar-width");sidebar.style.removeProperty("--desktop-sidebar-width");resizer.style.removeProperty("--desktop-sidebar-width")}}function showSidebar(){if(isSrcPage){window.rustdocShowSourceSidebar()}else{removeClass(document.documentElement,"hide-sidebar");updateLocalStorage("hide-sidebar","false")}}function changeSidebarSize(size){if(isSrcPage){updateLocalStorage("src-sidebar-width",size);sidebar.style.setProperty("--src-sidebar-width",size+"px");resizer.style.setProperty("--src-sidebar-width",size+"px")}else{updateLocalStorage("desktop-sidebar-width",size);sidebar.style.setProperty("--desktop-sidebar-width",size+"px");resizer.style.setProperty("--desktop-sidebar-width",size+"px")}}function isSidebarHidden(){return isSrcPage?!hasClass(document.documentElement,"src-sidebar-expanded"):hasClass(document.documentElement,"hide-sidebar")}function resize(e){if(currentPointerId===null||currentPointerId!==e.pointerId){return}e.preventDefault();const pos=e.clientX-3;if(pos=SIDEBAR_MIN){if(isSidebarHidden()){showSidebar()}const constrainedPos=Math.min(pos,window.innerWidth-BODY_MIN,SIDEBAR_MAX);changeSidebarSize(constrainedPos);desiredSidebarSize=constrainedPos;if(pendingSidebarResizingFrame!==false){clearTimeout(pendingSidebarResizingFrame)}pendingSidebarResizingFrame=setTimeout(()=>{if(currentPointerId===null||pendingSidebarResizingFrame===false){return}pendingSidebarResizingFrame=false;document.documentElement.style.setProperty("--resizing-sidebar-width",desiredSidebarSize+"px")},100)}}window.addEventListener("resize",()=>{if(window.innerWidth=(window.innerWidth-BODY_MIN)){changeSidebarSize(window.innerWidth-BODY_MIN)}else if(desiredSidebarSize!==null&&desiredSidebarSize>SIDEBAR_MIN){changeSidebarSize(desiredSidebarSize)}});function stopResize(e){if(currentPointerId===null){return}if(e){e.preventDefault()}desiredSidebarSize=sidebar.getBoundingClientRect().width;removeClass(resizer,"active");window.removeEventListener("pointermove",resize,false);window.removeEventListener("pointerup",stopResize,false);removeClass(document.documentElement,"sidebar-resizing");document.documentElement.style.removeProperty("--resizing-sidebar-width");if(resizer.releasePointerCapture){resizer.releasePointerCapture(currentPointerId);currentPointerId=null}}function initResize(e){if(currentPointerId!==null||e.altKey||e.ctrlKey||e.metaKey||e.button!==0){return}if(resizer.setPointerCapture){resizer.setPointerCapture(e.pointerId);if(!resizer.hasPointerCapture(e.pointerId)){resizer.releasePointerCapture(e.pointerId);return}currentPointerId=e.pointerId}window.hideAllModals(false);e.preventDefault();window.addEventListener("pointermove",resize,false);window.addEventListener("pointercancel",stopResize,false);window.addEventListener("pointerup",stopResize,false);addClass(resizer,"active");addClass(document.documentElement,"sidebar-resizing");const pos=e.clientX-sidebar.offsetLeft-3;document.documentElement.style.setProperty("--resizing-sidebar-width",pos+"px");desiredSidebarSize=null}resizer.addEventListener("pointerdown",initResize,false)}());(function(){let reset_button_timeout=null;const but=document.getElementById("copy-path");if(!but){return}but.onclick=()=>{const parent=but.parentElement;const path=[];onEach(parent.childNodes,child=>{if(child.tagName==="A"){path.push(child.textContent)}});const el=document.createElement("textarea");el.value=path.join("::");el.setAttribute("readonly","");el.style.position="absolute";el.style.left="-9999px";document.body.appendChild(el);el.select();document.execCommand("copy");document.body.removeChild(el);but.children[0].style.display="none";let tmp;if(but.childNodes.length<2){tmp=document.createTextNode("✓");but.appendChild(tmp)}else{onEachLazy(but.childNodes,e=>{if(e.nodeType===Node.TEXT_NODE){tmp=e;return true}});tmp.textContent="✓"}if(reset_button_timeout!==null){window.clearTimeout(reset_button_timeout)}function reset_button(){tmp.textContent="";reset_button_timeout=null;but.children[0].style.display=""}reset_button_timeout=window.setTimeout(reset_button,1000)}}()) \ No newline at end of file diff --git a/static.files/normalize-76eba96aa4d2e634.css b/static.files/normalize-76eba96aa4d2e634.css new file mode 100644 index 00000000..469959f1 --- /dev/null +++ b/static.files/normalize-76eba96aa4d2e634.css @@ -0,0 +1,2 @@ + /*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */ +html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}main{display:block}h1{font-size:2em;margin:0.67em 0}hr{box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a{background-color:transparent}abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-0.25em}sup{top:-0.5em}img{border-style:none}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type="button"],[type="reset"],[type="submit"],button{-webkit-appearance:button}[type="button"]::-moz-focus-inner,[type="reset"]::-moz-focus-inner,[type="submit"]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type="button"]:-moz-focusring,[type="reset"]:-moz-focusring,[type="submit"]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:0.35em 0.75em 0.625em}legend{box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{vertical-align:baseline}textarea{overflow:auto}[type="checkbox"],[type="radio"]{box-sizing:border-box;padding:0}[type="number"]::-webkit-inner-spin-button,[type="number"]::-webkit-outer-spin-button{height:auto}[type="search"]{-webkit-appearance:textfield;outline-offset:-2px}[type="search"]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details{display:block}summary{display:list-item}template{display:none}[hidden]{display:none} \ No newline at end of file diff --git a/static.files/noscript-04d5337699b92874.css b/static.files/noscript-04d5337699b92874.css new file mode 100644 index 00000000..fbd55f57 --- /dev/null +++ b/static.files/noscript-04d5337699b92874.css @@ -0,0 +1 @@ + #main-content .attributes{margin-left:0 !important;}#copy-path,#sidebar-button,.sidebar-resizer{display:none !important;}nav.sub{display:none;}.src .sidebar{display:none;}.notable-traits{display:none;}:root{--main-background-color:white;--main-color:black;--settings-input-color:#2196f3;--settings-input-border-color:#717171;--settings-button-color:#000;--settings-button-border-focus:#717171;--sidebar-background-color:#f5f5f5;--sidebar-background-color-hover:#e0e0e0;--code-block-background-color:#f5f5f5;--scrollbar-track-background-color:#dcdcdc;--scrollbar-thumb-background-color:rgba(36,37,39,0.6);--scrollbar-color:rgba(36,37,39,0.6) #d9d9d9;--headings-border-bottom-color:#ddd;--border-color:#e0e0e0;--button-background-color:#fff;--right-side-color:grey;--code-attribute-color:#999;--toggles-color:#999;--toggle-filter:none;--mobile-sidebar-menu-filter:none;--search-input-focused-border-color:#66afe9;--copy-path-button-color:#999;--copy-path-img-filter:invert(50%);--copy-path-img-hover-filter:invert(35%);--codeblock-error-hover-color:rgb(255,0,0);--codeblock-error-color:rgba(255,0,0,.5);--codeblock-ignore-hover-color:rgb(255,142,0);--codeblock-ignore-color:rgba(255,142,0,.6);--warning-border-color:#ff8e00;--type-link-color:#ad378a;--trait-link-color:#6e4fc9;--assoc-item-link-color:#3873ad;--function-link-color:#ad7c37;--macro-link-color:#068000;--keyword-link-color:#3873ad;--mod-link-color:#3873ad;--link-color:#3873ad;--sidebar-link-color:#356da4;--sidebar-current-link-background-color:#fff;--search-result-link-focus-background-color:#ccc;--search-result-border-color:#aaa3;--search-color:#000;--search-error-code-background-color:#d0cccc;--search-results-alias-color:#000;--search-results-grey-color:#999;--search-tab-title-count-color:#888;--search-tab-button-not-selected-border-top-color:#e6e6e6;--search-tab-button-not-selected-background:#e6e6e6;--search-tab-button-selected-border-top-color:#0089ff;--search-tab-button-selected-background:#fff;--stab-background-color:#fff5d6;--stab-code-color:#000;--code-highlight-kw-color:#8959a8;--code-highlight-kw-2-color:#4271ae;--code-highlight-lifetime-color:#b76514;--code-highlight-prelude-color:#4271ae;--code-highlight-prelude-val-color:#c82829;--code-highlight-number-color:#718c00;--code-highlight-string-color:#718c00;--code-highlight-literal-color:#c82829;--code-highlight-attribute-color:#c82829;--code-highlight-self-color:#c82829;--code-highlight-macro-color:#3e999f;--code-highlight-question-mark-color:#ff9011;--code-highlight-comment-color:#8e908c;--code-highlight-doc-comment-color:#4d4d4c;--src-line-numbers-span-color:#c67e2d;--src-line-number-highlighted-background-color:#fdffd3;--test-arrow-color:#f5f5f5;--test-arrow-background-color:rgba(78,139,202,0.2);--test-arrow-hover-color:#f5f5f5;--test-arrow-hover-background-color:rgb(78,139,202);--target-background-color:#fdffd3;--target-border-color:#ad7c37;--kbd-color:#000;--kbd-background:#fafbfc;--kbd-box-shadow-color:#c6cbd1;--rust-logo-filter:initial;--crate-search-div-filter:invert(100%) sepia(0%) saturate(4223%) hue-rotate(289deg) brightness(114%) contrast(76%);--crate-search-div-hover-filter:invert(44%) sepia(18%) saturate(23%) hue-rotate(317deg) brightness(96%) contrast(93%);--crate-search-hover-border:#717171;--src-sidebar-background-selected:#fff;--src-sidebar-background-hover:#e0e0e0;--table-alt-row-background-color:#f5f5f5;--codeblock-link-background:#eee;--scrape-example-toggle-line-background:#ccc;--scrape-example-toggle-line-hover-background:#999;--scrape-example-code-line-highlight:#fcffd6;--scrape-example-code-line-highlight-focus:#f6fdb0;--scrape-example-help-border-color:#555;--scrape-example-help-color:#333;--scrape-example-help-hover-border-color:#000;--scrape-example-help-hover-color:#000;--scrape-example-code-wrapper-background-start:rgba(255,255,255,1);--scrape-example-code-wrapper-background-end:rgba(255,255,255,0);--sidebar-resizer-hover:hsl(207,90%,66%);--sidebar-resizer-active:hsl(207,90%,54%);}@media (prefers-color-scheme:dark){:root{--main-background-color:#353535;--main-color:#ddd;--settings-input-color:#2196f3;--settings-input-border-color:#999;--settings-button-color:#000;--settings-button-border-focus:#ffb900;--sidebar-background-color:#505050;--sidebar-background-color-hover:#676767;--code-block-background-color:#2A2A2A;--scrollbar-track-background-color:#717171;--scrollbar-thumb-background-color:rgba(32,34,37,.6);--scrollbar-color:rgba(32,34,37,.6) #5a5a5a;--headings-border-bottom-color:#d2d2d2;--border-color:#e0e0e0;--button-background-color:#f0f0f0;--right-side-color:grey;--code-attribute-color:#999;--toggles-color:#999;--toggle-filter:invert(100%);--mobile-sidebar-menu-filter:invert(100%);--search-input-focused-border-color:#008dfd;--copy-path-button-color:#999;--copy-path-img-filter:invert(50%);--copy-path-img-hover-filter:invert(65%);--codeblock-error-hover-color:rgb(255,0,0);--codeblock-error-color:rgba(255,0,0,.5);--codeblock-ignore-hover-color:rgb(255,142,0);--codeblock-ignore-color:rgba(255,142,0,.6);--warning-border-color:#ff8e00;--type-link-color:#2dbfb8;--trait-link-color:#b78cf2;--assoc-item-link-color:#d2991d;--function-link-color:#2bab63;--macro-link-color:#09bd00;--keyword-link-color:#d2991d;--mod-link-color:#d2991d;--link-color:#d2991d;--sidebar-link-color:#fdbf35;--sidebar-current-link-background-color:#444;--search-result-link-focus-background-color:#616161;--search-result-border-color:#aaa3;--search-color:#111;--search-error-code-background-color:#484848;--search-results-alias-color:#fff;--search-results-grey-color:#ccc;--search-tab-title-count-color:#888;--search-tab-button-not-selected-border-top-color:#252525;--search-tab-button-not-selected-background:#252525;--search-tab-button-selected-border-top-color:#0089ff;--search-tab-button-selected-background:#353535;--stab-background-color:#314559;--stab-code-color:#e6e1cf;--code-highlight-kw-color:#ab8ac1;--code-highlight-kw-2-color:#769acb;--code-highlight-lifetime-color:#d97f26;--code-highlight-prelude-color:#769acb;--code-highlight-prelude-val-color:#ee6868;--code-highlight-number-color:#83a300;--code-highlight-string-color:#83a300;--code-highlight-literal-color:#ee6868;--code-highlight-attribute-color:#ee6868;--code-highlight-self-color:#ee6868;--code-highlight-macro-color:#3e999f;--code-highlight-question-mark-color:#ff9011;--code-highlight-comment-color:#8d8d8b;--code-highlight-doc-comment-color:#8ca375;--src-line-numbers-span-color:#3b91e2;--src-line-number-highlighted-background-color:#0a042f;--test-arrow-color:#dedede;--test-arrow-background-color:rgba(78,139,202,0.2);--test-arrow-hover-color:#dedede;--test-arrow-hover-background-color:#4e8bca;--target-background-color:#494a3d;--target-border-color:#bb7410;--kbd-color:#000;--kbd-background:#fafbfc;--kbd-box-shadow-color:#c6cbd1;--rust-logo-filter:drop-shadow(1px 0 0px #fff) drop-shadow(0 1px 0 #fff) drop-shadow(-1px 0 0 #fff) drop-shadow(0 -1px 0 #fff);--crate-search-div-filter:invert(94%) sepia(0%) saturate(721%) hue-rotate(255deg) brightness(90%) contrast(90%);--crate-search-div-hover-filter:invert(69%) sepia(60%) saturate(6613%) hue-rotate(184deg) brightness(100%) contrast(91%);--crate-search-hover-border:#2196f3;--src-sidebar-background-selected:#333;--src-sidebar-background-hover:#444;--table-alt-row-background-color:#2a2a2a;--codeblock-link-background:#333;--scrape-example-toggle-line-background:#999;--scrape-example-toggle-line-hover-background:#c5c5c5;--scrape-example-code-line-highlight:#5b3b01;--scrape-example-code-line-highlight-focus:#7c4b0f;--scrape-example-help-border-color:#aaa;--scrape-example-help-color:#eee;--scrape-example-help-hover-border-color:#fff;--scrape-example-help-hover-color:#fff;--scrape-example-code-wrapper-background-start:rgba(53,53,53,1);--scrape-example-code-wrapper-background-end:rgba(53,53,53,0);--sidebar-resizer-hover:hsl(207,30%,54%);--sidebar-resizer-active:hsl(207,90%,54%);}} \ No newline at end of file diff --git a/static.files/rust-logo-151179464ae7ed46.svg b/static.files/rust-logo-151179464ae7ed46.svg new file mode 100644 index 00000000..62424d8f --- /dev/null +++ b/static.files/rust-logo-151179464ae7ed46.svg @@ -0,0 +1,61 @@ + + + diff --git a/static.files/rustdoc-5bc39a1768837dd0.css b/static.files/rustdoc-5bc39a1768837dd0.css new file mode 100644 index 00000000..175164ef --- /dev/null +++ b/static.files/rustdoc-5bc39a1768837dd0.css @@ -0,0 +1,24 @@ + :root{--nav-sub-mobile-padding:8px;--search-typename-width:6.75rem;--desktop-sidebar-width:200px;--src-sidebar-width:300px;--desktop-sidebar-z-index:100;}@font-face {font-family:'Fira Sans';font-style:normal;font-weight:400;src:local('Fira Sans'),url("FiraSans-Regular-018c141bf0843ffd.woff2") format("woff2");font-display:swap;}@font-face {font-family:'Fira Sans';font-style:normal;font-weight:500;src:local('Fira Sans Medium'),url("FiraSans-Medium-8f9a781e4970d388.woff2") format("woff2");font-display:swap;}@font-face {font-family:'Source Serif 4';font-style:normal;font-weight:400;src:local('Source Serif 4'),url("SourceSerif4-Regular-46f98efaafac5295.ttf.woff2") format("woff2");font-display:swap;}@font-face {font-family:'Source Serif 4';font-style:italic;font-weight:400;src:local('Source Serif 4 Italic'),url("SourceSerif4-It-acdfaf1a8af734b1.ttf.woff2") format("woff2");font-display:swap;}@font-face {font-family:'Source Serif 4';font-style:normal;font-weight:700;src:local('Source Serif 4 Bold'),url("SourceSerif4-Bold-a2c9cd1067f8b328.ttf.woff2") format("woff2");font-display:swap;}@font-face {font-family:'Source Code Pro';font-style:normal;font-weight:400;src:url("SourceCodePro-Regular-562dcc5011b6de7d.ttf.woff2") format("woff2");font-display:swap;}@font-face {font-family:'Source Code Pro';font-style:italic;font-weight:400;src:url("SourceCodePro-It-1cc31594bf4f1f79.ttf.woff2") format("woff2");font-display:swap;}@font-face {font-family:'Source Code Pro';font-style:normal;font-weight:600;src:url("SourceCodePro-Semibold-d899c5a5c4aeb14a.ttf.woff2") format("woff2");font-display:swap;}@font-face {font-family:'NanumBarunGothic';src:url("NanumBarunGothic-0f09457c7a19b7c6.ttf.woff2") format("woff2");font-display:swap;unicode-range:U+AC00-D7AF,U+1100-11FF,U+3130-318F,U+A960-A97F,U+D7B0-D7FF;}*{box-sizing:border-box;}body{font:1rem/1.5 "Source Serif 4",NanumBarunGothic,serif;margin:0;position:relative;overflow-wrap:break-word;overflow-wrap:anywhere;font-feature-settings:"kern","liga";background-color:var(--main-background-color);color:var(--main-color);}h1{font-size:1.5rem;}h2{font-size:1.375rem;}h3{font-size:1.25rem;}h1,h2,h3,h4,h5,h6{font-weight:500;}h1,h2,h3,h4{margin:25px 0 15px 0;padding-bottom:6px;}.docblock h3,.docblock h4,h5,h6{margin:15px 0 5px 0;}.docblock>h2:first-child,.docblock>h3:first-child,.docblock>h4:first-child,.docblock>h5:first-child,.docblock>h6:first-child{margin-top:0;}.main-heading h1{margin:0;padding:0;flex-grow:1;overflow-wrap:break-word;overflow-wrap:anywhere;}.main-heading{display:flex;flex-wrap:wrap;padding-bottom:6px;margin-bottom:15px;}.content h2,.top-doc .docblock>h3,.top-doc .docblock>h4{border-bottom:1px solid var(--headings-border-bottom-color);}h1,h2{line-height:1.25;padding-top:3px;padding-bottom:9px;}h3.code-header{font-size:1.125rem;}h4.code-header{font-size:1rem;}.code-header{font-weight:600;margin:0;padding:0;white-space:pre-wrap;}#crate-search,h1,h2,h3,h4,h5,h6,.sidebar,.mobile-topbar,.search-input,.search-results .result-name,.item-name>a,.out-of-band,span.since,a.src,#help-button>a,summary.hideme,.scraped-example-list,ul.all-items{font-family:"Fira Sans",Arial,NanumBarunGothic,sans-serif;}#toggle-all-docs,a.anchor,.section-header a,#src-sidebar a,.rust a,.sidebar h2 a,.sidebar h3 a,.mobile-topbar h2 a,h1 a,.search-results a,.stab,.result-name i{color:var(--main-color);}span.enum,a.enum,span.struct,a.struct,span.union,a.union,span.primitive,a.primitive,span.type,a.type,span.foreigntype,a.foreigntype{color:var(--type-link-color);}span.trait,a.trait,span.traitalias,a.traitalias{color:var(--trait-link-color);}span.associatedtype,a.associatedtype,span.constant,a.constant,span.static,a.static{color:var(--assoc-item-link-color);}span.fn,a.fn,span.method,a.method,span.tymethod,a.tymethod{color:var(--function-link-color);}span.attr,a.attr,span.derive,a.derive,span.macro,a.macro{color:var(--macro-link-color);}span.mod,a.mod{color:var(--mod-link-color);}span.keyword,a.keyword{color:var(--keyword-link-color);}a{color:var(--link-color);text-decoration:none;}ol,ul{padding-left:24px;}ul ul,ol ul,ul ol,ol ol{margin-bottom:.625em;}p,.docblock>.warning{margin:0 0 .75em 0;}p:last-child,.docblock>.warning:last-child{margin:0;}button{padding:1px 6px;cursor:pointer;}button#toggle-all-docs{padding:0;background:none;border:none;-webkit-appearance:none;opacity:1;}.rustdoc{display:flex;flex-direction:row;flex-wrap:nowrap;}main{position:relative;flex-grow:1;padding:10px 15px 40px 45px;min-width:0;}.src main{padding:15px;}.width-limiter{max-width:960px;margin-right:auto;}details:not(.toggle) summary{margin-bottom:.6em;}code,pre,a.test-arrow,.code-header{font-family:"Source Code Pro",monospace;}.docblock code,.docblock-short code{border-radius:3px;padding:0 0.125em;}.docblock pre code,.docblock-short pre code{padding:0;}pre{padding:14px;line-height:1.5;}pre.item-decl{overflow-x:auto;}.item-decl .type-contents-toggle{contain:initial;}.src .content pre{padding:20px;}.rustdoc.src .example-wrap pre.src-line-numbers{padding:20px 0 20px 4px;}img{max-width:100%;}.logo-container{line-height:0;display:block;}.rust-logo{filter:var(--rust-logo-filter);}.sidebar{font-size:0.875rem;flex:0 0 var(--desktop-sidebar-width);width:var(--desktop-sidebar-width);overflow-y:scroll;overscroll-behavior:contain;position:sticky;height:100vh;top:0;left:0;z-index:var(--desktop-sidebar-z-index);}.rustdoc.src .sidebar{flex-basis:50px;width:50px;border-right:1px solid;overflow-x:hidden;overflow-y:hidden;}.hide-sidebar .sidebar,.hide-sidebar .sidebar-resizer{display:none;}.sidebar-resizer{touch-action:none;width:9px;cursor:col-resize;z-index:calc(var(--desktop-sidebar-z-index) + 1);position:fixed;height:100%;left:calc(var(--desktop-sidebar-width) + 1px);}.rustdoc.src .sidebar-resizer{left:49px;}.src-sidebar-expanded .src .sidebar-resizer{left:var(--src-sidebar-width);}.sidebar-resizing{-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none;user-select:none;}.sidebar-resizing*{cursor:col-resize !important;}.sidebar-resizing .sidebar{position:fixed;}.sidebar-resizing>body{padding-left:var(--resizing-sidebar-width);}.sidebar-resizer:hover,.sidebar-resizer:active,.sidebar-resizer:focus,.sidebar-resizer.active{width:10px;margin:0;left:var(--desktop-sidebar-width);border-left:solid 1px var(--sidebar-resizer-hover);}.src-sidebar-expanded .rustdoc.src .sidebar-resizer:hover,.src-sidebar-expanded .rustdoc.src .sidebar-resizer:active,.src-sidebar-expanded .rustdoc.src .sidebar-resizer:focus,.src-sidebar-expanded .rustdoc.src .sidebar-resizer.active{left:calc(var(--src-sidebar-width) - 1px);}@media (pointer:coarse){.sidebar-resizer{display:none !important;}}.sidebar-resizer.active{padding:0 140px;width:2px;margin-left:-140px;border-left:none;}.sidebar-resizer.active:before{border-left:solid 2px var(--sidebar-resizer-active);display:block;height:100%;content:"";}.sidebar,.mobile-topbar,.sidebar-menu-toggle,#src-sidebar{background-color:var(--sidebar-background-color);}.src .sidebar>*{visibility:hidden;}.src-sidebar-expanded .src .sidebar{overflow-y:auto;flex-basis:var(--src-sidebar-width);width:var(--src-sidebar-width);}.src-sidebar-expanded .src .sidebar>*{visibility:visible;}#all-types{margin-top:1em;}*{scrollbar-width:initial;scrollbar-color:var(--scrollbar-color);}.sidebar{scrollbar-width:thin;scrollbar-color:var(--scrollbar-color);}::-webkit-scrollbar{width:12px;}.sidebar::-webkit-scrollbar{width:8px;}::-webkit-scrollbar-track{-webkit-box-shadow:inset 0;background-color:var(--scrollbar-track-background-color);}.sidebar::-webkit-scrollbar-track{background-color:var(--scrollbar-track-background-color);}::-webkit-scrollbar-thumb,.sidebar::-webkit-scrollbar-thumb{background-color:var(--scrollbar-thumb-background-color);}.hidden{display:none !important;}.logo-container>img{height:48px;width:48px;}ul.block,.block li{padding:0;margin:0;list-style:none;}.sidebar-elems a,.sidebar>h2 a{display:block;padding:0.25rem;margin-left:-0.25rem;margin-right:0.25rem;}.sidebar h2{overflow-wrap:anywhere;padding:0;margin:0.7rem 0;}.sidebar h3{font-size:1.125rem;padding:0;margin:0;}.sidebar-elems,.sidebar>.version,.sidebar>h2{padding-left:24px;}.sidebar a{color:var(--sidebar-link-color);}.sidebar .current,.sidebar .current a,.sidebar-crate a.logo-container:hover+h2 a,.sidebar a:hover:not(.logo-container){background-color:var(--sidebar-current-link-background-color);}.sidebar-elems .block{margin-bottom:2em;}.sidebar-elems .block li a{white-space:nowrap;text-overflow:ellipsis;overflow:hidden;}.sidebar-crate{display:flex;align-items:center;justify-content:center;margin:14px 32px 1rem;row-gap:10px;column-gap:32px;flex-wrap:wrap;}.sidebar-crate h2{flex-grow:1;margin:0 -8px;align-self:start;}.sidebar-crate .logo-container{margin:0 -16px 0 -16px;text-align:center;}.sidebar-crate h2 a{display:block;margin:0 calc(-24px + 0.25rem) 0 -0.2rem;padding:calc((16px - 0.57rem ) / 2 ) 0.25rem;padding-left:0.2rem;}.sidebar-crate h2 .version{display:block;font-weight:normal;font-size:1rem;overflow-wrap:break-word;}.sidebar-crate+.version{margin-top:-1rem;margin-bottom:1rem;}.mobile-topbar{display:none;}.rustdoc .example-wrap{display:flex;position:relative;margin-bottom:10px;}.rustdoc .example-wrap:last-child{margin-bottom:0px;}.rustdoc .example-wrap pre{margin:0;flex-grow:1;}.rustdoc:not(.src) .example-wrap pre{overflow:auto hidden;}.rustdoc .example-wrap pre.example-line-numbers,.rustdoc .example-wrap pre.src-line-numbers{flex-grow:0;min-width:fit-content;overflow:initial;text-align:right;-webkit-user-select:none;user-select:none;padding:14px 8px;color:var(--src-line-numbers-span-color);}.rustdoc .example-wrap pre.src-line-numbers{padding:14px 0;}.src-line-numbers a,.src-line-numbers span{color:var(--src-line-numbers-span-color);padding:0 8px;}.src-line-numbers :target{background-color:transparent;border-right:none;padding:0 8px;}.src-line-numbers .line-highlighted{background-color:var(--src-line-number-highlighted-background-color);}.search-loading{text-align:center;}.docblock-short{overflow-wrap:break-word;overflow-wrap:anywhere;}.docblock :not(pre)>code,.docblock-short code{white-space:pre-wrap;}.top-doc .docblock h2{font-size:1.375rem;}.top-doc .docblock h3{font-size:1.25rem;}.top-doc .docblock h4,.top-doc .docblock h5{font-size:1.125rem;}.top-doc .docblock h6{font-size:1rem;}.docblock h5{font-size:1rem;}.docblock h6{font-size:0.875rem;}.docblock{margin-left:24px;position:relative;}.docblock>:not(.more-examples-toggle):not(.example-wrap){max-width:100%;overflow-x:auto;}.out-of-band{flex-grow:0;font-size:1.125rem;}.docblock code,.docblock-short code,pre,.rustdoc.src .example-wrap{background-color:var(--code-block-background-color);}#main-content{position:relative;}.docblock table{margin:.5em 0;border-collapse:collapse;}.docblock table td,.docblock table th{padding:.5em;border:1px solid var(--border-color);}.docblock table tbody tr:nth-child(2n){background:var(--table-alt-row-background-color);}div.where{white-space:pre-wrap;font-size:0.875rem;}.item-info{display:block;margin-left:24px;}.item-info code{font-size:0.875rem;}#main-content>.item-info{margin-left:0;}nav.sub{flex-grow:1;flex-flow:row nowrap;margin:4px 0 25px 0;display:flex;align-items:center;}.search-form{position:relative;display:flex;height:34px;flex-grow:1;}.src nav.sub{margin:0 0 15px 0;}.section-header{display:block;position:relative;}.section-header:hover>.anchor,.impl:hover>.anchor,.trait-impl:hover>.anchor,.variant:hover>.anchor{display:initial;}.anchor{display:none;position:absolute;left:-0.5em;background:none !important;}.anchor.field{left:-5px;}.section-header>.anchor{left:-15px;padding-right:8px;}h2.section-header>.anchor{padding-right:6px;}a.doc-anchor{color:var(--main-color);display:none;position:absolute;left:-17px;padding-right:5px;padding-left:3px;}*:hover>.doc-anchor{display:block;}.top-doc>.docblock>*:first-child>.doc-anchor{display:none !important;}.main-heading a:hover,.example-wrap .rust a:hover,.all-items a:hover,.docblock a:not(.test-arrow):not(.scrape-help):not(.tooltip):hover:not(.doc-anchor),.docblock-short a:not(.test-arrow):not(.scrape-help):not(.tooltip):hover,.item-info a{text-decoration:underline;}.crate.block li.current a{font-weight:500;}table,.item-table{overflow-wrap:break-word;}.item-table{display:table;padding:0;margin:0;}.item-table>li{display:table-row;}.item-table>li>div{display:table-cell;}.item-table>li>.item-name{padding-right:1.25rem;}.search-results-title{margin-top:0;white-space:nowrap;display:flex;align-items:baseline;}#crate-search-div{position:relative;min-width:5em;}#crate-search{min-width:115px;padding:0 23px 0 4px;max-width:100%;text-overflow:ellipsis;border:1px solid var(--border-color);border-radius:4px;outline:none;cursor:pointer;-moz-appearance:none;-webkit-appearance:none;text-indent:0.01px;background-color:var(--main-background-color);color:inherit;line-height:1.5;font-weight:500;}#crate-search:hover,#crate-search:focus{border-color:var(--crate-search-hover-border);}#crate-search-div::after{pointer-events:none;width:100%;height:100%;position:absolute;top:0;left:0;content:"";background-repeat:no-repeat;background-size:20px;background-position:calc(100% - 2px) 56%;background-image:url('data:image/svg+xml, \ + ');filter:var(--crate-search-div-filter);}#crate-search-div:hover::after,#crate-search-div:focus-within::after{filter:var(--crate-search-div-hover-filter);}#crate-search>option{font-size:1rem;}.search-input{-webkit-appearance:none;outline:none;border:1px solid var(--border-color);border-radius:2px;padding:8px;font-size:1rem;flex-grow:1;background-color:var(--button-background-color);color:var(--search-color);}.search-input:focus{border-color:var(--search-input-focused-border-color);}.search-results{display:none;}.search-results.active{display:block;}.search-results>a{display:flex;margin-left:2px;margin-right:2px;border-bottom:1px solid var(--search-result-border-color);gap:1em;}.search-results>a>div.desc{white-space:nowrap;text-overflow:ellipsis;overflow:hidden;flex:2;}.search-results a:hover,.search-results a:focus{background-color:var(--search-result-link-focus-background-color);}.search-results .result-name{display:flex;align-items:center;justify-content:start;flex:3;}.search-results .result-name .alias{color:var(--search-results-alias-color);}.search-results .result-name .grey{color:var(--search-results-grey-color);}.search-results .result-name .typename{color:var(--search-results-grey-color);font-size:0.875rem;width:var(--search-typename-width);}.search-results .result-name .path{word-break:break-all;max-width:calc(100% - var(--search-typename-width));display:inline-block;}.search-results .result-name .path>*{display:inline;}.popover{position:absolute;top:100%;right:0;z-index:calc(var(--desktop-sidebar-z-index) + 1);margin-top:7px;border-radius:3px;border:1px solid var(--border-color);background-color:var(--main-background-color);color:var(--main-color);--popover-arrow-offset:11px;}.popover::before{content:'';position:absolute;right:var(--popover-arrow-offset);border:solid var(--border-color);border-width:1px 1px 0 0;background-color:var(--main-background-color);padding:4px;transform:rotate(-45deg);top:-5px;}.setting-line{margin:1.2em 0.6em;}.setting-radio input,.setting-check input{margin-right:0.3em;height:1.2rem;width:1.2rem;border:2px solid var(--settings-input-border-color);outline:none;-webkit-appearance:none;cursor:pointer;}.setting-radio input{border-radius:50%;}.setting-radio span,.setting-check span{padding-bottom:1px;}.setting-radio{margin-top:0.1em;margin-bottom:0.1em;min-width:3.8em;padding:0.3em;display:inline-flex;align-items:center;cursor:pointer;}.setting-radio+.setting-radio{margin-left:0.5em;}.setting-check{margin-right:20px;display:flex;align-items:center;cursor:pointer;}.setting-radio input:checked{box-shadow:inset 0 0 0 3px var(--main-background-color);background-color:var(--settings-input-color);}.setting-check input:checked{background-color:var(--settings-input-color);border-width:1px;content:url('data:image/svg+xml,\ + \ + ');}.setting-radio input:focus,.setting-check input:focus{box-shadow:0 0 1px 1px var(--settings-input-color);}.setting-radio input:checked:focus{box-shadow:inset 0 0 0 3px var(--main-background-color),0 0 2px 2px var(--settings-input-color);}.setting-radio input:hover,.setting-check input:hover{border-color:var(--settings-input-color) !important;}#help.popover{max-width:600px;--popover-arrow-offset:48px;}#help dt{float:left;clear:left;margin-right:0.5rem;}#help span.top,#help span.bottom{text-align:center;display:block;font-size:1.125rem;}#help span.top{margin:10px 0;border-bottom:1px solid var(--border-color);padding-bottom:4px;margin-bottom:6px;}#help span.bottom{clear:both;border-top:1px solid var(--border-color);}.side-by-side>div{width:50%;float:left;padding:0 20px 20px 17px;}.item-info .stab{display:block;padding:3px;margin-bottom:5px;}.item-name .stab{margin-left:0.3125em;}.stab{padding:0 2px;font-size:0.875rem;font-weight:normal;color:var(--main-color);background-color:var(--stab-background-color);width:fit-content;white-space:pre-wrap;border-radius:3px;display:inline;vertical-align:baseline;}.stab.portability>code{background:none;color:var(--stab-code-color);}.stab .emoji,.item-info .stab::before{font-size:1.25rem;}.stab .emoji{margin-right:0.3rem;}.item-info .stab::before{content:"\0";width:0;display:inline-block;color:transparent;}.emoji{text-shadow:1px 0 0 black,-1px 0 0 black,0 1px 0 black,0 -1px 0 black;}.since{font-weight:normal;font-size:initial;}.rightside{padding-left:12px;float:right;}.rightside:not(a),.out-of-band{color:var(--right-side-color);}pre.rust{tab-size:4;-moz-tab-size:4;}pre.rust .kw{color:var(--code-highlight-kw-color);}pre.rust .kw-2{color:var(--code-highlight-kw-2-color);}pre.rust .lifetime{color:var(--code-highlight-lifetime-color);}pre.rust .prelude-ty{color:var(--code-highlight-prelude-color);}pre.rust .prelude-val{color:var(--code-highlight-prelude-val-color);}pre.rust .string{color:var(--code-highlight-string-color);}pre.rust .number{color:var(--code-highlight-number-color);}pre.rust .bool-val{color:var(--code-highlight-literal-color);}pre.rust .self{color:var(--code-highlight-self-color);}pre.rust .attr{color:var(--code-highlight-attribute-color);}pre.rust .macro,pre.rust .macro-nonterminal{color:var(--code-highlight-macro-color);}pre.rust .question-mark{font-weight:bold;color:var(--code-highlight-question-mark-color);}pre.rust .comment{color:var(--code-highlight-comment-color);}pre.rust .doccomment{color:var(--code-highlight-doc-comment-color);}.rustdoc.src .example-wrap pre.rust a{background:var(--codeblock-link-background);}.example-wrap.compile_fail,.example-wrap.should_panic{border-left:2px solid var(--codeblock-error-color);}.ignore.example-wrap{border-left:2px solid var(--codeblock-ignore-color);}.example-wrap.compile_fail:hover,.example-wrap.should_panic:hover{border-left:2px solid var(--codeblock-error-hover-color);}.example-wrap.ignore:hover{border-left:2px solid var(--codeblock-ignore-hover-color);}.example-wrap.compile_fail .tooltip,.example-wrap.should_panic .tooltip{color:var(--codeblock-error-color);}.example-wrap.ignore .tooltip{color:var(--codeblock-ignore-color);}.example-wrap.compile_fail:hover .tooltip,.example-wrap.should_panic:hover .tooltip{color:var(--codeblock-error-hover-color);}.example-wrap.ignore:hover .tooltip{color:var(--codeblock-ignore-hover-color);}.example-wrap .tooltip{position:absolute;display:block;left:-25px;top:5px;margin:0;line-height:1;}.example-wrap.compile_fail .tooltip,.example-wrap.should_panic .tooltip,.example-wrap.ignore .tooltip{font-weight:bold;font-size:1.25rem;}.content .docblock .warning{border-left:2px solid var(--warning-border-color);padding:14px;position:relative;overflow-x:visible !important;}.content .docblock .warning::before{color:var(--warning-border-color);content:"ⓘ";position:absolute;left:-25px;top:5px;font-weight:bold;font-size:1.25rem;}.top-doc>.docblock>.warning:first-child::before{top:20px;}a.test-arrow{visibility:hidden;position:absolute;padding:5px 10px 5px 10px;border-radius:5px;font-size:1.375rem;top:5px;right:5px;z-index:1;color:var(--test-arrow-color);background-color:var(--test-arrow-background-color);}a.test-arrow:hover{color:var(--test-arrow-hover-color);background-color:var(--test-arrow-hover-background-color);}.example-wrap:hover .test-arrow{visibility:visible;}.code-attribute{font-weight:300;color:var(--code-attribute-color);}.item-spacer{width:100%;height:12px;display:block;}.out-of-band>span.since{font-size:1.25rem;}.sub-variant h4{font-size:1rem;font-weight:400;margin-top:0;margin-bottom:0;}.sub-variant{margin-left:24px;margin-bottom:40px;}.sub-variant>.sub-variant-field{margin-left:24px;}:target{padding-right:3px;background-color:var(--target-background-color);border-right:3px solid var(--target-border-color);}.code-header a.tooltip{color:inherit;margin-right:15px;position:relative;}.code-header a.tooltip:hover{color:var(--link-color);}a.tooltip:hover::after{position:absolute;top:calc(100% - 10px);left:-15px;right:-15px;height:20px;content:"\00a0";}.fade-out{opacity:0;transition:opacity 0.45s cubic-bezier(0,0,0.1,1.0);}.popover.tooltip .content{margin:0.25em 0.5em;}.popover.tooltip .content pre,.popover.tooltip .content code{background:transparent;margin:0;padding:0;font-size:1.25rem;white-space:pre-wrap;}.popover.tooltip .content>h3:first-child{margin:0 0 5px 0;}.search-failed{text-align:center;margin-top:20px;display:none;}.search-failed.active{display:block;}.search-failed>ul{text-align:left;max-width:570px;margin-left:auto;margin-right:auto;}#search-tabs{display:flex;flex-direction:row;gap:1px;margin-bottom:4px;}#search-tabs button{text-align:center;font-size:1.125rem;border:0;border-top:2px solid;flex:1;line-height:1.5;color:inherit;}#search-tabs button:not(.selected){background-color:var(--search-tab-button-not-selected-background);border-top-color:var(--search-tab-button-not-selected-border-top-color);}#search-tabs button:hover,#search-tabs button.selected{background-color:var(--search-tab-button-selected-background);border-top-color:var(--search-tab-button-selected-border-top-color);}#search-tabs .count{font-size:1rem;font-variant-numeric:tabular-nums;color:var(--search-tab-title-count-color);}#search .error code{border-radius:3px;background-color:var(--search-error-code-background-color);}.search-corrections{font-weight:normal;}#src-sidebar{width:100%;overflow:auto;}#src-sidebar div.files>a:hover,details.dir-entry summary:hover,#src-sidebar div.files>a:focus,details.dir-entry summary:focus{background-color:var(--src-sidebar-background-hover);}#src-sidebar div.files>a.selected{background-color:var(--src-sidebar-background-selected);}.src-sidebar-title{position:sticky;top:0;display:flex;padding:8px 8px 0 48px;margin-bottom:7px;background:var(--sidebar-background-color);border-bottom:1px solid var(--border-color);}#settings-menu,#help-button{margin-left:4px;display:flex;}#sidebar-button{display:none;line-height:0;}.hide-sidebar #sidebar-button,.src #sidebar-button{display:flex;margin-right:4px;position:fixed;left:6px;height:34px;width:34px;background-color:var(--main-background-color);z-index:1;}.src #sidebar-button{left:8px;z-index:calc(var(--desktop-sidebar-z-index) + 1);}.hide-sidebar .src #sidebar-button{position:static;}#settings-menu>a,#help-button>a,#sidebar-button>a{display:flex;align-items:center;justify-content:center;background-color:var(--button-background-color);border:1px solid var(--border-color);border-radius:2px;color:var(--settings-button-color);font-size:20px;width:33px;}#settings-menu>a:hover,#settings-menu>a:focus,#help-button>a:hover,#help-button>a:focus,#sidebar-button>a:hover,#sidebar-button>a:focus{border-color:var(--settings-button-border-focus);}#sidebar-button>a:before{content:url('data:image/svg+xml,\ + \ + \ + ');width:22px;height:22px;}#copy-path{color:var(--copy-path-button-color);background:var(--main-background-color);height:34px;margin-left:10px;padding:0;padding-left:2px;border:0;width:33px;}#copy-path>img{filter:var(--copy-path-img-filter);}#copy-path:hover>img{filter:var(--copy-path-img-hover-filter);}@keyframes rotating{from{transform:rotate(0deg);}to{transform:rotate(360deg);}}#settings-menu.rotate>a img{animation:rotating 2s linear infinite;}kbd{display:inline-block;padding:3px 5px;font:15px monospace;line-height:10px;vertical-align:middle;border:solid 1px var(--border-color);border-radius:3px;color:var(--kbd-color);background-color:var(--kbd-background);box-shadow:inset 0 -1px 0 var(--kbd-box-shadow-color);}ul.all-items>li{list-style:none;}details.dir-entry{padding-left:4px;}details.dir-entry>summary{margin:0 0 0 -4px;padding:0 0 0 4px;cursor:pointer;}details.dir-entry div.folders,details.dir-entry div.files{padding-left:23px;}details.dir-entry a{display:block;}details.toggle{contain:layout;position:relative;}details.toggle>summary.hideme{cursor:pointer;font-size:1rem;}details.toggle>summary{list-style:none;outline:none;}details.toggle>summary::-webkit-details-marker,details.toggle>summary::marker{display:none;}details.toggle>summary.hideme>span{margin-left:9px;}details.toggle>summary::before{background:url('data:image/svg+xml,') no-repeat top left;content:"";cursor:pointer;width:16px;height:16px;display:inline-block;vertical-align:middle;opacity:.5;filter:var(--toggle-filter);}details.toggle>summary.hideme>span,.more-examples-toggle summary,.more-examples-toggle .hide-more{color:var(--toggles-color);}details.toggle>summary::after{content:"Expand";overflow:hidden;width:0;height:0;position:absolute;}details.toggle>summary.hideme::after{content:"";}details.toggle>summary:focus::before,details.toggle>summary:hover::before{opacity:1;}details.toggle>summary:focus-visible::before{outline:1px dotted #000;outline-offset:1px;}details.non-exhaustive{margin-bottom:8px;}details.toggle>summary.hideme::before{position:relative;}details.toggle>summary:not(.hideme)::before{position:absolute;left:-24px;top:4px;}.impl-items>details.toggle>summary:not(.hideme)::before{position:absolute;left:-24px;}details.toggle[open] >summary.hideme{position:absolute;}details.toggle[open] >summary.hideme>span{display:none;}details.toggle[open] >summary::before{background:url('data:image/svg+xml,') no-repeat top left;}details.toggle[open] >summary::after{content:"Collapse";}.docblock summary>*{display:inline-block;}.docblock>.example-wrap:first-child .tooltip{margin-top:16px;}.src #sidebar-button>a:before,.sidebar-menu-toggle:before{content:url('data:image/svg+xml,\ + ');opacity:0.75;}.sidebar-menu-toggle:hover:before,.sidebar-menu-toggle:active:before,.sidebar-menu-toggle:focus:before{opacity:1;}.src #sidebar-button>a:before{content:url('data:image/svg+xml,\ + \ + \ + ');opacity:0.75;}@media (max-width:850px){#search-tabs .count{display:block;}}@media (max-width:700px){*[id]{scroll-margin-top:45px;}.rustdoc{display:block;}main{padding-left:15px;padding-top:0px;}.main-heading{flex-direction:column;}.out-of-band{text-align:left;margin-left:initial;padding:initial;}.out-of-band .since::before{content:"Since ";}.sidebar .logo-container,.sidebar .location,.sidebar-resizer{display:none;}.sidebar{position:fixed;top:45px;left:-1000px;z-index:11;height:calc(100vh - 45px);width:200px;}.src main,.rustdoc.src .sidebar{top:0;padding:0;height:100vh;border:0;}.src .search-form{margin-left:40px;}.hide-sidebar .search-form{margin-left:32px;}.hide-sidebar .src .search-form{margin-left:0;}.sidebar.shown,.src-sidebar-expanded .src .sidebar,.rustdoc:not(.src) .sidebar:focus-within{left:0;}.mobile-topbar h2{padding-bottom:0;margin:auto 0.5em auto auto;overflow:hidden;font-size:24px;}.mobile-topbar h2 a{display:block;text-overflow:ellipsis;overflow:hidden;white-space:nowrap;}.mobile-topbar .logo-container>img{max-width:35px;max-height:35px;margin:5px 0 5px 20px;}.mobile-topbar{display:flex;flex-direction:row;position:sticky;z-index:10;font-size:2rem;height:45px;width:100%;left:0;top:0;}.hide-sidebar .mobile-topbar{display:none;}.sidebar-menu-toggle{width:45px;border:none;line-height:0;}.hide-sidebar .sidebar-menu-toggle{display:none;}.sidebar-elems{margin-top:1em;}.anchor{display:none !important;}#main-content>details.toggle>summary::before,#main-content>div>details.toggle>summary::before{left:-11px;}#copy-path,#help-button{display:none;}#sidebar-button>a:before{content:url('data:image/svg+xml,\ + \ + \ + ');width:22px;height:22px;}.sidebar-menu-toggle:before{filter:var(--mobile-sidebar-menu-filter);}.sidebar-menu-toggle:hover{background:var(--main-background-color);}.item-table,.item-row,.item-table>li,.item-table>li>div,.search-results>a,.search-results>a>div{display:block;}.search-results>a{padding:5px 0px;}.search-results>a>div.desc,.item-table>li>div.desc{padding-left:2em;}.search-results .result-name{display:block;}.search-results .result-name .typename{width:initial;margin-right:0;}.search-results .result-name .typename,.search-results .result-name .path{display:inline;}.src-sidebar-expanded .src .sidebar{position:fixed;max-width:100vw;width:100vw;}.src .src-sidebar-title{padding-top:0;}details.toggle:not(.top-doc)>summary{margin-left:10px;}.impl-items>details.toggle>summary:not(.hideme)::before,#main-content>details.toggle:not(.top-doc)>summary::before,#main-content>div>details.toggle>summary::before{left:-11px;}.impl-items>.item-info{margin-left:34px;}.src nav.sub{margin:0;padding:var(--nav-sub-mobile-padding);}}@media (min-width:701px){.scraped-example-title{position:absolute;z-index:10;background:var(--main-background-color);bottom:8px;right:5px;padding:2px 4px;box-shadow:0 0 4px var(--main-background-color);}}@media print{nav.sidebar,nav.sub,.out-of-band,a.src,#copy-path,details.toggle[open] >summary::before,details.toggle>summary::before,details.toggle.top-doc>summary{display:none;}.docblock{margin-left:0;}main{padding:10px;}}@media (max-width:464px){.docblock{margin-left:12px;}.docblock code{overflow-wrap:break-word;overflow-wrap:anywhere;}nav.sub{flex-direction:column;}.search-form{align-self:stretch;}}.variant,.implementors-toggle>summary,.impl,#implementors-list>.docblock,.impl-items>section,.impl-items>.toggle>summary,.methods>section,.methods>.toggle>summary{margin-bottom:0.75em;}.variants>.docblock,.implementors-toggle>.docblock,.impl-items>.toggle[open]:not(:last-child),.methods>.toggle[open]:not(:last-child),.implementors-toggle[open]:not(:last-child){margin-bottom:2em;}#trait-implementations-list .impl-items>.toggle:not(:last-child),#synthetic-implementations-list .impl-items>.toggle:not(:last-child),#blanket-implementations-list .impl-items>.toggle:not(:last-child){margin-bottom:1em;}.scraped-example-list .scrape-help{margin-left:10px;padding:0 4px;font-weight:normal;font-size:12px;position:relative;bottom:1px;border:1px solid var(--scrape-example-help-border-color);border-radius:50px;color:var(--scrape-example-help-color);}.scraped-example-list .scrape-help:hover{border-color:var(--scrape-example-help-hover-border-color);color:var(--scrape-example-help-hover-color);}.scraped-example{position:relative;}.scraped-example .code-wrapper{position:relative;display:flex;flex-direction:row;flex-wrap:wrap;width:100%;}.scraped-example:not(.expanded) .code-wrapper{max-height:calc(1.5em * 5 + 10px);}.scraped-example:not(.expanded) .code-wrapper pre{overflow-y:hidden;padding-bottom:0;max-height:calc(1.5em * 5 + 10px);}.more-scraped-examples .scraped-example:not(.expanded) .code-wrapper,.more-scraped-examples .scraped-example:not(.expanded) .code-wrapper pre{max-height:calc(1.5em * 10 + 10px);}.scraped-example .code-wrapper .next,.scraped-example .code-wrapper .prev,.scraped-example .code-wrapper .expand{color:var(--main-color);position:absolute;top:0.25em;z-index:1;padding:0;background:none;border:none;-webkit-appearance:none;opacity:1;}.scraped-example .code-wrapper .prev{right:2.25em;}.scraped-example .code-wrapper .next{right:1.25em;}.scraped-example .code-wrapper .expand{right:0.25em;}.scraped-example:not(.expanded) .code-wrapper::before,.scraped-example:not(.expanded) .code-wrapper::after{content:" ";width:100%;height:5px;position:absolute;z-index:1;}.scraped-example:not(.expanded) .code-wrapper::before{top:0;background:linear-gradient(to bottom,var(--scrape-example-code-wrapper-background-start),var(--scrape-example-code-wrapper-background-end));}.scraped-example:not(.expanded) .code-wrapper::after{bottom:0;background:linear-gradient(to top,var(--scrape-example-code-wrapper-background-start),var(--scrape-example-code-wrapper-background-end));}.scraped-example .code-wrapper .example-wrap{width:100%;overflow-y:hidden;margin-bottom:0;}.scraped-example:not(.expanded) .code-wrapper .example-wrap{overflow-x:hidden;}.scraped-example .example-wrap .rust span.highlight{background:var(--scrape-example-code-line-highlight);}.scraped-example .example-wrap .rust span.highlight.focus{background:var(--scrape-example-code-line-highlight-focus);}.more-examples-toggle{max-width:calc(100% + 25px);margin-top:10px;margin-left:-25px;}.more-examples-toggle .hide-more{margin-left:25px;cursor:pointer;}.more-scraped-examples{margin-left:25px;position:relative;}.toggle-line{position:absolute;top:5px;bottom:0;right:calc(100% + 10px);padding:0 4px;cursor:pointer;}.toggle-line-inner{min-width:2px;height:100%;background:var(--scrape-example-toggle-line-background);}.toggle-line:hover .toggle-line-inner{background:var(--scrape-example-toggle-line-hover-background);}.more-scraped-examples .scraped-example,.example-links{margin-top:20px;}.more-scraped-examples .scraped-example:first-child{margin-top:5px;}.example-links ul{margin-bottom:0;}:root[data-theme="light"]{--main-background-color:white;--main-color:black;--settings-input-color:#2196f3;--settings-input-border-color:#717171;--settings-button-color:#000;--settings-button-border-focus:#717171;--sidebar-background-color:#f5f5f5;--sidebar-background-color-hover:#e0e0e0;--code-block-background-color:#f5f5f5;--scrollbar-track-background-color:#dcdcdc;--scrollbar-thumb-background-color:rgba(36,37,39,0.6);--scrollbar-color:rgba(36,37,39,0.6) #d9d9d9;--headings-border-bottom-color:#ddd;--border-color:#e0e0e0;--button-background-color:#fff;--right-side-color:grey;--code-attribute-color:#999;--toggles-color:#999;--toggle-filter:none;--mobile-sidebar-menu-filter:none;--search-input-focused-border-color:#66afe9;--copy-path-button-color:#999;--copy-path-img-filter:invert(50%);--copy-path-img-hover-filter:invert(35%);--codeblock-error-hover-color:rgb(255,0,0);--codeblock-error-color:rgba(255,0,0,.5);--codeblock-ignore-hover-color:rgb(255,142,0);--codeblock-ignore-color:rgba(255,142,0,.6);--warning-border-color:#ff8e00;--type-link-color:#ad378a;--trait-link-color:#6e4fc9;--assoc-item-link-color:#3873ad;--function-link-color:#ad7c37;--macro-link-color:#068000;--keyword-link-color:#3873ad;--mod-link-color:#3873ad;--link-color:#3873ad;--sidebar-link-color:#356da4;--sidebar-current-link-background-color:#fff;--search-result-link-focus-background-color:#ccc;--search-result-border-color:#aaa3;--search-color:#000;--search-error-code-background-color:#d0cccc;--search-results-alias-color:#000;--search-results-grey-color:#999;--search-tab-title-count-color:#888;--search-tab-button-not-selected-border-top-color:#e6e6e6;--search-tab-button-not-selected-background:#e6e6e6;--search-tab-button-selected-border-top-color:#0089ff;--search-tab-button-selected-background:#fff;--stab-background-color:#fff5d6;--stab-code-color:#000;--code-highlight-kw-color:#8959a8;--code-highlight-kw-2-color:#4271ae;--code-highlight-lifetime-color:#b76514;--code-highlight-prelude-color:#4271ae;--code-highlight-prelude-val-color:#c82829;--code-highlight-number-color:#718c00;--code-highlight-string-color:#718c00;--code-highlight-literal-color:#c82829;--code-highlight-attribute-color:#c82829;--code-highlight-self-color:#c82829;--code-highlight-macro-color:#3e999f;--code-highlight-question-mark-color:#ff9011;--code-highlight-comment-color:#8e908c;--code-highlight-doc-comment-color:#4d4d4c;--src-line-numbers-span-color:#c67e2d;--src-line-number-highlighted-background-color:#fdffd3;--test-arrow-color:#f5f5f5;--test-arrow-background-color:rgba(78,139,202,0.2);--test-arrow-hover-color:#f5f5f5;--test-arrow-hover-background-color:rgb(78,139,202);--target-background-color:#fdffd3;--target-border-color:#ad7c37;--kbd-color:#000;--kbd-background:#fafbfc;--kbd-box-shadow-color:#c6cbd1;--rust-logo-filter:initial;--crate-search-div-filter:invert(100%) sepia(0%) saturate(4223%) hue-rotate(289deg) brightness(114%) contrast(76%);--crate-search-div-hover-filter:invert(44%) sepia(18%) saturate(23%) hue-rotate(317deg) brightness(96%) contrast(93%);--crate-search-hover-border:#717171;--src-sidebar-background-selected:#fff;--src-sidebar-background-hover:#e0e0e0;--table-alt-row-background-color:#f5f5f5;--codeblock-link-background:#eee;--scrape-example-toggle-line-background:#ccc;--scrape-example-toggle-line-hover-background:#999;--scrape-example-code-line-highlight:#fcffd6;--scrape-example-code-line-highlight-focus:#f6fdb0;--scrape-example-help-border-color:#555;--scrape-example-help-color:#333;--scrape-example-help-hover-border-color:#000;--scrape-example-help-hover-color:#000;--scrape-example-code-wrapper-background-start:rgba(255,255,255,1);--scrape-example-code-wrapper-background-end:rgba(255,255,255,0);--sidebar-resizer-hover:hsl(207,90%,66%);--sidebar-resizer-active:hsl(207,90%,54%);}:root[data-theme="dark"]{--main-background-color:#353535;--main-color:#ddd;--settings-input-color:#2196f3;--settings-input-border-color:#999;--settings-button-color:#000;--settings-button-border-focus:#ffb900;--sidebar-background-color:#505050;--sidebar-background-color-hover:#676767;--code-block-background-color:#2A2A2A;--scrollbar-track-background-color:#717171;--scrollbar-thumb-background-color:rgba(32,34,37,.6);--scrollbar-color:rgba(32,34,37,.6) #5a5a5a;--headings-border-bottom-color:#d2d2d2;--border-color:#e0e0e0;--button-background-color:#f0f0f0;--right-side-color:grey;--code-attribute-color:#999;--toggles-color:#999;--toggle-filter:invert(100%);--mobile-sidebar-menu-filter:invert(100%);--search-input-focused-border-color:#008dfd;--copy-path-button-color:#999;--copy-path-img-filter:invert(50%);--copy-path-img-hover-filter:invert(65%);--codeblock-error-hover-color:rgb(255,0,0);--codeblock-error-color:rgba(255,0,0,.5);--codeblock-ignore-hover-color:rgb(255,142,0);--codeblock-ignore-color:rgba(255,142,0,.6);--warning-border-color:#ff8e00;--type-link-color:#2dbfb8;--trait-link-color:#b78cf2;--assoc-item-link-color:#d2991d;--function-link-color:#2bab63;--macro-link-color:#09bd00;--keyword-link-color:#d2991d;--mod-link-color:#d2991d;--link-color:#d2991d;--sidebar-link-color:#fdbf35;--sidebar-current-link-background-color:#444;--search-result-link-focus-background-color:#616161;--search-result-border-color:#aaa3;--search-color:#111;--search-error-code-background-color:#484848;--search-results-alias-color:#fff;--search-results-grey-color:#ccc;--search-tab-title-count-color:#888;--search-tab-button-not-selected-border-top-color:#252525;--search-tab-button-not-selected-background:#252525;--search-tab-button-selected-border-top-color:#0089ff;--search-tab-button-selected-background:#353535;--stab-background-color:#314559;--stab-code-color:#e6e1cf;--code-highlight-kw-color:#ab8ac1;--code-highlight-kw-2-color:#769acb;--code-highlight-lifetime-color:#d97f26;--code-highlight-prelude-color:#769acb;--code-highlight-prelude-val-color:#ee6868;--code-highlight-number-color:#83a300;--code-highlight-string-color:#83a300;--code-highlight-literal-color:#ee6868;--code-highlight-attribute-color:#ee6868;--code-highlight-self-color:#ee6868;--code-highlight-macro-color:#3e999f;--code-highlight-question-mark-color:#ff9011;--code-highlight-comment-color:#8d8d8b;--code-highlight-doc-comment-color:#8ca375;--src-line-numbers-span-color:#3b91e2;--src-line-number-highlighted-background-color:#0a042f;--test-arrow-color:#dedede;--test-arrow-background-color:rgba(78,139,202,0.2);--test-arrow-hover-color:#dedede;--test-arrow-hover-background-color:#4e8bca;--target-background-color:#494a3d;--target-border-color:#bb7410;--kbd-color:#000;--kbd-background:#fafbfc;--kbd-box-shadow-color:#c6cbd1;--rust-logo-filter:drop-shadow(1px 0 0px #fff) drop-shadow(0 1px 0 #fff) drop-shadow(-1px 0 0 #fff) drop-shadow(0 -1px 0 #fff);--crate-search-div-filter:invert(94%) sepia(0%) saturate(721%) hue-rotate(255deg) brightness(90%) contrast(90%);--crate-search-div-hover-filter:invert(69%) sepia(60%) saturate(6613%) hue-rotate(184deg) brightness(100%) contrast(91%);--crate-search-hover-border:#2196f3;--src-sidebar-background-selected:#333;--src-sidebar-background-hover:#444;--table-alt-row-background-color:#2a2a2a;--codeblock-link-background:#333;--scrape-example-toggle-line-background:#999;--scrape-example-toggle-line-hover-background:#c5c5c5;--scrape-example-code-line-highlight:#5b3b01;--scrape-example-code-line-highlight-focus:#7c4b0f;--scrape-example-help-border-color:#aaa;--scrape-example-help-color:#eee;--scrape-example-help-hover-border-color:#fff;--scrape-example-help-hover-color:#fff;--scrape-example-code-wrapper-background-start:rgba(53,53,53,1);--scrape-example-code-wrapper-background-end:rgba(53,53,53,0);--sidebar-resizer-hover:hsl(207,30%,54%);--sidebar-resizer-active:hsl(207,90%,54%);}:root[data-theme="ayu"]{--main-background-color:#0f1419;--main-color:#c5c5c5;--settings-input-color:#ffb454;--settings-input-border-color:#999;--settings-button-color:#fff;--settings-button-border-focus:#e0e0e0;--sidebar-background-color:#14191f;--sidebar-background-color-hover:rgba(70,70,70,0.33);--code-block-background-color:#191f26;--scrollbar-track-background-color:transparent;--scrollbar-thumb-background-color:#5c6773;--scrollbar-color:#5c6773 #24292f;--headings-border-bottom-color:#5c6773;--border-color:#5c6773;--button-background-color:#141920;--right-side-color:grey;--code-attribute-color:#999;--toggles-color:#999;--toggle-filter:invert(100%);--mobile-sidebar-menu-filter:invert(100%);--search-input-focused-border-color:#5c6773;--copy-path-button-color:#fff;--copy-path-img-filter:invert(70%);--copy-path-img-hover-filter:invert(100%);--codeblock-error-hover-color:rgb(255,0,0);--codeblock-error-color:rgba(255,0,0,.5);--codeblock-ignore-hover-color:rgb(255,142,0);--codeblock-ignore-color:rgba(255,142,0,.6);--warning-border-color:#ff8e00;--type-link-color:#ffa0a5;--trait-link-color:#39afd7;--assoc-item-link-color:#39afd7;--function-link-color:#fdd687;--macro-link-color:#a37acc;--keyword-link-color:#39afd7;--mod-link-color:#39afd7;--link-color:#39afd7;--sidebar-link-color:#53b1db;--sidebar-current-link-background-color:transparent;--search-result-link-focus-background-color:#3c3c3c;--search-result-border-color:#aaa3;--search-color:#fff;--search-error-code-background-color:#4f4c4c;--search-results-alias-color:#c5c5c5;--search-results-grey-color:#999;--search-tab-title-count-color:#888;--search-tab-button-not-selected-border-top-color:none;--search-tab-button-not-selected-background:transparent !important;--search-tab-button-selected-border-top-color:none;--search-tab-button-selected-background:#141920 !important;--stab-background-color:#314559;--stab-code-color:#e6e1cf;--code-highlight-kw-color:#ff7733;--code-highlight-kw-2-color:#ff7733;--code-highlight-lifetime-color:#ff7733;--code-highlight-prelude-color:#69f2df;--code-highlight-prelude-val-color:#ff7733;--code-highlight-number-color:#b8cc52;--code-highlight-string-color:#b8cc52;--code-highlight-literal-color:#ff7733;--code-highlight-attribute-color:#e6e1cf;--code-highlight-self-color:#36a3d9;--code-highlight-macro-color:#a37acc;--code-highlight-question-mark-color:#ff9011;--code-highlight-comment-color:#788797;--code-highlight-doc-comment-color:#a1ac88;--src-line-numbers-span-color:#5c6773;--src-line-number-highlighted-background-color:rgba(255,236,164,0.06);--test-arrow-color:#788797;--test-arrow-background-color:rgba(57,175,215,0.09);--test-arrow-hover-color:#c5c5c5;--test-arrow-hover-background-color:rgba(57,175,215,0.368);--target-background-color:rgba(255,236,164,0.06);--target-border-color:rgba(255,180,76,0.85);--kbd-color:#c5c5c5;--kbd-background:#314559;--kbd-box-shadow-color:#5c6773;--rust-logo-filter:drop-shadow(1px 0 0px #fff) drop-shadow(0 1px 0 #fff) drop-shadow(-1px 0 0 #fff) drop-shadow(0 -1px 0 #fff);--crate-search-div-filter:invert(41%) sepia(12%) saturate(487%) hue-rotate(171deg) brightness(94%) contrast(94%);--crate-search-div-hover-filter:invert(98%) sepia(12%) saturate(81%) hue-rotate(343deg) brightness(113%) contrast(76%);--crate-search-hover-border:#e0e0e0;--src-sidebar-background-selected:#14191f;--src-sidebar-background-hover:#14191f;--table-alt-row-background-color:#191f26;--codeblock-link-background:#333;--scrape-example-toggle-line-background:#999;--scrape-example-toggle-line-hover-background:#c5c5c5;--scrape-example-code-line-highlight:#5b3b01;--scrape-example-code-line-highlight-focus:#7c4b0f;--scrape-example-help-border-color:#aaa;--scrape-example-help-color:#eee;--scrape-example-help-hover-border-color:#fff;--scrape-example-help-hover-color:#fff;--scrape-example-code-wrapper-background-start:rgba(15,20,25,1);--scrape-example-code-wrapper-background-end:rgba(15,20,25,0);--sidebar-resizer-hover:hsl(34,50%,33%);--sidebar-resizer-active:hsl(34,100%,66%);}:root[data-theme="ayu"] h1,:root[data-theme="ayu"] h2,:root[data-theme="ayu"] h3,:root[data-theme="ayu"] h4,:where(:root[data-theme="ayu"]) h1 a,:root[data-theme="ayu"] .sidebar h2 a,:root[data-theme="ayu"] .sidebar h3 a{color:#fff;}:root[data-theme="ayu"] .docblock code{color:#ffb454;}:root[data-theme="ayu"] .docblock a>code{color:#39AFD7 !important;}:root[data-theme="ayu"] .code-header,:root[data-theme="ayu"] .docblock pre>code,:root[data-theme="ayu"] pre,:root[data-theme="ayu"] pre>code,:root[data-theme="ayu"] .item-info code,:root[data-theme="ayu"] .rustdoc.source .example-wrap{color:#e6e1cf;}:root[data-theme="ayu"] .sidebar .current,:root[data-theme="ayu"] .sidebar .current a,:root[data-theme="ayu"] .sidebar a:hover,:root[data-theme="ayu"] #src-sidebar div.files>a:hover,:root[data-theme="ayu"] details.dir-entry summary:hover,:root[data-theme="ayu"] #src-sidebar div.files>a:focus,:root[data-theme="ayu"] details.dir-entry summary:focus,:root[data-theme="ayu"] #src-sidebar div.files>a.selected{color:#ffb44c;}:root[data-theme="ayu"] .sidebar-elems .location{color:#ff7733;}:root[data-theme="ayu"] .src-line-numbers .line-highlighted{color:#708090;padding-right:7px;border-right:1px solid #ffb44c;}:root[data-theme="ayu"] .search-results a:hover,:root[data-theme="ayu"] .search-results a:focus{color:#fff !important;background-color:#3c3c3c;}:root[data-theme="ayu"] .search-results a{color:#0096cf;}:root[data-theme="ayu"] .search-results a div.desc{color:#c5c5c5;}:root[data-theme="ayu"] .result-name .primitive>i,:root[data-theme="ayu"] .result-name .keyword>i{color:#788797;}:root[data-theme="ayu"] #search-tabs>button.selected{border-bottom:1px solid #ffb44c !important;border-top:none;}:root[data-theme="ayu"] #search-tabs>button:not(.selected){border:none;background-color:transparent !important;}:root[data-theme="ayu"] #search-tabs>button:hover{border-bottom:1px solid rgba(242,151,24,0.3);}:root[data-theme="ayu"] #settings-menu>a img,:root[data-theme="ayu"] #sidebar-button>a:before{filter:invert(100);} \ No newline at end of file diff --git a/static.files/scrape-examples-ef1e698c1d417c0c.js b/static.files/scrape-examples-ef1e698c1d417c0c.js new file mode 100644 index 00000000..ba830e37 --- /dev/null +++ b/static.files/scrape-examples-ef1e698c1d417c0c.js @@ -0,0 +1 @@ +"use strict";(function(){const DEFAULT_MAX_LINES=5;const HIDDEN_MAX_LINES=10;function scrollToLoc(elt,loc,isHidden){const lines=elt.querySelector(".src-line-numbers");let scrollOffset;const maxLines=isHidden?HIDDEN_MAX_LINES:DEFAULT_MAX_LINES;if(loc[1]-loc[0]>maxLines){const line=Math.max(0,loc[0]-1);scrollOffset=lines.children[line].offsetTop}else{const wrapper=elt.querySelector(".code-wrapper");const halfHeight=wrapper.offsetHeight/2;const offsetTop=lines.children[loc[0]].offsetTop;const lastLine=lines.children[loc[1]];const offsetBot=lastLine.offsetTop+lastLine.offsetHeight;const offsetMid=(offsetTop+offsetBot)/2;scrollOffset=offsetMid-halfHeight}lines.scrollTo(0,scrollOffset);elt.querySelector(".rust").scrollTo(0,scrollOffset)}function updateScrapedExample(example,isHidden){const locs=JSON.parse(example.attributes.getNamedItem("data-locs").textContent);let locIndex=0;const highlights=Array.prototype.slice.call(example.querySelectorAll(".highlight"));const link=example.querySelector(".scraped-example-title a");if(locs.length>1){const onChangeLoc=changeIndex=>{removeClass(highlights[locIndex],"focus");changeIndex();scrollToLoc(example,locs[locIndex][0],isHidden);addClass(highlights[locIndex],"focus");const url=locs[locIndex][1];const title=locs[locIndex][2];link.href=url;link.innerHTML=title};example.querySelector(".prev").addEventListener("click",()=>{onChangeLoc(()=>{locIndex=(locIndex-1+locs.length)%locs.length})});example.querySelector(".next").addEventListener("click",()=>{onChangeLoc(()=>{locIndex=(locIndex+1)%locs.length})})}const expandButton=example.querySelector(".expand");if(expandButton){expandButton.addEventListener("click",()=>{if(hasClass(example,"expanded")){removeClass(example,"expanded");scrollToLoc(example,locs[0][0],isHidden)}else{addClass(example,"expanded")}})}scrollToLoc(example,locs[0][0],isHidden)}const firstExamples=document.querySelectorAll(".scraped-example-list > .scraped-example");onEachLazy(firstExamples,el=>updateScrapedExample(el,false));onEachLazy(document.querySelectorAll(".more-examples-toggle"),toggle=>{onEachLazy(toggle.querySelectorAll(".toggle-line, .hide-more"),button=>{button.addEventListener("click",()=>{toggle.open=false})});const moreExamples=toggle.querySelectorAll(".scraped-example");toggle.querySelector("summary").addEventListener("click",()=>{setTimeout(()=>{onEachLazy(moreExamples,el=>updateScrapedExample(el,true))})},{once:true})})})() \ No newline at end of file diff --git a/static.files/search-dd67cee4cfa65049.js b/static.files/search-dd67cee4cfa65049.js new file mode 100644 index 00000000..ef8bf865 --- /dev/null +++ b/static.files/search-dd67cee4cfa65049.js @@ -0,0 +1,5 @@ +"use strict";if(!Array.prototype.toSpliced){Array.prototype.toSpliced=function(){const me=this.slice();Array.prototype.splice.apply(me,arguments);return me}}(function(){const itemTypes=["keyword","primitive","mod","externcrate","import","struct","enum","fn","type","static","trait","impl","tymethod","method","structfield","variant","macro","associatedtype","constant","associatedconstant","union","foreigntype","existential","attr","derive","traitalias","generic",];const longItemTypes=["keyword","primitive type","module","extern crate","re-export","struct","enum","function","type alias","static","trait","","trait method","method","struct field","enum variant","macro","assoc type","constant","assoc const","union","foreign type","existential type","attribute macro","derive macro","trait alias",];const TY_GENERIC=itemTypes.indexOf("generic");const ROOT_PATH=typeof window!=="undefined"?window.rootPath:"../";function printTab(nb){let iter=0;let foundCurrentTab=false;let foundCurrentResultSet=false;onEachLazy(document.getElementById("search-tabs").childNodes,elem=>{if(nb===iter){addClass(elem,"selected");foundCurrentTab=true}else{removeClass(elem,"selected")}iter+=1});const isTypeSearch=(nb>0||iter===1);iter=0;onEachLazy(document.getElementById("results").childNodes,elem=>{if(nb===iter){addClass(elem,"active");foundCurrentResultSet=true}else{removeClass(elem,"active")}iter+=1});if(foundCurrentTab&&foundCurrentResultSet){searchState.currentTab=nb;const correctionsElem=document.getElementsByClassName("search-corrections");if(isTypeSearch){removeClass(correctionsElem[0],"hidden")}else{addClass(correctionsElem[0],"hidden")}}else if(nb!==0){printTab(0)}}const editDistanceState={current:[],prev:[],prevPrev:[],calculate:function calculate(a,b,limit){if(a.lengthlimit){return limit+1}while(b.length>0&&b[0]===a[0]){a=a.substring(1);b=b.substring(1)}while(b.length>0&&b[b.length-1]===a[a.length-1]){a=a.substring(0,a.length-1);b=b.substring(0,b.length-1)}if(b.length===0){return minDist}const aLength=a.length;const bLength=b.length;for(let i=0;i<=bLength;++i){this.current[i]=0;this.prev[i]=i;this.prevPrev[i]=Number.MAX_VALUE}for(let i=1;i<=aLength;++i){this.current[0]=i;const aIdx=i-1;for(let j=1;j<=bLength;++j){const bIdx=j-1;const substitutionCost=a[aIdx]===b[bIdx]?0:1;this.current[j]=Math.min(this.prev[j]+1,this.current[j-1]+1,this.prev[j-1]+substitutionCost);if((i>1)&&(j>1)&&(a[aIdx]===b[bIdx-1])&&(a[aIdx-1]===b[bIdx])){this.current[j]=Math.min(this.current[j],this.prevPrev[j-2]+1)}}const prevPrevTmp=this.prevPrev;this.prevPrev=this.prev;this.prev=this.current;this.current=prevPrevTmp}const distance=this.prev[bLength];return distance<=limit?distance:(limit+1)},};function editDistance(a,b,limit){return editDistanceState.calculate(a,b,limit)}function initSearch(rawSearchIndex){const MAX_RESULTS=200;const NO_TYPE_FILTER=-1;let searchIndex;let functionTypeFingerprint;let currentResults;let typeNameIdMap;const ALIASES=new Map();let typeNameIdOfArray;let typeNameIdOfSlice;let typeNameIdOfArrayOrSlice;let typeNameIdOfTuple;let typeNameIdOfUnit;let typeNameIdOfTupleOrUnit;function buildTypeMapIndex(name,isAssocType){if(name===""||name===null){return null}if(typeNameIdMap.has(name)){const obj=typeNameIdMap.get(name);obj.assocOnly=isAssocType&&obj.assocOnly;return obj.id}else{const id=typeNameIdMap.size;typeNameIdMap.set(name,{id,assocOnly:isAssocType});return id}}function isSpecialStartCharacter(c){return"<\"".indexOf(c)!==-1}function isEndCharacter(c){return"=,>-])".indexOf(c)!==-1}function itemTypeFromName(typename){const index=itemTypes.findIndex(i=>i===typename);if(index<0){throw["Unknown type filter ",typename]}return index}function getStringElem(query,parserState,isInGenerics){if(isInGenerics){throw["Unexpected ","\""," in generics"]}else if(query.literalSearch){throw["Cannot have more than one literal search element"]}else if(parserState.totalElems-parserState.genericsElems>0){throw["Cannot use literal search when there is more than one element"]}parserState.pos+=1;const start=parserState.pos;const end=getIdentEndPosition(parserState);if(parserState.pos>=parserState.length){throw["Unclosed ","\""]}else if(parserState.userQuery[end]!=="\""){throw["Unexpected ",parserState.userQuery[end]," in a string element"]}else if(start===end){throw["Cannot have empty string element"]}parserState.pos+=1;query.literalSearch=true}function isPathStart(parserState){return parserState.userQuery.slice(parserState.pos,parserState.pos+2)==="::"}function isReturnArrow(parserState){return parserState.userQuery.slice(parserState.pos,parserState.pos+2)==="->"}function isIdentCharacter(c){return(c==="_"||(c>="0"&&c<="9")||(c>="a"&&c<="z")||(c>="A"&&c<="Z"))}function isSeparatorCharacter(c){return c===","||c==="="}function isPathSeparator(c){return c===":"||c===" "}function prevIs(parserState,lookingFor){let pos=parserState.pos;while(pos>0){const c=parserState.userQuery[pos-1];if(c===lookingFor){return true}else if(c!==" "){break}pos-=1}return false}function isLastElemGeneric(elems,parserState){return(elems.length>0&&elems[elems.length-1].generics.length>0)||prevIs(parserState,">")}function skipWhitespace(parserState){while(parserState.pos0){throw["Cannot have more than one element if you use quotes"]}const typeFilter=parserState.typeFilter;parserState.typeFilter=null;if(name==="!"){if(typeFilter!==null&&typeFilter!=="primitive"){throw["Invalid search type: primitive never type ","!"," and ",typeFilter," both specified",]}if(generics.length!==0){throw["Never type ","!"," does not accept generic parameters",]}const bindingName=parserState.isInBinding;parserState.isInBinding=null;return{name:"never",id:null,fullPath:["never"],pathWithoutLast:[],pathLast:"never",normalizedPathLast:"never",generics:[],bindings:new Map(),typeFilter:"primitive",bindingName,}}const quadcolon=/::\s*::/.exec(path);if(path.startsWith("::")){throw["Paths cannot start with ","::"]}else if(path.endsWith("::")){throw["Paths cannot end with ","::"]}else if(quadcolon!==null){throw["Unexpected ",quadcolon[0]]}const pathSegments=path.split(/(?:::\s*)|(?:\s+(?:::\s*)?)/);if(pathSegments.length===0||(pathSegments.length===1&&pathSegments[0]==="")){if(generics.length>0||prevIs(parserState,">")){throw["Found generics without a path"]}else{throw["Unexpected ",parserState.userQuery[parserState.pos]]}}for(const[i,pathSegment]of pathSegments.entries()){if(pathSegment==="!"){if(i!==0){throw["Never type ","!"," is not associated item"]}pathSegments[i]="never"}}parserState.totalElems+=1;if(isInGenerics){parserState.genericsElems+=1}const bindingName=parserState.isInBinding;parserState.isInBinding=null;const bindings=new Map();const pathLast=pathSegments[pathSegments.length-1];return{name:name.trim(),id:null,fullPath:pathSegments,pathWithoutLast:pathSegments.slice(0,pathSegments.length-1),pathLast,normalizedPathLast:pathLast.replace(/_/g,""),generics:generics.filter(gen=>{if(gen.bindingName!==null){bindings.set(gen.bindingName.name,[gen,...gen.bindingName.generics]);return false}return true}),bindings,typeFilter,bindingName,}}function getIdentEndPosition(parserState){const start=parserState.pos;let end=parserState.pos;let foundExclamation=-1;while(parserState.pos0){throw["Unexpected ",c," after ",parserState.userQuery[parserState.pos-1]]}else{throw["Unexpected ",c]}}parserState.pos+=1;end=parserState.pos}if(foundExclamation!==-1&&foundExclamation!==start&&isIdentCharacter(parserState.userQuery[foundExclamation-1])){if(parserState.typeFilter===null){parserState.typeFilter="macro"}else if(parserState.typeFilter!=="macro"){throw["Invalid search type: macro ","!"," and ",parserState.typeFilter," both specified",]}end=foundExclamation}return end}function getNextElem(query,parserState,elems,isInGenerics){const generics=[];skipWhitespace(parserState);let start=parserState.pos;let end;if("[(".indexOf(parserState.userQuery[parserState.pos])!==-1){let endChar=")";let name="()";let friendlyName="tuple";if(parserState.userQuery[parserState.pos]==="["){endChar="]";name="[]";friendlyName="slice"}parserState.pos+=1;const{foundSeparator}=getItemsBefore(query,parserState,generics,endChar);const typeFilter=parserState.typeFilter;const isInBinding=parserState.isInBinding;if(typeFilter!==null&&typeFilter!=="primitive"){throw["Invalid search type: primitive ",name," and ",typeFilter," both specified",]}parserState.typeFilter=null;parserState.isInBinding=null;for(const gen of generics){if(gen.bindingName!==null){throw["Type parameter ","=",` cannot be within ${friendlyName} `,name]}}if(name==="()"&&!foundSeparator&&generics.length===1&&typeFilter===null){elems.push(generics[0])}else{parserState.totalElems+=1;if(isInGenerics){parserState.genericsElems+=1}elems.push({name:name,id:null,fullPath:[name],pathWithoutLast:[],pathLast:name,normalizedPathLast:name,generics,bindings:new Map(),typeFilter:"primitive",bindingName:isInBinding,})}}else{const isStringElem=parserState.userQuery[start]==="\"";if(isStringElem){start+=1;getStringElem(query,parserState,isInGenerics);end=parserState.pos-1}else{end=getIdentEndPosition(parserState)}if(parserState.pos=end){throw["Found generics without a path"]}parserState.pos+=1;getItemsBefore(query,parserState,generics,">")}if(isStringElem){skipWhitespace(parserState)}if(start>=end&&generics.length===0){return}if(parserState.userQuery[parserState.pos]==="="){if(parserState.isInBinding){throw["Cannot write ","="," twice in a binding"]}if(!isInGenerics){throw["Type parameter ","="," must be within generics list"]}const name=parserState.userQuery.slice(start,end).trim();if(name==="!"){throw["Type parameter ","="," key cannot be ","!"," never type"]}if(name.includes("!")){throw["Type parameter ","="," key cannot be ","!"," macro"]}if(name.includes("::")){throw["Type parameter ","="," key cannot contain ","::"," path"]}if(name.includes(":")){throw["Type parameter ","="," key cannot contain ",":"," type"]}parserState.isInBinding={name,generics}}else{elems.push(createQueryElement(query,parserState,parserState.userQuery.slice(start,end),generics,isInGenerics))}}}function getItemsBefore(query,parserState,elems,endChar){let foundStopChar=true;let foundSeparator=false;let start=parserState.pos;const oldTypeFilter=parserState.typeFilter;parserState.typeFilter=null;const oldIsInBinding=parserState.isInBinding;parserState.isInBinding=null;let extra="";if(endChar===">"){extra="<"}else if(endChar==="]"){extra="["}else if(endChar===")"){extra="("}else if(endChar===""){extra="->"}else{extra=endChar}while(parserState.pos"]}else if(prevIs(parserState,"\"")){throw["Cannot have more than one element if you use quotes"]}if(endChar!==""){throw["Expected ",",",", ","=",", or ",endChar,...extra,", found ",c,]}throw["Expected ",","," or ","=",...extra,", found ",c,]}const posBefore=parserState.pos;start=parserState.pos;getNextElem(query,parserState,elems,endChar!=="");if(endChar!==""&&parserState.pos>=parserState.length){throw["Unclosed ",extra]}if(posBefore===parserState.pos){parserState.pos+=1}foundStopChar=false}if(parserState.pos>=parserState.length&&endChar!==""){throw["Unclosed ",extra]}parserState.pos+=1;parserState.typeFilter=oldTypeFilter;parserState.isInBinding=oldIsInBinding;return{foundSeparator}}function checkExtraTypeFilterCharacters(start,parserState){const query=parserState.userQuery.slice(start,parserState.pos).trim();for(const c in query){if(!isIdentCharacter(query[c])){throw["Unexpected ",query[c]," in type filter (before ",":",")",]}}}function parseInput(query,parserState){let foundStopChar=true;let start=parserState.pos;while(parserState.pos"){if(isReturnArrow(parserState)){break}throw["Unexpected ",c," (did you mean ","->","?)"]}else if(parserState.pos>0){throw["Unexpected ",c," after ",parserState.userQuery[parserState.pos-1]]}throw["Unexpected ",c]}else if(c===":"&&!isPathStart(parserState)){if(parserState.typeFilter!==null){throw["Unexpected ",":"," (expected path after type filter ",parserState.typeFilter+":",")",]}else if(query.elems.length===0){throw["Expected type filter before ",":"]}else if(query.literalSearch){throw["Cannot use quotes on type filter"]}const typeFilterElem=query.elems.pop();checkExtraTypeFilterCharacters(start,parserState);parserState.typeFilter=typeFilterElem.name;parserState.pos+=1;parserState.totalElems-=1;query.literalSearch=false;foundStopChar=true;continue}else if(c===" "){skipWhitespace(parserState);continue}if(!foundStopChar){let extra="";if(isLastElemGeneric(query.elems,parserState)){extra=[" after ",">"]}else if(prevIs(parserState,"\"")){throw["Cannot have more than one element if you use quotes"]}if(parserState.typeFilter!==null){throw["Expected ",","," or ","->",...extra,", found ",c,]}throw["Expected ",",",", ",":"," or ","->",...extra,", found ",c,]}const before=query.elems.length;start=parserState.pos;getNextElem(query,parserState,query.elems,false);if(query.elems.length===before){parserState.pos+=1}foundStopChar=false}if(parserState.typeFilter!==null){throw["Unexpected ",":"," (expected path after type filter ",parserState.typeFilter+":",")",]}while(parserState.pos"]}break}else{parserState.pos+=1}}}function newParsedQuery(userQuery){return{original:userQuery,userQuery:userQuery.toLowerCase(),elems:[],returned:[],foundElems:0,totalElems:0,literalSearch:false,error:null,correction:null,proposeCorrectionFrom:null,proposeCorrectionTo:null,typeFingerprint:new Uint32Array(4),}}function buildUrl(search,filterCrates){let extra="?search="+encodeURIComponent(search);if(filterCrates!==null){extra+="&filter-crate="+encodeURIComponent(filterCrates)}return getNakedUrl()+extra+window.location.hash}function getFilterCrates(){const elem=document.getElementById("crate-search");if(elem&&elem.value!=="all crates"&&rawSearchIndex.has(elem.value)){return elem.value}return null}function parseQuery(userQuery){function convertTypeFilterOnElem(elem){if(elem.typeFilter!==null){let typeFilter=elem.typeFilter;if(typeFilter==="const"){typeFilter="constant"}elem.typeFilter=itemTypeFromName(typeFilter)}else{elem.typeFilter=NO_TYPE_FILTER}for(const elem2 of elem.generics){convertTypeFilterOnElem(elem2)}for(const constraints of elem.bindings.values()){for(const constraint of constraints){convertTypeFilterOnElem(constraint)}}}userQuery=userQuery.trim().replace(/\r|\n|\t/g," ");const parserState={length:userQuery.length,pos:0,totalElems:0,genericsElems:0,typeFilter:null,isInBinding:null,userQuery:userQuery.toLowerCase(),};let query=newParsedQuery(userQuery);try{parseInput(query,parserState);for(const elem of query.elems){convertTypeFilterOnElem(elem)}for(const elem of query.returned){convertTypeFilterOnElem(elem)}}catch(err){query=newParsedQuery(userQuery);query.error=err;return query}if(!query.literalSearch){query.literalSearch=parserState.totalElems>1}query.foundElems=query.elems.length+query.returned.length;query.totalElems=parserState.totalElems;return query}function createQueryResults(results_in_args,results_returned,results_others,parsedQuery){return{"in_args":results_in_args,"returned":results_returned,"others":results_others,"query":parsedQuery,}}function execQuery(parsedQuery,filterCrates,currentCrate){const results_others=new Map(),results_in_args=new Map(),results_returned=new Map();function transformResults(results){const duplicates=new Set();const out=[];for(const result of results){if(result.id!==-1){const obj=searchIndex[result.id];obj.dist=result.dist;const res=buildHrefAndPath(obj);obj.displayPath=pathSplitter(res[0]);obj.fullPath=obj.displayPath+obj.name;obj.fullPath+="|"+obj.ty;if(duplicates.has(obj.fullPath)){continue}duplicates.add(obj.fullPath);obj.href=res[1];out.push(obj);if(out.length>=MAX_RESULTS){break}}}return out}function sortResults(results,isType,preferredCrate){if(results.size===0){return[]}const userQuery=parsedQuery.userQuery;const result_list=[];for(const result of results.values()){result.item=searchIndex[result.id];result.word=searchIndex[result.id].word;result_list.push(result)}result_list.sort((aaa,bbb)=>{let a,b;a=(aaa.word!==userQuery);b=(bbb.word!==userQuery);if(a!==b){return a-b}a=(aaa.index<0);b=(bbb.index<0);if(a!==b){return a-b}a=aaa.path_dist;b=bbb.path_dist;if(a!==b){return a-b}a=aaa.index;b=bbb.index;if(a!==b){return a-b}a=(aaa.dist);b=(bbb.dist);if(a!==b){return a-b}a=aaa.item.deprecated;b=bbb.item.deprecated;if(a!==b){return a-b}a=(aaa.item.crate!==preferredCrate);b=(bbb.item.crate!==preferredCrate);if(a!==b){return a-b}a=aaa.word.length;b=bbb.word.length;if(a!==b){return a-b}a=aaa.word;b=bbb.word;if(a!==b){return(a>b?+1:-1)}a=(aaa.item.desc==="");b=(bbb.item.desc==="");if(a!==b){return a-b}a=aaa.item.ty;b=bbb.item.ty;if(a!==b){return a-b}a=aaa.item.path;b=bbb.item.path;if(a!==b){return(a>b?+1:-1)}return 0});return transformResults(result_list)}function unifyFunctionTypes(fnTypesIn,queryElems,whereClause,mgensIn,solutionCb){const mgens=mgensIn===null?null:new Map(mgensIn);if(queryElems.length===0){return!solutionCb||solutionCb(mgens)}if(!fnTypesIn||fnTypesIn.length===0){return false}const ql=queryElems.length;const fl=fnTypesIn.length;if(ql===1&&queryElems[0].generics.length===0&&queryElems[0].bindings.size===0){const queryElem=queryElems[0];for(const fnType of fnTypesIn){if(!unifyFunctionTypeIsMatchCandidate(fnType,queryElem,whereClause,mgens)){continue}if(fnType.id<0&&queryElem.id<0){if(mgens&&mgens.has(fnType.id)&&mgens.get(fnType.id)!==queryElem.id){continue}const mgensScratch=new Map(mgens);mgensScratch.set(fnType.id,queryElem.id);if(!solutionCb||solutionCb(mgensScratch)){return true}}else if(!solutionCb||solutionCb(mgens?new Map(mgens):null)){return true}}for(const fnType of fnTypesIn){if(!unifyFunctionTypeIsUnboxCandidate(fnType,queryElem,whereClause,mgens)){continue}if(fnType.id<0){if(mgens&&mgens.has(fnType.id)&&mgens.get(fnType.id)!==0){continue}const mgensScratch=new Map(mgens);mgensScratch.set(fnType.id,0);if(unifyFunctionTypes(whereClause[(-fnType.id)-1],queryElems,whereClause,mgensScratch,solutionCb)){return true}}else if(unifyFunctionTypes([...fnType.generics,...Array.from(fnType.bindings.values()).flat()],queryElems,whereClause,mgens?new Map(mgens):null,solutionCb)){return true}}return false}const fnTypes=fnTypesIn.slice();const flast=fl-1;const qlast=ql-1;const queryElem=queryElems[qlast];let queryElemsTmp=null;for(let i=flast;i>=0;i-=1){const fnType=fnTypes[i];if(!unifyFunctionTypeIsMatchCandidate(fnType,queryElem,whereClause,mgens)){continue}let mgensScratch;if(fnType.id<0){mgensScratch=new Map(mgens);if(mgensScratch.has(fnType.id)&&mgensScratch.get(fnType.id)!==queryElem.id){continue}mgensScratch.set(fnType.id,queryElem.id)}else{mgensScratch=mgens}fnTypes[i]=fnTypes[flast];fnTypes.length=flast;if(!queryElemsTmp){queryElemsTmp=queryElems.slice(0,qlast)}const passesUnification=unifyFunctionTypes(fnTypes,queryElemsTmp,whereClause,mgensScratch,mgensScratch=>{if(fnType.generics.length===0&&queryElem.generics.length===0&&fnType.bindings.size===0&&queryElem.bindings.size===0){return!solutionCb||solutionCb(mgensScratch)}const solution=unifyFunctionTypeCheckBindings(fnType,queryElem,whereClause,mgensScratch);if(!solution){return false}const simplifiedGenerics=solution.simplifiedGenerics;for(const simplifiedMgens of solution.mgens){const passesUnification=unifyFunctionTypes(simplifiedGenerics,queryElem.generics,whereClause,simplifiedMgens,solutionCb);if(passesUnification){return true}}return false});if(passesUnification){return true}fnTypes[flast]=fnTypes[i];fnTypes[i]=fnType;fnTypes.length=fl}for(let i=flast;i>=0;i-=1){const fnType=fnTypes[i];if(!unifyFunctionTypeIsUnboxCandidate(fnType,queryElem,whereClause,mgens)){continue}let mgensScratch;if(fnType.id<0){mgensScratch=new Map(mgens);if(mgensScratch.has(fnType.id)&&mgensScratch.get(fnType.id)!==0){continue}mgensScratch.set(fnType.id,0)}else{mgensScratch=mgens}const generics=fnType.id<0?whereClause[(-fnType.id)-1]:fnType.generics;const bindings=fnType.bindings?Array.from(fnType.bindings.values()).flat():[];const passesUnification=unifyFunctionTypes(fnTypes.toSpliced(i,1,...generics,...bindings),queryElems,whereClause,mgensScratch,solutionCb);if(passesUnification){return true}}return false}function unifyFunctionTypeIsMatchCandidate(fnType,queryElem,whereClause,mgensIn){if(!typePassesFilter(queryElem.typeFilter,fnType.ty)){return false}if(fnType.id<0&&queryElem.id<0){if(mgensIn){if(mgensIn.has(fnType.id)&&mgensIn.get(fnType.id)!==queryElem.id){return false}for(const[fid,qid]of mgensIn.entries()){if(fnType.id!==fid&&queryElem.id===qid){return false}if(fnType.id===fid&&queryElem.id!==qid){return false}}}return true}else{if(queryElem.id===typeNameIdOfArrayOrSlice&&(fnType.id===typeNameIdOfSlice||fnType.id===typeNameIdOfArray)){}else if(queryElem.id===typeNameIdOfTupleOrUnit&&(fnType.id===typeNameIdOfTuple||fnType.id===typeNameIdOfUnit)){}else if(fnType.id!==queryElem.id||queryElem.id===null){return false}if((fnType.generics.length+fnType.bindings.size)===0&&queryElem.generics.length!==0){return false}if(fnType.bindings.size0){const fnTypePath=fnType.path!==undefined&&fnType.path!==null?fnType.path.split("::"):[];if(queryElemPathLength>fnTypePath.length){return false}let i=0;for(const path of fnTypePath){if(path===queryElem.pathWithoutLast[i]){i+=1;if(i>=queryElemPathLength){break}}}if(i0){let mgensSolutionSet=[mgensIn];for(const[name,constraints]of queryElem.bindings.entries()){if(mgensSolutionSet.length===0){return false}if(!fnType.bindings.has(name)){return false}const fnTypeBindings=fnType.bindings.get(name);mgensSolutionSet=mgensSolutionSet.flatMap(mgens=>{const newSolutions=[];unifyFunctionTypes(fnTypeBindings,constraints,whereClause,mgens,newMgens=>{newSolutions.push(newMgens);return false});return newSolutions})}if(mgensSolutionSet.length===0){return false}const binds=Array.from(fnType.bindings.entries()).flatMap(entry=>{const[name,constraints]=entry;if(queryElem.bindings.has(name)){return[]}else{return constraints}});if(simplifiedGenerics.length>0){simplifiedGenerics=[...simplifiedGenerics,...binds]}else{simplifiedGenerics=binds}return{simplifiedGenerics,mgens:mgensSolutionSet}}return{simplifiedGenerics,mgens:[mgensIn]}}function unifyFunctionTypeIsUnboxCandidate(fnType,queryElem,whereClause,mgens){if(fnType.id<0&&queryElem.id>=0){if(!whereClause){return false}if(mgens&&mgens.has(fnType.id)&&mgens.get(fnType.id)!==0){return false}const mgensTmp=new Map(mgens);mgensTmp.set(fnType.id,null);return checkIfInList(whereClause[(-fnType.id)-1],queryElem,whereClause,mgensTmp)}else if(fnType.generics.length>0||fnType.bindings.size>0){const simplifiedGenerics=[...fnType.generics,...Array.from(fnType.bindings.values()).flat(),];return checkIfInList(simplifiedGenerics,queryElem,whereClause,mgens)}return false}function checkIfInList(list,elem,whereClause,mgens){for(const entry of list){if(checkType(entry,elem,whereClause,mgens)){return true}}return false}function checkType(row,elem,whereClause,mgens){if(row.bindings.size===0&&elem.bindings.size===0){if(elem.id<0){return row.id<0||checkIfInList(row.generics,elem,whereClause,mgens)}if(row.id>0&&elem.id>0&&elem.pathWithoutLast.length===0&&typePassesFilter(elem.typeFilter,row.ty)&&elem.generics.length===0&&elem.id!==typeNameIdOfArrayOrSlice&&elem.id!==typeNameIdOfTupleOrUnit){return row.id===elem.id||checkIfInList(row.generics,elem,whereClause,mgens)}}return unifyFunctionTypes([row],[elem],whereClause,mgens)}function checkPath(contains,ty){if(contains.length===0){return 0}const maxPathEditDistance=Math.floor(contains.reduce((acc,next)=>acc+next.length,0)/3);let ret_dist=maxPathEditDistance+1;const path=ty.path.split("::");if(ty.parent&&ty.parent.name){path.push(ty.parent.name.toLowerCase())}const length=path.length;const clength=contains.length;pathiter:for(let i=length-clength;i>=0;i-=1){let dist_total=0;for(let x=0;xmaxPathEditDistance){continue pathiter}dist_total+=dist}}ret_dist=Math.min(ret_dist,Math.round(dist_total/clength))}return ret_dist>maxPathEditDistance?null:ret_dist}function typePassesFilter(filter,type){if(filter<=NO_TYPE_FILTER||filter===type)return true;const name=itemTypes[type];switch(itemTypes[filter]){case"constant":return name==="associatedconstant";case"fn":return name==="method"||name==="tymethod";case"type":return name==="primitive"||name==="associatedtype";case"trait":return name==="traitalias"}return false}function createAliasFromItem(item){return{crate:item.crate,name:item.name,path:item.path,desc:item.desc,ty:item.ty,parent:item.parent,type:item.type,is_alias:true,deprecated:item.deprecated,implDisambiguator:item.implDisambiguator,}}function handleAliases(ret,query,filterCrates,currentCrate){const lowerQuery=query.toLowerCase();const aliases=[];const crateAliases=[];if(filterCrates!==null){if(ALIASES.has(filterCrates)&&ALIASES.get(filterCrates).has(lowerQuery)){const query_aliases=ALIASES.get(filterCrates).get(lowerQuery);for(const alias of query_aliases){aliases.push(createAliasFromItem(searchIndex[alias]))}}}else{for(const[crate,crateAliasesIndex]of ALIASES){if(crateAliasesIndex.has(lowerQuery)){const pushTo=crate===currentCrate?crateAliases:aliases;const query_aliases=crateAliasesIndex.get(lowerQuery);for(const alias of query_aliases){pushTo.push(createAliasFromItem(searchIndex[alias]))}}}}const sortFunc=(aaa,bbb)=>{if(aaa.path{alias.alias=query;const res=buildHrefAndPath(alias);alias.displayPath=pathSplitter(res[0]);alias.fullPath=alias.displayPath+alias.name;alias.href=res[1];ret.others.unshift(alias);if(ret.others.length>MAX_RESULTS){ret.others.pop()}};aliases.forEach(pushFunc);crateAliases.forEach(pushFunc)}function addIntoResults(results,fullId,id,index,dist,path_dist,maxEditDistance){if(dist<=maxEditDistance||index!==-1){if(results.has(fullId)){const result=results.get(fullId);if(result.dontValidate||result.dist<=dist){return}}results.set(fullId,{id:id,index:index,dontValidate:parsedQuery.literalSearch,dist:dist,path_dist:path_dist,})}}function handleSingleArg(row,pos,elem,results_others,results_in_args,results_returned,maxEditDistance){if(!row||(filterCrates!==null&&row.crate!==filterCrates)){return}let path_dist=0;const fullId=row.id;const tfpDist=compareTypeFingerprints(fullId,parsedQuery.typeFingerprint);if(tfpDist!==null){const in_args=row.type&&row.type.inputs&&checkIfInList(row.type.inputs,elem,row.type.where_clause);const returned=row.type&&row.type.output&&checkIfInList(row.type.output,elem,row.type.where_clause);if(in_args){results_in_args.max_dist=Math.max(results_in_args.max_dist||0,tfpDist);const maxDist=results_in_args.sizenormalizedIndex&&normalizedIndex!==-1)){index=normalizedIndex}if(elem.fullPath.length>1){path_dist=checkPath(elem.pathWithoutLast,row);if(path_dist===null){return}}if(parsedQuery.literalSearch){if(row.word===elem.pathLast){addIntoResults(results_others,fullId,pos,index,0,path_dist)}return}const dist=editDistance(row.normalizedName,elem.normalizedPathLast,maxEditDistance);if(index===-1&&dist>maxEditDistance){return}addIntoResults(results_others,fullId,pos,index,dist,path_dist,maxEditDistance)}function handleArgs(row,pos,results){if(!row||(filterCrates!==null&&row.crate!==filterCrates)||!row.type){return}const tfpDist=compareTypeFingerprints(row.id,parsedQuery.typeFingerprint);if(tfpDist===null){return}if(results.size>=MAX_RESULTS&&tfpDist>results.max_dist){return}if(!unifyFunctionTypes(row.type.inputs,parsedQuery.elems,row.type.where_clause,null,mgens=>{return unifyFunctionTypes(row.type.output,parsedQuery.returned,row.type.where_clause,mgens)})){return}results.max_dist=Math.max(results.max_dist||0,tfpDist);addIntoResults(results,row.id,pos,0,tfpDist,0,Number.MAX_VALUE)}function innerRunQuery(){const queryLen=parsedQuery.elems.reduce((acc,next)=>acc+next.pathLast.length,0)+parsedQuery.returned.reduce((acc,next)=>acc+next.pathLast.length,0);const maxEditDistance=Math.floor(queryLen/3);const genericSymbols=new Map();function convertNameToId(elem,isAssocType){if(typeNameIdMap.has(elem.normalizedPathLast)&&(isAssocType||!typeNameIdMap.get(elem.normalizedPathLast).assocOnly)){elem.id=typeNameIdMap.get(elem.normalizedPathLast).id}else if(!parsedQuery.literalSearch){let match=null;let matchDist=maxEditDistance+1;let matchName="";for(const[name,{id,assocOnly}]of typeNameIdMap){const dist=editDistance(name,elem.normalizedPathLast,maxEditDistance);if(dist<=matchDist&&dist<=maxEditDistance&&(isAssocType||!assocOnly)){if(dist===matchDist&&matchName>name){continue}match=id;matchDist=dist;matchName=name}}if(match!==null){parsedQuery.correction=matchName}elem.id=match}if((elem.id===null&&parsedQuery.totalElems>1&&elem.typeFilter===-1&&elem.generics.length===0&&elem.bindings.size===0)||elem.typeFilter===TY_GENERIC){if(genericSymbols.has(elem.name)){elem.id=genericSymbols.get(elem.name)}else{elem.id=-(genericSymbols.size+1);genericSymbols.set(elem.name,elem.id)}if(elem.typeFilter===-1&&elem.name.length>=3){const maxPartDistance=Math.floor(elem.name.length/3);let matchDist=maxPartDistance+1;let matchName="";for(const name of typeNameIdMap.keys()){const dist=editDistance(name,elem.name,maxPartDistance);if(dist<=matchDist&&dist<=maxPartDistance){if(dist===matchDist&&matchName>name){continue}matchDist=dist;matchName=name}}if(matchName!==""){parsedQuery.proposeCorrectionFrom=elem.name;parsedQuery.proposeCorrectionTo=matchName}}elem.typeFilter=TY_GENERIC}if(elem.generics.length>0&&elem.typeFilter===TY_GENERIC){parsedQuery.error=["Generic type parameter ",elem.name," does not accept generic parameters",]}for(const elem2 of elem.generics){convertNameToId(elem2)}elem.bindings=new Map(Array.from(elem.bindings.entries()).map(entry=>{const[name,constraints]=entry;if(!typeNameIdMap.has(name)){parsedQuery.error=["Type parameter ",name," does not exist",];return[null,[]]}for(const elem2 of constraints){convertNameToId(elem2)}return[typeNameIdMap.get(name).id,constraints]}))}const fps=new Set();for(const elem of parsedQuery.elems){convertNameToId(elem);buildFunctionTypeFingerprint(elem,parsedQuery.typeFingerprint,fps)}for(const elem of parsedQuery.returned){convertNameToId(elem);buildFunctionTypeFingerprint(elem,parsedQuery.typeFingerprint,fps)}if(parsedQuery.foundElems===1&&parsedQuery.returned.length===0){if(parsedQuery.elems.length===1){const elem=parsedQuery.elems[0];for(let i=0,nSearchIndex=searchIndex.length;i0){const sortQ=(a,b)=>{const ag=a.generics.length===0&&a.bindings.size===0;const bg=b.generics.length===0&&b.bindings.size===0;if(ag!==bg){return ag-bg}const ai=a.id>0;const bi=b.id>0;return ai-bi};parsedQuery.elems.sort(sortQ);parsedQuery.returned.sort(sortQ);for(let i=0,nSearchIndex=searchIndex.length;i");if(tmp.endsWith("")){return tmp.slice(0,tmp.length-6)}return tmp}function addTab(array,query,display){const extraClass=display?" active":"";const output=document.createElement("div");if(array.length>0){output.className="search-results "+extraClass;array.forEach(item=>{const name=item.name;const type=itemTypes[item.ty];const longType=longItemTypes[item.ty];const typeName=longType.length!==0?`${longType}`:"?";const link=document.createElement("a");link.className="result-"+type;link.href=item.href;const resultName=document.createElement("div");resultName.className="result-name";resultName.insertAdjacentHTML("beforeend",`${typeName}`);link.appendChild(resultName);let alias=" ";if(item.is_alias){alias=`
\ +${item.alias} - see \ +
`}resultName.insertAdjacentHTML("beforeend",`
${alias}\ +${item.displayPath}${name}\ +
`);const description=document.createElement("div");description.className="desc";description.insertAdjacentHTML("beforeend",item.desc);link.appendChild(description);output.appendChild(link)})}else if(query.error===null){output.className="search-failed"+extraClass;output.innerHTML="No results :(
"+"Try on DuckDuckGo?

"+"Or try looking in one of these:"}return[output,array.length]}function makeTabHeader(tabNb,text,nbElems){const fmtNbElems=nbElems<10?`\u{2007}(${nbElems})\u{2007}\u{2007}`:nbElems<100?`\u{2007}(${nbElems})\u{2007}`:`\u{2007}(${nbElems})`;if(searchState.currentTab===tabNb){return""}return""}function showResults(results,go_to_first,filterCrates){const search=searchState.outputElement();if(go_to_first||(results.others.length===1&&getSettingValue("go-to-only-result")==="true")){window.onunload=()=>{};searchState.removeQueryParameters();const elem=document.createElement("a");elem.href=results.others[0].href;removeClass(elem,"active");document.body.appendChild(elem);elem.click();return}if(results.query===undefined){results.query=parseQuery(searchState.input.value)}currentResults=results.query.userQuery;const ret_others=addTab(results.others,results.query,true);const ret_in_args=addTab(results.in_args,results.query,false);const ret_returned=addTab(results.returned,results.query,false);let currentTab=searchState.currentTab;if((currentTab===0&&ret_others[1]===0)||(currentTab===1&&ret_in_args[1]===0)||(currentTab===2&&ret_returned[1]===0)){if(ret_others[1]!==0){currentTab=0}else if(ret_in_args[1]!==0){currentTab=1}else if(ret_returned[1]!==0){currentTab=2}}let crates="";if(rawSearchIndex.size>1){crates=" in 
"}let output=`

Results${crates}

`;if(results.query.error!==null){const error=results.query.error;error.forEach((value,index)=>{value=value.split("<").join("<").split(">").join(">");if(index%2!==0){error[index]=`${value.replaceAll(" ", " ")}`}else{error[index]=value}});output+=`

Query parser error: "${error.join("")}".

`;output+="
"+makeTabHeader(0,"In Names",ret_others[1])+"
";currentTab=0}else if(results.query.foundElems<=1&&results.query.returned.length===0){output+="
"+makeTabHeader(0,"In Names",ret_others[1])+makeTabHeader(1,"In Parameters",ret_in_args[1])+makeTabHeader(2,"In Return Types",ret_returned[1])+"
"}else{const signatureTabTitle=results.query.elems.length===0?"In Function Return Types":results.query.returned.length===0?"In Function Parameters":"In Function Signatures";output+="
"+makeTabHeader(0,signatureTabTitle,ret_others[1])+"
";currentTab=0}if(results.query.correction!==null){const orig=results.query.returned.length>0?results.query.returned[0].name:results.query.elems[0].name;output+="

"+`Type "${orig}" not found. `+"Showing results for closest type name "+`"${results.query.correction}" instead.

`}if(results.query.proposeCorrectionFrom!==null){const orig=results.query.proposeCorrectionFrom;const targ=results.query.proposeCorrectionTo;output+="

"+`Type "${orig}" not found and used as generic parameter. `+`Consider searching for "${targ}" instead.

`}const resultsElem=document.createElement("div");resultsElem.id="results";resultsElem.appendChild(ret_others[0]);resultsElem.appendChild(ret_in_args[0]);resultsElem.appendChild(ret_returned[0]);search.innerHTML=output;const crateSearch=document.getElementById("crate-search");if(crateSearch){crateSearch.addEventListener("input",updateCrate)}search.appendChild(resultsElem);searchState.showResults(search);const elems=document.getElementById("search-tabs").childNodes;searchState.focusedByTab=[];let i=0;for(const elem of elems){const j=i;elem.onclick=()=>printTab(j);searchState.focusedByTab.push(null);i+=1}printTab(currentTab)}function updateSearchHistory(url){if(!browserSupportsHistoryApi()){return}const params=searchState.getQueryStringParams();if(!history.state&&!params.search){history.pushState(null,"",url)}else{history.replaceState(null,"",url)}}function search(forced){const query=parseQuery(searchState.input.value.trim());let filterCrates=getFilterCrates();if(!forced&&query.userQuery===currentResults){if(query.userQuery.length>0){putBackSearch()}return}searchState.setLoadingSearch();const params=searchState.getQueryStringParams();if(filterCrates===null&¶ms["filter-crate"]!==undefined){filterCrates=params["filter-crate"]}searchState.title="Results for "+query.original+" - Rust";updateSearchHistory(buildUrl(query.original,filterCrates));showResults(execQuery(query,filterCrates,window.currentCrate),params.go_to_first,filterCrates)}function buildItemSearchTypeAll(types,lowercasePaths){return types.length>0?types.map(type=>buildItemSearchType(type,lowercasePaths)):EMPTY_GENERICS_ARRAY}const EMPTY_BINDINGS_MAP=new Map();const EMPTY_GENERICS_ARRAY=[];let TYPES_POOL=new Map();function buildItemSearchType(type,lowercasePaths,isAssocType){const PATH_INDEX_DATA=0;const GENERICS_DATA=1;const BINDINGS_DATA=2;let pathIndex,generics,bindings;if(typeof type==="number"){pathIndex=type;generics=EMPTY_GENERICS_ARRAY;bindings=EMPTY_BINDINGS_MAP}else{pathIndex=type[PATH_INDEX_DATA];generics=buildItemSearchTypeAll(type[GENERICS_DATA],lowercasePaths);if(type.length>BINDINGS_DATA&&type[BINDINGS_DATA].length>0){bindings=new Map(type[BINDINGS_DATA].map(binding=>{const[assocType,constraints]=binding;return[buildItemSearchType(assocType,lowercasePaths,true).id,buildItemSearchTypeAll(constraints,lowercasePaths),]}))}else{bindings=EMPTY_BINDINGS_MAP}}let result;if(pathIndex<0){result={id:pathIndex,ty:TY_GENERIC,path:null,generics,bindings,}}else if(pathIndex===0){result={id:null,ty:null,path:null,generics,bindings,}}else{const item=lowercasePaths[pathIndex-1];result={id:buildTypeMapIndex(item.name,isAssocType),ty:item.ty,path:item.path,generics,bindings,}}const cr=TYPES_POOL.get(result.id);if(cr){if(cr.generics.length===result.generics.length&&cr.generics!==result.generics&&cr.generics.every((x,i)=>result.generics[i]===x)){result.generics=cr.generics}if(cr.bindings.size===result.bindings.size&&cr.bindings!==result.bindings){let ok=true;for(const[k,v]of cr.bindings.entries()){const v2=result.bindings.get(v);if(!v2){ok=false;break}if(v!==v2&&v.length===v2.length&&v.every((x,i)=>v2[i]===x)){result.bindings.set(k,v)}else if(v!==v2){ok=false;break}}if(ok){result.bindings=cr.bindings}}if(cr.ty===result.ty&&cr.path===result.path&&cr.bindings===result.bindings&&cr.generics===result.generics&&cr.ty===result.ty){return cr}}TYPES_POOL.set(result.id,result);return result}function buildFunctionSearchType(itemFunctionDecoder,lowercasePaths){const c=itemFunctionDecoder.string.charCodeAt(itemFunctionDecoder.offset);itemFunctionDecoder.offset+=1;const[zero,ua,la,ob,cb]=["0","@","`","{","}"].map(c=>c.charCodeAt(0));if(c===la){return null}if(c>=zero&&c>1];itemFunctionDecoder.offset+=1;return sign?-value:value}const functionSearchType=decodeList();const INPUTS_DATA=0;const OUTPUT_DATA=1;let inputs,output;if(typeof functionSearchType[INPUTS_DATA]==="number"){inputs=[buildItemSearchType(functionSearchType[INPUTS_DATA],lowercasePaths)]}else{inputs=buildItemSearchTypeAll(functionSearchType[INPUTS_DATA],lowercasePaths)}if(functionSearchType.length>1){if(typeof functionSearchType[OUTPUT_DATA]==="number"){output=[buildItemSearchType(functionSearchType[OUTPUT_DATA],lowercasePaths)]}else{output=buildItemSearchTypeAll(functionSearchType[OUTPUT_DATA],lowercasePaths)}}else{output=[]}const where_clause=[];const l=functionSearchType.length;for(let i=2;i16){itemFunctionDecoder.backrefQueue.pop()}return ret}function buildFunctionTypeFingerprint(type,output,fps){let input=type.id;if(input===typeNameIdOfArray||input===typeNameIdOfSlice){input=typeNameIdOfArrayOrSlice}if(input===typeNameIdOfTuple||input===typeNameIdOfUnit){input=typeNameIdOfTupleOrUnit}const hashint1=k=>{k=(~~k+0x7ed55d16)+(k<<12);k=(k ^ 0xc761c23c)^(k>>>19);k=(~~k+0x165667b1)+(k<<5);k=(~~k+0xd3a2646c)^(k<<9);k=(~~k+0xfd7046c5)+(k<<3);return(k ^ 0xb55a4f09)^(k>>>16)};const hashint2=k=>{k=~k+(k<<15);k ^=k>>>12;k+=k<<2;k ^=k>>>4;k=Math.imul(k,2057);return k ^(k>>16)};if(input!==null){const h0a=hashint1(input);const h0b=hashint2(input);const h1a=~~(h0a+Math.imul(h0b,2));const h1b=~~(h0a+Math.imul(h0b,3));const h2a=~~(h0a+Math.imul(h0b,4));const h2b=~~(h0a+Math.imul(h0b,5));output[0]|=(1<<(h0a%32))|(1<<(h1b%32));output[1]|=(1<<(h1a%32))|(1<<(h2b%32));output[2]|=(1<<(h2a%32))|(1<<(h0b%32));fps.add(input)}for(const g of type.generics){buildFunctionTypeFingerprint(g,output,fps)}const fb={id:null,ty:0,generics:EMPTY_GENERICS_ARRAY,bindings:EMPTY_BINDINGS_MAP,};for(const[k,v]of type.bindings.entries()){fb.id=k;fb.generics=v;buildFunctionTypeFingerprint(fb,output,fps)}output[3]=fps.size}function compareTypeFingerprints(fullId,queryFingerprint){const fh0=functionTypeFingerprint[fullId*4];const fh1=functionTypeFingerprint[(fullId*4)+1];const fh2=functionTypeFingerprint[(fullId*4)+2];const[qh0,qh1,qh2]=queryFingerprint;const[in0,in1,in2]=[fh0&qh0,fh1&qh1,fh2&qh2];if((in0 ^ qh0)||(in1 ^ qh1)||(in2 ^ qh2)){return null}return functionTypeFingerprint[(fullId*4)+3]}function buildIndex(rawSearchIndex){searchIndex=[];typeNameIdMap=new Map();const charA="A".charCodeAt(0);let currentIndex=0;let id=0;typeNameIdOfArray=buildTypeMapIndex("array");typeNameIdOfSlice=buildTypeMapIndex("slice");typeNameIdOfTuple=buildTypeMapIndex("tuple");typeNameIdOfUnit=buildTypeMapIndex("unit");typeNameIdOfArrayOrSlice=buildTypeMapIndex("[]");typeNameIdOfTupleOrUnit=buildTypeMapIndex("()");for(const crate of rawSearchIndex.values()){id+=crate.t.length+1}functionTypeFingerprint=new Uint32Array((id+1)*4);id=0;for(const[crate,crateCorpus]of rawSearchIndex){const crateRow={crate:crate,ty:3,name:crate,path:"",desc:crateCorpus.doc,parent:undefined,type:null,id:id,word:crate,normalizedName:crate.indexOf("_")===-1?crate:crate.replace(/_/g,""),deprecated:null,implDisambiguator:null,};id+=1;searchIndex.push(crateRow);currentIndex+=1;const itemTypes=crateCorpus.t;const itemNames=crateCorpus.n;const itemPaths=new Map(crateCorpus.q);const itemDescs=crateCorpus.d;const itemParentIdxs=crateCorpus.i;const itemFunctionDecoder={string:crateCorpus.f,offset:0,backrefQueue:[],};const deprecatedItems=new Set(crateCorpus.c);const implDisambiguator=new Map(crateCorpus.b);const paths=crateCorpus.p;const aliases=crateCorpus.a;const lowercasePaths=[];let len=paths.length;let lastPath=itemPaths.get(0);for(let i=0;i2){path=itemPaths.has(elem[2])?itemPaths.get(elem[2]):lastPath;lastPath=path}lowercasePaths.push({ty:ty,name:name.toLowerCase(),path:path});paths[i]={ty:ty,name:name,path:path}}lastPath="";len=itemTypes.length;for(let i=0;i0?paths[itemParentIdxs[i]-1]:undefined,type,id:id,word,normalizedName:word.indexOf("_")===-1?word:word.replace(/_/g,""),deprecated:deprecatedItems.has(i),implDisambiguator:implDisambiguator.has(i)?implDisambiguator.get(i):null,};id+=1;searchIndex.push(row);lastPath=row.path}if(aliases){const currentCrateAliases=new Map();ALIASES.set(crate,currentCrateAliases);for(const alias_name in aliases){if(!Object.prototype.hasOwnProperty.call(aliases,alias_name)){continue}let currentNameAliases;if(currentCrateAliases.has(alias_name)){currentNameAliases=currentCrateAliases.get(alias_name)}else{currentNameAliases=[];currentCrateAliases.set(alias_name,currentNameAliases)}for(const local_alias of aliases[alias_name]){currentNameAliases.push(local_alias+currentIndex)}}}currentIndex+=itemTypes.length}TYPES_POOL=new Map()}function onSearchSubmit(e){e.preventDefault();searchState.clearInputTimeout();search()}function putBackSearch(){const search_input=searchState.input;if(!searchState.input){return}if(search_input.value!==""&&!searchState.isDisplayed()){searchState.showResults();if(browserSupportsHistoryApi()){history.replaceState(null,"",buildUrl(search_input.value,getFilterCrates()))}document.title=searchState.title}}function registerSearchEvents(){const params=searchState.getQueryStringParams();if(searchState.input.value===""){searchState.input.value=params.search||""}const searchAfter500ms=()=>{searchState.clearInputTimeout();if(searchState.input.value.length===0){searchState.hideResults()}else{searchState.timeout=setTimeout(search,500)}};searchState.input.onkeyup=searchAfter500ms;searchState.input.oninput=searchAfter500ms;document.getElementsByClassName("search-form")[0].onsubmit=onSearchSubmit;searchState.input.onchange=e=>{if(e.target!==document.activeElement){return}searchState.clearInputTimeout();setTimeout(search,0)};searchState.input.onpaste=searchState.input.onchange;searchState.outputElement().addEventListener("keydown",e=>{if(e.altKey||e.ctrlKey||e.shiftKey||e.metaKey){return}if(e.which===38){const previous=document.activeElement.previousElementSibling;if(previous){previous.focus()}else{searchState.focus()}e.preventDefault()}else if(e.which===40){const next=document.activeElement.nextElementSibling;if(next){next.focus()}const rect=document.activeElement.getBoundingClientRect();if(window.innerHeight-rect.bottom{if(e.which===40){focusSearchResult();e.preventDefault()}});searchState.input.addEventListener("focus",()=>{putBackSearch()});searchState.input.addEventListener("blur",()=>{searchState.input.placeholder=searchState.input.origPlaceholder});if(browserSupportsHistoryApi()){const previousTitle=document.title;window.addEventListener("popstate",e=>{const params=searchState.getQueryStringParams();document.title=previousTitle;currentResults=null;if(params.search&¶ms.search.length>0){searchState.input.value=params.search;e.preventDefault();search()}else{searchState.input.value="";searchState.hideResults()}})}window.onpageshow=()=>{const qSearch=searchState.getQueryStringParams().search;if(searchState.input.value===""&&qSearch){searchState.input.value=qSearch}search()}}function updateCrate(ev){if(ev.target.value==="all crates"){const query=searchState.input.value.trim();updateSearchHistory(buildUrl(query,null))}currentResults=null;search(true)}buildIndex(rawSearchIndex);if(typeof window!=="undefined"){registerSearchEvents();if(window.searchState.getQueryStringParams().search){search()}}if(typeof exports!=="undefined"){exports.initSearch=initSearch;exports.execQuery=execQuery;exports.parseQuery=parseQuery}}if(typeof window!=="undefined"){window.initSearch=initSearch;if(window.searchIndex!==undefined){initSearch(window.searchIndex)}}else{initSearch(new Map())}})() \ No newline at end of file diff --git a/static.files/settings-4313503d2e1961c2.js b/static.files/settings-4313503d2e1961c2.js new file mode 100644 index 00000000..ab425fe4 --- /dev/null +++ b/static.files/settings-4313503d2e1961c2.js @@ -0,0 +1,17 @@ +"use strict";(function(){const isSettingsPage=window.location.pathname.endsWith("/settings.html");function changeSetting(settingName,value){if(settingName==="theme"){const useSystem=value==="system preference"?"true":"false";updateLocalStorage("use-system-theme",useSystem)}updateLocalStorage(settingName,value);switch(settingName){case"theme":case"preferred-dark-theme":case"preferred-light-theme":updateTheme();updateLightAndDark();break;case"line-numbers":if(value===true){window.rustdoc_add_line_numbers_to_examples()}else{window.rustdoc_remove_line_numbers_from_examples()}break;case"hide-sidebar":if(value===true){addClass(document.documentElement,"hide-sidebar")}else{removeClass(document.documentElement,"hide-sidebar")}break}}function showLightAndDark(){removeClass(document.getElementById("preferred-light-theme"),"hidden");removeClass(document.getElementById("preferred-dark-theme"),"hidden")}function hideLightAndDark(){addClass(document.getElementById("preferred-light-theme"),"hidden");addClass(document.getElementById("preferred-dark-theme"),"hidden")}function updateLightAndDark(){const useSystem=getSettingValue("use-system-theme");if(useSystem==="true"||(useSystem===null&&getSettingValue("theme")===null)){showLightAndDark()}else{hideLightAndDark()}}function setEvents(settingsElement){updateLightAndDark();onEachLazy(settingsElement.querySelectorAll("input[type=\"checkbox\"]"),toggle=>{const settingId=toggle.id;const settingValue=getSettingValue(settingId);if(settingValue!==null){toggle.checked=settingValue==="true"}toggle.onchange=()=>{changeSetting(toggle.id,toggle.checked)}});onEachLazy(settingsElement.querySelectorAll("input[type=\"radio\"]"),elem=>{const settingId=elem.name;let settingValue=getSettingValue(settingId);if(settingId==="theme"){const useSystem=getSettingValue("use-system-theme");if(useSystem==="true"||settingValue===null){settingValue=useSystem==="false"?"light":"system preference"}}if(settingValue!==null&&settingValue!=="null"){elem.checked=settingValue===elem.value}elem.addEventListener("change",ev=>{changeSetting(ev.target.name,ev.target.value)})})}function buildSettingsPageSections(settings){let output="";for(const setting of settings){const js_data_name=setting["js_name"];const setting_name=setting["name"];if(setting["options"]!==undefined){output+=`\ +
+
${setting_name}
+
`;onEach(setting["options"],option=>{const checked=option===setting["default"]?" checked":"";const full=`${js_data_name}-${option.replace(/ /g,"-")}`;output+=`\ + `});output+=`\ +
+
`}else{const checked=setting["default"]===true?" checked":"";output+=`\ +
\ + \ +
`}}return output}function buildSettingsPage(){const theme_names=getVar("themes").split(",").filter(t=>t);theme_names.push("light","dark","ayu");const settings=[{"name":"Theme","js_name":"theme","default":"system preference","options":theme_names.concat("system preference"),},{"name":"Preferred light theme","js_name":"preferred-light-theme","default":"light","options":theme_names,},{"name":"Preferred dark theme","js_name":"preferred-dark-theme","default":"dark","options":theme_names,},{"name":"Auto-hide item contents for large items","js_name":"auto-hide-large-items","default":true,},{"name":"Auto-hide item methods' documentation","js_name":"auto-hide-method-docs","default":false,},{"name":"Auto-hide trait implementation documentation","js_name":"auto-hide-trait-implementations","default":false,},{"name":"Directly go to item in search if there is only one result","js_name":"go-to-only-result","default":false,},{"name":"Show line numbers on code examples","js_name":"line-numbers","default":false,},{"name":"Hide persistent navigation bar","js_name":"hide-sidebar","default":false,},{"name":"Disable keyboard shortcuts","js_name":"disable-shortcuts","default":false,},];const elementKind=isSettingsPage?"section":"div";const innerHTML=`
${buildSettingsPageSections(settings)}
`;const el=document.createElement(elementKind);el.id="settings";if(!isSettingsPage){el.className="popover"}el.innerHTML=innerHTML;if(isSettingsPage){document.getElementById(MAIN_ID).appendChild(el)}else{el.setAttribute("tabindex","-1");getSettingsButton().appendChild(el)}return el}const settingsMenu=buildSettingsPage();function displaySettings(){settingsMenu.style.display="";onEachLazy(settingsMenu.querySelectorAll("input[type='checkbox']"),el=>{const val=getSettingValue(el.id);const checked=val==="true";if(checked!==el.checked&&val!==null){el.checked=checked}})}function settingsBlurHandler(event){blurHandler(event,getSettingsButton(),window.hidePopoverMenus)}if(isSettingsPage){getSettingsButton().onclick=event=>{event.preventDefault()}}else{const settingsButton=getSettingsButton();const settingsMenu=document.getElementById("settings");settingsButton.onclick=event=>{if(settingsMenu.contains(event.target)){return}event.preventDefault();const shouldDisplaySettings=settingsMenu.style.display==="none";window.hideAllModals();if(shouldDisplaySettings){displaySettings()}};settingsButton.onblur=settingsBlurHandler;settingsButton.querySelector("a").onblur=settingsBlurHandler;onEachLazy(settingsMenu.querySelectorAll("input"),el=>{el.onblur=settingsBlurHandler});settingsMenu.onblur=settingsBlurHandler}setTimeout(()=>{setEvents(settingsMenu);if(!isSettingsPage){displaySettings()}removeClass(getSettingsButton(),"rotate")},0)})() \ No newline at end of file diff --git a/static.files/src-script-e66d777a5a92e9b2.js b/static.files/src-script-e66d777a5a92e9b2.js new file mode 100644 index 00000000..d0aebb85 --- /dev/null +++ b/static.files/src-script-e66d777a5a92e9b2.js @@ -0,0 +1 @@ +"use strict";(function(){const rootPath=getVar("root-path");const NAME_OFFSET=0;const DIRS_OFFSET=1;const FILES_OFFSET=2;const RUSTDOC_MOBILE_BREAKPOINT=700;function closeSidebarIfMobile(){if(window.innerWidth{removeClass(document.documentElement,"src-sidebar-expanded");updateLocalStorage("source-sidebar-show","false")};window.rustdocShowSourceSidebar=()=>{addClass(document.documentElement,"src-sidebar-expanded");updateLocalStorage("source-sidebar-show","true")};window.rustdocToggleSrcSidebar=()=>{if(document.documentElement.classList.contains("src-sidebar-expanded")){window.rustdocCloseSourceSidebar()}else{window.rustdocShowSourceSidebar()}};function createSrcSidebar(){const container=document.querySelector("nav.sidebar");const sidebar=document.createElement("div");sidebar.id="src-sidebar";let hasFoundFile=false;for(const[key,source]of srcIndex){source[NAME_OFFSET]=key;hasFoundFile=createDirEntry(source,sidebar,"",hasFoundFile)}container.appendChild(sidebar);const selected_elem=sidebar.getElementsByClassName("selected")[0];if(typeof selected_elem!=="undefined"){selected_elem.focus()}}function highlightSrcLines(){const match=window.location.hash.match(/^#?(\d+)(?:-(\d+))?$/);if(!match){return}let from=parseInt(match[1],10);let to=from;if(typeof match[2]!=="undefined"){to=parseInt(match[2],10)}if(to{onEachLazy(e.getElementsByTagName("a"),i_e=>{removeClass(i_e,"line-highlighted")})});for(let i=from;i<=to;++i){elem=document.getElementById(i);if(!elem){break}addClass(elem,"line-highlighted")}}const handleSrcHighlight=(function(){let prev_line_id=0;const set_fragment=name=>{const x=window.scrollX,y=window.scrollY;if(browserSupportsHistoryApi()){history.replaceState(null,null,"#"+name);highlightSrcLines()}else{location.replace("#"+name)}window.scrollTo(x,y)};return ev=>{let cur_line_id=parseInt(ev.target.id,10);if(isNaN(cur_line_id)||ev.ctrlKey||ev.altKey||ev.metaKey){return}ev.preventDefault();if(ev.shiftKey&&prev_line_id){if(prev_line_id>cur_line_id){const tmp=prev_line_id;prev_line_id=cur_line_id;cur_line_id=tmp}set_fragment(prev_line_id+"-"+cur_line_id)}else{prev_line_id=cur_line_id;set_fragment(cur_line_id)}}}());window.addEventListener("hashchange",highlightSrcLines);onEachLazy(document.getElementsByClassName("src-line-numbers"),el=>{el.addEventListener("click",handleSrcHighlight)});highlightSrcLines();window.createSrcSidebar=createSrcSidebar})() \ No newline at end of file diff --git a/static.files/storage-4c98445ec4002617.js b/static.files/storage-4c98445ec4002617.js new file mode 100644 index 00000000..b378b856 --- /dev/null +++ b/static.files/storage-4c98445ec4002617.js @@ -0,0 +1 @@ +"use strict";const builtinThemes=["light","dark","ayu"];const darkThemes=["dark","ayu"];window.currentTheme=document.getElementById("themeStyle");const settingsDataset=(function(){const settingsElement=document.getElementById("default-settings");return settingsElement&&settingsElement.dataset?settingsElement.dataset:null})();function getSettingValue(settingName){const current=getCurrentValue(settingName);if(current===null&&settingsDataset!==null){const def=settingsDataset[settingName.replace(/-/g,"_")];if(def!==undefined){return def}}return current}const localStoredTheme=getSettingValue("theme");function hasClass(elem,className){return elem&&elem.classList&&elem.classList.contains(className)}function addClass(elem,className){if(elem&&elem.classList){elem.classList.add(className)}}function removeClass(elem,className){if(elem&&elem.classList){elem.classList.remove(className)}}function onEach(arr,func){for(const elem of arr){if(func(elem)){return true}}return false}function onEachLazy(lazyArray,func){return onEach(Array.prototype.slice.call(lazyArray),func)}function updateLocalStorage(name,value){try{window.localStorage.setItem("rustdoc-"+name,value)}catch(e){}}function getCurrentValue(name){try{return window.localStorage.getItem("rustdoc-"+name)}catch(e){return null}}const getVar=(function getVar(name){const el=document.querySelector("head > meta[name='rustdoc-vars']");return el?el.attributes["data-"+name].value:null});function switchTheme(newThemeName,saveTheme){const themeNames=getVar("themes").split(",").filter(t=>t);themeNames.push(...builtinThemes);if(themeNames.indexOf(newThemeName)===-1){return}if(saveTheme){updateLocalStorage("theme",newThemeName)}document.documentElement.setAttribute("data-theme",newThemeName);if(builtinThemes.indexOf(newThemeName)!==-1){if(window.currentTheme){window.currentTheme.parentNode.removeChild(window.currentTheme);window.currentTheme=null}}else{const newHref=getVar("root-path")+encodeURIComponent(newThemeName)+getVar("resource-suffix")+".css";if(!window.currentTheme){if(document.readyState==="loading"){document.write(``);window.currentTheme=document.getElementById("themeStyle")}else{window.currentTheme=document.createElement("link");window.currentTheme.rel="stylesheet";window.currentTheme.id="themeStyle";window.currentTheme.href=newHref;document.documentElement.appendChild(window.currentTheme)}}else if(newHref!==window.currentTheme.href){window.currentTheme.href=newHref}}}const updateTheme=(function(){const mql=window.matchMedia("(prefers-color-scheme: dark)");function updateTheme(){if(getSettingValue("use-system-theme")!=="false"){const lightTheme=getSettingValue("preferred-light-theme")||"light";const darkTheme=getSettingValue("preferred-dark-theme")||"dark";updateLocalStorage("use-system-theme","true");switchTheme(mql.matches?darkTheme:lightTheme,true)}else{switchTheme(getSettingValue("theme"),false)}}mql.addEventListener("change",updateTheme);return updateTheme})();if(getSettingValue("use-system-theme")!=="false"&&window.matchMedia){if(getSettingValue("use-system-theme")===null&&getSettingValue("preferred-dark-theme")===null&&darkThemes.indexOf(localStoredTheme)>=0){updateLocalStorage("preferred-dark-theme",localStoredTheme)}}updateTheme();if(getSettingValue("source-sidebar-show")==="true"){addClass(document.documentElement,"src-sidebar-expanded")}if(getSettingValue("hide-sidebar")==="true"){addClass(document.documentElement,"hide-sidebar")}function updateSidebarWidth(){const desktopSidebarWidth=getSettingValue("desktop-sidebar-width");if(desktopSidebarWidth&&desktopSidebarWidth!=="null"){document.documentElement.style.setProperty("--desktop-sidebar-width",desktopSidebarWidth+"px")}const srcSidebarWidth=getSettingValue("src-sidebar-width");if(srcSidebarWidth&&srcSidebarWidth!=="null"){document.documentElement.style.setProperty("--src-sidebar-width",srcSidebarWidth+"px")}}updateSidebarWidth();window.addEventListener("pageshow",ev=>{if(ev.persisted){setTimeout(updateTheme,0);setTimeout(updateSidebarWidth,0)}}) \ No newline at end of file diff --git a/static.files/wheel-7b819b6101059cd0.svg b/static.files/wheel-7b819b6101059cd0.svg new file mode 100644 index 00000000..83c07f63 --- /dev/null +++ b/static.files/wheel-7b819b6101059cd0.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/trait.impl/core/clone/trait.Clone.js b/trait.impl/core/clone/trait.Clone.js new file mode 100644 index 00000000..b8743e27 --- /dev/null +++ b/trait.impl/core/clone/trait.Clone.js @@ -0,0 +1,3 @@ +(function() {var implementors = { +"pubgrub":[["impl<VS: Clone + VersionSet> Clone for Term<VS>"],["impl<P: Clone + Package, VS: Clone + VersionSet> Clone for DerivationTree<P, VS>"],["impl Clone for NumberVersion"],["impl<P: Clone + Package, VS: Clone + VersionSet> Clone for External<P, VS>
where\n VS::V: Clone,
"],["impl<P: Clone + Package, VS: Clone + VersionSet> Clone for Derived<P, VS>"],["impl<P: Clone + Package, VS: Clone + VersionSet> Clone for Dependencies<P, VS>"],["impl<V: Clone> Clone for Range<V>"],["impl Clone for SemanticVersion"],["impl<P: Clone + Package, VS: Clone + VersionSet> Clone for OfflineDependencyProvider<P, VS>
where\n VS::V: Clone,
"]] +};if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/trait.impl/core/cmp/trait.Eq.js b/trait.impl/core/cmp/trait.Eq.js new file mode 100644 index 00000000..1ffe5454 --- /dev/null +++ b/trait.impl/core/cmp/trait.Eq.js @@ -0,0 +1,3 @@ +(function() {var implementors = { +"pubgrub":[["impl<VS: Eq + VersionSet> Eq for Term<VS>"],["impl Eq for VersionParseError"],["impl Eq for SemanticVersion"],["impl Eq for NumberVersion"],["impl<V: Eq> Eq for Range<V>"]] +};if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/trait.impl/core/cmp/trait.Ord.js b/trait.impl/core/cmp/trait.Ord.js new file mode 100644 index 00000000..bb9445b2 --- /dev/null +++ b/trait.impl/core/cmp/trait.Ord.js @@ -0,0 +1,3 @@ +(function() {var implementors = { +"pubgrub":[["impl Ord for NumberVersion"],["impl Ord for SemanticVersion"]] +};if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/trait.impl/core/cmp/trait.PartialEq.js b/trait.impl/core/cmp/trait.PartialEq.js new file mode 100644 index 00000000..7ae580e1 --- /dev/null +++ b/trait.impl/core/cmp/trait.PartialEq.js @@ -0,0 +1,3 @@ +(function() {var implementors = { +"pubgrub":[["impl<VS: PartialEq + VersionSet> PartialEq for Term<VS>"],["impl PartialEq for NumberVersion"],["impl PartialEq for SemanticVersion"],["impl PartialEq for VersionParseError"],["impl<V: PartialEq> PartialEq for Range<V>"]] +};if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/trait.impl/core/cmp/trait.PartialOrd.js b/trait.impl/core/cmp/trait.PartialOrd.js new file mode 100644 index 00000000..0f31daf5 --- /dev/null +++ b/trait.impl/core/cmp/trait.PartialOrd.js @@ -0,0 +1,3 @@ +(function() {var implementors = { +"pubgrub":[["impl PartialOrd for NumberVersion"],["impl PartialOrd for SemanticVersion"]] +};if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/trait.impl/core/convert/trait.AsRef.js b/trait.impl/core/convert/trait.AsRef.js new file mode 100644 index 00000000..11c28495 --- /dev/null +++ b/trait.impl/core/convert/trait.AsRef.js @@ -0,0 +1,3 @@ +(function() {var implementors = { +"pubgrub":[["impl<VS: VersionSet> AsRef<Term<VS>> for Term<VS>"]] +};if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/trait.impl/core/convert/trait.From.js b/trait.impl/core/convert/trait.From.js new file mode 100644 index 00000000..f31bd5d8 --- /dev/null +++ b/trait.impl/core/convert/trait.From.js @@ -0,0 +1,3 @@ +(function() {var implementors = { +"pubgrub":[["impl From<&(u32, u32, u32)> for SemanticVersion"],["impl From<u32> for NumberVersion"],["impl From<&SemanticVersion> for SemanticVersion"],["impl From<&u32> for NumberVersion"],["impl From<&NumberVersion> for NumberVersion"],["impl From<NumberVersion> for u32"],["impl From<(u32, u32, u32)> for SemanticVersion"],["impl From<SemanticVersion> for (u32, u32, u32)"]] +};if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/trait.impl/core/default/trait.Default.js b/trait.impl/core/default/trait.Default.js new file mode 100644 index 00000000..3384424f --- /dev/null +++ b/trait.impl/core/default/trait.Default.js @@ -0,0 +1,3 @@ +(function() {var implementors = { +"pubgrub":[["impl<P: Default + Package, VS: Default + VersionSet> Default for OfflineDependencyProvider<P, VS>
where\n VS::V: Default,
"],["impl Default for DefaultStringReportFormatter"]] +};if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/trait.impl/core/error/trait.Error.js b/trait.impl/core/error/trait.Error.js new file mode 100644 index 00000000..bbfd14e2 --- /dev/null +++ b/trait.impl/core/error/trait.Error.js @@ -0,0 +1,3 @@ +(function() {var implementors = { +"pubgrub":[["impl<P: Package, VS: VersionSet, E> Error for PubGrubError<P, VS, E>
where\n E: Error + 'static,\n Self: Debug + Display,
"],["impl Error for VersionParseError"]] +};if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/trait.impl/core/fmt/trait.Debug.js b/trait.impl/core/fmt/trait.Debug.js new file mode 100644 index 00000000..079e4117 --- /dev/null +++ b/trait.impl/core/fmt/trait.Debug.js @@ -0,0 +1,3 @@ +(function() {var implementors = { +"pubgrub":[["impl Debug for NumberVersion"],["impl Debug for SemanticVersion"],["impl<VS: Debug + VersionSet> Debug for Term<VS>"],["impl Debug for VersionParseError"],["impl<P: Debug + Package, VS: Debug + VersionSet> Debug for External<P, VS>
where\n VS::V: Debug,
"],["impl<P: Debug + Package, VS: Debug + VersionSet> Debug for OfflineDependencyProvider<P, VS>
where\n VS::V: Debug,
"],["impl<P: Debug + Package, VS: Debug + VersionSet> Debug for Derived<P, VS>"],["impl Debug for DefaultStringReportFormatter"],["impl<P: Debug + Package, VS: Debug + VersionSet, E: Debug + Error> Debug for PubGrubError<P, VS, E>
where\n VS::V: Debug,
"],["impl<P: Debug + Package, VS: Debug + VersionSet> Debug for DerivationTree<P, VS>"],["impl<V: Debug> Debug for Range<V>"]] +};if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/trait.impl/core/fmt/trait.Display.js b/trait.impl/core/fmt/trait.Display.js new file mode 100644 index 00000000..2fc7a835 --- /dev/null +++ b/trait.impl/core/fmt/trait.Display.js @@ -0,0 +1,3 @@ +(function() {var implementors = { +"pubgrub":[["impl<VS: VersionSet + Display> Display for Term<VS>"],["impl<V: Display + Eq> Display for Range<V>"],["impl Display for NumberVersion"],["impl<P, VS: VersionSet, E: Error> Display for PubGrubError<P, VS, E>
where\n P: Display + Package,
"],["impl<P: Package, VS: VersionSet> Display for External<P, VS>"],["impl Display for SemanticVersion"],["impl Display for VersionParseError"]] +};if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/trait.impl/core/hash/trait.Hash.js b/trait.impl/core/hash/trait.Hash.js new file mode 100644 index 00000000..cd86c4e9 --- /dev/null +++ b/trait.impl/core/hash/trait.Hash.js @@ -0,0 +1,3 @@ +(function() {var implementors = { +"pubgrub":[["impl<V: Hash> Hash for Range<V>"],["impl Hash for NumberVersion"],["impl Hash for SemanticVersion"]] +};if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/trait.impl/core/marker/trait.Copy.js b/trait.impl/core/marker/trait.Copy.js new file mode 100644 index 00000000..20b04c1d --- /dev/null +++ b/trait.impl/core/marker/trait.Copy.js @@ -0,0 +1,3 @@ +(function() {var implementors = { +"pubgrub":[["impl Copy for SemanticVersion"],["impl Copy for NumberVersion"]] +};if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/trait.impl/core/marker/trait.Freeze.js b/trait.impl/core/marker/trait.Freeze.js new file mode 100644 index 00000000..22e1594a --- /dev/null +++ b/trait.impl/core/marker/trait.Freeze.js @@ -0,0 +1,3 @@ +(function() {var implementors = { +"pubgrub":[["impl<P, VS, E> Freeze for PubGrubError<P, VS, E>
where\n E: Freeze,\n P: Freeze,\n VS: Freeze,\n <VS as VersionSet>::V: Freeze,
",1,["pubgrub::error::PubGrubError"]],["impl<V> Freeze for Range<V>
where\n V: Freeze,
",1,["pubgrub::range::Range"]],["impl<P, VS> Freeze for DerivationTree<P, VS>
where\n P: Freeze,\n VS: Freeze,\n <VS as VersionSet>::V: Freeze,
",1,["pubgrub::report::DerivationTree"]],["impl<P, VS> Freeze for External<P, VS>
where\n P: Freeze,\n VS: Freeze,\n <VS as VersionSet>::V: Freeze,
",1,["pubgrub::report::External"]],["impl<P, VS> Freeze for Derived<P, VS>",1,["pubgrub::report::Derived"]],["impl Freeze for DefaultStringReportFormatter",1,["pubgrub::report::DefaultStringReportFormatter"]],["impl Freeze for DefaultStringReporter",1,["pubgrub::report::DefaultStringReporter"]],["impl<P, VS> Freeze for Dependencies<P, VS>",1,["pubgrub::solver::Dependencies"]],["impl<P, VS> Freeze for OfflineDependencyProvider<P, VS>",1,["pubgrub::solver::OfflineDependencyProvider"]],["impl<VS> Freeze for Term<VS>
where\n VS: Freeze,
",1,["pubgrub::term::Term"]],["impl Freeze for SemanticVersion",1,["pubgrub::version::SemanticVersion"]],["impl Freeze for VersionParseError",1,["pubgrub::version::VersionParseError"]],["impl Freeze for NumberVersion",1,["pubgrub::version::NumberVersion"]]] +};if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/trait.impl/core/marker/trait.Send.js b/trait.impl/core/marker/trait.Send.js new file mode 100644 index 00000000..4273d1e9 --- /dev/null +++ b/trait.impl/core/marker/trait.Send.js @@ -0,0 +1,3 @@ +(function() {var implementors = { +"pubgrub":[["impl<P, VS, E> Send for PubGrubError<P, VS, E>
where\n E: Send,\n P: Sync + Send,\n VS: Sync + Send,\n <VS as VersionSet>::V: Sync + Send,
",1,["pubgrub::error::PubGrubError"]],["impl<V> Send for Range<V>
where\n V: Send,
",1,["pubgrub::range::Range"]],["impl<P, VS> Send for DerivationTree<P, VS>
where\n P: Sync + Send,\n VS: Sync + Send,\n <VS as VersionSet>::V: Sync + Send,
",1,["pubgrub::report::DerivationTree"]],["impl<P, VS> Send for External<P, VS>
where\n P: Send,\n VS: Send,\n <VS as VersionSet>::V: Send,
",1,["pubgrub::report::External"]],["impl<P, VS> Send for Derived<P, VS>
where\n P: Sync + Send,\n VS: Sync + Send,\n <VS as VersionSet>::V: Sync + Send,
",1,["pubgrub::report::Derived"]],["impl Send for DefaultStringReportFormatter",1,["pubgrub::report::DefaultStringReportFormatter"]],["impl Send for DefaultStringReporter",1,["pubgrub::report::DefaultStringReporter"]],["impl<P, VS> Send for Dependencies<P, VS>
where\n P: Send,\n VS: Send,
",1,["pubgrub::solver::Dependencies"]],["impl<P, VS> Send for OfflineDependencyProvider<P, VS>
where\n P: Send,\n VS: Send,\n <VS as VersionSet>::V: Send,
",1,["pubgrub::solver::OfflineDependencyProvider"]],["impl<VS> Send for Term<VS>
where\n VS: Send,
",1,["pubgrub::term::Term"]],["impl Send for SemanticVersion",1,["pubgrub::version::SemanticVersion"]],["impl Send for VersionParseError",1,["pubgrub::version::VersionParseError"]],["impl Send for NumberVersion",1,["pubgrub::version::NumberVersion"]]] +};if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/trait.impl/core/marker/trait.StructuralPartialEq.js b/trait.impl/core/marker/trait.StructuralPartialEq.js new file mode 100644 index 00000000..ade1255f --- /dev/null +++ b/trait.impl/core/marker/trait.StructuralPartialEq.js @@ -0,0 +1,3 @@ +(function() {var implementors = { +"pubgrub":[["impl StructuralPartialEq for SemanticVersion"],["impl<V> StructuralPartialEq for Range<V>"],["impl StructuralPartialEq for VersionParseError"],["impl<VS: VersionSet> StructuralPartialEq for Term<VS>"],["impl StructuralPartialEq for NumberVersion"]] +};if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/trait.impl/core/marker/trait.Sync.js b/trait.impl/core/marker/trait.Sync.js new file mode 100644 index 00000000..9e661e12 --- /dev/null +++ b/trait.impl/core/marker/trait.Sync.js @@ -0,0 +1,3 @@ +(function() {var implementors = { +"pubgrub":[["impl<P, VS, E> Sync for PubGrubError<P, VS, E>
where\n E: Sync,\n P: Sync + Send,\n VS: Sync + Send,\n <VS as VersionSet>::V: Sync + Send,
",1,["pubgrub::error::PubGrubError"]],["impl<V> Sync for Range<V>
where\n V: Sync,
",1,["pubgrub::range::Range"]],["impl<P, VS> Sync for DerivationTree<P, VS>
where\n P: Sync + Send,\n VS: Sync + Send,\n <VS as VersionSet>::V: Sync + Send,
",1,["pubgrub::report::DerivationTree"]],["impl<P, VS> Sync for External<P, VS>
where\n P: Sync,\n VS: Sync,\n <VS as VersionSet>::V: Sync,
",1,["pubgrub::report::External"]],["impl<P, VS> Sync for Derived<P, VS>
where\n P: Sync + Send,\n VS: Sync + Send,\n <VS as VersionSet>::V: Sync + Send,
",1,["pubgrub::report::Derived"]],["impl Sync for DefaultStringReportFormatter",1,["pubgrub::report::DefaultStringReportFormatter"]],["impl Sync for DefaultStringReporter",1,["pubgrub::report::DefaultStringReporter"]],["impl<P, VS> Sync for Dependencies<P, VS>
where\n P: Sync,\n VS: Sync,
",1,["pubgrub::solver::Dependencies"]],["impl<P, VS> Sync for OfflineDependencyProvider<P, VS>
where\n P: Sync,\n VS: Sync,\n <VS as VersionSet>::V: Sync,
",1,["pubgrub::solver::OfflineDependencyProvider"]],["impl<VS> Sync for Term<VS>
where\n VS: Sync,
",1,["pubgrub::term::Term"]],["impl Sync for SemanticVersion",1,["pubgrub::version::SemanticVersion"]],["impl Sync for VersionParseError",1,["pubgrub::version::VersionParseError"]],["impl Sync for NumberVersion",1,["pubgrub::version::NumberVersion"]]] +};if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/trait.impl/core/marker/trait.Unpin.js b/trait.impl/core/marker/trait.Unpin.js new file mode 100644 index 00000000..1a7a11d3 --- /dev/null +++ b/trait.impl/core/marker/trait.Unpin.js @@ -0,0 +1,3 @@ +(function() {var implementors = { +"pubgrub":[["impl<P, VS, E> Unpin for PubGrubError<P, VS, E>
where\n E: Unpin,\n P: Unpin,\n VS: Unpin,\n <VS as VersionSet>::V: Unpin,
",1,["pubgrub::error::PubGrubError"]],["impl<V> Unpin for Range<V>
where\n V: Unpin,
",1,["pubgrub::range::Range"]],["impl<P, VS> Unpin for DerivationTree<P, VS>
where\n P: Unpin,\n VS: Unpin,\n <VS as VersionSet>::V: Unpin,
",1,["pubgrub::report::DerivationTree"]],["impl<P, VS> Unpin for External<P, VS>
where\n P: Unpin,\n VS: Unpin,\n <VS as VersionSet>::V: Unpin,
",1,["pubgrub::report::External"]],["impl<P, VS> Unpin for Derived<P, VS>
where\n P: Unpin,\n VS: Unpin,
",1,["pubgrub::report::Derived"]],["impl Unpin for DefaultStringReportFormatter",1,["pubgrub::report::DefaultStringReportFormatter"]],["impl Unpin for DefaultStringReporter",1,["pubgrub::report::DefaultStringReporter"]],["impl<P, VS> Unpin for Dependencies<P, VS>
where\n P: Unpin,\n VS: Unpin,
",1,["pubgrub::solver::Dependencies"]],["impl<P, VS> Unpin for OfflineDependencyProvider<P, VS>
where\n P: Unpin,
",1,["pubgrub::solver::OfflineDependencyProvider"]],["impl<VS> Unpin for Term<VS>
where\n VS: Unpin,
",1,["pubgrub::term::Term"]],["impl Unpin for SemanticVersion",1,["pubgrub::version::SemanticVersion"]],["impl Unpin for VersionParseError",1,["pubgrub::version::VersionParseError"]],["impl Unpin for NumberVersion",1,["pubgrub::version::NumberVersion"]]] +};if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/trait.impl/core/panic/unwind_safe/trait.RefUnwindSafe.js b/trait.impl/core/panic/unwind_safe/trait.RefUnwindSafe.js new file mode 100644 index 00000000..01dd0ef3 --- /dev/null +++ b/trait.impl/core/panic/unwind_safe/trait.RefUnwindSafe.js @@ -0,0 +1,3 @@ +(function() {var implementors = { +"pubgrub":[["impl<P, VS, E> RefUnwindSafe for PubGrubError<P, VS, E>
where\n E: RefUnwindSafe,\n P: RefUnwindSafe,\n VS: RefUnwindSafe,\n <VS as VersionSet>::V: RefUnwindSafe,
",1,["pubgrub::error::PubGrubError"]],["impl<V> RefUnwindSafe for Range<V>
where\n V: RefUnwindSafe,
",1,["pubgrub::range::Range"]],["impl<P, VS> RefUnwindSafe for DerivationTree<P, VS>
where\n P: RefUnwindSafe,\n VS: RefUnwindSafe,\n <VS as VersionSet>::V: RefUnwindSafe,
",1,["pubgrub::report::DerivationTree"]],["impl<P, VS> RefUnwindSafe for External<P, VS>
where\n P: RefUnwindSafe,\n VS: RefUnwindSafe,\n <VS as VersionSet>::V: RefUnwindSafe,
",1,["pubgrub::report::External"]],["impl<P, VS> RefUnwindSafe for Derived<P, VS>
where\n P: RefUnwindSafe,\n VS: RefUnwindSafe,\n <VS as VersionSet>::V: RefUnwindSafe,
",1,["pubgrub::report::Derived"]],["impl RefUnwindSafe for DefaultStringReportFormatter",1,["pubgrub::report::DefaultStringReportFormatter"]],["impl RefUnwindSafe for DefaultStringReporter",1,["pubgrub::report::DefaultStringReporter"]],["impl<P, VS> RefUnwindSafe for Dependencies<P, VS>
where\n P: RefUnwindSafe,\n VS: RefUnwindSafe,
",1,["pubgrub::solver::Dependencies"]],["impl<P, VS> RefUnwindSafe for OfflineDependencyProvider<P, VS>
where\n P: RefUnwindSafe,\n VS: RefUnwindSafe,\n <VS as VersionSet>::V: RefUnwindSafe,
",1,["pubgrub::solver::OfflineDependencyProvider"]],["impl<VS> RefUnwindSafe for Term<VS>
where\n VS: RefUnwindSafe,
",1,["pubgrub::term::Term"]],["impl RefUnwindSafe for SemanticVersion",1,["pubgrub::version::SemanticVersion"]],["impl RefUnwindSafe for VersionParseError",1,["pubgrub::version::VersionParseError"]],["impl RefUnwindSafe for NumberVersion",1,["pubgrub::version::NumberVersion"]]] +};if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/trait.impl/core/panic/unwind_safe/trait.UnwindSafe.js b/trait.impl/core/panic/unwind_safe/trait.UnwindSafe.js new file mode 100644 index 00000000..61f1187f --- /dev/null +++ b/trait.impl/core/panic/unwind_safe/trait.UnwindSafe.js @@ -0,0 +1,3 @@ +(function() {var implementors = { +"pubgrub":[["impl<P, VS, E> UnwindSafe for PubGrubError<P, VS, E>",1,["pubgrub::error::PubGrubError"]],["impl<V> UnwindSafe for Range<V>
where\n V: UnwindSafe,
",1,["pubgrub::range::Range"]],["impl<P, VS> UnwindSafe for DerivationTree<P, VS>",1,["pubgrub::report::DerivationTree"]],["impl<P, VS> UnwindSafe for External<P, VS>
where\n P: UnwindSafe,\n VS: UnwindSafe,\n <VS as VersionSet>::V: UnwindSafe,
",1,["pubgrub::report::External"]],["impl<P, VS> UnwindSafe for Derived<P, VS>",1,["pubgrub::report::Derived"]],["impl UnwindSafe for DefaultStringReportFormatter",1,["pubgrub::report::DefaultStringReportFormatter"]],["impl UnwindSafe for DefaultStringReporter",1,["pubgrub::report::DefaultStringReporter"]],["impl<P, VS> UnwindSafe for Dependencies<P, VS>
where\n P: UnwindSafe,\n VS: UnwindSafe,
",1,["pubgrub::solver::Dependencies"]],["impl<P, VS> UnwindSafe for OfflineDependencyProvider<P, VS>",1,["pubgrub::solver::OfflineDependencyProvider"]],["impl<VS> UnwindSafe for Term<VS>
where\n VS: UnwindSafe,
",1,["pubgrub::term::Term"]],["impl UnwindSafe for SemanticVersion",1,["pubgrub::version::SemanticVersion"]],["impl UnwindSafe for VersionParseError",1,["pubgrub::version::VersionParseError"]],["impl UnwindSafe for NumberVersion",1,["pubgrub::version::NumberVersion"]]] +};if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/trait.impl/core/str/traits/trait.FromStr.js b/trait.impl/core/str/traits/trait.FromStr.js new file mode 100644 index 00000000..4443b93f --- /dev/null +++ b/trait.impl/core/str/traits/trait.FromStr.js @@ -0,0 +1,3 @@ +(function() {var implementors = { +"pubgrub":[["impl FromStr for SemanticVersion"]] +};if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/trait.impl/pubgrub/package/trait.Package.js b/trait.impl/pubgrub/package/trait.Package.js new file mode 100644 index 00000000..c9eaa632 --- /dev/null +++ b/trait.impl/pubgrub/package/trait.Package.js @@ -0,0 +1,3 @@ +(function() {var implementors = { +"pubgrub":[] +};if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/trait.impl/pubgrub/report/trait.ReportFormatter.js b/trait.impl/pubgrub/report/trait.ReportFormatter.js new file mode 100644 index 00000000..c9eaa632 --- /dev/null +++ b/trait.impl/pubgrub/report/trait.ReportFormatter.js @@ -0,0 +1,3 @@ +(function() {var implementors = { +"pubgrub":[] +};if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/trait.impl/pubgrub/report/trait.Reporter.js b/trait.impl/pubgrub/report/trait.Reporter.js new file mode 100644 index 00000000..c9eaa632 --- /dev/null +++ b/trait.impl/pubgrub/report/trait.Reporter.js @@ -0,0 +1,3 @@ +(function() {var implementors = { +"pubgrub":[] +};if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/trait.impl/pubgrub/solver/trait.DependencyProvider.js b/trait.impl/pubgrub/solver/trait.DependencyProvider.js new file mode 100644 index 00000000..c9eaa632 --- /dev/null +++ b/trait.impl/pubgrub/solver/trait.DependencyProvider.js @@ -0,0 +1,3 @@ +(function() {var implementors = { +"pubgrub":[] +};if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/trait.impl/pubgrub/version/trait.Version.js b/trait.impl/pubgrub/version/trait.Version.js new file mode 100644 index 00000000..c9eaa632 --- /dev/null +++ b/trait.impl/pubgrub/version/trait.Version.js @@ -0,0 +1,3 @@ +(function() {var implementors = { +"pubgrub":[] +};if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/trait.impl/pubgrub/version_set/trait.VersionSet.js b/trait.impl/pubgrub/version_set/trait.VersionSet.js new file mode 100644 index 00000000..c9eaa632 --- /dev/null +++ b/trait.impl/pubgrub/version_set/trait.VersionSet.js @@ -0,0 +1,3 @@ +(function() {var implementors = { +"pubgrub":[] +};if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/type.impl/pubgrub/type_aliases/type.Map.js b/type.impl/pubgrub/type_aliases/type.Map.js new file mode 100644 index 00000000..536bb091 --- /dev/null +++ b/type.impl/pubgrub/type_aliases/type.Map.js @@ -0,0 +1,3 @@ +(function() {var type_impls = { +"pubgrub":[] +};if (window.register_type_impls) {window.register_type_impls(type_impls);} else {window.pending_type_impls = type_impls;}})() \ No newline at end of file diff --git a/type.impl/rustc_hash/type.FxHashMap.js b/type.impl/rustc_hash/type.FxHashMap.js new file mode 100644 index 00000000..536bb091 --- /dev/null +++ b/type.impl/rustc_hash/type.FxHashMap.js @@ -0,0 +1,3 @@ +(function() {var type_impls = { +"pubgrub":[] +};if (window.register_type_impls) {window.register_type_impls(type_impls);} else {window.pending_type_impls = type_impls;}})() \ No newline at end of file diff --git a/type.impl/rustc_hash/type.FxHashSet.js b/type.impl/rustc_hash/type.FxHashSet.js new file mode 100644 index 00000000..536bb091 --- /dev/null +++ b/type.impl/rustc_hash/type.FxHashSet.js @@ -0,0 +1,3 @@ +(function() {var type_impls = { +"pubgrub":[] +};if (window.register_type_impls) {window.register_type_impls(type_impls);} else {window.pending_type_impls = type_impls;}})() \ No newline at end of file