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

use std::fmt;

/// Contains the API configuration as prescribed by [ECMA 402][ecma].
///
///    [ecma]: https://www.ecma-international.org/publications/standards/Ecma-402.htm
///
/// The meaning of the options is the same as in the similarly named
/// options in the JS version.
///
/// See [Options] for the contents of the options.  See the [NumberFormat::try_new]
/// for the use of the options.
pub mod options {

    /// Controls whether short or long form display is used.  Short is slightly
    /// more economical with spacing.  Only used when notation is Compact.
    #[derive(Eq, PartialEq, Debug, Clone)]
    pub enum CompactDisplay {
        /// Default.
        Short,
        /// Long display layout.
        Long,
    }

    /// The ISO currency code for a currency, if the currency formatting is being used.
    /// For example "EUR" or "USD".
    #[derive(Eq, PartialEq, Debug, Clone)]
    pub struct Currency(pub String);

    impl From<&str> for Currency {
        fn from(s: &str) -> Self {
            Self(s.to_string())
        }
    }

    /// Controls the display of currency information.
    #[derive(Eq, PartialEq, Debug, Clone)]
    pub enum CurrencyDisplay {
        /// Use a localized currency symbol such as €, this is the default value.
        Symbol,
        /// Narrow format symbol ("$100" rather than "US$100").
        NarrowSymbol,
        /// Use the ISO currency code.
        Code,
        /// Use a localized currency name, e.g. "dollar".
        Name,
    }

    /// Controls the display of currency sign.
    #[derive(Eq, PartialEq, Debug, Clone)]
    pub enum CurrencySign {
        /// Uses accounting notation such as `($100)` to mean "minus one hundred dollars".
        Accounting,
        /// Uses standard notation such as `$-100`.
        Standard,
    }

    /// Controls the number formatting.
    #[derive(Eq, PartialEq, Debug, Clone)]
    pub enum Notation {
        /// Example: 10,000.00.  This is the default.
        Standard,
        /// Example: 1e+4
        Scientific,
        /// Example: 10k
        Engineering,
        /// Example: 10000
        Compact,
    }

    /// Controls the number formatting.
    ///
    /// Possible values include: "arab", "arabext", " bali", "beng", "deva", "fullwide", "gujr",
    /// "guru", "hanidec", "khmr", " knda", "laoo", "latn", "limb", "mlym", " mong", "mymr",
    /// "orya", "tamldec", " telu", "thai", "tibt".
    #[derive(Eq, PartialEq, Debug, Clone)]
    pub struct NumberingSystem(pub String);

    impl From<&str> for NumberingSystem {
        fn from(s: &str) -> Self {
            Self(s.to_string())
        }
    }

    impl Default for NumberingSystem {
        fn default() -> Self {
            NumberingSystem("latn".to_string())
        }
    }

    /// When to display the sign of the number.
    #[derive(Eq, PartialEq, Debug, Clone)]
    pub enum SignDisplay {
        /// Display for negative numbers only.
        Auto,
        /// Never display the sign.
        Never,
        /// Always display the sign (even plus).
        Always,
        /// Display for positive and negative numbers, but not zero.
        ExceptZero,
    }

    /// When to display the sign of the number.
    #[derive(Eq, PartialEq, Debug, Clone)]
    pub enum Style {
        /// For plain number formatting.
        Decimal,
        /// For currency formatting ("10 EUR")
        Currency,
        /// For percentage formatting ("10%")
        Percent,
        /// For unit formatting ("10 meters")
        Unit,
    }

    /// The unit formatting style, when [Style::Unit] is used.
    ///
    /// Possible values are core unit identifiers, defined in UTS #35, Part 2, Section 6. A subset
    /// of units from the full list was selected for use in ECMAScript. Pairs of simple units can
    /// be concatenated with "-per-" to make a compound unit. There is no default value; if the
    /// style is "unit", the unit property must be provided.
    #[derive(Eq, PartialEq, Debug, Clone)]
    pub enum UnitDisplay {
        /// "16 litres"
        Long,
        /// "16 l"
        Short,
        /// "16l"
        Narrow,
    }

    /// The unit to use when [Style::Unit] is selected as [Style].
    ///
    /// Possible values are core unit identifiers, defined in UTS #35, Part 2, Section 6. A subset
    /// of units from the full list was selected for use in ECMAScript. Pairs of simple units can
    /// be concatenated with "-per-" to make a compound unit. There is no default value; if the
    /// style is "unit", the unit property must be provided.
    #[derive(Debug, Clone)]
    pub struct Unit(pub String);
}

/// The options set by the user at construction time.  See discussion at the top level
/// about the name choice.  Provides as a "bag of options" since we don't expect any
/// implementations to be attached to this struct.
///
/// The default values of all the options are prescribed in by the [TC39 report][tc39lf].
///
///   [tc39lf]: https://tc39.es/proposal-intl-number-format/#sec-Intl.NumberFormat
#[derive(Debug, Clone)]
pub struct Options {
    pub compact_display: Option<options::CompactDisplay>,
    pub currency: Option<options::Currency>,
    pub currency_display: options::CurrencyDisplay,
    pub currency_sign: options::CurrencySign,
    pub notation: options::Notation,
    pub numbering_system: Option<options::NumberingSystem>,
    pub sign_display: options::SignDisplay,
    pub style: options::Style,
    pub unit: Option<options::Unit>,

    pub minimum_integer_digits: Option<u8>,
    pub minimum_fraction_digits: Option<u8>,
    pub maximum_fraction_digits: Option<u8>,
    pub minimum_significant_digits: Option<u8>,
    pub maximum_significant_digits: Option<u8>,
}

impl Default for Options {
    /// Gets the default values of [Options] if omitted at setup.  The
    /// default values are prescribed in by the [TC39 report][tc39lf].
    ///
    ///   [tc39lf]: https://tc39.es/proposal-intl-list-format/#sec-Intl.ListFormat
    fn default() -> Self {
        Options {
            compact_display: None,
            currency: None,
            currency_display: options::CurrencyDisplay::Symbol,
            currency_sign: options::CurrencySign::Standard,
            notation: options::Notation::Standard,
            sign_display: options::SignDisplay::Auto,
            style: options::Style::Decimal,
            unit: None,
            numbering_system: None,
            minimum_integer_digits: None,
            minimum_fraction_digits: None,
            maximum_fraction_digits: None,
            minimum_significant_digits: None,
            maximum_significant_digits: None,
        }
    }
}

/// Formats number based on the rules configured on initialization.
pub trait NumberFormat {
    /// The type of error reported, if any.
    type Error: std::error::Error;

    /// Creates a new [NumberFormat].
    ///
    /// Creation may fail, for example, if the locale-specific data is not loaded, or if
    /// the supplied options are inconsistent.
    fn try_new<L>(l: L, opts: Options) -> Result<Self, Self::Error>
    where
        L: crate::Locale,
        Self: Sized;

    /// Formats `number` into the supplied `writer`.
    ///
    /// The function implements [`Intl.NumberFormat`][nfmt] from [ECMA 402][ecma].
    ///
    ///    [nfmt]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat
    ///    [ecma]: https://www.ecma-international.org/publications/standards/Ecma-402.htm
    fn format<W>(&self, number: f64, writer: &mut W) -> fmt::Result
    where
        W: fmt::Write;
}
<commit_msg>Handle code review comments<commit_after>// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::fmt;

/// Contains the API configuration as prescribed by [ECMA 402][ecma].
///
///    [ecma]: https://www.ecma-international.org/publications/standards/Ecma-402.htm
///
/// The meaning of the options is the same as in the similarly named
/// options in the JS version.
///
/// See [Options] for the contents of the options.  See the [NumberFormat::try_new]
/// for the use of the options.
pub mod options {

    /// Controls whether short or long form display is used.  Short is slightly
    /// more economical with spacing.  Only used when notation is Compact.
    #[derive(Eq, PartialEq, Debug, Clone)]
    pub enum CompactDisplay {
        /// Default.
        Short,
        /// Long display layout.
        Long,
    }

    /// The ISO currency code for a currency, if the currency formatting is being used.
    /// For example "EUR" or "USD".
    ///
    /// The value entered as currency is not validated.  This responsibility is
    /// delegated to the implementor.
    #[derive(Eq, PartialEq, Debug, Clone)]
    pub struct Currency(pub String);

    impl From<&str> for Currency {
        fn from(s: &str) -> Self {
            Self(s.to_string())
        }
    }

    /// Controls the display of currency information.
    #[derive(Eq, PartialEq, Debug, Clone)]
    pub enum CurrencyDisplay {
        /// Use a localized currency symbol such as €, this is the default value.
        Symbol,
        /// Narrow format symbol ("$100" rather than "US$100").
        NarrowSymbol,
        /// Use the ISO currency code.
        Code,
        /// Use a localized currency name, e.g. "dollar".
        Name,
    }

    /// Controls the display of currency sign.
    #[derive(Eq, PartialEq, Debug, Clone)]
    pub enum CurrencySign {
        /// Uses accounting notation such as `($100)` to mean "minus one hundred dollars".
        Accounting,
        /// Uses standard notation such as `$-100`.
        Standard,
    }

    /// Controls the number formatting.
    #[derive(Eq, PartialEq, Debug, Clone)]
    pub enum Notation {
        /// Example: 10,000.00.  This is the default.
        Standard,
        /// Example: 1e+4
        Scientific,
        /// Example: 10k
        Engineering,
        /// Example: 10000
        Compact,
    }

    /// Controls the number formatting.
    ///
    /// Possible values include: "arab", "arabext", " bali", "beng", "deva", "fullwide", "gujr",
    /// "guru", "hanidec", "khmr", " knda", "laoo", "latn", "limb", "mlym", " mong", "mymr",
    /// "orya", "tamldec", " telu", "thai", "tibt".
    ///
    /// The value entered as currency is not validated.  This responsibility is
    /// delegated to the implementor.
    #[derive(Eq, PartialEq, Debug, Clone)]
    pub struct NumberingSystem(pub String);

    impl From<&str> for NumberingSystem {
        fn from(s: &str) -> Self {
            Self(s.to_string())
        }
    }

    impl Default for NumberingSystem {
        fn default() -> Self {
            NumberingSystem("latn".to_string())
        }
    }

    /// When to display the sign of the number.
    #[derive(Eq, PartialEq, Debug, Clone)]
    pub enum SignDisplay {
        /// Display for negative numbers only.
        Auto,
        /// Never display the sign.
        Never,
        /// Always display the sign (even plus).
        Always,
        /// Display for positive and negative numbers, but not zero.
        ExceptZero,
    }

    /// When to display the sign of the number.
    #[derive(Eq, PartialEq, Debug, Clone)]
    pub enum Style {
        /// For plain number formatting.
        Decimal,
        /// For currency formatting ("10 EUR")
        Currency,
        /// For percentage formatting ("10%")
        Percent,
        /// For unit formatting ("10 meters")
        Unit,
    }

    /// The unit formatting style, when [Style::Unit] is used.
    ///
    /// Possible values are core unit identifiers, defined in UTS #35, Part 2, Section 6. A subset
    /// of units from the full list was selected for use in ECMAScript. Pairs of simple units can
    /// be concatenated with "-per-" to make a compound unit. There is no default value; if the
    /// style is "unit", the unit property must be provided.
    #[derive(Eq, PartialEq, Debug, Clone)]
    pub enum UnitDisplay {
        /// "16 litres"
        Long,
        /// "16 l"
        Short,
        /// "16l"
        Narrow,
    }

