<commit_before>//! Tables making up a font file.

#![allow(non_camel_case_types, non_snake_case)]

macro_rules! table(
    ($structure:ident { $($field:ident ($($kind:tt)+) $(|$this:ident| $body:block)*,)+ }) => (
        declare!($structure { $($field ($($kind)+),)+ });
        implement!($structure { $($field ($($kind)+) $(|$this| $body)*,)+ });
    );
);

macro_rules! declare(
    ($structure:ident { $($field:ident ($kind:ty),)+ }) => (
        itemize! {
            #[derive(Clone, Debug, Default, Eq, PartialEq)]
            pub struct $structure { $(pub $field: $kind,)+ }
        }
    );
);

macro_rules! implement(
    ($structure:ident { $($field:ident ($($kind:tt)+) $(|$this:ident| $body:block)*,)+ }) => (
        impl ::band::Value for $structure {
            fn read<T: ::band::Band>(band: &mut T) -> ::Result<Self> {
                let mut value = $structure::default();
                $(value.$field = read!($structure, value, band, [$($kind)+] $(|$this| $body)*);)+
                Ok(value)
            }
        }
    );
);

macro_rules! itemize(
    ($code:item) => ($code);
);

macro_rules! read(
    ($structure:ident, $this:ident, $band:ident, [$kind:ty] |$that:ident| $body:block) => ({
        #[inline(always)]
        #[allow(unused_variables)]
        fn count($that: &$structure) -> ::Result<usize> $body
        let count = try!(count(&$this));
        let mut values = Vec::with_capacity(count);
        for _ in 0..count {
            values.push(try!(::band::Value::read($band)));
        }
        values
    });
    ($structure:ident, $this:ident, $band:ident, [$kind:ty]) => ({
        try!(::band::Value::read($band))
    });
);

mod char_mapping;
mod font_header;
mod horizontal_header;
mod horizontal_metrics;
mod maximum_profile;
mod offset_table;
mod windows_metrics;

pub use self::char_mapping::{CharMapping, CharMappingHeader, CharMappingRecord};
pub use self::char_mapping::{CharMappingEncoding, CharMappingEncoding4, CharMappingEncoding6};
pub use self::font_header::FontHeader;
pub use self::horizontal_header::HorizontalHeader;
pub use self::horizontal_metrics::HorizontalMetrics;
pub use self::maximum_profile::{MaximumProfile, MaximumProfile05, MaximumProfile10};
pub use self::offset_table::{OffsetTable, OffsetTableHeader, OffsetTableRecord};
pub use self::windows_metrics::{WindowsMetrics, WindowsMetrics5};
<commit_msg>Export WindowsMetrics3<commit_after>//! Tables making up a font file.

#![allow(non_camel_case_types, non_snake_case)]

macro_rules! table(
    ($structure:ident { $($field:ident ($($kind:tt)+) $(|$this:ident| $body:block)*,)+ }) => (
        declare!($structure { $($field ($($kind)+),)+ });
        implement!($structure { $($field ($($kind)+) $(|$this| $body)*,)+ });
    );
);

macro_rules! declare(
    ($structure:ident { $($field:ident ($kind:ty),)+ }) => (
        itemize! {
            #[derive(Clone, Debug, Default, Eq, PartialEq)]
            pub struct $structure { $(pub $field: $kind,)+ }
        }
    );
);

macro_rules! implement(
    ($structure:ident { $($field:ident ($($kind:tt)+) $(|$this:ident| $body:block)*,)+ }) => (
        impl ::band::Value for $structure {
            fn read<T: ::band::Band>(band: &mut T) -> ::Result<Self> {
                let mut value = $structure::default();
                $(value.$field = read!($structure, value, band, [$($kind)+] $(|$this| $body)*);)+
                Ok(value)
            }
        }
    );
);

macro_rules! itemize(
    ($code:item) => ($code);
);

macro_rules! read(
    ($structure:ident, $this:ident, $band:ident, [$kind:ty] |$that:ident| $body:block) => ({
        #[inline(always)]
        #[allow(unused_variables)]
        fn count($that: &$structure) -> ::Result<usize> $body
        let count = try!(count(&$this));
        let mut values = Vec::with_capacity(count);
        for _ in 0..count {
            values.push(try!(::band::Value::read($band)));
        }
        values
    });
    ($structure:ident, $this:ident, $band:ident, [$kind:ty]) => ({
        try!(::band::Value::read($band))
    });
);

mod char_mapping;
mod font_header;
mod horizontal_header;
mod horizontal_metrics;
mod maximum_profile;
mod offset_table;
mod windows_metrics;

pub use self::char_mapping::{CharMapping, CharMappingHeader, CharMappingRecord};
pub use self::char_mapping::{CharMappingEncoding, CharMappingEncoding4, CharMappingEncoding6};
pub use self::font_header::FontHeader;
pub use self::horizontal_header::HorizontalHeader;
pub use self::horizontal_metrics::HorizontalMetrics;
pub use self::maximum_profile::{MaximumProfile, MaximumProfile05, MaximumProfile10};
pub use self::offset_table::{OffsetTable, OffsetTableHeader, OffsetTableRecord};
pub use self::windows_metrics::{WindowsMetrics, WindowsMetrics3, WindowsMetrics5};
<|endoftext|>


<commit_before>use super::ssz::SszStream;
use super::utils::hash::canonical_hash;
use super::utils::types::Hash256;

/// Generates the message used to validate the signature provided with an AttestationRecord.
///
/// Ensures that the signer of the message has a view of the chain that is compatible with ours.
pub fn generate_signed_message(slot: u64,
                           parent_hashes: &[Hash256],
                           shard_id: u16,
                           shard_block_hash: &Hash256,
                           justified_slot: u64)
    -> Vec<u8>
{
    /*
     * Note: it's a little risky here to use SSZ, because the encoding is not necessarily SSZ
     * (for example, SSZ might change whilst this doesn't).
     *
     * I have suggested switching this to ssz here:
     * https://github.com/ethereum/eth2.0-specs/issues/5
     *
     * If this doesn't happen, it would be safer to not use SSZ at all.
     */
    let mut ssz_stream = SszStream::new();
    ssz_stream.append(&slot);
    ssz_stream.append_vec(&parent_hashes.to_vec());
    ssz_stream.append(&shard_id);
    ssz_stream.append(shard_block_hash);
    ssz_stream.append(&justified_slot);
    let bytes = ssz_stream.drain();
    canonical_hash(&bytes)
}
<commit_msg>Add test for attestation msg generation<commit_after>use super::ssz::SszStream;
use super::utils::hash::canonical_hash;
use super::utils::types::Hash256;

/// Generates the message used to validate the signature provided with an AttestationRecord.
///
/// Ensures that the signer of the message has a view of the chain that is compatible with ours.
pub fn generate_signed_message(
    slot: u64,
    parent_hashes: &[Hash256],
    shard_id: u16,
    shard_block_hash: &Hash256,
    justified_slot: u64)
    -> Vec<u8>
{
    /*
     * Note: it's a little risky here to use SSZ, because the encoding is not necessarily SSZ
     * (for example, SSZ might change whilst this doesn't).
     *
     * I have suggested switching this to ssz here:
     * https://github.com/ethereum/eth2.0-specs/issues/5
     *
     * If this doesn't happen, it would be safer to not use SSZ at all.
     */
    let mut ssz_stream = SszStream::new();
    ssz_stream.append(&slot);
    ssz_stream.append_vec(&parent_hashes.to_vec());
    ssz_stream.append(&shard_id);
    ssz_stream.append(shard_block_hash);
    ssz_stream.append(&justified_slot);
    let bytes = ssz_stream.drain();
    canonical_hash(&bytes)
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_generate_signed_message() {
        let slot = 93;
        let parent_hashes: Vec<Hash256> = (0..12)
            .map(|i| Hash256::from(i as u64))
            .collect();
        let shard_id = 15;
        let shard_block_hash = Hash256::from("shard_block_hash".as_bytes());
        let justified_slot = 18;

        let output = generate_signed_message(
            slot,
            &parent_hashes,
            shard_id,
            &shard_block_hash,
            justified_slot);

        /*
         * Note: this is not some well-known test vector, it's simply the result of running
         * this and printing the output.
         *
         * Once well-known test vectors are established, they should be placed here.
         */
        let expected = vec![
            149, 99, 94, 229, 72, 144, 233, 14, 164, 16, 143, 53, 94, 48,
            118, 179, 33, 181, 172, 215, 2, 191, 176, 18, 188, 172, 137,
            178, 236, 66, 74, 120
        ];

        assert_eq!(output, expected);
    }
}
<|endoftext|>


<commit_before>use proc_macro::TokenStream;
use proc_macro_hack::proc_macro_hack;
use quote::quote;
use syn::{parse_macro_input, Expr};

#[proc_macro_hack]
pub fn add_one(input: TokenStream) -> TokenStream {
    let expr = parse_macro_input!(input as Expr);
    TokenStream::from(quote! {
        1 + (#expr)
    })
}
<commit_msg>Ignore buggy nonstandard_macro_braces clippy lint<commit_after>#![allow(
    // Clippy bug: https://github.com/rust-lang/rust-clippy/issues/7422
    clippy::nonstandard_macro_braces,
)]

use proc_macro::TokenStream;
use proc_macro_hack::proc_macro_hack;
use quote::quote;
use syn::{parse_macro_input, Expr};

