vstorage 0.10.0

Common API for various icalendar/vcard storages.
Documentation
// Copyright 2023-2024 Hugo Osvaldo Barrera
//
// SPDX-License-Identifier: EUPL-1.2

//! Components used for synchronising storages.
//!
//! The general gist behind synchronising is:
//!
//! - Create a new [`declare::StoragePair`]. This type specifies which storages and which
//!   collections are to be synchronised. A [`status::StatusDatabase`] instance with details of the
//!   previous synchronisation should be provided, if it exists.
//! - Use [`plan::Plan::new`] to create a plan, a stream of synchronisation operations. If operations
//!   need to be reviewed first, they should be allocated into a single container. For the typical
//!   usage, it's best to consume items from the stream as needed.
//! - The stream may contain conflict operations. These can be resolved using a
//!   [`conflict::ConflictResolver`], by writing merged files using the `Storage` APIs
//!   directly, or by wrapping the stream in a type which applies mutations.
//! - Use the [`execute::Executor`] type to execute operations from the stream. It updates the
//!   status database to reflect which items exist on both sides and their metadata. The status
//!   database shall be used on the next cycle to understand which items have changed on which
//!   sides.
//!
//! The synchronisation algorithm is based on [the algorithm from the original vdirsyncer][orig].
//!
//! [orig]: https://unterwaditzer.net/2016/sync-algorithm.html

pub mod conflict;
pub mod declare;
mod error;
pub mod execute;
pub mod items;
pub mod mapping;
mod mode;
mod one_way;
pub mod operation;
pub mod ordering;
pub mod plan;
pub mod status;
mod two_way;

pub use error::SyncError;
pub use mode::Mode;
pub use one_way::OneWaySync;
pub use two_way::TwoWaySync;

/// Storages are synchronised between two "sides", 'a' or 'b'.
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Side {
    /// Side `a` from the sync pair.
    ///
    /// Serialised into the status database as `0`.
    A,
    /// Side `b` from the sync pair.
    B,
}

impl Side {
    /// Return the opposite side for this one.
    #[must_use]
    pub fn opposite(self) -> Side {
        match self {
            Side::A => Side::B,
            Side::B => Side::A,
        }
    }

    /// Returns a human-friendly representation (i.e.: `a` or `b`).
    #[must_use]
    pub fn as_char(self) -> char {
        match self {
            Side::A => 'a',
            Side::B => 'b',
        }
    }
}

impl std::fmt::Display for Side {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        self.as_char().fmt(f)
    }
}