    /// The unit to use when [Style::Unit] is selected as [Style].
    ///
    /// Possible values are core unit identifiers, defined in UTS #35, Part 2, Section 6. A subset
    /// of units from the full list was selected for use in ECMAScript. Pairs of simple units can
    /// be concatenated with "-per-" to make a compound unit. There is no default value; if the
    /// style is "unit", the unit property must be provided.
    #[derive(Debug, Clone)]
    pub struct Unit(pub String);
}

/// The options set by the user at construction time.  See discussion at the top level
/// about the name choice.  Provides as a "bag of options" since we don't expect any
/// implementations to be attached to this struct.
///
/// The default values of all the options are prescribed in by the [TC39 report][tc39lf].
///
///   [tc39lf]: https://tc39.es/proposal-intl-number-format/#sec-Intl.NumberFormat
#[derive(Debug, Clone)]
pub struct Options {
    pub compact_display: Option<options::CompactDisplay>,
    pub currency: Option<options::Currency>,
    pub currency_display: options::CurrencyDisplay,
    pub currency_sign: options::CurrencySign,
    pub notation: options::Notation,
    pub numbering_system: Option<options::NumberingSystem>,
    pub sign_display: options::SignDisplay,
    pub style: options::Style,
    pub unit: Option<options::Unit>,

    pub minimum_integer_digits: Option<u8>,
    pub minimum_fraction_digits: Option<u8>,
    pub maximum_fraction_digits: Option<u8>,
    pub minimum_significant_digits: Option<u8>,
    pub maximum_significant_digits: Option<u8>,
}

impl Default for Options {
    /// Gets the default values of [Options] if omitted at setup.  The
    /// default values are prescribed in by the [TC39 report][tc39lf].
    ///
    ///   [tc39lf]: https://tc39.es/proposal-intl-list-format/#sec-Intl.ListFormat
    fn default() -> Self {
        Options {
            compact_display: None,
            currency: None,
            currency_display: options::CurrencyDisplay::Symbol,
            currency_sign: options::CurrencySign::Standard,
            notation: options::Notation::Standard,
            sign_display: options::SignDisplay::Auto,
            style: options::Style::Decimal,
            unit: None,
            numbering_system: None,
            minimum_integer_digits: None,
            minimum_fraction_digits: None,
            maximum_fraction_digits: None,
            minimum_significant_digits: None,
            maximum_significant_digits: None,
        }
    }
}

/// Formats number based on the rules configured on initialization.
pub trait NumberFormat {
    /// The type of error reported, if any.
    type Error: std::error::Error;

    /// Creates a new [NumberFormat].
    ///
    /// Creation may fail, for example, if the locale-specific data is not loaded, or if
    /// the supplied options are inconsistent.
    fn try_new<L>(l: L, opts: Options) -> Result<Self, Self::Error>
    where
        L: crate::Locale,
        Self: Sized;

    /// Formats `number` into the supplied `writer`.
    ///
    /// The function implements [`Intl.NumberFormat`][nfmt] from [ECMA 402][ecma].
    ///
    ///    [nfmt]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat
    ///    [ecma]: https://www.ecma-international.org/publications/standards/Ecma-402.htm
    fn format<W>(&self, number: f64, writer: &mut W) -> fmt::Result
    where
        W: fmt::Write;
}
<|endoftext|>


<commit_before>//! A "souped up" echo server example.
//!
//! Very similar to the example at https://tokio.rs

#![feature(proc_macro, conservative_impl_trait, generators)]

extern crate futures_await as futures;
extern crate tokio_core;
extern crate tokio_io;

use std::io::{self, BufReader};

use futures::prelude::*;
use tokio_core::net::{TcpListener, TcpStream};
use tokio_core::reactor::Core;
use tokio_io::{AsyncRead};

fn main() {
    // Create the event loop that will drive this server
    let mut core = Core::new().unwrap();
    let handle = core.handle();

    // Bind the server's socket
    let addr = "127.0.0.1:12345".parse().unwrap();
    let tcp = TcpListener::bind(&addr, &handle).expect("failed to bind listener");

    let server = async_block! {
        #[async]
        for (client, _) in tcp.incoming() {
            handle.spawn(handle_client(client).then(|result| {
                match result {
                    Ok(n) => println!("wrote {} bytes", n),
                    Err(e) => println!("IO error {:?}", e),
                }
                Ok(())
            }));
        }

        Ok::<(), io::Error>(())
    };
    core.run(server).unwrap();
}

#[async]
fn handle_client(socket: TcpStream) -> io::Result<u64> {
    let (reader, mut writer) = socket.split();
    let input = BufReader::new(reader);

    let mut total = 0;

    #[async]
    for line in tokio_io::io::lines(input) {
        println!("got client line: {}", line);
        total += line.len() as u64;
        writer = await!(tokio_io::io::write_all(writer, line))?.0;
    }

    Ok(total)
}
<commit_msg>Print connection address on echo server<commit_after>//! A "souped up" echo server example.
//!
//! Very similar to the example at https://tokio.rs

#![feature(proc_macro, conservative_impl_trait, generators)]

extern crate futures_await as futures;
extern crate tokio_core;
extern crate tokio_io;

use std::io::{self, BufReader};

use futures::prelude::*;
use tokio_core::net::{TcpListener, TcpStream};
use tokio_core::reactor::Core;
use tokio_io::{AsyncRead};

fn main() {
    // Create the event loop that will drive this server
    let mut core = Core::new().unwrap();
    let handle = core.handle();

    // Bind the server's socket
    let addr = "127.0.0.1:12345".parse().unwrap();
    let tcp = TcpListener::bind(&addr, &handle).expect("failed to bind listener");
    println!("listening for connections on {}",
             tcp.local_addr().unwrap());

    let server = async_block! {
        #[async]
        for (client, _) in tcp.incoming() {
            handle.spawn(handle_client(client).then(|result| {
                match result {
                    Ok(n) => println!("wrote {} bytes", n),
                    Err(e) => println!("IO error {:?}", e),
                }
                Ok(())
            }));
        }

        Ok::<(), io::Error>(())
    };
    core.run(server).unwrap();
}

#[async]
fn handle_client(socket: TcpStream) -> io::Result<u64> {
    let (reader, mut writer) = socket.split();
    let input = BufReader::new(reader);

    let mut total = 0;

    #[async]
    for line in tokio_io::io::lines(input) {
        println!("got client line: {}", line);
        total += line.len() as u64;
        writer = await!(tokio_io::io::write_all(writer, line))?.0;
    }

    Ok(total)
}
<|endoftext|>


<commit_before>use socket::Socket;

#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Gain {
    LV,
    HV,
}

impl ::std::fmt::Display for Gain {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        let display = match self {
            &Gain::LV => "LV",
            &Gain::HV => "HV",
        };

        write!(f, "{}", display)
    }
}

#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Source {
    IN1,
    IN2,
}

impl ::std::fmt::Display for Source {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        let display = match self {
            &Source::IN1 => "SOUR1",
            &Source::IN2 => "SOUR2",
        };

        write!(f, "{}", display)
    }
}

#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Decimation {
    DEC_1,
    DEC_8,
    DEC_64,
    DEC_1024,
    DEC_8192,
    DEC_65536,
}

impl Decimation {
    pub fn get_buffer_duration(&self) -> ::std::time::Duration {
        let (s, ns) = match self {
            &Decimation::DEC_1 => (0, 131_072),
            &Decimation::DEC_8 => (0, 1_049_000),
            &Decimation::DEC_64 => (0, 8_389_000),
            &Decimation::DEC_1024 => (0, 134_218_000),
            &Decimation::DEC_8192 => (1, 740_000_000),
            &Decimation::DEC_65536 => (8, 590_000_000),
        };

        ::std::time::Duration::new(s, ns)
    }
}

impl ::std::fmt::Display for Decimation {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        let display = match self {
            &Decimation::DEC_1 => "1",
            &Decimation::DEC_8 => "8",
            &Decimation::DEC_64 => "64",
            &Decimation::DEC_1024 => "1024",
            &Decimation::DEC_8192 => "8192",
            &Decimation::DEC_65536 => "65536",
        };

        write!(f, "{}", display)
    }
}

impl ::std::convert::From<String> for Decimation {
    fn from(s: String) -> Self {
        match s.as_str() {
            "1" => Decimation::DEC_1,
            "8" => Decimation::DEC_8,
            "64" => Decimation::DEC_64,
            "1024" => Decimation::DEC_1024,
            "8192" => Decimation::DEC_8192,
            "65536" => Decimation::DEC_65536,
            _ => Decimation::DEC_1,
        }
    }
}

#[derive(Clone)]
pub struct Acquire {
    socket: ::std::cell::RefCell<Socket>,
    started: bool,
}

impl Acquire {
    pub fn new(socket: Socket) -> Self {
        Acquire {
            socket: ::std::cell::RefCell::new(socket),
            started: false,
        }
    }

    /**
     * Starts acquisition.
     */
    pub fn start(&mut self) {
        self.send("ACQ:START");
        self.started = true;
    }

    /**
     * Stops acquisition.
     */
    pub fn stop(&mut self) {
        self.send("ACQ:STOP");
        self.started = false;
    }

    pub fn is_started(&self) -> bool {
        self.started
    }

    /**
     * Stops acquisition and sets all parameters to default values.
     */
    pub fn reset(&self) {
        self.send("ACQ:RST");
    }

    /**
     * Set decimation factor.
     */
    pub fn set_decimation(&self, decimation: Decimation) {
        self.send(format!("ACQ:DEC {}", decimation));
    }

    /**
     * Get decimation factor.
     */
    pub fn get_decimation(&self) -> Decimation {
        self.send("ACQ:DEC?");

        self.receive()
            .into()
    }

    /**
     * Enable averaging.
     */
    pub fn enable_average(&self) {
        self.send("ACQ:AVG ON");
    }

    /**
     * Disable averaging.
     */
    pub fn disable_average(&self) {
        self.send("ACQ:AVG OFF");
    }

    /**
     * Get averaging status.
     */
    pub fn is_average_enabled(&self) -> bool {
        self.send("ACQ:AVG?");

        let message = self.receive();

        match message.as_str() {
            "ON" => true,
            _ => false,
        }
    }

    /**
     * Set gain settings to HIGH or LOW.
     *
     * This gain is referring to jumper settings on Red Pitaya fast analog inputs.
     */
    pub fn set_gain(&self, source: Source, gain: Gain) {
        self.send(format!("ACQ:{}:GAIN {}", source, gain));
    }

    fn send<D>(&self, message: D)
        where D: ::std::fmt::Display
    {
        let mut socket = self.socket.borrow_mut();

        socket.send(message);
    }

    fn receive(&self) -> String {
        let mut socket = self.socket.borrow_mut();

        socket.receive()
    }
}

#[cfg(test)]
mod test {
    #[test]
    fn test_decimation_get_buffer_duration() {
        let duration = ::std::time::Duration::new(8, 590_000_000);

        assert_eq!(duration, ::acquire::Decimation::DEC_65536.get_buffer_duration());
    }

    macro_rules! acquire_assert {
        ($f:ident, $e:expr) => {
            let (rx, acquire) = create_acquire();

            acquire.$f();
            assert_eq!($e, rx.recv().unwrap());
        }
    }

    #[test]
    fn test_start() {
        let (rx, mut acquire) = create_acquire();

        acquire.start();
        assert_eq!("ACQ:START\r\n", rx.recv().unwrap());
    }

    #[test]
    fn test_stop() {
        let (rx, mut acquire) = create_acquire();

        acquire.stop();
        assert_eq!("ACQ:STOP\r\n", rx.recv().unwrap());
    }

    #[test]
    fn test_is_started() {
        let (_, mut acquire) = create_acquire();

        assert_eq!(acquire.is_started(), false);
        acquire.start();
        assert_eq!(acquire.is_started(), true);
        acquire.stop();
        assert_eq!(acquire.is_started(), false);
    }