#[proc_macro_hack]
pub fn add_one(input: TokenStream) -> TokenStream {
    let expr = parse_macro_input!(input as Expr);
    TokenStream::from(quote! {
        1 + (#expr)
    })
}
<|endoftext|>


<commit_before>
extern crate rand;

extern crate fastmap;

use fastmap::FastMap;

#[cfg(test)]
mod tests {
    use super::*;

    fn get_random_range(count: usize) -> Vec<u64> {
        use rand::{Rng, SeedableRng, StdRng};

        let mut vec = Vec::new();

        let seed: &[_] = &[4, 2, 4, 2];
        let mut rng: StdRng = SeedableRng::from_seed(seed);

        for _ in 0..count {
            vec.push(rng.gen::<u64>());
        }

        vec.sort();
        vec.dedup();

        vec
    }

    #[test]
    fn fastmap_get_insert_impl() {
        let count = 20_000;
        let data = get_random_range(count as usize);
        let mut map: FastMap<u64, u64> = FastMap::new();

        println!("");
        println!("Starting test");

        for s in data.iter() {
            assert!(map.insert(*s, *s), "fastmap insert failed! ix: {:?}", s);
        }

        assert_eq!(map.len(), count);
        assert!(map.assert_count());

        for s in data.iter() {
            assert_eq!(*map.get(*s).unwrap(), *s, "fastmap get failed! key: {:?}", s);
        }

        assert_eq!(map.len(), count);

        for s in data.iter() {
            assert!(map.contains_key(*s), "fastmap contains_key failed! key: {:?}", s);
        }

        assert_eq!(map.len(), count);

        for s in data.iter() {
            let val = map.remove(*s).unwrap();
            assert_eq!(val, *s, "fastmap remove failed! key: {:?}", s);
        }

        assert_eq!(map.len(), 0);
        assert!(map.assert_count());
    }

    #[test]
    fn add_string() {
        let mut map = FastMap::new();

        for i in 0..20_000 {
            map.insert(i, format!("item: {:?}", i));
        }
    }

    #[test]
    fn single_add_get() {
        let mut map: FastMap<u64, u64> = FastMap::new();
        map.insert(21, 42);
        let val = map.get(21);
        assert!(val.is_some());
        assert_eq!(*val.unwrap(), 42);
    }

    #[test]
    fn map_iter() {
        let count = 20_000;
        let mut map: FastMap<u64, u64> = FastMap::new();

        for i in 0..count {
            map.insert(i, i);
        }

        for (k, v) in map.iter() {
            assert_eq!(*k, *v);
        }
    }

    #[test]
    fn map_iter_keys() {
        let count = 20_000;
        let data: Vec<_> = (0..count).collect();
        let mut map: FastMap<u64, u64> = FastMap::new();

        for i in 0..count {
            map.insert(i, i);
        }

        for k in map.keys() {
            assert_eq!(*k, data[*k as usize]);
        }
    }

    #[test]
    fn map_iter_values() {
        let count = 20_000;
        let data: Vec<_> = (0..count).collect();
        let mut map: FastMap<u64, u64> = FastMap::new();

        for i in 0..count {
            map.insert(i, i);
        }

        for v in map.values() {
            assert_eq!(*v, data[*v as usize]);
        }
    }

    #[test]
    fn map_mut_iter() {
        let count = 20_000;
        let mut map: FastMap<u64, u64> = FastMap::new();

        for i in 0..count {
            map.insert(i, i);
        }

        for kv in map.iter_mut() {
            *kv.1 += 1;
        }

        for n in 0..count {
            assert_eq!(n+1, *map.get(n).expect("Failed to get number!"));
        }

    }

    #[test]
    fn map_iter_empty() {
        let mut map: FastMap<u64, u64> = FastMap::new();
        map.clear();

        for kv in map.iter() {
            println!("Not printing: {:?}", kv);
        }
    }

    #[test]
    fn map_mut_iter_empty() {
        let mut map: FastMap<u64, u64> = FastMap::new();
        map.clear();

        for kv in map.iter_mut() {
            *kv.1 += 1;
        }
    }
}
<commit_msg>updated some test for better error reporting<commit_after>
extern crate rand;

extern crate fastmap;

use fastmap::FastMap;

#[cfg(test)]
mod tests {
    use super::*;

    fn get_random_range(count: usize) -> Vec<u64> {
        use rand::{Rng, SeedableRng, StdRng};

        let mut vec = Vec::new();

        let seed: &[_] = &[4, 2, 4, 2];
        let mut rng: StdRng = SeedableRng::from_seed(seed);

        for _ in 0..count {
            vec.push(rng.gen::<u64>());
        }

        vec.sort();
        vec.dedup();

        vec
    }

    #[test]
    fn fastmap_get_insert_impl() {
        let count = 20_000;
        let data = get_random_range(count as usize);
        let mut map: FastMap<u64, u64> = FastMap::new();

        println!("");
        println!("Starting test");

        for s in data.iter() {
            assert!(map.insert(*s, *s), "fastmap insert failed! ix: {:?}", s);
        }

        assert_eq!(map.len(), count);
        assert!(map.assert_count());

        for s in data.iter() {
            assert_eq!(*map.get(*s).unwrap(), *s, "fastmap get failed! key: {:?}", s);
        }

        assert_eq!(map.len(), count);

        for s in data.iter() {
            assert!(map.contains_key(*s), "fastmap contains_key failed! key: {:?}", s);
        }

        assert_eq!(map.len(), count);

        for s in data.iter() {
            if let Some(val) = map.remove(*s) {
                assert_eq!(val, *s, "fastmap remove failed! key: {:?}", s);
            } else {
                assert!(false, "Failed to remove value: {:?}", *s);
            }
        }

        assert_eq!(map.len(), 0);
        assert!(map.assert_count());
    }

    #[test]
    fn add_string() {
        let mut map = FastMap::new();

        for i in 0..20_000 {
            assert!(map.insert(i, format!("item: {:?}", i)), format!("Failed to insert key in map: {}", i));
        }

        for i in 0..20_000 {
            if let Some(s) = map.get(i) {
                assert_eq!(*s, format!("item: {:?}", i));
            } else {
                assert!(false, format!("Failed to retrive key in map: {}", i));
            }
        }
    }

    #[test]
    fn single_add_get() {
        let mut map: FastMap<u64, u64> = FastMap::new();
        map.insert(21, 42);
        let val = map.get(21);
        assert!(val.is_some());
        assert_eq!(*val.unwrap(), 42);
    }

    #[test]
    fn map_iter() {
        let count = 20_000;
        let mut map: FastMap<u64, u64> = FastMap::new();

        for i in 0..count {
            map.insert(i, i);
        }

        for (k, v) in map.iter() {
            assert_eq!(*k, *v);
        }
    }

    #[test]
    fn map_iter_keys() {
        let count = 20_000;
        let data: Vec<_> = (0..count).collect();
        let mut map: FastMap<u64, u64> = FastMap::new();

        for i in 0..count {
            map.insert(i, i);
        }

        for k in map.keys() {
            assert_eq!(*k, data[*k as usize]);
        }
    }

    #[test]
    fn map_iter_values() {
        let count = 20_000;
        let data: Vec<_> = (0..count).collect();
        let mut map: FastMap<u64, u64> = FastMap::new();

        for i in 0..count {
            map.insert(i, i);
        }

        for v in map.values() {
            assert_eq!(*v, data[*v as usize]);
        }
    }

    #[test]
    fn map_mut_iter() {
        let count = 20_000;
        let mut map: FastMap<u64, u64> = FastMap::new();

        for i in 0..count {
            map.insert(i, i);
        }

        for kv in map.iter_mut() {
            *kv.1 += 1;
        }

        for n in 0..count {
            assert_eq!(n+1, *map.get(n).expect("Failed to get number!"));
        }

    }

    #[test]
    fn map_iter_empty() {
        let mut map: FastMap<u64, u64> = FastMap::new();
        map.clear();

        for kv in map.iter() {
            println!("Not printing: {:?}", kv);
        }
    }

    #[test]
    fn map_mut_iter_empty() {
        let mut map: FastMap<u64, u64> = FastMap::new();
        map.clear();

        for kv in map.iter_mut() {
            *kv.1 += 1;
        }
    }
}
<|endoftext|>


<commit_before>use super::nodes_types::{Entry, Field, Storage, TypeName};

use std::collections::BTreeMap as Map;
use std::collections::BTreeSet as Set;
use std::fmt;
use std::path::Path;
use tree_sitter::{Language, Node, Parser, Tree};

pub struct Extractor {
    pub parser: Parser,
    pub schema: Vec<Entry>,
}

pub fn create(language: Language, schema: Vec<Entry>) -> Extractor {
    let mut parser = Parser::new();
    parser.set_language(language).unwrap();

    Extractor { parser, schema }
}
impl Extractor {
    pub fn extract<'a>(&'a mut self, path: &Path) -> std::io::Result<Program> {
        let source = std::fs::read(&path)?;
        let tree = &self
            .parser
            .parse(&source, None)
            .expect("Failed to parse file");
        let mut visitor = Visitor {
            source: &source,
            program: vec![Fact::Comment(format!(
                "Auto-generated FACT file for {}, generated by the cool kids",
                path.display()
            ))],
            counter: -1,
            // TODO: should we handle path strings that are not valid UTF8 better?
            path: format!("{}", path.display()),
            stack: Vec::new(),
            tables: build_schema_lookup(&self.schema),
            union_types: build_union_type_lookup(&self.schema),
        };
        traverse(&tree, &mut visitor);

        &self.parser.reset();
        Ok(Program(visitor.program))
    }
}

fn build_schema_lookup<'a>(schema: &'a Vec<Entry>) -> Map<&'a TypeName, &'a Entry> {
    let mut map = std::collections::BTreeMap::new();
    for entry in schema {
        if let Entry::Table { type_name, .. } = entry {
            map.insert(type_name, entry);
        }
    }
    map
}

fn build_union_type_lookup<'a>(schema: &'a Vec<Entry>) -> Map<&'a TypeName, &'a Set<TypeName>> {
    let mut union_types = std::collections::BTreeMap::new();
    for entry in schema {
        if let Entry::Union { type_name, members } = entry {
            union_types.insert(type_name, members);
        }
    }
    union_types
}

struct Visitor<'a> {
    source: &'a Vec<u8>,
    program: Vec<Fact>,
    counter: i32,
    path: String,
    stack: Vec<Vec<(Option<&'static str>, Id, TypeName)>>,
    tables: Map<&'a TypeName, &'a Entry>,
    union_types: Map<&'a TypeName, &'a Set<TypeName>>,
}

impl Visitor<'_> {
    fn enter_node(&mut self, node: Node) {
        if node.is_extra() {
            return;
        }
        self.stack.push(Vec::new());
    }

    fn leave_node(&mut self, field_name: Option<&'static str>, node: Node) {
        if node.is_extra() {
            return;
        }
        let child_nodes = self.stack.pop().expect("Vistor: empty stack");
        let table = self.tables.get(&TypeName {
            kind: node.kind().to_owned(),
            named: node.is_named(),
        });
        if let Some(Entry::Table { fields, .. }) = table {
            self.counter += 1;
            let id = Id(self.counter);
            let loc = Loc(self.counter);
            self.program.push(Fact::New(Arg::IdArg(id)));
            self.program.push(Fact::New(Arg::LocArg(loc)));
            self.program.push(location_for(&self.path, loc, node));
            let table_name = node_type_name(node.kind(), node.is_named());
            let args: Option<Vec<Arg>>;
            if fields.is_empty() {
                args = Some(vec![sliced_source_arg(self.source, node)]);
            } else {
                args = self.complex_node(fields, child_nodes, id);
            }
            if let Some(args) = args {
                self.program
                    .push(Fact::Definition(table_name, id, args, loc));
            }
            if let Some(parent) = self.stack.last_mut() {
                parent.push((
                    field_name,
                    id,
                    TypeName {
                        kind: node.kind().to_owned(),
                        named: node.is_named(),
                    },
                ))
            };
        } else {
            panic!(format!("Unknown table type: '{}'", node.kind()))
        }
    }

    fn complex_node(
        &mut self,
        fields: &Vec<Field>,
        child_nodes: Vec<(Option<&str>, Id, TypeName)>,
        parent_id: Id,
    ) -> Option<Vec<Arg>> {
        let mut map: Map<&Option<String>, (&Field, Vec<Id>)> = std::collections::BTreeMap::new();
        for field in fields {
            map.insert(&field.name, (field, Vec::new()));
        }
        for (child_field, child_id, child_type) in child_nodes {
            if let Some((field, values)) = map.get_mut(&child_field.map(|x| x.to_owned())) {
                //TODO: handle error and missing nodes
                if self.type_matches(&child_type, &field.types) {
                    values.push(child_id);
                } else if field.name.is_some() {
                    println!(
                        "Type mismatch for field {:?} with type {:?} != {:?}",
                        child_field, child_type, field.types
                    )
                }
            } else {
                println!(
                    "Value for unknown field: {:?} and type {:?}",
                    &child_field, &child_type
                );
            }
        }
        let mut args = Vec::new();
        let mut is_valid = true;
        for field in fields {
            let child_ids = &map.get(&field.name).unwrap().1;
            match &field.storage {
                Storage::Column => {
                    if child_ids.len() == 1 {
                        args.push(Arg::IdArg(*child_ids.first().unwrap()));
                    } else {
                        is_valid = false;
                        println!("Argument count mismatch for field {:?}", field.name);
                    }
                }
                Storage::Table { parent, index } => {
                    for child_id in child_ids {
                        self.program.push(Fact::ChildOf(
                            node_type_name(&parent.kind, parent.named),
                            parent_id,
                            match &field.name {
                                Some(name) => name.to_owned(),
                                None => "child".to_owned(),
                            },
                            Index(*index),
                            *child_id,
                        ));
                    }
                }
            }
        }
        if is_valid {
            Some(args)
        } else {
            None
        }
    }
    fn type_matches(&self, tp: &TypeName, types: &Set<TypeName>) -> bool {
        if types.contains(tp) {
            return true;
        }
        for other in types.iter() {
            if let Some(x) = self.union_types.get(other) {
                if self.type_matches(tp, x) {
                    return true;
                }
            }
        }
        return false;
    }
}

// Emit a slice of a source file as an Arg.
fn sliced_source_arg(source: &Vec<u8>, n: Node) -> Arg {
    let range = n.byte_range();
    Arg::StringArg(String::from(
        std::str::from_utf8(&source[range.start..range.end]).expect("Failed to decode string"),
    ))
}

// Emit a 'Located' fact for the provided node, appropriately calibrated.
fn location_for<'a>(fp: &String, ident: Loc, n: Node) -> Fact {
    let start_line = n.start_position().row;
    let start_col = n.start_position().column;
    let end_line = n.end_position().row;
    let end_col = n.end_position().column;
    Fact::Located(vec![
        Arg::LocArg(ident),
        Arg::StringArg(fp.to_owned()),
        Arg::IntArg(start_line),
        Arg::IntArg(start_col),
        Arg::IntArg(end_line),
        Arg::IntArg(end_col),
    ])
}

fn traverse(tree: &Tree, visitor: &mut Visitor) {
    let cursor = &mut tree.walk();
    visitor.enter_node(cursor.node());
    let mut recurse = true;
    loop {
        if recurse && cursor.goto_first_child() {
            visitor.enter_node(cursor.node());
        } else {
            visitor.leave_node(cursor.field_name(), cursor.node());

            if cursor.goto_next_sibling() {
                recurse = true;
                visitor.enter_node(cursor.node());
            } else if cursor.goto_parent() {
                recurse = false;
            } else {
                break;
            }
        }
    }
}
pub struct Program(Vec<Fact>);

