<commit_before>//! The YAML parser. Here is where we convert the yaml in to commands to be
/// processed later.

use yaml_rust::Yaml;
use command::{Command, Session, SendKeys, Split, Layout, Window, Attach, KillWindow};
use rand::random;

#[cfg(test)] use yaml_rust::{YamlLoader};

/// Here was pass in the parsed yaml and project name. The purpose of this main
/// loop is to build the stack of commands that are run to setup a users tmux
/// session.
///
/// yaml_string: The parsed yaml from the config file.
/// project_name: The name of the project.
pub fn main(yaml_string: &Vec<Yaml>, project_name: &String, daemonize: bool) -> Result<Vec<Command>, String> {
    let mut commands: Vec<Command> = vec!();
    let tmp_window_name = format!("muxed_first_window_{}", random::<u16>());

    // There should only be one doc but it's a vec so loop it.
    for doc in yaml_string {
        let root = match doc["root"].as_str() {
            Some(x) => Some(x.to_string()),
            None    => None
        };

        let windows = doc["windows"].as_vec().expect("No Windows have been defined.");

        for window in windows.iter() {
            match window {
                &Yaml::Hash(ref h)  => {
                    for (k, v) in h {
                        if v.as_hash().is_some() {
                            commands.push(Command::Window(Window{
                                    session_name: project_name.clone(),
                                    name: k.as_str().unwrap().to_string()
                            }));

                            if root.is_some() {
                              let r = root.clone().unwrap();
                              commands.push(Command::SendKeys(SendKeys{
                                  target: format!("{}:{}", project_name, k.as_str().unwrap().to_string()).to_string(),
                                  exec: format!("cd {}", r)
                              }));
                            };

                            commands.append(&mut try!(pane_matcher(&project_name, v, &root.clone(), k.as_str().unwrap().to_string())));
                        } else {
                            commands.push(Command::Window(Window{
                                session_name: project_name.clone(),
                                name: try!(k.as_str().ok_or_else(|| "Windows require being named in your config.").map(|x| x.to_string()))
                            }));

                            if root.is_some() {
                              let r = root.clone().unwrap();
                              commands.push(Command::SendKeys(SendKeys{
                                  target: format!("{}:{}", project_name, k.as_str().unwrap().to_string()).to_string(),
                                  exec: format!("cd {}", r)
                              }));
                            };

                            if v.as_str().is_some() {
                                commands.push(Command::SendKeys(SendKeys{
                                    target: format!("{}:{}", project_name, k.as_str().unwrap().to_string()).to_string(),
                                    exec: v.as_str().unwrap().to_string()
                                }));
                            }
                        }
                    }
                },
                &Yaml::String(ref s) => {
                    commands.push(Command::Window(Window{
                        session_name: project_name.clone(),
                        name: s.clone()
                    }));

                    if root.is_some() {
                      let r = root.clone().unwrap();
                      commands.push(Command::SendKeys(SendKeys{
                          target: format!("{}:{}", project_name, s).to_string(),
                          exec: format!("cd {}", r).to_string()
                      }));
                    };
                },
                &Yaml::Integer(ref s) => {
                    commands.push(Command::Window(Window{
                        session_name: project_name.clone(),
                        name: s.to_string()
                    }));

                    if root.is_some() {
                      let r = root.clone().unwrap();
                      commands.push(Command::SendKeys(SendKeys{
                          target: format!("{}:{}", project_name, s).to_string(),
                          exec: format!("cd {}", r).to_string()
                      }));
                    };
                },
                _ => panic!("Muxed config file formatting isn't recognized.")
            };
        };
    };

    if !daemonize { commands.push(Command::Attach(Attach{name: project_name.clone()})) };

    let (first, commands) = commands.split_first().unwrap();
    let mut remains = commands.to_vec();

    match first {
        &Command::Window(ref w) => {
            remains.insert(0, Command::Session(Session{
                name: project_name.clone(),
                window_name: w.name.clone()
            }));
        },
        _ => {}
    };

    Ok(remains)
}

/// Pane matcher is for breaking apart the panes. Splitting windows when needed
/// and executing commands as needed.
fn pane_matcher(session: &String, window: &Yaml, root: &Option<String>, window_name: String) -> Result<Vec<Command>, String> {
    let mut commands = vec!();
    let panes = window["panes"].as_vec().expect("Something is wrong with panes.");

    for (i, pane) in panes.iter().enumerate() {
        // For every pane, we need one less split.
        // ex. An existing window to become 2 panes, needs 1 split.
        if i < (panes.len()-1) {
            commands.push(Command::Split(Split{
                target: format!("{}:{}.{}", session, window_name, i).to_string(),
                root: root.clone()
            }));
        };
        // Execute given commands in each new pane after all splits are
        // complete.

        if pane.as_str().is_some() {
            commands.push(Command::SendKeys(SendKeys{
                target: format!("{}:{}.{}", session, window_name, i).to_string(),
                exec: pane.as_str().unwrap().to_string()
            }));
        }
    };

    // After all panes are split select the layout for the window
    if window["layout"].as_str().is_some() {
        let layout = window["layout"].as_str().expect("Bad layout").to_string();
        commands.push(Command::Layout(Layout{
            target: format!("{}:{}", session, window_name).to_string(),
            layout: layout
        }));
    };

    Ok(commands)
}

#[test]
pub fn expect_1_session() {
    let s = "---
windows: ['cargo', 'vim', 'git']
";
    let yaml = YamlLoader::load_from_str(s).unwrap();
    let remains: Vec<Command> = main(&yaml, &"muxed".to_string(), false).unwrap().into_iter().filter(|x| match x {
        &Command::Session(_) => true,
        _ => false
    }).collect();

    assert_eq!(remains.len(), 1)
}

#[test]
pub fn expect_3_windows_from_array() {
    let s = "---
windows: ['cargo', 'vim', 'git']
";
    let yaml = YamlLoader::load_from_str(s).unwrap();
    let remains: Vec<Command> = main(&yaml, &"muxed".to_string(), false).unwrap().into_iter().filter(|x| match x {
        &Command::Window(_) => true,
        _ => false
    }).collect();

    assert_eq!(remains.len(), 3)
}

#[test]
pub fn expect_1_attach() {
    let s = "---
windows: ['cargo', 'vim', 'git']
";
    let yaml = YamlLoader::load_from_str(s).unwrap();
    let remains: Vec<Command> = main(&yaml, &"muxed".to_string(), false).unwrap().into_iter().filter(|x| match x {
        &Command::Attach(_) => true,
        _ => false
    }).collect();

    assert_eq!(remains.len(), 1)
}

#[test]
pub fn expect_3_windows_with_mixed_type_names() {
    let s = "---
windows: [1, 'vim', 3]
";
    let yaml = YamlLoader::load_from_str(s).unwrap();
    let remains: Vec<Command> = main(&yaml, &"muxed".to_string(), false).unwrap().into_iter().filter(|x| match x {
        &Command::Window(_) => true,
        _ => false
    }).collect();
    assert_eq!(remains.len(), 3)
}

#[test]
pub fn expect_3_windows_from_list() {
    let s = "---
windows:
  - cargo: ''
  - vim: ''
  - git: ''
";
    let yaml = YamlLoader::load_from_str(s).unwrap();
    let remains: Vec<Command> = main(&yaml, &"muxed".to_string(), false).unwrap().into_iter().filter(|x| match x {
        &Command::Window(_) => true,
        _ => false
    }).collect();
    assert_eq!(remains.len(), 3)
}

#[test]
pub fn expect_ok_with_empty_syscommands() {
    let s = "---
windows:
  - editor:
";
    let yaml = YamlLoader::load_from_str(s).unwrap();
    let result = main(&yaml, &"muxed".to_string(), false);
    assert!(result.is_ok())
}

#[test]
pub fn expect_no_send_keys_commands() {
    let s = "---
windows:
  - editor:
";

    let yaml = YamlLoader::load_from_str(s).unwrap();
    let remains: Vec<Command> = main(&yaml, &"muxed".to_string(), false).unwrap().into_iter().filter(|x| match x {
        &Command::SendKeys(_) => true,
        _ => false
    }).collect();

    assert_eq!(remains.len(), 0)
}

#[test]
pub fn expect_err_with_nameless_window() {
    let s = "---
windows:
  - : ls
";
    let yaml = YamlLoader::load_from_str(s).unwrap();
    let result = main(&yaml, &"muxed".to_string(), false);
    assert!(result.is_err())
}

#[test]
pub fn expect_ok_with_empty_panes_syscommands() {
    let s = "---
windows:
  - cargo:
      layout: 'main-vertical'
      panes:
        -
";
    let yaml = YamlLoader::load_from_str(s).unwrap();
    let result = main(&yaml, &"muxed".to_string(), false);
    assert!(result.is_ok())
}

#[test]
pub fn expect_no_send_keys_with_empty_panes_syscommands() {
    let s = "---
windows:
  - editor:
      panes:
        -
";

    let yaml = YamlLoader::load_from_str(s).unwrap();
    let remains: Vec<Command> = main(&yaml, &"muxed".to_string(), false).unwrap().into_iter().filter(|x| match x {
        &Command::SendKeys(_) => true,
        _ => false
    }).collect();

    assert_eq!(remains.len(), 0)
}

#[test]
pub fn expect_1_split_window() {
    let s = "---
windows:
  - editor:
      layout: 'main-vertical'
      panes: ['vim', 'guard']
";

    let yaml = YamlLoader::load_from_str(s).unwrap();
    let remains: Vec<Command> = main(&yaml, &"muxed".to_string(), false).unwrap().into_iter().filter(|x| match x {
        &Command::Split(_) => true,
        _ => false
    }).collect();

    assert_eq!(remains.len(), 1)
}

#[test]
pub fn expect_1_layout() {
    let s = "---
windows:
  - editor:
      layout: 'main-vertical'
      panes: ['vim', 'guard']
";

    let yaml = YamlLoader::load_from_str(s).unwrap();
    let remains: Vec<Command> = main(&yaml, &"muxed".to_string(), false).unwrap().into_iter().filter(|x| match x {
        &Command::Layout(_) => true,
        _ => false
    }).collect();

    assert_eq!(remains.len(), 1)
}

#[test]
pub fn expect_1_window_with_panes_array() {
    let s = "---
windows:
  - editor:
      layout: 'main-vertical'
      panes: ['vim', 'guard']
";

    let yaml = YamlLoader::load_from_str(s).unwrap();
    let remains: Vec<Command> = main(&yaml, &"muxed".to_string(), false).unwrap().into_iter().filter(|x| match x {
        &Command::Window(_) => true,
        _ => false
    }).collect();

    assert_eq!(remains.len(), 1)
}

#[test]
pub fn expect_1_session_with_panes_array() {
    let s = "---
windows:
  - editor:
      layout: 'main-vertical'
      panes: ['vim', 'guard']
";

    let yaml = YamlLoader::load_from_str(s).unwrap();
    let remains: Vec<Command> = main(&yaml, &"muxed".to_string(), false).unwrap().into_iter().filter(|x| match x {
        &Command::Session(_) => true,
        _ => false
    }).collect();

    assert_eq!(remains.len(), 1)
}
<commit_msg>Re-work the parser tests for the change is how default directories are applied and the first window is now created.<commit_after>//! The YAML parser. Here is where we convert the yaml in to commands to be
/// processed later.

