1use std::any::Any;
2use std::io::{Cursor, Read, Seek, SeekFrom, Write};
3use std::panic::RefUnwindSafe;
4
5use glycin_common::Operations;
6#[cfg(feature = "external")]
7use zbus::zvariant::{self, DeserializeDict, SerializeDict, Type, as_value};
8
9use crate::{
10 ByteData, EncodedImage, EncodingOptions, FungibleMemory, GenericContexts,
11 InitializationDetails, MemoryAllocationError, NewImage, ProcessError,
12};
13
14pub trait EditorImplementation: Send + Sync + Sized + RefUnwindSafe + 'static {
16 const USEABLE: bool = true;
17
18 fn edit<S: Read + Any>(
19 stream: S,
20 mime_type: String,
21 details: InitializationDetails,
22 ) -> Result<Self, ProcessError>;
23
24 fn create<B: ByteData>(
25 mime_type: String,
26 new_image: NewImage<B>,
27 encoding_options: EncodingOptions,
28 ) -> Result<EncodedImage<B>, ProcessError>;
29
30 fn apply_sparse<B: ByteData>(
31 &self,
32 operations: Operations,
33 ) -> Result<SparseEditorOutput<B>, ProcessError> {
34 let complete = Self::apply_complete(self, operations)?;
35
36 Ok(SparseEditorOutput::from(complete))
37 }
38
39 fn apply_complete<B: ByteData>(
40 &self,
41 operations: Operations,
42 ) -> Result<CompleteEditorOutput<B>, ProcessError>;
43}
44
45#[cfg(feature = "external")]
46#[derive(serde::Deserialize, serde::Serialize, Type, Debug, Clone)]
48pub struct RemoteEditableImage {
49 pub edit_request: zvariant::OwnedObjectPath,
50}
51
52#[cfg(feature = "external")]
53impl RemoteEditableImage {
54 pub fn new(frame_request: zvariant::OwnedObjectPath) -> Self {
55 Self {
56 edit_request: frame_request,
57 }
58 }
59}
60
61#[derive(Debug)]
66#[cfg_attr(
67 feature = "external",
68 derive(Type, serde::Serialize, serde::Deserialize)
69)]
70#[cfg_attr(feature = "external", zvariant(signature = "dict"))]
71#[cfg_attr(
72 feature = "external",
73 serde(bound(
74 serialize = "B: ByteData + serde::Serialize + zbus::zvariant::Type + 'static",
75 deserialize = "B: ByteData + serde::de::DeserializeOwned + zbus::zvariant::Type + 'static"
76 ))
77)]
78#[non_exhaustive]
79pub struct SparseEditorOutput<B: ByteData> {
80 #[cfg_attr(
81 feature = "external",
82 serde(
83 with = "as_value::optional",
84 skip_serializing_if = "Option::is_none",
85 default
86 )
87 )]
88 pub byte_changes: Option<ByteChanges>,
89 #[cfg_attr(
90 feature = "external",
91 serde(
92 with = "as_value::optional",
93 skip_serializing_if = "Option::is_none",
94 default
95 )
96 )]
97 pub data: Option<B>,
98 #[cfg_attr(feature = "external", serde(with = "as_value"))]
99 pub info: EditorOutputInfo,
100}
101
102impl<B: ByteData> SparseEditorOutput<B> {
103 pub fn byte_changes(byte_changes: ByteChanges) -> Self {
104 SparseEditorOutput {
105 byte_changes: Some(byte_changes),
106 data: None,
107 info: EditorOutputInfo { lossless: true },
108 }
109 }
110
111 pub fn into_fungible(self) -> SparseEditorOutput<FungibleMemory> {
112 SparseEditorOutput {
113 byte_changes: self.byte_changes,
114 data: self.data.map(|x| x.into_fungible()),
115 info: self.info,
116 }
117 }
118
119 pub async fn initial_seal(&mut self) -> Result<(), MemoryAllocationError> {
120 if let Some(data) = &mut self.data {
121 data.initial_seal().await?;
122 }
123
124 Ok(())
125 }
126
127 pub async fn final_seal(&mut self) -> Result<(), MemoryAllocationError> {
128 if let Some(data) = &mut self.data {
129 data.final_seal().await?;
130 }
131
132 Ok(())
133 }
134}
135
136impl<B: ByteData> From<CompleteEditorOutput<B>> for SparseEditorOutput<B> {
137 fn from(value: CompleteEditorOutput<B>) -> Self {
138 Self {
139 byte_changes: None,
140 data: Some(value.data),
141 info: value.info,
142 }
143 }
144}
145
146#[derive(Debug, Clone)]
147#[cfg_attr(feature = "external", derive(DeserializeDict, SerializeDict, Type))]
148#[cfg_attr(feature = "external", zvariant(signature = "dict"))]
149#[non_exhaustive]
150pub struct ByteChanges {
151 pub changes: Vec<ByteChange>,
152}
153
154#[derive(Debug, Clone)]
155#[cfg_attr(
156 feature = "external",
157 derive(serde::Deserialize, serde::Serialize, Type)
158)]
159pub struct ByteChange {
160 pub offset: u64,
161 pub new_value: u8,
162}
163
164impl ByteChanges {
165 pub fn from_slice(changes: &[(u64, u8)]) -> Self {
166 ByteChanges {
167 changes: changes
168 .iter()
169 .map(|(offset, new_value)| ByteChange {
170 offset: *offset,
171 new_value: *new_value,
172 })
173 .collect(),
174 }
175 }
176
177 pub fn apply(&self, data: &mut [u8]) -> std::io::Result<()> {
178 let mut cur = Cursor::new(data);
179 for change in self.changes.iter() {
180 cur.seek(SeekFrom::Start(change.offset))?;
181 cur.write_all(&[change.new_value])?;
182 }
183 Ok(())
184 }
185}
186
187#[derive(Debug)]
188#[cfg_attr(
189 feature = "external",
190 derive(Type, serde::Serialize, serde::Deserialize)
191)]
192#[cfg_attr(feature = "external", zvariant(signature = "dict"))]
193#[cfg_attr(
194 feature = "external",
195 serde(bound(
196 serialize = "B: ByteData + serde::Serialize + zbus::zvariant::Type + 'static",
197 deserialize = "B: ByteData + serde::de::DeserializeOwned + zbus::zvariant::Type + 'static"
198 ))
199)]
200#[non_exhaustive]
201pub struct CompleteEditorOutput<B: ByteData> {
202 #[cfg_attr(feature = "external", serde(with = "as_value"))]
203 pub data: B,
204 #[cfg_attr(feature = "external", serde(with = "as_value"))]
205 pub info: EditorOutputInfo,
206}
207
208impl<B: ByteData> CompleteEditorOutput<B> {
223 pub fn new(data: B) -> Self {
224 Self {
225 data,
226 info: Default::default(),
227 }
228 }
229
230 pub fn new_lossless(data: Vec<u8>) -> Result<Self, ProcessError> {
231 let data = B::try_from_vec(data).expected_error()?;
232 let info = EditorOutputInfo { lossless: true };
233 Ok(Self { data, info })
234 }
235
236 pub fn into_fungible(self) -> CompleteEditorOutput<FungibleMemory> {
237 CompleteEditorOutput {
238 data: self.data.into_fungible(),
239 info: self.info,
240 }
241 }
242
243 pub async fn initial_seal(&mut self) -> Result<(), MemoryAllocationError> {
244 self.data.initial_seal().await
245 }
246
247 pub async fn final_seal(&mut self) -> Result<(), MemoryAllocationError> {
248 self.data.final_seal().await
249 }
250}
251
252#[derive(Debug, Default, Clone)]
253#[cfg_attr(feature = "external", derive(DeserializeDict, SerializeDict, Type))]
254#[cfg_attr(feature = "external", zvariant(signature = "dict"))]
255#[non_exhaustive]
256pub struct EditorOutputInfo {
257 pub lossless: bool,
262}