<commit_before>#![feature(fs_walk)]
#![feature(slice_patterns)]

extern crate rustc_serialize;
extern crate time;
extern crate eve;

use std::env;
use std::fs::{OpenOptions, walk_dir};
use std::io::prelude::*;
use rustc_serialize::json::{ToJson, Json};

use eve::server::*;
use eve::flow::*;
use eve::compiler::*;

fn read_events(filename: &str) -> Vec<Event> {
    let mut events_string = String::new();
    {
        let mut events_file = OpenOptions::new().create(true).open(&filename).unwrap();
        events_file.read_to_string(&mut events_string).unwrap();
    }
    events_string.lines().map(|line|
        FromJson::from_json(&Json::from_str(&line).unwrap())
        ).collect()
}

fn write_events(filename: &str, events: &[Event]) {
    let mut new_events_file = OpenOptions::new().create(true).truncate(true).write(true).open(&filename).unwrap();
    for event in events.iter() {
        new_events_file.write_all(format!("{}", event.to_json()).as_bytes()).unwrap();
        new_events_file.write_all("\n".as_bytes()).unwrap();
    }
}

fn all_filenames() -> Vec<String> {
    let mut filenames = vec![];
    filenames.push("./events".to_owned());
    filenames.push("./boostrap".to_owned());
    for entry in walk_dir("./test-inputs").unwrap() {
        filenames.push(entry.unwrap().path().to_str().unwrap().to_owned());
    }
    for entry in walk_dir("./test-outputs").unwrap() {
        filenames.push(entry.unwrap().path().to_str().unwrap().to_owned());
    }
    for entry in walk_dir("./examples").unwrap() {
        filenames.push(entry.unwrap().path().to_str().unwrap().to_owned());
    }
    filenames
}

fn remove_view(id: &str) {
    for filename in all_filenames() {
        let mut events = read_events(&filename[..]);
        for event in events.iter_mut() {
            event.changes.retain(|&(ref change_id, _)| change_id != id);
        }
        write_events(&filename[..], &events[..]);
    }
}

fn reset_internal_views() {
    let compiler_schema = compiler_schema();
    let client_schema = client_schema();
    for filename in all_filenames() {
        let mut events = read_events(&filename[..]);
        for event in events.iter_mut() {
            event.changes.retain(|&(ref change_id, _)|
                !compiler_schema.iter().chain(client_schema.iter()).any(|&(ref id, _)| change_id == id)
                );
        }
        write_events(&filename[..], &events[..]);
    }
}

fn compact(filename: &str) {
    let bootstrap_events = read_events("./bootstrap");
    let events = read_events(&filename[..]);
    let mut flow = Flow::new();
    for event in bootstrap_events.into_iter().chain(events.into_iter()) {
        flow.quiesce(event.changes);
    }
    // TODO session is blank which doesn't seem to matter because it is never used
    write_events(&filename[..], &[Event{changes: flow.as_changes(), session: "".to_owned()}]);
}

fn make_bug_test() {
    let events = read_events("./events");
    let time = time::precise_time_ns();
    let input_filename = format!("./test-inputs/bug-{}", time);
    let output_filename = format!("./test-outputs/bug-{}", time);
    write_events(&input_filename[..], &events[..]);
    write_events(&output_filename[..], &[]);
}

fn make_regression_test() {
    let bootstrap_events = read_events("./bootstrap");
    let events = read_events("./events");
    let mut flow = Flow::new();
    for event in bootstrap_events.into_iter().chain(events.into_iter()) {
        flow.quiesce(event.changes);
    }
    let time = time::precise_time_ns();
    let input_filename = format!("./test-inputs/regression-{}", time);
    let output_filename = format!("./test-outputs/regression-{}", time);
    write_events(&input_filename[..], &[Event{changes: flow.as_changes(), session: "".to_owned()}]);
    write_events(&output_filename[..],  &[Event{changes: flow.as_changes(), session: "".to_owned()}]);
}

#[test]
fn test_examples() {
    let inputs = walk_dir("./test-inputs").unwrap().collect::<Vec<_>>();
    let outputs = walk_dir("./test-outputs").unwrap().collect::<Vec<_>>();
    assert_eq!(inputs.len(), outputs.len());
    for (input_entry, output_entry) in inputs.into_iter().zip(outputs.into_iter()) {
        let input_filename = input_entry.unwrap().path().to_str().unwrap().to_owned();
        let output_filename = output_entry.unwrap().path().to_str().unwrap().to_owned();
        println!("Testing {:?} against {:?}", input_filename, output_filename);

        let bootstrap_events = read_events("./bootstrap");
        let input_events = read_events(&input_filename[..]);
        let mut input_flow = Flow::new();
        for event in bootstrap_events.into_iter().chain(input_events.into_iter()) {
            input_flow.quiesce(event.changes);
        }

        let output_events = read_events(&output_filename[..]);
        let mut output_flow = Flow::new();
        for event in output_events.into_iter() {
            output_flow.change(event.changes);
        }

        let schema = schema();
        for output_cell in output_flow.outputs.iter() {
            let output = output_cell.borrow();
            // ignore internal views
            if !schema.iter().any(|&(ref id, _)| **id == *output.view) {
                assert_eq!(output.index, input_flow.get_output(&output.view[..]).index);
            }
        }
    }
}

fn main() {
    let args = env::args().collect::<Vec<String>>();
    let borrowed_args = args.iter().map(|s| &s[..]).collect::<Vec<&str>>();
    match &borrowed_args[..] {
        [_, "remove_view", id] => remove_view(id),
        [_, "reset_internal_views"] => reset_internal_views(),
        [_, "compact", filename] => compact(filename),
        [_, "make_bug_test"] => make_bug_test(),
        [_, "make_regression_test"] => make_regression_test(),
        other => panic!("Bad arguments (look at src/bin/migrate.rs for correct usage): {:?}", &other[1..]),
    }
}<commit_msg>Use unix epoch time for test names<commit_after>#![feature(fs_walk)]
#![feature(slice_patterns)]

extern crate rustc_serialize;
extern crate time;
extern crate eve;

use std::env;
use std::fs::{OpenOptions, walk_dir};
use std::io::prelude::*;
use rustc_serialize::json::{ToJson, Json};

use eve::server::*;
use eve::flow::*;
use eve::compiler::*;

fn read_events(filename: &str) -> Vec<Event> {
    let mut events_string = String::new();
    {
        let mut events_file = OpenOptions::new().create(true).open(&filename).unwrap();
        events_file.read_to_string(&mut events_string).unwrap();
    }
    events_string.lines().map(|line|
        FromJson::from_json(&Json::from_str(&line).unwrap())
        ).collect()
}

fn write_events(filename: &str, events: &[Event]) {
    let mut new_events_file = OpenOptions::new().create(true).truncate(true).write(true).open(&filename).unwrap();
    for event in events.iter() {
        new_events_file.write_all(format!("{}", event.to_json()).as_bytes()).unwrap();
        new_events_file.write_all("\n".as_bytes()).unwrap();
    }
}

fn all_filenames() -> Vec<String> {
    let mut filenames = vec![];
    filenames.push("./events".to_owned());
    filenames.push("./boostrap".to_owned());
    for entry in walk_dir("./test-inputs").unwrap() {
        filenames.push(entry.unwrap().path().to_str().unwrap().to_owned());
    }
    for entry in walk_dir("./test-outputs").unwrap() {
        filenames.push(entry.unwrap().path().to_str().unwrap().to_owned());
    }
    for entry in walk_dir("./examples").unwrap() {
        filenames.push(entry.unwrap().path().to_str().unwrap().to_owned());
    }
    filenames
}

fn remove_view(id: &str) {
    for filename in all_filenames() {
        let mut events = read_events(&filename[..]);
        for event in events.iter_mut() {
            event.changes.retain(|&(ref change_id, _)| change_id != id);
        }
        write_events(&filename[..], &events[..]);
    }
}

fn reset_internal_views() {
    let compiler_schema = compiler_schema();
    let client_schema = client_schema();
    for filename in all_filenames() {
        let mut events = read_events(&filename[..]);
        for event in events.iter_mut() {
            event.changes.retain(|&(ref change_id, _)|
                !compiler_schema.iter().chain(client_schema.iter()).any(|&(ref id, _)| change_id == id)
                );
        }
        write_events(&filename[..], &events[..]);
    }
}

fn compact(filename: &str) {
    let bootstrap_events = read_events("./bootstrap");
    let events = read_events(&filename[..]);
    let mut flow = Flow::new();
    for event in bootstrap_events.into_iter().chain(events.into_iter()) {
        flow.quiesce(event.changes);
    }
    // TODO session is blank which doesn't seem to matter because it is never used
    write_events(&filename[..], &[Event{changes: flow.as_changes(), session: "".to_owned()}]);
}

fn make_bug_test() {
    let events = read_events("./events");
    let time = time::get_time().sec;
    let input_filename = format!("./test-inputs/bug-{}", time);
    let output_filename = format!("./test-outputs/bug-{}", time);
    write_events(&input_filename[..], &events[..]);
    write_events(&output_filename[..], &[]);
}

