0

I am writing a line wrapping program with the textwrap library and want to store unwrapped and wrapped lines under different structs. Code:

struct Lines<'a> {
    opt: textwrap::Options<'a>,
    buf: String,
}

impl<'a> Lines<'a> {
    fn new(options: &Options) -> Self {
        let opt = textwrap::Options::new(options.line_width)
            .wrap_algorithm(WrapAlgorithm::OptimalFit(Penalties::new()));
        Self {
            opt,
            buf: String::new(),
        }
    }

    fn push(&mut self, v: &[u8]) -> Result<(), str::Utf8Error> {
        self.buf.push_str(str::from_utf8(v)?);
        Ok(())
    }

    fn push_char(&mut self, c: char) {
        self.buf.push(c);
    }
}

struct WrappedLines<'a> {
    buf: String,
    wrapped: Vec<Cow<'a, str>>,
}

impl<'a> Into<WrappedLines<'a>> for Lines<'a> {
    fn into(self) -> WrappedLines<'a> {
        WrappedLines {
            buf: self.buf,
            wrapped: textwrap::wrap(&self.buf, self.opt),
        }
    }
}

I know that reference to self.buf will last long enough because it is owned by the same struct, but the compiler gives this message:

error[E0515]: cannot return value referencing local data `self.buf`
  --> src/main.rs:64:9
   |
64 | /         WrappedLines {
65 | |             buf: self.buf,
66 | |             wrapped: textwrap::wrap(&self.buf, self.opt),
   | |                                     --------- `self.buf` is borrowed here
67 | |         }
   | |_________^ returns a value referencing data owned by the current function

error[E0382]: borrow of moved value: `self.buf`
  --> src/main.rs:66:37
   |
65 |             buf: self.buf,
   |                  -------- value moved here
66 |             wrapped: textwrap::wrap(&self.buf, self.opt),
   |                                     ^^^^^^^^^ value borrowed here after move
   |
   = note: move occurs because `self.buf` has type `String`, which does not implement the `Copy` trait

How do I fix this?

I tried moving the wrapping code to another member function:

impl<'a> WrappedLines<'a> {
    fn wrap(&'a mut self) {
        let opt =
            textwrap::Options::new(79).wrap_algorithm(WrapAlgorithm::OptimalFit(Penalties::new()));
        self.wrapped = textwrap::wrap(&self.buf, opt);
    }
}

This removes the error but I would like to keep the wrapping code inside the into function.

cafce25
  • 15,907
  • 4
  • 25
  • 31
  • 3
    You can't store `self.buf` and a reference to `self.buf` in the same struct, see [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) – cafce25 Feb 22 '23 at 23:07

0 Answers0