1 use serde::{
2 de::{self, DeserializeSeed, VariantAccess, Visitor},
3 Deserialize,
4 };
5 use static_assertions::assert_impl_all;
6
7 use std::{marker::PhantomData, os::unix::io::RawFd, str};
8
9 #[cfg(feature = "gvariant")]
10 use crate::gvariant::Deserializer as GVDeserializer;
11 use crate::{
12 dbus::Deserializer as DBusDeserializer, signature_parser::SignatureParser, utils::*, Basic,
13 DynamicDeserialize, DynamicType, EncodingContext, EncodingFormat, Error, Fd, ObjectPath,
14 Result, Signature, Type,
15 };
16
17 /// Deserialize `T` from a given slice of bytes, containing file descriptor indices.
18 ///
19 /// Please note that actual file descriptors are not part of the encoding and need to be transferred
20 /// via an out-of-band platform specific mechanism. The encoding only contain the indices of the
21 /// file descriptors and hence the reason, caller must pass a slice of file descriptors.
22 ///
23 /// # Examples
24 ///
25 /// ```
26 /// use zvariant::{to_bytes_fds, from_slice_fds};
27 /// use zvariant::{EncodingContext, Fd};
28 ///
29 /// let ctxt = EncodingContext::<byteorder::LE>::new_dbus(0);
30 /// let (encoded, fds) = to_bytes_fds(ctxt, &Fd::from(42)).unwrap();
31 /// let decoded: Fd = from_slice_fds(&encoded, Some(&fds), ctxt).unwrap();
32 /// assert_eq!(decoded, Fd::from(42));
33 /// ```
34 ///
35 /// [`from_slice`]: fn.from_slice.html
from_slice_fds<'d, 'r: 'd, B, T: ?Sized>( bytes: &'r [u8], fds: Option<&[RawFd]>, ctxt: EncodingContext<B>, ) -> Result<T> where B: byteorder::ByteOrder, T: Deserialize<'d> + Type,36 pub fn from_slice_fds<'d, 'r: 'd, B, T: ?Sized>(
37 bytes: &'r [u8],
38 fds: Option<&[RawFd]>,
39 ctxt: EncodingContext<B>,
40 ) -> Result<T>
41 where
42 B: byteorder::ByteOrder,
43 T: Deserialize<'d> + Type,
44 {
45 let signature = T::signature();
46 from_slice_fds_for_signature(bytes, fds, ctxt, &signature)
47 }
48
49 /// Deserialize `T` from a given slice of bytes.
50 ///
51 /// If `T` is an, or (potentially) contains an [`Fd`], use [`from_slice_fds`] instead.
52 ///
53 /// # Examples
54 ///
55 /// ```
56 /// use zvariant::{to_bytes, from_slice};
57 /// use zvariant::EncodingContext;
58 ///
59 /// let ctxt = EncodingContext::<byteorder::LE>::new_dbus(0);
60 /// let encoded = to_bytes(ctxt, "hello world").unwrap();
61 /// let decoded: &str = from_slice(&encoded, ctxt).unwrap();
62 /// assert_eq!(decoded, "hello world");
63 /// ```
64 ///
65 /// [`Fd`]: struct.Fd.html
66 /// [`from_slice_fds`]: fn.from_slice_fds.html
from_slice<'d, 'r: 'd, B, T: ?Sized>(bytes: &'r [u8], ctxt: EncodingContext<B>) -> Result<T> where B: byteorder::ByteOrder, T: Deserialize<'d> + Type,67 pub fn from_slice<'d, 'r: 'd, B, T: ?Sized>(bytes: &'r [u8], ctxt: EncodingContext<B>) -> Result<T>
68 where
69 B: byteorder::ByteOrder,
70 T: Deserialize<'d> + Type,
71 {
72 let signature = T::signature();
73 from_slice_for_signature(bytes, ctxt, &signature)
74 }
75
76 /// Deserialize `T` from a given slice of bytes with the given signature.
77 ///
78 /// Use this function instead of [`from_slice`] if the value being deserialized does not implement
79 /// [`Type`]. Also, if `T` is an, or (potentially) contains an [`Fd`], use
80 /// [`from_slice_fds_for_signature`] instead.
81 ///
82 /// # Examples
83 ///
84 /// One known case where `Type` implementation isn't possible, is enum types (except simple ones
85 /// with unit variants only).
86 ///
87 /// ```
88 /// use std::convert::TryInto;
89 /// use serde::{Deserialize, Serialize};
90 ///
91 /// use zvariant::{to_bytes_for_signature, from_slice_for_signature};
92 /// use zvariant::EncodingContext;
93 ///
94 /// #[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
95 /// enum Test {
96 /// Unit,
97 /// NewType(u8),
98 /// Tuple(u8, u64),
99 /// Struct { y: u8, t: u64 },
100 /// }
101 ///
102 /// let ctxt = EncodingContext::<byteorder::LE>::new_dbus(0);
103 /// let signature = "u".try_into().unwrap();
104 /// let encoded = to_bytes_for_signature(ctxt, &signature, &Test::Unit).unwrap();
105 /// let decoded: Test = from_slice_for_signature(&encoded, ctxt, &signature).unwrap();
106 /// assert_eq!(decoded, Test::Unit);
107 ///
108 /// let signature = "y".try_into().unwrap();
109 /// let encoded = to_bytes_for_signature(ctxt, &signature, &Test::NewType(42)).unwrap();
110 /// let decoded: Test = from_slice_for_signature(&encoded, ctxt, &signature).unwrap();
111 /// assert_eq!(decoded, Test::NewType(42));
112 ///
113 /// let signature = "(yt)".try_into().unwrap();
114 /// let encoded = to_bytes_for_signature(ctxt, &signature, &Test::Tuple(42, 42)).unwrap();
115 /// let decoded: Test = from_slice_for_signature(&encoded, ctxt, &signature).unwrap();
116 /// assert_eq!(decoded, Test::Tuple(42, 42));
117 ///
118 /// let s = Test::Struct { y: 42, t: 42 };
119 /// let encoded = to_bytes_for_signature(ctxt, &signature, &s).unwrap();
120 /// let decoded: Test = from_slice_for_signature(&encoded, ctxt, &signature).unwrap();
121 /// assert_eq!(decoded, Test::Struct { y: 42, t: 42 });
122 /// ```
123 ///
124 /// [`Type`]: trait.Type.html
125 /// [`Fd`]: struct.Fd.html
126 /// [`from_slice_fds_for_signature`]: fn.from_slice_fds_for_signature.html
127 // TODO: Return number of bytes parsed?
from_slice_for_signature<'d, 'r: 'd, B, T: ?Sized>( bytes: &'r [u8], ctxt: EncodingContext<B>, signature: &Signature<'_>, ) -> Result<T> where B: byteorder::ByteOrder, T: Deserialize<'d>,128 pub fn from_slice_for_signature<'d, 'r: 'd, B, T: ?Sized>(
129 bytes: &'r [u8],
130 ctxt: EncodingContext<B>,
131 signature: &Signature<'_>,
132 ) -> Result<T>
133 where
134 B: byteorder::ByteOrder,
135 T: Deserialize<'d>,
136 {
137 from_slice_fds_for_signature(bytes, None, ctxt, signature)
138 }
139
140 /// Deserialize `T` from a given slice of bytes containing file descriptor indices, with the given signature.
141 ///
142 /// Please note that actual file descriptors are not part of the encoding and need to be transferred
143 /// via an out-of-band platform specific mechanism. The encoding only contain the indices of the
144 /// file descriptors and hence the reason, caller must pass a slice of file descriptors.
145 ///
146 /// [`from_slice`]: fn.from_slice.html
147 /// [`from_slice_for_signature`]: fn.from_slice_for_signature.html
148 // TODO: Return number of bytes parsed?
from_slice_fds_for_signature<'d, 'r: 'd, B, T: ?Sized>( bytes: &'r [u8], fds: Option<&[RawFd]>, ctxt: EncodingContext<B>, signature: &Signature<'_>, ) -> Result<T> where B: byteorder::ByteOrder, T: Deserialize<'d>,149 pub fn from_slice_fds_for_signature<'d, 'r: 'd, B, T: ?Sized>(
150 bytes: &'r [u8],
151 fds: Option<&[RawFd]>,
152 ctxt: EncodingContext<B>,
153 signature: &Signature<'_>,
154 ) -> Result<T>
155 where
156 B: byteorder::ByteOrder,
157 T: Deserialize<'d>,
158 {
159 let mut de = match ctxt.format() {
160 #[cfg(feature = "gvariant")]
161 EncodingFormat::GVariant => {
162 Deserializer::GVariant(GVDeserializer::new(bytes, fds, signature, ctxt))
163 }
164 EncodingFormat::DBus => {
165 Deserializer::DBus(DBusDeserializer::new(bytes, fds, signature, ctxt))
166 }
167 };
168
169 T::deserialize(&mut de)
170 }
171
172 /// Deserialize `T` from a given slice of bytes containing file descriptor indices, with the given
173 /// signature.
174 ///
175 /// Please note that actual file descriptors are not part of the encoding and need to be transferred
176 /// via an out-of-band platform specific mechanism. The encoding only contain the indices of the
177 /// file descriptors and hence the reason, caller must pass a slice of file descriptors.
from_slice_for_dynamic_signature<'d, B, T>( bytes: &'d [u8], ctxt: EncodingContext<B>, signature: &Signature<'d>, ) -> Result<T> where B: byteorder::ByteOrder, T: DynamicDeserialize<'d>,178 pub fn from_slice_for_dynamic_signature<'d, B, T>(
179 bytes: &'d [u8],
180 ctxt: EncodingContext<B>,
181 signature: &Signature<'d>,
182 ) -> Result<T>
183 where
184 B: byteorder::ByteOrder,
185 T: DynamicDeserialize<'d>,
186 {
187 from_slice_fds_for_dynamic_signature(bytes, None, ctxt, signature)
188 }
189
190 /// Deserialize `T` from a given slice of bytes containing file descriptor indices, with the given
191 /// signature.
192 ///
193 /// Please note that actual file descriptors are not part of the encoding and need to be transferred
194 /// via an out-of-band platform specific mechanism. The encoding only contain the indices of the
195 /// file descriptors and hence the reason, caller must pass a slice of file descriptors.
from_slice_fds_for_dynamic_signature<'d, B, T>( bytes: &'d [u8], fds: Option<&[RawFd]>, ctxt: EncodingContext<B>, signature: &Signature<'d>, ) -> Result<T> where B: byteorder::ByteOrder, T: DynamicDeserialize<'d>,196 pub fn from_slice_fds_for_dynamic_signature<'d, B, T>(
197 bytes: &'d [u8],
198 fds: Option<&[RawFd]>,
199 ctxt: EncodingContext<B>,
200 signature: &Signature<'d>,
201 ) -> Result<T>
202 where
203 B: byteorder::ByteOrder,
204 T: DynamicDeserialize<'d>,
205 {
206 let seed = T::deserializer_for_signature(signature)?;
207
208 from_slice_fds_with_seed(bytes, fds, ctxt, seed)
209 }
210
211 /// Deserialize `T` from a given slice of bytes containing file descriptor indices, using the given
212 /// seed.
213 ///
214 /// Please note that actual file descriptors are not part of the encoding and need to be transferred
215 /// via an out-of-band platform specific mechanism. The encoding only contain the indices of the
216 /// file descriptors and hence the reason, caller must pass a slice of file descriptors.
from_slice_with_seed<'d, B, S>( bytes: &'d [u8], ctxt: EncodingContext<B>, seed: S, ) -> Result<S::Value> where B: byteorder::ByteOrder, S: DeserializeSeed<'d> + DynamicType,217 pub fn from_slice_with_seed<'d, B, S>(
218 bytes: &'d [u8],
219 ctxt: EncodingContext<B>,
220 seed: S,
221 ) -> Result<S::Value>
222 where
223 B: byteorder::ByteOrder,
224 S: DeserializeSeed<'d> + DynamicType,
225 {
226 from_slice_fds_with_seed(bytes, None, ctxt, seed)
227 }
228
229 /// Deserialize `T` from a given slice of bytes containing file descriptor indices, using the given
230 /// seed.
231 ///
232 /// Please note that actual file descriptors are not part of the encoding and need to be transferred
233 /// via an out-of-band platform specific mechanism. The encoding only contain the indices of the
234 /// file descriptors and hence the reason, caller must pass a slice of file descriptors.
from_slice_fds_with_seed<'d, B, S>( bytes: &'d [u8], fds: Option<&[RawFd]>, ctxt: EncodingContext<B>, seed: S, ) -> Result<S::Value> where B: byteorder::ByteOrder, S: DeserializeSeed<'d> + DynamicType,235 pub fn from_slice_fds_with_seed<'d, B, S>(
236 bytes: &'d [u8],
237 fds: Option<&[RawFd]>,
238 ctxt: EncodingContext<B>,
239 seed: S,
240 ) -> Result<S::Value>
241 where
242 B: byteorder::ByteOrder,
243 S: DeserializeSeed<'d> + DynamicType,
244 {
245 let signature = S::dynamic_signature(&seed).to_owned();
246
247 let mut de = match ctxt.format() {
248 #[cfg(feature = "gvariant")]
249 EncodingFormat::GVariant => {
250 Deserializer::GVariant(GVDeserializer::new(bytes, fds, &signature, ctxt))
251 }
252 EncodingFormat::DBus => {
253 Deserializer::DBus(DBusDeserializer::new(bytes, fds, &signature, ctxt))
254 }
255 };
256
257 seed.deserialize(&mut de)
258 }
259
260 /// Our deserialization implementation.
261 #[derive(Debug)]
262 pub(crate) struct DeserializerCommon<'de, 'sig, 'f, B> {
263 pub(crate) ctxt: EncodingContext<B>,
264 pub(crate) bytes: &'de [u8],
265 pub(crate) fds: Option<&'f [RawFd]>,
266 pub(crate) pos: usize,
267
268 pub(crate) sig_parser: SignatureParser<'sig>,
269
270 pub(crate) b: PhantomData<B>,
271 }
272
273 /// Our deserialization implementation.
274 ///
275 /// Using this deserializer involves an redirection to the actual deserializer. It's best
276 /// to use the serialization functions, e.g [`crate::to_bytes`] or specific serializers,
277 /// [`crate::dbus::Deserializer`] or [`crate::zvariant::Deserializer`].
278 pub enum Deserializer<'ser, 'sig, 'f, B> {
279 DBus(DBusDeserializer<'ser, 'sig, 'f, B>),
280 #[cfg(feature = "gvariant")]
281 GVariant(GVDeserializer<'ser, 'sig, 'f, B>),
282 }
283
284 assert_impl_all!(Deserializer<'_, '_, '_, u8>: Send, Sync, Unpin);
285
286 impl<'de, 'sig, 'f, B> Deserializer<'de, 'sig, 'f, B>
287 where
288 B: byteorder::ByteOrder,
289 {
290 /// Create a Deserializer struct instance.
new<'r: 'de>( bytes: &'r [u8], fds: Option<&'f [RawFd]>, signature: &Signature<'sig>, ctxt: EncodingContext<B>, ) -> Self291 pub fn new<'r: 'de>(
292 bytes: &'r [u8],
293 fds: Option<&'f [RawFd]>,
294 signature: &Signature<'sig>,
295 ctxt: EncodingContext<B>,
296 ) -> Self {
297 match ctxt.format() {
298 #[cfg(feature = "gvariant")]
299 EncodingFormat::GVariant => {
300 Self::GVariant(GVDeserializer::new(bytes, fds, signature, ctxt))
301 }
302 EncodingFormat::DBus => Self::DBus(DBusDeserializer::new(bytes, fds, signature, ctxt)),
303 }
304 }
305 }
306
307 impl<'de, 'sig, 'f, B> DeserializerCommon<'de, 'sig, 'f, B>
308 where
309 B: byteorder::ByteOrder,
310 {
get_fd(&self, idx: u32) -> Result<i32>311 pub fn get_fd(&self, idx: u32) -> Result<i32> {
312 self.fds
313 .map(|fds| fds.get(idx as usize))
314 .flatten()
315 .copied()
316 .ok_or(Error::UnknownFd)
317 }
318
parse_padding(&mut self, alignment: usize) -> Result<usize>319 pub fn parse_padding(&mut self, alignment: usize) -> Result<usize> {
320 let padding = padding_for_n_bytes(self.abs_pos(), alignment);
321 if padding > 0 {
322 if self.pos + padding > self.bytes.len() {
323 return Err(serde::de::Error::invalid_length(
324 self.bytes.len(),
325 &format!(">= {}", self.pos + padding).as_str(),
326 ));
327 }
328
329 for i in 0..padding {
330 let byte = self.bytes[self.pos + i];
331 if byte != 0 {
332 return Err(Error::PaddingNot0(byte));
333 }
334 }
335 self.pos += padding;
336 }
337
338 Ok(padding)
339 }
340
prep_deserialize_basic<T>(&mut self) -> Result<()> where T: Basic,341 pub fn prep_deserialize_basic<T>(&mut self) -> Result<()>
342 where
343 T: Basic,
344 {
345 self.sig_parser.skip_char()?;
346 self.parse_padding(T::alignment(self.ctxt.format()))?;
347
348 Ok(())
349 }
350
next_slice(&mut self, len: usize) -> Result<&'de [u8]>351 pub fn next_slice(&mut self, len: usize) -> Result<&'de [u8]> {
352 if self.pos + len > self.bytes.len() {
353 return Err(serde::de::Error::invalid_length(
354 self.bytes.len(),
355 &format!(">= {}", self.pos + len).as_str(),
356 ));
357 }
358
359 let slice = &self.bytes[self.pos..self.pos + len];
360 self.pos += len;
361
362 Ok(slice)
363 }
364
next_const_size_slice<T>(&mut self) -> Result<&[u8]> where T: Basic,365 pub fn next_const_size_slice<T>(&mut self) -> Result<&[u8]>
366 where
367 T: Basic,
368 {
369 self.prep_deserialize_basic::<T>()?;
370
371 self.next_slice(T::alignment(self.ctxt.format()))
372 }
373
abs_pos(&self) -> usize374 pub fn abs_pos(&self) -> usize {
375 self.ctxt.position() + self.pos
376 }
377 }
378
379 macro_rules! deserialize_method {
380 ($method:ident($($arg:ident: $type:ty),*)) => {
381 #[inline]
382 fn $method<V>(self, $($arg: $type,)* visitor: V) -> Result<V::Value>
383 where
384 V: Visitor<'de>,
385 {
386 match self {
387 #[cfg(feature = "gvariant")]
388 Deserializer::GVariant(de) => {
389 de.$method($($arg,)* visitor)
390 }
391 Deserializer::DBus(de) => {
392 de.$method($($arg,)* visitor)
393 }
394 }
395 }
396 }
397 }
398
399 impl<'de, 'd, 'sig, 'f, B> de::Deserializer<'de> for &'d mut Deserializer<'de, 'sig, 'f, B>
400 where
401 B: byteorder::ByteOrder,
402 {
403 type Error = Error;
404
405 deserialize_method!(deserialize_any());
406 deserialize_method!(deserialize_bool());
407 deserialize_method!(deserialize_i8());
408 deserialize_method!(deserialize_i16());
409 deserialize_method!(deserialize_i32());
410 deserialize_method!(deserialize_i64());
411 deserialize_method!(deserialize_u8());
412 deserialize_method!(deserialize_u16());
413 deserialize_method!(deserialize_u32());
414 deserialize_method!(deserialize_u64());
415 deserialize_method!(deserialize_f32());
416 deserialize_method!(deserialize_f64());
417 deserialize_method!(deserialize_char());
418 deserialize_method!(deserialize_str());
419 deserialize_method!(deserialize_string());
420 deserialize_method!(deserialize_bytes());
421 deserialize_method!(deserialize_byte_buf());
422 deserialize_method!(deserialize_option());
423 deserialize_method!(deserialize_unit());
424 deserialize_method!(deserialize_unit_struct(n: &'static str));
425 deserialize_method!(deserialize_newtype_struct(n: &'static str));
426 deserialize_method!(deserialize_seq());
427 deserialize_method!(deserialize_map());
428 deserialize_method!(deserialize_tuple(n: usize));
429 deserialize_method!(deserialize_tuple_struct(n: &'static str, l: usize));
430 deserialize_method!(deserialize_struct(
431 n: &'static str,
432 f: &'static [&'static str]
433 ));
434 deserialize_method!(deserialize_enum(
435 n: &'static str,
436 f: &'static [&'static str]
437 ));
438 deserialize_method!(deserialize_identifier());
439 deserialize_method!(deserialize_ignored_any());
440 }
441
442 #[derive(Debug)]
443 pub(crate) enum ValueParseStage {
444 Signature,
445 Value,
446 Done,
447 }
448
deserialize_any<'de, 'sig, 'f, B, D, V>( de: D, next_char: char, visitor: V, ) -> Result<V::Value> where D: de::Deserializer<'de, Error = Error>, V: Visitor<'de>, B: byteorder::ByteOrder,449 pub(crate) fn deserialize_any<'de, 'sig, 'f, B, D, V>(
450 de: D,
451 next_char: char,
452 visitor: V,
453 ) -> Result<V::Value>
454 where
455 D: de::Deserializer<'de, Error = Error>,
456 V: Visitor<'de>,
457 B: byteorder::ByteOrder,
458 {
459 match next_char {
460 u8::SIGNATURE_CHAR => de.deserialize_u8(visitor),
461 bool::SIGNATURE_CHAR => de.deserialize_bool(visitor),
462 i16::SIGNATURE_CHAR => de.deserialize_i16(visitor),
463 u16::SIGNATURE_CHAR => de.deserialize_u16(visitor),
464 i32::SIGNATURE_CHAR | Fd::SIGNATURE_CHAR => de.deserialize_i32(visitor),
465 u32::SIGNATURE_CHAR => de.deserialize_u32(visitor),
466 i64::SIGNATURE_CHAR => de.deserialize_i64(visitor),
467 u64::SIGNATURE_CHAR => de.deserialize_u64(visitor),
468 f64::SIGNATURE_CHAR => de.deserialize_f64(visitor),
469 <&str>::SIGNATURE_CHAR | ObjectPath::SIGNATURE_CHAR | Signature::SIGNATURE_CHAR => {
470 de.deserialize_str(visitor)
471 }
472 VARIANT_SIGNATURE_CHAR => de.deserialize_seq(visitor),
473 ARRAY_SIGNATURE_CHAR => de.deserialize_seq(visitor),
474 STRUCT_SIG_START_CHAR => de.deserialize_seq(visitor),
475 #[cfg(feature = "gvariant")]
476 MAYBE_SIGNATURE_CHAR => de.deserialize_option(visitor),
477 c => Err(de::Error::invalid_value(
478 de::Unexpected::Char(c),
479 &"a valid signature character",
480 )),
481 }
482 }
483
484 pub(crate) trait GetDeserializeCommon<'de, 'sig, 'f, B>
485 where
486 B: byteorder::ByteOrder,
487 {
common_mut<'d>(self) -> &'d mut DeserializerCommon<'de, 'sig, 'f, B> where Self: 'd488 fn common_mut<'d>(self) -> &'d mut DeserializerCommon<'de, 'sig, 'f, B>
489 where
490 Self: 'd;
491 }
492
493 // Enum handling is very generic so it can be here and specific deserializers can use this.
494 pub(crate) struct Enum<B, D> {
495 pub(crate) de: D,
496 pub(crate) name: &'static str,
497 pub(crate) phantom: PhantomData<B>,
498 }
499
500 impl<'de, 'sig, 'f, B, D> VariantAccess<'de> for Enum<B, D>
501 where
502 B: byteorder::ByteOrder,
503 D: de::Deserializer<'de, Error = Error> + GetDeserializeCommon<'de, 'sig, 'f, B>,
504 {
505 type Error = Error;
506
unit_variant(self) -> std::result::Result<(), Self::Error>507 fn unit_variant(self) -> std::result::Result<(), Self::Error> {
508 self.de.common_mut().sig_parser.skip_char()
509 }
510
newtype_variant_seed<T>(self, seed: T) -> Result<T::Value> where T: DeserializeSeed<'de>,511 fn newtype_variant_seed<T>(self, seed: T) -> Result<T::Value>
512 where
513 T: DeserializeSeed<'de>,
514 {
515 seed.deserialize(self.de)
516 }
517
tuple_variant<V>(self, _len: usize, visitor: V) -> Result<V::Value> where V: Visitor<'de>,518 fn tuple_variant<V>(self, _len: usize, visitor: V) -> Result<V::Value>
519 where
520 V: Visitor<'de>,
521 {
522 de::Deserializer::deserialize_struct(self.de, self.name, &[], visitor)
523 }
524
struct_variant<V>(self, fields: &'static [&'static str], visitor: V) -> Result<V::Value> where V: Visitor<'de>,525 fn struct_variant<V>(self, fields: &'static [&'static str], visitor: V) -> Result<V::Value>
526 where
527 V: Visitor<'de>,
528 {
529 de::Deserializer::deserialize_struct(self.de, self.name, fields, visitor)
530 }
531 }
532