fn make_regression_test() {
    let bootstrap_events = read_events("./bootstrap");
    let events = read_events("./events");
    let mut flow = Flow::new();
    for event in bootstrap_events.into_iter().chain(events.into_iter()) {
        flow.quiesce(event.changes);
    }
    let time = time::get_time().sec;
    let input_filename = format!("./test-inputs/regression-{}", time);
    let output_filename = format!("./test-outputs/regression-{}", time);
    write_events(&input_filename[..], &[Event{changes: flow.as_changes(), session: "".to_owned()}]);
    write_events(&output_filename[..],  &[Event{changes: flow.as_changes(), session: "".to_owned()}]);
}

#[test]
fn test_examples() {
    let inputs = walk_dir("./test-inputs").unwrap().collect::<Vec<_>>();
    let outputs = walk_dir("./test-outputs").unwrap().collect::<Vec<_>>();
    assert_eq!(inputs.len(), outputs.len());
    for (input_entry, output_entry) in inputs.into_iter().zip(outputs.into_iter()) {
        let input_filename = input_entry.unwrap().path().to_str().unwrap().to_owned();
        let output_filename = output_entry.unwrap().path().to_str().unwrap().to_owned();
        println!("Testing {:?} against {:?}", input_filename, output_filename);

        let bootstrap_events = read_events("./bootstrap");
        let input_events = read_events(&input_filename[..]);
        let mut input_flow = Flow::new();
        for event in bootstrap_events.into_iter().chain(input_events.into_iter()) {
            input_flow.quiesce(event.changes);
        }

        let output_events = read_events(&output_filename[..]);
        let mut output_flow = Flow::new();
        for event in output_events.into_iter() {
            output_flow.change(event.changes);
        }

        let schema = schema();
        for output_cell in output_flow.outputs.iter() {
            let output = output_cell.borrow();
            // ignore internal views
            if !schema.iter().any(|&(ref id, _)| **id == *output.view) {
                assert_eq!(output.index, input_flow.get_output(&output.view[..]).index);
            }
        }
    }
}

fn main() {
    let args = env::args().collect::<Vec<String>>();
    let borrowed_args = args.iter().map(|s| &s[..]).collect::<Vec<&str>>();
    match &borrowed_args[..] {
        [_, "remove_view", id] => remove_view(id),
        [_, "reset_internal_views"] => reset_internal_views(),
        [_, "compact", filename] => compact(filename),
        [_, "make_bug_test"] => make_bug_test(),
        [_, "make_regression_test"] => make_regression_test(),
        other => panic!("Bad arguments (look at src/bin/migrate.rs for correct usage): {:?}", &other[1..]),
    }
}<|endoftext|>


<commit_before>tag color {
    red = 0xff0000;
    green = 0x00ff00;
    blue = 0x0000ff;
    black = 0x000000;
    white = 0xFFFFFF;
}

fn main() {
    assert uint::to_str(red as uint, 10u) == #fmt["%?", red];
    assert uint::to_str(green as uint, 10u) == #fmt["%?", green];
    assert uint::to_str(white as uint, 10u) == #fmt["%?", white];
}

<commit_msg>test: xfail-pretty run-pass/tag-disr-val-shape<commit_after>// xfail-pretty Issue #1510
tag color {
    red = 0xff0000;
    green = 0x00ff00;
    blue = 0x0000ff;
    black = 0x000000;
    white = 0xFFFFFF;
}

fn main() {
    assert uint::to_str(red as uint, 10u) == #fmt["%?", red];
    assert uint::to_str(green as uint, 10u) == #fmt["%?", green];
    assert uint::to_str(white as uint, 10u) == #fmt["%?", white];
}

<|endoftext|>


<commit_before>use clap::{Arg, ArgGroup, App, SubCommand};

use libimagentrytag::ui::tag_argument;
use libimagentrytag::ui::tag_argument_name;

pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> {
    app
        .subcommand(SubCommand::with_name("create")
                   .about("Create a note")
                   .version("0.1")
                   .arg(Arg::with_name("name")
                        .long("name")
                        .short("n")
                        .takes_value(true)
                        .required(true)
                        .help("Create Note with this name"))
                   .arg(Arg::with_name("edit")
                        .long("edit")
                        .short("e")
                        .takes_value(false)
                        .required(false)
                        .help("Edit after creating"))
                   )

        .subcommand(SubCommand::with_name("delete")
                   .about("Delete a Note")
                   .version("0.1")
                   .arg(Arg::with_name("name")
                        .long("name")
                        .short("n")
                        .takes_value(true)
                        .required(true)
                        .help("Delete Note with this name")))

        .subcommand(SubCommand::with_name("edit")
                   .about("Edit a Note")
                   .version("0.1")
                   .arg(Arg::with_name("name")
                        .long("name")
                        .short("n")
                        .takes_value(true)
                        .required(true)
                        .help("Edit Note with this name"))

                   .arg(tag_argument())
                   .group(ArgGroup::with_name("editargs")
                          .args(&[tag_argument_name(), "name"])
                          .required(true))
                   )

        .subcommand(SubCommand::with_name("list")
                   .about("List Notes")
                   .version("0.1"))

}

<commit_msg>Add value_name() call in ui specification code<commit_after>use clap::{Arg, ArgGroup, App, SubCommand};

use libimagentrytag::ui::tag_argument;
use libimagentrytag::ui::tag_argument_name;

pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> {
    app
        .subcommand(SubCommand::with_name("create")
                   .about("Create a note")
                   .version("0.1")
                   .arg(Arg::with_name("name")
                        .long("name")
                        .short("n")
                        .takes_value(true)
                        .required(true)
                        .help("Create Note with this name")
                        .value_name("NAME"))
                   .arg(Arg::with_name("edit")
                        .long("edit")
                        .short("e")
                        .takes_value(false)
                        .required(false)
                        .help("Edit after creating"))
                   )

        .subcommand(SubCommand::with_name("delete")
                   .about("Delete a Note")
                   .version("0.1")
                   .arg(Arg::with_name("name")
                        .long("name")
                        .short("n")
                        .takes_value(true)
                        .required(true)
                        .help("Delete Note with this name")
                        .value_name("NAME")))

        .subcommand(SubCommand::with_name("edit")
                   .about("Edit a Note")
                   .version("0.1")
                   .arg(Arg::with_name("name")
                        .long("name")
                        .short("n")
                        .takes_value(true)
                        .required(true)
                        .help("Edit Note with this name")
                        .value_name("NAME"))

                   .arg(tag_argument())
                   .group(ArgGroup::with_name("editargs")
                          .args(&[tag_argument_name(), "name"])
                          .required(true))
                   )

        .subcommand(SubCommand::with_name("list")
                   .about("List Notes")
                   .version("0.1"))

}
<|endoftext|>


<commit_before>use std::collections::{BTreeMap};
use std::collections::Bound::{Included, Unbounded};
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
use vec_map::{VecMap};
use entity::{Entity};
use location::{Location};
use item::Slot;
use self::Place::*;

/// Entities can be placed either on open locations or inside other entities.
/// A sum type will represent this nicely.
#[derive(Copy, Eq, PartialEq, Clone, PartialOrd, Ord, Debug, RustcEncodable, RustcDecodable)]
pub enum Place {
    At(Location),
    In(Entity, Option<Slot>),
}

/// Spatial index for game entities
pub struct Spatial {
    place_to_entities: BTreeMap<Place, Vec<Entity>>,
    entity_to_place: VecMap<Place>,
}

impl Spatial {
    pub fn new() -> Spatial {
        Spatial {
            place_to_entities: BTreeMap::new(),
            entity_to_place: VecMap::new(),
        }
    }

    fn insert(&mut self, Entity(idx): Entity, p: Place) {
        // Remove the entity from its old position.
        self.single_remove(Entity(idx));

        if let In(_, Some(_)) = p {
            // Slotted in-places are a special case that can hold at most one entity.
            if self.place_to_entities.contains_key(&p) {
                panic!("Equipping to an occupied inventory slot");
            }
        }

        self.entity_to_place.insert(idx, p);
        match self.place_to_entities.get_mut(&p) {
            Some(v) => { v.push(Entity(idx)); return; }
            _ => ()
        };
        // Didn't return above, that means this location isn't indexed
        // yet and needs a brand new container. (Can't do this in match
        // block because borrows.)
        self.place_to_entities.insert(p, vec![Entity(idx)]);
    }

    /// Insert an entity into space.
    pub fn insert_at(&mut self, e: Entity, loc: Location) {
        self.insert(e, At(loc));
    }

    /// Return whether the parent entity or an entity contained in the parent
    /// entity contains entity e.
    pub fn contains(&self, parent: Entity, Entity(idx): Entity) -> bool {
        match self.entity_to_place.get(&idx) {
            Some(&In(p, _)) if p == parent => true,
            Some(&In(p, _)) => self.contains(parent, p),
            _ => false
        }
    }

    /// Insert an entity into container.
    pub fn insert_in(&mut self, e: Entity, parent: Entity) {
        assert!(!self.contains(e, parent), "Trying to create circular containment");
        self.insert(e, In(parent, None));
    }

    /// Insert an entity into an equipment slot. Will panic if there already
    /// is an item present in the slot.
    pub fn equip(&mut self, e: Entity, parent: Entity, slot: Slot) {
        self.insert(e, In(parent, Some(slot)));
    }