impl fmt::Display for Program {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let mut text = String::new();
        for fact in &self.0 {
            text.push_str(&format!("{}\n", fact));
        }
        write!(f, "{}", text)
    }
}
#[derive(Debug)]
enum Fact {
    // @id = *@
    New(Arg),
    // @node_def(self, arg?, location)@
    Definition(String, Id, Vec<Arg>, Loc),
    // @node_child(self, index, parent)@
    ChildOf(String, Id, String, Index, Id),
    // @location(loc, path, r1, c1, r2, c2)
    Located(Vec<Arg>),
    Comment(String),
}
impl fmt::Display for Fact {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            Fact::New(id) => write!(f, "{} = *", id),
            Fact::Definition(n, id, args, loc) => {
                let mut args_str = String::new();
                for arg in args {
                    args_str.push_str(&format!("{}, ", arg));
                }
                write!(
                    f,
                    "{}({}, {}{})",
                    escape_name(&format!("{}_def", &n)),
                    id,
                    args_str,
                    loc
                )
            }
            Fact::ChildOf(pname, id, fname, idx, p) => write!(
                f,
                "{}({}, {}, {})",
                escape_name(&format!("{}_{}", &pname, &fname)),
                id,
                idx,
                p
            ),
            Fact::Located(args) => write!(
                f,
                "location({}, {}, {}, {}, {}, {})",
                args.get(0).unwrap(),
                args.get(1).unwrap(),
                args.get(2).unwrap(),
                args.get(3).unwrap(),
                args.get(4).unwrap(),
                args.get(5).unwrap(),
            ),
            Fact::Comment(line) => write!(f, "// {}", line),
        }
    }
}
// Identifiers of the form #0, #1...
#[derive(Debug, Copy, Clone)]
struct Id(i32);

impl fmt::Display for Id {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "#{}", self.0)
    }
}
// Locative identifiers of the form #0_loc, #1_loc...
#[derive(Debug, Copy, Clone)]
struct Loc(i32);

impl fmt::Display for Loc {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "#{}_loc", self.0)
    }
}
// Numeric indices.
#[derive(Debug, Copy, Clone)]
struct Index(usize);

impl fmt::Display for Index {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.0)
    }
}

// Some untyped argument to a fact.
#[derive(Debug)]
enum Arg {
    IntArg(usize),
    StringArg(String),
    IdArg(Id),
    LocArg(Loc),
}

impl fmt::Display for Arg {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            Arg::IntArg(x) => write!(f, "{}", x),
            Arg::StringArg(x) => write!(f, "\"{}\"", x.replace("\"", "\"\"")),
            Arg::IdArg(x) => write!(f, "{}", x),
            Arg::LocArg(x) => write!(f, "{}", x),
        }
    }
}

const RESERVED_KEYWORDS: [&'static str; 14] = [
    "boolean", "case", "date", "float", "int", "key", "of", "order", "ref", "string", "subtype",
    "type", "unique", "varchar",
];

/// Returns a string that's a copy of `name` but suitably escaped to be a valid
/// QL identifier.
pub fn escape_name(name: &str) -> String {
    let mut result = String::new();

    // If there's a leading underscore, replace it with 'underscore_'.
    if let Some(c) = name.chars().next() {
        if c == '_' {
            result.push_str("underscore");
        }
    }
    for c in name.chars() {
        match c {
            '{' => result.push_str("lbrace"),
            '}' => result.push_str("rbrace"),
            '<' => result.push_str("langle"),
            '>' => result.push_str("rangle"),
            '[' => result.push_str("lbracket"),
            ']' => result.push_str("rbracket"),
            '(' => result.push_str("lparen"),
            ')' => result.push_str("rparen"),
            '|' => result.push_str("pipe"),
            '=' => result.push_str("equal"),
            '~' => result.push_str("tilde"),
            '?' => result.push_str("question"),
            '`' => result.push_str("backtick"),
            '^' => result.push_str("caret"),
            '!' => result.push_str("bang"),
            '#' => result.push_str("hash"),
            '%' => result.push_str("percent"),
            '&' => result.push_str("ampersand"),
            '.' => result.push_str("dot"),
            ',' => result.push_str("comma"),
            '/' => result.push_str("slash"),
            ':' => result.push_str("colon"),
            ';' => result.push_str("semicolon"),
            '"' => result.push_str("dquote"),
            '*' => result.push_str("star"),
            '+' => result.push_str("plus"),
            '-' => result.push_str("minus"),
            '@' => result.push_str("at"),
            _ => result.push_str(&c.to_lowercase().to_string()),
        }
    }

    for &keyword in &RESERVED_KEYWORDS {
        if result == keyword {
            result.push_str("__");
            break;
        }
    }

    result
}

/// Given a tree-sitter node type's (kind, named) pair, returns a single string
/// representing the (unescaped) name we'll use to refer to corresponding QL
/// type.
fn node_type_name(kind: &str, named: bool) -> String {
    if named {
        kind.to_string()
    } else {
        format!("{}_unnamed", kind)
    }
}
<commit_msg>Improve error messages<commit_after>use super::nodes_types::{Entry, Field, Storage, TypeName};

use std::collections::BTreeMap as Map;
use std::collections::BTreeSet as Set;
use std::fmt;
use std::path::Path;
use tree_sitter::{Language, Node, Parser, Tree};

pub struct Extractor {
    pub parser: Parser,
    pub schema: Vec<Entry>,
}

pub fn create(language: Language, schema: Vec<Entry>) -> Extractor {
    let mut parser = Parser::new();
    parser.set_language(language).unwrap();

    Extractor { parser, schema }
}
impl Extractor {
    pub fn extract<'a>(&'a mut self, path: &Path) -> std::io::Result<Program> {
        let source = std::fs::read(&path)?;
        let tree = &self
            .parser
            .parse(&source, None)
            .expect("Failed to parse file");
        let mut visitor = Visitor {
            source: &source,
            program: vec![Fact::Comment(format!(
                "Auto-generated FACT file for {}, generated by the cool kids",
                path.display()
            ))],
            counter: -1,
            // TODO: should we handle path strings that are not valid UTF8 better?
            path: format!("{}", path.display()),
            stack: Vec::new(),
            tables: build_schema_lookup(&self.schema),
            union_types: build_union_type_lookup(&self.schema),
        };
        traverse(&tree, &mut visitor);

        &self.parser.reset();
        Ok(Program(visitor.program))
    }
}

fn build_schema_lookup<'a>(schema: &'a Vec<Entry>) -> Map<&'a TypeName, &'a Entry> {
    let mut map = std::collections::BTreeMap::new();
    for entry in schema {
        if let Entry::Table { type_name, .. } = entry {
            map.insert(type_name, entry);
        }
    }
    map
}

fn build_union_type_lookup<'a>(schema: &'a Vec<Entry>) -> Map<&'a TypeName, &'a Set<TypeName>> {
    let mut union_types = std::collections::BTreeMap::new();
    for entry in schema {
        if let Entry::Union { type_name, members } = entry {
            union_types.insert(type_name, members);
        }
    }
    union_types
}

struct Visitor<'a> {
    source: &'a Vec<u8>,
    program: Vec<Fact>,
    counter: i32,
    path: String,
    stack: Vec<Vec<(Option<&'static str>, Id, TypeName)>>,
    tables: Map<&'a TypeName, &'a Entry>,
    union_types: Map<&'a TypeName, &'a Set<TypeName>>,
}

impl Visitor<'_> {
    fn enter_node(&mut self, node: Node) {
        if node.is_error() {
            println!(
                "error: {}:{}: parse error",
                &self.path,
                node.start_position().row,
            );
            return;
        }
        if node.is_missing() {
            println!(
                "error: {}:{}: parse error: expecting '{}'",
                &self.path,
                node.start_position().row,
                node.kind()
            );
            return;
        }

        if node.is_extra() {
            return;
        }

        self.stack.push(Vec::new());
    }

    fn leave_node(&mut self, field_name: Option<&'static str>, node: Node) {
        if node.is_extra() || node.is_error() || node.is_missing() {
            return;
        }
        let child_nodes = self.stack.pop().expect("Vistor: empty stack");
        let table = self.tables.get(&TypeName {
            kind: node.kind().to_owned(),
            named: node.is_named(),
        });
        if let Some(Entry::Table { fields, .. }) = table {
            self.counter += 1;
            let id = Id(self.counter);
            let loc = Loc(self.counter);
            self.program.push(Fact::New(Arg::IdArg(id)));
            self.program.push(Fact::New(Arg::LocArg(loc)));
            self.program.push(location_for(&self.path, loc, node));
            let table_name = node_type_name(node.kind(), node.is_named());
            let args: Option<Vec<Arg>>;
            if fields.is_empty() {
                args = Some(vec![sliced_source_arg(self.source, node)]);
            } else {
                args = self.complex_node(&node, fields, child_nodes, id);
            }
            if let Some(args) = args {
                self.program
                    .push(Fact::Definition(table_name, id, args, loc));
            }
            if let Some(parent) = self.stack.last_mut() {
                parent.push((
                    field_name,
                    id,
                    TypeName {
                        kind: node.kind().to_owned(),
                        named: node.is_named(),
                    },
                ))
            };
        } else {
            println!(
                "error: {}:{}: unknown table type: '{}'",
                &self.path,
                node.start_position().row,
                node.kind()
            );
        }
    }
    fn complex_node(
        &mut self,
        node: &Node,
        fields: &Vec<Field>,
        child_nodes: Vec<(Option<&str>, Id, TypeName)>,
        parent_id: Id,
    ) -> Option<Vec<Arg>> {
        let mut map: Map<&Option<String>, (&Field, Vec<Id>)> = std::collections::BTreeMap::new();
        for field in fields {
            map.insert(&field.name, (field, Vec::new()));
        }
        for (child_field, child_id, child_type) in child_nodes {
            if let Some((field, values)) = map.get_mut(&child_field.map(|x| x.to_owned())) {
                //TODO: handle error and missing nodes
                if self.type_matches(&child_type, &field.types) {
                    values.push(child_id);
                } else if field.name.is_some() {
                    println!(
                        "error: {}:{}: type mismatch for field {}::{} with type {:?} != {:?}",
                        &self.path,
                        node.start_position().row,
                        node.kind(),
                        child_field.unwrap_or("child"),
                        child_type,
                        field.types
                    )
                }
            } else {
                if child_field.is_some() || child_type.named {
                    println!(
                        "error: {}:{}: value for unknown field: {}::{} and type {:?}",
                        &self.path,
                        node.start_position().row,
                        node.kind(),
                        &child_field.unwrap_or("child"),
                        &child_type
                    );
                }
            }
        }
        let mut args = Vec::new();
        let mut is_valid = true;
        for field in fields {
            let child_ids = &map.get(&field.name).unwrap().1;
            match &field.storage {
                Storage::Column => {
                    if child_ids.len() == 1 {
                        args.push(Arg::IdArg(*child_ids.first().unwrap()));
                    } else {
                        is_valid = false;
                        println!(
                            "error: {}:{}: {} for field: {}::{}",
                            &self.path,
                            node.start_position().row,
                            if child_ids.is_empty() {
                                "missing value"
                            } else {
                                "too many values"
                            },
                            node.kind(),
                            match field.name.as_ref() {
                                Some(x) => x,
                                None => "child",
                            }
                        )
                    }
                }
                Storage::Table { parent, index } => {
                    for child_id in child_ids {
                        self.program.push(Fact::ChildOf(
                            node_type_name(&parent.kind, parent.named),
                            parent_id,
                            match &field.name {
                                Some(name) => name.to_owned(),
                                None => "child".to_owned(),
                            },
                            Index(*index),
                            *child_id,
                        ));
                    }
                }
            }
        }
        if is_valid {
            Some(args)
        } else {
            None
        }
    }
    fn type_matches(&self, tp: &TypeName, types: &Set<TypeName>) -> bool {
        if types.contains(tp) {
            return true;
        }
        for other in types.iter() {
            if let Some(x) = self.union_types.get(other) {
                if self.type_matches(tp, x) {
                    return true;
                }
            }
        }
        return false;
    }
}

// Emit a slice of a source file as an Arg.
fn sliced_source_arg(source: &Vec<u8>, n: Node) -> Arg {
    let range = n.byte_range();
    Arg::StringArg(String::from(
        std::str::from_utf8(&source[range.start..range.end]).expect("Failed to decode string"),
    ))
}

// Emit a 'Located' fact for the provided node, appropriately calibrated.
fn location_for<'a>(fp: &String, ident: Loc, n: Node) -> Fact {
    let start_line = n.start_position().row;
    let start_col = n.start_position().column;
    let end_line = n.end_position().row;
    let end_col = n.end_position().column;
    Fact::Located(vec![
        Arg::LocArg(ident),
        Arg::StringArg(fp.to_owned()),
        Arg::IntArg(start_line),
        Arg::IntArg(start_col),
        Arg::IntArg(end_line),
        Arg::IntArg(end_col),
    ])
}

