git-bug 0.2.4

A rust library for interfacing with git-bug repositories
Documentation
// git-bug-rs - A rust library for interfacing with git-bug repositories
//
// Copyright (C) 2025 Benedikt Peetz <benedikt.peetz@b-peetz.de>
// SPDX-License-Identifier: GPL-3.0-or-later
//
// This file is part of git-bug-rs/git-gub.
//
// You should have received a copy of the License along with this program.
// If not, see <https://www.gnu.org/licenses/agpl.txt>.

use simd_json::{borrowed, derived::ValueTryIntoArray, owned};

use crate::{
    entities::issue::{data::label::Label, issue_operation::IssueOperationData},
    replica::entity::operation::operation_data::get,
};

struct LabelChange {
    added: Option<Vec<owned::Value>>,
    removed: Option<Vec<owned::Value>>,
}

pub(crate) fn label_change(
    mut value: owned::Object,
) -> Result<IssueOperationData, super::decode::Error> {
    Ok({
        let base: LabelChange = LabelChange {
            added: get! {@option value, "added", try_into_array, super::decode::Error},
            removed: get! {@option value, "removed", try_into_array, super::decode::Error},
        };

        IssueOperationData::LabelChange {
            added: base
                .added
                .unwrap_or_default()
                .into_iter()
                .map(Label::try_from)
                .collect::<Result<_, _>>()?,
            removed: base
                .removed
                .unwrap_or_default()
                .into_iter()
                .map(Label::try_from)
                .collect::<Result<_, _>>()?,
        }
    })
}

pub(crate) fn label_change_value<'a>(
    added: &'a [Label],
    removed: &'a [Label],
) -> borrowed::Object<'a> {
    let added: Option<Vec<_>> = if added.is_empty() {
        None
    } else {
        Some(
            added
                .iter()
                .map(Into::<borrowed::Value<'_>>::into)
                .collect(),
        )
    };

    let removed: Option<Vec<_>> = if removed.is_empty() {
        None
    } else {
        Some(
            removed
                .iter()
                .map(Into::<borrowed::Value<'_>>::into)
                .collect(),
        )
    };

    let mut object = borrowed::Object::new();

    // Safety:
    // We just created this object. As such, it is empty.
    unsafe {
        object.insert_nocheck("added".into(), added.into());
        object.insert_nocheck("removed".into(), removed.into());
    }

    object
}