    /// Remove an entity from the local structures but do not pop out its
    /// items. Unless the entity is added back in or the contents are handled
    /// somehow, this will leave the spatial index in an inconsistent state.
    fn single_remove(&mut self, Entity(idx): Entity) {
        if !self.entity_to_place.contains_key(&idx) { return; }

        let &p = self.entity_to_place.get(&idx).unwrap();
        self.entity_to_place.remove(&idx);

        {
            let v = self.place_to_entities.get_mut(&p).unwrap();
            assert!(v.len() > 0);
            if v.len() > 1 {
                // More than one entity present, remove this one, keep the
                // rest.
                for i in (0..v.len()) {
                    if v[i] == Entity(idx) {
                        v.swap_remove(i);
                        return;
                    }
                }
                panic!("Entity being removed from place it's not in");
            } else {
                // This was the only entity in the location.
                // Drop the entry for this location from the index.
                // (Need to drop out of scope for borrows reasons)
                assert!((*v)[0] == Entity(idx));
            }
        }
        // We only end up here if we need to clear the container for the
        // location.
        self.place_to_entities.remove(&p);
    }

    /// Remove an entity from the space. Entities contained in the entity will
    /// also be removed from the space.
    pub fn remove(&mut self, Entity(idx): Entity) {
        // Remove the contents
        for &content in self.entities_in(Entity(idx)).iter() {
            self.remove(content);
        }
        self.single_remove(Entity(idx));
    }

    fn entities(&self, p: Place) -> Vec<Entity> {
        match self.place_to_entities.get(&p) {
            None => vec![],
            Some(v) => v.clone(),
        }
    }

    /// List entities at a location.
    pub fn entities_at(&self, loc: Location) -> Vec<Entity> {
        self.entities(At(loc))
    }

    /// List entities in a container.
    pub fn entities_in(&self, parent: Entity) -> Vec<Entity> {
        // XXX: Can't make the API return an iterator (more efficient than
        // running collect) since the chain depends on a closure that captures
        // the 'parent' parameter from the outside scope, and closures can't
        // be typed in the return signature.
        self.place_to_entities.range(Included(&In(parent, None)), Unbounded)
            // Consume the contingent elements for the parent container.
            .take_while(|&(ref k, _)| if let &&In(ref p, _) = k { *p == parent } else { false })
            // Flatten the Vec results into a single stream.
            .flat_map(|(_, ref v)| v.iter())
            .map(|&x| x)
            .collect()
    }

    pub fn entity_equipped(&self, parent: Entity, slot: Slot) -> Option<Entity> {
        match self.place_to_entities.get(&In(parent, Some(slot))) {
            None => None,
            Some(v) => {
                assert!(v.len() == 1, "Slot entity container corrupt");
                Some(v[0])
            }
        }
    }

    /// Return the place of an entity if the entity is present in the space.
    pub fn get(&self, Entity(idx): Entity) -> Option<Place> {
        self.entity_to_place.get(&idx).map(|&loc| loc)
    }

    /// Flatten to an easily serializable vector.
    fn dump(&self) -> Vec<Elt> {
        let mut ret = vec![];
        for (idx, &loc) in self.entity_to_place.iter() {
            ret.push(Elt(Entity(idx), loc));
        }
        ret
    }

    /// Construct from the serialized vector.
    fn slurp(dump: Vec<Elt>) -> Spatial {
        let mut ret = Spatial::new();

        for &Elt(e, loc) in dump.iter() {
            ret.insert(e, loc);
        }
        ret
    }
}

#[derive(Clone, RustcDecodable, RustcEncodable)]
struct Elt(Entity, Place);

impl Decodable for Spatial {
    fn decode<D: Decoder>(d: &mut D) -> Result<Spatial, D::Error> {
        Ok(Spatial::slurp(try!(Decodable::decode(d))))
    }
}

impl Encodable for Spatial {
    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
        self.dump().encode(s)
    }
}

#[cfg(test)]
mod test {
    use super::{Place};
    use item::Slot;
    use entity::Entity;

    #[test]
    fn test_place_adjacency() {
        // Test that the Place type gets a lexical ordering where elements in
        // the same parent entity get sorted next to each other, and that None
        // is the minimum value for the slot option.
        //
        // This needs to be right for the containment logic to function, but
        // it's not obvious which way the derived lexical order sorts, so put
        // an unit test here to check it out.
        let mut places = vec![
            Place::In(Entity(0), Some(Slot::Melee)),
            Place::In(Entity(1), None),
            Place::In(Entity(0), Some(Slot::Ranged)),
            Place::In(Entity(0), None),
        ];

        places.sort();
        assert_eq!(places,
            vec![
                Place::In(Entity(0), None),
                Place::In(Entity(0), Some(Slot::Melee)),
                Place::In(Entity(0), Some(Slot::Ranged)),
                Place::In(Entity(1), None),
            ]);
    }
}
<commit_msg>Use a nasty hack instead of unstable BTreeMap bounds<commit_after>use std::collections::{BTreeMap};
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
use vec_map::{VecMap};
use entity::{Entity};
use location::{Location};
use item::Slot;
use self::Place::*;

/// Entities can be placed either on open locations or inside other entities.
/// A sum type will represent this nicely.
#[derive(Copy, Eq, PartialEq, Clone, PartialOrd, Ord, Debug, RustcEncodable, RustcDecodable)]
pub enum Place {
    At(Location),
    In(Entity, Option<Slot>),
}

/// Spatial index for game entities
pub struct Spatial {
    place_to_entities: BTreeMap<Place, Vec<Entity>>,
    entity_to_place: VecMap<Place>,
}

impl Spatial {
    pub fn new() -> Spatial {
        Spatial {
            place_to_entities: BTreeMap::new(),
            entity_to_place: VecMap::new(),
        }
    }

    fn insert(&mut self, Entity(idx): Entity, p: Place) {
        // Remove the entity from its old position.
        self.single_remove(Entity(idx));

        if let In(_, Some(_)) = p {
            // Slotted in-places are a special case that can hold at most one entity.
            if self.place_to_entities.contains_key(&p) {
                panic!("Equipping to an occupied inventory slot");
            }
        }

        self.entity_to_place.insert(idx, p);
        match self.place_to_entities.get_mut(&p) {
            Some(v) => { v.push(Entity(idx)); return; }
            _ => ()
        };
        // Didn't return above, that means this location isn't indexed
        // yet and needs a brand new container. (Can't do this in match
        // block because borrows.)
        self.place_to_entities.insert(p, vec![Entity(idx)]);
    }

    /// Insert an entity into space.
    pub fn insert_at(&mut self, e: Entity, loc: Location) {
        self.insert(e, At(loc));
    }

    /// Return whether the parent entity or an entity contained in the parent
    /// entity contains entity e.
    pub fn contains(&self, parent: Entity, Entity(idx): Entity) -> bool {
        match self.entity_to_place.get(&idx) {
            Some(&In(p, _)) if p == parent => true,
            Some(&In(p, _)) => self.contains(parent, p),
            _ => false
        }
    }

    /// Insert an entity into container.
    pub fn insert_in(&mut self, e: Entity, parent: Entity) {
        assert!(!self.contains(e, parent), "Trying to create circular containment");
        self.insert(e, In(parent, None));
    }

    /// Insert an entity into an equipment slot. Will panic if there already
    /// is an item present in the slot.
    pub fn equip(&mut self, e: Entity, parent: Entity, slot: Slot) {
        self.insert(e, In(parent, Some(slot)));
    }

    /// Remove an entity from the local structures but do not pop out its
    /// items. Unless the entity is added back in or the contents are handled
    /// somehow, this will leave the spatial index in an inconsistent state.
    fn single_remove(&mut self, Entity(idx): Entity) {
        if !self.entity_to_place.contains_key(&idx) { return; }

        let &p = self.entity_to_place.get(&idx).unwrap();
        self.entity_to_place.remove(&idx);

        {
            let v = self.place_to_entities.get_mut(&p).unwrap();
            assert!(v.len() > 0);
            if v.len() > 1 {
                // More than one entity present, remove this one, keep the
                // rest.
                for i in (0..v.len()) {
                    if v[i] == Entity(idx) {
                        v.swap_remove(i);
                        return;
                    }
                }
                panic!("Entity being removed from place it's not in");
            } else {
                // This was the only entity in the location.
                // Drop the entry for this location from the index.
                // (Need to drop out of scope for borrows reasons)
                assert!((*v)[0] == Entity(idx));
            }
        }
        // We only end up here if we need to clear the container for the
        // location.
        self.place_to_entities.remove(&p);
    }

    /// Remove an entity from the space. Entities contained in the entity will
    /// also be removed from the space.
    pub fn remove(&mut self, Entity(idx): Entity) {
        // Remove the contents
        for &content in self.entities_in(Entity(idx)).iter() {
            self.remove(content);
        }
        self.single_remove(Entity(idx));
    }

    fn entities(&self, p: Place) -> Vec<Entity> {
        match self.place_to_entities.get(&p) {
            None => vec![],
            Some(v) => v.clone(),
        }
    }

    /// List entities at a location.
    pub fn entities_at(&self, loc: Location) -> Vec<Entity> {
        self.entities(At(loc))
    }