    #[test]
    fn test_reset() {
        acquire_assert!(reset, "ACQ:RST\r\n");
    }

    #[test]
    fn test_set_decimation() {
        let (rx, acquire) = create_acquire();

        acquire.set_decimation(::acquire::Decimation::DEC_8);
        assert_eq!("ACQ:DEC 8\r\n", rx.recv().unwrap());
    }

    #[test]
    fn test_get_decimation() {
        let (_, acquire) = create_acquire();

        assert_eq!(acquire.get_decimation(), ::acquire::Decimation::DEC_1);
    }

    #[test]
    fn test_enable_average() {
        acquire_assert!(enable_average, "ACQ:AVG ON\r\n");
    }

    #[test]
    fn test_disable_average() {
        acquire_assert!(disable_average, "ACQ:AVG OFF\r\n");
    }

    #[test]
    fn test_is_average_enabled() {
        let (_, acquire) = create_acquire();

        assert_eq!(acquire.is_average_enabled(), true);
    }

    #[test]
    fn test_set_gain() {
        let (rx, trigger) = create_acquire();

        trigger.set_gain(::acquire::Source::IN1, ::acquire::Gain::LV);
        assert_eq!("ACQ:SOUR1:GAIN LV\r\n", rx.recv().unwrap());
    }

    fn create_acquire() -> (::std::sync::mpsc::Receiver<String>, ::acquire::Acquire) {
        let (addr, rx) = ::test::launch_server();
        let socket = ::socket::Socket::new(addr);

        (rx, ::acquire::Acquire::new(socket))
    }
}
<commit_msg>[acquire] Add acquire::Decimation.get_sampling_rate()<commit_after>use socket::Socket;

#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Gain {
    LV,
    HV,
}

impl ::std::fmt::Display for Gain {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        let display = match self {
            &Gain::LV => "LV",
            &Gain::HV => "HV",
        };

        write!(f, "{}", display)
    }
}

#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Source {
    IN1,
    IN2,
}

impl ::std::fmt::Display for Source {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        let display = match self {
            &Source::IN1 => "SOUR1",
            &Source::IN2 => "SOUR2",
        };

        write!(f, "{}", display)
    }
}

#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Decimation {
    DEC_1,
    DEC_8,
    DEC_64,
    DEC_1024,
    DEC_8192,
    DEC_65536,
}

impl Decimation {
    pub fn get_buffer_duration(&self) -> ::std::time::Duration {
        let (s, ns) = match self {
            &Decimation::DEC_1 => (0, 131_072),
            &Decimation::DEC_8 => (0, 1_049_000),
            &Decimation::DEC_64 => (0, 8_389_000),
            &Decimation::DEC_1024 => (0, 134_218_000),
            &Decimation::DEC_8192 => (1, 740_000_000),
            &Decimation::DEC_65536 => (8, 590_000_000),
        };

        ::std::time::Duration::new(s, ns)
    }

    pub fn get_sampling_rate(&self) -> &'static str {
        match self {
            &Decimation::DEC_1 => "125 MS/s",
            &Decimation::DEC_8 => "15.6 MS/s",
            &Decimation::DEC_64 => "1.9 MS/s",
            &Decimation::DEC_1024 => "122.0 MS/s",
            &Decimation::DEC_8192 => "15.2 kS/s",
            &Decimation::DEC_65536 => "7.6 kS/s",
        }
    }
}

impl ::std::fmt::Display for Decimation {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        let display = match self {
            &Decimation::DEC_1 => "1",
            &Decimation::DEC_8 => "8",
            &Decimation::DEC_64 => "64",
            &Decimation::DEC_1024 => "1024",
            &Decimation::DEC_8192 => "8192",
            &Decimation::DEC_65536 => "65536",
        };

        write!(f, "{}", display)
    }
}

impl ::std::convert::From<String> for Decimation {
    fn from(s: String) -> Self {
        match s.as_str() {
            "1" => Decimation::DEC_1,
            "8" => Decimation::DEC_8,
            "64" => Decimation::DEC_64,
            "1024" => Decimation::DEC_1024,
            "8192" => Decimation::DEC_8192,
            "65536" => Decimation::DEC_65536,
            _ => Decimation::DEC_1,
        }
    }
}

#[derive(Clone)]
pub struct Acquire {
    socket: ::std::cell::RefCell<Socket>,
    started: bool,
}

impl Acquire {
    pub fn new(socket: Socket) -> Self {
        Acquire {
            socket: ::std::cell::RefCell::new(socket),
            started: false,
        }
    }

    /**
     * Starts acquisition.
     */
    pub fn start(&mut self) {
        self.send("ACQ:START");
        self.started = true;
    }

    /**
     * Stops acquisition.
     */
    pub fn stop(&mut self) {
        self.send("ACQ:STOP");
        self.started = false;
    }

    pub fn is_started(&self) -> bool {
        self.started
    }

    /**
     * Stops acquisition and sets all parameters to default values.
     */
    pub fn reset(&self) {
        self.send("ACQ:RST");
    }

    /**
     * Set decimation factor.
     */
    pub fn set_decimation(&self, decimation: Decimation) {
        self.send(format!("ACQ:DEC {}", decimation));
    }

    /**
     * Get decimation factor.
     */
    pub fn get_decimation(&self) -> Decimation {
        self.send("ACQ:DEC?");

        self.receive()
            .into()
    }

    /**
     * Enable averaging.
     */
    pub fn enable_average(&self) {
        self.send("ACQ:AVG ON");
    }

    /**
     * Disable averaging.
     */
    pub fn disable_average(&self) {
        self.send("ACQ:AVG OFF");
    }

    /**
     * Get averaging status.
     */
    pub fn is_average_enabled(&self) -> bool {
        self.send("ACQ:AVG?");

        let message = self.receive();

        match message.as_str() {
            "ON" => true,
            _ => false,
        }
    }

    /**
     * Set gain settings to HIGH or LOW.
     *
     * This gain is referring to jumper settings on Red Pitaya fast analog inputs.
     */
    pub fn set_gain(&self, source: Source, gain: Gain) {
        self.send(format!("ACQ:{}:GAIN {}", source, gain));
    }

    fn send<D>(&self, message: D)
        where D: ::std::fmt::Display
    {
        let mut socket = self.socket.borrow_mut();

        socket.send(message);
    }

    fn receive(&self) -> String {
        let mut socket = self.socket.borrow_mut();

        socket.receive()
    }
}

#[cfg(test)]
mod test {
    #[test]
    fn test_decimation_get_buffer_duration() {
        let duration = ::std::time::Duration::new(8, 590_000_000);

        assert_eq!(duration, ::acquire::Decimation::DEC_65536.get_buffer_duration());
    }

    macro_rules! acquire_assert {
        ($f:ident, $e:expr) => {
            let (rx, acquire) = create_acquire();

            acquire.$f();
            assert_eq!($e, rx.recv().unwrap());
        }
    }

    #[test]
    fn test_start() {
        let (rx, mut acquire) = create_acquire();

        acquire.start();
        assert_eq!("ACQ:START\r\n", rx.recv().unwrap());
    }

    #[test]
    fn test_stop() {
        let (rx, mut acquire) = create_acquire();

        acquire.stop();
        assert_eq!("ACQ:STOP\r\n", rx.recv().unwrap());
    }

    #[test]
    fn test_is_started() {
        let (_, mut acquire) = create_acquire();

        assert_eq!(acquire.is_started(), false);
        acquire.start();
        assert_eq!(acquire.is_started(), true);
        acquire.stop();
        assert_eq!(acquire.is_started(), false);
    }

    #[test]
    fn test_reset() {
        acquire_assert!(reset, "ACQ:RST\r\n");
    }

    #[test]
    fn test_set_decimation() {
        let (rx, acquire) = create_acquire();

        acquire.set_decimation(::acquire::Decimation::DEC_8);
        assert_eq!("ACQ:DEC 8\r\n", rx.recv().unwrap());
    }

    #[test]
    fn test_get_decimation() {
        let (_, acquire) = create_acquire();

        assert_eq!(acquire.get_decimation(), ::acquire::Decimation::DEC_1);
    }

    #[test]
    fn test_enable_average() {
        acquire_assert!(enable_average, "ACQ:AVG ON\r\n");
    }

    #[test]
    fn test_disable_average() {
        acquire_assert!(disable_average, "ACQ:AVG OFF\r\n");
    }

    #[test]
    fn test_is_average_enabled() {
        let (_, acquire) = create_acquire();

        assert_eq!(acquire.is_average_enabled(), true);
    }

    #[test]
    fn test_set_gain() {
        let (rx, trigger) = create_acquire();

        trigger.set_gain(::acquire::Source::IN1, ::acquire::Gain::LV);
        assert_eq!("ACQ:SOUR1:GAIN LV\r\n", rx.recv().unwrap());
    }

    fn create_acquire() -> (::std::sync::mpsc::Receiver<String>, ::acquire::Acquire) {
        let (addr, rx) = ::test::launch_server();
        let socket = ::socket::Socket::new(addr);

        (rx, ::acquire::Acquire::new(socket))
    }
}
<|endoftext|>


<commit_before>use gc_error::GcError;
use types::binding::Binding;
use types::js_var::{JsPtrEnum, JsVar};

pub trait Backend {
    fn alloc(&mut self, var: JsVar, ptr: Option<JsPtrEnum>) -> Result<Binding, GcError>;
    fn load(&self, bnd: &Binding) -> Result<(JsVar, Option<JsPtrEnum>), GcError>;
    fn store(&mut self, var: JsVar, ptr: Option<JsPtrEnum>) -> Result<(), GcError>;
}
<commit_msg>Change &self -> &mut self in load signature for working with caches<commit_after>use gc_error::GcError;
use types::binding::Binding;
use types::js_var::{JsPtrEnum, JsVar};

pub trait Backend {
    fn alloc(&mut self, var: JsVar, ptr: Option<JsPtrEnum>) -> Result<Binding, GcError>;
    fn load(&mut self, bnd: &Binding) -> Result<(JsVar, Option<JsPtrEnum>), GcError>;
    fn store(&mut self, var: JsVar, ptr: Option<JsPtrEnum>) -> Result<(), GcError>;
}
<|endoftext|>


<commit_before>/// mush graph backend and abstraction to swap out with custom backend

use uuid::Uuid;
use std::collections::{HashMap,HashSet};

// graph functions
/*pub trait GraphBackend<I:PartialEq> {
    fn add(&mut self) -> I;
    //fn disable(N) -> bool;

    /// forcefully removes element from graph, all edge nodes should be updatedb
    fn remove(&mut self, node: &I);// -> Vec<E>;

    fn direct(&mut self, from: &I, to: &I);
    fn undirect(&mut self, from: &I, to: &I);
}*/

//pub trait<I> GraphSearch<I> {
  //  fn connections(&self, from: I, to: I) -> Vec<I>;
//}

#[derive(Debug)]
pub struct GraphNode {
    uuid: Uuid,
    edges: HashMap<Uuid,Option<f64>>, //to,weight
}

/// unidirectional edge, use two edges for bidirectional/undirected graph
/*pub struct GraphEdge {
    to: Uuid,
    maybe_weight: Option<f64>,
}*/
impl GraphNode {
    fn new (uuid: Uuid) -> GraphNode {
        GraphNode { uuid: uuid,
                    edges: HashMap::new() }
    }
    /// direct the node towards another node
    // todo: rename me! sounds too similar to unidirectional
    fn direct (&mut self, to:&Uuid, weight: Option<f64>) -> bool {
        self.edges.insert(*to,weight).is_some()
    }
    fn undirect (&mut self, to:&Uuid, weight: Option<f64>) -> bool {
        self.edges.remove(to).is_some()
    }
}

