fera_graph/ext.rs
1// This Source Code Form is subject to the terms of the Mozilla Public
2// License, v. 2.0. If a copy of the MPL was not distributed with this
3// file, You can obtain one at http://mozilla.org/MPL/2.0/.
4
5//! Extension traits for std types.
6//!
7//! The traits is this module are included in the [prelude].
8//!
9//! # Examples
10//!
11//! ```
12//! extern crate fera_fun;
13//! extern crate fera_graph;
14//!
15//! use fera_graph::prelude::*;
16//! use fera_fun::vec;
17//!
18//! # fn main() {
19//! let g = CompleteGraph::new(4);
20//! let mut w = g.default_vertex_prop(0);
21//! w[0] = 1;
22//! w[1] = 2;
23//! w[2] = 3;
24//! w[3] = 0;
25//!
26//! let mut vertices = vec(g.vertices());
27//! assert!(!vertices.is_sorted_by_prop(&w));
28//!
29//! vertices.sort_by_prop(&w);
30//! assert!(vertices.is_sorted_by_prop(&w));
31//! assert_eq!(vec![3, 0, 1, 2], vertices);
32//!
33//! // returns the index of the vertex with w = 2,
34//! // that is, the index of vertex 1
35//! assert_eq!(Ok(2), vertices.binary_search_by_prop(&2, &w));
36//!
37//! // returns the index that a vertex with w = 5
38//! // could be inserted while maintaining sorted order
39//! assert_eq!(Err(4), vertices.binary_search_by_prop(&5, &w));
40//! # }
41//! ```
42//!
43//! [prelude]: ../prelude/index.html
44
45use params::IntoOwned;
46use prelude::*;
47
48/// Extension trait for slices.
49///
50/// See the [module documentation] for examples.
51///
52/// [module documentation]: index.html
53pub trait GraphsSliceExt<T> {
54 /// Returns `true` if a slice is sorted according to a [property], otherwise, returns `false`.
55 ///
56 /// [property]: ../props/index.html
57 fn is_sorted_by_prop<P, K>(&self, prop: P) -> bool
58 where
59 P: PropGet<K>,
60 for<'a> &'a T: IntoOwned<K>,
61 P::Output: Ord;
62
63 /// Sort a slice using a [property].
64 ///
65 /// This functions calls [`slice::sort_by_key`].
66 ///
67 /// [property]: ../props/index.html
68 /// [`slice::sort_by_key`]:
69 /// https://doc.rust-lang.org/stable/std/primitive.slice.html#method.sort_by_key
70 fn sort_by_prop<P, K>(&mut self, prop: P)
71 where
72 P: PropGet<K>,
73 for<'a> &'a T: IntoOwned<K>,
74 P::Output: Ord;
75
76 /// Sort a slice using a [property].
77 ///
78 /// This functions calls [`slice::sort_unstable_by_key`].
79 ///
80 /// [property]: ../props/index.html
81 /// [`slice::sort_unstable_by_key`]:
82 /// https://doc.rust-lang.org/stable/std/primitive.slice.html#method.sort_unstable_by_key
83 fn sort_unstable_by_prop<P, K>(&mut self, prop: P)
84 where
85 P: PropGet<K>,
86 for<'a> &'a T: IntoOwned<K>,
87 P::Output: Ord;
88
89 /// Binary searches a slice that is sorted by a [property].
90 ///
91 /// This functions calls [`slice::binary_search_by_key`].
92 ///
93 /// [property]: ../props/index.html
94 /// [`slice::binary_search_by_key`]:
95 /// https://doc.rust-lang.org/stable/std/primitive.slice.html#method.binary_search_by_key
96 fn binary_search_by_prop<P, K>(&self, prop_value: &P::Output, prop: P) -> Result<usize, usize>
97 where
98 P: PropGet<K>,
99 for<'a> &'a T: IntoOwned<K>,
100 P::Output: Ord;
101}
102
103impl<T> GraphsSliceExt<T> for [T] {
104 fn is_sorted_by_prop<P, K>(&self, prop: P) -> bool
105 where
106 P: PropGet<K>,
107 for<'a> &'a T: IntoOwned<K>,
108 P::Output: Ord,
109 {
110 let mut iter = self.iter();
111 if let Some(item) = iter.next() {
112 let mut p = prop.get(item.into_owned());
113 for item in iter {
114 let q = prop.get(item.into_owned());
115 if p > q {
116 return false;
117 }
118 p = q;
119 }
120 }
121 true
122 }
123
124 #[inline]
125 fn sort_by_prop<P, K>(&mut self, prop: P)
126 where
127 P: PropGet<K>,
128 for<'a> &'a T: IntoOwned<K>,
129 P::Output: Ord,
130 {
131 self.sort_by_key(|item| prop.get(item.into_owned()))
132 }
133
134 #[inline]
135 fn sort_unstable_by_prop<P, K>(&mut self, prop: P)
136 where
137 P: PropGet<K>,
138 for<'a> &'a T: IntoOwned<K>,
139 P::Output: Ord,
140 {
141 self.sort_unstable_by_key(|item| prop.get(item.into_owned()))
142 }
143
144 #[inline]
145 fn binary_search_by_prop<P, K>(&self, prop_value: &P::Output, prop: P) -> Result<usize, usize>
146 where
147 P: PropGet<K>,
148 for<'a> &'a T: IntoOwned<K>,
149 P::Output: Ord,
150 {
151 self.binary_search_by_key(prop_value, |item| prop.get(item.into_owned()))
152 }
153}
154
155/// Extension trait for vectors.
156///
157/// See the [module documentation] for examples.
158///
159/// [module documentation]: index.html
160pub trait GraphsVecExt<T> {
161 /// Returns a vector sorted by a [property].
162 ///
163 /// This functions calls [`GraphsSliceExt::sort_by_prop`].
164 ///
165 /// [property]: ../props/index.html
166 /// [`GraphsSliceExt::sort_by_prop`]: trait.GraphsSliceExt.html#tymethod.sort_by_prop
167 fn sorted_by_prop<P, K>(self, prop: P) -> Self
168 where
169 P: PropGet<K>,
170 for<'a> &'a T: IntoOwned<K>,
171 P::Output: Ord;
172
173 /// Returns a vector sorted by a [property].
174 ///
175 /// This functions calls [`GraphsSliceExt::sort_unstable_by_prop`].
176 ///
177 /// [property]: ../props/index.html
178 /// [`GraphsSliceExt::sort_unstable_by_prop`]: trait.GraphsSliceExt.html#tymethod.sort_unstable_by_prop
179 fn sorted_unstable_by_prop<P, K>(self, prop: P) -> Self
180 where
181 P: PropGet<K>,
182 for<'a> &'a T: IntoOwned<K>,
183 P::Output: Ord;
184}
185
186impl<T> GraphsVecExt<T> for Vec<T> {
187 #[inline]
188 fn sorted_by_prop<P, K>(mut self, prop: P) -> Self
189 where
190 P: PropGet<K>,
191 for<'a> &'a T: IntoOwned<K>,
192 P::Output: Ord,
193 {
194 self.sort_by_prop(prop);
195 self
196 }
197
198 #[inline]
199 fn sorted_unstable_by_prop<P, K>(mut self, prop: P) -> Self
200 where
201 P: PropGet<K>,
202 for<'a> &'a T: IntoOwned<K>,
203 P::Output: Ord,
204 {
205 self.sort_unstable_by_prop(prop);
206 self
207 }
208}