    /// List entities in a container.
    pub fn entities_in(&self, parent: Entity) -> Vec<Entity> {
        // XXX: Can't make the API return an iterator (more efficient than
        // running collect) since the chain depends on a closure that captures
        // the 'parent' parameter from the outside scope, and closures can't
        // be typed in the return signature.

        // TODO: Get range iteration for BTreeMaps working in stable Rust.
        /*
        self.place_to_entities.range(Included(&In(parent, None)), Unbounded)
            // Consume the contingent elements for the parent container.
            .take_while(|&(ref k, _)| if let &&In(ref p, _) = k { *p == parent } else { false })
         */

        // XXX: This replacement thing is quite nasty, it iterates over the
        // whole collection for every query.
        self.place_to_entities.iter()
            .filter(|&(ref k, _)|
                        if let &&In(ref p, _) = k {*p == parent} else { false })

            // Flatten the Vec results into a single stream.
            .flat_map(|(_, ref v)| v.iter())
            .map(|&x| x)
            .collect()
    }

    pub fn entity_equipped(&self, parent: Entity, slot: Slot) -> Option<Entity> {
        match self.place_to_entities.get(&In(parent, Some(slot))) {
            None => None,
            Some(v) => {
                assert!(v.len() == 1, "Slot entity container corrupt");
                Some(v[0])
            }
        }
    }

    /// Return the place of an entity if the entity is present in the space.
    pub fn get(&self, Entity(idx): Entity) -> Option<Place> {
        self.entity_to_place.get(&idx).map(|&loc| loc)
    }

    /// Flatten to an easily serializable vector.
    fn dump(&self) -> Vec<Elt> {
        let mut ret = vec![];
        for (idx, &loc) in self.entity_to_place.iter() {
            ret.push(Elt(Entity(idx), loc));
        }
        ret
    }

    /// Construct from the serialized vector.
    fn slurp(dump: Vec<Elt>) -> Spatial {
        let mut ret = Spatial::new();

        for &Elt(e, loc) in dump.iter() {
            ret.insert(e, loc);
        }
        ret
    }
}

#[derive(Clone, RustcDecodable, RustcEncodable)]
struct Elt(Entity, Place);

impl Decodable for Spatial {
    fn decode<D: Decoder>(d: &mut D) -> Result<Spatial, D::Error> {
        Ok(Spatial::slurp(try!(Decodable::decode(d))))
    }
}

impl Encodable for Spatial {
    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
        self.dump().encode(s)
    }
}

#[cfg(test)]
mod test {
    use super::{Place};
    use item::Slot;
    use entity::Entity;

    #[test]
    fn test_place_adjacency() {
        // Test that the Place type gets a lexical ordering where elements in
        // the same parent entity get sorted next to each other, and that None
        // is the minimum value for the slot option.
        //
        // This needs to be right for the containment logic to function, but
        // it's not obvious which way the derived lexical order sorts, so put
        // an unit test here to check it out.
        let mut places = vec![
            Place::In(Entity(0), Some(Slot::Melee)),
            Place::In(Entity(1), None),
            Place::In(Entity(0), Some(Slot::Ranged)),
            Place::In(Entity(0), None),
        ];

        places.sort();
        assert_eq!(places,
            vec![
                Place::In(Entity(0), None),
                Place::In(Entity(0), Some(Slot::Melee)),
                Place::In(Entity(0), Some(Slot::Ranged)),
                Place::In(Entity(1), None),
            ]);
    }
}
<|endoftext|>


<commit_before>mod changelog;

use xshell::{cmd, Shell};

use crate::{date_iso, flags, is_release_tag, project_root};

impl flags::Release {
    pub(crate) fn run(self, sh: &Shell) -> anyhow::Result<()> {
        if !self.dry_run {
            cmd!(sh, "git switch release").run()?;
            cmd!(sh, "git fetch upstream --tags --force").run()?;
            cmd!(sh, "git reset --hard tags/nightly").run()?;
            // The `release` branch sometimes has a couple of cherry-picked
            // commits for patch releases. If that's the case, just overwrite
            // it. As we are setting `release` branch to an up-to-date `nightly`
            // tag, this shouldn't be problematic in general.
            //
            // Note that, as we tag releases, we don't worry about "losing"
            // commits -- they'll be kept alive by the tag. More generally, we
            // don't care about historic releases all that much, it's fine even
            // to delete old tags.
            cmd!(sh, "git push --force").run()?;
        }

        // Generates bits of manual.adoc.
        cmd!(sh, "cargo test -p ide-assists -p ide-diagnostics -p rust-analyzer -- sourcegen_")
            .run()?;

        let website_root = project_root().join("../rust-analyzer.github.io");
        {
            let _dir = sh.push_dir(&website_root);
            cmd!(sh, "git switch src").run()?;
            cmd!(sh, "git pull").run()?;
        }
        let changelog_dir = website_root.join("./thisweek/_posts");

        let today = date_iso(sh)?;
        let commit = cmd!(sh, "git rev-parse HEAD").read()?;
        let changelog_n = sh.read_dir(changelog_dir.as_path())?.len();

        for adoc in [
            "manual.adoc",
            "generated_assists.adoc",
            "generated_config.adoc",
            "generated_diagnostic.adoc",
            "generated_features.adoc",
        ] {
            let src = project_root().join("./docs/user/").join(adoc);
            let dst = website_root.join(adoc);

            let contents = sh.read_file(src)?;
            sh.write_file(dst, contents)?;
        }

        let tags = cmd!(sh, "git tag --list").read()?;
        let prev_tag = tags.lines().filter(|line| is_release_tag(line)).last().unwrap();

        let contents = changelog::get_changelog(sh, changelog_n, &commit, prev_tag, &today)?;
        let path = changelog_dir.join(format!("{}-changelog-{}.adoc", today, changelog_n));
        sh.write_file(&path, &contents)?;

        Ok(())
    }
}

impl flags::Promote {
    pub(crate) fn run(self, sh: &Shell) -> anyhow::Result<()> {
        let _dir = sh.push_dir("../rust-rust-analyzer");
        cmd!(sh, "git switch master").run()?;
        cmd!(sh, "git fetch upstream").run()?;
        cmd!(sh, "git reset --hard upstream/master").run()?;
        cmd!(sh, "git submodule update --recursive").run()?;

        let date = date_iso(sh)?;
        let branch = format!("rust-analyzer-{date}");
        cmd!(sh, "git switch -c {branch}").run()?;
        {
            let _dir = sh.push_dir("src/tools/rust-analyzer");
            cmd!(sh, "git fetch origin").run()?;
            cmd!(sh, "git reset --hard origin/release").run()?;
        }
        cmd!(sh, "git add src/tools/rust-analyzer").run()?;
        cmd!(sh, "git commit -m':arrow_up: rust-analyzer'").run()?;
        if !self.dry_run {
            cmd!(sh, "git push -u origin {branch}").run()?;
            cmd!(
                sh,
                "xdg-open https://github.com/matklad/rust/pull/new/{branch}?body=r%3F%20%40ghost"
            )
            .run()?;
        }
        Ok(())
    }
}
<commit_msg>Auto merge of #12581 - lnicola:changelog-number, r=lnicola<commit_after>mod changelog;

use xshell::{cmd, Shell};

use crate::{date_iso, flags, is_release_tag, project_root};

impl flags::Release {
    pub(crate) fn run(self, sh: &Shell) -> anyhow::Result<()> {
        if !self.dry_run {
            cmd!(sh, "git switch release").run()?;
            cmd!(sh, "git fetch upstream --tags --force").run()?;
            cmd!(sh, "git reset --hard tags/nightly").run()?;
            // The `release` branch sometimes has a couple of cherry-picked
            // commits for patch releases. If that's the case, just overwrite
            // it. As we are setting `release` branch to an up-to-date `nightly`
            // tag, this shouldn't be problematic in general.
            //
            // Note that, as we tag releases, we don't worry about "losing"
            // commits -- they'll be kept alive by the tag. More generally, we
            // don't care about historic releases all that much, it's fine even
            // to delete old tags.
            cmd!(sh, "git push --force").run()?;
        }

        // Generates bits of manual.adoc.
        cmd!(sh, "cargo test -p ide-assists -p ide-diagnostics -p rust-analyzer -- sourcegen_")
            .run()?;

        let website_root = project_root().join("../rust-analyzer.github.io");
        {
            let _dir = sh.push_dir(&website_root);
            cmd!(sh, "git switch src").run()?;
            cmd!(sh, "git pull").run()?;
        }
        let changelog_dir = website_root.join("./thisweek/_posts");

        let today = date_iso(sh)?;
        let commit = cmd!(sh, "git rev-parse HEAD").read()?;
        let changelog_n = sh
            .read_dir(changelog_dir.as_path())?
            .into_iter()
            .filter_map(|p| p.file_stem().map(|s| s.to_string_lossy().to_string()))
            .filter_map(|s| s.splitn(5, '-').last().map(|n| n.replace('-', ".")))
            .filter_map(|s| s.parse::<f32>().ok())
            .map(|n| 1 + n.floor() as usize)
            .max()
            .unwrap_or_default();

        for adoc in [
            "manual.adoc",
            "generated_assists.adoc",
            "generated_config.adoc",
            "generated_diagnostic.adoc",
            "generated_features.adoc",
        ] {
            let src = project_root().join("./docs/user/").join(adoc);
            let dst = website_root.join(adoc);

            let contents = sh.read_file(src)?;
            sh.write_file(dst, contents)?;
        }

        let tags = cmd!(sh, "git tag --list").read()?;
        let prev_tag = tags.lines().filter(|line| is_release_tag(line)).last().unwrap();

        let contents = changelog::get_changelog(sh, changelog_n, &commit, prev_tag, &today)?;
        let path = changelog_dir.join(format!("{}-changelog-{}.adoc", today, changelog_n));
        sh.write_file(&path, &contents)?;

        Ok(())
    }
}