//----

pub struct Graph {
    nodes: HashMap<Uuid,GraphNode>,
}
impl Graph {
    fn new () -> Graph {
        Graph { nodes: HashMap::new() }
    }

    fn get_mut(&mut self, uuid: &Uuid) -> Option<&mut GraphNode> {
        self.nodes.get_mut(uuid)
    }
    fn get(&mut self, uuid: &Uuid) -> Option<&GraphNode> {
        self.nodes.get(uuid)
    }

    fn add (&mut self) -> Uuid { //todo: maybe_edges fn arg
        let uuid = Uuid::new_v4();
        let n = GraphNode::new(uuid);
        self.nodes.insert(uuid,n);
        uuid
    }
    fn remove(&mut self, node: &Uuid) {
        self.nodes.remove(node);
    }
    fn direct(&mut self, from: &Uuid, to: &Uuid) -> bool {
        if let Some(f) = self.nodes.get_mut(from) {
            f.direct(to,None)
        }
        else { false }
    }
    fn undirect(&mut self, from: &Uuid, to: &Uuid) -> bool {
        if let Some(f) = self.nodes.get_mut(from) {
            f.undirect(to,None)
        }
        else { false }
    }

    // search functions
    // todo: consider weights between nodes, breadth/depth first, cycle-detection
    fn get_path(&mut self, s: GraphSearch) -> Option<Vec<Uuid>> {
        let mut visited: HashSet<Uuid> = HashSet::new();
        let mut result = vec!(); //: HashSet<Uuid> = HashSet::new();

        match s {
            GraphSearch::Depth(from,to) => {
                let mut stack = vec!();

                stack.push(from);
                visited.insert(from);
                result.push(from);

                let mut cursor = Some(from);

                while cursor.is_some() {
                    if let Some(ref node) = self.get(&cursor.unwrap()) {
                        //get first unvisited node
                        let not_visited = node.edges.iter().find(|&(&n,v)| !visited.contains(&n));

                        if let Some((&n,w)) = not_visited {
                            stack.push(n);
                            visited.insert(n);
                            result.push(n);

                            if n == to { break; }

                            cursor = Some(n);
                        }
                        else { cursor = stack.pop(); }
                    }
                    else { cursor = stack.pop(); }
                }

                if result.contains(&to) {
                    Some(result)
                }
                else { None }
            },
            _ => { None },
        }

    }

    fn get_cycle(&self, s: GraphSearch) -> Option<Vec<&Uuid>> {
        None
    }

    fn get_next(&self, s:GraphSearch) {
        match s {
            GraphSearch::Depth(from,to) => {},
            _ => {},
        }
    }
}

// todo: impl as trait instead?
pub enum GraphSearch {
    Depth(Uuid,Uuid),
    Breadth(Uuid,Uuid),
}

//impl<I:PartialEq> GraphBackend<I> for Graph {
//}

// ----
// tests
// ----
#[cfg(test)]
mod tests {
    extern crate test;
    use ::backend::{Graph,GraphNode,GraphSearch};

    #[test]
    fn test_basic() {
        let mut graph = Graph::new();
        let mut nodes = vec!();
        for i in 0..5 {
            nodes.push(graph.add());
        }

        graph.get_mut(&nodes[0]).unwrap().direct(&nodes[1],None); //note there is no verification that b exists when doing this manually

        graph.direct(&nodes[3],&nodes[0]);
        graph.direct(&nodes[4],&nodes[3]);
        graph.remove(&nodes[2]);
        assert!(!graph.direct(&nodes[2],&nodes[3]));

        let r = graph.get_path(GraphSearch::Depth(nodes[0],nodes[4]));
        assert!(!r.is_some());

        let r = graph.get_path(GraphSearch::Depth(nodes[4],nodes[0]));
        assert_eq!(r.unwrap().len(), 3);
    }

}
<commit_msg>breadth-first search, needs testing!<commit_after>/// mush graph backend and abstraction to swap out with custom backend

use uuid::Uuid;
use std::collections::{HashMap,HashSet,VecDeque};

// graph functions
/*pub trait GraphBackend<I:PartialEq> {
    fn add(&mut self) -> I;
    //fn disable(N) -> bool;

    /// forcefully removes element from graph, all edge nodes should be updatedb
    fn remove(&mut self, node: &I);// -> Vec<E>;

    fn direct(&mut self, from: &I, to: &I);
    fn undirect(&mut self, from: &I, to: &I);
}*/

//pub trait<I> GraphSearch<I> {
  //  fn connections(&self, from: I, to: I) -> Vec<I>;
//}

#[derive(Debug)]
pub struct GraphNode {
    uuid: Uuid,
    edges: HashMap<Uuid,Option<f64>>, //to,weight
}

/// unidirectional edge, use two edges for bidirectional/undirected graph
/*pub struct GraphEdge {
    to: Uuid,
    maybe_weight: Option<f64>,
}*/
impl GraphNode {
    fn new (uuid: Uuid) -> GraphNode {
        GraphNode { uuid: uuid,
                    edges: HashMap::new() }
    }
    /// direct the node towards another node
    // todo: rename me! sounds too similar to unidirectional
    fn direct (&mut self, to:&Uuid, weight: Option<f64>) -> bool {
        self.edges.insert(*to,weight).is_some()
    }
    fn undirect (&mut self, to:&Uuid, weight: Option<f64>) -> bool {
        self.edges.remove(to).is_some()
    }
}

//----

pub struct Graph {
    nodes: HashMap<Uuid,GraphNode>,
}
impl Graph {
    fn new () -> Graph {
        Graph { nodes: HashMap::new() }
    }

    fn get_mut(&mut self, uuid: &Uuid) -> Option<&mut GraphNode> {
        self.nodes.get_mut(uuid)
    }
    fn get(&mut self, uuid: &Uuid) -> Option<&GraphNode> {
        self.nodes.get(uuid)
    }

    fn add (&mut self) -> Uuid { //todo: maybe_edges fn arg
        let uuid = Uuid::new_v4();
        let n = GraphNode::new(uuid);
        self.nodes.insert(uuid,n);
        uuid
    }
    fn remove(&mut self, node: &Uuid) {
        self.nodes.remove(node);
    }
    fn direct(&mut self, from: &Uuid, to: &Uuid) -> bool {
        if let Some(f) = self.nodes.get_mut(from) {
            f.direct(to,None)
        }
        else { false }
    }
    fn undirect(&mut self, from: &Uuid, to: &Uuid) -> bool {
        if let Some(f) = self.nodes.get_mut(from) {
            f.undirect(to,None)
        }
        else { false }
    }

    // search functions
    // todo: consider weights between nodes, breadth/depth first, cycle-detection
    fn get_path(&mut self, s: GraphSearch) -> Option<Vec<Uuid>> {
        let mut visited: HashSet<Uuid> = HashSet::new();
        let mut result = vec!();

        match s {
            GraphSearch::Depth(from,to) => {
                let mut stack = vec!();

                stack.push(from);
                visited.insert(from);
                result.push(from);

                let mut cursor = Some(from);

                while cursor.is_some() {
                    if let Some(ref node) = self.get(&cursor.unwrap()) {
                        //get first unvisited node
                        let not_visited = node.edges.iter().find(|&(&n,v)| !visited.contains(&n));

                        if let Some((&n,w)) = not_visited {
                            stack.push(n);
                            visited.insert(n);
                            result.push(n);

                            if n == to { break; }

                            cursor = Some(n);
                        }
                        else { cursor = stack.pop(); }
                    }
                    else { cursor = stack.pop(); }
                }

                if result.contains(&to) {
                    Some(result)
                }
                else { None }
            },
            GraphSearch::Breadth(from,to) => { // breadth first search, uses a queue
                let mut queue = VecDeque::new();

                queue.push_back(from);
                visited.insert(from);
                result.push(from);

                let mut cursor = Some(from);

                while cursor.is_some() {
                    if let Some(ref node) = self.get(&cursor.unwrap()) {
                        //get first unvisited node
                        let not_visited: Vec<Option<(Uuid,Option<f64>)>> = node.edges.iter().map(|(&n,&v)| {
                            if !visited.contains(&n) {
                                Some((n,v))
                            }
                            else { None }
                        }).collect();

                        for maybe_node in not_visited {
                            if let Some((n,w)) = maybe_node {
                                queue.push_back(n);
                                visited.insert(n);
                                result.push(n);

                                if n == to { break; }

                                cursor = Some(n);
                            }
                        }

                        cursor = queue.pop_front();
                    }
                    else { cursor = queue.pop_front(); }
                }

                if result.contains(&to) {
                    Some(result)
                }
                else { None }
            },
        }

    }

    fn get_cycle(&self, s: GraphSearch) -> Option<Vec<&Uuid>> {
        None
    }

    fn get_next(&self, s:GraphSearch) {
        match s {
            GraphSearch::Depth(from,to) => {},
            _ => {},
        }
    }
}

// todo: impl as trait instead?
pub enum GraphSearch {
    Depth(Uuid,Uuid),
    Breadth(Uuid,Uuid),
}

//impl<I:PartialEq> GraphBackend<I> for Graph {
//}

// ----
// tests
// ----
#[cfg(test)]
mod tests {
    extern crate test;
    use ::backend::{Graph,GraphNode,GraphSearch};

    #[test]
    fn test_basic() {
        let mut graph = Graph::new();
        let mut nodes = vec!();
        for i in 0..5 {
            nodes.push(graph.add());
        }

        graph.get_mut(&nodes[0]).unwrap().direct(&nodes[1],None); //note there is no verification that b exists when doing this manually

        graph.direct(&nodes[3],&nodes[0]);
        graph.direct(&nodes[4],&nodes[3]);
        graph.remove(&nodes[2]);
        assert!(!graph.direct(&nodes[2],&nodes[3]));

        let r = graph.get_path(GraphSearch::Depth(nodes[0],nodes[4]));
        assert!(!r.is_some());

        let r = graph.get_path(GraphSearch::Depth(nodes[4],nodes[0]));
        assert_eq!(r.unwrap().len(), 3);

        let r = graph.get_path(GraphSearch::Breadth(nodes[4],nodes[0]));
        assert!(r.is_some());
    }

}
<|endoftext|>


<commit_before>extern crate ucd_raw;

use std::collections::HashMap;
use std::fs::File;
use std::io::Write;
use std::time::Instant;
use ucd_raw::Character;
use ucd_raw::CHARACTERS;

#[derive(Debug)]
struct Entry {
    index: usize,
    codepoints: Vec<u32>,
}

#[derive(Debug)]
struct TempSuffix<'a> {
    suffix: &'a str,
    entry: Entry,
}

fn char_iter() -> impl Iterator<Item = &'static Character> {
    CHARACTERS
        .iter()
        .filter(|character| match character.codepoint {
            0x03400...0x04DB5 => false,
            0x04E00...0x09FEA => false,
            0x20000...0x2A6D6 => false,
            0x2A700...0x2B734 => false,
            0x2B740...0x2B81D => false,
            0x2B820...0x2CEA1 => false,
            0x2CEB0...0x2EBE0 => false,
            0x17000...0x187EC => false,
            0x1B170...0x1B2FB => false,
            0x0F900...0x0FA6D => false,
            0x0FA70...0x0FAD9 => false,
            0x2F800...0x2FA1D => false,
            _ => true,
        })
}

fn suffixes<'a>(string: &'a str) -> impl Iterator<Item = (usize, &'a str)> {
    (0..string.len()).map(move |i| &string[i..]).enumerate()
}

