Skip to content

Commit 6c67b19

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 6c67b19

File tree

3 files changed

+367
-0
lines changed

3 files changed

+367
-0
lines changed

glib/Cargo.toml

+2
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

+3
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

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

0 commit comments

Comments
 (0)