vstorage 0.8.1

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

//! Item analysis types.

use crate::{
    base::{FetchedItem, Item, ItemVersion},
    sync::status::ItemState,
};

/// Item state with data present.
#[derive(Clone, Debug, PartialEq)]
pub struct ItemWithData {
    /// Metadata and state for this item.
    pub state: ItemState,
    /// Data for this version of the item.
    pub data: Item,
}

/// Source data for copying an item onto the other side.
#[derive(Clone, Debug, PartialEq)]
pub struct ItemSource {
    /// Metadata and state for this item.
    pub state: ItemState,
    /// Data for this version of the item, if available.
    pub data: Option<Item>,
}

impl From<ItemWithData> for ItemSource {
    fn from(item: ItemWithData) -> Self {
        ItemSource {
            state: item.state,
            data: Some(item.data),
        }
    }
}

/// Current state of an item on one side.
#[derive(Clone)]
pub enum SideState {
    /// Item changed from status (data was fetched).
    Changed { state: ItemState, data: Item },
    /// Item unchanged from status (data not fetched).
    Unchanged { state: ItemState },
}

impl SideState {
    /// Create changed status from a fetched item (changed or new).
    #[must_use]
    pub fn from_fetched(FetchedItem { href, item, etag }: FetchedItem) -> Self {
        Self::Changed {
            state: ItemState {
                version: ItemVersion::new(href, etag),
                uid: item.ident(),
                hash: item.hash(),
            },
            data: item,
        }
    }

    /// Create for an unchanged item (data not fetched).
    #[must_use]
    pub fn unchanged(state: ItemState) -> Self {
        Self::Unchanged { state }
    }

    /// Get the item state.
    #[must_use]
    pub fn state(&self) -> &ItemState {
        match self {
            Self::Changed { state, .. } | Self::Unchanged { state } => state,
        }
    }
}

impl From<SideState> for ItemVersion {
    /// Convert from `SideState` without copying.
    fn from(value: SideState) -> Self {
        match value {
            SideState::Changed { state, .. } | SideState::Unchanged { state } => state.version,
        }
    }
}

impl From<SideState> for ItemSource {
    /// Convert from `SideState`, preserving data is any.
    fn from(value: SideState) -> Self {
        match value {
            SideState::Changed { state, data } => ItemSource {
                state,
                data: Some(data),
            },
            SideState::Unchanged { state } => ItemSource { state, data: None },
        }
    }
}