use core::mem::swap;
use super::prelude::*;
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum Order {
Before,
After,
}
impl Default for Order {
#[inline]
fn default() -> Self {
Self::Before
}
}
#[derive(Debug, Default, Clone, Copy)]
pub struct Ordered<T> {
value: T,
order: Order,
}
impl<T> Ordered<T> {
#[inline]
pub fn new(value: T) -> Self {
Self::with_order(value, Order::default())
}
#[inline]
pub fn with_order(value: T, order: Order) -> Self {
Self { value, order }
}
#[inline]
pub fn order(&self) -> Order {
self.order
}
#[inline]
pub fn set_order<O>(&mut self, order: O)
where
O: Into<Order>,
{
self.order = order.into();
}
#[inline]
pub fn into_value(self) -> T {
self.value
}
}
impl<T> Merge for Ordered<T>
where
T: Merge,
{
fn merge_ref(&mut self, mut other: Self) -> Result<(), Error> {
if other.order == Order::Before {
swap(&mut self.value, &mut other.value);
}
self.value.merge_ref(other.value)
}
}
impl<T> From<T> for Ordered<T> {
#[inline]
fn from(value: T) -> Self {
Self::new(value)
}
}
impl_wrapper!(Ordered<T> => T { .value });
#[cfg(feature = "serde")]
mod serde_impl {
use super::*;
use serde::Deserialize;
use serde::de::Deserializer;
#[derive(Deserialize)]
#[serde(rename_all = "lowercase")]
enum OrderRepr {
Before,
After,
}
impl From<OrderRepr> for Order {
fn from(x: OrderRepr) -> Self {
match x {
OrderRepr::Before => Order::Before,
OrderRepr::After => Order::After,
}
}
}
#[derive(Deserialize)]
#[serde(untagged)]
enum Repr<T> {
Order { value: T, order: OrderRepr },
Value { value: T },
Raw(T),
}
impl<T> From<Repr<T>> for Ordered<T> {
fn from(x: Repr<T>) -> Self {
match x {
Repr::Order { value, order } => Self::with_order(value, Order::from(order)),
Repr::Value { value } => Ordered::new(value),
Repr::Raw(value) => Ordered::new(value),
}
}
}
impl<'de, T> Deserialize<'de> for Ordered<T>
where
T: Deserialize<'de>,
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
<Repr<T> as Deserialize>::deserialize(deserializer).map(Into::into)
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use Order::{After, Before};
#[inline]
fn x<T>(value: T, order: Order) -> Ordered<T> {
Ordered::with_order(value, order)
}
#[test]
fn test_before_after() {
let a = x(vec![0, 1, 2, 3], Before);
let b = x(vec![4, 5, 6], After);
let c = a.merge(b).unwrap();
assert_eq!(*c, &[0, 1, 2, 3, 4, 5, 6]);
}
#[test]
fn test_after_before() {
let a = x(vec![0, 1, 2, 3], After);
let b = x(vec![4, 5, 6], Before);
let c = a.merge(b).unwrap();
assert_eq!(*c, &[4, 5, 6, 0, 1, 2, 3]);
}
#[test]
fn test_after_after() {
let a = x(vec![0, 1, 2, 3], Before);
let b = x(vec![4, 5, 6], After);
let c = a.merge(b).unwrap();
assert_eq!(*c, &[0, 1, 2, 3, 4, 5, 6]);
}
#[test]
fn test_before_before() {
let a = x(vec![0, 1, 2, 3], Before);
let b = x(vec![4, 5, 6], Before);
let c = a.merge(b).unwrap();
assert_eq!(*c, &[4, 5, 6, 0, 1, 2, 3]);
}
}
#[cfg(test)]
#[cfg(feature = "serde")]
mod serde_tests {
use super::*;
#[test]
fn test_deserialize_t() {
let x: Ordered<i32> = serde_json::from_str("42").unwrap();
assert_eq!(x.order(), Order::Before);
assert_eq!(*x, 42);
}
#[test]
fn test_deserialize_value() {
let x: Ordered<i32> = serde_json::from_str("{ \"value\": 42 }").unwrap();
assert_eq!(x.order(), Order::Before);
assert_eq!(*x, 42);
}
#[test]
fn test_deserialize_value_order_before() {
let x: Ordered<i32> =
serde_json::from_str("{ \"value\": 42, \"order\": \"before\" }").unwrap();
assert_eq!(x.order(), Order::Before);
assert_eq!(*x, 42);
}
#[test]
fn test_deserialize_value_order_after() {
let x: Ordered<i32> =
serde_json::from_str("{ \"value\": 42, \"order\": \"after\" }").unwrap();
assert_eq!(x.order(), Order::After);
assert_eq!(*x, 42);
}
}