#Better way to update value in a struct?

14 messages · Page 1 of 1 (latest)

topaz sparrow
#

Example code:

use std::mem::swap;
use bson::{ doc, Bson, Document, Array };
use tap::Pipe;

#[derive(Debug)]
pub struct Data {
    pub query: Document,
    // and more fields...
}

fn main() {
    let mut data = Data {
        query: doc! {"a": 1, "b": 2},
    };

    let mut temp = doc! {};
    swap(&mut temp, &mut data.query);
    data.query = temp.into_iter()
        .map(|(key, value)| doc! {key: value})
        .map(|document| Bson::Document(document))
        .collect::<Array>()
        .pipe(|array| doc! {"$and": array});
    
    println!("{data:#?}");
}

My main problem is this:

let mut temp = doc! {};
swap(&mut temp, &mut data.query);
data.query = temp.into_iter()

Creating the temp just to be able to swap feels wasteful.

Other solutions:

  • std::mem::replace - I wasn't able to make it work.
  • Changing the struct from query: Document to query: Option<Document>, just so I'll be able to use take() and insert() also annoying, since afterward i'll have to unwrap() everywhere.
gilded hound
#

This is how you use replace:

let temp = swap(&mut data.query, doc! {});
#

You might want to make a map-like method that hides the temp value, though.

topaz sparrow
#

I meant with the replace, that I wasn't able to do something like that:

std::mem::replace(&mut data.query, data.query.into_iter()/*...*/);

to avoid the wasteful doc! {}

gilded hound
#

You can do data.query = data.query.into_iter() when you have ownership like above, but when you only have &mut, then you can't, since if something panics in between taking and replacing query, you'll end up with an uninitialized query field.

topaz sparrow
#

Right, that's the problem in my original code, my Data sits in a Vec and I need to do this update on the last element, so I'm using Vec::last_mut to get to it, but it gives &mut

gilded hound
#

btw Document implements Default so you can use std::mem::take. Same thing but less typing.

gilded hound
topaz sparrow
#

I don't know when Vec shrinks, won't this (in some cases) re-expand the size of the Vec?

gilded hound
#

They never shrink unless you do it explicitly.

topaz sparrow
#

Oh

#

wow

#

then this indeed solves this, the best way possible

gilded hound
#

yup