fn main() {
    let start = Instant::now();

    let mut combined = String::new();
    let mut visited_words = HashMap::new();
    let mut temp_suffixes = Vec::new();

    let mut out = File::create("src/generated.rs").unwrap();

    for character in char_iter().take(20) {
        for word in character.name.split_whitespace() {
            let mut start;

            if visited_words.contains_key(word) {
                start = visited_words[word];
            } else {
                start = combined.len();

                visited_words.insert(word, start);
                combined.push_str(word);
                combined.push('\n');
            }

            for (offset, suffix) in suffixes(word) {
                temp_suffixes.push(TempSuffix {
                    suffix,
                    entry: Entry {
                        index: start + offset,
                        codepoints: vec![character.codepoint],
                    },
                });
            }
        }
    }

    temp_suffixes.sort_by_key(|temp_suffix| temp_suffix.suffix);
    temp_suffixes.dedup_by(|a, b| {
        let equal = a.suffix == b.suffix;

        if equal {
            b.entry.codepoints.extend_from_slice(&a.entry.codepoints);
        }

        equal
    });

    writeln!(out, "// Auto-generated by `src/bin/gen`\n").unwrap();
    writeln!(out, "use table::Entry;").unwrap();

    writeln!(
        out,
        "pub const ENTRIES: &[Entry] = &{:#?};",
        temp_suffixes
            // .into_iter()
            // .map(|temp_suffix| temp_suffix.entry)
            // .collect::<Vec<_>>()
    ).unwrap();

    writeln!(out, "pub const COMBINED: &[u8] = b\"{}\";", combined).unwrap();

    println!("Generated in {:?}", start.elapsed());
}
<commit_msg>Buffer writes to file<commit_after>extern crate ucd_raw;

use std::collections::HashMap;
use std::fs::create_dir_all;
use std::fs::File;
use std::io::BufWriter;
use std::io::Write;
use std::time::Instant;
use ucd_raw::Character;
use ucd_raw::CHARACTERS;

#[derive(Debug)]
struct Entry {
    index: usize,
    codepoints: Vec<u32>,
}

#[derive(Debug)]
struct TempSuffix<'a> {
    suffix: &'a str,
    entry: Entry,
}

fn char_iter() -> impl Iterator<Item = &'static Character> {
    CHARACTERS
        .iter()
        .filter(|character| match character.codepoint {
            0x03400...0x04DB5 => false,
            0x04E00...0x09FEA => false,
            0x20000...0x2A6D6 => false,
            0x2A700...0x2B734 => false,
            0x2B740...0x2B81D => false,
            0x2B820...0x2CEA1 => false,
            0x2CEB0...0x2EBE0 => false,
            0x17000...0x187EC => false,
            0x1B170...0x1B2FB => false,
            0x0F900...0x0FA6D => false,
            0x0FA70...0x0FAD9 => false,
            0x2F800...0x2FA1D => false,
            _ => true,
        })
}

fn suffixes<'a>(string: &'a str) -> impl Iterator<Item = (usize, &'a str)> {
    (0..string.len()).map(move |i| &string[i..]).enumerate()
}

fn main() {
    println!("indexing {} codepoints...", char_iter().count());

    let start = Instant::now();

    let mut combined = String::new();
    let mut visited_words = HashMap::new();
    let mut temp_suffixes = Vec::new();

    create_dir_all("src/generated").unwrap();
    let out = File::create("src/generated/generated.rs").unwrap();
    let mut out = BufWriter::new(out);

    for character in char_iter() {
        for word in character.name.split_whitespace() {
            let mut start;

            if visited_words.contains_key(word) {
                start = visited_words[word];
            } else {
                start = combined.len();

                visited_words.insert(word, start);
                combined.push_str(word);
                combined.push('\n');
            }

            for (offset, suffix) in suffixes(word) {
                temp_suffixes.push(TempSuffix {
                    suffix,
                    entry: Entry {
                        index: start + offset,
                        codepoints: vec![character.codepoint],
                    },
                });
            }
        }
    }

    temp_suffixes.sort_by_key(|temp_suffix| temp_suffix.suffix);

    println!("length before dedup: {}", temp_suffixes.len());

    temp_suffixes.dedup_by(|a, b| {
        let equal = a.suffix == b.suffix;

        if equal {
            b.entry.codepoints.extend_from_slice(&a.entry.codepoints);
        }

        equal
    });

    println!("after: {}", temp_suffixes.len());

    writeln!(out, "// Auto-generated by `src/bin/gen`\n").unwrap();
    writeln!(out, "use table::Entry;").unwrap();

    writeln!(
        out,
        "pub const ENTRIES: &[Entry] = &{:#?};",
        temp_suffixes
            // .into_iter()
            // .map(|temp_suffix| temp_suffix.entry)
            // .collect::<Vec<_>>()
    ).unwrap();

    writeln!(out, "pub const COMBINED: &[u8] = b\"{}\";", combined).unwrap();

    println!("Generated in {:?}", start.elapsed());
}
<|endoftext|>


<commit_before>pub use self::parse_mode::ParseMode;
pub use self::chat_action::ChatAction;

mod parse_mode;
mod chat_action;

use reqwest::Client;
use serde_json;
use serde_json::Value;

use bot::chat_action::get_chat_action;
use bot::parse_mode::get_parse_mode;
use error::{Result, check_for_error};
use error::Error::{JsonNotFound, RequestFailed};
use objects::{Update, Message, Contact, InlineKeyboardMarkup};

use value_extension::ValueExtension;

/// A `Bot` which will do all the API calls.
///
/// The `Bot` will be given access to in a `Command` with which you can do all
/// the API interactions in your `Command`s.
#[derive(Debug)]
pub struct Bot {
    pub id: i64,
    pub first_name: String,
    pub last_name: Option<String>,
    pub username: String,
    client: Client,
    pub bot_url: String,
}

impl Bot {
    /// Constructs a new `Bot`.
    pub fn new(bot_url: String) -> Result<Self> {
        let client = Client::new()?;
        let rjson = Bot::get_me(&client, &bot_url)?;
        let id = rjson.as_required_i64("id")?;
        let first_name = rjson.as_required_string("first_name")?;
        let last_name = rjson.as_optional_string("last_name");
        let username = rjson.as_required_string("username")?;

        Ok(Bot {
               id: id,
               first_name: first_name,
               last_name: last_name,
               username: username,
               client: client,
               bot_url: bot_url,
           })
    }

    /// API call which gets the information about your bot.
    pub fn get_me(client: &Client, bot_url: &str) -> Result<Value> {
        let path = ["getMe"];
        let url = ::construct_api_url(bot_url, &path);
        let mut resp = client.get(&url).send()?;

        if resp.status().is_success() {
            let rjson: Value = resp.json()?;
            rjson.get("result").cloned().ok_or(JsonNotFound)
        } else {
            Err(RequestFailed(*resp.status()))
        }
    }

    /// API call which will get called to get the updates for your bot.
    pub fn get_updates(&self,
                       offset: i32,
                       limit: Option<i32>,
                       timeout: Option<i32>,
                       network_delay: Option<f32>)
                       -> Result<Option<Vec<Update>>> {
        let limit = limit.unwrap_or(100);
        let timeout = timeout.unwrap_or(0);
        let network_delay = network_delay.unwrap_or(0.0);
        let path = ["getUpdates"];
        let path_url = ::construct_api_url(&self.bot_url, &path);
        let url = format!("{}?offset={}&limit={}&timeout={}&network_delay={}",
                          path_url,
                          offset,
                          limit,
                          timeout,
                          network_delay);
        println!("{}", url);
        let mut data = self.client.get(&url).send()?;
        let rjson: Value = check_for_error(data.json()?)?;
        let updates_json = rjson.get("result");

        if let Some(result) = updates_json {
            let updates: Vec<Update> = serde_json::from_value(result.clone())?;
            Ok(Some(updates))
        } else {
            Ok(None)
        }
    }

    /// API call which will send a message to a chat which your bot participates in.
    pub fn send_message(&self,
                        chat_id: &i64,
                        text: &str,
                        parse_mode: Option<&ParseMode>,
                        disable_web_page_preview: Option<&bool>,
                        disable_notification: Option<&bool>,
                        reply_to_message_id: Option<&i64>,
                        reply_markup: Option<&InlineKeyboardMarkup>)
                        -> Result<Message> {
        let chat_id: &str = &chat_id.to_string();
        let parse_mode = &get_parse_mode(parse_mode.unwrap_or(&ParseMode::Text));
        let disable_web_page_preview: &str =
            &disable_web_page_preview.unwrap_or(&false).to_string();
        let disable_notification: &str = &disable_notification.unwrap_or(&false).to_string();
        let reply_to_message_id: &str = &reply_to_message_id
                                             .map(|i| i.to_string())
                                             .unwrap_or("None".to_string());
        let reply_markup =
            &reply_markup
                 .map(|r| serde_json::to_string(r).unwrap_or("".to_string()))
                 .unwrap_or("".to_string());

        let path = ["sendMessage"];
        let params = [("chat_id", chat_id),
                      ("text", text),
                      ("parse_mode", parse_mode),
                      ("disable_web_page_preview", disable_web_page_preview),
                      ("disable_notification", disable_notification),
                      ("reply_to_message_id", reply_to_message_id),
                      ("reply_markup", reply_markup)];
        self.post_message(&path, &params)
    }

    /// API call which will reply to a message directed to your bot.
    pub fn reply_to_message(&self, update: &Update, text: &str) -> Result<Message> {
        let message = update.clone().message.unwrap();
        let message_id = message.message_id;
        let chat_id = message.chat.id;
        self.send_message(&chat_id, text, None, None, None, Some(&message_id), None)
    }

    /// API call which will forward a message.
    pub fn forward_message(&self,
                           update: &Update,
                           chat_id: &i32,
                           disable_notification: Option<&bool>)
                           -> Result<Message> {
        let message = update.clone().message.unwrap();
        let chat_id: &str = &chat_id.to_string();
        let from_chat_id: &str = &message.chat.id.to_string();
        let message_id: &str = &message.message_id.to_string();
        let disable_notification: &str = &disable_notification.unwrap_or(&false).to_string();
        let path = ["forwardMessage"];
        let params = [("chat_id", chat_id),
                      ("from_chat_id", from_chat_id),
                      ("disable_notification", disable_notification),
                      ("message_id", message_id)];
        self.post_message(&path, &params)
    }

    /// API call which will show the given chat action to the users.
    pub fn send_chat_action(&self, chat_id: &i64, action: &ChatAction) -> Result<bool> {
        let chat_id: &str = &chat_id.to_string();
        let action = &get_chat_action(action);
        let path = ["sendChatAction"];
        let params = [("chat_id", chat_id), ("action", action)];
        let url = ::construct_api_url(&self.bot_url, &path);
        let mut data = self.client.post(&url).form(&params).send()?;
        let rjson: Value = check_for_error(data.json()?)?;
        let result_json = rjson.get("result").ok_or(JsonNotFound)?;
        let chat_action_succeeded: bool = serde_json::from_value(result_json.clone())?;
        Ok(chat_action_succeeded)
    }

