Skip to content

Commit 3479d6a

Browse files
committed
glib: Add optional support for serialization and deserialization with serde
This feature is gated as `serde` Supports both serialization and deserialization: - glib::Bytes - glib::GString - glib::PtrSlice<_> - glib::Slice<_> - glib::List<_> - glib::SList<_> Supports serialization only: - glib::ByteArray - glib::GStr - glib::StrV Collection types are also supported as long as the type parameters implement the necessary traits: - glib::PtrSlice<T: TransparentPtrType + _> - glib::Slice<T: TransparentType + _> - glib::List<T: TransparentPtrType + _> - glib::SList<T: TransparentPtrType + _>
1 parent 7f9a20b commit 3479d6a

File tree

3 files changed

+365
-0
lines changed

3 files changed

+365
-0
lines changed

glib/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ smallvec = "1.0"
3535
thiserror = "1"
3636
gio_ffi = { package = "gio-sys", path = "../gio/sys", optional = true }
3737
memchr = "2.5.0"
38+
serde = { version = "1.0", optional = true }
3839

3940
[dev-dependencies]
4041
tempfile = "3"
@@ -59,6 +60,7 @@ log_macros = ["log"]
5960
dox = ["ffi/dox", "gobject_ffi/dox", "log_macros"]
6061
compiletests = []
6162
gio = ["gio_ffi"]
63+
serde = ["dep:serde"]
6264

6365
[package.metadata.docs.rs]
6466
features = ["dox"]

glib/src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,9 @@ pub use self::thread_pool::{ThreadHandle, ThreadPool};
213213

214214
pub mod thread_guard;
215215

216+
#[cfg(feature = "serde")]
217+
mod serde;
218+
216219
// rustdoc-stripper-ignore-next
217220
/// This is the log domain used by the [`clone!`][crate::clone!] macro. If you want to use a custom
218221
/// logger (it prints to stdout by default), you can set your own logger using the corresponding

glib/src/serde.rs

