0

I'm deserialising using Serde and I want to take advantage of the zero-copy functionality while using a streaming iterator which returns a reference to the current value. This reference is valid until advance is called on the iterator.

use serde::Deserialize;
use streaming_iterator::StreamingIterator;

struct Iterator<'i> {
    owned_value: String,
    message: Option<Message<'i>>
}

#[derive(Deserialize, Debug)]
struct Message<'i> {
    content: &'i str
}

fn convert<'c>(input: &'c str) -> Message<'c> {
    serde_json::from_str(input).unwrap()
}

impl<'i> StreamingIterator for Iterator<'i> {
    type Item = Message<'i>;

    fn advance(&mut self) {
        self.message = Some(convert(&self.owned_value))
    }

    fn get(&self) -> Option<&Self::Item> {
        Some(&self.message.unwrap())
    }
}

fn main() {
    let data = r#"
        {
            "content": "Hello world",
        }"#;

    let iter = Iterator{owned_value: String::from(data), message: None};
    println!("{}", iter.get().unwrap().content);
}

cargo.toml

[dependencies]
serde = {version = "1.0", features = ["derive"]}
serde_json = "1.0"
streaming-iterator = "0.1.4"

The compiler complains

cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
  --> src\main.rs:22:37
   |
22 |         self.message = Some(convert(&self.owned_value))
   |                                     ^^^^^^^^^^^^^^^^^
   |
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 21:5...
  --> src\main.rs:21:5
   |
21 | /     fn advance(&mut self) {
22 | |         self.message = Some(convert(&self.owned_value))
23 | |     }
   | |_____^
note: ...so that reference does not outlive borrowed content
  --> src\main.rs:22:37
   |
22 |         self.message = Some(convert(&self.owned_value))
   |                                     ^^^^^^^^^^^^^^^^^
note: but, the lifetime must be valid for the lifetime 'i as defined on the impl at 18:6...
  --> src\main.rs:18:6
   |
18 | impl<'i> StreamingIterator for Iterator<'i> {
   |      ^^
   = note: ...so that the expression is assignable:
           expected std::option::Option<Message<'i>>
              found std::option::Option<Message<'_>>

From what I can tell, this is because the compiler is unable to prove that a reference to self will last long enough

Is what I am trying to do possible? Is there a way I can prove to the borrow checker that as long as there is a reference to self then any references returned from get are valid?

ali2992
  • 129
  • 1
  • 2
  • 8
  • 1
    Can you please provide a [Minimal, Reproducible Example](https://stackoverflow.com/help/minimal-reproducible-example)? – Peter Varo Aug 19 '19 at 15:19
  • Highly likely to be a duplicate of [Why can't I store a value and a reference to that value in the same struct?](https://stackoverflow.com/q/32300132/155423). – Shepmaster Aug 19 '19 at 15:25
  • Possible duplicate of [Why can't I store a value and a reference to that value in the same struct?](https://stackoverflow.com/questions/32300132/why-cant-i-store-a-value-and-a-reference-to-that-value-in-the-same-struct) – E_net4 Aug 20 '19 at 10:19
  • While this is a duplicate as pointed out already, in this specific instance, using a `str` reference with the same lifetime as your message instead of an owned `String` in `Iterator` makes more sense. – CodenameLambda Aug 20 '19 at 17:55

0 Answers0