use yaml_rust::Yaml;
use command::{Command, Session, SendKeys, Split, Layout, Window, Attach, KillWindow};
use rand::random;

#[cfg(test)] use yaml_rust::{YamlLoader};

/// Here was pass in the parsed yaml and project name. The purpose of this main
/// loop is to build the stack of commands that are run to setup a users tmux
/// session.
///
/// yaml_string: The parsed yaml from the config file.
/// project_name: The name of the project.
pub fn main(yaml_string: &Vec<Yaml>, project_name: &String, daemonize: bool) -> Result<Vec<Command>, String> {
    let mut commands: Vec<Command> = vec!();
    let tmp_window_name = format!("muxed_first_window_{}", random::<u16>());

    // There should only be one doc but it's a vec so loop it.
    for doc in yaml_string {
        let root = match doc["root"].as_str() {
            Some(x) => Some(x.to_string()),
            None    => None
        };

        let windows = doc["windows"].as_vec().expect("No Windows have been defined.");

        for window in windows.iter() {
            match window {
                &Yaml::Hash(ref h)  => {
                    for (k, v) in h {
                        if v.as_hash().is_some() {
                            commands.push(Command::Window(Window{
                                    session_name: project_name.clone(),
                                    name: k.as_str().unwrap().to_string()
                            }));

                            if root.is_some() {
                              let r = root.clone().unwrap();
                              commands.push(Command::SendKeys(SendKeys{
                                  target: format!("{}:{}", project_name, k.as_str().unwrap().to_string()).to_string(),
                                  exec: format!("cd {}", r)
                              }));
                            };

                            commands.append(&mut try!(pane_matcher(&project_name, v, &root.clone(), k.as_str().unwrap().to_string())));
                        } else {
                            commands.push(Command::Window(Window{
                                session_name: project_name.clone(),
                                name: try!(k.as_str().ok_or_else(|| "Windows require being named in your config.").map(|x| x.to_string()))
                            }));

                            if root.is_some() {
                              let r = root.clone().unwrap();
                              commands.push(Command::SendKeys(SendKeys{
                                  target: format!("{}:{}", project_name, k.as_str().unwrap().to_string()).to_string(),
                                  exec: format!("cd {}", r)
                              }));
                            };

                            if v.as_str().is_some() {
                                commands.push(Command::SendKeys(SendKeys{
                                    target: format!("{}:{}", project_name, k.as_str().unwrap().to_string()).to_string(),
                                    exec: v.as_str().unwrap().to_string()
                                }));
                            }
                        }
                    }
                },
                &Yaml::String(ref s) => {
                    commands.push(Command::Window(Window{
                        session_name: project_name.clone(),
                        name: s.clone()
                    }));

                    if root.is_some() {
                      let r = root.clone().unwrap();
                      commands.push(Command::SendKeys(SendKeys{
                          target: format!("{}:{}", project_name, s).to_string(),
                          exec: format!("cd {}", r).to_string()
                      }));
                    };
                },
                &Yaml::Integer(ref s) => {
                    commands.push(Command::Window(Window{
                        session_name: project_name.clone(),
                        name: s.to_string()
                    }));

                    if root.is_some() {
                      let r = root.clone().unwrap();
                      commands.push(Command::SendKeys(SendKeys{
                          target: format!("{}:{}", project_name, s).to_string(),
                          exec: format!("cd {}", r).to_string()
                      }));
                    };
                },
                _ => panic!("Muxed config file formatting isn't recognized.")
            };
        };
    };

    if !daemonize { commands.push(Command::Attach(Attach{name: project_name.clone()})) };

    let (first, commands) = commands.split_first().unwrap();
    let mut remains = commands.to_vec();

    match first {
        &Command::Window(ref w) => {
            remains.insert(0, Command::Session(Session{
                name: project_name.clone(),
                window_name: w.name.clone()
            }));
        },
        _ => {}
    };

    Ok(remains)
}

/// Pane matcher is for breaking apart the panes. Splitting windows when needed
/// and executing commands as needed.
fn pane_matcher(session: &String, window: &Yaml, root: &Option<String>, window_name: String) -> Result<Vec<Command>, String> {
    let mut commands = vec!();
    let panes = window["panes"].as_vec().expect("Something is wrong with panes.");

    for (i, pane) in panes.iter().enumerate() {
        // For every pane, we need one less split.
        // ex. An existing window to become 2 panes, needs 1 split.
        if i < (panes.len()-1) {
            commands.push(Command::Split(Split{
                target: format!("{}:{}.{}", session, window_name, i).to_string(),
                root: root.clone()
            }));
        };
        // Execute given commands in each new pane after all splits are
        // complete.

        if pane.as_str().is_some() {
            commands.push(Command::SendKeys(SendKeys{
                target: format!("{}:{}.{}", session, window_name, i).to_string(),
                exec: pane.as_str().unwrap().to_string()
            }));
        }
    };

    // After all panes are split select the layout for the window
    if window["layout"].as_str().is_some() {
        let layout = window["layout"].as_str().expect("Bad layout").to_string();
        commands.push(Command::Layout(Layout{
            target: format!("{}:{}", session, window_name).to_string(),
            layout: layout
        }));
    };

    Ok(commands)
}

#[test]
pub fn expect_1_session() {
    let s = "---
windows: ['cargo', 'vim', 'git']
";
    let yaml = YamlLoader::load_from_str(s).unwrap();
    let remains: Vec<Command> = main(&yaml, &"muxed".to_string(), false).unwrap().into_iter().filter(|x| match x {
        &Command::Session(_) => true,
        _ => false
    }).collect();

    assert_eq!(remains.len(), 1)
}

#[test]
pub fn expect_2_windows_from_array() {
    let s = "---
windows: ['cargo', 'vim', 'git']
";
    let yaml = YamlLoader::load_from_str(s).unwrap();
    let remains: Vec<Command> = main(&yaml, &"muxed".to_string(), false).unwrap().into_iter().filter(|x| match x {
        &Command::Window(_) => true,
        _ => false
    }).collect();

    assert_eq!(remains.len(), 2)
}

#[test]
pub fn expect_1_attach() {
    let s = "---
windows: ['cargo', 'vim', 'git']
";
    let yaml = YamlLoader::load_from_str(s).unwrap();
    let remains: Vec<Command> = main(&yaml, &"muxed".to_string(), false).unwrap().into_iter().filter(|x| match x {
        &Command::Attach(_) => true,
        _ => false
    }).collect();

    assert_eq!(remains.len(), 1)
}

#[test]
pub fn expect_2_windows_with_mixed_type_names() {
    let s = "---
windows: [1, 'vim', 3]
";
    let yaml = YamlLoader::load_from_str(s).unwrap();
    let remains: Vec<Command> = main(&yaml, &"muxed".to_string(), false).unwrap().into_iter().filter(|x| match x {
        &Command::Window(_) => true,
        _ => false
    }).collect();
    assert_eq!(remains.len(), 2)
}

#[test]
pub fn expect_2_windows_from_list() {
    let s = "---
windows:
  - cargo: ''
  - vim: ''
  - git: ''
";
    let yaml = YamlLoader::load_from_str(s).unwrap();
    let remains: Vec<Command> = main(&yaml, &"muxed".to_string(), false).unwrap().into_iter().filter(|x| match x {
        &Command::Window(_) => true,
        _ => false
    }).collect();
    assert_eq!(remains.len(), 2)
}

#[test]
pub fn expect_ok_with_empty_syscommands() {
    let s = "---
windows:
  - editor:
";
    let yaml = YamlLoader::load_from_str(s).unwrap();
    let result = main(&yaml, &"muxed".to_string(), false);
    assert!(result.is_ok())
}

#[test]
pub fn expect_no_send_keys_commands() {
    let s = "---
windows:
  - editor:
";

    let yaml = YamlLoader::load_from_str(s).unwrap();
    let remains: Vec<Command> = main(&yaml, &"muxed".to_string(), false).unwrap().into_iter().filter(|x| match x {
        &Command::SendKeys(_) => true,
        _ => false
    }).collect();

    assert_eq!(remains.len(), 0)
}

#[test]
pub fn expect_err_with_nameless_window() {
    let s = "---
windows:
  - : ls
";
    let yaml = YamlLoader::load_from_str(s).unwrap();
    let result = main(&yaml, &"muxed".to_string(), false);
    assert!(result.is_err())
}

#[test]
pub fn expect_ok_with_empty_panes_syscommands() {
    let s = "---
windows:
  - cargo:
      layout: 'main-vertical'
      panes:
        -
";
    let yaml = YamlLoader::load_from_str(s).unwrap();
    let result = main(&yaml, &"muxed".to_string(), false);
    assert!(result.is_ok())
}

#[test]
pub fn expect_no_send_keys_with_empty_panes_syscommands() {
    let s = "---
windows:
  - editor:
      panes:
        -
";

    let yaml = YamlLoader::load_from_str(s).unwrap();
    let remains: Vec<Command> = main(&yaml, &"muxed".to_string(), false).unwrap().into_iter().filter(|x| match x {
        &Command::SendKeys(_) => true,
        _ => false
    }).collect();

    assert_eq!(remains.len(), 0)
}

#[test]
pub fn expect_1_split_window() {
    let s = "---
windows:
  - editor:
      layout: 'main-vertical'
      panes: ['vim', 'guard']
";

    let yaml = YamlLoader::load_from_str(s).unwrap();
    let remains: Vec<Command> = main(&yaml, &"muxed".to_string(), false).unwrap().into_iter().filter(|x| match x {
        &Command::Split(_) => true,
        _ => false
    }).collect();

    assert_eq!(remains.len(), 1)
}

#[test]
pub fn expect_1_layout() {
    let s = "---
windows:
  - editor:
      layout: 'main-vertical'
      panes: ['vim', 'guard']
";

    let yaml = YamlLoader::load_from_str(s).unwrap();
    let remains: Vec<Command> = main(&yaml, &"muxed".to_string(), false).unwrap().into_iter().filter(|x| match x {
        &Command::Layout(_) => true,
        _ => false
    }).collect();

    assert_eq!(remains.len(), 1)
}

#[test]
pub fn expect_1_session_with_panes_array() {
    let s = "---
windows:
  - editor:
      layout: 'main-vertical'
      panes: ['vim', 'guard']
";

    let yaml = YamlLoader::load_from_str(s).unwrap();
    let remains: Vec<Command> = main(&yaml, &"muxed".to_string(), false).unwrap().into_iter().filter(|x| match x {
        &Command::Session(_) => true,
        _ => false
    }).collect();

    assert_eq!(remains.len(), 1)
}
<|endoftext|>


<commit_before>//
// imag - the personal information management suite for the commandline
// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; version
// 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//

use std::ops::DerefMut;
use std::path::PathBuf;

use libimagrt::runtime::Runtime;
use libimagerror::trace::trace_error_exit;
use libimagstore::storeid::StoreId;

use util::build_toml_header;