fn traverse(tree: &Tree, visitor: &mut Visitor) {
    let cursor = &mut tree.walk();
    visitor.enter_node(cursor.node());
    let mut recurse = true;
    loop {
        if recurse && cursor.goto_first_child() {
            visitor.enter_node(cursor.node());
        } else {
            visitor.leave_node(cursor.field_name(), cursor.node());

            if cursor.goto_next_sibling() {
                recurse = true;
                visitor.enter_node(cursor.node());
            } else if cursor.goto_parent() {
                recurse = false;
            } else {
                break;
            }
        }
    }
}
pub struct Program(Vec<Fact>);

impl fmt::Display for Program {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let mut text = String::new();
        for fact in &self.0 {
            text.push_str(&format!("{}\n", fact));
        }
        write!(f, "{}", text)
    }
}
#[derive(Debug)]
enum Fact {
    // @id = *@
    New(Arg),
    // @node_def(self, arg?, location)@
    Definition(String, Id, Vec<Arg>, Loc),
    // @node_child(self, index, parent)@
    ChildOf(String, Id, String, Index, Id),
    // @location(loc, path, r1, c1, r2, c2)
    Located(Vec<Arg>),
    Comment(String),
}
impl fmt::Display for Fact {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            Fact::New(id) => write!(f, "{} = *", id),
            Fact::Definition(n, id, args, loc) => {
                let mut args_str = String::new();
                for arg in args {
                    args_str.push_str(&format!("{}, ", arg));
                }
                write!(
                    f,
                    "{}({}, {}{})",
                    escape_name(&format!("{}_def", &n)),
                    id,
                    args_str,
                    loc
                )
            }
            Fact::ChildOf(pname, id, fname, idx, p) => write!(
                f,
                "{}({}, {}, {})",
                escape_name(&format!("{}_{}", &pname, &fname)),
                id,
                idx,
                p
            ),
            Fact::Located(args) => write!(
                f,
                "location({}, {}, {}, {}, {}, {})",
                args.get(0).unwrap(),
                args.get(1).unwrap(),
                args.get(2).unwrap(),
                args.get(3).unwrap(),
                args.get(4).unwrap(),
                args.get(5).unwrap(),
            ),
            Fact::Comment(line) => write!(f, "// {}", line),
        }
    }
}
// Identifiers of the form #0, #1...
#[derive(Debug, Copy, Clone)]
struct Id(i32);

impl fmt::Display for Id {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "#{}", self.0)
    }
}
// Locative identifiers of the form #0_loc, #1_loc...
#[derive(Debug, Copy, Clone)]
struct Loc(i32);

impl fmt::Display for Loc {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "#{}_loc", self.0)
    }
}
// Numeric indices.
#[derive(Debug, Copy, Clone)]
struct Index(usize);

impl fmt::Display for Index {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.0)
    }
}

// Some untyped argument to a fact.
#[derive(Debug)]
enum Arg {
    IntArg(usize),
    StringArg(String),
    IdArg(Id),
    LocArg(Loc),
}

impl fmt::Display for Arg {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            Arg::IntArg(x) => write!(f, "{}", x),
            Arg::StringArg(x) => write!(f, "\"{}\"", x.replace("\"", "\"\"")),
            Arg::IdArg(x) => write!(f, "{}", x),
            Arg::LocArg(x) => write!(f, "{}", x),
        }
    }
}

const RESERVED_KEYWORDS: [&'static str; 14] = [
    "boolean", "case", "date", "float", "int", "key", "of", "order", "ref", "string", "subtype",
    "type", "unique", "varchar",
];

/// Returns a string that's a copy of `name` but suitably escaped to be a valid
/// QL identifier.
pub fn escape_name(name: &str) -> String {
    let mut result = String::new();

    // If there's a leading underscore, replace it with 'underscore_'.
    if let Some(c) = name.chars().next() {
        if c == '_' {
            result.push_str("underscore");
        }
    }
    for c in name.chars() {
        match c {
            '{' => result.push_str("lbrace"),
            '}' => result.push_str("rbrace"),
            '<' => result.push_str("langle"),
            '>' => result.push_str("rangle"),
            '[' => result.push_str("lbracket"),
            ']' => result.push_str("rbracket"),
            '(' => result.push_str("lparen"),
            ')' => result.push_str("rparen"),
            '|' => result.push_str("pipe"),
            '=' => result.push_str("equal"),
            '~' => result.push_str("tilde"),
            '?' => result.push_str("question"),
            '`' => result.push_str("backtick"),
            '^' => result.push_str("caret"),
            '!' => result.push_str("bang"),
            '#' => result.push_str("hash"),
            '%' => result.push_str("percent"),
            '&' => result.push_str("ampersand"),
            '.' => result.push_str("dot"),
            ',' => result.push_str("comma"),
            '/' => result.push_str("slash"),
            ':' => result.push_str("colon"),
            ';' => result.push_str("semicolon"),
            '"' => result.push_str("dquote"),
            '*' => result.push_str("star"),
            '+' => result.push_str("plus"),
            '-' => result.push_str("minus"),
            '@' => result.push_str("at"),
            _ => result.push_str(&c.to_lowercase().to_string()),
        }
    }

    for &keyword in &RESERVED_KEYWORDS {
        if result == keyword {
            result.push_str("__");
            break;
        }
    }

    result
}

/// Given a tree-sitter node type's (kind, named) pair, returns a single string
/// representing the (unescaped) name we'll use to refer to corresponding QL
/// type.
fn node_type_name(kind: &str, named: bool) -> String {
    if named {
        kind.to_string()
    } else {
        format!("{}_unnamed", kind)
    }
}
<|endoftext|>


<commit_before>use std::collections::BTreeMap;

use context::ContextMap;
use dispatcher::demux::Demultiplexer;
use dispatcher::request::{RequestHandle, Request};
use reactor::{Event, EventDemultiplexer, EventHandler, Reactor, SharedData};
use dispatcher::response::ResponseSender;

pub struct RequestReactor {
    handlers: BTreeMap<RequestHandle, Box<for<'a> EventHandler<Request, SharedData<'a>>>>,
    demultiplexer: Demultiplexer<Request>,
    context_map: ContextMap,
    responder: Box<ResponseSender>,
}

impl RequestReactor {
    pub fn new(demultiplexer: Demultiplexer<Request>,
               context_map: ContextMap,
               responder: Box<ResponseSender>)
               -> RequestReactor {
        RequestReactor {
            demultiplexer: demultiplexer,
            context_map: context_map,
            handlers: BTreeMap::new(),
            responder: responder,
        }
    }
}

impl Reactor for RequestReactor {
    type Event = Request;
    fn handle_events(&mut self) {
        let mut shared_data = SharedData::new(&mut self.context_map, &mut *self.responder);
        while let Some(request) = self.demultiplexer.select() {
            trace!("RequestReactor: got event");
            if let Some(handler) = self.handlers.get_mut(&request.handle()) {
                handler.handle_event(request, &mut shared_data);
            } else {
                trace!("RequestReactor: no handler found for event");
            }
        }
    }
    fn register_handler(&mut self,
                        handler: Box<for<'a> EventHandler<Self::Event, SharedData<'a>>>) {
        self.handlers.insert(handler.handle(), handler);
    }
    fn remove_handler_by_handle(&mut self, handler: &RequestHandle) {
        self.handlers.remove(handler);
    }
}
<commit_msg>RequestReactor: allow complex types<commit_after>use std::collections::BTreeMap;

use context::ContextMap;
use dispatcher::demux::Demultiplexer;
use dispatcher::request::{RequestHandle, Request};
use reactor::{Event, EventDemultiplexer, EventHandler, Reactor, SharedData};
use dispatcher::response::ResponseSender;

#[allow(type_complexity)]
pub struct RequestReactor {
    handlers: BTreeMap<RequestHandle, Box<for<'a> EventHandler<Request, SharedData<'a>>>>,
    demultiplexer: Demultiplexer<Request>,
    context_map: ContextMap,
    responder: Box<ResponseSender>,
}

impl RequestReactor {
    pub fn new(demultiplexer: Demultiplexer<Request>,
               context_map: ContextMap,
               responder: Box<ResponseSender>)
               -> RequestReactor {
        RequestReactor {
            demultiplexer: demultiplexer,
            context_map: context_map,
            handlers: BTreeMap::new(),
            responder: responder,
        }
    }
}

impl Reactor for RequestReactor {
    type Event = Request;
    fn handle_events(&mut self) {
        let mut shared_data = SharedData::new(&mut self.context_map, &mut *self.responder);
        while let Some(request) = self.demultiplexer.select() {
            trace!("RequestReactor: got event");
            if let Some(handler) = self.handlers.get_mut(&request.handle()) {
                handler.handle_event(request, &mut shared_data);
            } else {
                trace!("RequestReactor: no handler found for event");
            }
        }
    }
    fn register_handler(&mut self,
                        handler: Box<for<'a> EventHandler<Self::Event, SharedData<'a>>>) {
        self.handlers.insert(handler.handle(), handler);
    }
    fn remove_handler_by_handle(&mut self, handler: &RequestHandle) {
        self.handlers.remove(handler);
    }
}
<|endoftext|>


<commit_before>//! Common code of `build.rs` of two tests

pub use protobuf_codegen::Customize;

use std::io::Write;
use std::fs;
use std::fmt;
use std::path::Path;

use glob;

pub fn glob_simple(pattern: &str) -> Vec<String> {
    glob::glob(pattern)
        .expect("glob")
        .map(|g| {
            g.expect("item")
                .as_path()
                .to_str()
                .expect("utf-8")
                .to_owned()
        })
        .collect()
}

pub fn clean_old_files() {
    // TODO: use .gitignore
    for f in glob_simple("src/**/*_pb.rs") {
        fs::remove_file(f).expect("rm");
    }
    for f in glob_simple("src/**/*_pb_proto3.rs") {
        fs::remove_file(f).expect("rm");
    }
}

#[derive(Default)]
pub struct GenInDirArgs<'a> {
    pub out_dir: &'a str,
    pub input: &'a [&'a str],
    pub includes: &'a [&'a str],
    pub customize: Customize,
}

/// Generate mod.rs from all files in a directory
pub fn gen_mod_rs_in_dir(dir: &str) {
    assert!(Path::new(dir).is_dir());

    let mut mod_rs = fs::File::create(&format!("{}/mod.rs", dir)).expect("create");

    writeln!(mod_rs, "// generated by {}", module_path!()).expect("write");
    writeln!(mod_rs, "").expect("write");

    let rs_files = glob_simple(&format!("{}/*.rs", dir));

    for rs in rs_files {
        let file_name = Path::new(&rs).file_name().expect("file_name").to_str().expect("file_name");
        if file_name == "mod.rs" {
            continue;
        }
        assert!(file_name.ends_with(".rs"));
        let mod_name = &file_name[..file_name.len() - ".rs".len()];

        if mod_name.contains("carllerche") {
            writeln!(mod_rs, r#"#[cfg(feature = "with-bytes")]"#).expect("write");
        }
        writeln!(mod_rs, "mod {};", mod_name).expect("write");
    }

    mod_rs.flush().expect("flush");
}

pub fn gen_in_dir<F, E>(dir: &str, gen: F)
    where
        F : for<'a> Fn(GenInDirArgs<'a>) -> Result<(), E>,
        E : fmt::Debug,
{
    info!("generating protos in {}", dir);

    let mut protos = Vec::new();
    for suffix in &[".proto", ".proto3"] {
        protos.extend(glob_simple(&format!("{}/*{}", dir, suffix)));
    }

    assert!(!protos.is_empty());

    gen(GenInDirArgs {
        out_dir: dir,
        input: &protos.iter().map(|a| a.as_ref()).collect::<Vec<&str>>(),
        includes: &["../proto", dir],
        .. Default::default()
    }).expect("protoc");

    gen_mod_rs_in_dir(dir);
}
<commit_msg>Use .gitignore to clean old files<commit_after>//! Common code of `build.rs` of two tests

pub use protobuf_codegen::Customize;

use std::io::Write;
use std::io::BufRead;
use std::io::BufReader;
use std::fs;
use std::fmt;
use std::path::Path;

use glob;

pub fn glob_simple(pattern: &str) -> Vec<String> {
    glob::glob(pattern)
        .expect("glob")
        .map(|g| {
            g.expect("item")
                .as_path()
                .to_str()
                .expect("utf-8")
                .to_owned()
        })
        .collect()
}