impl flags::Promote {
    pub(crate) fn run(self, sh: &Shell) -> anyhow::Result<()> {
        let _dir = sh.push_dir("../rust-rust-analyzer");
        cmd!(sh, "git switch master").run()?;
        cmd!(sh, "git fetch upstream").run()?;
        cmd!(sh, "git reset --hard upstream/master").run()?;
        cmd!(sh, "git submodule update --recursive").run()?;

        let date = date_iso(sh)?;
        let branch = format!("rust-analyzer-{date}");
        cmd!(sh, "git switch -c {branch}").run()?;
        {
            let _dir = sh.push_dir("src/tools/rust-analyzer");
            cmd!(sh, "git fetch origin").run()?;
            cmd!(sh, "git reset --hard origin/release").run()?;
        }
        cmd!(sh, "git add src/tools/rust-analyzer").run()?;
        cmd!(sh, "git commit -m':arrow_up: rust-analyzer'").run()?;
        if !self.dry_run {
            cmd!(sh, "git push -u origin {branch}").run()?;
            cmd!(
                sh,
                "xdg-open https://github.com/matklad/rust/pull/new/{branch}?body=r%3F%20%40ghost"
            )
            .run()?;
        }
        Ok(())
    }
}
<|endoftext|>


<commit_before>/*
 * Copyright 2017 Sreejith Krishnan R
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
*/

use ::props::*;

#[derive(Immutable, Clone)]
pub struct InheritedProps {
    display_style: bool,
    math_size: MathSize,
    script_level: ScriptLevel,
    dir: Directionality,
    math_color: Color,
    script_size_multiplier: f32,
    script_min_size: f32,
    linebreak_mult_char: String,
    indent_align:IndentAlign,
    indent_shift: Length,
    indent_target: Option<String>,
    indent_align_first: IndentAlignFirstLast,
    indent_shift_first: IndentShiftFirstLast,
    indent_align_last: IndentAlignFirstLast,
    indent_shift_last: IndentShiftFirstLast,
    table_row_align: VAlign,
    table_column_align: Vec<HAlign>,
    table_group_align: Vec<Vec<GroupAlign>>,
    table_mtd_column_align: HAlign,
    table_mtd_group_align: Vec<GroupAlign>,
}

impl InheritedProps {
    pub fn new() -> InheritedProps {
        InheritedProps {
            display_style: true,
            script_level: ScriptLevel::new(0, 64.),
            math_size: MathSize::NORMAL,
            dir: Directionality::LTR,
            math_color: Color::parse("#000000").unwrap(),
            script_size_multiplier: 0.707,
            script_min_size: 8.0,
            linebreak_mult_char: String::from("\u{2062}"),
            indent_align: IndentAlign::Auto,
            indent_shift: Length::PX(0.0),
            indent_target: None,
            indent_align_first: IndentAlignFirstLast::IndentAlign,
            indent_shift_first: IndentShiftFirstLast::IndentShift,
            indent_align_last: IndentAlignFirstLast::IndentAlign,
            indent_shift_last: IndentShiftFirstLast::IndentShift,
            table_row_align: VAlign::Baseline,
            table_column_align: vec![HAlign::Center],
            table_group_align: vec![vec![GroupAlign::Left]],
            table_mtd_column_align: HAlign::Center,
            table_mtd_group_align: vec![GroupAlign::Left]
        }
    }
}<commit_msg>Rust idiomatic<commit_after>/*
 * Copyright 2017 Sreejith Krishnan R
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
*/

use ::props::*;

#[derive(Immutable, Clone)]
pub struct InheritedProps {
    display_style: bool,
    math_size: MathSize,
    script_level: ScriptLevel,
    dir: Directionality,
    math_color: Color,
    script_size_multiplier: f32,
    script_min_size: f32,
    linebreak_mult_char: String,
    indent_align:IndentAlign,
    indent_shift: Length,
    indent_target: Option<String>,
    indent_align_first: IndentAlignFirstLast,
    indent_shift_first: IndentShiftFirstLast,
    indent_align_last: IndentAlignFirstLast,
    indent_shift_last: IndentShiftFirstLast,
    table_row_align: VAlign,
    table_column_align: Vec<HAlign>,
    table_group_align: Vec<Vec<GroupAlign>>,
    table_mtd_column_align: HAlign,
    table_mtd_group_align: Vec<GroupAlign>,
}

impl Default for InheritedProps {
    fn default() -> InheritedProps {
        InheritedProps {
            display_style: true,
            script_level: ScriptLevel::new(0, 64.),
            math_size: MathSize::NORMAL,
            dir: Directionality::LTR,
            math_color: Color::parse("#000000").unwrap(),
            script_size_multiplier: 0.707,
            script_min_size: 8.0,
            linebreak_mult_char: String::from("\u{2062}"),
            indent_align: IndentAlign::Auto,
            indent_shift: Length::PX(0.0),
            indent_target: None,
            indent_align_first: IndentAlignFirstLast::IndentAlign,
            indent_shift_first: IndentShiftFirstLast::IndentShift,
            indent_align_last: IndentAlignFirstLast::IndentAlign,
            indent_shift_last: IndentShiftFirstLast::IndentShift,
            table_row_align: VAlign::Baseline,
            table_column_align: vec![HAlign::Center],
            table_group_align: vec![vec![GroupAlign::Left]],
            table_mtd_column_align: HAlign::Center,
            table_mtd_group_align: vec![GroupAlign::Left]
        }
    }
}<|endoftext|>


<commit_before>///! Basic tests for instructions/constructions, missing in wabt tests

use std::sync::{Arc, Weak};
use builder::module;
use elements::{ExportEntry, Internal, ImportEntry, External, GlobalEntry, GlobalType,
	InitExpr, ValueType, BlockType, Opcodes, Opcode, FunctionType};
use interpreter::Error;
use interpreter::env_native::{env_native_module, UserFunctions, UserFunctionExecutor, UserFunctionDescriptor};
use interpreter::memory::MemoryInstance;
use interpreter::module::{ModuleInstance, ModuleInstanceInterface, CallerContext, ItemIndex, ExecutionParams, ExportEntryType, FunctionSignature};
use interpreter::program::ProgramInstance;
use interpreter::validator::{FunctionValidationContext, Validator};
use interpreter::value::RuntimeValue;

#[test]
fn import_function() {
	let module1 = module()
		.with_export(ExportEntry::new("external_func".into(), Internal::Function(0)))
		.function()
			.signature().return_type().i32().build()
			.body().with_opcodes(Opcodes::new(vec![
				Opcode::I32Const(3),
				Opcode::End,
			])).build()
			.build()
		.build();

	let module2 = module()
		.with_import(ImportEntry::new("external_module".into(), "external_func".into(), External::Function(0)))
		.function()
			.signature().return_type().i32().build()
			.body().with_opcodes(Opcodes::new(vec![
				Opcode::Call(0),
				Opcode::I32Const(7),
				Opcode::I32Add,
				Opcode::End,
			])).build()
			.build()
		.build();

	let program = ProgramInstance::new().unwrap();
	let external_module = program.add_module("external_module", module1, None).unwrap();
	let main_module = program.add_module("main", module2, None).unwrap();

	assert_eq!(external_module.execute_index(0, vec![].into()).unwrap().unwrap(), RuntimeValue::I32(3));
	assert_eq!(main_module.execute_index(1, vec![].into()).unwrap().unwrap(), RuntimeValue::I32(10));
}

#[test]
fn wrong_import() {
	let side_module = module()
		.with_export(ExportEntry::new("cool_func".into(), Internal::Function(0)))
		.function()
			.signature().return_type().i32().build()
			.body().with_opcodes(Opcodes::new(vec![
				Opcode::I32Const(3),
				Opcode::End,
			])).build()
			.build()
		.build();

	let module = module()
		.with_import(ImportEntry::new("side_module".into(), "not_cool_func".into(), External::Function(0)))
		.function()
			.signature().return_type().i32().build()
			.body().with_opcodes(Opcodes::new(vec![
				Opcode::Call(0),
				Opcode::I32Const(7),
				Opcode::I32Add,
				Opcode::End,
			])).build()
			.build()
		.build();

	let program = ProgramInstance::new().unwrap();
	let _side_module_instance = program.add_module("side_module", side_module, None).unwrap();
	assert!(program.add_module("main", module, None).is_err());
}

#[test]
fn global_get_set() {
	let module = module()
		.with_global(GlobalEntry::new(GlobalType::new(ValueType::I32, true), InitExpr::new(vec![Opcode::I32Const(42)])))
		.function()
			.signature().return_type().i32().build()
			.body().with_opcodes(Opcodes::new(vec![
				Opcode::GetGlobal(0),
				Opcode::I32Const(8),
				Opcode::I32Add,
				Opcode::SetGlobal(0),
				Opcode::GetGlobal(0),
				Opcode::End,
			])).build()
			.build()
		.build();

	let program = ProgramInstance::new().unwrap();
	let module = program.add_module("main", module, None).unwrap();
	assert_eq!(module.execute_index(0, vec![].into()).unwrap().unwrap(), RuntimeValue::I32(50));
}

const SIGNATURE_I32_I32: &'static [ValueType] = &[ValueType::I32, ValueType::I32];

