p2panda_rs/operation/
operation_value.rs1use serde::Serialize;
4
5use crate::document::{DocumentId, DocumentViewId};
6use crate::operation::{PinnedRelation, PinnedRelationList, Relation, RelationList};
7
8#[derive(Clone, Debug, PartialEq, Serialize)]
10pub enum OperationValue {
11 Boolean(bool),
13
14 #[serde(with = "serde_bytes")]
16 Bytes(Vec<u8>),
17
18 Integer(i64),
20
21 Float(f64),
23
24 String(String),
26
27 Relation(Relation),
29
30 RelationList(RelationList),
32
33 PinnedRelation(PinnedRelation),
35
36 PinnedRelationList(PinnedRelationList),
38}
39
40impl OperationValue {
41 pub fn field_type(&self) -> &str {
43 match self {
44 OperationValue::Boolean(_) => "bool",
45 OperationValue::Bytes(_) => "bytes",
46 OperationValue::Integer(_) => "int",
47 OperationValue::Float(_) => "float",
48 OperationValue::String(_) => "str",
49 OperationValue::Relation(_) => "relation",
50 OperationValue::RelationList(_) => "relation_list",
51 OperationValue::PinnedRelation(_) => "pinned_relation",
52 OperationValue::PinnedRelationList(_) => "pinned_relation_list",
53 }
54 }
55}
56
57impl From<bool> for OperationValue {
58 fn from(value: bool) -> Self {
59 OperationValue::Boolean(value)
60 }
61}
62
63impl From<f64> for OperationValue {
64 fn from(value: f64) -> Self {
65 OperationValue::Float(value)
66 }
67}
68
69impl From<i64> for OperationValue {
70 fn from(value: i64) -> Self {
71 OperationValue::Integer(value)
72 }
73}
74
75impl From<String> for OperationValue {
76 fn from(value: String) -> Self {
77 OperationValue::String(value)
78 }
79}
80
81impl From<&str> for OperationValue {
82 fn from(value: &str) -> Self {
83 OperationValue::String(value.to_string())
84 }
85}
86
87impl From<&[u8]> for OperationValue {
88 fn from(value: &[u8]) -> Self {
89 OperationValue::Bytes(value.to_owned())
90 }
91}
92
93impl From<DocumentId> for OperationValue {
94 fn from(value: DocumentId) -> Self {
95 OperationValue::Relation(Relation::new(value))
96 }
97}
98
99impl From<Vec<DocumentId>> for OperationValue {
100 fn from(value: Vec<DocumentId>) -> Self {
101 OperationValue::RelationList(RelationList::new(value))
102 }
103}
104
105impl From<DocumentViewId> for OperationValue {
106 fn from(value: DocumentViewId) -> Self {
107 OperationValue::PinnedRelation(PinnedRelation::new(value))
108 }
109}
110
111impl From<Vec<DocumentViewId>> for OperationValue {
112 fn from(value: Vec<DocumentViewId>) -> Self {
113 OperationValue::PinnedRelationList(PinnedRelationList::new(value))
114 }
115}
116
117#[cfg(test)]
118mod tests {
119 use rstest::rstest;
120
121 use crate::document::{DocumentId, DocumentViewId};
122 use crate::operation::{
123 OperationId, PinnedRelation, PinnedRelationList, Relation, RelationList,
124 };
125 use crate::test_utils::fixtures::{document_id, document_view_id, random_operation_id};
126
127 use super::OperationValue;
128
129 #[rstest]
130 fn to_field_type(#[from(random_operation_id)] operation_id: OperationId) {
131 let bool = OperationValue::Boolean(true);
132 assert_eq!(bool.field_type(), "bool");
133
134 let int = OperationValue::Integer(1);
135 assert_eq!(int.field_type(), "int");
136
137 let float = OperationValue::Float(0.1);
138 assert_eq!(float.field_type(), "float");
139
140 let text = OperationValue::String("Hello".to_string());
141 assert_eq!(text.field_type(), "str");
142
143 let relation = OperationValue::Relation(Relation::new(DocumentId::new(&operation_id)));
144 assert_eq!(relation.field_type(), "relation");
145
146 let pinned_relation =
147 OperationValue::PinnedRelation(PinnedRelation::new(DocumentViewId::new(&[
148 operation_id.clone(),
149 ])));
150 assert_eq!(pinned_relation.field_type(), "pinned_relation");
151
152 let relation_list =
153 OperationValue::RelationList(RelationList::new(vec![DocumentId::new(&operation_id)]));
154 assert_eq!(relation_list.field_type(), "relation_list");
155
156 let pinned_relation_list = OperationValue::PinnedRelationList(PinnedRelationList::new(
157 vec![DocumentViewId::new(&[operation_id])],
158 ));
159 assert_eq!(pinned_relation_list.field_type(), "pinned_relation_list");
160 }
161
162 #[rstest]
163 fn from_primitives(document_id: DocumentId, document_view_id: DocumentViewId) {
164 assert_eq!(OperationValue::Boolean(true), true.into());
166 assert_eq!(OperationValue::Float(1.5), 1.5.into());
167 assert_eq!(OperationValue::Integer(3), 3.into());
168 assert_eq!(OperationValue::String("hellö".to_string()), "hellö".into());
169
170 assert_eq!(
172 OperationValue::Relation(Relation::new(document_id.clone())),
173 document_id.clone().into()
174 );
175 assert_eq!(
176 OperationValue::RelationList(RelationList::new(vec![document_id.clone()])),
177 vec![document_id].into()
178 );
179 assert_eq!(
180 OperationValue::PinnedRelation(PinnedRelation::new(document_view_id.clone())),
181 document_view_id.clone().into()
182 );
183 assert_eq!(
184 OperationValue::PinnedRelationList(PinnedRelationList::new(vec![
185 document_view_id.clone()
186 ])),
187 vec![document_view_id].into()
188 );
189 }
190}