git_bug/replica/entity/operation/
operations.rs1use std::iter::{Once, once};
16
17use serde::{Deserialize, Serialize};
18
19use super::{Operation, operation_data::OperationData};
20use crate::replica::entity::Entity;
21
22#[derive(Debug, Deserialize, Serialize)]
24pub struct Operations<E: Entity> {
25 #[serde(bound = "Operation<E>: serde::Serialize + serde::de::DeserializeOwned")]
26 root_operation: Operation<E>,
27
28 #[serde(bound = "Vec<Operation<E>>: serde::Serialize + serde::de::DeserializeOwned")]
29 other_operations: Vec<Operation<E>>,
30}
31
32#[allow(missing_docs)]
33pub mod create {
34 use crate::replica::entity::{Entity, operation::Operation};
35
36 #[derive(Debug, thiserror::Error)]
37 pub enum Error<E: Entity> {
38 #[error("Tried to collect an empty vector to an Operations structure")]
39 EmptyOperations,
40
41 #[error(
42 "Tried to use an non root operation ({first}) as root for an Operations structure."
43 )]
44 OperationsFromNonRoot { first: Box<Operation<E>> },
45 }
46}
47
48impl<E: Entity> Operations<E> {
49 #[allow(clippy::missing_panics_doc)]
57 pub fn from_operations(mut ops: Vec<Operation<E>>) -> Result<Self, create::Error<E>> {
58 if ops.is_empty() {
59 return Err(create::Error::EmptyOperations);
60 }
61
62 if !ops
63 .first()
64 .expect("Exists, as the operations are not empty")
65 .data
66 .is_root()
67 {
68 return Err(create::Error::OperationsFromNonRoot {
69 first: Box::new(ops.remove(0)),
70 });
71 }
72
73 Ok(Self {
74 root_operation: ops.remove(0),
75 other_operations: ops,
76 })
77 }
78
79 pub fn root(&self) -> &Operation<E> {
81 &self.root_operation
82 }
83}
84
85impl<T: Entity> Operations<T> {
87 #[must_use]
89 #[allow(clippy::len_without_is_empty)]
91 pub fn len(&self) -> usize {
92 self.other_operations.len() + 1
93 }
94
95 #[must_use]
97 pub fn iter(&self) -> <&Self as IntoIterator>::IntoIter {
98 self.into_iter()
99 }
100}
101
102impl<E: Entity> IntoIterator for Operations<E> {
103 type IntoIter =
104 std::iter::Chain<Once<Self::Item>, <Vec<Operation<E>> as IntoIterator>::IntoIter>;
105 type Item = <Vec<Operation<E>> as IntoIterator>::Item;
106
107 fn into_iter(self) -> Self::IntoIter {
108 once(self.root_operation).chain(self.other_operations)
109 }
110}
111impl<'a, E: Entity> IntoIterator for &'a Operations<E> {
112 type IntoIter =
113 std::iter::Chain<Once<Self::Item>, <&'a Vec<Operation<E>> as IntoIterator>::IntoIter>;
114 type Item = <&'a Vec<Operation<E>> as IntoIterator>::Item;
115
116 fn into_iter(self) -> Self::IntoIter {
117 once(&self.root_operation).chain(self.other_operations.iter())
118 }
119}