const SIGNATURES: &'static [UserFunctionDescriptor] = &[
	UserFunctionDescriptor::Static(
		"add",
		SIGNATURE_I32_I32,
		Some(ValueType::I32),
	),
	UserFunctionDescriptor::Static(
		"sub",
		SIGNATURE_I32_I32,
		Some(ValueType::I32),
	),
];

// user function executor
struct FunctionExecutor {
	pub memory: Arc<MemoryInstance>,
	pub values: Vec<i32>,
}

impl UserFunctionExecutor for FunctionExecutor {
	fn execute(&mut self, name: &str, context: CallerContext) -> Result<Option<RuntimeValue>, Error> {
		match name {
			"add" => {
				let memory_value = self.memory.get(0, 1).unwrap()[0];
				let fn_argument_unused = context.value_stack.pop_as::<u32>().unwrap() as u8;
				let fn_argument = context.value_stack.pop_as::<u32>().unwrap() as u8;
				assert_eq!(fn_argument_unused, 0);

				let sum = memory_value + fn_argument;
				self.memory.set(0, &vec![sum]).unwrap();
				self.values.push(sum as i32);
				Ok(Some(RuntimeValue::I32(sum as i32)))
			},
			"sub" => {
				let memory_value = self.memory.get(0, 1).unwrap()[0];
				let fn_argument_unused = context.value_stack.pop_as::<u32>().unwrap() as u8;
				let fn_argument = context.value_stack.pop_as::<u32>().unwrap() as u8;
				assert_eq!(fn_argument_unused, 0);

				let diff = memory_value - fn_argument;
				self.memory.set(0, &vec![diff]).unwrap();
				self.values.push(diff as i32);
				Ok(Some(RuntimeValue::I32(diff as i32)))
			},
			_ => Err(Error::Trap("not implemented".into())),
		}
	}
}

#[test]
fn single_program_different_modules() {
	// create new program
	let program = ProgramInstance::new().unwrap();
	// => env module is created
	let env_instance = program.module("env").unwrap();
	// => linear memory is created
	let env_memory = env_instance.memory(ItemIndex::Internal(0)).unwrap();

	// create native env module executor
	let mut executor = FunctionExecutor {
		memory: env_memory.clone(),
		values: Vec::new(),
	};
	{
		let functions: UserFunctions = UserFunctions {
			executor: &mut executor,
			functions: ::std::borrow::Cow::from(SIGNATURES),
		};
		let native_env_instance = Arc::new(env_native_module(env_instance, functions).unwrap());
		let params = ExecutionParams::with_external("env".into(), native_env_instance);

		let module = module()
			.with_import(ImportEntry::new("env".into(), "add".into(), External::Function(0)))
			.with_import(ImportEntry::new("env".into(), "sub".into(), External::Function(0)))
			.function()
				.signature().param().i32().param().i32().return_type().i32().build()
				.body().with_opcodes(Opcodes::new(vec![
					Opcode::GetLocal(0),
					Opcode::GetLocal(1),
					Opcode::Call(0),
					Opcode::End,
				])).build()
				.build()
			.function()
				.signature().param().i32().param().i32().return_type().i32().build()
				.body().with_opcodes(Opcodes::new(vec![
					Opcode::GetLocal(0),
					Opcode::GetLocal(1),
					Opcode::Call(1),
					Opcode::End,
				])).build()
				.build()
			.build();

		// load module
		let module_instance = program.add_module("main", module, Some(&params.externals)).unwrap();

		{
			assert_eq!(module_instance.execute_index(2, params.clone().add_argument(RuntimeValue::I32(7)).add_argument(RuntimeValue::I32(0))).unwrap().unwrap(), RuntimeValue::I32(7));
			assert_eq!(module_instance.execute_index(2, params.clone().add_argument(RuntimeValue::I32(50)).add_argument(RuntimeValue::I32(0))).unwrap().unwrap(), RuntimeValue::I32(57));
			assert_eq!(module_instance.execute_index(3, params.clone().add_argument(RuntimeValue::I32(15)).add_argument(RuntimeValue::I32(0))).unwrap().unwrap(), RuntimeValue::I32(42));
		}
	}

	assert_eq!(executor.memory.get(0, 1).unwrap()[0], 42);
	assert_eq!(executor.values, vec![7, 57, 42]);
}

#[test]
fn env_native_export_entry_type_check() {
	let program = ProgramInstance::new().unwrap();
	let mut function_executor = FunctionExecutor {
		memory: program.module("env").unwrap().memory(ItemIndex::Internal(0)).unwrap(),
		values: Vec::new(),
	};
	let native_env_instance = Arc::new(env_native_module(program.module("env").unwrap(), UserFunctions {
		executor: &mut function_executor,
		functions: ::std::borrow::Cow::from(SIGNATURES),
	}).unwrap());

	assert!(native_env_instance.export_entry("add", &ExportEntryType::Function(FunctionSignature::Module(&FunctionType::new(vec![ValueType::I32, ValueType::I32], Some(ValueType::I32))))).is_ok());
	assert!(native_env_instance.export_entry("add", &ExportEntryType::Function(FunctionSignature::Module(&FunctionType::new(vec![], Some(ValueType::I32))))).is_err());
	assert!(native_env_instance.export_entry("add", &ExportEntryType::Function(FunctionSignature::Module(&FunctionType::new(vec![ValueType::I32, ValueType::I32], None)))).is_err());
	assert!(native_env_instance.export_entry("add", &ExportEntryType::Function(FunctionSignature::Module(&FunctionType::new(vec![ValueType::I32, ValueType::I32], Some(ValueType::I64))))).is_err());
}

#[test]
fn if_else_with_return_type_validation() {
	let module_instance = ModuleInstance::new(Weak::default(), "test".into(), module().build()).unwrap();
	let mut context = FunctionValidationContext::new(&module_instance, &[], 1024, 1024, FunctionSignature::Module(&FunctionType::default()));

	Validator::validate_function(&mut context, BlockType::NoResult, &[
		Opcode::I32Const(1),
		Opcode::If(BlockType::NoResult),
			Opcode::I32Const(1),
			Opcode::If(BlockType::Value(ValueType::I32)),
				Opcode::I32Const(1),
			Opcode::Else,
				Opcode::I32Const(2),
			Opcode::End,
		Opcode::Drop,
		Opcode::End,
		Opcode::End,
	]).unwrap();
}
<commit_msg>assert global value persistence<commit_after>///! Basic tests for instructions/constructions, missing in wabt tests

use std::sync::{Arc, Weak};
use builder::module;
use elements::{ExportEntry, Internal, ImportEntry, External, GlobalEntry, GlobalType,
	InitExpr, ValueType, BlockType, Opcodes, Opcode, FunctionType};
use interpreter::Error;
use interpreter::env_native::{env_native_module, UserFunctions, UserFunctionExecutor, UserFunctionDescriptor};
use interpreter::memory::MemoryInstance;
use interpreter::module::{ModuleInstance, ModuleInstanceInterface, CallerContext, ItemIndex, ExecutionParams, ExportEntryType, FunctionSignature};
use interpreter::program::ProgramInstance;
use interpreter::validator::{FunctionValidationContext, Validator};
use interpreter::value::RuntimeValue;

#[test]
fn import_function() {
	let module1 = module()
		.with_export(ExportEntry::new("external_func".into(), Internal::Function(0)))
		.function()
			.signature().return_type().i32().build()
			.body().with_opcodes(Opcodes::new(vec![
				Opcode::I32Const(3),
				Opcode::End,
			])).build()
			.build()
		.build();

	let module2 = module()
		.with_import(ImportEntry::new("external_module".into(), "external_func".into(), External::Function(0)))
		.function()
			.signature().return_type().i32().build()
			.body().with_opcodes(Opcodes::new(vec![
				Opcode::Call(0),
				Opcode::I32Const(7),
				Opcode::I32Add,
				Opcode::End,
			])).build()
			.build()
		.build();

	let program = ProgramInstance::new().unwrap();
	let external_module = program.add_module("external_module", module1, None).unwrap();
	let main_module = program.add_module("main", module2, None).unwrap();

	assert_eq!(external_module.execute_index(0, vec![].into()).unwrap().unwrap(), RuntimeValue::I32(3));
	assert_eq!(main_module.execute_index(1, vec![].into()).unwrap().unwrap(), RuntimeValue::I32(10));
}

#[test]
fn wrong_import() {
	let side_module = module()
		.with_export(ExportEntry::new("cool_func".into(), Internal::Function(0)))
		.function()
			.signature().return_type().i32().build()
			.body().with_opcodes(Opcodes::new(vec![
				Opcode::I32Const(3),
				Opcode::End,
			])).build()
			.build()
		.build();

	let module = module()
		.with_import(ImportEntry::new("side_module".into(), "not_cool_func".into(), External::Function(0)))
		.function()
			.signature().return_type().i32().build()
			.body().with_opcodes(Opcodes::new(vec![
				Opcode::Call(0),
				Opcode::I32Const(7),
				Opcode::I32Add,
				Opcode::End,
			])).build()
			.build()
		.build();

	let program = ProgramInstance::new().unwrap();
	let _side_module_instance = program.add_module("side_module", side_module, None).unwrap();
	assert!(program.add_module("main", module, None).is_err());
}

