serde icon indicating copy to clipboard operation
serde copied to clipboard

Add helper CowStrVisitor and CowBytesVisitor types

Open Mingun opened this issue 6 months ago • 4 comments

As all known, when you deserialize Cow, it will always be deserialized as Owned, which makes it difficult to implement effective deserialization when you manually want to deserialize Cow<str> or Cow<[u8]>. This PR adds two helper types, CowStrVisitor and CowBytesVisitor, which both serves as a Visitor and a DeserializeSeed and allows you to read borrowed data from, for example, MapAccess:

use serde::de::{DeserializeSeed, Deserializer, MapAccess, Visitor};
use serde::de::value::CowStrVisitor;
use std::borrow::Cow;

/// A simple XML DOM node.
struct Element<'a> {
    name: Cow<'a, str>,
    children: Vec<Node<'a>>,
}
enum Node<'a> {
    Text(Cow<'a, str>),
    Element(Element<'a>),
}

impl<'de> Visitor<'de> for Element<'de> {
    type Value = Self;

    fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        f.write_str("a map")
    }

    fn visit_map<A>(mut self, mut map: A) -> Result<Self::Value, A::Error>
    where
        A: MapAccess<'de>,
    {
        while let Some(key) = map.next_key_seed(CowStrVisitor)? {
            if "$text" == key {
                let text = map.next_value_seed(CowStrVisitor)?;
                self.children.push(Node::Text(text));
            } else {
                let elem = Element { name: key, children: Vec::new() };
                let elem = map.next_value_seed(elem)?;
                self.children.push(Node::Element(elem));
            }
        }
        Ok(self)
    }
}

impl<'de> DeserializeSeed<'de> for Element<'de> {
    type Value = Self;

    fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
    where
        D: Deserializer<'de>,
    {
        deserializer.deserialize_map(self)
    }
}

Mingun avatar May 08 '25 07:05 Mingun

Doctests is not enough?

Mingun avatar May 08 '25 10:05 Mingun

They just test compilation, not execution actually producing Cow::Borrowed

oli-obk avatar May 08 '25 10:05 oli-obk

Ah, yes. Will be soon

Mingun avatar May 08 '25 10:05 Mingun

@dtolnay this seems like a good addition to serde. even if it could live out of tree, it's for basic libstd types

oli-obk avatar May 08 '25 16:05 oli-obk