    /// API call which will send the given contact.
    pub fn send_contact(&self,
                        chat_id: &i64,
                        contact: &Contact,
                        disable_notification: Option<&bool>,
                        reply_to_message_id: Option<&i64>,
                        reply_markup: Option<&InlineKeyboardMarkup>)
                        -> Result<Message> {
        let chat_id: &str = &chat_id.to_string();
        let phone_number = &contact.phone_number;
        let first_name = &contact.first_name;
        let last_name = &contact.clone().last_name.unwrap();
        let disable_notification: &str = &disable_notification.unwrap_or(&false).to_string();
        let reply_to_message_id: &str = &reply_to_message_id
                                             .map(|i| i.to_string())
                                             .unwrap_or("None".to_string());
        let reply_markup = &reply_markup
                                .and_then(|r| serde_json::to_string(r).ok())
                                .unwrap_or("".to_string());
        let path = ["sendContact"];
        let params = [("chat_id", chat_id),
                      ("phone_number", phone_number),
                      ("first_name", first_name),
                      ("last_name", last_name),
                      ("disable_notification", disable_notification),
                      ("reply_to_message_id", reply_to_message_id),
                      ("reply_markup", reply_markup)];
        self.post_message(&path, &params)
    }

    /// The actual networking done for sending messages.
    fn post_message(&self, path: &[&str], params: &[(&str, &str)]) -> Result<Message> {
        let url = ::construct_api_url(&self.bot_url, path);
        let mut data = self.client.post(&url).form(&params).send()?;
        let rjson: Value = check_for_error(data.json()?)?;
        let message_json = rjson.get("result").ok_or(JsonNotFound)?;
        let message: Message = serde_json::from_value(message_json.clone())?;
        Ok(message)
    }
}
<commit_msg>Removing debug println<commit_after>pub use self::parse_mode::ParseMode;
pub use self::chat_action::ChatAction;

mod parse_mode;
mod chat_action;

use reqwest::Client;
use serde_json;
use serde_json::Value;

use bot::chat_action::get_chat_action;
use bot::parse_mode::get_parse_mode;
use error::{Result, check_for_error};
use error::Error::{JsonNotFound, RequestFailed};
use objects::{Update, Message, Contact, InlineKeyboardMarkup};

use value_extension::ValueExtension;

/// A `Bot` which will do all the API calls.
///
/// The `Bot` will be given access to in a `Command` with which you can do all
/// the API interactions in your `Command`s.
#[derive(Debug)]
pub struct Bot {
    pub id: i64,
    pub first_name: String,
    pub last_name: Option<String>,
    pub username: String,
    client: Client,
    pub bot_url: String,
}

impl Bot {
    /// Constructs a new `Bot`.
    pub fn new(bot_url: String) -> Result<Self> {
        let client = Client::new()?;
        let rjson = Bot::get_me(&client, &bot_url)?;
        let id = rjson.as_required_i64("id")?;
        let first_name = rjson.as_required_string("first_name")?;
        let last_name = rjson.as_optional_string("last_name");
        let username = rjson.as_required_string("username")?;

        Ok(Bot {
               id: id,
               first_name: first_name,
               last_name: last_name,
               username: username,
               client: client,
               bot_url: bot_url,
           })
    }

    /// API call which gets the information about your bot.
    pub fn get_me(client: &Client, bot_url: &str) -> Result<Value> {
        let path = ["getMe"];
        let url = ::construct_api_url(bot_url, &path);
        let mut resp = client.get(&url).send()?;

        if resp.status().is_success() {
            let rjson: Value = resp.json()?;
            rjson.get("result").cloned().ok_or(JsonNotFound)
        } else {
            Err(RequestFailed(*resp.status()))
        }
    }

    /// API call which will get called to get the updates for your bot.
    pub fn get_updates(&self,
                       offset: i32,
                       limit: Option<i32>,
                       timeout: Option<i32>,
                       network_delay: Option<f32>)
                       -> Result<Option<Vec<Update>>> {
        let limit = limit.unwrap_or(100);
        let timeout = timeout.unwrap_or(0);
        let network_delay = network_delay.unwrap_or(0.0);
        let path = ["getUpdates"];
        let path_url = ::construct_api_url(&self.bot_url, &path);
        let url = format!("{}?offset={}&limit={}&timeout={}&network_delay={}",
                          path_url,
                          offset,
                          limit,
                          timeout,
                          network_delay);
        let mut data = self.client.get(&url).send()?;
        let rjson: Value = check_for_error(data.json()?)?;
        let updates_json = rjson.get("result");

        if let Some(result) = updates_json {
            let updates: Vec<Update> = serde_json::from_value(result.clone())?;
            Ok(Some(updates))
        } else {
            Ok(None)
        }
    }

    /// API call which will send a message to a chat which your bot participates in.
    pub fn send_message(&self,
                        chat_id: &i64,
                        text: &str,
                        parse_mode: Option<&ParseMode>,
                        disable_web_page_preview: Option<&bool>,
                        disable_notification: Option<&bool>,
                        reply_to_message_id: Option<&i64>,
                        reply_markup: Option<&InlineKeyboardMarkup>)
                        -> Result<Message> {
        let chat_id: &str = &chat_id.to_string();
        let parse_mode = &get_parse_mode(parse_mode.unwrap_or(&ParseMode::Text));
        let disable_web_page_preview: &str =
            &disable_web_page_preview.unwrap_or(&false).to_string();
        let disable_notification: &str = &disable_notification.unwrap_or(&false).to_string();
        let reply_to_message_id: &str = &reply_to_message_id
                                             .map(|i| i.to_string())
                                             .unwrap_or("None".to_string());
        let reply_markup =
            &reply_markup
                 .map(|r| serde_json::to_string(r).unwrap_or("".to_string()))
                 .unwrap_or("".to_string());

        let path = ["sendMessage"];
        let params = [("chat_id", chat_id),
                      ("text", text),
                      ("parse_mode", parse_mode),
                      ("disable_web_page_preview", disable_web_page_preview),
                      ("disable_notification", disable_notification),
                      ("reply_to_message_id", reply_to_message_id),
                      ("reply_markup", reply_markup)];
        self.post_message(&path, &params)
    }

    /// API call which will reply to a message directed to your bot.
    pub fn reply_to_message(&self, update: &Update, text: &str) -> Result<Message> {
        let message = update.clone().message.unwrap();
        let message_id = message.message_id;
        let chat_id = message.chat.id;
        self.send_message(&chat_id, text, None, None, None, Some(&message_id), None)
    }

    /// API call which will forward a message.
    pub fn forward_message(&self,
                           update: &Update,
                           chat_id: &i32,
                           disable_notification: Option<&bool>)
                           -> Result<Message> {
        let message = update.clone().message.unwrap();
        let chat_id: &str = &chat_id.to_string();
        let from_chat_id: &str = &message.chat.id.to_string();
        let message_id: &str = &message.message_id.to_string();
        let disable_notification: &str = &disable_notification.unwrap_or(&false).to_string();
        let path = ["forwardMessage"];
        let params = [("chat_id", chat_id),
                      ("from_chat_id", from_chat_id),
                      ("disable_notification", disable_notification),
                      ("message_id", message_id)];
        self.post_message(&path, &params)
    }

    /// API call which will show the given chat action to the users.
    pub fn send_chat_action(&self, chat_id: &i64, action: &ChatAction) -> Result<bool> {
        let chat_id: &str = &chat_id.to_string();
        let action = &get_chat_action(action);
        let path = ["sendChatAction"];
        let params = [("chat_id", chat_id), ("action", action)];
        let url = ::construct_api_url(&self.bot_url, &path);
        let mut data = self.client.post(&url).form(&params).send()?;
        let rjson: Value = check_for_error(data.json()?)?;
        let result_json = rjson.get("result").ok_or(JsonNotFound)?;
        let chat_action_succeeded: bool = serde_json::from_value(result_json.clone())?;
        Ok(chat_action_succeeded)
    }

    /// API call which will send the given contact.
    pub fn send_contact(&self,
                        chat_id: &i64,
                        contact: &Contact,
                        disable_notification: Option<&bool>,
                        reply_to_message_id: Option<&i64>,
                        reply_markup: Option<&InlineKeyboardMarkup>)
                        -> Result<Message> {
        let chat_id: &str = &chat_id.to_string();
        let phone_number = &contact.phone_number;
        let first_name = &contact.first_name;
        let last_name = &contact.clone().last_name.unwrap();
        let disable_notification: &str = &disable_notification.unwrap_or(&false).to_string();
        let reply_to_message_id: &str = &reply_to_message_id
                                             .map(|i| i.to_string())
                                             .unwrap_or("None".to_string());
        let reply_markup = &reply_markup
                                .and_then(|r| serde_json::to_string(r).ok())
                                .unwrap_or("".to_string());
        let path = ["sendContact"];
        let params = [("chat_id", chat_id),
                      ("phone_number", phone_number),
                      ("first_name", first_name),
                      ("last_name", last_name),
                      ("disable_notification", disable_notification),
                      ("reply_to_message_id", reply_to_message_id),
                      ("reply_markup", reply_markup)];
        self.post_message(&path, &params)
    }

    /// The actual networking done for sending messages.
    fn post_message(&self, path: &[&str], params: &[(&str, &str)]) -> Result<Message> {
        let url = ::construct_api_url(&self.bot_url, path);
        let mut data = self.client.post(&url).form(&params).send()?;
        let rjson: Value = check_for_error(data.json()?)?;
        let message_json = rjson.get("result").ok_or(JsonNotFound)?;
        let message: Message = serde_json::from_value(message_json.clone())?;
        Ok(message)
    }
}
<|endoftext|>


<commit_before>use crate::query::Query;
use crate::repository::{Repository, Template};
use std::collections::hash_map::DefaultHasher;
use std::env::temp_dir;
use std::fs::{read_to_string, File};
use std::hash::{Hash, Hasher};
use std::io::{Error, Write};
use std::path::PathBuf;

const FILE_NAME_PREFIX: &str = "alfred-gitignore-";

/// Constructs a `.gitignore` file from a query.
///
/// The builder combines the `*.gitignore` templates in a query into a single `.gitignore` file.
pub struct Builder {
    repository: Repository,
    templates: Vec<Template>,
}

impl Builder {
    /// Returns a new builder that can turn the query into a single `.gitignore` file.
    pub fn new(repository: Repository, query: &Query) -> Self {
        Builder {
            repository,
            templates: query.sanitized_query(),
        }
    }

    /// Build a single `.gitignore` file from the query.
    ///
    /// The templates selected in the query are written to a single `.gitignore` file at a temporary
    /// location on the local disk, and the path to the file is returned.
    pub fn build(&self) -> Result<PathBuf, Error> {
        let destination = temp_dir().join(self.file_name());
        let mut file = File::create(&destination)?;

        for i in 0..self.templates.len() {
            if let Some(template) = self.templates.get(i) {
                let template_path = self.repository.path().join(template.file_name());
                let content = read_to_string(template_path)?;

                file.write_all(format!("### {}\n", template.file_name()).as_bytes())?;
                file.write_all(&content.as_bytes())?;

                if i < self.templates.len() - 1 {
                    file.write_all(b"\n")?;
                }
            }
        }

        file.sync_all()?;

        Ok(destination)
    }

    /// Returns the file name for the given query.
    ///
    /// The names of the templates in the given query are concatenated and then hashed to allow the
    /// results of the query to be cached.
    fn file_name(&self) -> PathBuf {
        let mut template_names: Vec<String> = self
            .templates
            .iter()
            .map(|template| template.name())
            .cloned()
            .collect();

        template_names.sort();

        let mut hasher = DefaultHasher::new();
        template_names.join("").hash(&mut hasher);
        let hash = hasher.finish();

        let mut file_name = String::from(FILE_NAME_PREFIX);
        file_name.push_str(&hash.to_string());
        file_name.push_str(".gitignore");

        PathBuf::from(file_name)
    }
}

#[cfg(test)]
mod tests {
    use crate::builder::Builder;
    use crate::query::Query;
    use crate::testing::initialize_repository;
    use std::fs::read_to_string;
    use tempfile::TempDir;