#[test]
fn global_get_set() {
	let module = module()
		.with_global(GlobalEntry::new(GlobalType::new(ValueType::I32, true), InitExpr::new(vec![Opcode::I32Const(42)])))
		.function()
			.signature().return_type().i32().build()
			.body().with_opcodes(Opcodes::new(vec![
				Opcode::GetGlobal(0),
				Opcode::I32Const(8),
				Opcode::I32Add,
				Opcode::SetGlobal(0),
				Opcode::GetGlobal(0),
				Opcode::End,
			])).build()
			.build()
		.build();

	let program = ProgramInstance::new().unwrap();
	let module = program.add_module("main", module, None).unwrap();
	assert_eq!(module.execute_index(0, vec![].into()).unwrap().unwrap(), RuntimeValue::I32(50));
	assert_eq!(module.execute_index(0, vec![].into()).unwrap().unwrap(), RuntimeValue::I32(58));
}

const SIGNATURE_I32_I32: &'static [ValueType] = &[ValueType::I32, ValueType::I32];

const SIGNATURES: &'static [UserFunctionDescriptor] = &[
	UserFunctionDescriptor::Static(
		"add",
		SIGNATURE_I32_I32,
		Some(ValueType::I32),
	),
	UserFunctionDescriptor::Static(
		"sub",
		SIGNATURE_I32_I32,
		Some(ValueType::I32),
	),
];

// user function executor
struct FunctionExecutor {
	pub memory: Arc<MemoryInstance>,
	pub values: Vec<i32>,
}

impl UserFunctionExecutor for FunctionExecutor {
	fn execute(&mut self, name: &str, context: CallerContext) -> Result<Option<RuntimeValue>, Error> {
		match name {
			"add" => {
				let memory_value = self.memory.get(0, 1).unwrap()[0];
				let fn_argument_unused = context.value_stack.pop_as::<u32>().unwrap() as u8;
				let fn_argument = context.value_stack.pop_as::<u32>().unwrap() as u8;
				assert_eq!(fn_argument_unused, 0);

				let sum = memory_value + fn_argument;
				self.memory.set(0, &vec![sum]).unwrap();
				self.values.push(sum as i32);
				Ok(Some(RuntimeValue::I32(sum as i32)))
			},
			"sub" => {
				let memory_value = self.memory.get(0, 1).unwrap()[0];
				let fn_argument_unused = context.value_stack.pop_as::<u32>().unwrap() as u8;
				let fn_argument = context.value_stack.pop_as::<u32>().unwrap() as u8;
				assert_eq!(fn_argument_unused, 0);

				let diff = memory_value - fn_argument;
				self.memory.set(0, &vec![diff]).unwrap();
				self.values.push(diff as i32);
				Ok(Some(RuntimeValue::I32(diff as i32)))
			},
			_ => Err(Error::Trap("not implemented".into())),
		}
	}
}

#[test]
fn single_program_different_modules() {
	// create new program
	let program = ProgramInstance::new().unwrap();
	// => env module is created
	let env_instance = program.module("env").unwrap();
	// => linear memory is created
	let env_memory = env_instance.memory(ItemIndex::Internal(0)).unwrap();

	// create native env module executor
	let mut executor = FunctionExecutor {
		memory: env_memory.clone(),
		values: Vec::new(),
	};
	{
		let functions: UserFunctions = UserFunctions {
			executor: &mut executor,
			functions: ::std::borrow::Cow::from(SIGNATURES),
		};
		let native_env_instance = Arc::new(env_native_module(env_instance, functions).unwrap());
		let params = ExecutionParams::with_external("env".into(), native_env_instance);

		let module = module()
			.with_import(ImportEntry::new("env".into(), "add".into(), External::Function(0)))
			.with_import(ImportEntry::new("env".into(), "sub".into(), External::Function(0)))
			.function()
				.signature().param().i32().param().i32().return_type().i32().build()
				.body().with_opcodes(Opcodes::new(vec![
					Opcode::GetLocal(0),
					Opcode::GetLocal(1),
					Opcode::Call(0),
					Opcode::End,
				])).build()
				.build()
			.function()
				.signature().param().i32().param().i32().return_type().i32().build()
				.body().with_opcodes(Opcodes::new(vec![
					Opcode::GetLocal(0),
					Opcode::GetLocal(1),
					Opcode::Call(1),
					Opcode::End,
				])).build()
				.build()
			.build();

		// load module
		let module_instance = program.add_module("main", module, Some(&params.externals)).unwrap();

		{
			assert_eq!(module_instance.execute_index(2, params.clone().add_argument(RuntimeValue::I32(7)).add_argument(RuntimeValue::I32(0))).unwrap().unwrap(), RuntimeValue::I32(7));
			assert_eq!(module_instance.execute_index(2, params.clone().add_argument(RuntimeValue::I32(50)).add_argument(RuntimeValue::I32(0))).unwrap().unwrap(), RuntimeValue::I32(57));
			assert_eq!(module_instance.execute_index(3, params.clone().add_argument(RuntimeValue::I32(15)).add_argument(RuntimeValue::I32(0))).unwrap().unwrap(), RuntimeValue::I32(42));
		}
	}

	assert_eq!(executor.memory.get(0, 1).unwrap()[0], 42);
	assert_eq!(executor.values, vec![7, 57, 42]);
}

#[test]
fn env_native_export_entry_type_check() {
	let program = ProgramInstance::new().unwrap();
	let mut function_executor = FunctionExecutor {
		memory: program.module("env").unwrap().memory(ItemIndex::Internal(0)).unwrap(),
		values: Vec::new(),
	};
	let native_env_instance = Arc::new(env_native_module(program.module("env").unwrap(), UserFunctions {
		executor: &mut function_executor,
		functions: ::std::borrow::Cow::from(SIGNATURES),
	}).unwrap());

	assert!(native_env_instance.export_entry("add", &ExportEntryType::Function(FunctionSignature::Module(&FunctionType::new(vec![ValueType::I32, ValueType::I32], Some(ValueType::I32))))).is_ok());
	assert!(native_env_instance.export_entry("add", &ExportEntryType::Function(FunctionSignature::Module(&FunctionType::new(vec![], Some(ValueType::I32))))).is_err());
	assert!(native_env_instance.export_entry("add", &ExportEntryType::Function(FunctionSignature::Module(&FunctionType::new(vec![ValueType::I32, ValueType::I32], None)))).is_err());
	assert!(native_env_instance.export_entry("add", &ExportEntryType::Function(FunctionSignature::Module(&FunctionType::new(vec![ValueType::I32, ValueType::I32], Some(ValueType::I64))))).is_err());
}

#[test]
fn if_else_with_return_type_validation() {
	let module_instance = ModuleInstance::new(Weak::default(), "test".into(), module().build()).unwrap();
	let mut context = FunctionValidationContext::new(&module_instance, &[], 1024, 1024, FunctionSignature::Module(&FunctionType::default()));

	Validator::validate_function(&mut context, BlockType::NoResult, &[
		Opcode::I32Const(1),
		Opcode::If(BlockType::NoResult),
			Opcode::I32Const(1),
			Opcode::If(BlockType::Value(ValueType::I32)),
				Opcode::I32Const(1),
			Opcode::Else,
				Opcode::I32Const(2),
			Opcode::End,
		Opcode::Drop,
		Opcode::End,
		Opcode::End,
	]).unwrap();
}
<|endoftext|>


<commit_before>//! An abstraction over exfiltrating information out of signal handlers.
//!
//! The [`Exfiltrator`] trait provides a way to abstract the information extracted from a signal
//! handler and the way it is extracted out of it.
//!
//! The implementations can be used to parametrize the
//! [`SignalsInfo`][crate::iterator::SignalsInfo] to specify what results are returned.
//!
//! # Sealed
//!
//! Currently, the trait is sealed and all methods hidden. This is likely temporary, until some
//! experience with them is gained.

#[cfg(feature = "extended-siginfo")]
#[cfg_attr(docsrs, doc(cfg(feature = "extended-siginfo")))]
pub mod origin;
pub mod raw;

#[cfg(feature = "extended-siginfo")]
pub use origin::WithOrigin;
pub use raw::WithRawSiginfo;

use std::sync::atomic::{AtomicBool, Ordering};

use libc::{c_int, siginfo_t};

mod sealed {
    use std::fmt::Debug;

    use libc::{c_int, siginfo_t};

    /// The actual implementation of the [`Exfiltrator`][super::Exfiltrator].
    ///
    /// For now, this is hidden from the public API, but the intention is to move it to a public
    /// place so users can implement it eventually, once we verify that it works well.
    ///
    /// The trait is unsafe as the [`Exfiltrator::store`] is called inside the signal handler and
    /// must be async-signal-safe. Implementing this correctly may be difficult, therefore care
    /// needs to be taken. One method known to work is encoding the data into an atomic variable.
    /// Other, less limiting approaches, will be eventually explored.
    pub unsafe trait Exfiltrator: Debug + Send + Sync + 'static {
        /// One slot for storing the data.
        ///
        /// Each signal will get its one slot of this type, independent of other signals. It can
        /// store the information in there inside the signal handler and will be loaded from it in
        /// load.
        ///
        /// Each slot is initialized to the [`Default`] value. It is expected this value represents
        /// „no signal delivered“ state.
        type Storage: Debug + Default + Send + Sync + 'static;

        /// The type returned to the user.
        type Output;

        /// If the given signal is supported by this specific exfiltrator.
        ///
        /// Not all information is available to all signals, therefore not all exfiltrators must
        /// support all signals. If `false` is returned, the user is prevented for registering such
        /// signal number with the given exfiltrator.
        fn supports_signal(&self, sig: c_int) -> bool;

