try_partialord/lib.rs
1// Mit License from https://github.com/rust-lang/rust
2//
3// Permission is hereby granted, free of charge, to any
4// person obtaining a copy of this software and associated
5// documentation files (the "Software"), to deal in the
6// Software without restriction, including without
7// limitation the rights to use, copy, modify, merge,
8// publish, distribute, sublicense, and/or sell copies of
9// the Software, and to permit persons to whom the Software
10// is furnished to do so, subject to the following
11// conditions:
12//
13// The above copyright notice and this permission notice
14// shall be included in all copies or substantial portions
15// of the Software.
16//
17// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
18// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
19// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
20// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
21// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
22// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
24// IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25// DEALINGS IN THE SOFTWARE.
26
27// ignore-tidy-undocumented-unsafe
28
29//! __Safe failable sort, min, max, binary_search functions for PartialOrd. No need to wrap `f32`, `f64` to sort any more.__
30//!
31//! This crate provides helper traits for type with only [`PartialOrd`] but not [`Ord`]( like [`f32`], [`f64`]), to use methods where [`Ord`](`core::cmp::Ord`) is needed, like sort, min, max and binary_search.
32//! These methods are almost same as the methods for Ord, exept that it returns [`InvalidOrderError`] when the [`partial_cmp`](`std::cmp::PartialOrd::partial_cmp`)
33//! returns [`None`](`core::option::Option::None`).
34//! These traits have `try_` methods like [`try_sort`](`TrySort::try_sort`) for [`slice::sort`].
35//!
36//! This is safer than using something like `sort_by` with ignoreing None case of [`partial_cmp`](`std::cmp::PartialOrd::partial_cmp`) because it handle error instead of panic.
37//!
38//! Sort is using the same logic as std.
39//!
40//! This supports `no_std` with no `std` feature flag.
41//!
42//! ```
43//! use try_partialord::*;
44//! use rand::distributions::Standard;
45//! use rand::prelude::*;
46//!
47//! let mut vec: Vec<f32> = Standard.sample_iter(thread_rng()).take(100).collect();
48//! //no NAN in vec so sort should succed
49//! let sort_result = vec.try_sort();
50//! assert!(sort_result.is_ok());
51//! assert!(vec.try_is_sorted().unwrap_or(false));
52//!
53//! vec.push(f32::NAN);
54//! //NAN in vec so sort should fail
55//! let sort_result = vec.try_sort();
56//! assert!(sort_result.is_err());
57//! assert!(vec.try_is_sorted().is_err());
58//! ```
59
60#![cfg_attr(not(feature = "std"), no_std)]
61
62mod binary_search;
63mod min_max;
64mod sort;
65pub use binary_search::TryBinarySearch;
66use core::fmt::{Display, Error, Formatter};
67pub use min_max::TryMinMax;
68pub use sort::*;
69
70/// Error when [`partial_cmp`](`std::cmp::PartialOrd::partial_cmp`) returns [`None`] during the operation.
71#[derive(Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Default, Debug)]
72pub struct InvalidOrderError;
73
74impl Display for InvalidOrderError {
75 fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error> {
76 fmt.write_str("Failed because partial_cmp returns None.")
77 }
78}
79
80#[cfg(feature = "std")]
81impl std::error::Error for InvalidOrderError {}
82
83/// Alias for result
84pub type OrderResult<T> = Result<T, InvalidOrderError>;
85
86fn ord_as_cmp<T>(a: &T, b: &T) -> Option<bool>
87where
88 T: PartialOrd<T>,
89{
90 a.partial_cmp(b).map(|a| a == core::cmp::Ordering::Less)
91}