summaryrefslogtreecommitdiffstats
path: root/third_party/rust/topological-sort
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:22:09 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:22:09 +0000
commit43a97878ce14b72f0981164f87f2e35e14151312 (patch)
tree620249daf56c0258faa40cbdcf9cfba06de2a846 /third_party/rust/topological-sort
parentInitial commit. (diff)
downloadfirefox-upstream.tar.xz
firefox-upstream.zip
Adding upstream version 110.0.1.upstream/110.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/topological-sort')
-rw-r--r--third_party/rust/topological-sort/.cargo-checksum.json1
-rw-r--r--third_party/rust/topological-sort/Cargo.toml21
-rw-r--r--third_party/rust/topological-sort/LICENSE-APACHE202
-rw-r--r--third_party/rust/topological-sort/LICENSE-MIT19
-rw-r--r--third_party/rust/topological-sort/README.md40
-rw-r--r--third_party/rust/topological-sort/rustfmt.toml2
-rw-r--r--third_party/rust/topological-sort/src/lib.rs384
7 files changed, 669 insertions, 0 deletions
diff --git a/third_party/rust/topological-sort/.cargo-checksum.json b/third_party/rust/topological-sort/.cargo-checksum.json
new file mode 100644
index 0000000000..705676c229
--- /dev/null
+++ b/third_party/rust/topological-sort/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{"Cargo.toml":"b4bfbe31191f3e86445d277cf036bc7b2318baf853e8b2b0c7fcca5d61f7a089","LICENSE-APACHE":"c6596eb7be8581c18be736c846fb9173b69eccf6ef94c5135893ec56bd92ba08","LICENSE-MIT":"bf04ecfb8f9aec247301556319593dd528886f67bb9ad81654025d12b20d9e01","README.md":"fb45c72e0317c713589e90b028324c0b7320b6eb7aebbbefd31ade38aaf7e1e2","rustfmt.toml":"785022765c76126d4a9954f880c30cc651b3895857ffcfed55ce8a4f8cf3f61a","src/lib.rs":"aaa8b5ff915f1c6e3132bef12afacede4fc91216fe0711efbd1ead7ab106e82e"},"package":"aa7c7f42dea4b1b99439786f5633aeb9c14c1b53f75e282803c2ec2ad545873c"} \ No newline at end of file
diff --git a/third_party/rust/topological-sort/Cargo.toml b/third_party/rust/topological-sort/Cargo.toml
new file mode 100644
index 0000000000..1526eb8c66
--- /dev/null
+++ b/third_party/rust/topological-sort/Cargo.toml
@@ -0,0 +1,21 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g. crates.io) dependencies
+#
+# If you believe there's an error in this file please file an
+# issue against the rust-lang/cargo repository. If you're
+# editing this file be aware that the upstream Cargo.toml
+# will likely look very different (and much more reasonable)
+
+[package]
+name = "topological-sort"
+version = "0.1.0"
+authors = ["gifnksm <makoto.nksm+github@gmail.com>"]
+description = "Performs topological sorting."
+documentation = "https://docs.rs/topological-sort/~0.0"
+readme = "README.md"
+license = "MIT OR Apache-2.0"
+repository = "https://github.com/gifnksm/topological-sort-rs"
diff --git a/third_party/rust/topological-sort/LICENSE-APACHE b/third_party/rust/topological-sort/LICENSE-APACHE
new file mode 100644
index 0000000000..8f71f43fee
--- /dev/null
+++ b/third_party/rust/topological-sort/LICENSE-APACHE
@@ -0,0 +1,202 @@
+ 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/third_party/rust/topological-sort/LICENSE-MIT b/third_party/rust/topological-sort/LICENSE-MIT
new file mode 100644
index 0000000000..672d559c7b
--- /dev/null
+++ b/third_party/rust/topological-sort/LICENSE-MIT
@@ -0,0 +1,19 @@
+Copyright (c) 2015 The topological-sort-rs Developers
+
+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/third_party/rust/topological-sort/README.md b/third_party/rust/topological-sort/README.md
new file mode 100644
index 0000000000..87dd7bea59
--- /dev/null
+++ b/third_party/rust/topological-sort/README.md
@@ -0,0 +1,40 @@
+# topological-sort-rs
+
+[![Build Status](https://travis-ci.org/gifnksm/topological-sort-rs.svg)](https://travis-ci.org/gifnksm/topological-sort-rs)
+[![Coverage Status](https://coveralls.io/repos/gifnksm/topological-sort-rs/badge.svg?branch=master&service=github)](https://coveralls.io/github/gifnksm/topological-sort-rs?branch=master)
+[![crates.io](http://meritbadge.herokuapp.com/topological-sort)](https://crates.io/crates/topological-sort)
+
+Performs topological sorting.
+
+[Documentation](https://docs.rs/topological-sort/~0.0)
+
+## How to use?
+
+Add this to your `Cargo.toml`:
+
+```toml
+[dependencies]
+topological-sort = "0.0"
+```
+
+and this to your crate root:
+
+```rust
+extern crate topological_sort;
+```
+
+## License
+
+Licensed under either of
+
+ * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
+ * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
+
+at your option.
+
+### Contribution
+
+Unless you explicitly state otherwise, any contribution intentionally
+submitted for inclusion in the work by you, as defined in the Apache-2.0
+license, shall be dual licensed as above, without any additional terms or
+conditions.
diff --git a/third_party/rust/topological-sort/rustfmt.toml b/third_party/rust/topological-sort/rustfmt.toml
new file mode 100644
index 0000000000..0468aa5872
--- /dev/null
+++ b/third_party/rust/topological-sort/rustfmt.toml
@@ -0,0 +1,2 @@
+reorder_imports = true
+reorder_imported_names = true
diff --git a/third_party/rust/topological-sort/src/lib.rs b/third_party/rust/topological-sort/src/lib.rs
new file mode 100644
index 0000000000..08b04aab15
--- /dev/null
+++ b/third_party/rust/topological-sort/src/lib.rs
@@ -0,0 +1,384 @@
+// Copyright 2016 oauth-client-rs Developers
+//
+// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
+// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
+// http://opensource.org/licenses/MIT>, at your option. This file may not be
+// copied, modified, or distributed except according to those terms.
+
+//! Performs topological sorting.
+
+#![warn(bad_style)]
+#![warn(missing_copy_implementations)]
+#![warn(missing_debug_implementations)]
+#![warn(missing_docs)]
+#![warn(trivial_casts)]
+#![warn(trivial_numeric_casts)]
+#![warn(unused)]
+#![warn(unused_extern_crates)]
+#![warn(unused_import_braces)]
+#![warn(unused_qualifications)]
+#![warn(unused_results)]
+#![cfg_attr(feature = "cargo-clippy", warn(if_not_else))]
+#![cfg_attr(feature = "cargo-clippy", warn(invalid_upcast_comparisons))]
+#![cfg_attr(feature = "cargo-clippy", warn(items_after_statements))]
+#![cfg_attr(feature = "cargo-clippy", warn(mut_mut))]
+#![cfg_attr(feature = "cargo-clippy", warn(never_loop))]
+#![cfg_attr(feature = "cargo-clippy", warn(nonminimal_bool))]
+#![cfg_attr(feature = "cargo-clippy", warn(option_map_unwrap_or))]
+#![cfg_attr(feature = "cargo-clippy", warn(option_map_unwrap_or_else))]
+#![cfg_attr(feature = "cargo-clippy", warn(option_unwrap_used))]
+#![cfg_attr(feature = "cargo-clippy", warn(result_unwrap_used))]
+#![cfg_attr(feature = "cargo-clippy", warn(used_underscore_binding))]
+
+use std::cmp::Ordering;
+use std::collections::{HashMap, HashSet};
+use std::collections::hash_map::Entry;
+use std::fmt;
+use std::hash::Hash;
+use std::iter::FromIterator;
+
+#[derive(Clone)]
+struct Dependency<T> {
+ num_prec: usize,
+ succ: HashSet<T>,
+}
+
+impl<T: Hash + Eq> Dependency<T> {
+ fn new() -> Dependency<T> {
+ Dependency {
+ num_prec: 0,
+ succ: HashSet::new(),
+ }
+ }
+}
+
+
+
+/// Performs topological sorting.
+#[derive(Clone)]
+pub struct TopologicalSort<T> {
+ top: HashMap<T, Dependency<T>>,
+}
+
+impl<T: Hash + Eq + Clone> TopologicalSort<T> {
+ /// Creates new empty `TopologicalSort`.
+ ///
+ /// ```rust
+ /// # extern crate topological_sort;
+ /// # fn main() {
+ /// use topological_sort::TopologicalSort;
+ /// let mut ts = TopologicalSort::<&str>::new();
+ /// ts.add_dependency("hello_world.o", "hello_world");
+ /// ts.add_dependency("hello_world.c", "hello_world");
+ /// ts.add_dependency("stdio.h", "hello_world.o");
+ /// ts.add_dependency("glibc.so", "hello_world");
+ /// assert_eq!(vec!["glibc.so", "hello_world.c", "stdio.h"],
+ /// { let mut v = ts.pop_all(); v.sort(); v });
+ /// assert_eq!(vec!["hello_world.o"],
+ /// { let mut v = ts.pop_all(); v.sort(); v });
+ /// assert_eq!(vec!["hello_world"],
+ /// { let mut v = ts.pop_all(); v.sort(); v });
+ /// assert!(ts.pop_all().is_empty());
+ /// # }
+ /// ```
+ #[inline]
+ pub fn new() -> TopologicalSort<T> {
+ TopologicalSort {
+ top: HashMap::new(),
+ }
+ }
+
+ /// Returns the number of elements in the `TopologicalSort`.
+ #[inline]
+ pub fn len(&self) -> usize {
+ self.top.len()
+ }
+
+ /// Returns true if the `TopologicalSort` contains no elements.
+ #[inline]
+ pub fn is_empty(&self) -> bool {
+ self.top.is_empty()
+ }
+
+ /// Registers the two elements' dependency.
+ ///
+ /// # Arguments
+ ///
+ /// * `prec` - The element appears before `succ`. `prec` is depended on by `succ`.
+ /// * `succ` - The element appears after `prec`. `succ` depends on `prec`.
+ pub fn add_dependency<P, S>(&mut self, prec: P, succ: S)
+ where
+ P: Into<T>,
+ S: Into<T>,
+ {
+ self.add_dependency_impl(prec.into(), succ.into())
+ }
+
+ fn add_dependency_impl(&mut self, prec: T, succ: T) {
+ match self.top.entry(prec) {
+ Entry::Vacant(e) => {
+ let mut dep = Dependency::new();
+ let _ = dep.succ.insert(succ.clone());
+ let _ = e.insert(dep);
+ }
+ Entry::Occupied(e) => {
+ if !e.into_mut().succ.insert(succ.clone()) {
+ // Already registered
+ return;
+ }
+ }
+ }
+
+ match self.top.entry(succ) {
+ Entry::Vacant(e) => {
+ let mut dep = Dependency::new();
+ dep.num_prec += 1;
+ let _ = e.insert(dep);
+ }
+ Entry::Occupied(e) => {
+ e.into_mut().num_prec += 1;
+ }
+ }
+ }
+
+ /// Registers a dependency link.
+ pub fn add_link(&mut self, link: DependencyLink<T>) {
+ self.add_dependency(link.prec, link.succ)
+ }
+
+ /// Inserts an element, without adding any dependencies from or to it.
+ ///
+ /// If the `TopologicalSort` did not have this element present, `true` is returned.
+ ///
+ /// If the `TopologicalSort` already had this element present, `false` is returned.
+ pub fn insert<U>(&mut self, elt: U) -> bool
+ where
+ U: Into<T>,
+ {
+ match self.top.entry(elt.into()) {
+ Entry::Vacant(e) => {
+ let dep = Dependency::new();
+ let _ = e.insert(dep);
+ true
+ }
+ Entry::Occupied(_) => false,
+ }
+ }
+
+ /// Removes the item that is not depended on by any other items and returns it, or `None` if
+ /// there is no such item.
+ ///
+ /// If `pop` returns `None` and `len` is not 0, there is cyclic dependencies.
+ pub fn pop(&mut self) -> Option<T> {
+ self.peek().map(T::clone).map(|key| {
+ let _ = self.remove(&key);
+ key
+ })
+ }
+
+
+ /// Removes all items that are not depended on by any other items and returns it, or empty
+ /// vector if there are no such items.
+ ///
+ /// If `pop_all` returns an empty vector and `len` is not 0, there is cyclic dependencies.
+ pub fn pop_all(&mut self) -> Vec<T> {
+ let keys = self.top
+ .iter()
+ .filter(|&(_, v)| v.num_prec == 0)
+ .map(|(k, _)| k.clone())
+ .collect::<Vec<_>>();
+ for k in &keys {
+ let _ = self.remove(k);
+ }
+ keys
+ }
+
+ /// Return a reference to the first item that does not depend on any other items, or `None` if
+ /// there is no such item.
+ pub fn peek(&self) -> Option<&T> {
+ self.top
+ .iter()
+ .filter(|&(_, v)| v.num_prec == 0)
+ .map(|(k, _)| k)
+ .next()
+ }
+
+ /// Return a vector of references to all items that do not depend on any other items, or an
+ /// empty vector if there are no such items.
+ pub fn peek_all(&self) -> Vec<&T> {
+ self.top
+ .iter()
+ .filter(|&(_, v)| v.num_prec == 0)
+ .map(|(k, _)| k)
+ .collect::<Vec<_>>()
+ }
+
+
+ fn remove(&mut self, prec: &T) -> Option<Dependency<T>> {
+ let result = self.top.remove(prec);
+ if let Some(ref p) = result {
+ for s in &p.succ {
+ if let Some(y) = self.top.get_mut(s) {
+ y.num_prec -= 1;
+ }
+ }
+ }
+ result
+ }
+}
+
+impl<T: PartialOrd + Eq + Hash + Clone> FromIterator<T> for TopologicalSort<T> {
+ fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> TopologicalSort<T> {
+ let mut top = TopologicalSort::new();
+ let mut seen = Vec::<T>::default();
+ for item in iter {
+ let _ = top.insert(item.clone());
+ for seen_item in seen.iter().cloned() {
+ match seen_item.partial_cmp(&item) {
+ Some(Ordering::Less) => {
+ top.add_dependency(seen_item, item.clone());
+ }
+ Some(Ordering::Greater) => {
+ top.add_dependency(item.clone(), seen_item);
+ }
+ _ => (),
+ }
+ }
+ seen.push(item);
+ }
+ top
+ }
+}
+
+/// A link between two items in a sort.
+#[derive(Copy, Clone, Debug)]
+pub struct DependencyLink<T> {
+ /// The element which is depened upon by `succ`.
+ pub prec: T,
+ /// The element which depends on `prec`.
+ pub succ: T,
+}
+
+impl<T> From<(T, T)> for DependencyLink<T> {
+ fn from(tuple: (T, T)) -> Self {
+ DependencyLink {
+ succ: tuple.0,
+ prec: tuple.1,
+ }
+ }
+}
+
+impl<T: Eq + Hash + Clone> FromIterator<DependencyLink<T>> for TopologicalSort<T> {
+ fn from_iter<I: IntoIterator<Item = DependencyLink<T>>>(iter: I) -> TopologicalSort<T> {
+ let mut top = TopologicalSort::new();
+ for link in iter {
+ top.add_link(link);
+ }
+ top
+ }
+}
+
+impl<T: Hash + Eq + Clone> Iterator for TopologicalSort<T> {
+ type Item = T;
+
+ fn next(&mut self) -> Option<T> {
+ self.pop()
+ }
+}
+
+impl<T: fmt::Debug + Hash + Eq> fmt::Debug for Dependency<T> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "prec={}, succ={:?}", self.num_prec, self.succ)
+ }
+}
+
+impl<T: fmt::Debug + Hash + Eq + Clone> fmt::Debug for TopologicalSort<T> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "{:?}", self.top)
+ }
+}
+
+
+#[cfg(test)]
+mod test {
+ use super::TopologicalSort;
+ use std::iter::FromIterator;
+
+ #[test]
+ fn from_iter() {
+ let t = vec![4, 3, 3, 5, 7, 6, 8];
+ let mut ts = TopologicalSort::<i32>::from_iter(t);
+ assert_eq!(Some(3), ts.next());
+ assert_eq!(Some(4), ts.next());
+ assert_eq!(Some(5), ts.next());
+ assert_eq!(Some(6), ts.next());
+ assert_eq!(Some(7), ts.next());
+ assert_eq!(Some(8), ts.next());
+ assert_eq!(None, ts.next());
+ }
+
+ #[test]
+ fn iter() {
+ let mut ts = TopologicalSort::<i32>::new();
+ ts.add_dependency(1, 2);
+ ts.add_dependency(2, 3);
+ ts.add_dependency(3, 4);
+ assert_eq!(Some(1), ts.next());
+ assert_eq!(Some(2), ts.next());
+ assert_eq!(Some(3), ts.next());
+ assert_eq!(Some(4), ts.next());
+ assert_eq!(None, ts.next());
+ }
+
+ #[test]
+ fn pop_all() {
+ fn check(result: &[i32], ts: &mut TopologicalSort<i32>) {
+ let l = ts.len();
+ let mut v = ts.pop_all();
+ v.sort();
+ assert_eq!(result, &v[..]);
+ assert_eq!(l - result.len(), ts.len());
+ }
+
+ let mut ts = TopologicalSort::new();
+ ts.add_dependency(7, 11);
+ assert_eq!(2, ts.len());
+ ts.add_dependency(7, 8);
+ assert_eq!(3, ts.len());
+ ts.add_dependency(5, 11);
+ assert_eq!(4, ts.len());
+ ts.add_dependency(3, 8);
+ assert_eq!(5, ts.len());
+ ts.add_dependency(3, 10);
+ assert_eq!(6, ts.len());
+ ts.add_dependency(11, 2);
+ assert_eq!(7, ts.len());
+ ts.add_dependency(11, 9);
+ assert_eq!(8, ts.len());
+ ts.add_dependency(11, 10);
+ assert_eq!(8, ts.len());
+ ts.add_dependency(8, 9);
+ assert_eq!(8, ts.len());
+
+ check(&[3, 5, 7], &mut ts);
+ check(&[8, 11], &mut ts);
+ check(&[2, 9, 10], &mut ts);
+ check(&[], &mut ts);
+ }
+
+ #[test]
+ fn cyclic_deadlock() {
+ let mut ts = TopologicalSort::new();
+ ts.add_dependency("stone", "sharp");
+
+ ts.add_dependency("bucket", "hole");
+ ts.add_dependency("hole", "straw");
+ ts.add_dependency("straw", "axe");
+ ts.add_dependency("axe", "sharp");
+ ts.add_dependency("sharp", "water");
+ ts.add_dependency("water", "bucket");
+ assert_eq!(ts.pop(), Some("stone"));
+ assert!(ts.pop().is_none());
+ println!("{:?}", ts);
+ }
+}