fn read_gitignore(dir: &Path) -> Vec<String> {
    let mut patterns = Vec::new();

    let gitignore = format!("{}/.gitignore", dir.display());
    let gitignore = &Path::new(&gitignore);
    if gitignore.exists() {
        let gitignore = fs::File::open(gitignore).expect("open gitignore");
        for line in BufReader::new(gitignore).lines() {
            let line = line.expect("read_line");
            if line.is_empty() || line.starts_with("#") {
                continue;
            }
            patterns.push(line);
        }
    }

    patterns
}

fn clean_recursively(dir: &Path, patterns: &[&str]) {
    assert!(dir.is_dir());

    let gitignore_patterns = read_gitignore(dir);

    let mut patterns = patterns.to_vec();
    patterns.extend(gitignore_patterns.iter().map(String::as_str));

    let patterns_compiled: Vec<_> = patterns.iter()
        .map(|&p| glob::Pattern::new(p).expect("failed to compile pattern"))
        .collect();

    for entry in fs::read_dir(dir).expect("read_dir") {
        let entry = entry.expect("entry");
        let entry_path = entry.path();
        let file_name = entry_path.as_path().file_name().unwrap().to_str().unwrap();
        if entry.metadata().expect("metadata").is_dir() {
            clean_recursively(&entry_path, &patterns);
        } else if file_name == ".gitignore" {
            // keep it
        } else {
            for pattern in &patterns_compiled {
                if pattern.matches(file_name) {
                    fs::remove_file(&entry_path).expect("remove_file");
                    break;
                }
            }
        }
    }
}

pub fn clean_old_files() {
    clean_recursively(&Path::new("src"), &["*_pb.rs", "*_pb_proto3.rs"]);
}

#[derive(Default)]
pub struct GenInDirArgs<'a> {
    pub out_dir: &'a str,
    pub input: &'a [&'a str],
    pub includes: &'a [&'a str],
    pub customize: Customize,
}

/// Generate mod.rs from all files in a directory
pub fn gen_mod_rs_in_dir(dir: &str) {
    assert!(Path::new(dir).is_dir());

    let mut mod_rs = fs::File::create(&format!("{}/mod.rs", dir)).expect("create");

    writeln!(mod_rs, "// generated by {}", module_path!()).expect("write");
    writeln!(mod_rs, "").expect("write");

    let rs_files = glob_simple(&format!("{}/*.rs", dir));

    for rs in rs_files {
        let file_name = Path::new(&rs).file_name().expect("file_name").to_str().expect("file_name");
        if file_name == "mod.rs" {
            continue;
        }
        assert!(file_name.ends_with(".rs"));
        let mod_name = &file_name[..file_name.len() - ".rs".len()];

        if mod_name.contains("carllerche") {
            writeln!(mod_rs, r#"#[cfg(feature = "with-bytes")]"#).expect("write");
        }
        writeln!(mod_rs, "mod {};", mod_name).expect("write");
    }

    mod_rs.flush().expect("flush");
}

pub fn gen_in_dir<F, E>(dir: &str, gen: F)
    where
        F : for<'a> Fn(GenInDirArgs<'a>) -> Result<(), E>,
        E : fmt::Debug,
{
    info!("generating protos in {}", dir);

    let mut protos = Vec::new();
    for suffix in &[".proto", ".proto3"] {
        protos.extend(glob_simple(&format!("{}/*{}", dir, suffix)));
    }

    assert!(!protos.is_empty());

    gen(GenInDirArgs {
        out_dir: dir,
        input: &protos.iter().map(|a| a.as_ref()).collect::<Vec<&str>>(),
        includes: &["../proto", dir],
        .. Default::default()
    }).expect("protoc");

    gen_mod_rs_in_dir(dir);
}
<|endoftext|>


<commit_before>// See: https://github.com/rust-lang/regex/issues/48
#[test]
fn invalid_regexes_no_crash() {
    assert!(regex_new!("(*)").is_err());
    assert!(regex_new!("(?:?)").is_err());
    assert!(regex_new!("(?)").is_err());
    assert!(regex_new!("*").is_err());
}

// See: https://github.com/rust-lang/regex/issues/98
#[test]
fn regression_many_repeat_stack_overflow() {
    let re = regex!("^.{1,2500}");
    assert_eq!(vec![(0, 1)], findall!(re, "a"));
}

// See: https://github.com/rust-lang/regex/issues/555
#[test]
fn regression_invalid_repetition_expr() {
    assert!(regex_new!("(?m){1,1}").is_err());
}

// See: https://github.com/rust-lang/regex/issues/527
#[test]
fn regression_invalid_flags_expression() {
    assert!(regex_new!("(((?x)))").is_ok());
}

// See: https://github.com/rust-lang/regex/issues/75
mat!(regression_unsorted_binary_search_1, r"(?i-u)[a_]+", "A_", Some((0, 2)));
mat!(regression_unsorted_binary_search_2, r"(?i-u)[A_]+", "a_", Some((0, 2)));

// See: https://github.com/rust-lang/regex/issues/99
#[cfg(feature = "unicode-case")]
mat!(regression_negated_char_class_1, r"(?i)[^x]", "x", None);
#[cfg(feature = "unicode-case")]
mat!(regression_negated_char_class_2, r"(?i)[^x]", "X", None);

// See: https://github.com/rust-lang/regex/issues/101
mat!(regression_ascii_word_underscore, r"[[:word:]]", "_", Some((0, 1)));

// See: https://github.com/rust-lang/regex/issues/129
#[test]
fn regression_captures_rep() {
    let re = regex!(r"([a-f]){2}(?P<foo>[x-z])");
    let caps = re.captures(text!("abx")).unwrap();
    assert_eq!(match_text!(caps.name("foo").unwrap()), text!("x"));
}

// See: https://github.com/rust-lang/regex/issues/153
mat!(regression_alt_in_alt1, r"ab?|$", "az", Some((0, 1)));
mat!(regression_alt_in_alt2, r"^(.*?)(\n|\r\n?|$)", "ab\rcd", Some((0, 3)));

// See: https://github.com/rust-lang/regex/issues/169
mat!(regression_leftmost_first_prefix, r"z*azb", "azb", Some((0, 3)));

// See: https://github.com/rust-lang/regex/issues/76
#[cfg(all(feature = "unicode-case", feature = "unicode-gencat"))]
mat!(uni_case_lower_nocase_flag, r"(?i)\p{Ll}+", "ΛΘΓΔα", Some((0, 10)));

// See: https://github.com/rust-lang/regex/issues/191
mat!(many_alternates, r"1|2|3|4|5|6|7|8|9|10|int", "int", Some((0, 3)));

// burntsushi was bad and didn't create an issue for this bug.
mat!(anchored_prefix1, r"^a[[:^space:]]", "a ", None);
mat!(anchored_prefix2, r"^a[[:^space:]]", "foo boo a ", None);
mat!(anchored_prefix3, r"^-[a-z]", "r-f", None);

// See: https://github.com/rust-lang/regex/issues/204
#[cfg(feature = "unicode-perl")]
split!(
    split_on_word_boundary,
    r"\b",
    r"Should this (work?)",
    &[
        t!(""),
        t!("Should"),
        t!(" "),
        t!("this"),
        t!(" ("),
        t!("work"),
        t!("?)")
    ]
);
#[cfg(feature = "unicode-perl")]
matiter!(
    word_boundary_dfa,
    r"\b",
    "a b c",
    (0, 0),
    (1, 1),
    (2, 2),
    (3, 3),
    (4, 4),
    (5, 5)
);

// See: https://github.com/rust-lang/regex/issues/268
matiter!(partial_anchor, r"^a|b", "ba", (0, 1));

// See: https://github.com/rust-lang/regex/issues/280
ismatch!(partial_anchor_alternate_begin, r"^a|z", "yyyyya", false);
ismatch!(partial_anchor_alternate_end, r"a$|z", "ayyyyy", false);

// See: https://github.com/rust-lang/regex/issues/289
mat!(lits_unambiguous1, r"(ABC|CDA|BC)X", "CDAX", Some((0, 4)));

// See: https://github.com/rust-lang/regex/issues/291
mat!(
    lits_unambiguous2,
    r"((IMG|CAM|MG|MB2)_|(DSCN|CIMG))(?P<n>[0-9]+)$",
    "CIMG2341",
    Some((0, 8)),
    Some((0, 4)),
    None,
    Some((0, 4)),
    Some((4, 8))
);

// See: https://github.com/rust-lang/regex/issues/271
mat!(endl_or_wb, r"(?m:$)|(?-u:\b)", "\u{6084e}", Some((4, 4)));
mat!(zero_or_end, r"(?i-u:\x00)|$", "\u{e682f}", Some((4, 4)));
mat!(y_or_endl, r"(?i-u:y)|(?m:$)", "\u{b4331}", Some((4, 4)));
#[cfg(feature = "unicode-perl")]
mat!(wb_start_x, r"(?u:\b)^(?-u:X)", "X", Some((0, 1)));

// See: https://github.com/rust-lang/regex/issues/321
ismatch!(strange_anchor_non_complete_prefix, r"a^{2}", "", false);
ismatch!(strange_anchor_non_complete_suffix, r"${2}a", "", false);

// See: https://github.com/BurntSushi/ripgrep/issues/1203
ismatch!(reverse_suffix1, r"[0-4][0-4][0-4]000", "153.230000", true);
ismatch!(reverse_suffix2, r"[0-9][0-9][0-9]000", "153.230000\n", true);
matiter!(reverse_suffix3, r"[0-9][0-9][0-9]000", "153.230000\n", (4, 10));

// See: https://github.com/rust-lang/regex/issues/334
// See: https://github.com/rust-lang/regex/issues/557
mat!(
    captures_after_dfa_premature_end1,
    r"a(b*(X|$))?",
    "abcbX",
    Some((0, 1)),
    None,
    None
);
mat!(
    captures_after_dfa_premature_end2,
    r"a(bc*(X|$))?",
    "abcbX",
    Some((0, 1)),
    None,
    None
);
mat!(captures_after_dfa_premature_end3, r"(aa$)?", "aaz", Some((0, 0)));

// See: https://github.com/rust-lang/regex/issues/437
ismatch!(
    literal_panic,
    r"typename type\-parameter\-[0-9]+\-[0-9]+::.+",
    "test",
    false
);

// See: https://github.com/rust-lang/regex/issues/533
ismatch!(
    blank_matches_nothing_between_space_and_tab,
    r"[[:blank:]]",
    "\u{a}\u{b}\u{c}\u{d}\u{e}\u{f}\
     \u{10}\u{11}\u{12}\u{13}\u{14}\u{15}\u{16}\u{17}\
     \u{18}\u{19}\u{1a}\u{1b}\u{1c}\u{1d}\u{1e}\u{1f}",
    false
);

ismatch!(
    inverted_blank_matches_everything_between_space_and_tab,
    r"^[[:^blank:]]+$",
    "\u{a}\u{b}\u{c}\u{d}\u{e}\u{f}\
     \u{10}\u{11}\u{12}\u{13}\u{14}\u{15}\u{16}\u{17}\
     \u{18}\u{19}\u{1a}\u{1b}\u{1c}\u{1d}\u{1e}\u{1f}",
    true
);

// Tests that our Aho-Corasick optimization works correctly. It only
// kicks in when we have >32 literals. By "works correctly," we mean that
// leftmost-first match semantics are properly respected. That is, samwise
// should match, not sam.
mat!(
    ahocorasick1,
    "samwise|sam|a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z|\
     A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z",
    "samwise",
    Some((0, 7))
);

// See: https://github.com/BurntSushi/ripgrep/issues/1247
#[test]
#[cfg(feature = "unicode-perl")]
fn regression_nfa_stops1() {
    let re = ::regex::bytes::Regex::new(r"\bs(?:[ab])").unwrap();
    assert_eq!(0, re.find_iter(b"s\xE4").count());
}

// See: https://github.com/rust-lang/regex/issues/640
#[cfg(feature = "unicode-case")]
matiter!(
    flags_are_unset,
    r"((?i)foo)|Bar",
    "foo Foo bar Bar",
    (0, 3),
    (4, 7),
    (12, 15)
);
<commit_msg>tests: add regression test for #659<commit_after>// See: https://github.com/rust-lang/regex/issues/48
#[test]
fn invalid_regexes_no_crash() {
    assert!(regex_new!("(*)").is_err());
    assert!(regex_new!("(?:?)").is_err());
    assert!(regex_new!("(?)").is_err());
    assert!(regex_new!("*").is_err());
}

// See: https://github.com/rust-lang/regex/issues/98
#[test]
fn regression_many_repeat_stack_overflow() {
    let re = regex!("^.{1,2500}");
    assert_eq!(vec![(0, 1)], findall!(re, "a"));
}