    #[test]
    fn build_one_file() {
        let tempdir = TempDir::new().unwrap();
        let repository = initialize_repository(tempdir.path()).unwrap();
        let query = Query::new(&repository, Some(vec!["apples"])).unwrap();

        let builder = Builder::new(repository, &query);
        let path = builder.build().unwrap();

        let mut expected = String::new();
        expected.push_str("### apples.gitignore\n");
        expected.push_str(include_str!("../tests/files/repository/apples.gitignore"));

        let content = read_to_string(path).unwrap();

        assert_eq!(expected, content);
    }

    #[test]
    fn build_two_files() {
        let tempdir = TempDir::new().unwrap();
        let repository = initialize_repository(tempdir.path()).unwrap();
        let query = Query::new(&repository, Some(vec!["oranges", "apples"])).unwrap();

        let builder = Builder::new(repository, &query);
        let path = builder.build().unwrap();

        let mut expected = String::new();
        expected.push_str("### oranges.gitignore\n");
        expected.push_str(include_str!("../tests/files/repository/oranges.gitignore"));

        expected.push_str("\n### apples.gitignore\n");
        expected.push_str(include_str!("../tests/files/repository/apples.gitignore"));

        let content = read_to_string(path).unwrap();
        assert_eq!(expected, content);
    }

    #[test]
    fn file_name() {
        let tempdir = TempDir::new().unwrap();
        let repository = initialize_repository(tempdir.path()).unwrap();
        let query = Query::new(&repository, Some(vec!["apples"])).unwrap();

        let builder = Builder::new(repository, &query);

        assert_eq!(
            "alfred-gitignore-16623996710012718148.gitignore",
            builder.file_name().to_str().unwrap()
        );
    }
}
<commit_msg>Remove needless borrow<commit_after>use crate::query::Query;
use crate::repository::{Repository, Template};
use std::collections::hash_map::DefaultHasher;
use std::env::temp_dir;
use std::fs::{read_to_string, File};
use std::hash::{Hash, Hasher};
use std::io::{Error, Write};
use std::path::PathBuf;

const FILE_NAME_PREFIX: &str = "alfred-gitignore-";

/// Constructs a `.gitignore` file from a query.
///
/// The builder combines the `*.gitignore` templates in a query into a single `.gitignore` file.
pub struct Builder {
    repository: Repository,
    templates: Vec<Template>,
}

impl Builder {
    /// Returns a new builder that can turn the query into a single `.gitignore` file.
    pub fn new(repository: Repository, query: &Query) -> Self {
        Builder {
            repository,
            templates: query.sanitized_query(),
        }
    }

    /// Build a single `.gitignore` file from the query.
    ///
    /// The templates selected in the query are written to a single `.gitignore` file at a temporary
    /// location on the local disk, and the path to the file is returned.
    pub fn build(&self) -> Result<PathBuf, Error> {
        let destination = temp_dir().join(self.file_name());
        let mut file = File::create(&destination)?;

        for i in 0..self.templates.len() {
            if let Some(template) = self.templates.get(i) {
                let template_path = self.repository.path().join(template.file_name());
                let content = read_to_string(template_path)?;

                file.write_all(format!("### {}\n", template.file_name()).as_bytes())?;
                file.write_all(content.as_bytes())?;

                if i < self.templates.len() - 1 {
                    file.write_all(b"\n")?;
                }
            }
        }

        file.sync_all()?;

        Ok(destination)
    }

    /// Returns the file name for the given query.
    ///
    /// The names of the templates in the given query are concatenated and then hashed to allow the
    /// results of the query to be cached.
    fn file_name(&self) -> PathBuf {
        let mut template_names: Vec<String> = self
            .templates
            .iter()
            .map(|template| template.name())
            .cloned()
            .collect();

        template_names.sort();

        let mut hasher = DefaultHasher::new();
        template_names.join("").hash(&mut hasher);
        let hash = hasher.finish();

        let mut file_name = String::from(FILE_NAME_PREFIX);
        file_name.push_str(&hash.to_string());
        file_name.push_str(".gitignore");

        PathBuf::from(file_name)
    }
}

#[cfg(test)]
mod tests {
    use crate::builder::Builder;
    use crate::query::Query;
    use crate::testing::initialize_repository;
    use std::fs::read_to_string;
    use tempfile::TempDir;

    #[test]
    fn build_one_file() {
        let tempdir = TempDir::new().unwrap();
        let repository = initialize_repository(tempdir.path()).unwrap();
        let query = Query::new(&repository, Some(vec!["apples"])).unwrap();

        let builder = Builder::new(repository, &query);
        let path = builder.build().unwrap();

        let mut expected = String::new();
        expected.push_str("### apples.gitignore\n");
        expected.push_str(include_str!("../tests/files/repository/apples.gitignore"));

        let content = read_to_string(path).unwrap();

        assert_eq!(expected, content);
    }

    #[test]
    fn build_two_files() {
        let tempdir = TempDir::new().unwrap();
        let repository = initialize_repository(tempdir.path()).unwrap();
        let query = Query::new(&repository, Some(vec!["oranges", "apples"])).unwrap();

        let builder = Builder::new(repository, &query);
        let path = builder.build().unwrap();

        let mut expected = String::new();
        expected.push_str("### oranges.gitignore\n");
        expected.push_str(include_str!("../tests/files/repository/oranges.gitignore"));

        expected.push_str("\n### apples.gitignore\n");
        expected.push_str(include_str!("../tests/files/repository/apples.gitignore"));

        let content = read_to_string(path).unwrap();
        assert_eq!(expected, content);
    }

    #[test]
    fn file_name() {
        let tempdir = TempDir::new().unwrap();
        let repository = initialize_repository(tempdir.path()).unwrap();
        let query = Query::new(&repository, Some(vec!["apples"])).unwrap();

        let builder = Builder::new(repository, &query);

        assert_eq!(
            "alfred-gitignore-16623996710012718148.gitignore",
            builder.file_name().to_str().unwrap()
        );
    }
}
<|endoftext|>


<commit_before>// Copyright 2013-2014 The Rust Project Developers.
// Copyright 2018 The Uuid Project Developers.
//
// See the COPYRIGHT file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! A Builder type for [`Uuid`]s.
//!
//! [`Uuid`]: ../struct.Uuid.html

use crate::prelude::*;

/// A builder struct for creating a [`Uuid`]
///
/// # Examples
///
/// Creating a v4 `Uuid` from externally generated bytes:
///
/// ```
/// use uuid::{Builder, Variant, Version};
///
/// # let rng = || [
/// #     70, 235, 208, 238, 14, 109, 67, 201, 185, 13, 204, 195, 90,
/// # 145, 63, 62,
/// # ];
/// let random_bytes = rng();
/// let uuid = Builder::from_bytes(random_bytes)
///     .set_variant(Variant::RFC4122)
///     .set_version(Version::Random)
///     .build();
/// ```
#[allow(missing_copy_implementations)]
#[derive(Debug)]
pub struct Builder(crate::Bytes);

impl Builder {
    /// Creates a `Builder` using the supplied big-endian bytes.
    ///
    /// # Examples
    ///
    /// Basic usage:
    ///
    /// ```
    /// use uuid::Builder;
    /// use uuid::Bytes;
    ///
    /// let bytes: Bytes = [
    ///     70, 235, 208, 238, 14, 109, 67, 201, 185, 13, 204, 195, 90, 145, 63, 62,
    /// ];
    ///
    /// let mut builder = Builder::from_bytes(bytes);
    /// let uuid = builder.build().to_hyphenated().to_string();
    ///
    /// let expected_uuid = String::from("46ebd0ee-0e6d-43c9-b90d-ccc35a913f3e");
    ///
    /// assert_eq!(expected_uuid, uuid);
    /// ```
    ///
    /// An incorrect number of bytes:
    ///
    /// ```compile_fail
    /// use uuid::Builder;
    /// use uuid::Bytes;
    ///
    /// let bytes: Bytes = [4, 54, 67, 12, 43, 2, 98, 76]; // doesn't compile
    ///
    /// let uuid = Builder::from_bytes(bytes);
    /// ```
    pub const fn from_bytes(b: Bytes) -> Self {
        Builder(b)
    }

    /// Creates a `Builder` using the supplied big-endian bytes.
    ///
    /// # Errors
    ///
    /// This function will return an error if `b` has any length other than 16.
    ///
    /// # Examples
    ///
    /// Basic usage:
    ///
    /// ```
    /// use uuid::Builder;
    ///
    /// let bytes = [4, 54, 67, 12, 43, 2, 98, 76, 32, 50, 87, 5, 1, 33, 43, 87];
    ///
    /// let builder = Builder::from_slice(&bytes);
    /// let uuid =
    ///     builder.map(|mut builder| builder.build().to_hyphenated().to_string());
    ///
    /// let expected_uuid =
    ///     Ok(String::from("0436430c-2b02-624c-2032-570501212b57"));
    ///
    /// assert_eq!(expected_uuid, uuid);
    /// ```
    ///
    /// An incorrect number of bytes:
    ///
    /// ```
    /// use uuid::prelude::*;
    /// use uuid::Builder;
    ///
    /// let bytes = [4, 54, 67, 12, 43, 2, 98, 76];
    ///
    /// let builder = Builder::from_slice(&bytes);
    ///
    /// assert!(builder.is_err());
    /// ```
    pub fn from_slice(b: &[u8]) -> Result<Self, crate::BytesError> {
        const BYTES_LEN: usize = 16;

        let len = b.len();

        if len != BYTES_LEN {
            return Err(crate::BytesError::new(BYTES_LEN, len));
        }

        let mut bytes: crate::Bytes = [0; 16];
        bytes.copy_from_slice(b);
        Ok(Self::from_bytes(bytes))
    }

    /// Creates a `Builder` from four field values.
    ///
    /// # Errors
    ///
    /// This function will return an error if `d4`'s length is not 8 bytes.
    ///
    /// # Examples
    ///
    /// Basic usage:
    ///
    /// ```
    /// use uuid::Builder;
    ///
    /// let d4 = [12, 3, 9, 56, 54, 43, 8, 9];
    ///
    /// let builder = Builder::from_fields(42, 12, 5, &d4);
    /// let uuid =
    ///     builder.map(|mut builder| builder.build().to_hyphenated().to_string());
    ///
    /// let expected_uuid =
    ///     Ok(String::from("0000002a-000c-0005-0c03-0938362b0809"));
    ///
    /// assert_eq!(expected_uuid, uuid);
    /// ```
    ///
    /// An invalid length:
    ///
    /// ```
    /// use uuid::prelude::*;
    ///
    /// let d4 = [12];
    ///
    /// let builder = uuid::Builder::from_fields(42, 12, 5, &d4);
    ///
    /// assert!(builder.is_err());
    /// ```
    pub fn from_fields(
        d1: u32,
        d2: u16,
        d3: u16,
        d4: &[u8],
    ) -> Result<Self, crate::BytesError> {
        crate::Uuid::from_fields(d1, d2, d3, d4).map(|uuid| {
            let bytes = uuid.as_bytes().to_owned();

            Builder::from_bytes(bytes)
        })
    }

    /// Creates a `Builder` with an initial [`Uuid::nil`]
    /// # Examples
    ///
    /// Basic usage:
    ///
    /// ```
    /// use uuid::Builder;
    ///
    /// let mut builder = Builder::nil();
    ///
    /// assert_eq!(
    ///     builder.build().to_hyphenated().to_string(),
    ///     "00000000-0000-0000-0000-000000000000"
    /// );
    /// ```
    pub const fn nil() -> Self {
        Builder([0; 16])
    }

