softprops / recap

deserialize typed structures from regex captures
MIT License
167 stars 12 forks source link

RFE: Capture borrowed types #2

Closed cuviper closed 1 year ago

cuviper commented 5 years ago

💡 Feature description

It would be nice to be able to capture referenced data, like a more general Deserialize<'de> rather than just DeserializeOwned.

I realize that FromStr can't borrow data, since there's no lifetime parameter to use in relation to Self, but maybe there could be a trait Recap<'s> which does permit borrowing. I would think recap::from_captures could just use a 'de parameter for D: Deserialize<'de>.

💻 Basic example

I tried to write something like this for Advent of Code 2015 day 9:

#[derive(Deserialize, Recap)]
#[recap(regex = r"(?P<a>\w+) to (?P<b>\w+) = (?P<distance>\d+)")]
struct Distance<'a> {
    a: &'a str,
    b: &'a str,
    distance: u32,
}
error: implementation of `_IMPL_DESERIALIZE_FOR_Distance::_serde::Deserialize` is not general enough
[...]
   = note: `Distance<'_>` must implement `_IMPL_DESERIALIZE_FOR_Distance::_serde::Deserialize<'0>`, for any lifetime `'0`
   = note: but `Distance<'_>` actually implements `_IMPL_DESERIALIZE_FOR_Distance::_serde::Deserialize<'1>`, for some specific lifetime `'1`

It's not a big deal to use String instead in this case, since there aren't very many inputs overall, but it seems like a borrowed &str should be possible.

softprops commented 5 years ago

neat idea. I'll look into this next weekend

Ten0 commented 1 year ago

It looks like we have:

impl<'a: 'de, 'de> de::Deserializer<'de> for Val<'a> {
    type Error = Error;
    fn deserialize_any<V>(
        self,
        visitor: V,
    ) -> Result<V::Value>
    where
        V: de::Visitor<'de>,
    {
        BorrowedStrDeserializer::new(self.1).deserialize_any(visitor)
    }

in the current code of the crate, so this should work no?

cuviper commented 1 year ago

Cool! It looks like that was #13, and my original example does compile now.