// See: https://github.com/rust-lang/regex/issues/555
#[test]
fn regression_invalid_repetition_expr() {
    assert!(regex_new!("(?m){1,1}").is_err());
}

// See: https://github.com/rust-lang/regex/issues/527
#[test]
fn regression_invalid_flags_expression() {
    assert!(regex_new!("(((?x)))").is_ok());
}

// See: https://github.com/rust-lang/regex/issues/75
mat!(regression_unsorted_binary_search_1, r"(?i-u)[a_]+", "A_", Some((0, 2)));
mat!(regression_unsorted_binary_search_2, r"(?i-u)[A_]+", "a_", Some((0, 2)));

// See: https://github.com/rust-lang/regex/issues/99
#[cfg(feature = "unicode-case")]
mat!(regression_negated_char_class_1, r"(?i)[^x]", "x", None);
#[cfg(feature = "unicode-case")]
mat!(regression_negated_char_class_2, r"(?i)[^x]", "X", None);

// See: https://github.com/rust-lang/regex/issues/101
mat!(regression_ascii_word_underscore, r"[[:word:]]", "_", Some((0, 1)));

// See: https://github.com/rust-lang/regex/issues/129
#[test]
fn regression_captures_rep() {
    let re = regex!(r"([a-f]){2}(?P<foo>[x-z])");
    let caps = re.captures(text!("abx")).unwrap();
    assert_eq!(match_text!(caps.name("foo").unwrap()), text!("x"));
}

// See: https://github.com/rust-lang/regex/issues/153
mat!(regression_alt_in_alt1, r"ab?|$", "az", Some((0, 1)));
mat!(regression_alt_in_alt2, r"^(.*?)(\n|\r\n?|$)", "ab\rcd", Some((0, 3)));

// See: https://github.com/rust-lang/regex/issues/169
mat!(regression_leftmost_first_prefix, r"z*azb", "azb", Some((0, 3)));

// See: https://github.com/rust-lang/regex/issues/76
#[cfg(all(feature = "unicode-case", feature = "unicode-gencat"))]
mat!(uni_case_lower_nocase_flag, r"(?i)\p{Ll}+", "ΛΘΓΔα", Some((0, 10)));

// See: https://github.com/rust-lang/regex/issues/191
mat!(many_alternates, r"1|2|3|4|5|6|7|8|9|10|int", "int", Some((0, 3)));

// burntsushi was bad and didn't create an issue for this bug.
mat!(anchored_prefix1, r"^a[[:^space:]]", "a ", None);
mat!(anchored_prefix2, r"^a[[:^space:]]", "foo boo a ", None);
mat!(anchored_prefix3, r"^-[a-z]", "r-f", None);

// See: https://github.com/rust-lang/regex/issues/204
#[cfg(feature = "unicode-perl")]
split!(
    split_on_word_boundary,
    r"\b",
    r"Should this (work?)",
    &[
        t!(""),
        t!("Should"),
        t!(" "),
        t!("this"),
        t!(" ("),
        t!("work"),
        t!("?)")
    ]
);
#[cfg(feature = "unicode-perl")]
matiter!(
    word_boundary_dfa,
    r"\b",
    "a b c",
    (0, 0),
    (1, 1),
    (2, 2),
    (3, 3),
    (4, 4),
    (5, 5)
);

// See: https://github.com/rust-lang/regex/issues/268
matiter!(partial_anchor, r"^a|b", "ba", (0, 1));

// See: https://github.com/rust-lang/regex/issues/280
ismatch!(partial_anchor_alternate_begin, r"^a|z", "yyyyya", false);
ismatch!(partial_anchor_alternate_end, r"a$|z", "ayyyyy", false);

// See: https://github.com/rust-lang/regex/issues/289
mat!(lits_unambiguous1, r"(ABC|CDA|BC)X", "CDAX", Some((0, 4)));

// See: https://github.com/rust-lang/regex/issues/291
mat!(
    lits_unambiguous2,
    r"((IMG|CAM|MG|MB2)_|(DSCN|CIMG))(?P<n>[0-9]+)$",
    "CIMG2341",
    Some((0, 8)),
    Some((0, 4)),
    None,
    Some((0, 4)),
    Some((4, 8))
);

// See: https://github.com/rust-lang/regex/issues/271
mat!(endl_or_wb, r"(?m:$)|(?-u:\b)", "\u{6084e}", Some((4, 4)));
mat!(zero_or_end, r"(?i-u:\x00)|$", "\u{e682f}", Some((4, 4)));
mat!(y_or_endl, r"(?i-u:y)|(?m:$)", "\u{b4331}", Some((4, 4)));
#[cfg(feature = "unicode-perl")]
mat!(wb_start_x, r"(?u:\b)^(?-u:X)", "X", Some((0, 1)));

// See: https://github.com/rust-lang/regex/issues/321
ismatch!(strange_anchor_non_complete_prefix, r"a^{2}", "", false);
ismatch!(strange_anchor_non_complete_suffix, r"${2}a", "", false);

// See: https://github.com/BurntSushi/ripgrep/issues/1203
ismatch!(reverse_suffix1, r"[0-4][0-4][0-4]000", "153.230000", true);
ismatch!(reverse_suffix2, r"[0-9][0-9][0-9]000", "153.230000\n", true);
matiter!(reverse_suffix3, r"[0-9][0-9][0-9]000", "153.230000\n", (4, 10));

// See: https://github.com/rust-lang/regex/issues/334
// See: https://github.com/rust-lang/regex/issues/557
mat!(
    captures_after_dfa_premature_end1,
    r"a(b*(X|$))?",
    "abcbX",
    Some((0, 1)),
    None,
    None
);
mat!(
    captures_after_dfa_premature_end2,
    r"a(bc*(X|$))?",
    "abcbX",
    Some((0, 1)),
    None,
    None
);
mat!(captures_after_dfa_premature_end3, r"(aa$)?", "aaz", Some((0, 0)));

// See: https://github.com/rust-lang/regex/issues/437
ismatch!(
    literal_panic,
    r"typename type\-parameter\-[0-9]+\-[0-9]+::.+",
    "test",
    false
);

// See: https://github.com/rust-lang/regex/issues/533
ismatch!(
    blank_matches_nothing_between_space_and_tab,
    r"[[:blank:]]",
    "\u{a}\u{b}\u{c}\u{d}\u{e}\u{f}\
     \u{10}\u{11}\u{12}\u{13}\u{14}\u{15}\u{16}\u{17}\
     \u{18}\u{19}\u{1a}\u{1b}\u{1c}\u{1d}\u{1e}\u{1f}",
    false
);

ismatch!(
    inverted_blank_matches_everything_between_space_and_tab,
    r"^[[:^blank:]]+$",
    "\u{a}\u{b}\u{c}\u{d}\u{e}\u{f}\
     \u{10}\u{11}\u{12}\u{13}\u{14}\u{15}\u{16}\u{17}\
     \u{18}\u{19}\u{1a}\u{1b}\u{1c}\u{1d}\u{1e}\u{1f}",
    true
);

// Tests that our Aho-Corasick optimization works correctly. It only
// kicks in when we have >32 literals. By "works correctly," we mean that
// leftmost-first match semantics are properly respected. That is, samwise
// should match, not sam.
mat!(
    ahocorasick1,
    "samwise|sam|a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z|\
     A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z",
    "samwise",
    Some((0, 7))
);

// See: https://github.com/BurntSushi/ripgrep/issues/1247
#[test]
#[cfg(feature = "unicode-perl")]
fn regression_nfa_stops1() {
    let re = ::regex::bytes::Regex::new(r"\bs(?:[ab])").unwrap();
    assert_eq!(0, re.find_iter(b"s\xE4").count());
}

// See: https://github.com/rust-lang/regex/issues/640
#[cfg(feature = "unicode-case")]
matiter!(
    flags_are_unset,
    r"((?i)foo)|Bar",
    "foo Foo bar Bar",
    (0, 3),
    (4, 7),
    (12, 15)
);

// See: https://github.com/rust-lang/regex/issues/659
//
// Note that 'Ј' is not 'j', but cyrillic Je
// https://en.wikipedia.org/wiki/Je_(Cyrillic)
ismatch!(empty_group_match, r"()Ј01", "zЈ01", true);
matiter!(empty_group_find, r"()Ј01", "zЈ01", (1, 5));
<|endoftext|>


<commit_before>extern crate hyper;
extern crate alacrity;
extern crate env_logger;
#[macro_use] extern crate log;

use hyper::server::{Server, Request, Response, Handler};
use hyper::header::{ContentLength};
use hyper::Client;
use std::io::{Read, Write};
use std::net::SocketAddr;
use alacrity::pool::Pool;
use std::{thread, time};

fn with_server<H: Handler + 'static, R>(handle: H, proxy_port: u16, test: &Fn(u16) -> R) -> R {
    let mut server = Server::http("127.0.0.1:0").unwrap().handle(handle).unwrap();
    let port = server.socket.port();
    let server_addr = server.socket;

    // test directly against http server
    test(port);

    // test against proxy
    thread::spawn(move || {
        // TODO: it would be more convenient to use the port 0 to let the kernel pick one free port for us
        // https://github.com/hjr3/alacrity/issues/12
        let proxy_addr = format!("127.0.0.1:{}", proxy_port);
        let addr = proxy_addr.parse::<SocketAddr>().unwrap();
        let pool = Pool::with_servers(vec![server_addr]);
        alacrity::proxy::listen(addr, pool.clone()).expect("Failed to start server");
    });
    // TODO: need a better way to wait for proxy to be up
    thread::sleep(time::Duration::from_millis(50));

    let result_proxy = test(proxy_port);

    // TODO: close proxy - https://github.com/hjr3/alacrity/issues/11
    // TODO: close previously created thread
    server.close().unwrap();
    result_proxy
}

fn url(port: u16) -> String {
    format!("http://localhost:{}", port)
}

fn hello_request_method(req: Request, mut res: Response) {
    let body = format!("hello {}", req.method);
    res.headers_mut().set(ContentLength(body.len() as u64));
    let mut res = res.start().unwrap();
    res.write_all(body.as_ref()).unwrap();
}

#[test]
fn get_on_http_server() {
    let _ = env_logger::init();

    with_server(hello_request_method, 8081, &|port| {
        let client = Client::new();
        let url = url(port);
        let mut res = client.get(&url).send().unwrap();
        assert_eq!(res.status, hyper::Ok);

        let mut body = String::new();
        res.read_to_string(&mut body).unwrap();
        assert_eq!(body, "hello GET");
    });
}

#[test]
fn delete_on_http_server() {
    let _ = env_logger::init();

    with_server(hello_request_method, 8082, &|port| {
        let client = Client::new();
        let url = url(port);
        let mut res = client.delete(&url).send().unwrap();
        assert_eq!(res.status, hyper::Ok);

        let mut body = String::new();
        res.read_to_string(&mut body).unwrap();
        assert_eq!(body, "hello DELETE");
    });
}
<commit_msg>test more methods<commit_after>extern crate hyper;
extern crate alacrity;
extern crate env_logger;
#[macro_use] extern crate log;

use hyper::server::{Server, Request, Response, Handler};
use hyper::header::{ContentLength};
use hyper::Client;
use std::io::{Read, Write};
use std::net::SocketAddr;
use alacrity::pool::Pool;
use std::{thread, time};

fn with_server<H: Handler + 'static, R>(handle: H, proxy_port: u16, test: &Fn(u16) -> R) -> R {
    let mut server = Server::http("127.0.0.1:0").unwrap().handle(handle).unwrap();
    let port = server.socket.port();
    let server_addr = server.socket;

    // test directly against http server
    test(port);

    // test against proxy
    thread::spawn(move || {
        // TODO: it would be more convenient to use the port 0 to let the kernel pick one free port for us
        // https://github.com/hjr3/alacrity/issues/12
        let proxy_addr = format!("127.0.0.1:{}", proxy_port);
        let addr = proxy_addr.parse::<SocketAddr>().unwrap();
        let pool = Pool::with_servers(vec![server_addr]);
        alacrity::proxy::listen(addr, pool.clone()).expect("Failed to start server");
    });
    // TODO: need a better way to wait for proxy to be up
    thread::sleep(time::Duration::from_millis(50));

    let result_proxy = test(proxy_port);

    // TODO: close proxy - https://github.com/hjr3/alacrity/issues/11
    // TODO: close previously created thread
    server.close().unwrap();
    result_proxy
}

fn url(port: u16) -> String {
    format!("http://localhost:{}", port)
}

fn hello_request_method(req: Request, mut res: Response) {
    let body = format!("hello {}", req.method);
    res.headers_mut().set(ContentLength(body.len() as u64));
    let mut res = res.start().unwrap();
    res.write_all(body.as_ref()).unwrap();
}

