Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can't find a way to repeat value #2630

Open
zoryamba opened this issue Oct 16, 2023 · 1 comment
Open

Can't find a way to repeat value #2630

zoryamba opened this issue Oct 16, 2023 · 1 comment

Comments

@zoryamba
Copy link

Hi everyone.
Have to say, that I'm pretty new to Rust, so my question may be quite amateur.
I'm trying to implement serde for zipson format. You can find details here: https://www.npmjs.com/package/zipson
There is repeat feature, þ char means repeat last item. So that |¨aaa¨þþ÷ should be parsed as ["aaa", "aaa", "aaa"].

The most obvious way is to make it in SeqAccess implementation, so i desided to store last_elem ref in my SeqAccess and return it in case I see þ char.

struct SeqAccess<'a, 'de: 'a> {
    de: &'a mut Deserializer<'de>,
    last_element: Value,
}

impl<'a, 'de: 'a> SeqAccess<'a, 'de> {
    fn new(de: &'a mut Deserializer<'de>) -> Self {
        SeqAccess {
            de,
            last_element: Value::Undefined
        }
    }
}

impl<'de, 'a> de::SeqAccess<'de> for SeqAccess<'a, 'de> {
    type Error = Error;

    fn next_element_seed<T>(&mut self, seed: T) -> std::result::Result<Option<T::Value>, Self::Error>
        where T: DeserializeSeed<'de>
    {
        match self.de.peek_char()? {
            ARRAY_END_TOKEN => {
                self.de.next_char()?;
                Ok(None)
            }
            ARRAY_REPEAT_TOKEN => {
                self.de.next_char()?;
                Ok(Some(self.last_element.clone()))
            }
            _ => Ok(Some(seed.deserialize(&mut *self.de)?))
        }
    }
}

Unfortunately I'm getting compillation error:

error[E0308]: mismatched types
   --> src/de.rs:661:25
    |
661 |                 Ok(Some(self.last_element.clone()))
    |                    ---- ^^^^^^^^^^^^^^^^^^^^^^^^^ expected associated type, found `Value`
    |                    |
    |                    arguments to this enum variant are incorrect
    |
    = note: expected associated type `<T as DeserializeSeed<'de>>::Value`
                          found enum `Value`
help: the type constructed contains `Value` due to the type of the argument passed
   --> src/de.rs:661:20
    |
661 |                 Ok(Some(self.last_element.clone()))
    |                    ^^^^^-------------------------^
    |                         |
    |                         this argument influences the type of `Some`
note: tuple variant defined here
   --> /Users/zoryamba/.rustup/toolchains/stable-aarch64-apple-darwin/lib/rustlib/src/rust/library/core/src/option.rs:571:5
    |
571 |     Some(#[stable(feature = "rust1", since = "1.0.0")] T),
    |     ^^^^
help: consider constraining the associated type `<T as DeserializeSeed<'de>>::Value` to `Value`
    |
652 |         where T: DeserializeSeed<'de, Value = Value>
    |                                     +++++++++++++++

Tried to constrain Value for DeserializeSeed:

    fn next_element_seed<T>(&mut self, seed: T) -> std::result::Result<Option<T::Value>, Self::Error>
        where T: DeserializeSeed<'de, Value = Value>

It also didn't help:

error[E0271]: type mismatch resolving `<T as DeserializeSeed<'de>>::Value == Value`
    --> src/de.rs:652:39
     |
652  |         where T: DeserializeSeed<'de, Value = Value>
     |                                       ^^^^^^^^^^^^^ expected associated type, found `Value`
     |
     = note: expected associated type `<T as DeserializeSeed<'de>>::Value`
                           found enum `Value`
note: the requirement `<T as DeserializeSeed<'de>>::Value == Value` appears on the `impl`'s method `next_element_seed` but not on the corresponding trait's method
    --> /Users/zoryamba/.cargo/registry/src/index.crates.io-6f17d22bba15001f/serde-1.0.188/src/de/mod.rs:1712:8
     |
1702 | pub trait SeqAccess<'de> {
     |           --------- in this trait
...
1712 |     fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error>
     |        ^^^^^^^^^^^^^^^^^ this trait's method doesn't have the requirement `<T as DeserializeSeed<'de>>::Value == Value`

I tried to implement own DeseriealizeSeed, but it's deserialize method requires Deserializer trait:

fn deserialize<D>(self, deserializer: D) -> std::result::Result<Self::Value, D::Error>
        where D: de::Deserializer<'de>

So that i can't use my deserializer custom methods like next_char of peek_char.

So my question is: Is it possible to achieve what I want? And what is most convenient method to do that?
Thank you!

@zoryamba
Copy link
Author

As I understand is SeqAccess trait was generic itself, it would be possible to do such a trick:

pub trait SeqAccess<'de, V> {
    fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error>
    where
        T: DeserializeSeed<'de Value = V>;
}

struct SeqAccess<'a, 'de: 'a, V> {
    de: &'a mut Deserializer<'de>,
    last_element: V,
}

Wouldn't that be useful?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

1 participant