pub fn update(rt: &Runtime) {
    rt.cli()
        .subcommand_matches("update")
        .map(|scmd| {
            scmd.value_of("id")
                .map(|id| {
                    let path = PathBuf::from(id);
                    let path = match StoreId::new(Some(rt.store().path().clone()), path) {
                        Err(e) => trace_error_exit(&e, 1),
                        Ok(p) => p,
                    };

                    rt.store()
                        .retrieve(path)
                        .map(|mut locked_e| {
                            let e = locked_e.deref_mut();

                            scmd.value_of("content")
                                .map(|new_content| {
                                    *e.get_content_mut() = String::from(new_content);
                                    debug!("New content set");
                                });

                            *e.get_header_mut() = build_toml_header(scmd, e.get_header().clone());
                            debug!("New header set");
                        })
                })
        });

}

<commit_msg>Rewrite update() to use positional arg<commit_after>//
// imag - the personal information management suite for the commandline
// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; version
// 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//

use std::ops::DerefMut;
use std::path::PathBuf;

use libimagrt::runtime::Runtime;
use libimagerror::trace::trace_error_exit;
use libimagstore::storeid::StoreId;

use util::build_toml_header;

pub fn update(rt: &Runtime) {
    let scmd  = rt.cli().subcommand_matches("update").unwrap();
    let id    = scmd.value_of("id").unwrap(); // Safe by clap
    let path  = PathBuf::from(id);
    let store = Some(rt.store().path().clone());
    let path  = StoreId::new(store, path).unwrap_or_else(|e| trace_error_exit(&e, 1));

    let _ = rt.store()
        .retrieve(path)
        .map(|mut locked_e| {
            let e = locked_e.deref_mut();

            scmd.value_of("content")
                .map(|new_content| {
                    *e.get_content_mut() = String::from(new_content);
                    debug!("New content set");
                });

            *e.get_header_mut() = build_toml_header(scmd, e.get_header().clone());
            debug!("New header set");
        });
}

<|endoftext|>


<commit_before>use grammar::*;

pub fn generate_code(program: Program) -> Result<String, Vec<String>> {
    let mut resulting_program = String::new();
    let mut errors = Vec::new();

    for stmt in program.body {
        match visit(stmt) {
            Ok(p) => resulting_program.push_str(&p),
            Err(err) => errors.push(err)
        }
    }
    if errors.len() > 0 {
        Err(errors)
    } else {
        Ok(resulting_program)
    }
}

fn visit(statement: Statement) -> Result<String, String> {
    match statement {
        Statement::VariableDeclarationStatement{kind: kind, declarations: declarations } => {
            var_declaration(kind, declarations)
        },
        _ => Err(format!("Unknown tree node {:?}",statement))
    }
}

fn var_declaration(kind: VariableDeclarationKind, declarations: Vec<(String, Expression)>) -> Result<String, String> {
    match kind {
        VariableDeclarationKind::Var | VariableDeclarationKind::Const => {
            if declarations.len() == 1 {
                let ref variable_name = declarations[0].0;
                let value  = declarations[0].1.clone();
                Ok(format!("var {} = {};", variable_name, literal_value(value).unwrap()))
            } else {
                let mut declaration_str = String::new();
                for declaration in declarations {
                    let ref variable_name = declaration.0;
                    let value  = declaration.1.clone();
                    declaration_str = declaration_str + &format!("{} = {}, ", variable_name, literal_value(value).unwrap());
                }
                declaration_str.pop();
                declaration_str.pop();
                Ok(format!("var {};", declaration_str))
            }
        },
        VariableDeclarationKind::Let => Err("Unsupported statement: let".into()),
    }
}

fn literal_value(expression: Expression) -> Result<String, String> {
    match expression {
        Expression::LiteralExpression(literal) => {
            Ok(literal_to_string(literal).unwrap())
        },
        _ => Err(format!("unsupported expression type: {:?}", expression))
    }
}

fn literal_to_string(literal: LiteralValue) -> Result<String, String> {
    match literal {
        LiteralUndefined => Ok("undefined".into()),
        LiteralNull => Ok("null".into()),
        LiteralTrue => Ok("true".into()),
        LiteralFalse => Ok("false".into()),
        LiteralInteger(num) => Ok(num.to_string()),
        LiteralFloat(num) => Ok(num.to_string()),
        LiteralString(st) => Ok(format!("\"{}\"", st)),
        _ => Err("Invalid literal".into())
    }
}
<commit_msg>We do only handle var statements in the code generator<commit_after>use grammar::*;

pub fn generate_code(program: Program) -> Result<String, Vec<String>> {
    let mut resulting_program = String::new();
    let mut errors = Vec::new();

    for stmt in program.body {
        match visit(stmt) {
            Ok(p) => resulting_program.push_str(&p),
            Err(err) => errors.push(err)
        }
    }
    if errors.len() > 0 {
        Err(errors)
    } else {
        Ok(resulting_program)
    }
}

fn visit(statement: Statement) -> Result<String, String> {
    match statement {
        Statement::VariableDeclarationStatement{kind: kind, declarations: declarations } => {
            var_declaration(kind, declarations)
        },
        _ => Err(format!("Unknown tree node {:?}",statement))
    }
}

fn var_declaration(kind: VariableDeclarationKind, declarations: Vec<(String, Expression)>) -> Result<String, String> {
    match kind {
        VariableDeclarationKind::Var => {
            if declarations.len() == 1 {
                let ref variable_name = declarations[0].0;
                let value  = declarations[0].1.clone();
                Ok(format!("var {} = {};", variable_name, literal_value(value).unwrap()))
            } else {
                let mut declaration_str = String::new();
                for declaration in declarations {
                    let ref variable_name = declaration.0;
                    let value  = declaration.1.clone();
                    declaration_str = declaration_str + &format!("{} = {}, ", variable_name, literal_value(value).unwrap());
                }
                declaration_str.pop();
                declaration_str.pop();
                Ok(format!("var {};", declaration_str))
            }
        },
        _ => Err("Unsupported statement: let".into()),
    }
}

fn literal_value(expression: Expression) -> Result<String, String> {
    match expression {
        Expression::LiteralExpression(literal) => {
            Ok(literal_to_string(literal).unwrap())
        },
        _ => Err(format!("unsupported expression type: {:?}", expression))
    }
}

fn literal_to_string(literal: LiteralValue) -> Result<String, String> {
    match literal {
        LiteralUndefined => Ok("undefined".into()),
        LiteralNull => Ok("null".into()),
        LiteralTrue => Ok("true".into()),
        LiteralFalse => Ok("false".into()),
        LiteralInteger(num) => Ok(num.to_string()),
        LiteralFloat(num) => Ok(num.to_string()),
        LiteralString(st) => Ok(format!("\"{}\"", st)),
        _ => Err("Invalid literal".into())
    }
}
<|endoftext|>


<commit_before>use std::io::net::ip::{SocketAddr, Ipv4Addr, Ipv6Addr};
use libc::{malloc, sockaddr, sockaddr_in, sockaddr_in6, in_addr, in6_addr, c_int, c_char, socklen_t, AF_INET, AF_INET6};
use std::mem::{size_of, transmute};
use std::string;

/*
 const char *
     inet_ntop(int af, const void * restrict src, char * restrict dst,
         socklen_t size);
*/
extern {
    fn getnameinfo(sa: *const sockaddr, salen: socklen_t,
                   host: *mut c_char, hostlen: socklen_t,
                   serv: *mut c_char, servlen: socklen_t,
                   flags: c_int) -> c_int;
}

#[cfg(target_os = "linux")]
#[cfg(target_os = "android")]
fn new_sockaddr_in(port: u16, addr: in_addr) -> sockaddr_in {
    sockaddr_in {
        sin_family: AF_INET as u16,
        sin_port: port,
        sin_addr: addr,
        sin_zero: [0, ..8]
    }
}
#[cfg(target_os = "macos")]
fn new_sockaddr_in(port: u16, addr: in_addr) -> sockaddr_in {
    sockaddr_in {
        sin_len: size_of::<sockaddr_in>() as u8,
        sin_family: AF_INET as u8,
        sin_port: port,
        sin_addr: addr,
        sin_zero: [0, ..8]
    }
}

#[cfg(target_os = "linux")]
#[cfg(target_os = "android")]
fn new_sockaddr_in6(port: u16, addr: in6_addr) -> sockaddr_in6 {
    sockaddr_in6 {
        sin6_family: AF_INET6 as u16,
        sin6_port: port,
        sin6_flowinfo: 0,
        sin6_addr: addr,
        sin6_scope_id: 0,
    }
}
#[cfg(target_os = "macos")]
fn new_sockaddr_in6(port: u16, addr: in6_addr) -> sockaddr_in6 {
    sockaddr_in6 {
        sin6_len: size_of::<sockaddr_in6>() as u8,
        sin6_family: AF_INET6 as u8,
        sin6_port: port,
        sin6_flowinfo: 0,
        sin6_addr: addr,
        sin6_scope_id: 0,
    }
}

//static NI_NUMERICHOST: c_int = 0x00000002;
//static NI_NAMEREQD: c_int = 0x00000004;

/// Returns the hostname for an ip address
/// TODO: make this safe, see manpage
pub fn get_nameinfo(peer_socket: SocketAddr) -> String {
    let SocketAddr { ip: ip, port: port } = peer_socket;
    let buf: *mut i8;
    let _ = unsafe {
        let hostlen = 80;
        buf = transmute(malloc(hostlen as u64 + 1));
        match ip {
            Ipv4Addr(a, b, c, d) => {
                let addr = in_addr {
                    s_addr: a as u32 << 24
                          | b as u32 << 16
                          | c as u32 << 8
                          | d as u32
                };
                let sockaddr = new_sockaddr_in(port, addr);
                getnameinfo(transmute(&sockaddr), size_of::<sockaddr_in>() as socklen_t,
                            buf, hostlen, transmute(0u), 0, 0)
            },
            Ipv6Addr(a, b, c, d, e, f, g, h) => {
                let addr = in6_addr {
                    s6_addr: [a, b, c, d, e, f, g, h]
                };
                let sockaddr = new_sockaddr_in6(port, addr);
                getnameinfo(transmute(&sockaddr), size_of::<sockaddr_in6>() as socklen_t,
                            buf, hostlen, transmute(0u), 0, 0)
            },
        }

    };
    unsafe {string::raw::from_buf(transmute(buf))}

}
<commit_msg>correct size for 32bit<commit_after>use std::io::net::ip::{SocketAddr, Ipv4Addr, Ipv6Addr};
use libc::{size_t, malloc, sockaddr, sockaddr_in, sockaddr_in6, in_addr, in6_addr, c_int, c_char, socklen_t, AF_INET, AF_INET6};
use std::mem::{size_of, transmute};
use std::string;

/*
 const char *
     inet_ntop(int af, const void * restrict src, char * restrict dst,
         socklen_t size);
*/
extern {
    fn getnameinfo(sa: *const sockaddr, salen: socklen_t,
                   host: *mut c_char, hostlen: socklen_t,
                   serv: *mut c_char, servlen: socklen_t,
                   flags: c_int) -> c_int;
}

#[cfg(target_os = "linux")]
#[cfg(target_os = "android")]
fn new_sockaddr_in(port: u16, addr: in_addr) -> sockaddr_in {
    sockaddr_in {
        sin_family: AF_INET as u16,
        sin_port: port,
        sin_addr: addr,
        sin_zero: [0, ..8]
    }
}
#[cfg(target_os = "macos")]
fn new_sockaddr_in(port: u16, addr: in_addr) -> sockaddr_in {
    sockaddr_in {
        sin_len: size_of::<sockaddr_in>() as u8,
        sin_family: AF_INET as u8,
        sin_port: port,
        sin_addr: addr,
        sin_zero: [0, ..8]
    }
}

