尝试在 Cloudflare Workers 中使用 serde 进行零复制反序列化时出错

Error trying to zero-copy deserialize using serde in Cloudflare workers

提问人:Lu_ 提问时间:10/27/2023 最后编辑:John KugelmanLu_ 更新时间:11/3/2023 访问量:68

问:

我有一个结构,其中包含与结构本身具有相同生存期注释的结构。当我尝试调用该方法时,该方法应该查询我的数据库并将值解析为类型,我得到“'反序列化'的实现不够通用”。&strfirst::<T>(None)worker::d1::D1PreparedStatementT

这是我的一些代码:

use worker::;
use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize)]
pub struct User<'a> {
    #[serde(with = "uuid_as_string")]
    uuid: Uuid,
    name: &'a str,
    display_name: &'a str,
    profile_text: &'a str,
    profile_picture_url: &'a str,
    email_address: &'a str,
    password: &'a str,
    created: usize,
    deleted: usize,
    timezone: isize,
}

mod uuid_as_string {
    use serde::{self, Deserialize, Deserializer, Serializer};
    use uuid::Uuid;

    pub fn serialize<S>(uuid: &Uuid, serializer: S) -> Result<S::Ok, S::Error>
        where
            S: Serializer,
    {
        serializer.serialize_str(&uuid.to_string())
    }

    pub fn deserialize<'a, D>(deserializer: D) -> Result<Uuid, D::Error>
        where
            D: Deserializer<'a>,
    {
        let s = String::deserialize(deserializer)?;
        Uuid::parse_str(&s).map_err(serde::de::Error::custom)
    }
}

#[event(fetch, respond_with_errors)]
pub async fn main(request: Request, env: Env, _ctx: Context) -> Result<Response> {
    Router::new()
        .getasync("/", |, ctx| async move {
            let d1 = ctx.env.d1("D1_DATABASE")?;
            let statement = d1.prepare("SELECT FROM users");
            match statement.first::<User>(None).await? {
                Some(user) => Response::from_json(&user),
                None => Response::error("Not found", 404),
            }
        })
        .run(request, env)
        .await
}

我尝试完全删除字段和用于处理它的模块,但它没有改变任何东西。Uuid

Rust 后端 WebAssembly serde cloudflare-workers

评论

1赞 Kevin Reid 10/27/2023
我们需要更多的信息。请在打印时发布错误消息的全文。cargo check
0赞 Chayim Friedman 10/27/2023
什么 ?是工人板条箱吗?worker
1赞 Colonel Thirty Two 10/28/2023
顺便说一句,该功能实现了 serde 特征 - 无需使用您的模块重新发明轮子。uuidserdeuuid_as_string

答:

1赞 Anders Evensen 11/3/2023 #1

问题是在这种情况下,您不能进行零拷贝反序列化。workers::d 1::D 1PreparedStatement::first() 的签名如下:

pub async fn first<T>(&self, col_name: Option<&str>) -> Result<Option<T>>
where
    T: for<'a> Deserialize<'a>,
{
    // ...
}

这意味着必须拥有反序列化(请注意,这正是实现方式),因此“可以在不从反序列化程序中借用任何数据的情况下进行反序列化”。where T: for<'a> Deserialize<'a>DeserializeOwned

您必须从结构中删除借用才能在此上下文中使用它,也许可以通过将字段替换为 owned s。&'a strString