As detailed in this SO question, I'm using custom logic in a BTreeSet to automatically sort a foreign data type as elements are added to the container. Note that the Data type is used from another module in the actual implementation, so I can't just implement Ord for it, necessitating this approach.
I'm concerned that the iterator pipeline I'm using in main() is too complex and that the various impls are just boilerplate for something that really boils down to a single line of actual desired logic.
Here's a Rust Playground link.
use std::collections::BTreeSet;
use std::convert::{From, Into};
use std::cmp::Ordering;
use std::ops::Deref;
// Here's the original struct...
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
struct Data(usize);
impl From<usize> for Data {
fn from(i: usize) -> Self {
Data(i)
}
}
// And here's the wrapper type we'll use to sort it.
#[derive(PartialEq, Eq, Debug)]
struct SortableData(Data);
impl Deref for SortableData {
type Target = Data;
fn deref<'a>(&'a self) -> &'a Data {
&self.0
}
}
impl From<Data> for SortableData {
fn from(data: Data) -> Self {
SortableData(data)
}
}
impl PartialOrd for SortableData {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl Ord for SortableData {
fn cmp(&self, other: &Self) -> Ordering {
(self.0).0.cmp(&(other.0).0)
}
}
fn main() {
let source: [Data; 3] = [Data(9), Data(4), Data(2)];
let sorted: BTreeSet<SortableData> = source.iter().cloned().map(|i| i.into()).collect();
for d in sorted.iter() {
println!("{:?}", **d);
}
}