#[cfg(target_os = "linux")]
#[cfg(target_os = "android")]
fn new_sockaddr_in6(port: u16, addr: in6_addr) -> sockaddr_in6 {
    sockaddr_in6 {
        sin6_family: AF_INET6 as u16,
        sin6_port: port,
        sin6_flowinfo: 0,
        sin6_addr: addr,
        sin6_scope_id: 0,
    }
}
#[cfg(target_os = "macos")]
fn new_sockaddr_in6(port: u16, addr: in6_addr) -> sockaddr_in6 {
    sockaddr_in6 {
        sin6_len: size_of::<sockaddr_in6>() as u8,
        sin6_family: AF_INET6 as u8,
        sin6_port: port,
        sin6_flowinfo: 0,
        sin6_addr: addr,
        sin6_scope_id: 0,
    }
}

//static NI_NUMERICHOST: c_int = 0x00000002;
//static NI_NAMEREQD: c_int = 0x00000004;

/// Returns the hostname for an ip address
/// TODO: make this safe, see manpage
pub fn get_nameinfo(peer_socket: SocketAddr) -> String {
    let SocketAddr { ip: ip, port: port } = peer_socket;
    let buf: *mut i8;
    let _ = unsafe {
        let hostlen = 80;
        buf = transmute(malloc(hostlen as size_t + 1));
        match ip {
            Ipv4Addr(a, b, c, d) => {
                let addr = in_addr {
                    s_addr: a as u32 << 24
                          | b as u32 << 16
                          | c as u32 << 8
                          | d as u32
                };
                let sockaddr = new_sockaddr_in(port, addr);
                getnameinfo(transmute(&sockaddr), size_of::<sockaddr_in>() as socklen_t,
                            buf, hostlen, transmute(0u), 0, 0)
            },
            Ipv6Addr(a, b, c, d, e, f, g, h) => {
                let addr = in6_addr {
                    s6_addr: [a, b, c, d, e, f, g, h]
                };
                let sockaddr = new_sockaddr_in6(port, addr);
                getnameinfo(transmute(&sockaddr), size_of::<sockaddr_in6>() as socklen_t,
                            buf, hostlen, transmute(0u), 0, 0)
            },
        }

    };
    unsafe {string::raw::from_buf(transmute(buf))}

}
<|endoftext|>


<commit_before>use crate::fmt;
use crate::iter::adapters::{zip::try_get_unchecked, SourceIter, TrustedRandomAccess};
use crate::iter::{FusedIterator, InPlaceIterable, TrustedLen};
use crate::ops::Try;

/// An iterator that maps the values of `iter` with `f`.
///
/// This `struct` is created by the [`map`] method on [`Iterator`]. See its
/// documentation for more.
///
/// [`map`]: Iterator::map
/// [`Iterator`]: trait.Iterator.html
///
/// # Notes about side effects
///
/// The [`map`] iterator implements [`DoubleEndedIterator`], meaning that
/// you can also [`map`] backwards:
///
/// ```rust
/// let v: Vec<i32> = vec![1, 2, 3].into_iter().map(|x| x + 1).rev().collect();
///
/// assert_eq!(v, [4, 3, 2]);
/// ```
///
/// [`DoubleEndedIterator`]: trait.DoubleEndedIterator.html
///
/// But if your closure has state, iterating backwards may act in a way you do
/// not expect. Let's go through an example. First, in the forward direction:
///
/// ```rust
/// let mut c = 0;
///
/// for pair in vec!['a', 'b', 'c'].into_iter()
///                                .map(|letter| { c += 1; (letter, c) }) {
///     println!("{:?}", pair);
/// }
/// ```
///
/// This will print "('a', 1), ('b', 2), ('c', 3)".
///
/// Now consider this twist where we add a call to `rev`. This version will
/// print `('c', 1), ('b', 2), ('a', 3)`. Note that the letters are reversed,
/// but the values of the counter still go in order. This is because `map()` is
/// still being called lazily on each item, but we are popping items off the
/// back of the vector now, instead of shifting them from the front.
///
/// ```rust
/// let mut c = 0;
///
/// for pair in vec!['a', 'b', 'c'].into_iter()
///                                .map(|letter| { c += 1; (letter, c) })
///                                .rev() {
///     println!("{:?}", pair);
/// }
/// ```
#[must_use = "iterators are lazy and do nothing unless consumed"]
#[stable(feature = "rust1", since = "1.0.0")]
#[derive(Clone)]
pub struct Map<I, F> {
    iter: I,
    f: F,
}
impl<I, F> Map<I, F> {
    pub(in crate::iter) fn new(iter: I, f: F) -> Map<I, F> {
        Map { iter, f }
    }
}

#[stable(feature = "core_impl_debug", since = "1.9.0")]
impl<I: fmt::Debug, F> fmt::Debug for Map<I, F> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("Map").field("iter", &self.iter).finish()
    }
}

fn map_fold<T, B, Acc>(
    mut f: impl FnMut(T) -> B,
    mut g: impl FnMut(Acc, B) -> Acc,
) -> impl FnMut(Acc, T) -> Acc {
    move |acc, elt| g(acc, f(elt))
}