Lines changed: 360 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,360 @@
1+
use serde::{
2+
de::{self, Visitor},
3+
Deserialize, Serialize,
4+
};
5+
6+
mod byte_array {
7+
use crate::ByteArray;
8+
9+
use super::*;
10+
11+
impl Serialize for ByteArray {
12+
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
13+
where
14+
S: serde::Serializer,
15+
{
16+
serializer.serialize_bytes(self)
17+
}
18+
}
19+
}
20+
21+
mod bytes {
22+
use crate::Bytes;
23+
24+
use super::*;
25+
26+
impl Serialize for Bytes {
27+
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
28+
where
29+
S: serde::Serializer,
30+
{
31+
serializer.serialize_bytes(self)
32+
}
33+
}
34+
35+
struct BytesVisitor;
36+
37+
impl<'a> Visitor<'a> for BytesVisitor {
38+
type Value = Bytes;
39+
40+
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
41+
formatter.write_str("an array of bytes")
42+
}
43+
44+
fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
45+
where
46+
E: de::Error,
47+
{
48+
Ok(Bytes::from_owned(v.to_owned()))
49+
}
50+
51+
fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E>
52+
where
53+
E: de::Error,
54+
{
55+
Ok(Bytes::from_owned(v))
56+
}
57+
58+
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
59+
where
60+
A: de::SeqAccess<'a>,
61+
{
62+
let mut byte_vec = vec![];
63+
64+
while let Some(_size @ 1..) = seq.size_hint() {
65+
match seq.next_element()? {
66+
Some(byte) => byte_vec.push(byte),
67+
None => break,
68+
}
69+
}
70+
71+
Ok(Bytes::from_owned(byte_vec))
72+
}
73+
}
74+
75+
impl<'de> Deserialize<'de> for Bytes {
76+
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
77+
where
78+
D: serde::Deserializer<'de>,
79+
{
80+
deserializer.deserialize_seq(BytesVisitor)
81+
}
82+
}
83+
}
84+
85+
mod gstring {
86+
use super::*;
87+
88+
use std::fmt;
89+
90+
use crate::{GStr, GString, GStringPtr};
91+
92+
impl Serialize for GStr {
93+
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
94+
where
95+
S: serde::Serializer,
96+
{
97+
serializer.serialize_str(self.as_str())
98+
}
99+
}
100+
101+
impl Serialize for GString {
102+
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
103+
where
104+
S: serde::Serializer,
105+
{
106+
serializer.serialize_str(self.as_str())
107+
}
108+
}
109+
110+
struct GStringVisitor;
111+
112+
impl<'a> Visitor<'a> for GStringVisitor {
113+
type Value = GString;
114+
115+
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
116+
formatter.write_str("a GString")
117+
}
118+
119+
fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
120+
where
121+
E: de::Error,
122+
{
123+
GString::from_string_checked(v).map_err(|e| de::Error::custom(e))
124+
}
125+
126+
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
127+
where
128+
E: de::Error,
129+
{
130+
Ok(GString::from(v))
131+
}
132+
}
133+
134+
impl<'de> Deserialize<'de> for GString {
135+
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
136+
where
137+
D: serde::Deserializer<'de>,
138+
{
139+
// String to GString conversion is pretty much a zero-alloc op, so this gets used instead
140+
deserializer.deserialize_string(GStringVisitor)
141+
}
142+
}
143+
144+
impl Serialize for GStringPtr {
145+
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
146+
where
147+
S: serde::Serializer,
148+
{
149+
serializer.serialize_str(self.to_str())
150+
}
151+
}
152+
}
153+
154+
mod collections {
155+
use super::*;
156+
157+
use crate::{
158+
translate::{TransparentPtrType, TransparentType},
159+
List, PtrSlice, SList, Slice, StrV,
160+
};
161+
162+
impl<T: Serialize + TransparentPtrType> Serialize for PtrSlice<T> {
163+
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
164+
where
165+
S: serde::Serializer,
166+
{
167+
serializer.collect_seq(self)
168+
}
169+
}
170+
171+
struct PtrSliceVisitor<'v, T: Deserialize<'v> + TransparentPtrType>(
172+
std::marker::PhantomData<&'v T>,
173+
);
174+
175+
impl<'a, T: Deserialize<'a> + TransparentPtrType> Visitor<'a> for PtrSliceVisitor<'a, T> {
176+
type Value = PtrSlice<T>;
177+
178+
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
179+
formatter.write_str("a sequence of GLib transparent pointer values")
180+
}
181+
182+
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
183+
where
184+
A: de::SeqAccess<'a>,
185+
{
186+
let mut ret = PtrSlice::new();
187+
188+
while let Some(_size @ 1..) = seq.size_hint() {
189+
ret.push(match seq.next_element()? {
190+
Some(item) => item,
191+
None => break,
192+
})
193+
}
194+
195+
Ok(ret)
196+
}
197+
}
198+
199+
impl<'de: 'a, 'a: 'de, T: 'de + Deserialize<'a> + TransparentPtrType> Deserialize<'de>
200+
for PtrSlice<T>
201+
{
202+
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
203+
where
204+
D: serde::Deserializer<'de>,
205+
{
206+
deserializer.deserialize_seq(PtrSliceVisitor(Default::default()))
207+
}
208+
}
209+
210+
impl<T: Serialize + TransparentType> Serialize for Slice<T> {
211+
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
212+
where
213+
S: serde::Serializer,
214+
{
215+
serializer.collect_seq(self)
216+
}
217+
}
218+
219+
struct SliceVisitor<'v, T: Deserialize<'v>>(std::marker::PhantomData<&'v T>);
220+
221+
impl<'a, T: Deserialize<'a> + TransparentType> Visitor<'a> for SliceVisitor<'a, T> {
222+
type Value = Slice<T>;
223+
224+
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
225+
formatter.write_str("a sequence of GLib transparent values")
226+
}
227+
228+
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
229+
where
230+
A: de::SeqAccess<'a>,
231+
{
232+
let mut ret = Slice::new();
233+
234+
while let Some(_size @ 1..) = seq.size_hint() {
235+
ret.push(match seq.next_element()? {
236+
Some(item) => item,
237+
None => break,
238+
})
239+
}
240+
241+
Ok(ret)
242+
}
243+
}
244+
245+
impl<'de: 'a, 'a: 'de, T: 'de + Deserialize<'a> + TransparentType> Deserialize<'de> for Slice<T> {
246+
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
247+
where
248+
D: serde::Deserializer<'de>,
249+
{
250+
deserializer.deserialize_seq(SliceVisitor(Default::default()))
251+
}
252+
}
253+
254+
impl<T: Serialize + TransparentPtrType> Serialize for List<T> {
255+
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
256+
where
257+
S: serde::Serializer,
258+
{
259+
serializer.collect_seq(self.iter())
260+
}
261+
}
262+
263+
struct ListVisitor<'v, T: Deserialize<'v> + TransparentPtrType>(
264+
std::marker::PhantomData<&'v T>,
265+
);
266+
267+
impl<'a, T: Deserialize<'a> + TransparentPtrType> Visitor<'a> for ListVisitor<'a, T> {
268+
type Value = List<T>;
269+
270+
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
271+
formatter.write_str("a sequence of GLib transparent pointer values")
272+
}
273+
274+
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
275+
where
276+
A: de::SeqAccess<'a>,
277+
{
278+
let mut ret = List::new();
279+
280+
while let Some(_size @ 1..) = seq.size_hint() {
281+
ret.push_front(match seq.next_element()? {
282+
Some(item) => item,
283+
None => break,
284+
})
285+
}
286+
287+
ret.reverse();
288+
289+
Ok(ret)
290+
}
291+
}
292+
293+
impl<'de: 'a, 'a: 'de, T: 'de + Deserialize<'a> + TransparentPtrType> Deserialize<'de> for List<T> {
294+
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
295+
where
296+
D: serde::Deserializer<'de>,
297+
{
298+
deserializer.deserialize_seq(ListVisitor(Default::default()))
299+
}
300+
}
301+
302+
impl<T: Serialize + TransparentPtrType> Serialize for SList<T> {
303+
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
304+
where
305+
S: serde::Serializer,
306+
{
307+
serializer.collect_seq(self.iter())
308+
}
309+
}
310+
311+
struct SListVisitor<'v, T: Deserialize<'v> + TransparentPtrType>(
312+
std::marker::PhantomData<&'v T>,
313+
);
314+
315+
impl<'a, T: Deserialize<'a> + TransparentPtrType> Visitor<'a> for SListVisitor<'a, T> {
316+
type Value = SList<T>;
317+
318+
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
319+
formatter.write_str("a sequence of GLib transparent pointer values")
320+
}
321+
322+
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
323+
where
324+
A: de::SeqAccess<'a>,
325+
{
326+
let mut ret = SList::new();
327+
328+
while let Some(_size @ 1..) = seq.size_hint() {
329+
ret.push_front(match seq.next_element()? {
330+
Some(item) => item,
331+
None => break,
332+
})
333+
}
334+
335+
ret.reverse();
336+
337+
Ok(ret)
338+
}
339+
}
340+
341+
impl<'de: 'a, 'a: 'de, T: 'de + Deserialize<'a> + TransparentPtrType> Deserialize<'de>
342+
for SList<T>
343+
{
344+
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
345+
where
346+
D: serde::Deserializer<'de>,
347+
{
348+
deserializer.deserialize_seq(SListVisitor(Default::default()))
349+
}
350+
}
351+
352+
impl Serialize for StrV {
353+
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
354+
where
355+
S: serde::Serializer,
356+
{
357+
serializer.collect_seq(self)
358+
}
359+
}
360+
}

0 commit comments

Comments
 (0)