        /// Puts the signal information inside the slot.
        ///
        /// It needs to somehow store the relevant information and the fact that a signal happened.
        ///
        /// # Warning
        ///
        /// This will be called inside the signal handler. It needs to be async-signal-safe. In
        /// particular, very small amount of operations are allowed in there. This namely does
        /// *not* include any locking nor allocation.
        ///
        /// It is also possible that multiple store methods are called concurrently; it is up to
        /// the implementor to deal with that.
        fn store(&self, slot: &Self::Storage, signal: c_int, info: &siginfo_t);

        /// Loads the signal information from the given slot.
        ///
        /// The method shall check if the signal happened (it may be possible to be called without
        /// the signal previously being delivered; it is up to the implementer to recognize it). It
        /// is assumed the [`Default`] value is recognized as no signal delivered.
        ///
        /// If it was delivered, the method shall extract the relevant information *and reset the
        /// slot* to the no signal delivered state.
        ///
        /// It shall return `Some(value)` if the signal was successfully received and `None` in
        /// case no signal was delivered.
        ///
        /// No blocking shall happen inside this method. It may be called concurrently with
        /// [`store`][Exfiltrator::store] (due to how signals work, concurrently even inside the
        /// same thread ‒ a `store` may „interrupt“ a call to `load`). It is up to the implementer
        /// to deal with that.
        fn load(&self, slot: &Self::Storage, signal: c_int) -> Option<Self::Output>;

        /// Initialize the given slot for the given signal before the first use.
        ///
        /// This is called before the first use of the given slot (and it is annotated with the
        /// corresponding signal). The default does nothing, this is just an opportunity to
        /// allocate data lazily (this is called outside of the signal handler, so it doesn't have
        /// to be async-signal-safe). It will be called at most once for each slot.
        ///
        /// Note that you can rely on this being called for correctness, but not for safety (this
        /// crate calls it before the first use, but a user abusing the trait might not and in such
        /// case it is OK to eg. lose signals, but not segfault).
        fn init(&self, slot: &Self::Storage, signal: c_int) {
            // Suppress unused variable warning without putting the underscores into public
            // signature.
            let _ = slot;
            let _ = signal;
        }
    }
}

/// A trait describing what and how is extracted from signal handlers.
///
/// By choosing a specific implementor as the type parameter for
/// [`SignalsInfo`][crate::iterator::SignalsInfo], one can pick how much and what information is
/// returned from the iterator.
pub trait Exfiltrator: sealed::Exfiltrator {}

impl<E: sealed::Exfiltrator> Exfiltrator for E {}

/// An [`Exfiltrator`] providing just the signal numbers.
///
/// This is the basic exfiltrator for most needs. For that reason, there's the
/// [`crate::iterator::Signals`] type alias, to simplify the type names for usual needs.
#[derive(Clone, Copy, Debug, Default)]
pub struct SignalOnly;

unsafe impl sealed::Exfiltrator for SignalOnly {
    type Storage = AtomicBool;
    fn supports_signal(&self, _: c_int) -> bool {
        true
    }
    type Output = c_int;

    fn store(&self, slot: &Self::Storage, _: c_int, _: &siginfo_t) {
        slot.store(true, Ordering::SeqCst);
    }

    fn load(&self, slot: &Self::Storage, signal: c_int) -> Option<Self::Output> {
        if slot
            .compare_exchange(true, false, Ordering::SeqCst, Ordering::Relaxed)
            .is_ok()
        {
            Some(signal)
        } else {
            None
        }
    }
}
<commit_msg>Make clippy shut up<commit_after>//! An abstraction over exfiltrating information out of signal handlers.
//!
//! The [`Exfiltrator`] trait provides a way to abstract the information extracted from a signal
//! handler and the way it is extracted out of it.
//!
//! The implementations can be used to parametrize the
//! [`SignalsInfo`][crate::iterator::SignalsInfo] to specify what results are returned.
//!
//! # Sealed
//!
//! Currently, the trait is sealed and all methods hidden. This is likely temporary, until some
//! experience with them is gained.

#[cfg(feature = "extended-siginfo")]
#[cfg_attr(docsrs, doc(cfg(feature = "extended-siginfo")))]
pub mod origin;
pub mod raw;

#[cfg(feature = "extended-siginfo")]
pub use origin::WithOrigin;
pub use raw::WithRawSiginfo;

use std::sync::atomic::{AtomicBool, Ordering};

use libc::{c_int, siginfo_t};

mod sealed {
    use std::fmt::Debug;

    use libc::{c_int, siginfo_t};

    /// The actual implementation of the [`Exfiltrator`][super::Exfiltrator].
    ///
    /// For now, this is hidden from the public API, but the intention is to move it to a public
    /// place so users can implement it eventually, once we verify that it works well.
    ///
    /// # Safety
    ///
    /// The trait is unsafe as the [`Exfiltrator::store`] is called inside the signal handler and
    /// must be async-signal-safe. Implementing this correctly may be difficult, therefore care
    /// needs to be taken. One method known to work is encoding the data into an atomic variable.
    /// Other, less limiting approaches, will be eventually explored.
    pub unsafe trait Exfiltrator: Debug + Send + Sync + 'static {
        /// One slot for storing the data.
        ///
        /// Each signal will get its one slot of this type, independent of other signals. It can
        /// store the information in there inside the signal handler and will be loaded from it in
        /// load.
        ///
        /// Each slot is initialized to the [`Default`] value. It is expected this value represents
        /// „no signal delivered“ state.
        type Storage: Debug + Default + Send + Sync + 'static;

        /// The type returned to the user.
        type Output;

        /// If the given signal is supported by this specific exfiltrator.
        ///
        /// Not all information is available to all signals, therefore not all exfiltrators must
        /// support all signals. If `false` is returned, the user is prevented for registering such
        /// signal number with the given exfiltrator.
        fn supports_signal(&self, sig: c_int) -> bool;

        /// Puts the signal information inside the slot.
        ///
        /// It needs to somehow store the relevant information and the fact that a signal happened.
        ///
        /// # Warning
        ///
        /// This will be called inside the signal handler. It needs to be async-signal-safe. In
        /// particular, very small amount of operations are allowed in there. This namely does
        /// *not* include any locking nor allocation.
        ///
        /// It is also possible that multiple store methods are called concurrently; it is up to
        /// the implementor to deal with that.
        fn store(&self, slot: &Self::Storage, signal: c_int, info: &siginfo_t);

        /// Loads the signal information from the given slot.
        ///
        /// The method shall check if the signal happened (it may be possible to be called without
        /// the signal previously being delivered; it is up to the implementer to recognize it). It
        /// is assumed the [`Default`] value is recognized as no signal delivered.
        ///
        /// If it was delivered, the method shall extract the relevant information *and reset the
        /// slot* to the no signal delivered state.
        ///
        /// It shall return `Some(value)` if the signal was successfully received and `None` in
        /// case no signal was delivered.
        ///
        /// No blocking shall happen inside this method. It may be called concurrently with
        /// [`store`][Exfiltrator::store] (due to how signals work, concurrently even inside the
        /// same thread ‒ a `store` may „interrupt“ a call to `load`). It is up to the implementer
        /// to deal with that.
        fn load(&self, slot: &Self::Storage, signal: c_int) -> Option<Self::Output>;

        /// Initialize the given slot for the given signal before the first use.
        ///
        /// This is called before the first use of the given slot (and it is annotated with the
        /// corresponding signal). The default does nothing, this is just an opportunity to
        /// allocate data lazily (this is called outside of the signal handler, so it doesn't have
        /// to be async-signal-safe). It will be called at most once for each slot.
        ///
        /// Note that you can rely on this being called for correctness, but not for safety (this
        /// crate calls it before the first use, but a user abusing the trait might not and in such
        /// case it is OK to eg. lose signals, but not segfault).
        fn init(&self, slot: &Self::Storage, signal: c_int) {
            // Suppress unused variable warning without putting the underscores into public
            // signature.
            let _ = slot;
            let _ = signal;
        }
    }
}

/// A trait describing what and how is extracted from signal handlers.
///
/// By choosing a specific implementor as the type parameter for
/// [`SignalsInfo`][crate::iterator::SignalsInfo], one can pick how much and what information is
/// returned from the iterator.
pub trait Exfiltrator: sealed::Exfiltrator {}

impl<E: sealed::Exfiltrator> Exfiltrator for E {}

/// An [`Exfiltrator`] providing just the signal numbers.
///
/// This is the basic exfiltrator for most needs. For that reason, there's the
/// [`crate::iterator::Signals`] type alias, to simplify the type names for usual needs.
#[derive(Clone, Copy, Debug, Default)]
pub struct SignalOnly;

unsafe impl sealed::Exfiltrator for SignalOnly {
    type Storage = AtomicBool;
    fn supports_signal(&self, _: c_int) -> bool {
        true
    }
    type Output = c_int;

    fn store(&self, slot: &Self::Storage, _: c_int, _: &siginfo_t) {
        slot.store(true, Ordering::SeqCst);
    }

    fn load(&self, slot: &Self::Storage, signal: c_int) -> Option<Self::Output> {
        if slot
            .compare_exchange(true, false, Ordering::SeqCst, Ordering::Relaxed)
            .is_ok()
        {
            Some(signal)
        } else {
            None
        }
    }
}
<|endoftext|>