stack overflow with wrongly derived deserialize implementation
I was trying to follow along with @bilelmoussaoui's excellent post, for making a file chooser dialog, but I got stuck deserializing the response.
The short version is that I was mistakenly using #[derive(serde::Deserialize)]
when I should have been using #[derive(zvariant_derive::DeserializeDict)]
. So 100% my fault, but it would be nice if there were a more helpful error than a stack overflow.
The longer version is that my structs that I was trying to deserialize into were:
#[derive(serde::Deserialize, Debug)]
struct ResponseResult(u32, Response);
#[derive(serde::Deserialize, Debug)]
struct Response {
uris: Vec<String>,
choices: Option<Vec<(String, String)>>,
}
And here is a small, cyclic, portion of the backtrace:
#18211 0x000055555565457f in zvariant::de::deserialize_any<byteorder::LittleEndian,&mut zvariant::dbus::de::Deserializer<byteorder::LittleEndian>,serde::de::ignored_any::IgnoredAny> (de=0x7fffffff9e10, next_char=118 'v', visitor=...) at /home/jneeman/.cargo/git/checkouts/zbus-e0109d69954ffaa9/cf489ca/zvariant/src/de.rs:380
#18212 0x00005555555e6f7c in zvariant::dbus::de::{{impl}}::deserialize_any<byteorder::LittleEndian,serde::de::ignored_any::IgnoredAny> (self=0x7fffffff9e10, visitor=...) at /home/jneeman/.cargo/git/checkouts/zbus-e0109d69954ffaa9/cf489ca/zvariant/src/dbus/de.rs:81
#18213 0x00005555555f7ce6 in zvariant::dbus::de::{{impl}}::deserialize_ignored_any<byteorder::LittleEndian,serde::de::ignored_any::IgnoredAny> (self=0x7fffffff9e10, visitor=...) at /home/jneeman/.cargo/git/checkouts/zbus-e0109d69954ffaa9/cf489ca/zvariant/src/dbus/de.rs:64
#18214 0x0000555555617b97 in serde::de::ignored_any::{{impl}}::deserialize<&mut zvariant::dbus::de::Deserializer<byteorder::LittleEndian>> (deserializer=0x7fffffff9e10) at /home/jneeman/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.125/src/de/ignored_any.rs:241
#18215 0x00005555556e3246 in serde::de::{{impl}}::deserialize<serde::de::ignored_any::IgnoredAny,&mut zvariant::dbus::de::Deserializer<byteorder::LittleEndian>> (self=..., deserializer=0x7fffffff9e10) at /home/jneeman/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.125/src/de/mod.rs:785
#18216 0x00005555555cae2d in zvariant::dbus::de::{{impl}}::next_element_seed<byteorder::LittleEndian,core::marker::PhantomData<serde::de::ignored_any::IgnoredAny>> (self=0x7fffffff73c0, seed=...) at /home/jneeman/.cargo/git/checkouts/zbus-e0109d69954ffaa9/cf489ca/zvariant/src/dbus/de.rs:536
#18217 0x00005555555c5067 in serde::de::SeqAccess::next_element<zvariant::dbus::de::ValueDeserializer<byteorder::LittleEndian>,serde::de::ignored_any::IgnoredAny> (self=0x7fffffff73c0) at /home/jneeman/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.125/src/de/mod.rs:1707
#18218 0x00005555556176f9 in serde::de::ignored_any::{{impl}}::visit_seq<zvariant::dbus::de::ValueDeserializer<byteorder::LittleEndian>> (self=..., seq=...) at /home/jneeman/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.125/src/de/ignored_any.rs:201
#18219 0x00005555555ec448 in zvariant::dbus::de::{{impl}}::deserialize_seq<byteorder::LittleEndian,serde::de::ignored_any::IgnoredAny> (self=0x7fffffff9e10, visitor=...) at /home/jneeman/.cargo/git/checkouts/zbus-e0109d69954ffaa9/cf489ca/zvariant/src/dbus/de.rs:258
#18220 0x000055555565457f in zvariant::de::deserialize_any<byteorder::LittleEndian,&mut zvariant::dbus::de::Deserializer<byteorder::LittleEndian>,serde::de::ignored_any::IgnoredAny> (de=0x7fffffff9e10, next_char=118 'v', visitor=...) at /home/jneeman/.cargo/git/checkouts/zbus-e0109d69954ffaa9/cf489ca/zvariant/src/de.rs:380
The full code follows, and works with zbus 2.0.0-beta.3 (or git main)
use std::collections::HashMap;
use zbus::{dbus_proxy, fdo, Connection};
use zvariant::{OwnedObjectPath, OwnedValue, Value};
#[derive(serde::Deserialize, Debug)]
// no stack overflow if I use this instead.
// struct ResponseResult(u32, HashMap<String, OwnedValue>);
struct ResponseResult(u32, Response);
#[derive(serde::Deserialize, Debug)]
struct Response {
uris: Vec<String>,
choices: Option<Vec<(String, String)>>,
}
impl zvariant::Type for Response {
fn signature() -> zvariant::Signature<'static> {
<HashMap<&str, OwnedValue>>::signature()
}
}
impl zvariant::Type for ResponseResult {
fn signature() -> zvariant::Signature<'static> {
<(u32, Response)>::signature()
}
}
#[dbus_proxy(
interface = "org.freedesktop.portal.FileChooser",
default_service = "org.freedesktop.portal.Desktop",
default_path = "/org/freedesktop/portal/desktop"
)]
trait FileChooser {
fn open_file(
&self,
parent_window: &str,
title: &str,
options: HashMap<&str, &Value<'_>>,
) -> fdo::Result<OwnedObjectPath>;
}
fn main() -> fdo::Result<()> {
let connection = Connection::new_session()?;
let proxy = FileChooserProxy::new(&connection);
let reply = proxy.open_file("", "Title", HashMap::new())?;
dbg!(reply);
loop {
let msg = connection.receive_message()?;
let msg_header = msg.header()?;
if msg_header.message_type()? == zbus::MessageType::Signal
&& msg_header.member()? == Some("Response")
{
dbg!(msg.body_signature()?);
dbg!(msg.body::<ResponseResult>()?);
break;
}
}
Ok(())
}