samply 0.13.1

A command line profiler for macOS and Linux.
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
pub struct Region {
    pub start: u64,
    pub end: u64,
    pub is_read: bool,
    pub is_write: bool,
    pub is_executable: bool,
    pub is_shared: bool,
    pub file_offset: u64,
    pub major: u32,
    pub minor: u32,
    pub inode: u64,
    pub name: String,
}

fn get_until<'a>(p: &mut &'a str, delimiter: char) -> &'a str {
    let mut found = None;
    for (index, ch) in p.char_indices() {
        if ch == delimiter {
            found = Some(index);
            break;
        }
    }

    if let Some(index) = found {
        let (before, after) = p.split_at(index);
        *p = &after[delimiter.len_utf8()..];
        before
    } else {
        let before = *p;
        *p = "";
        before
    }
}

fn get_char(p: &mut &str) -> Option<char> {
    let ch = p.chars().next()?;
    *p = &p[ch.len_utf8()..];
    Some(ch)
}

fn skip_whitespace(p: &mut &str) {
    while let Some(ch) = p.chars().next() {
        if ch == ' ' {
            *p = &p[ch.len_utf8()..];
        } else {
            break;
        }
    }
}

pub fn parse(maps: &str) -> Vec<Region> {
    if maps.is_empty() {
        return Vec::new();
    }

    let mut output = Vec::new();
    for mut line in maps.trim().split('\n') {
        let start = u64::from_str_radix(get_until(&mut line, '-'), 16).unwrap();
        let end = u64::from_str_radix(get_until(&mut line, ' '), 16).unwrap();
        let is_read = get_char(&mut line).unwrap() == 'r';
        let is_write = get_char(&mut line).unwrap() == 'w';
        let is_executable = get_char(&mut line).unwrap() == 'x';
        let is_shared = get_char(&mut line).unwrap() == 's';
        get_char(&mut line);

        let file_offset = u64::from_str_radix(get_until(&mut line, ' '), 16).unwrap();
        let major = u32::from_str_radix(get_until(&mut line, ':'), 16).unwrap();
        let minor = u32::from_str_radix(get_until(&mut line, ' '), 16).unwrap();
        let inode = get_until(&mut line, ' ').parse().unwrap();
        skip_whitespace(&mut line);
        let name = line.to_owned();

        output.push(Region {
            start,
            end,
            is_read,
            is_write,
            is_executable,
            is_shared,
            file_offset,
            major,
            minor,
            inode,
            name,
        });
    }

    output
}

#[test]
fn test_get_until() {
    let mut p = "1234 5678";
    assert_eq!(get_until(&mut p, ' '), "1234");
    assert_eq!(p, "5678");

    assert_eq!(get_until(&mut p, ' '), "5678");
    assert_eq!(p, "");

    assert_eq!(get_until(&mut p, ' '), "");
}

#[test]
fn test_parse() {
    let maps = r#"
00400000-0040c000 r-xp 00000000 08:02 1321238                            /usr/bin/cat
0060d000-0062e000 rw-p 00000000 00:00 0                                  [heap]
7ffff672c000-7ffff69db000 r--s 00001ac2 1f:33 1335289                    /usr/lib/locale/locale-archive
7ffff5600000-7ffff5800000 rw-p 00000000 00:00 0
"#;

    assert_eq!(
        parse(maps),
        vec![
            Region {
                start: 0x00400000,
                end: 0x0040c000,
                is_read: true,
                is_write: false,
                is_executable: true,
                is_shared: false,
                file_offset: 0,
                major: 0x08,
                minor: 0x02,
                inode: 1321238,
                name: "/usr/bin/cat".to_owned()
            },
            Region {
                start: 0x0060d000,
                end: 0x0062e000,
                is_read: true,
                is_write: true,
                is_executable: false,
                is_shared: false,
                file_offset: 0,
                major: 0,
                minor: 0,
                inode: 0,
                name: "[heap]".to_owned()
            },
            Region {
                start: 0x7ffff672c000,
                end: 0x7ffff69db000,
                is_read: true,
                is_write: false,
                is_executable: false,
                is_shared: true,
                file_offset: 0x1ac2,
                major: 0x1f,
                minor: 0x33,
                inode: 1335289,
                name: "/usr/lib/locale/locale-archive".to_owned()
            },
            Region {
                start: 0x7ffff5600000,
                end: 0x7ffff5800000,
                is_read: true,
                is_write: true,
                is_executable: false,
                is_shared: false,
                file_offset: 0,
                major: 0,
                minor: 0,
                inode: 0,
                name: "".to_owned()
            }
        ]
    );
}

#[test]
fn test_empty_maps() {
    assert_eq!(parse(""), vec![]);
}