    /// Specifies the variant of the internal [`Uuid`].
    pub fn set_variant(&mut self, v: crate::Variant) -> &mut Self {
        let byte = self.0[8];

        self.0[8] = match v {
            crate::Variant::NCS => byte & 0x7f,
            crate::Variant::RFC4122 => (byte & 0x3f) | 0x80,
            crate::Variant::Microsoft => (byte & 0x1f) | 0xc0,
            crate::Variant::Future => (byte & 0x1f) | 0xe0,
        };

        self
    }

    /// Specifies the version number of the internal [`Uuid`].
    pub fn set_version(&mut self, v: crate::Version) -> &mut Self {
        self.0[6] = (self.0[6] & 0x0f) | ((v as u8) << 4);

        self
    }

    /// Hands over the internal constructed [`Uuid`]
    /// # Examples
    ///
    /// Basic usage:
    ///
    /// ```
    /// use uuid::Builder;
    ///
    /// let uuid = Builder::nil().build();
    ///
    /// assert_eq!(
    ///     uuid.to_hyphenated().to_string(),
    ///     "00000000-0000-0000-0000-000000000000"
    /// );
    /// ```
    pub fn build(&mut self) -> Uuid {
        let uuid = crate::Uuid::from_bytes(self.0);

        uuid
    }
}
<commit_msg>properly dereference the array<commit_after>// Copyright 2013-2014 The Rust Project Developers.
// Copyright 2018 The Uuid Project Developers.
//
// See the COPYRIGHT file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! A Builder type for [`Uuid`]s.
//!
//! [`Uuid`]: ../struct.Uuid.html

use crate::prelude::*;

/// A builder struct for creating a [`Uuid`]
///
/// # Examples
///
/// Creating a v4 `Uuid` from externally generated bytes:
///
/// ```
/// use uuid::{Builder, Variant, Version};
///
/// # let rng = || [
/// #     70, 235, 208, 238, 14, 109, 67, 201, 185, 13, 204, 195, 90,
/// # 145, 63, 62,
/// # ];
/// let random_bytes = rng();
/// let uuid = Builder::from_bytes(random_bytes)
///     .set_variant(Variant::RFC4122)
///     .set_version(Version::Random)
///     .build();
/// ```
#[allow(missing_copy_implementations)]
#[derive(Debug)]
pub struct Builder(crate::Bytes);

impl Builder {
    /// Creates a `Builder` using the supplied big-endian bytes.
    ///
    /// # Examples
    ///
    /// Basic usage:
    ///
    /// ```
    /// use uuid::Builder;
    /// use uuid::Bytes;
    ///
    /// let bytes: Bytes = [
    ///     70, 235, 208, 238, 14, 109, 67, 201, 185, 13, 204, 195, 90, 145, 63, 62,
    /// ];
    ///
    /// let mut builder = Builder::from_bytes(bytes);
    /// let uuid = builder.build().to_hyphenated().to_string();
    ///
    /// let expected_uuid = String::from("46ebd0ee-0e6d-43c9-b90d-ccc35a913f3e");
    ///
    /// assert_eq!(expected_uuid, uuid);
    /// ```
    ///
    /// An incorrect number of bytes:
    ///
    /// ```compile_fail
    /// use uuid::Builder;
    /// use uuid::Bytes;
    ///
    /// let bytes: Bytes = [4, 54, 67, 12, 43, 2, 98, 76]; // doesn't compile
    ///
    /// let uuid = Builder::from_bytes(bytes);
    /// ```
    pub const fn from_bytes(b: Bytes) -> Self {
        Builder(b)
    }

    /// Creates a `Builder` using the supplied big-endian bytes.
    ///
    /// # Errors
    ///
    /// This function will return an error if `b` has any length other than 16.
    ///
    /// # Examples
    ///
    /// Basic usage:
    ///
    /// ```
    /// use uuid::Builder;
    ///
    /// let bytes = [4, 54, 67, 12, 43, 2, 98, 76, 32, 50, 87, 5, 1, 33, 43, 87];
    ///
    /// let builder = Builder::from_slice(&bytes);
    /// let uuid =
    ///     builder.map(|mut builder| builder.build().to_hyphenated().to_string());
    ///
    /// let expected_uuid =
    ///     Ok(String::from("0436430c-2b02-624c-2032-570501212b57"));
    ///
    /// assert_eq!(expected_uuid, uuid);
    /// ```
    ///
    /// An incorrect number of bytes:
    ///
    /// ```
    /// use uuid::prelude::*;
    /// use uuid::Builder;
    ///
    /// let bytes = [4, 54, 67, 12, 43, 2, 98, 76];
    ///
    /// let builder = Builder::from_slice(&bytes);
    ///
    /// assert!(builder.is_err());
    /// ```
    pub fn from_slice(b: &[u8]) -> Result<Self, crate::BytesError> {
        const BYTES_LEN: usize = 16;

        let len = b.len();

        if len != BYTES_LEN {
            return Err(crate::BytesError::new(BYTES_LEN, len));
        }

        let mut bytes: crate::Bytes = [0; 16];
        bytes.copy_from_slice(b);
        Ok(Self::from_bytes(bytes))
    }

    /// Creates a `Builder` from four field values.
    ///
    /// # Errors
    ///
    /// This function will return an error if `d4`'s length is not 8 bytes.
    ///
    /// # Examples
    ///
    /// Basic usage:
    ///
    /// ```
    /// use uuid::Builder;
    ///
    /// let d4 = [12, 3, 9, 56, 54, 43, 8, 9];
    ///
    /// let builder = Builder::from_fields(42, 12, 5, &d4);
    /// let uuid =
    ///     builder.map(|mut builder| builder.build().to_hyphenated().to_string());
    ///
    /// let expected_uuid =
    ///     Ok(String::from("0000002a-000c-0005-0c03-0938362b0809"));
    ///
    /// assert_eq!(expected_uuid, uuid);
    /// ```
    ///
    /// An invalid length:
    ///
    /// ```
    /// use uuid::prelude::*;
    ///
    /// let d4 = [12];
    ///
    /// let builder = uuid::Builder::from_fields(42, 12, 5, &d4);
    ///
    /// assert!(builder.is_err());
    /// ```
    pub fn from_fields(
        d1: u32,
        d2: u16,
        d3: u16,
        d4: &[u8],
    ) -> Result<Self, crate::BytesError> {
        crate::Uuid::from_fields(d1, d2, d3, d4).map(|uuid| {
            let bytes = *uuid.as_bytes();

            Builder::from_bytes(bytes)
        })
    }

    /// Creates a `Builder` with an initial [`Uuid::nil`]
    /// # Examples
    ///
    /// Basic usage:
    ///
    /// ```
    /// use uuid::Builder;
    ///
    /// let mut builder = Builder::nil();
    ///
    /// assert_eq!(
    ///     builder.build().to_hyphenated().to_string(),
    ///     "00000000-0000-0000-0000-000000000000"
    /// );
    /// ```
    pub const fn nil() -> Self {
        Builder([0; 16])
    }

    /// Specifies the variant of the internal [`Uuid`].
    pub fn set_variant(&mut self, v: crate::Variant) -> &mut Self {
        let byte = self.0[8];

        self.0[8] = match v {
            crate::Variant::NCS => byte & 0x7f,
            crate::Variant::RFC4122 => (byte & 0x3f) | 0x80,
            crate::Variant::Microsoft => (byte & 0x1f) | 0xc0,
            crate::Variant::Future => (byte & 0x1f) | 0xe0,
        };

        self
    }

    /// Specifies the version number of the internal [`Uuid`].
    pub fn set_version(&mut self, v: crate::Version) -> &mut Self {
        self.0[6] = (self.0[6] & 0x0f) | ((v as u8) << 4);

        self
    }

    /// Hands over the internal constructed [`Uuid`]
    /// # Examples
    ///
    /// Basic usage:
    ///
    /// ```
    /// use uuid::Builder;
    ///
    /// let uuid = Builder::nil().build();
    ///
    /// assert_eq!(
    ///     uuid.to_hyphenated().to_string(),
    ///     "00000000-0000-0000-0000-000000000000"
    /// );
    /// ```
    pub fn build(&mut self) -> Uuid {
        let uuid = crate::Uuid::from_bytes(self.0);

        uuid
    }
}
<|endoftext|>


<commit_before>//! [PUT /_matrix/federation/v1/send_knock/{roomId}/{eventId}](https://spec.matrix.org/v1.1/server-server-api/#put_matrixfederationv1send_knockroomideventid)

use ruma_api::ruma_api;
use ruma_events::AnyStrippedStateEvent;
use ruma_identifiers::{EventId, RoomId};
use serde_json::value::RawValue as RawJsonValue;

ruma_api! {
    metadata: {
        description: "Submits a signed knock event to the resident homeserver for it to accept into the room's graph.",
        name: "send_knock",
        method: PUT,
        path: "/_matrix/federation/v1/send_knock/:room_id/:event_id",
        rate_limited: false,
        authentication: ServerSignatures,
    }

    request: {
        /// The room ID that should receive the knock.
        #[ruma_api(path)]
        pub room_id: &'a RoomId,

        /// The event ID for the knock event.
        #[ruma_api(path)]
        pub event_id: &'a EventId,

        /// The PDU.
        #[ruma_api(body)]
        pub pdu: &'a RawJsonValue,
    }

    response: {
        /// State events providing public room metadata.
        pub knock_room_state: Vec<AnyStrippedStateEvent>,
    }
}

impl<'a> Request<'a> {
    /// Creates a new `Request` with the given room ID, event ID and knock event.
    pub fn new(room_id: &'a RoomId, event_id: &'a EventId, pdu: &'a RawJsonValue) -> Self {
        Self { room_id, event_id, pdu }
    }
}

impl Response {
    /// Creates a new `Response` with the given public room metadata state events.
    pub fn new(knock_room_state: Vec<AnyStrippedStateEvent>) -> Self {
        Self { knock_room_state }
    }
}
<commit_msg>federation-api: Use Raw for knock_room_state<commit_after>//! [PUT /_matrix/federation/v1/send_knock/{roomId}/{eventId}](https://spec.matrix.org/v1.1/server-server-api/#put_matrixfederationv1send_knockroomideventid)

use ruma_api::ruma_api;
use ruma_events::AnyStrippedStateEvent;
use ruma_identifiers::{EventId, RoomId};
use ruma_serde::Raw;
use serde_json::value::RawValue as RawJsonValue;

ruma_api! {
    metadata: {
        description: "Submits a signed knock event to the resident homeserver for it to accept into the room's graph.",
        name: "send_knock",
        method: PUT,
        path: "/_matrix/federation/v1/send_knock/:room_id/:event_id",
        rate_limited: false,
        authentication: ServerSignatures,
    }

    request: {
        /// The room ID that should receive the knock.
        #[ruma_api(path)]
        pub room_id: &'a RoomId,

        /// The event ID for the knock event.
        #[ruma_api(path)]
        pub event_id: &'a EventId,

        /// The PDU.
        #[ruma_api(body)]
        pub pdu: &'a RawJsonValue,
    }

    response: {
        /// State events providing public room metadata.
        pub knock_room_state: Vec<Raw<AnyStrippedStateEvent>>,
    }
}

impl<'a> Request<'a> {
    /// Creates a new `Request` with the given room ID, event ID and knock event.
    pub fn new(room_id: &'a RoomId, event_id: &'a EventId, pdu: &'a RawJsonValue) -> Self {
        Self { room_id, event_id, pdu }
    }
}

impl Response {
    /// Creates a new `Response` with the given public room metadata state events.
    pub fn new(knock_room_state: Vec<Raw<AnyStrippedStateEvent>>) -> Self {
        Self { knock_room_state }
    }
}
<|endoftext|>