#[test]
fn method_on_http_server() {
    use hyper::method::Method;
    use std::str::FromStr;

    let _ = env_logger::init();

    let methods = vec!("GET", "DELETE", "PATCH", "OPTIONS", "POST", "PUT", "TRACE", "HEAD", "CONNECT", "GARBAGE");
    let port = 8081;

    for (i, method) in methods.iter().enumerate() {
        with_server(hello_request_method, port + i as u16, &|port| {
            let client = Client::new();
            let url = url(port);
            let mut res = client.request(Method::from_str(&method).unwrap(), &url).send().unwrap();
            assert_eq!(res.status, hyper::Ok);

            // missing HEAD, CONNECT as the server cannot return any body
            if *method != "HEAD" && *method != "CONNECT" {
                let mut body = String::new();
                res.read_to_string(&mut body).unwrap();
                let expected = format!("hello {}", method);
                assert_eq!(body, expected);
            }
        });
    };
}
<|endoftext|>


<commit_before>#![allow(
    clippy::decimal_literal_representation,
    clippy::derive_partial_eq_without_eq,
    clippy::unreadable_literal,
    clippy::shadow_unrelated
)]

use indoc::indoc;
use serde_derive::{Deserialize, Serialize};
use serde_yaml::Value;
use std::collections::BTreeMap;
use std::fmt::Debug;

fn test_serde<T>(thing: &T, yaml: &str)
where
    T: serde::Serialize + serde::de::DeserializeOwned + PartialEq + Debug,
{
    let serialized = serde_yaml::to_string(&thing).unwrap();
    assert_eq!(yaml, serialized);

    let value = serde_yaml::to_value(&thing).unwrap();
    let serialized = serde_yaml::to_string(&value).unwrap();
    assert_eq!(yaml, serialized);

    let deserialized: T = serde_yaml::from_str(yaml).unwrap();
    assert_eq!(*thing, deserialized);

    let value: Value = serde_yaml::from_str(yaml).unwrap();
    let deserialized: T = serde_yaml::from_value(value).unwrap();
    assert_eq!(*thing, deserialized);

    serde_yaml::from_str::<serde::de::IgnoredAny>(yaml).unwrap();
}

#[test]
fn test_default() {
    assert_eq!(Value::default(), Value::Null);
}

