fieldwork-borrow 0.1.0

Field-level borrow splitting for Rust
Documentation
//! e3: iterate over segments, call method that mutates buf

use fieldwork_borrow::with_;

struct Segment {
    rel_media_range_90k: i32,
}

impl Segment {
    fn media(&self) -> i32 {
        100
    }
}

pub struct FileBuilder {
    segments: Vec<Segment>,
    buf: Vec<u8>,
}

impl FileBuilder {
    // Original problem code (won't compile):
    // fn problem(&mut self) {
    //     for s in &self.segments {
    //         let mr = &s.rel_media_range_90k;
    //         let media_off = s.media();
    //         self.append_u32(Self::some_f5(mr, media_off));
    //     }
    //     Self::some_code4(&mut self.buf[0..3]);
    // }

    fn problem(&mut self) {
        with_!(self, {
            methods {
                append_u32(mut buf, v: u32) {
                    Self::some_code3(buf, v);
                }
            }
            fields {
                segments
                mut buf
            }
            body {
                for s in segments.iter() {
                    let mr = &s.rel_media_range_90k;
                    let media_off = s.media();
                    self.append_u32(Self::some_f5(mr, media_off));
                }
                Self::some_code4(&mut buf[0..3]);
            }
        });
    }

    fn some_f5(_: &i32, _: i32) -> u32 {
        0
    }

    fn some_code4(_: &mut [u8]) {}

    fn some_code3(buf: &mut Vec<u8>, v: u32) {
        buf.push(v as u8);
    }
}

#[test]
fn test_e3() {
    let mut builder = FileBuilder {
        segments: vec![
            Segment { rel_media_range_90k: 1 },
            Segment { rel_media_range_90k: 2 },
        ],
        buf: vec![0, 0, 0],
    };
    builder.problem();
    assert_eq!(builder.buf, vec![0, 0, 0, 0, 0]); // two appends
}