glycin_common/
operations.rs1use std::io::Read;
2use std::str::FromStr;
3
4use gufo_common::orientation::{Orientation, Rotation};
5use serde::de::{value, IntoDeserializer};
6use serde::{Deserialize, Deserializer, Serialize};
7
8#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
9#[non_exhaustive]
10pub enum Operation {
11 Clip((u32, u32, u32, u32)),
12 MirrorHorizontally,
13 MirrorVertically,
14 Rotate(gufo_common::orientation::Rotation),
16}
17
18#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)]
19#[non_exhaustive]
20pub enum OperationId {
21 Clip,
22 MirrorHorizontally,
23 MirrorVertically,
24 Rotate,
25}
26
27#[derive(Debug, PartialEq, Deserialize, Serialize)]
28#[serde(from = "OperationsIntermediate")]
29pub struct Operations {
30 operations: Vec<Operation>,
31 #[serde(skip)]
32 unknown_operations: Vec<String>,
33}
34
35impl Operations {
36 pub fn new(operations: Vec<Operation>) -> Operations {
37 Self {
38 operations,
39 unknown_operations: vec![],
40 }
41 }
42
43 pub fn new_orientation(orientation: Orientation) -> Operations {
45 let mut operations = Vec::new();
46
47 if orientation.mirror() {
48 operations.push(Operation::MirrorHorizontally);
49 }
50
51 let rotate = orientation.rotate();
52 if rotate != Rotation::_0 {
53 operations.push(Operation::Rotate(rotate));
54 }
55
56 Self {
57 operations,
58 unknown_operations: Vec::new(),
59 }
60 }
61
62 pub fn prepend(&mut self, mut operations: Operations) {
79 std::mem::swap(self, &mut operations);
80 self.operations.append(&mut operations.operations);
81 }
82
83 pub fn from_read(reader: impl Read) -> Result<Self, rmp_serde::decode::Error> {
84 rmp_serde::decode::from_read(reader)
85 }
86
87 pub fn from_slice(slice: impl AsRef<[u8]>) -> Result<Self, rmp_serde::decode::Error> {
88 rmp_serde::decode::from_slice(slice.as_ref())
89 }
90
91 pub fn to_message_pack(&self) -> Result<Vec<u8>, rmp_serde::encode::Error> {
92 let mut buf = Vec::new();
93 self.serialize(&mut rmp_serde::Serializer::new(&mut buf).with_human_readable())?;
94
95 Ok(buf)
96 }
97
98 pub fn operations(&self) -> &[Operation] {
99 &self.operations
100 }
101
102 pub fn operation_ids(&self) -> Vec<OperationId> {
103 self.operations.iter().map(|x| x.id()).collect()
104 }
105
106 pub fn unknown_operations(&self) -> &[String] {
109 &self.unknown_operations
110 }
111
112 pub fn orientation(&self) -> Option<Orientation> {
147 let mut orientation = Orientation::Id;
148
149 for operation in &self.operations {
150 match operation {
151 Operation::MirrorHorizontally => {
152 orientation = orientation.add_mirror_horizontally();
153 }
154 Operation::MirrorVertically => {
155 orientation = orientation.add_mirror_vertically();
156 }
157 Operation::Rotate(rotation) => {
158 orientation = orientation.add_rotation(*rotation);
159 }
160 _ => return None,
161 }
162 }
163
164 Some(orientation)
165 }
166}
167
168impl From<OperationsIntermediate> for Operations {
169 fn from(operations: OperationsIntermediate) -> Operations {
170 Operations {
171 operations: operations
172 .operations
173 .iter()
174 .filter_map(|x| x.operation().cloned())
175 .collect(),
176
177 unknown_operations: operations
178 .operations
179 .iter()
180 .filter_map(|x| x.unknown())
181 .collect(),
182 }
183 }
184}
185
186#[derive(Debug, PartialEq, Deserialize)]
188struct OperationsIntermediate {
189 operations: Vec<MaybeOperation>,
190}
191
192#[derive(Debug, PartialEq)]
193enum MaybeOperation {
194 Operation(Operation),
195 Unknown(String),
196}
197
198impl MaybeOperation {
199 fn operation(&self) -> Option<&Operation> {
200 match self {
201 Self::Operation(operation) => Some(operation),
202 Self::Unknown(_) => None,
203 }
204 }
205
206 fn unknown(&self) -> Option<String> {
207 match self {
208 Self::Operation(_) => None,
209 Self::Unknown(s) => Some(s.to_string()),
210 }
211 }
212}
213
214impl<'de> Deserialize<'de> for MaybeOperation {
215 fn deserialize<D>(deserializer: D) -> Result<MaybeOperation, D::Error>
216 where
217 D: Deserializer<'de>,
218 {
219 match serde::Deserialize::deserialize(deserializer) {
220 Ok(val) => Ok(Self::Operation(val)),
221 Err(err) => Ok(Self::Unknown(err.to_string())),
222 }
223 }
224}
225
226impl Operation {
227 pub fn id(&self) -> OperationId {
228 match self {
229 Self::Clip(_) => OperationId::Clip,
230 Self::MirrorHorizontally => OperationId::MirrorHorizontally,
231 Self::MirrorVertically => OperationId::MirrorVertically,
232 Self::Rotate(_) => OperationId::Rotate,
233 }
234 }
235}
236
237impl FromStr for OperationId {
238 type Err = value::Error;
239
240 fn from_str(slice: &str) -> Result<Self, value::Error> {
247 Self::deserialize(slice.into_deserializer())
248 }
249}