#[test]
fn test_int() {
    let thing = 256;
    let yaml = indoc! {"
        256
    "};
    test_serde(&thing, yaml);
}

#[test]
fn test_int_max_u64() {
    let thing = u64::MAX;
    let yaml = indoc! {"
        18446744073709551615
    "};
    test_serde(&thing, yaml);
}

#[test]
fn test_int_min_i64() {
    let thing = i64::MIN;
    let yaml = indoc! {"
        -9223372036854775808
    "};
    test_serde(&thing, yaml);
}

#[test]
fn test_int_max_i64() {
    let thing = i64::MAX;
    let yaml = indoc! {"
        9223372036854775807
    "};
    test_serde(&thing, yaml);
}

#[test]
fn test_i128_small() {
    let thing: i128 = -256;
    let yaml = indoc! {"
        -256
    "};
    test_serde(&thing, yaml);
}

#[test]
fn test_u128_small() {
    let thing: u128 = 256;
    let yaml = indoc! {"
        256
    "};
    test_serde(&thing, yaml);
}

#[test]
fn test_float() {
    let thing = 25.6;
    let yaml = indoc! {"
        25.6
    "};
    test_serde(&thing, yaml);

    let thing = 25.;
    let yaml = indoc! {"
        25.0
    "};
    test_serde(&thing, yaml);

    let thing = f64::INFINITY;
    let yaml = indoc! {"
        .inf
    "};
    test_serde(&thing, yaml);

    let thing = f64::NEG_INFINITY;
    let yaml = indoc! {"
        -.inf
    "};
    test_serde(&thing, yaml);

    let float: f64 = serde_yaml::from_str(indoc! {"
        .nan
    "})
    .unwrap();
    assert!(float.is_nan());
}

#[test]
fn test_float32() {
    let thing: f32 = 25.5;
    let yaml = indoc! {"
        25.5
    "};
    test_serde(&thing, yaml);

    let thing = f32::INFINITY;
    let yaml = indoc! {"
        .inf
    "};
    test_serde(&thing, yaml);

    let thing = f32::NEG_INFINITY;
    let yaml = indoc! {"
        -.inf
    "};
    test_serde(&thing, yaml);

    let single_float: f32 = serde_yaml::from_str(indoc! {"
        .nan
    "})
    .unwrap();
    assert!(single_float.is_nan());
}

#[test]
fn test_vec() {
    let thing = vec![1, 2, 3];
    let yaml = indoc! {"
        - 1
        - 2
        - 3
    "};
    test_serde(&thing, yaml);
}

#[test]
fn test_map() {
    let mut thing = BTreeMap::new();
    thing.insert("x".to_owned(), 1);
    thing.insert("y".to_owned(), 2);
    let yaml = indoc! {"
        x: 1
        y: 2
    "};
    test_serde(&thing, yaml);
}

#[test]
fn test_basic_struct() {
    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    struct Basic {
        w: char,
        x: isize,
        y: String,
        z: bool,
    }
    let thing = Basic {
        w: '.',
        x: -4,
        y: "hi\tquoted".to_owned(),
        z: true,
    };
    let yaml = indoc! {r#"
        w: .
        x: -4
        y: "hi\tquoted"
        z: true
    "#};
    test_serde(&thing, yaml);
}

#[test]
fn test_multiline_string() {
    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    struct Struct {
        trailing_newline: String,
        no_trailing_newline: String,
    }
    let thing = Struct {
        trailing_newline: "aaa\nbbb\n".to_owned(),
        no_trailing_newline: "aaa\nbbb".to_owned(),
    };
    let yaml = indoc! {r#"
        trailing_newline: |
          aaa
          bbb
        no_trailing_newline: |-
          aaa
          bbb
    "#};
    test_serde(&thing, yaml);
}

#[test]
fn test_strings_needing_quote() {
    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    struct Struct {
        boolean: String,
        integer: String,
        void: String,
    }
    let thing = Struct {
        boolean: "true".to_owned(),
        integer: "1".to_owned(),
        void: "null".to_owned(),
    };
    let yaml = indoc! {r#"
        boolean: 'true'
        integer: '1'
        void: 'null'
    "#};
    test_serde(&thing, yaml);
}

#[test]
fn test_nested_vec() {
    let thing = vec![vec![1, 2, 3], vec![4, 5, 6]];
    let yaml = indoc! {"
        - - 1
          - 2
          - 3
        - - 4
          - 5
          - 6
    "};
    test_serde(&thing, yaml);
}

#[test]
fn test_nested_struct() {
    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    struct Outer {
        inner: Inner,
    }
    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    struct Inner {
        v: u16,
    }
    let thing = Outer {
        inner: Inner { v: 512 },
    };
    let yaml = indoc! {"
        inner:
          v: 512
    "};
    test_serde(&thing, yaml);
}

#[test]
fn test_option() {
    let thing = vec![Some(1), None, Some(3)];
    let yaml = indoc! {"
        - 1
        - null
        - 3
    "};
    test_serde(&thing, yaml);
}

#[test]
fn test_unit() {
    let thing = vec![(), ()];
    let yaml = indoc! {"
        - null
        - null
    "};
    test_serde(&thing, yaml);
}

#[test]
fn test_unit_struct() {
    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    struct Foo;
    let thing = Foo;
    let yaml = indoc! {"
        null
    "};
    test_serde(&thing, yaml);
}

#[test]
fn test_unit_variant() {
    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    enum Variant {
        First,
        Second,
    }
    let thing = Variant::First;
    let yaml = indoc! {"
        First
    "};
    test_serde(&thing, yaml);
}

#[test]
fn test_newtype_struct() {
    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    struct OriginalType {
        v: u16,
    }
    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    struct NewType(OriginalType);
    let thing = NewType(OriginalType { v: 1 });
    let yaml = indoc! {"
        v: 1
    "};
    test_serde(&thing, yaml);
}

#[test]
fn test_newtype_variant() {
    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    enum Variant {
        Size(usize),
    }
    let thing = Variant::Size(127);
    let yaml = indoc! {"
        Size: 127
    "};
    test_serde(&thing, yaml);
}

#[test]
fn test_tuple_variant() {
    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    enum Variant {
        Rgb(u8, u8, u8),
    }
    let thing = Variant::Rgb(32, 64, 96);
    let yaml = indoc! {"
        Rgb:
        - 32
        - 64
        - 96
    "};
    test_serde(&thing, yaml);
}

#[test]
fn test_struct_variant() {
    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    enum Variant {
        Color { r: u8, g: u8, b: u8 },
    }
    let thing = Variant::Color {
        r: 32,
        g: 64,
        b: 96,
    };
    let yaml = indoc! {"
        Color:
          r: 32
          g: 64
          b: 96
    "};
    test_serde(&thing, yaml);
}

#[test]
fn test_value() {
    use serde_yaml::{Mapping, Number};

    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    pub struct GenericInstructions {
        #[serde(rename = "type")]
        pub typ: String,
        pub config: Value,
    }
    let thing = GenericInstructions {
        typ: "primary".to_string(),
        config: Value::Sequence(vec![
            Value::Null,
            Value::Bool(true),
            Value::Number(Number::from(65535)),
            Value::Number(Number::from(0.54321)),
            Value::String("s".into()),
            Value::Mapping(Mapping::new()),
        ]),
    };
    let yaml = indoc! {"
        type: primary
        config:
        - null
        - true
        - 65535
        - 0.54321
        - s
        - {}
    "};
    test_serde(&thing, yaml);
}

#[test]
fn test_mapping() {
    use serde_yaml::Mapping;
    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    struct Data {
        pub substructure: Mapping,
    }

    let mut thing = Data {
        substructure: Mapping::new(),
    };
    thing.substructure.insert(
        Value::String("a".to_owned()),
        Value::String("foo".to_owned()),
    );
    thing.substructure.insert(
        Value::String("b".to_owned()),
        Value::String("bar".to_owned()),
    );

    let yaml = indoc! {"
        substructure:
          a: foo
          b: bar
    "};

    test_serde(&thing, yaml);
}
<commit_msg>Better char test<commit_after>#![allow(
    clippy::decimal_literal_representation,
    clippy::derive_partial_eq_without_eq,
    clippy::unreadable_literal,
    clippy::shadow_unrelated
)]

use indoc::indoc;
use serde_derive::{Deserialize, Serialize};
use serde_yaml::Value;
use std::collections::BTreeMap;
use std::fmt::Debug;

fn test_serde<T>(thing: &T, yaml: &str)
where
    T: serde::Serialize + serde::de::DeserializeOwned + PartialEq + Debug,
{
    let serialized = serde_yaml::to_string(&thing).unwrap();
    assert_eq!(yaml, serialized);

    let value = serde_yaml::to_value(&thing).unwrap();
    let serialized = serde_yaml::to_string(&value).unwrap();
    assert_eq!(yaml, serialized);

    let deserialized: T = serde_yaml::from_str(yaml).unwrap();
    assert_eq!(*thing, deserialized);

    let value: Value = serde_yaml::from_str(yaml).unwrap();
    let deserialized: T = serde_yaml::from_value(value).unwrap();
    assert_eq!(*thing, deserialized);

    serde_yaml::from_str::<serde::de::IgnoredAny>(yaml).unwrap();
}

#[test]
fn test_default() {
    assert_eq!(Value::default(), Value::Null);
}

#[test]
fn test_int() {
    let thing = 256;
    let yaml = indoc! {"
        256
    "};
    test_serde(&thing, yaml);
}

#[test]
fn test_int_max_u64() {
    let thing = u64::MAX;
    let yaml = indoc! {"
        18446744073709551615
    "};
    test_serde(&thing, yaml);
}

#[test]
fn test_int_min_i64() {
    let thing = i64::MIN;
    let yaml = indoc! {"
        -9223372036854775808
    "};
    test_serde(&thing, yaml);
}

#[test]
fn test_int_max_i64() {
    let thing = i64::MAX;
    let yaml = indoc! {"
        9223372036854775807
    "};
    test_serde(&thing, yaml);
}

#[test]
fn test_i128_small() {
    let thing: i128 = -256;
    let yaml = indoc! {"
        -256
    "};
    test_serde(&thing, yaml);
}

#[test]
fn test_u128_small() {
    let thing: u128 = 256;
    let yaml = indoc! {"
        256
    "};
    test_serde(&thing, yaml);
}

#[test]
fn test_float() {
    let thing = 25.6;
    let yaml = indoc! {"
        25.6
    "};
    test_serde(&thing, yaml);

    let thing = 25.;
    let yaml = indoc! {"
        25.0
    "};
    test_serde(&thing, yaml);

    let thing = f64::INFINITY;
    let yaml = indoc! {"
        .inf
    "};
    test_serde(&thing, yaml);

    let thing = f64::NEG_INFINITY;
    let yaml = indoc! {"
        -.inf
    "};
    test_serde(&thing, yaml);

    let float: f64 = serde_yaml::from_str(indoc! {"
        .nan
    "})
    .unwrap();
    assert!(float.is_nan());
}

#[test]
fn test_float32() {
    let thing: f32 = 25.5;
    let yaml = indoc! {"
        25.5
    "};
    test_serde(&thing, yaml);

    let thing = f32::INFINITY;
    let yaml = indoc! {"
        .inf
    "};
    test_serde(&thing, yaml);

    let thing = f32::NEG_INFINITY;
    let yaml = indoc! {"
        -.inf
    "};
    test_serde(&thing, yaml);

    let single_float: f32 = serde_yaml::from_str(indoc! {"
        .nan
    "})
    .unwrap();
    assert!(single_float.is_nan());
}

#[test]
fn test_char() {
    let ch = '.';
    let yaml = indoc! {"
        .
    "};
    assert_eq!(yaml, serde_yaml::to_string(&ch).unwrap());

    let ch = '#';
    let yaml = indoc! {"
        '#'
    "};
    assert_eq!(yaml, serde_yaml::to_string(&ch).unwrap());

    let ch = '-';
    let yaml = indoc! {"
        '-'
    "};
    assert_eq!(yaml, serde_yaml::to_string(&ch).unwrap());
}

#[test]
fn test_vec() {
    let thing = vec![1, 2, 3];
    let yaml = indoc! {"
        - 1
        - 2
        - 3
    "};
    test_serde(&thing, yaml);
}

#[test]
fn test_map() {
    let mut thing = BTreeMap::new();
    thing.insert("x".to_owned(), 1);
    thing.insert("y".to_owned(), 2);
    let yaml = indoc! {"
        x: 1
        y: 2
    "};
    test_serde(&thing, yaml);
}

#[test]
fn test_basic_struct() {
    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    struct Basic {
        x: isize,
        y: String,
        z: bool,
    }
    let thing = Basic {
        x: -4,
        y: "hi\tquoted".to_owned(),
        z: true,
    };
    let yaml = indoc! {r#"
        x: -4
        y: "hi\tquoted"
        z: true
    "#};
    test_serde(&thing, yaml);
}

#[test]
fn test_multiline_string() {
    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    struct Struct {
        trailing_newline: String,
        no_trailing_newline: String,
    }
    let thing = Struct {
        trailing_newline: "aaa\nbbb\n".to_owned(),
        no_trailing_newline: "aaa\nbbb".to_owned(),
    };
    let yaml = indoc! {r#"
        trailing_newline: |
          aaa
          bbb
        no_trailing_newline: |-
          aaa
          bbb
    "#};
    test_serde(&thing, yaml);
}

#[test]
fn test_strings_needing_quote() {
    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    struct Struct {
        boolean: String,
        integer: String,
        void: String,
    }
    let thing = Struct {
        boolean: "true".to_owned(),
        integer: "1".to_owned(),
        void: "null".to_owned(),
    };
    let yaml = indoc! {r#"
        boolean: 'true'
        integer: '1'
        void: 'null'
    "#};
    test_serde(&thing, yaml);
}

#[test]
fn test_nested_vec() {
    let thing = vec![vec![1, 2, 3], vec![4, 5, 6]];
    let yaml = indoc! {"
        - - 1
          - 2
          - 3
        - - 4
          - 5
          - 6
    "};
    test_serde(&thing, yaml);
}

#[test]
fn test_nested_struct() {
    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    struct Outer {
        inner: Inner,
    }
    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    struct Inner {
        v: u16,
    }
    let thing = Outer {
        inner: Inner { v: 512 },
    };
    let yaml = indoc! {"
        inner:
          v: 512
    "};
    test_serde(&thing, yaml);
}

#[test]
fn test_option() {
    let thing = vec![Some(1), None, Some(3)];
    let yaml = indoc! {"
        - 1
        - null
        - 3
    "};
    test_serde(&thing, yaml);
}

#[test]
fn test_unit() {
    let thing = vec![(), ()];
    let yaml = indoc! {"
        - null
        - null
    "};
    test_serde(&thing, yaml);
}

#[test]
fn test_unit_struct() {
    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    struct Foo;
    let thing = Foo;
    let yaml = indoc! {"
        null
    "};
    test_serde(&thing, yaml);
}

#[test]
fn test_unit_variant() {
    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    enum Variant {
        First,
        Second,
    }
    let thing = Variant::First;
    let yaml = indoc! {"
        First
    "};
    test_serde(&thing, yaml);
}

#[test]
fn test_newtype_struct() {
    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    struct OriginalType {
        v: u16,
    }
    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    struct NewType(OriginalType);
    let thing = NewType(OriginalType { v: 1 });
    let yaml = indoc! {"
        v: 1
    "};
    test_serde(&thing, yaml);
}

#[test]
fn test_newtype_variant() {
    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    enum Variant {
        Size(usize),
    }
    let thing = Variant::Size(127);
    let yaml = indoc! {"
        Size: 127
    "};
    test_serde(&thing, yaml);
}

#[test]
fn test_tuple_variant() {
    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    enum Variant {
        Rgb(u8, u8, u8),
    }
    let thing = Variant::Rgb(32, 64, 96);
    let yaml = indoc! {"
        Rgb:
        - 32
        - 64
        - 96
    "};
    test_serde(&thing, yaml);
}

#[test]
fn test_struct_variant() {
    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    enum Variant {
        Color { r: u8, g: u8, b: u8 },
    }
    let thing = Variant::Color {
        r: 32,
        g: 64,
        b: 96,
    };
    let yaml = indoc! {"
        Color:
          r: 32
          g: 64
          b: 96
    "};
    test_serde(&thing, yaml);
}

#[test]
fn test_value() {
    use serde_yaml::{Mapping, Number};

    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    pub struct GenericInstructions {
        #[serde(rename = "type")]
        pub typ: String,
        pub config: Value,
    }
    let thing = GenericInstructions {
        typ: "primary".to_string(),
        config: Value::Sequence(vec![
            Value::Null,
            Value::Bool(true),
            Value::Number(Number::from(65535)),
            Value::Number(Number::from(0.54321)),
            Value::String("s".into()),
            Value::Mapping(Mapping::new()),
        ]),
    };
    let yaml = indoc! {"
        type: primary
        config:
        - null
        - true
        - 65535
        - 0.54321
        - s
        - {}
    "};
    test_serde(&thing, yaml);
}

#[test]
fn test_mapping() {
    use serde_yaml::Mapping;
    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    struct Data {
        pub substructure: Mapping,
    }

    let mut thing = Data {
        substructure: Mapping::new(),
    };
    thing.substructure.insert(
        Value::String("a".to_owned()),
        Value::String("foo".to_owned()),
    );
    thing.substructure.insert(
        Value::String("b".to_owned()),
        Value::String("bar".to_owned()),
    );

    let yaml = indoc! {"
        substructure:
          a: foo
          b: bar
    "};

    test_serde(&thing, yaml);
}
<|endoftext|>


<commit_before>use lib::*;
use {
    algorithms::{Algorithm, RateLimitState, RateLimitStateWithClock},
    instant::{AbsoluteInstant, RelativeInstant},
    DirectRateLimiter, InconsistentCapacity, NegativeMultiDecision,
};

/// The most naive implementation of a rate-limiter ever: Always
/// allows every cell through.
/// # Example
/// ```
/// use ratelimit_meter::DirectRateLimiter;
/// use ratelimit_meter::example_algorithms::Allower;
/// let mut allower = Allower::ratelimiter();
/// assert!(allower.check().is_ok());
/// ```
#[derive(Default, Copy, Clone, Debug)]
pub struct Allower {}

impl Allower {
    /// Return a rate-limiter that lies, i.e. that allows all requests
    /// through.
    pub fn ratelimiter() -> DirectRateLimiter<Allower, Always> {
        // These numbers are fake, but we make them up for convenience:
        DirectRateLimiter::per_second(nonzero!(1u32))
    }
}

impl RateLimitState<Allower, Always> for () {}

impl RateLimitStateWithClock<Allower, Always> for () {
    fn last_touched(&self, _params: &Allower) -> Always {
        Always::now()
    }
}

#[derive(Debug, PartialEq)]
pub struct Impossible();

impl fmt::Display for Impossible {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f, "can't happen")
    }
}

impl Algorithm<Always> for Allower {
    type BucketState = ();
    type NegativeDecision = Impossible;

    fn construct(
        _capacity: NonZeroU32,
        _cell_weight: NonZeroU32,
        _per_time_unit: Duration,
    ) -> Result<Self, InconsistentCapacity> {
        Ok(Allower {})
    }

    /// Allows all cells through unconditionally.
    fn test_n_and_update(
        &self,
        _state: &Self::BucketState,
        _n: u32,
        _t0: Always,
    ) -> Result<(), NegativeMultiDecision<Impossible>> {
        Ok(())
    }
}

/// A pseudo-instant that never changes.
///
/// It is used to implement the `Allower` rate-limiter type, which
/// never denies any requests.
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub struct Always();
impl RelativeInstant for Always {
    fn duration_since(&self, _other: Self) -> Duration {
        Duration::new(0, 0)
    }
}

impl AbsoluteInstant for Always {
    fn now() -> Self {
        Always()
    }
}

impl Add<Duration> for Always {
    type Output = Always;
    fn add(self, _rhs: Duration) -> Always {
        Always()
    }
}

impl Sub<Duration> for Always {
    type Output = Always;
    fn sub(self, _rhs: Duration) -> Always {
        Always()
    }
}

impl Sub<Always> for Always {
    type Output = Duration;
    fn sub(self, _rhs: Always) -> Duration {
        Duration::new(0, 0)
    }
}
<commit_msg>Don't impl Sub for Always<commit_after>use lib::*;
use {
    algorithms::{Algorithm, RateLimitState, RateLimitStateWithClock},
    instant::{AbsoluteInstant, RelativeInstant},
    DirectRateLimiter, InconsistentCapacity, NegativeMultiDecision,
};

/// The most naive implementation of a rate-limiter ever: Always
/// allows every cell through.
/// # Example
/// ```
/// use ratelimit_meter::DirectRateLimiter;
/// use ratelimit_meter::example_algorithms::Allower;
/// let mut allower = Allower::ratelimiter();
/// assert!(allower.check().is_ok());
/// ```
#[derive(Default, Copy, Clone, Debug)]
pub struct Allower {}

impl Allower {
    /// Return a rate-limiter that lies, i.e. that allows all requests
    /// through.
    pub fn ratelimiter() -> DirectRateLimiter<Allower, Always> {
        // These numbers are fake, but we make them up for convenience:
        DirectRateLimiter::per_second(nonzero!(1u32))
    }
}

impl RateLimitState<Allower, Always> for () {}

impl RateLimitStateWithClock<Allower, Always> for () {
    fn last_touched(&self, _params: &Allower) -> Always {
        Always::now()
    }
}

#[derive(Debug, PartialEq)]
pub struct Impossible();

impl fmt::Display for Impossible {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f, "can't happen")
    }
}

impl Algorithm<Always> for Allower {
    type BucketState = ();
    type NegativeDecision = Impossible;

    fn construct(
        _capacity: NonZeroU32,
        _cell_weight: NonZeroU32,
        _per_time_unit: Duration,
    ) -> Result<Self, InconsistentCapacity> {
        Ok(Allower {})
    }

    /// Allows all cells through unconditionally.
    fn test_n_and_update(
        &self,
        _state: &Self::BucketState,
        _n: u32,
        _t0: Always,
    ) -> Result<(), NegativeMultiDecision<Impossible>> {
        Ok(())
    }
}

/// A pseudo-instant that never changes.
///
/// It is used to implement the `Allower` rate-limiter type, which
/// never denies any requests.
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub struct Always();
impl RelativeInstant for Always {
    fn duration_since(&self, _other: Self) -> Duration {
        Duration::new(0, 0)
    }
}

impl AbsoluteInstant for Always {
    fn now() -> Self {
        Always()
    }
}

impl Add<Duration> for Always {
    type Output = Always;
    fn add(self, _rhs: Duration) -> Always {
        Always()
    }
}

impl Sub<Duration> for Always {
    type Output = Always;
    fn sub(self, _rhs: Duration) -> Always {
        Always()
    }
}
<|endoftext|>