fn map_try_fold<'a, T, B, Acc, R>(
    f: &'a mut impl FnMut(T) -> B,
    mut g: impl FnMut(Acc, B) -> R + 'a,
) -> impl FnMut(Acc, T) -> R + 'a {
    move |acc, elt| g(acc, f(elt))
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<B, I: Iterator, F> Iterator for Map<I, F>
where
    F: FnMut(I::Item) -> B,
{
    type Item = B;

    #[inline]
    fn next(&mut self) -> Option<B> {
        self.iter.next().map(&mut self.f)
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        self.iter.size_hint()
    }

    fn try_fold<Acc, G, R>(&mut self, init: Acc, g: G) -> R
    where
        Self: Sized,
        G: FnMut(Acc, Self::Item) -> R,
        R: Try<Ok = Acc>,
    {
        self.iter.try_fold(init, map_try_fold(&mut self.f, g))
    }

    fn fold<Acc, G>(self, init: Acc, g: G) -> Acc
    where
        G: FnMut(Acc, Self::Item) -> Acc,
    {
        self.iter.fold(init, map_fold(self.f, g))
    }

    unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> B
    where
        Self: TrustedRandomAccess,
    {
        // SAFETY: the caller must uphold the contract for
        // `Iterator::__iterator_get_unchecked`.
        unsafe { (self.f)(try_get_unchecked(&mut self.iter, idx)) }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<B, I: DoubleEndedIterator, F> DoubleEndedIterator for Map<I, F>
where
    F: FnMut(I::Item) -> B,
{
    #[inline]
    fn next_back(&mut self) -> Option<B> {
        self.iter.next_back().map(&mut self.f)
    }

    fn try_rfold<Acc, G, R>(&mut self, init: Acc, g: G) -> R
    where
        Self: Sized,
        G: FnMut(Acc, Self::Item) -> R,
        R: Try<Ok = Acc>,
    {
        self.iter.try_rfold(init, map_try_fold(&mut self.f, g))
    }

    fn rfold<Acc, G>(self, init: Acc, g: G) -> Acc
    where
        G: FnMut(Acc, Self::Item) -> Acc,
    {
        self.iter.rfold(init, map_fold(self.f, g))
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<B, I: ExactSizeIterator, F> ExactSizeIterator for Map<I, F>
where
    F: FnMut(I::Item) -> B,
{
    fn len(&self) -> usize {
        self.iter.len()
    }

    fn is_empty(&self) -> bool {
        self.iter.is_empty()
    }
}

#[stable(feature = "fused", since = "1.26.0")]
impl<B, I: FusedIterator, F> FusedIterator for Map<I, F> where F: FnMut(I::Item) -> B {}

#[unstable(feature = "trusted_len", issue = "37572")]
unsafe impl<B, I, F> TrustedLen for Map<I, F>
where
    I: TrustedLen,
    F: FnMut(I::Item) -> B,
{
}

#[doc(hidden)]
#[unstable(feature = "trusted_random_access", issue = "none")]
unsafe impl<I, F> TrustedRandomAccess for Map<I, F>
where
    I: TrustedRandomAccess,
{
    #[inline]
    fn may_have_side_effect() -> bool {
        true
    }
}

#[unstable(issue = "none", feature = "inplace_iteration")]
unsafe impl<S: Iterator, B, I: Iterator, F> SourceIter for Map<I, F>
where
    F: FnMut(I::Item) -> B,
    I: SourceIter<Source = S>,
{
    type Source = S;

    #[inline]
    unsafe fn as_inner(&mut self) -> &mut S {
        // SAFETY: unsafe function forwarding to unsafe function with the same requirements
        unsafe { SourceIter::as_inner(&mut self.iter) }
    }
}

#[unstable(issue = "none", feature = "inplace_iteration")]
unsafe impl<B, I: InPlaceIterable, F> InPlaceIterable for Map<I, F> where F: FnMut(I::Item) -> B {}
<commit_msg>Rollup merge of #81840 - ibraheemdev:patch-1, r=dtolnay<commit_after>use crate::fmt;
use crate::iter::adapters::{zip::try_get_unchecked, SourceIter, TrustedRandomAccess};
use crate::iter::{FusedIterator, InPlaceIterable, TrustedLen};
use crate::ops::Try;

/// An iterator that maps the values of `iter` with `f`.
///
/// This `struct` is created by the [`map`] method on [`Iterator`]. See its
/// documentation for more.
///
/// [`map`]: Iterator::map
/// [`Iterator`]: trait.Iterator.html
///
/// # Notes about side effects
///
/// The [`map`] iterator implements [`DoubleEndedIterator`], meaning that
/// you can also [`map`] backwards:
///
/// ```rust
/// let v: Vec<i32> = vec![1, 2, 3].into_iter().map(|x| x + 1).rev().collect();
///
/// assert_eq!(v, [4, 3, 2]);
/// ```
///
/// [`DoubleEndedIterator`]: trait.DoubleEndedIterator.html
///
/// But if your closure has state, iterating backwards may act in a way you do
/// not expect. Let's go through an example. First, in the forward direction:
///
/// ```rust
/// let mut c = 0;
///
/// for pair in vec!['a', 'b', 'c'].into_iter()
///                                .map(|letter| { c += 1; (letter, c) }) {
///     println!("{:?}", pair);
/// }
/// ```
///
/// This will print "('a', 1), ('b', 2), ('c', 3)".
///
/// Now consider this twist where we add a call to `rev`. This version will
/// print `('c', 1), ('b', 2), ('a', 3)`. Note that the letters are reversed,
/// but the values of the counter still go in order. This is because `map()` is
/// still being called lazily on each item, but we are popping items off the
/// back of the vector now, instead of shifting them from the front.
///
/// ```rust
/// let mut c = 0;
///
/// for pair in vec!['a', 'b', 'c'].into_iter()
///                                .map(|letter| { c += 1; (letter, c) })
///                                .rev() {
///     println!("{:?}", pair);
/// }
/// ```
#[must_use = "iterators are lazy and do nothing unless consumed"]
#[stable(feature = "rust1", since = "1.0.0")]
#[derive(Clone)]
pub struct Map<I, F> {
    iter: I,
    f: F,
}

impl<I, F> Map<I, F> {
    pub(in crate::iter) fn new(iter: I, f: F) -> Map<I, F> {
        Map { iter, f }
    }
}

#[stable(feature = "core_impl_debug", since = "1.9.0")]
impl<I: fmt::Debug, F> fmt::Debug for Map<I, F> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("Map").field("iter", &self.iter).finish()
    }
}

fn map_fold<T, B, Acc>(
    mut f: impl FnMut(T) -> B,
    mut g: impl FnMut(Acc, B) -> Acc,
) -> impl FnMut(Acc, T) -> Acc {
    move |acc, elt| g(acc, f(elt))
}

fn map_try_fold<'a, T, B, Acc, R>(
    f: &'a mut impl FnMut(T) -> B,
    mut g: impl FnMut(Acc, B) -> R + 'a,
) -> impl FnMut(Acc, T) -> R + 'a {
    move |acc, elt| g(acc, f(elt))
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<B, I: Iterator, F> Iterator for Map<I, F>
where
    F: FnMut(I::Item) -> B,
{
    type Item = B;

    #[inline]
    fn next(&mut self) -> Option<B> {
        self.iter.next().map(&mut self.f)
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        self.iter.size_hint()
    }

    fn try_fold<Acc, G, R>(&mut self, init: Acc, g: G) -> R
    where
        Self: Sized,
        G: FnMut(Acc, Self::Item) -> R,
        R: Try<Ok = Acc>,
    {
        self.iter.try_fold(init, map_try_fold(&mut self.f, g))
    }

    fn fold<Acc, G>(self, init: Acc, g: G) -> Acc
    where
        G: FnMut(Acc, Self::Item) -> Acc,
    {
        self.iter.fold(init, map_fold(self.f, g))
    }

    unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> B
    where
        Self: TrustedRandomAccess,
    {
        // SAFETY: the caller must uphold the contract for
        // `Iterator::__iterator_get_unchecked`.
        unsafe { (self.f)(try_get_unchecked(&mut self.iter, idx)) }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<B, I: DoubleEndedIterator, F> DoubleEndedIterator for Map<I, F>
where
    F: FnMut(I::Item) -> B,
{
    #[inline]
    fn next_back(&mut self) -> Option<B> {
        self.iter.next_back().map(&mut self.f)
    }

    fn try_rfold<Acc, G, R>(&mut self, init: Acc, g: G) -> R
    where
        Self: Sized,
        G: FnMut(Acc, Self::Item) -> R,
        R: Try<Ok = Acc>,
    {
        self.iter.try_rfold(init, map_try_fold(&mut self.f, g))
    }

    fn rfold<Acc, G>(self, init: Acc, g: G) -> Acc
    where
        G: FnMut(Acc, Self::Item) -> Acc,
    {
        self.iter.rfold(init, map_fold(self.f, g))
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<B, I: ExactSizeIterator, F> ExactSizeIterator for Map<I, F>
where
    F: FnMut(I::Item) -> B,
{
    fn len(&self) -> usize {
        self.iter.len()
    }

    fn is_empty(&self) -> bool {
        self.iter.is_empty()
    }
}

#[stable(feature = "fused", since = "1.26.0")]
impl<B, I: FusedIterator, F> FusedIterator for Map<I, F> where F: FnMut(I::Item) -> B {}

#[unstable(feature = "trusted_len", issue = "37572")]
unsafe impl<B, I, F> TrustedLen for Map<I, F>
where
    I: TrustedLen,
    F: FnMut(I::Item) -> B,
{
}

#[doc(hidden)]
#[unstable(feature = "trusted_random_access", issue = "none")]
unsafe impl<I, F> TrustedRandomAccess for Map<I, F>
where
    I: TrustedRandomAccess,
{
    #[inline]
    fn may_have_side_effect() -> bool {
        true
    }
}

#[unstable(issue = "none", feature = "inplace_iteration")]
unsafe impl<S: Iterator, B, I: Iterator, F> SourceIter for Map<I, F>
where
    F: FnMut(I::Item) -> B,
    I: SourceIter<Source = S>,
{
    type Source = S;

    #[inline]
    unsafe fn as_inner(&mut self) -> &mut S {
        // SAFETY: unsafe function forwarding to unsafe function with the same requirements
        unsafe { SourceIter::as_inner(&mut self.iter) }
    }
}

#[unstable(issue = "none", feature = "inplace_iteration")]
unsafe impl<B, I: InPlaceIterable, F> InPlaceIterable for Map<I, F> where F: FnMut(I::Item) -> B {}
<|endoftext|>


<commit_before>//! Macros used by iterators of slice.

// Inlining is_empty and len makes a huge performance difference
macro_rules! is_empty {
    // The way we encode the length of a ZST iterator, this works both for ZST
    // and non-ZST.
    ($self: ident) => {
        $self.ptr.as_ptr() as *const T == $self.end
    };
}

// To get rid of some bounds checks (see `position`), we compute the length in a somewhat
// unexpected way. (Tested by `codegen/slice-position-bounds-check`.)
macro_rules! len {
    ($self: ident) => {{
        #![allow(unused_unsafe)] // we're sometimes used within an unsafe block

        let start = $self.ptr;
        let size = size_from_ptr(start.as_ptr());
        if size == 0 {
            // This _cannot_ use `unchecked_sub` because we depend on wrapping
            // to represent the length of long ZST slice iterators.
            ($self.end as usize).wrapping_sub(start.as_ptr() as usize)
        } else {
            // We know that `start <= end`, so can do better than `offset_from`,
            // which needs to deal in signed.  By setting appropriate flags here
            // we can tell LLVM this, which helps it remove bounds checks.
            // SAFETY: By the type invariant, `start <= end`
            let diff = unsafe { unchecked_sub($self.end as usize, start.as_ptr() as usize) };
            // By also telling LLVM that the pointers are apart by an exact
            // multiple of the type size, it can optimize `len() == 0` down to
            // `start == end` instead of `(end - start) < size`.
            // SAFETY: By the type invariant, the pointers are aligned so the
            //         distance between them must be a multiple of pointee size
            unsafe { exact_div(diff, size) }
        }
    }};
}

// The shared definition of the `Iter` and `IterMut` iterators
macro_rules! iterator {
    (
        struct $name:ident -> $ptr:ty,
        $elem:ty,
        $raw_mut:tt,
        {$( $mut_:tt )?},
        {$($extra:tt)*}
    ) => {
        // Returns the first element and moves the start of the iterator forwards by 1.
        // Greatly improves performance compared to an inlined function. The iterator
        // must not be empty.
        macro_rules! next_unchecked {
            ($self: ident) => {& $( $mut_ )? *$self.post_inc_start(1)}
        }

        // Returns the last element and moves the end of the iterator backwards by 1.
        // Greatly improves performance compared to an inlined function. The iterator
        // must not be empty.
        macro_rules! next_back_unchecked {
            ($self: ident) => {& $( $mut_ )? *$self.pre_dec_end(1)}
        }

        // Shrinks the iterator when T is a ZST, by moving the end of the iterator
        // backwards by `n`. `n` must not exceed `self.len()`.
        macro_rules! zst_shrink {
            ($self: ident, $n: ident) => {
                $self.end = ($self.end as * $raw_mut u8).wrapping_offset(-$n) as * $raw_mut T;
            }
        }

        impl<'a, T> $name<'a, T> {
            // Helper function for creating a slice from the iterator.
            #[inline(always)]
            fn make_slice(&self) -> &'a [T] {
                // SAFETY: the iterator was created from a slice with pointer
                // `self.ptr` and length `len!(self)`. This guarantees that all
                // the prerequisites for `from_raw_parts` are fulfilled.
                unsafe { from_raw_parts(self.ptr.as_ptr(), len!(self)) }
            }

            // Helper function for moving the start of the iterator forwards by `offset` elements,
            // returning the old start.
            // Unsafe because the offset must not exceed `self.len()`.
            #[inline(always)]
            unsafe fn post_inc_start(&mut self, offset: isize) -> * $raw_mut T {
                if mem::size_of::<T>() == 0 {
                    zst_shrink!(self, offset);
                    self.ptr.as_ptr()
                } else {
                    let old = self.ptr.as_ptr();
                    // SAFETY: the caller guarantees that `offset` doesn't exceed `self.len()`,
                    // so this new pointer is inside `self` and thus guaranteed to be non-null.
                    self.ptr = unsafe { NonNull::new_unchecked(self.ptr.as_ptr().offset(offset)) };
                    old
                }
            }

            // Helper function for moving the end of the iterator backwards by `offset` elements,
            // returning the new end.
            // Unsafe because the offset must not exceed `self.len()`.
            #[inline(always)]
            unsafe fn pre_dec_end(&mut self, offset: isize) -> * $raw_mut T {
                if mem::size_of::<T>() == 0 {
                    zst_shrink!(self, offset);
                    self.ptr.as_ptr()
                } else {
                    // SAFETY: the caller guarantees that `offset` doesn't exceed `self.len()`,
                    // which is guaranteed to not overflow an `isize`. Also, the resulting pointer
                    // is in bounds of `slice`, which fulfills the other requirements for `offset`.
                    self.end = unsafe { self.end.offset(-offset) };
                    self.end
                }
            }
        }

        #[stable(feature = "rust1", since = "1.0.0")]
        impl<T> ExactSizeIterator for $name<'_, T> {
            #[inline(always)]
            fn len(&self) -> usize {
                len!(self)
            }

            #[inline(always)]
            fn is_empty(&self) -> bool {
                is_empty!(self)
            }
        }

        #[stable(feature = "rust1", since = "1.0.0")]
        impl<'a, T> Iterator for $name<'a, T> {
            type Item = $elem;

            #[inline]
            fn next(&mut self) -> Option<$elem> {
                // could be implemented with slices, but this avoids bounds checks

                // SAFETY: `assume` calls are safe since a slice's start pointer
                // must be non-null, and slices over non-ZSTs must also have a
                // non-null end pointer. The call to `next_unchecked!` is safe
                // since we check if the iterator is empty first.
                unsafe {
                    assume(!self.ptr.as_ptr().is_null());
                    if mem::size_of::<T>() != 0 {
                        assume(!self.end.is_null());
                    }
                    if is_empty!(self) {
                        None
                    } else {
                        Some(next_unchecked!(self))
                    }
                }
            }

            #[inline]
            fn size_hint(&self) -> (usize, Option<usize>) {
                let exact = len!(self);
                (exact, Some(exact))
            }

            #[inline]
            fn count(self) -> usize {
                len!(self)
            }

            #[inline]
            fn nth(&mut self, n: usize) -> Option<$elem> {
                if n >= len!(self) {
                    // This iterator is now empty.
                    if mem::size_of::<T>() == 0 {
                        // We have to do it this way as `ptr` may never be 0, but `end`
                        // could be (due to wrapping).
                        self.end = self.ptr.as_ptr();
                    } else {
                        // SAFETY: end can't be 0 if T isn't ZST because ptr isn't 0 and end >= ptr
                        unsafe {
                            self.ptr = NonNull::new_unchecked(self.end as *mut T);
                        }
                    }
                    return None;
                }
                // SAFETY: We are in bounds. `post_inc_start` does the right thing even for ZSTs.
                unsafe {
                    self.post_inc_start(n as isize);
                    Some(next_unchecked!(self))
                }
            }

            fn advance_by(&mut self, n: usize) -> Result<(), usize> {
                let advance = cmp::min(n, len!(self));
                // SAFETY: By construction, `advance` does not exceed `self.len()`.
                unsafe { self.post_inc_start(advance as isize) };
                if advance == n { Ok(()) } else { Err(advance) }
            }

            #[inline]
            fn last(mut self) -> Option<$elem> {
                self.next_back()
            }

            // We override the default implementation, which uses `try_fold`,
            // because this simple implementation generates less LLVM IR and is
            // faster to compile.
            #[inline]
            fn for_each<F>(mut self, mut f: F)
            where
                Self: Sized,
                F: FnMut(Self::Item),
            {
                while let Some(x) = self.next() {
                    f(x);
                }
            }

            // We override the default implementation, which uses `try_fold`,
            // because this simple implementation generates less LLVM IR and is
            // faster to compile.
            #[inline]
            fn all<F>(&mut self, mut f: F) -> bool
            where
                Self: Sized,
                F: FnMut(Self::Item) -> bool,
            {
                while let Some(x) = self.next() {
                    if !f(x) {
                        return false;
                    }
                }
                true
            }

            // We override the default implementation, which uses `try_fold`,
            // because this simple implementation generates less LLVM IR and is
            // faster to compile.
            #[inline]
            fn any<F>(&mut self, mut f: F) -> bool
            where
                Self: Sized,
                F: FnMut(Self::Item) -> bool,
            {
                while let Some(x) = self.next() {
                    if f(x) {
                        return true;
                    }
                }
                false
            }

            // We override the default implementation, which uses `try_fold`,
            // because this simple implementation generates less LLVM IR and is
            // faster to compile.
            #[inline]
            fn find<P>(&mut self, mut predicate: P) -> Option<Self::Item>
            where
                Self: Sized,
                P: FnMut(&Self::Item) -> bool,
            {
                while let Some(x) = self.next() {
                    if predicate(&x) {
                        return Some(x);
                    }
                }
                None
            }

            // We override the default implementation, which uses `try_fold`,
            // because this simple implementation generates less LLVM IR and is
            // faster to compile.
            #[inline]
            fn find_map<B, F>(&mut self, mut f: F) -> Option<B>
            where
                Self: Sized,
                F: FnMut(Self::Item) -> Option<B>,
            {
                while let Some(x) = self.next() {
                    if let Some(y) = f(x) {
                        return Some(y);
                    }
                }
                None
            }

            // We override the default implementation, which uses `try_fold`,
            // because this simple implementation generates less LLVM IR and is
            // faster to compile. Also, the `assume` avoids a bounds check.
            #[inline]
            #[rustc_inherit_overflow_checks]
            fn position<P>(&mut self, mut predicate: P) -> Option<usize> where
                Self: Sized,
                P: FnMut(Self::Item) -> bool,
            {
                let n = len!(self);
                let mut i = 0;
                while let Some(x) = self.next() {
                    if predicate(x) {
                        // SAFETY: we are guaranteed to be in bounds by the loop invariant:
                        // when `i >= n`, `self.next()` returns `None` and the loop breaks.
                        unsafe { assume(i < n) };
                        return Some(i);
                    }
                    i += 1;
                }
                None
            }

            // We override the default implementation, which uses `try_fold`,
            // because this simple implementation generates less LLVM IR and is
            // faster to compile. Also, the `assume` avoids a bounds check.
            #[inline]
            fn rposition<P>(&mut self, mut predicate: P) -> Option<usize> where
                P: FnMut(Self::Item) -> bool,
                Self: Sized + ExactSizeIterator + DoubleEndedIterator
            {
                let n = len!(self);
                let mut i = n;
                while let Some(x) = self.next_back() {
                    i -= 1;
                    if predicate(x) {
                        // SAFETY: `i` must be lower than `n` since it starts at `n`
                        // and is only decreasing.
                        unsafe { assume(i < n) };
                        return Some(i);
                    }
                }
                None
            }

            #[doc(hidden)]
            unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item {
                // SAFETY: the caller must guarantee that `i` is in bounds of
                // the underlying slice, so `i` cannot overflow an `isize`, and
                // the returned references is guaranteed to refer to an element
                // of the slice and thus guaranteed to be valid.
                //
                // Also note that the caller also guarantees that we're never
                // called with the same index again, and that no other methods
                // that will access this subslice are called, so it is valid
                // for the returned reference to be mutable in the case of
                // `IterMut`
                unsafe { & $( $mut_ )? * self.ptr.as_ptr().add(idx) }
            }

            $($extra)*
        }

        #[stable(feature = "rust1", since = "1.0.0")]
        impl<'a, T> DoubleEndedIterator for $name<'a, T> {
            #[inline]
            fn next_back(&mut self) -> Option<$elem> {
                // could be implemented with slices, but this avoids bounds checks

                // SAFETY: `assume` calls are safe since a slice's start pointer must be non-null,
                // and slices over non-ZSTs must also have a non-null end pointer.
                // The call to `next_back_unchecked!` is safe since we check if the iterator is
                // empty first.
                unsafe {
                    assume(!self.ptr.as_ptr().is_null());
                    if mem::size_of::<T>() != 0 {
                        assume(!self.end.is_null());
                    }
                    if is_empty!(self) {
                        None
                    } else {
                        Some(next_back_unchecked!(self))
                    }
                }
            }

            #[inline]
            fn nth_back(&mut self, n: usize) -> Option<$elem> {
                if n >= len!(self) {
                    // This iterator is now empty.
                    self.end = self.ptr.as_ptr();
                    return None;
                }
                // SAFETY: We are in bounds. `pre_dec_end` does the right thing even for ZSTs.
                unsafe {
                    self.pre_dec_end(n as isize);
                    Some(next_back_unchecked!(self))
                }
            }

            #[inline]
            fn advance_back_by(&mut self, n: usize) -> Result<(), usize> {
                let advance = cmp::min(n, len!(self));
                // SAFETY: By construction, `advance` does not exceed `self.len()`.
                unsafe { self.pre_dec_end(advance as isize) };
                if advance == n { Ok(()) } else { Err(advance) }
            }
        }

        #[stable(feature = "fused", since = "1.26.0")]
        impl<T> FusedIterator for $name<'_, T> {}

        #[unstable(feature = "trusted_len", issue = "37572")]
        unsafe impl<T> TrustedLen for $name<'_, T> {}
    }
}

macro_rules! forward_iterator {
    ($name:ident: $elem:ident, $iter_of:ty) => {
        #[stable(feature = "rust1", since = "1.0.0")]
        impl<'a, $elem, P> Iterator for $name<'a, $elem, P>
        where
            P: FnMut(&T) -> bool,
        {
            type Item = $iter_of;

            #[inline]
            fn next(&mut self) -> Option<$iter_of> {
                self.inner.next()
            }

            #[inline]
            fn size_hint(&self) -> (usize, Option<usize>) {
                self.inner.size_hint()
            }
        }

        #[stable(feature = "fused", since = "1.26.0")]
        impl<'a, $elem, P> FusedIterator for $name<'a, $elem, P> where P: FnMut(&T) -> bool {}
    };
}
<commit_msg>Auto merge of #87736 - the8472:inline-advance-by, r=Mark-Simulacrum<commit_after>//! Macros used by iterators of slice.

// Inlining is_empty and len makes a huge performance difference
macro_rules! is_empty {
    // The way we encode the length of a ZST iterator, this works both for ZST
    // and non-ZST.
    ($self: ident) => {
        $self.ptr.as_ptr() as *const T == $self.end
    };
}

// To get rid of some bounds checks (see `position`), we compute the length in a somewhat
// unexpected way. (Tested by `codegen/slice-position-bounds-check`.)
macro_rules! len {
    ($self: ident) => {{
        #![allow(unused_unsafe)] // we're sometimes used within an unsafe block

        let start = $self.ptr;
        let size = size_from_ptr(start.as_ptr());
        if size == 0 {
            // This _cannot_ use `unchecked_sub` because we depend on wrapping
            // to represent the length of long ZST slice iterators.
            ($self.end as usize).wrapping_sub(start.as_ptr() as usize)
        } else {
            // We know that `start <= end`, so can do better than `offset_from`,
            // which needs to deal in signed.  By setting appropriate flags here
            // we can tell LLVM this, which helps it remove bounds checks.
            // SAFETY: By the type invariant, `start <= end`
            let diff = unsafe { unchecked_sub($self.end as usize, start.as_ptr() as usize) };
            // By also telling LLVM that the pointers are apart by an exact
            // multiple of the type size, it can optimize `len() == 0` down to
            // `start == end` instead of `(end - start) < size`.
            // SAFETY: By the type invariant, the pointers are aligned so the
            //         distance between them must be a multiple of pointee size
            unsafe { exact_div(diff, size) }
        }
    }};
}

// The shared definition of the `Iter` and `IterMut` iterators
macro_rules! iterator {
    (
        struct $name:ident -> $ptr:ty,
        $elem:ty,
        $raw_mut:tt,
        {$( $mut_:tt )?},
        {$($extra:tt)*}
    ) => {
        // Returns the first element and moves the start of the iterator forwards by 1.
        // Greatly improves performance compared to an inlined function. The iterator
        // must not be empty.
        macro_rules! next_unchecked {
            ($self: ident) => {& $( $mut_ )? *$self.post_inc_start(1)}
        }

        // Returns the last element and moves the end of the iterator backwards by 1.
        // Greatly improves performance compared to an inlined function. The iterator
        // must not be empty.
        macro_rules! next_back_unchecked {
            ($self: ident) => {& $( $mut_ )? *$self.pre_dec_end(1)}
        }

        // Shrinks the iterator when T is a ZST, by moving the end of the iterator
        // backwards by `n`. `n` must not exceed `self.len()`.
        macro_rules! zst_shrink {
            ($self: ident, $n: ident) => {
                $self.end = ($self.end as * $raw_mut u8).wrapping_offset(-$n) as * $raw_mut T;
            }
        }

        impl<'a, T> $name<'a, T> {
            // Helper function for creating a slice from the iterator.
            #[inline(always)]
            fn make_slice(&self) -> &'a [T] {
                // SAFETY: the iterator was created from a slice with pointer
                // `self.ptr` and length `len!(self)`. This guarantees that all
                // the prerequisites for `from_raw_parts` are fulfilled.
                unsafe { from_raw_parts(self.ptr.as_ptr(), len!(self)) }
            }

            // Helper function for moving the start of the iterator forwards by `offset` elements,
            // returning the old start.
            // Unsafe because the offset must not exceed `self.len()`.
            #[inline(always)]
            unsafe fn post_inc_start(&mut self, offset: isize) -> * $raw_mut T {
                if mem::size_of::<T>() == 0 {
                    zst_shrink!(self, offset);
                    self.ptr.as_ptr()
                } else {
                    let old = self.ptr.as_ptr();
                    // SAFETY: the caller guarantees that `offset` doesn't exceed `self.len()`,
                    // so this new pointer is inside `self` and thus guaranteed to be non-null.
                    self.ptr = unsafe { NonNull::new_unchecked(self.ptr.as_ptr().offset(offset)) };
                    old
                }
            }

            // Helper function for moving the end of the iterator backwards by `offset` elements,
            // returning the new end.
            // Unsafe because the offset must not exceed `self.len()`.
            #[inline(always)]
            unsafe fn pre_dec_end(&mut self, offset: isize) -> * $raw_mut T {
                if mem::size_of::<T>() == 0 {
                    zst_shrink!(self, offset);
                    self.ptr.as_ptr()
                } else {
                    // SAFETY: the caller guarantees that `offset` doesn't exceed `self.len()`,
                    // which is guaranteed to not overflow an `isize`. Also, the resulting pointer
                    // is in bounds of `slice`, which fulfills the other requirements for `offset`.
                    self.end = unsafe { self.end.offset(-offset) };
                    self.end
                }
            }
        }

        #[stable(feature = "rust1", since = "1.0.0")]
        impl<T> ExactSizeIterator for $name<'_, T> {
            #[inline(always)]
            fn len(&self) -> usize {
                len!(self)
            }

            #[inline(always)]
            fn is_empty(&self) -> bool {
                is_empty!(self)
            }
        }

        #[stable(feature = "rust1", since = "1.0.0")]
        impl<'a, T> Iterator for $name<'a, T> {
            type Item = $elem;

            #[inline]
            fn next(&mut self) -> Option<$elem> {
                // could be implemented with slices, but this avoids bounds checks

                // SAFETY: `assume` calls are safe since a slice's start pointer
                // must be non-null, and slices over non-ZSTs must also have a
                // non-null end pointer. The call to `next_unchecked!` is safe
                // since we check if the iterator is empty first.
                unsafe {
                    assume(!self.ptr.as_ptr().is_null());
                    if mem::size_of::<T>() != 0 {
                        assume(!self.end.is_null());
                    }
                    if is_empty!(self) {
                        None
                    } else {
                        Some(next_unchecked!(self))
                    }
                }
            }

            #[inline]
            fn size_hint(&self) -> (usize, Option<usize>) {
                let exact = len!(self);
                (exact, Some(exact))
            }

            #[inline]
            fn count(self) -> usize {
                len!(self)
            }

            #[inline]
            fn nth(&mut self, n: usize) -> Option<$elem> {
                if n >= len!(self) {
                    // This iterator is now empty.
                    if mem::size_of::<T>() == 0 {
                        // We have to do it this way as `ptr` may never be 0, but `end`
                        // could be (due to wrapping).
                        self.end = self.ptr.as_ptr();
                    } else {
                        // SAFETY: end can't be 0 if T isn't ZST because ptr isn't 0 and end >= ptr
                        unsafe {
                            self.ptr = NonNull::new_unchecked(self.end as *mut T);
                        }
                    }
                    return None;
                }
                // SAFETY: We are in bounds. `post_inc_start` does the right thing even for ZSTs.
                unsafe {
                    self.post_inc_start(n as isize);
                    Some(next_unchecked!(self))
                }
            }

            #[inline]
            fn advance_by(&mut self, n: usize) -> Result<(), usize> {
                let advance = cmp::min(len!(self), n);
                // SAFETY: By construction, `advance` does not exceed `self.len()`.
                unsafe { self.post_inc_start(advance as isize) };
                if advance == n { Ok(()) } else { Err(advance) }
            }

            #[inline]
            fn last(mut self) -> Option<$elem> {
                self.next_back()
            }

            // We override the default implementation, which uses `try_fold`,
            // because this simple implementation generates less LLVM IR and is
            // faster to compile.
            #[inline]
            fn for_each<F>(mut self, mut f: F)
            where
                Self: Sized,
                F: FnMut(Self::Item),
            {
                while let Some(x) = self.next() {
                    f(x);
                }
            }

            // We override the default implementation, which uses `try_fold`,
            // because this simple implementation generates less LLVM IR and is
            // faster to compile.
            #[inline]
            fn all<F>(&mut self, mut f: F) -> bool
            where
                Self: Sized,
                F: FnMut(Self::Item) -> bool,
            {
                while let Some(x) = self.next() {
                    if !f(x) {
                        return false;
                    }
                }
                true
            }

            // We override the default implementation, which uses `try_fold`,
            // because this simple implementation generates less LLVM IR and is
            // faster to compile.
            #[inline]
            fn any<F>(&mut self, mut f: F) -> bool
            where
                Self: Sized,
                F: FnMut(Self::Item) -> bool,
            {
                while let Some(x) = self.next() {
                    if f(x) {
                        return true;
                    }
                }
                false
            }

            // We override the default implementation, which uses `try_fold`,
            // because this simple implementation generates less LLVM IR and is
            // faster to compile.
            #[inline]
            fn find<P>(&mut self, mut predicate: P) -> Option<Self::Item>
            where
                Self: Sized,
                P: FnMut(&Self::Item) -> bool,
            {
                while let Some(x) = self.next() {
                    if predicate(&x) {
                        return Some(x);
                    }
                }
                None
            }

            // We override the default implementation, which uses `try_fold`,
            // because this simple implementation generates less LLVM IR and is
            // faster to compile.
            #[inline]
            fn find_map<B, F>(&mut self, mut f: F) -> Option<B>
            where
                Self: Sized,
                F: FnMut(Self::Item) -> Option<B>,
            {
                while let Some(x) = self.next() {
                    if let Some(y) = f(x) {
                        return Some(y);
                    }
                }
                None
            }

            // We override the default implementation, which uses `try_fold`,
            // because this simple implementation generates less LLVM IR and is
            // faster to compile. Also, the `assume` avoids a bounds check.
            #[inline]
            #[rustc_inherit_overflow_checks]
            fn position<P>(&mut self, mut predicate: P) -> Option<usize> where
                Self: Sized,
                P: FnMut(Self::Item) -> bool,
            {
                let n = len!(self);
                let mut i = 0;
                while let Some(x) = self.next() {
                    if predicate(x) {
                        // SAFETY: we are guaranteed to be in bounds by the loop invariant:
                        // when `i >= n`, `self.next()` returns `None` and the loop breaks.
                        unsafe { assume(i < n) };
                        return Some(i);
                    }
                    i += 1;
                }
                None
            }

            // We override the default implementation, which uses `try_fold`,
            // because this simple implementation generates less LLVM IR and is
            // faster to compile. Also, the `assume` avoids a bounds check.
            #[inline]
            fn rposition<P>(&mut self, mut predicate: P) -> Option<usize> where
                P: FnMut(Self::Item) -> bool,
                Self: Sized + ExactSizeIterator + DoubleEndedIterator
            {
                let n = len!(self);
                let mut i = n;
                while let Some(x) = self.next_back() {
                    i -= 1;
                    if predicate(x) {
                        // SAFETY: `i` must be lower than `n` since it starts at `n`
                        // and is only decreasing.
                        unsafe { assume(i < n) };
                        return Some(i);
                    }
                }
                None
            }

            #[doc(hidden)]
            unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item {
                // SAFETY: the caller must guarantee that `i` is in bounds of
                // the underlying slice, so `i` cannot overflow an `isize`, and
                // the returned references is guaranteed to refer to an element
                // of the slice and thus guaranteed to be valid.
                //
                // Also note that the caller also guarantees that we're never
                // called with the same index again, and that no other methods
                // that will access this subslice are called, so it is valid
                // for the returned reference to be mutable in the case of
                // `IterMut`
                unsafe { & $( $mut_ )? * self.ptr.as_ptr().add(idx) }
            }

            $($extra)*
        }

        #[stable(feature = "rust1", since = "1.0.0")]
        impl<'a, T> DoubleEndedIterator for $name<'a, T> {
            #[inline]
            fn next_back(&mut self) -> Option<$elem> {
                // could be implemented with slices, but this avoids bounds checks

                // SAFETY: `assume` calls are safe since a slice's start pointer must be non-null,
                // and slices over non-ZSTs must also have a non-null end pointer.
                // The call to `next_back_unchecked!` is safe since we check if the iterator is
                // empty first.
                unsafe {
                    assume(!self.ptr.as_ptr().is_null());
                    if mem::size_of::<T>() != 0 {
                        assume(!self.end.is_null());
                    }
                    if is_empty!(self) {
                        None
                    } else {
                        Some(next_back_unchecked!(self))
                    }
                }
            }

            #[inline]
            fn nth_back(&mut self, n: usize) -> Option<$elem> {
                if n >= len!(self) {
                    // This iterator is now empty.
                    self.end = self.ptr.as_ptr();
                    return None;
                }
                // SAFETY: We are in bounds. `pre_dec_end` does the right thing even for ZSTs.
                unsafe {
                    self.pre_dec_end(n as isize);
                    Some(next_back_unchecked!(self))
                }
            }

            #[inline]
            fn advance_back_by(&mut self, n: usize) -> Result<(), usize> {
                let advance = cmp::min(len!(self), n);
                // SAFETY: By construction, `advance` does not exceed `self.len()`.
                unsafe { self.pre_dec_end(advance as isize) };
                if advance == n { Ok(()) } else { Err(advance) }
            }
        }

        #[stable(feature = "fused", since = "1.26.0")]
        impl<T> FusedIterator for $name<'_, T> {}

        #[unstable(feature = "trusted_len", issue = "37572")]
        unsafe impl<T> TrustedLen for $name<'_, T> {}
    }
}

macro_rules! forward_iterator {
    ($name:ident: $elem:ident, $iter_of:ty) => {
        #[stable(feature = "rust1", since = "1.0.0")]
        impl<'a, $elem, P> Iterator for $name<'a, $elem, P>
        where
            P: FnMut(&T) -> bool,
        {
            type Item = $iter_of;

            #[inline]
            fn next(&mut self) -> Option<$iter_of> {
                self.inner.next()
            }

            #[inline]
            fn size_hint(&self) -> (usize, Option<usize>) {
                self.inner.size_hint()
            }
        }

        #[stable(feature = "fused", since = "1.26.0")]
        impl<'a, $elem, P> FusedIterator for $name<'a, $elem, P> where P: FnMut(&T) -> bool {}
    };
}
<|endoftext|>


<commit_before>// no-system-llvm
// only-x86_64
// build-fail

#![feature(asm)]

// Checks that inline asm errors are mapped to the correct line in the source code.

fn main() {
    unsafe {
        asm!("invalid_instruction");
        //~^ ERROR: invalid instruction mnemonic 'invalid_instruction'

        asm!("
            invalid_instruction
        ");
        //~^^ ERROR: invalid instruction mnemonic 'invalid_instruction'

        asm!(r#"
            invalid_instruction
        "#);
        //~^^ ERROR: invalid instruction mnemonic 'invalid_instruction'

        asm!("
            mov eax, eax
            invalid_instruction
            mov eax, eax
        ");
        //~^^^ ERROR: invalid instruction mnemonic 'invalid_instruction'

        asm!(r#"
            mov eax, eax
            invalid_instruction
            mov eax, eax
        "#);
        //~^^^ ERROR: invalid instruction mnemonic 'invalid_instruction'

        asm!(concat!("invalid", "_", "instruction"));
        //~^ ERROR: invalid instruction mnemonic 'invalid_instruction'

        asm!("movaps %xmm3, (%esi, 2)", options(att_syntax));
        //~^ WARN: scale factor without index register is ignored

        asm!(
            "invalid_instruction",
        );
        //~^^ ERROR: invalid instruction mnemonic 'invalid_instruction'

        asm!(
            "mov eax, eax",
            "invalid_instruction",
            "mov eax, eax",
        );
        //~^^^ ERROR: invalid instruction mnemonic 'invalid_instruction'

        asm!(
            "mov eax, eax\n",
            "invalid_instruction",
            "mov eax, eax",
        );
        //~^^^ ERROR: invalid instruction mnemonic 'invalid_instruction'

        asm!(
            "mov eax, eax",
            concat!("invalid", "_", "instruction"),
            "mov eax, eax",
        );
        //~^^^ ERROR: invalid instruction mnemonic 'invalid_instruction'

        asm!(
            concat!("mov eax", ", ", "eax"),
            concat!("invalid", "_", "instruction"),
            concat!("mov eax", ", ", "eax"),
        );
        //~^^^ ERROR: invalid instruction mnemonic 'invalid_instruction'

        // Make sure template strings get separated
        asm!(
            "invalid_instruction1",
            "invalid_instruction2",
        );
        //~^^^ ERROR: invalid instruction mnemonic 'invalid_instruction1'
        //~^^^ ERROR: invalid instruction mnemonic 'invalid_instruction2'

        asm!(
            concat!(
                "invalid", "_", "instruction1", "\n",
                "invalid", "_", "instruction2",
            ),
        );
        //~^^^^^ ERROR: invalid instruction mnemonic 'invalid_instruction1'
        //~^^^^^^ ERROR: invalid instruction mnemonic 'invalid_instruction2'

        asm!(
            concat!(
                "invalid", "_", "instruction1", "\n",
                "invalid", "_", "instruction2",
            ),
            concat!(
                "invalid", "_", "instruction3", "\n",
                "invalid", "_", "instruction4",
            ),
        );
        //~^^^^^^^^^ ERROR: invalid instruction mnemonic 'invalid_instruction1'
        //~^^^^^^^^^^ ERROR: invalid instruction mnemonic 'invalid_instruction2'
        //~^^^^^^^ ERROR: invalid instruction mnemonic 'invalid_instruction3'
        //~^^^^^^^^ ERROR: invalid instruction mnemonic 'invalid_instruction4'

        asm!(
            concat!(
                "invalid", "_", "instruction1", "\n",
                "invalid", "_", "instruction2", "\n",
            ),
            concat!(
                "invalid", "_", "instruction3", "\n",
                "invalid", "_", "instruction4", "\n",
            ),
        );
        //~^^^^^^^^^ ERROR: invalid instruction mnemonic 'invalid_instruction1'
        //~^^^^^^^^^^ ERROR: invalid instruction mnemonic 'invalid_instruction2'
        //~^^^^^^^ ERROR: invalid instruction mnemonic 'invalid_instruction3'
        //~^^^^^^^^ ERROR: invalid instruction mnemonic 'invalid_instruction4'
    }
}
<commit_msg>Use a single codegen unit to reduce non-determinism in srcloc.rs test<commit_after>// no-system-llvm
// only-x86_64
// build-fail
// compile-flags: -Ccodegen-units=1
#![feature(asm)]

// Checks that inline asm errors are mapped to the correct line in the source code.

fn main() {
    unsafe {
        asm!("invalid_instruction");
        //~^ ERROR: invalid instruction mnemonic 'invalid_instruction'

        asm!("
            invalid_instruction
        ");
        //~^^ ERROR: invalid instruction mnemonic 'invalid_instruction'

        asm!(r#"
            invalid_instruction
        "#);
        //~^^ ERROR: invalid instruction mnemonic 'invalid_instruction'

        asm!("
            mov eax, eax
            invalid_instruction
            mov eax, eax
        ");
        //~^^^ ERROR: invalid instruction mnemonic 'invalid_instruction'

        asm!(r#"
            mov eax, eax
            invalid_instruction
            mov eax, eax
        "#);
        //~^^^ ERROR: invalid instruction mnemonic 'invalid_instruction'

        asm!(concat!("invalid", "_", "instruction"));
        //~^ ERROR: invalid instruction mnemonic 'invalid_instruction'

        asm!("movaps %xmm3, (%esi, 2)", options(att_syntax));
        //~^ WARN: scale factor without index register is ignored

        asm!(
            "invalid_instruction",
        );
        //~^^ ERROR: invalid instruction mnemonic 'invalid_instruction'

        asm!(
            "mov eax, eax",
            "invalid_instruction",
            "mov eax, eax",
        );
        //~^^^ ERROR: invalid instruction mnemonic 'invalid_instruction'

        asm!(
            "mov eax, eax\n",
            "invalid_instruction",
            "mov eax, eax",
        );
        //~^^^ ERROR: invalid instruction mnemonic 'invalid_instruction'

        asm!(
            "mov eax, eax",
            concat!("invalid", "_", "instruction"),
            "mov eax, eax",
        );
        //~^^^ ERROR: invalid instruction mnemonic 'invalid_instruction'

        asm!(
            concat!("mov eax", ", ", "eax"),
            concat!("invalid", "_", "instruction"),
            concat!("mov eax", ", ", "eax"),
        );
        //~^^^ ERROR: invalid instruction mnemonic 'invalid_instruction'

        // Make sure template strings get separated
        asm!(
            "invalid_instruction1",
            "invalid_instruction2",
        );
        //~^^^ ERROR: invalid instruction mnemonic 'invalid_instruction1'
        //~^^^ ERROR: invalid instruction mnemonic 'invalid_instruction2'

        asm!(
            concat!(
                "invalid", "_", "instruction1", "\n",
                "invalid", "_", "instruction2",
            ),
        );
        //~^^^^^ ERROR: invalid instruction mnemonic 'invalid_instruction1'
        //~^^^^^^ ERROR: invalid instruction mnemonic 'invalid_instruction2'

        asm!(
            concat!(
                "invalid", "_", "instruction1", "\n",
                "invalid", "_", "instruction2",
            ),
            concat!(
                "invalid", "_", "instruction3", "\n",
                "invalid", "_", "instruction4",
            ),
        );
        //~^^^^^^^^^ ERROR: invalid instruction mnemonic 'invalid_instruction1'
        //~^^^^^^^^^^ ERROR: invalid instruction mnemonic 'invalid_instruction2'
        //~^^^^^^^ ERROR: invalid instruction mnemonic 'invalid_instruction3'
        //~^^^^^^^^ ERROR: invalid instruction mnemonic 'invalid_instruction4'

        asm!(
            concat!(
                "invalid", "_", "instruction1", "\n",
                "invalid", "_", "instruction2", "\n",
            ),
            concat!(
                "invalid", "_", "instruction3", "\n",
                "invalid", "_", "instruction4", "\n",
            ),
        );
        //~^^^^^^^^^ ERROR: invalid instruction mnemonic 'invalid_instruction1'
        //~^^^^^^^^^^ ERROR: invalid instruction mnemonic 'invalid_instruction2'
        //~^^^^^^^ ERROR: invalid instruction mnemonic 'invalid_instruction3'
        //~^^^^^^^^ ERROR: invalid instruction mnemonic 'invalid_instruction4'
    }
}
<|endoftext|>


<commit_before>use std::fs::File;
use std::io;
use std::io::prelude::*;

#[derive(Debug)]
pub enum RunError {
    Error,
    IoError(String), //TODO: improve error reporting
}

type RunResult = Result<(), RunError>;

pub trait LoxImplementation {
    fn run(&mut self, source: &str) -> RunResult;
}

pub struct Runner<I: LoxImplementation> {
    rulox: I,
}

impl<I: LoxImplementation> Runner<I> {
    pub fn new(implementation: I) -> Runner<I> {
        Runner {
            rulox: implementation,
        }
    }
    pub fn run_file(&mut self, file_name: &str) -> RunResult {
        let mut file =
            File::open(file_name).map_err(|_| RunError::IoError("Error opening file".into()))?; // TODO: add context
        let mut source = String::new();
        file.read_to_string(&mut source)
            .map_err(|_| RunError::IoError("Error reading file".into()))?;
        self.rulox.run(&source)
    }

    fn run_prompt(&mut self) -> Result<(), RunError> {
        println!("Rulox - A lox interpreter written in Rust");
        let _ = io::stdout().flush(); //TODO: is this okay?
        loop {
            print!("> ");
            io::stdout().flush().unwrap();
            let mut source = String::new();
            let _ = io::stdin().read_line(&mut source);
            // TODO: add a way to exit
            self.rulox.run(&source).unwrap_or_else(|error| {
                println!("{:?}", error);
                io::stdout().flush().unwrap()
            });
        }
    }

    pub fn run(&mut self, args: &[String]) -> i32 {
        let result = match args.len() {
            // The first argument is the program name
            1 => self.run_prompt(),
            2 => self.run_file(&args[1]),
            _ => {
                println!("Usage: rulox [script]");
                Ok(())
            }
        };
        match result {
            Ok(_) => 0,
            _ => {
                println!("{:?}", result);
                1
            }
        }
    }
}
<commit_msg>Reuse strings<commit_after>use std::fs::File;
use std::io;
use std::io::prelude::*;

#[derive(Debug)]
pub enum RunError {
    Error,
    IoError(String), //TODO: improve error reporting
}

type RunResult = Result<(), RunError>;

pub trait LoxImplementation {
    fn run(&mut self, source: &str) -> RunResult;
}

pub struct Runner<I: LoxImplementation> {
    rulox: I,
}

impl<I: LoxImplementation> Runner<I> {
    pub fn new(implementation: I) -> Runner<I> {
        Runner {
            rulox: implementation,
        }
    }
    pub fn run_file(&mut self, file_name: &str) -> RunResult {
        let mut file =
            File::open(file_name).map_err(|_| RunError::IoError("Error opening file".into()))?; // TODO: add context
        let mut source = String::new();
        file.read_to_string(&mut source)
            .map_err(|_| RunError::IoError("Error reading file".into()))?;
        self.rulox.run(&source)
    }

    fn run_prompt(&mut self) -> Result<(), RunError> {
        println!("Rulox - A lox interpreter written in Rust");
        let _ = io::stdout().flush(); //TODO: is this okay?
        let mut source = String::new();
        loop {
            print!("> ");
            io::stdout().flush().unwrap();
            let _ = io::stdin().read_line(&mut source);
            // TODO: add a way to exit
            self.rulox.run(&source).unwrap_or_else(|error| {
                println!("{:?}", error);
                io::stdout().flush().unwrap()
            });
            source.clear();
        }
    }

    pub fn run(&mut self, args: &[String]) -> i32 {
        let result = match args.len() {
            // The first argument is the program name
            1 => self.run_prompt(),
            2 => self.run_file(&args[1]),
            _ => {
                println!("Usage: rulox [script]");
                Ok(())
            }
        };
        match result {
            Ok(_) => 0,
            _ => {
                println!("{:?}", result);
                1
            }
        }
    }
}
<|endoftext|>