<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.

//! Implements the traits found in [ecma402_traits::numberformat].

use {
    ecma402_traits, rust_icu_common as common, rust_icu_unumberformatter as unumf,
    std::convert::TryInto, std::fmt,
};

#[derive(Debug)]
pub struct NumberFormat {
    // The internal representation of number formatting.
    rep: unumf::UNumberFormatter,
    skeleton: String,
}

pub(crate) mod internal {
    use {
        ecma402_traits::numberformat, ecma402_traits::numberformat::options,
        rust_icu_common as common,
    };

    /// Produces a [skeleton][skel] that corresponds to the given option.
    ///
    /// The conversion may fail if the options are malformed, for example request currency
    /// formatting but do not have a currency defined.
    ///
    /// [skel]: https://github.com/unicode-org/icu/blob/master/docs/userguide/format_parse/numbers/skeletons.md
    pub fn skeleton_from(opts: &numberformat::Options) -> Result<String, common::Error> {
        let mut skel: Vec<String> = vec![];
        if let Some(ref c) = opts.compact_display {
            match c {
                options::CompactDisplay::Long => skel.push("compact-long".into()),
                options::CompactDisplay::Short => skel.push("compact-short".into()),
            }
        }
        match opts.style {
            options::Style::Currency => {
                match opts.currency {
                    None => {
                        return Err(common::Error::Wrapper(anyhow::anyhow!(
                            "currency not specified"
                        )));
                    }
                    Some(ref c) => {
                        skel.push(format!("currency/{}", &c.0));
                    }
                }
                match opts.currency_display {
                    options::CurrencyDisplay::Symbol => {
                        skel.push(format!("unit-width-short"));
                    }
                    options::CurrencyDisplay::NarrowSymbol => {
                        skel.push(format!("unit-width-narrow"));
                    }
                    options::CurrencyDisplay::Code => {
                        skel.push(format!("unit-width-iso-code"));
                    }
                    options::CurrencyDisplay::Name => {
                        skel.push(format!("unit-width-full-name"));
                    }
                }
                match opts.currency_sign {
                    options::CurrencySign::Accounting => {
                        skel.push(format!("sign-accounting"));
                    }
                    options::CurrencySign::Standard => {
                        // No special setup here.
                    }
                }
            }
            options::Style::Unit => match opts.unit {
                None => {
                    return Err(common::Error::Wrapper(anyhow::anyhow!(
                        "unit not specified"
                    )));
                }
                Some(ref u) => {
                    skel.push(format!("measure-unit/{}", &u.0));
                }
            },
            options::Style::Percent => {
                skel.push(format!("percent"));
            }
            options::Style::Decimal => {
                // Default, no special setup needed, apparently.
            }
        }
        match opts.notation {
            options::Notation::Standard => {
                // Nothing is needed here.
            }
            options::Notation::Engineering => match opts.sign_display {
                options::SignDisplay::Auto => {
                    skel.push(format!("scientific/*ee"));
                }
                options::SignDisplay::Always => {
                    skel.push(format!("scientific/*ee/sign-always"));
                }
                options::SignDisplay::Never => {
                    skel.push(format!("scientific/*ee/sign-never"));
                }
                options::SignDisplay::ExceptZero => {
                    skel.push(format!("scientific/*ee/sign-expect-zero"));
                }
            },
            options::Notation::Scientific => {
                skel.push(format!("scientific"));
            }
            options::Notation::Compact => {
                // ?? Is this true?
                skel.push(format!("compact-short"));
            }
        }
        if let Some(ref n) = opts.numbering_system {
            skel.push(format!("numbering-system/{}", &n.0));
        }

        if opts.notation != options::Notation::Engineering {
            match opts.sign_display {
                options::SignDisplay::Auto => {
                    skel.push("sign-auto".into());
                }
                options::SignDisplay::Never => {
                    skel.push("sign-never".into());
                }
                options::SignDisplay::Always => {
                    skel.push("sign-always".into());
                }
                options::SignDisplay::ExceptZero => {
                    skel.push("sign-always".into());
                }
            }
        }

        let minimum_integer_digits = opts.minimum_integer_digits.unwrap_or(1);
        // TODO: this should match the list at:
        // https://www.currency-iso.org/en/home/tables/table-a1.html
        let minimum_fraction_digits = opts.minimum_fraction_digits.unwrap_or(match opts.style {
            options::Style::Currency => 2,
            _ => 0,
        });
        let maximum_fraction_digits = opts.maximum_fraction_digits.unwrap_or(match opts.style {
            options::Style::Currency => std::cmp::max(2, minimum_fraction_digits),
            _ => 3,
        });
        let minimum_significant_digits = opts.minimum_significant_digits.unwrap_or(1);
        let maximum_significant_digits = opts.maximum_significant_digits.unwrap_or(21);

        // TODO: add skeleton items for min and max integer, fraction and significant digits.
        skel.push(integer_digits(minimum_integer_digits as usize));
        skel.push(fraction_digits(
            minimum_fraction_digits as usize,
            maximum_fraction_digits as usize,
            minimum_significant_digits as usize,
            maximum_significant_digits as usize,
        ));

        Ok(skel.iter().map(|s| format!("{} ", s)).collect())
    }

    // Returns the skeleton annotation for integer width
    // 1 -> "integer-width/*0"
    // 3 -> "integer-width/*000"
    fn integer_digits(digits: usize) -> String {
        let zeroes: String = std::iter::repeat("0").take(digits).collect();
        #[cfg(feature = "icu_version_67_plus")]
        return format!("integer-width/*{}", zeroes);
        #[cfg(not(feature = "icu_version_67_plus"))]
        return format!("integer-width/+{}", zeroes);
    }

    fn fraction_digits(min: usize, max: usize, min_sig: usize, max_sig: usize) -> String {
        eprintln!(
            "fraction_digits: min: {}, max: {} min_sig: {}, max_sig: {}",
            min, max, min_sig, max_sig
        );
        assert!(min <= max, "fraction_digits: min: {}, max: {}", min, max);
        let zeroes: String = std::iter::repeat("0").take(min).collect();
        let hashes: String = std::iter::repeat("#").take(max - min).collect();

        assert!(
            min_sig <= max_sig,
            "significant_digits: min: {}, max: {}",
            min_sig,
            max_sig
        );
        let ats: String = std::iter::repeat("@").take(min_sig).collect();
        let hashes_sig: String = std::iter::repeat("#").take(max_sig - min_sig).collect();

        return format!(
            ".{}{}/{}{}",
            zeroes, hashes, ats, hashes_sig,
        );
    }

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

        #[test]
        fn fraction_digits_skeleton_fragment() {
            assert_eq!(fraction_digits(0, 3, 1, 21), ".###/@####################");
            assert_eq!(fraction_digits(2, 2, 1, 21), ".00/@####################");
            assert_eq!(fraction_digits(0, 0, 0, 0), "./");
            assert_eq!(fraction_digits(0, 3, 3, 3), ".###/@@@");
        }
    }
}

impl ecma402_traits::numberformat::NumberFormat for NumberFormat {
    type Error = common::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: ecma402_traits::numberformat::Options) -> Result<Self, Self::Error>
    where
        L: ecma402_traits::Locale,
        Self: Sized,
    {
        let locale = format!("{}", l);
        let skeleton: String = internal::skeleton_from(&opts)?;
        let rep = unumf::UNumberFormatter::try_new(&skeleton, &locale)?;
        Ok(NumberFormat { rep, skeleton })
    }

    /// Formats the plural class of `number` into the supplied `writer`.
    ///
    /// The function implements [`Intl.NumberFormat`][plr] from [ECMA 402][ecma].
    ///
    ///    [plr]: 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,
    {
        let result = self.rep.format_double(number).map_err(|e| e.into())?;
        let result_str: String = result.try_into().map_err(|e: common::Error| e.into())?;
        write!(writer, "{}", result_str)
    }
}

#[cfg(test)]
mod testing {

    use super::*;
    use ecma402_traits::numberformat;
    use ecma402_traits::numberformat::NumberFormat;
    use rust_icu_uloc as uloc;
    use std::convert::TryFrom;

    #[test]
    fn formatting() {
        #[derive(Debug, Clone)]
        struct TestCase {
            locale: &'static str,
            opts: numberformat::Options,
            numbers: Vec<f64>,
            expected: Vec<&'static str>,
        }
        let tests = vec![
            TestCase {
                locale: "sr-RS",
                opts: Default::default(),
                numbers: vec![
                    0.0, 1.0, -1.0, 1.5, -1.5, 100.0, 1000.0, 10000.0, 123456.789,
                ],
                expected: vec![
                    "0",
                    "1",
                    "-1",
                    "1,5",
                    "-1,5",
                    "100",
                    "1.000",
                    "10.000",
                    "123.456,789",
                ],
            },
            TestCase {
                locale: "de-DE",
                opts: numberformat::Options {
                    style: numberformat::options::Style::Currency,
                    currency: Some("EUR".into()),
                    ..Default::default()
                },
                numbers: vec![123456.789],
                expected: vec!["123.456,79\u{a0}€"],
            },
            TestCase {
                locale: "ja-JP",
                opts: numberformat::Options {
                    style: numberformat::options::Style::Currency,
                    currency: Some("JPY".into()),
                    // This is the default for JPY, but we don't consult the
                    // currency list.
                    minimum_fraction_digits: Some(0),
                    maximum_fraction_digits: Some(0),
                    ..Default::default()
                },
                numbers: vec![123456.789],
                expected: vec!["￥123,457"],
            },
            // TODO: This ends up being a syntax error, why?
            //TestCase {
                //locale: "en-IN",
                //opts: numberformat::Options {
                    //maximum_significant_digits: Some(3),
                    //..Default::default()
                //},
                //numbers: vec![123456.789],
                //expected: vec!["1,23,000"],
            //},
        ];
        for test in tests {
            let locale =
                uloc::ULoc::try_from(test.locale).expect(&format!("locale exists: {:?}", &test));
            let format = crate::numberformat::NumberFormat::try_new(locale, test.clone().opts)
                .expect(&format!("try_from should succeed: {:?}", &test));
            let actual = test
                .numbers
                .iter()
                .map(|n| {
                    let mut result = String::new();
                    format
                        .format(*n, &mut result)
                        .expect(&format!("formatting succeeded for: {:?}", &test));
                    result
                })
                .collect::<Vec<String>>();
            assert_eq!(
                test.expected, actual,
                "\n\tfor test case: {:?},\n\tformat: {:?}",
                &test, &format
            );
        }
    }
}
<commit_msg>Remove an unused skeleton<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.

//! Implements the traits found in [ecma402_traits::numberformat].

use {
    ecma402_traits, rust_icu_common as common, rust_icu_unumberformatter as unumf,
    std::convert::TryInto, std::fmt,
};

#[derive(Debug)]
pub struct NumberFormat {
    // The internal representation of number formatting.
    rep: unumf::UNumberFormatter,
}

pub(crate) mod internal {
    use {
        ecma402_traits::numberformat, ecma402_traits::numberformat::options,
        rust_icu_common as common,
    };

    /// Produces a [skeleton][skel] that corresponds to the given option.
    ///
    /// The conversion may fail if the options are malformed, for example request currency
    /// formatting but do not have a currency defined.
    ///
    /// [skel]: https://github.com/unicode-org/icu/blob/master/docs/userguide/format_parse/numbers/skeletons.md
    pub fn skeleton_from(opts: &numberformat::Options) -> Result<String, common::Error> {
        let mut skel: Vec<String> = vec![];
        if let Some(ref c) = opts.compact_display {
            match c {
                options::CompactDisplay::Long => skel.push("compact-long".into()),
                options::CompactDisplay::Short => skel.push("compact-short".into()),
            }
        }
        match opts.style {
            options::Style::Currency => {
                match opts.currency {
                    None => {
                        return Err(common::Error::Wrapper(anyhow::anyhow!(
                            "currency not specified"
                        )));
                    }
                    Some(ref c) => {
                        skel.push(format!("currency/{}", &c.0));
                    }
                }
                match opts.currency_display {
                    options::CurrencyDisplay::Symbol => {
                        skel.push(format!("unit-width-short"));
                    }
                    options::CurrencyDisplay::NarrowSymbol => {
                        skel.push(format!("unit-width-narrow"));
                    }
                    options::CurrencyDisplay::Code => {
                        skel.push(format!("unit-width-iso-code"));
                    }
                    options::CurrencyDisplay::Name => {
                        skel.push(format!("unit-width-full-name"));
                    }
                }
                match opts.currency_sign {
                    options::CurrencySign::Accounting => {
                        skel.push(format!("sign-accounting"));
                    }
                    options::CurrencySign::Standard => {
                        // No special setup here.
                    }
                }
            }
            options::Style::Unit => match opts.unit {
                None => {
                    return Err(common::Error::Wrapper(anyhow::anyhow!(
                        "unit not specified"
                    )));
                }
                Some(ref u) => {
                    skel.push(format!("measure-unit/{}", &u.0));
                }
            },
            options::Style::Percent => {
                skel.push(format!("percent"));
            }
            options::Style::Decimal => {
                // Default, no special setup needed, apparently.
            }
        }
        match opts.notation {
            options::Notation::Standard => {
                // Nothing is needed here.
            }
            options::Notation::Engineering => match opts.sign_display {
                options::SignDisplay::Auto => {
                    skel.push(format!("scientific/*ee"));
                }
                options::SignDisplay::Always => {
                    skel.push(format!("scientific/*ee/sign-always"));
                }
                options::SignDisplay::Never => {
                    skel.push(format!("scientific/*ee/sign-never"));
                }
                options::SignDisplay::ExceptZero => {
                    skel.push(format!("scientific/*ee/sign-expect-zero"));
                }
            },
            options::Notation::Scientific => {
                skel.push(format!("scientific"));
            }
            options::Notation::Compact => {
                // ?? Is this true?
                skel.push(format!("compact-short"));
            }
        }
        if let Some(ref n) = opts.numbering_system {
            skel.push(format!("numbering-system/{}", &n.0));
        }

        if opts.notation != options::Notation::Engineering {
            match opts.sign_display {
                options::SignDisplay::Auto => {
                    skel.push("sign-auto".into());
                }
                options::SignDisplay::Never => {
                    skel.push("sign-never".into());
                }
                options::SignDisplay::Always => {
                    skel.push("sign-always".into());
                }
                options::SignDisplay::ExceptZero => {
                    skel.push("sign-always".into());
                }
            }
        }

        let minimum_integer_digits = opts.minimum_integer_digits.unwrap_or(1);
        // TODO: this should match the list at:
        // https://www.currency-iso.org/en/home/tables/table-a1.html
        let minimum_fraction_digits = opts.minimum_fraction_digits.unwrap_or(match opts.style {
            options::Style::Currency => 2,
            _ => 0,
        });
        let maximum_fraction_digits = opts.maximum_fraction_digits.unwrap_or(match opts.style {
            options::Style::Currency => std::cmp::max(2, minimum_fraction_digits),
            _ => 3,
        });
        let minimum_significant_digits = opts.minimum_significant_digits.unwrap_or(1);
        let maximum_significant_digits = opts.maximum_significant_digits.unwrap_or(21);

        // TODO: add skeleton items for min and max integer, fraction and significant digits.
        skel.push(integer_digits(minimum_integer_digits as usize));
        skel.push(fraction_digits(
            minimum_fraction_digits as usize,
            maximum_fraction_digits as usize,
            minimum_significant_digits as usize,
            maximum_significant_digits as usize,
        ));

        Ok(skel.iter().map(|s| format!("{} ", s)).collect())
    }

    // Returns the skeleton annotation for integer width
    // 1 -> "integer-width/*0"
    // 3 -> "integer-width/*000"
    fn integer_digits(digits: usize) -> String {
        let zeroes: String = std::iter::repeat("0").take(digits).collect();
        #[cfg(feature = "icu_version_67_plus")]
        return format!("integer-width/*{}", zeroes);
        #[cfg(not(feature = "icu_version_67_plus"))]
        return format!("integer-width/+{}", zeroes);
    }

    fn fraction_digits(min: usize, max: usize, min_sig: usize, max_sig: usize) -> String {
        eprintln!(
            "fraction_digits: min: {}, max: {} min_sig: {}, max_sig: {}",
            min, max, min_sig, max_sig
        );
        assert!(min <= max, "fraction_digits: min: {}, max: {}", min, max);
        let zeroes: String = std::iter::repeat("0").take(min).collect();
        let hashes: String = std::iter::repeat("#").take(max - min).collect();

        assert!(
            min_sig <= max_sig,
            "significant_digits: min: {}, max: {}",
            min_sig,
            max_sig
        );
        let ats: String = std::iter::repeat("@").take(min_sig).collect();
        let hashes_sig: String = std::iter::repeat("#").take(max_sig - min_sig).collect();

        return format!(
            ".{}{}/{}{}",
            zeroes, hashes, ats, hashes_sig,
        );
    }

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

        #[test]
        fn fraction_digits_skeleton_fragment() {
            assert_eq!(fraction_digits(0, 3, 1, 21), ".###/@####################");
            assert_eq!(fraction_digits(2, 2, 1, 21), ".00/@####################");
            assert_eq!(fraction_digits(0, 0, 0, 0), "./");
            assert_eq!(fraction_digits(0, 3, 3, 3), ".###/@@@");
        }
    }
}

impl ecma402_traits::numberformat::NumberFormat for NumberFormat {
    type Error = common::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: ecma402_traits::numberformat::Options) -> Result<Self, Self::Error>
    where
        L: ecma402_traits::Locale,
        Self: Sized,
    {
        let locale = format!("{}", l);
        let skeleton: String = internal::skeleton_from(&opts)?;
        let rep = unumf::UNumberFormatter::try_new(&skeleton, &locale)?;
        Ok(NumberFormat { rep })
    }

    /// Formats the plural class of `number` into the supplied `writer`.
    ///
    /// The function implements [`Intl.NumberFormat`][plr] from [ECMA 402][ecma].
    ///
    ///    [plr]: 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,
    {
        let result = self.rep.format_double(number).map_err(|e| e.into())?;
        let result_str: String = result.try_into().map_err(|e: common::Error| e.into())?;
        write!(writer, "{}", result_str)
    }
}

#[cfg(test)]
mod testing {

    use super::*;
    use ecma402_traits::numberformat;
    use ecma402_traits::numberformat::NumberFormat;
    use rust_icu_uloc as uloc;
    use std::convert::TryFrom;

    #[test]
    fn formatting() {
        #[derive(Debug, Clone)]
        struct TestCase {
            locale: &'static str,
            opts: numberformat::Options,
            numbers: Vec<f64>,
            expected: Vec<&'static str>,
        }
        let tests = vec![
            TestCase {
                locale: "sr-RS",
                opts: Default::default(),
                numbers: vec![
                    0.0, 1.0, -1.0, 1.5, -1.5, 100.0, 1000.0, 10000.0, 123456.789,
                ],
                expected: vec![
                    "0",
                    "1",
                    "-1",
                    "1,5",
                    "-1,5",
                    "100",
                    "1.000",
                    "10.000",
                    "123.456,789",
                ],
            },
            TestCase {
                locale: "de-DE",
                opts: numberformat::Options {
                    style: numberformat::options::Style::Currency,
                    currency: Some("EUR".into()),
                    ..Default::default()
                },
                numbers: vec![123456.789],
                expected: vec!["123.456,79\u{a0}€"],
            },
            TestCase {
                locale: "ja-JP",
                opts: numberformat::Options {
                    style: numberformat::options::Style::Currency,
                    currency: Some("JPY".into()),
                    // This is the default for JPY, but we don't consult the
                    // currency list.
                    minimum_fraction_digits: Some(0),
                    maximum_fraction_digits: Some(0),
                    ..Default::default()
                },
                numbers: vec![123456.789],
                expected: vec!["￥123,457"],
            },
            // TODO: This ends up being a syntax error, why?
            //TestCase {
                //locale: "en-IN",
                //opts: numberformat::Options {
                    //maximum_significant_digits: Some(3),
                    //..Default::default()
                //},
                //numbers: vec![123456.789],
                //expected: vec!["1,23,000"],
            //},
        ];
        for test in tests {
            let locale =
                uloc::ULoc::try_from(test.locale).expect(&format!("locale exists: {:?}", &test));
            let format = crate::numberformat::NumberFormat::try_new(locale, test.clone().opts)
                .expect(&format!("try_from should succeed: {:?}", &test));
            let actual = test
                .numbers
                .iter()
                .map(|n| {
                    let mut result = String::new();
                    format
                        .format(*n, &mut result)
                        .expect(&format!("formatting succeeded for: {:?}", &test));
                    result
                })
                .collect::<Vec<String>>();
            assert_eq!(
                test.expected, actual,
                "\n\tfor test case: {:?},\n\tformat: {:?}",
                &test, &format
            );
        }
    }
}
<|endoftext|>


<commit_before>use super::{Index, Range};
use small;
use std::{cmp::Ordering, u8};

fn numeric_range<'a>(
    start: isize,
    end: isize,
    step: isize,
    inclusive: bool,
    nb_digits: usize,
) -> Option<Box<Iterator<Item = small::String> + 'a>> {
    let end = if start < end && inclusive {
        end + 1
    } else if start > end && inclusive {
        end - 1
    } else {
        end
    };

    if step == 0 || (start < end && step < 0) || (start > end && step > 0) {
        None
    } else {
        let (x, y, ordering) = if start < end {
            (start, end, Ordering::Greater)
        } else {
            (end, start, Ordering::Less)
        };

        let iter = (x..y).scan(start, move |index, _| {
            if end.cmp(index) == ordering {
                let index_holder = *index;
                *index += step; // This step adds
                Some(format!("{:0width$}", index_holder, width = nb_digits).into())
            } else {
                None
            }
        });

        Some(Box::new(iter))
    }
}

#[inline]
fn byte_is_valid_range(b: u8) -> bool { (b >= b'a' && b <= b'z') || (b >= b'A' && b <= b'Z') }

fn char_range<'a>(
    start: u8,
    end: u8,
    step: isize,
    inclusive: bool,
) -> Option<Box<Iterator<Item = small::String> + 'a>> {
    let char_step = step.checked_abs()?;
    if !byte_is_valid_range(start) || !byte_is_valid_range(end) || step == 0 || char_step > u8::MAX as isize {
        return None;
    }

    let end = if start < end && inclusive {
        end + 1
    } else if start > end && inclusive {
        end - 1
    } else {
        end
    };
    let (x, y, ordering) = if start < end {
        (start, end, Ordering::Greater)
    } else {
        (end, start, Ordering::Less)
    };

    let iter = (x..y).scan(start, move |index, _| {
        if end.cmp(index) == ordering {
            let index_holder = *index;
            *index = match ordering {
                Ordering::Greater => index.wrapping_add(char_step as u8),
                Ordering::Less => index.wrapping_sub(char_step as u8),
                _ => unreachable!(),
            };
            Some((index_holder as char).to_string().into())
        } else {
            None
        }
    });

    Some(Box::new(iter))
}

fn count_minimum_digits(a: &str) -> usize {
    for c in a.chars() {
        match c {
            '-' => (),
            '0' => return a.len(),
            '1'...'9' => break,
            _ => panic!("count_minimum_digits should only be called for a valid number."),
        }
    }
    0
}

fn finish(inclusive: bool, start_str: &str, end_str: &str, step: isize) -> Option<Box<Iterator<Item = small::String>>> {
    if let (Ok(start), Ok(end)) = (start_str.parse::<isize>(), end_str.parse::<isize>())  {
        let step = if step == 1 {
            if start < end { step } else { -step }
        } else {
            step
        };
        let nb_digits = usize::max(count_minimum_digits(start_str), count_minimum_digits(end_str));
        numeric_range(start, end, step, inclusive, nb_digits)
    } else {
        char_range(start_str.bytes().next()?, end_str.bytes().next()?, step, inclusive)
    }
}

// TODO: Make this an iterator structure.
// In a range we allow the following syntax:
//      Exclusive nonstepped: {start..end}
//      Inclusive nonstepped: {start...end}
//      Exclusive stepped: {start..step..end}
//      Inclusive stepped: {start..step...end}
pub fn parse_range(input: &str) -> Option<Box<Iterator<Item = small::String>>> {
    let mut bytes_iterator = input.bytes().enumerate();
    let separator = bytes_iterator.by_ref().take_while(|&(i, b)| match b {
        b'a'...b'z' | b'-' | b'A'...b'Z' if i == 0 => true,
        b'0'...b'9' | b'.' => true,
        _ => false,
    }).position(|(_, b)| b == b'.')?;
    let start_str = &input[..separator];
    // The next byte has to be a dot to be valid range
    // syntax
    bytes_iterator.next().filter(|&(_, b)| b == b'.')?;

    // if the next byte is a dot we're certain it is an inclusive
    // unstepped range otherwise it has to be [-0-9a-zA-Z]
    bytes_iterator.next().and_then(|(start, b)| match b {
        b'.' | b'=' => {
            // this can only be an inclusive range
            finish(true, start_str, &input[start + 1..], 1)
        }
        b'0'...b'9' | b'-' | b'a'...b'z' | b'A'...b'Z' => {
            // further processing needed to find out if we're reading a step or
            // the end of an exclusive range. Step until we find another dot or
            // the iterator ends
            if let Some(end) = bytes_iterator.position(|(_, b)| b == b'.') {
                // stepped range input[start..read - 1] contains the step
                // size
                let step = (&input[start..=start + end]).parse::<isize>().ok()?;
                // count the dots to determine inclusive/exclusive
                let dots = bytes_iterator.take_while(|&(_, b)| b == b'.').count() + 1;
                finish(dots == 3, start_str, &input[start + end + dots + 1..], step)
            } else {
                // exhausted the iterator without finding anything new means
                // exclusive unstepped range
                finish(false, start_str, &input[start..], 1)
            }
        }
        // not a valid byte for ranges
        _ => None,
    })
}

pub fn parse_index_range(input: &str) -> Option<Range> {
    let mut bytes_iterator = input.bytes().enumerate();
    while let Some((id, byte)) = bytes_iterator.next() {
        match byte {
            b'0'...b'9' | b'-' => continue,
            b'.' => {
                let first = &input[..id];

                let mut dots = 1;
                let mut last_byte = 0;

                for (_, byte) in bytes_iterator {
                    last_byte = byte;
                    if byte == b'.' {
                        dots += 1
                    } else {
                        break;
                    }
                }

                if dots < 2 || dots > 3 {
                    break;
                }

                let inclusive = dots == 3 || (dots == 2 && last_byte == b'=');

                let end = &input[id + if inclusive { 3 } else { 2 }..];

                return if first.is_empty() && !end.is_empty() {
                    end.parse::<isize>().map(|end| Range::to(Index::new(end))).ok()
                } else if end.is_empty() {
                    first.parse::<isize>().map(|start| Range::from(Index::new(start))).ok()
                } else {
                    first
                        .parse::<isize>()
                        .and_then(|start| end.parse::<isize>().map(|end| (start, end)))
                        .map(|(start, end)| {
                            if inclusive {
                                Range::inclusive(Index::new(start), Index::new(end))
                            } else {
                                Range::exclusive(Index::new(start), Index::new(end))
                            }
                        })
                        .ok()
                };

            }
            _ => break,
        }
    }

    None
}
<commit_msg>Use native string functions for range parsing<commit_after>use super::{Index, Range};
use small;
use std::{cmp::Ordering, u8};

fn numeric_range<'a>(
    start: isize,
    end: isize,
    step: isize,
    inclusive: bool,
    nb_digits: usize,
) -> Option<Box<Iterator<Item = small::String> + 'a>> {
    let end = if start < end && inclusive {
        end + 1
    } else if start > end && inclusive {
        end - 1
    } else {
        end
    };

    if step == 0 || (start < end && step < 0) || (start > end && step > 0) {
        None
    } else {
        let (x, y, ordering) = if start < end {
            (start, end, Ordering::Greater)
        } else {
            (end, start, Ordering::Less)
        };

        let iter = (x..y).scan(start, move |index, _| {
            if end.cmp(index) == ordering {
                let index_holder = *index;
                *index += step; // This step adds
                Some(format!("{:0width$}", index_holder, width = nb_digits).into())
            } else {
                None
            }
        });

        Some(Box::new(iter))
    }
}

#[inline]
fn byte_is_valid_range(b: u8) -> bool { (b >= b'a' && b <= b'z') || (b >= b'A' && b <= b'Z') }

fn char_range<'a>(
    start: u8,
    end: u8,
    step: isize,
    inclusive: bool,
) -> Option<Box<Iterator<Item = small::String> + 'a>> {
    let char_step = step.checked_abs()?;
    if !byte_is_valid_range(start) || !byte_is_valid_range(end) || step == 0 || char_step > u8::MAX as isize {
        return None;
    }

    let end = if start < end && inclusive {
        end + 1
    } else if start > end && inclusive {
        end - 1
    } else {
        end
    };
    let (x, y, ordering) = if start < end {
        (start, end, Ordering::Greater)
    } else {
        (end, start, Ordering::Less)
    };

    let iter = (x..y).scan(start, move |index, _| {
        if end.cmp(index) == ordering {
            let index_holder = *index;
            *index = match ordering {
                Ordering::Greater => index.wrapping_add(char_step as u8),
                Ordering::Less => index.wrapping_sub(char_step as u8),
                _ => unreachable!(),
            };
            Some((index_holder as char).to_string().into())
        } else {
            None
        }
    });

    Some(Box::new(iter))
}

fn count_minimum_digits(a: &str) -> usize {
    for c in a.chars() {
        match c {
            '-' => (),
            '0' => return a.len(),
            '1'...'9' => break,
            _ => panic!("count_minimum_digits should only be called for a valid number."),
        }
    }
    0
}

fn finish(inclusive: bool, start_str: &str, end_str: &str, step: isize) -> Option<Box<Iterator<Item = small::String>>> {
    if let (Ok(start), Ok(end)) = (start_str.parse::<isize>(), end_str.parse::<isize>())  {
        let step = if step == 1 && start >= end { -step } else { step };
        let nb_digits = usize::max(count_minimum_digits(start_str), count_minimum_digits(end_str));
        numeric_range(start, end, step, inclusive, nb_digits)
    } else {
        if start_str.len() != 1 || end_str.len() != 1 {
            None
        } else {
            char_range(start_str.as_bytes()[0], end_str.as_bytes()[0], step, inclusive)
        }
    }
}

// TODO: Make this an iterator structure.
// In a range we allow the following syntax:
//      Exclusive nonstepped: {start..end}
//      Inclusive nonstepped: {start...end}
//      Exclusive stepped: {start..step..end}
//      Inclusive stepped: {start..step...end}
pub fn parse_range(input: &str) -> Option<Box<Iterator<Item = small::String>>> {
    let mut parts = input.split("..").collect::<Vec<_>>();
    let len = parts.len();

    // if the last separator contains three dots, this can only be an inclusive range
    let inclusive = parts.last()?.starts_with(|c| c == '.' || c == '=');
    if inclusive {
        parts[len - 1] = parts[len - 1].trim_start_matches(|c| c == '.' || c == '=');
    }

    match len {
        // two parts means unstepped range
        2 => finish(inclusive, parts[0], parts[1], 1),
        // middle string contains the step size
        3 => finish(inclusive, parts[0], parts[2], parts[1].parse::<isize>().ok()?),
        // not a valid byte for ranges
        _ => None,
    }
}

pub fn parse_index_range(input: &str) -> Option<Range> {
    let mut bytes_iterator = input.bytes().enumerate();
    while let Some((id, byte)) = bytes_iterator.next() {
        match byte {
            b'0'...b'9' | b'-' => continue,
            b'.' => {
                let first = &input[..id];

                let mut dots = 1;
                let mut last_byte = 0;

                for (_, byte) in bytes_iterator {
                    last_byte = byte;
                    if byte == b'.' {
                        dots += 1
                    } else {
                        break;
                    }
                }

                if dots < 2 || dots > 3 {
                    break;
                }

                let inclusive = dots == 3 || (dots == 2 && last_byte == b'=');

                let end = &input[id + if inclusive { 3 } else { 2 }..];

                return if first.is_empty() && !end.is_empty() {
                    end.parse::<isize>().map(|end| Range::to(Index::new(end))).ok()
                } else if end.is_empty() {
                    first.parse::<isize>().map(|start| Range::from(Index::new(start))).ok()
                } else {
                    first
                        .parse::<isize>()
                        .and_then(|start| end.parse::<isize>().map(|end| (start, end)))
                        .map(|(start, end)| {
                            if inclusive {
                                Range::inclusive(Index::new(start), Index::new(end))
                            } else {
                                Range::exclusive(Index::new(start), Index::new(end))
                            }
                        })
                        .ok()
                };

            }
            _ => break,
        }
    }

    None
}
<|endoftext|>


<commit_before>#![feature(tool_lints)]

#![warn(clippy::all,clippy::similar_names)]
#![allow(unused, clippy::println_empty_string)]

struct Foo {
    apple: i32,
    bpple: i32,
}

fn main() {
    let specter: i32;
    let spectre: i32;

    let apple: i32;

    let bpple: i32;

    let cpple: i32;

    let a_bar: i32;
    let b_bar: i32;
    let c_bar: i32;

    let items = [5];
    for item in &items {
        loop {}
    }

    let foo_x: i32;
    let foo_y: i32;

    let rhs: i32;
    let lhs: i32;

    let bla_rhs: i32;
    let bla_lhs: i32;

    let blubrhs: i32;
    let blublhs: i32;

    let blubx: i32;
    let bluby: i32;

    let cake: i32;
    let cakes: i32;
    let coke: i32;

    match 5 {
        cheese @ 1 => {},
        rabbit => panic!(),
    }
    let cheese: i32;
    match (42, 43) {
        (cheese1, 1) => {},
        (cheese2, 2) => panic!(),
        _ => println!(""),
    }
    let ipv4: i32;
    let ipv6: i32;
    let abcd1: i32;
    let abdc2: i32;
    let xyz1abc: i32;
    let xyz2abc: i32;
    let xyzeabc: i32;

    let parser: i32;
    let parsed: i32;
    let parsee: i32;

    let setter: i32;
    let getter: i32;
    let tx1: i32;
    let rx1: i32;
    let tx_cake: i32;
    let rx_cake: i32;
}

fn foo() {
    let Foo { apple, bpple } = unimplemented!();
    let Foo { apple: spring,
        bpple: sprang } = unimplemented!();
}

#[derive(Clone, Debug)]
enum MaybeInst {
    Split,
    Split1(usize),
    Split2(usize),
}

struct InstSplit {
    uiae: usize,
}

impl MaybeInst {
    fn fill(&mut self) {
        let filled = match *self {
            MaybeInst::Split1(goto1) => panic!(1),
            MaybeInst::Split2(goto2) => panic!(2),
            _ => unimplemented!(),
        };
        unimplemented!()
    }
}

fn bla() {
    let a: i32;
    let (b, c, d): (i32, i64, i16);
    {
        {
            let cdefg: i32;
            let blar: i32;
        }
        {
            let e: i32;
        }
        {
            let e: i32;
            let f: i32;

        }
        match 5 {
            1 => println!(""),
            e => panic!(),
        }
        match 5 {
            1 => println!(""),
            _ => panic!(),
        }
    }
}

fn underscores_and_numbers() {
    let _1 = 1; //~ERROR Consider a more descriptive name
    let ____1 = 1; //~ERROR Consider a more descriptive name
    let __1___2 = 12; //~ERROR Consider a more descriptive name
    let _1_ok= 1;
}

fn issue2927() {
  let args = 1;
  format!("{:?}", 2);
}

fn issue3078() {
    match "a" {
        stringify!(a) => {},
        _ => {}
    }
}

struct Bar;

impl Bar {
    fn bar() {
        let _1 = 1;
        let ____1 = 1;
        let __1___2 = 12;
        let _1_ok= 1;
    }
}
<commit_msg>add tests for #3057 and #2651<commit_after>#![feature(tool_lints)]

#![warn(clippy::all,clippy::similar_names)]
#![allow(unused, clippy::println_empty_string)]

struct Foo {
    apple: i32,
    bpple: i32,
}

fn main() {
    let specter: i32;
    let spectre: i32;

    let apple: i32;

    let bpple: i32;

    let cpple: i32;

    let a_bar: i32;
    let b_bar: i32;
    let c_bar: i32;

    let items = [5];
    for item in &items {
        loop {}
    }

    let foo_x: i32;
    let foo_y: i32;

    let rhs: i32;
    let lhs: i32;

    let bla_rhs: i32;
    let bla_lhs: i32;

    let blubrhs: i32;
    let blublhs: i32;

    let blubx: i32;
    let bluby: i32;

    let cake: i32;
    let cakes: i32;
    let coke: i32;

    match 5 {
        cheese @ 1 => {},
        rabbit => panic!(),
    }
    let cheese: i32;
    match (42, 43) {
        (cheese1, 1) => {},
        (cheese2, 2) => panic!(),
        _ => println!(""),
    }
    let ipv4: i32;
    let ipv6: i32;
    let abcd1: i32;
    let abdc2: i32;
    let xyz1abc: i32;
    let xyz2abc: i32;
    let xyzeabc: i32;

    let parser: i32;
    let parsed: i32;
    let parsee: i32;

    let setter: i32;
    let getter: i32;
    let tx1: i32;
    let rx1: i32;
    let tx_cake: i32;
    let rx_cake: i32;
}

fn foo() {
    let Foo { apple, bpple } = unimplemented!();
    let Foo { apple: spring,
        bpple: sprang } = unimplemented!();
}

#[derive(Clone, Debug)]
enum MaybeInst {
    Split,
    Split1(usize),
    Split2(usize),
}

struct InstSplit {
    uiae: usize,
}

impl MaybeInst {
    fn fill(&mut self) {
        let filled = match *self {
            MaybeInst::Split1(goto1) => panic!(1),
            MaybeInst::Split2(goto2) => panic!(2),
            _ => unimplemented!(),
        };
        unimplemented!()
    }
}

fn bla() {
    let a: i32;
    let (b, c, d): (i32, i64, i16);
    {
        {
            let cdefg: i32;
            let blar: i32;
        }
        {
            let e: i32;
        }
        {
            let e: i32;
            let f: i32;

        }
        match 5 {
            1 => println!(""),
            e => panic!(),
        }
        match 5 {
            1 => println!(""),
            _ => panic!(),
        }
    }
}

fn underscores_and_numbers() {
    let _1 = 1; //~ERROR Consider a more descriptive name
    let ____1 = 1; //~ERROR Consider a more descriptive name
    let __1___2 = 12; //~ERROR Consider a more descriptive name
    let _1_ok= 1;
}

fn issue2927() {
  let args = 1;
  format!("{:?}", 2);
}

fn issue3078() {
    match "a" {
        stringify!(a) => {},
        _ => {}
    }
}

struct Bar;

impl Bar {
    fn bar() {
        let _1 = 1;
        let ____1 = 1;
        let __1___2 = 12;
        let _1_ok= 1;
    }
}

// false positive similar_names (#3057, #2651)
// clippy claimed total_reg_src_size and total_size and
// numb_reg_src_checkouts and total_bin_size were similar
#[derive(Debug, Clone)]
pub(crate) struct DirSizes {
    pub(crate) total_size: u64,
    pub(crate) numb_bins: u64,
    pub(crate) total_bin_size: u64,
    pub(crate) total_reg_size: u64,
    pub(crate) total_git_db_size: u64,
    pub(crate) total_git_repos_bare_size: u64,
    pub(crate) numb_git_repos_bare_repos: u64,
    pub(crate) numb_git_checkouts: u64,
    pub(crate) total_git_chk_size: u64,
    pub(crate) total_reg_cache_size: u64,
    pub(crate) total_reg_src_size: u64,
    pub(crate) numb_reg_cache_entries: u64,
    pub(crate) numb_reg_src_checkouts: u64,
}
<|endoftext|>


<commit_before>#![feature(core)]

extern crate algorithmia;
extern crate getopts;

use algorithmia::{Service};
use getopts::Options;
use std::ascii::AsciiExt;
use std::env;
use std::fs::File;
use std::thread;

fn print_usage(opts: &Options) {
    let brief = vec![
        "Usage: algodata USER/COLLECTION [CMD [CMD_ARGS...]]",
        "Supported CMDs",
        "  CREATE",
        "  UPLOAD FILE..."
    ];
    println!("{}", opts.usage(&*brief.connect("\n")));
    env::set_exit_status(1);
}

struct AlgoData {
    service: Service,
}

impl AlgoData {
    fn new(api_key: &str) -> AlgoData {
        AlgoData { service: Service::new(api_key) }
    }

    fn show_collection(self, username: &str, collection_name: &str) {
        let mut my_bucket = self.service.collection(username, collection_name);
        match my_bucket.show() {
            Ok(output) => println!("{:?}", output),
            Err(why) => println!("ERROR: {:?}", why),
        };
    }

    fn create_collection(self, username: &str, collection_name: &str) {
        let mut my_bucket = self.service.collection(username, collection_name);
        match my_bucket.create() {
            Ok(output) => println!("{:?}", output),
            Err(why) => println!("ERROR: {:?}", why),
        };
    }

    fn upload_files(self, username: &str, collection_name: &str, file_paths: &[String]) {
        println!("Uploading {} file(s)...", file_paths.len());

        let _: Vec<_> = file_paths.iter().map(|file_path| {
            // println!("Uploading {}", file_path);
            let service = self.service.clone();
            thread::scoped( move || {
                let mut my_bucket = service.collection(username, collection_name);
                match File::open(file_path) {
                    Ok(mut file) => {
                        let ref mut bucket = my_bucket;
                        match bucket.upload_file(&mut file) {
                            Ok(file_added) => println!("Uploaded {}", file_added.result),
                            Err(e) => println!("ERROR uploading {}: {:?}", file_path, e),
                        };
                    },
                    Err(e) => println!("Failed to open {}: {}", file_path, e),
                };
            })
        }).collect();
        println!("Finished uploading {} file(s)", file_paths.len())
    }
}

fn main() {
    let mut opts = Options::new();
    opts.optflag("h", "help", "print this help");

    let argopts = match opts.parse(env::args()) {
        Ok(m) => m,
        Err(f) => {
            println!("Failed to parse args: {}", f);
            print_usage(&opts);
            return;
        }
    };

    let mut args_iter = argopts.free.clone().into_iter().skip(1);
    if argopts.opt_present("help") || args_iter.len() == 0 {
        print_usage(&opts);
        return;
    }

    let api_key = match env::var("ALGORITHMIA_API_KEY") {
        Ok(val) => val,
        Err(_) => {
            println!("Must set ALGORITHMIA_API_KEY");
            print_usage(&opts);
            return;
        }
    };

    let data = AlgoData::new(&*api_key);

    // Get the USERNAME/COLLECTION arg
    let first_arg = args_iter.next();
    let user_collection: Vec<&str> = match first_arg {
        Some(ref arg) => arg.split('/').collect(),
        None => {
            println!("Did not specify USERNAME/COLLECTION");
            print_usage(&opts);
            return;
        }
    };

    // Get the CMD arg
    let cmd = match args_iter.next() {
        Some(ref arg) => arg.to_ascii_lowercase(),
        None => "show".to_string(),
    };

    match user_collection.as_slice() {
        [user, collection] => {
            match cmd.as_slice() {
                "show" => data.show_collection(user, collection),
                "create" => data.create_collection(user, collection),
                "upload" => {
                    let files: Vec<String> = args_iter.collect();
                    data.upload_files(user, collection, files.as_slice());
                },
                invalid => {
                    println!("Not a valid command: {}", invalid);
                    print_usage(&opts);
                    return;
                }
            }
        },
        invalid => {
            println!("Invalid data repository: {:?}", invalid );
            print_usage(&opts);
            return;
        }
    }
}<commit_msg>Configurable upload concurrency<commit_after>#![feature(core)]
#![feature(std_misc)]

extern crate algorithmia;
extern crate getopts;

use algorithmia::{Service};
use getopts::Options;
use std::ascii::AsciiExt;
use std::env;
use std::fs::File;
use std::thread;
use std::sync::{Arc, Semaphore};

static DEFAULT_UPLOAD_CONCURRENCY: u32 = 8;

fn print_usage(opts: &Options) {
    let brief = vec![
        "Usage: algodata USER/COLLECTION [CMD [CMD_ARGS...]]",
        "Supported CMDs",
        "  CREATE",
        "  UPLOAD FILE..."
    ];
    println!("{}", opts.usage(&*brief.connect("\n")));
    env::set_exit_status(1);
}

struct AlgoData {
    service: Service,
}

impl AlgoData {
    fn new(api_key: &str) -> AlgoData {
        AlgoData { service: Service::new(api_key) }
    }

    fn show_collection(self, username: &str, collection_name: &str) {
        let mut my_bucket = self.service.collection(username, collection_name);
        match my_bucket.show() {
            Ok(output) => println!("{:?}", output),
            Err(why) => println!("ERROR: {:?}", why),
        };
    }

    fn create_collection(self, username: &str, collection_name: &str) {
        let mut my_bucket = self.service.collection(username, collection_name);
        match my_bucket.create() {
            Ok(output) => println!("{:?}", output),
            Err(why) => println!("ERROR: {:?}", why),
        };
    }

    fn upload_files(self, username: &str, collection_name: &str, file_paths: &[String], concurrency: u32) {
        println!("Uploading {} file(s)...", file_paths.len());
        let arc_sem = Arc::new(Semaphore::new(concurrency as isize));

        let _: Vec<_> = file_paths.iter().map(|file_path| {
            // Acquire semaphore before we start the thread
            let child_sem = arc_sem.clone();
            child_sem.acquire();
            // println!("Uploading {}", file_path);

            let service = self.service.clone();
            thread::scoped( move || {
                let mut my_bucket = service.collection(username, collection_name);
                match File::open(file_path) {
                    Ok(mut file) => {
                        let ref mut bucket = my_bucket;
                        match bucket.upload_file(&mut file) {
                            Ok(file_added) => println!("Uploaded {}", file_added.result),
                            Err(e) => println!("ERROR uploading {}: {:?}", file_path, e),
                        };
                    },
                    Err(e) => {
                        println!("Failed to open {}: {}", file_path, e);
                    }
                };

                // Release the semaphore
                child_sem.release();
            })
        }).collect();
        println!("Finished uploading {} file(s)", file_paths.len())
    }
}

fn main() {
    let mut opts = Options::new();
    opts.optflag("h", "help", "print this help");
    opts.optopt("c", "concurrency", &*format!("max concurrent threads to use for uploading files (default = {})", DEFAULT_UPLOAD_CONCURRENCY), "THREADS");

    let argopts = match opts.parse(env::args()) {
        Ok(m) => m,
        Err(f) => {
            println!("Failed to parse args: {}", f);
            print_usage(&opts);
            return;
        }
    };

    let mut args_iter = argopts.free.clone().into_iter().skip(1);
    if argopts.opt_present("help") || args_iter.len() == 0 {
        print_usage(&opts);
        return;
    }

    let api_key = match env::var("ALGORITHMIA_API_KEY") {
        Ok(val) => val,
        Err(_) => {
            println!("Must set ALGORITHMIA_API_KEY");
            print_usage(&opts);
            return;
        }
    };

    // Get the --concurrency
    let concurrency: u32 = match argopts.opt_str("concurrency") {
        Some(nstr) => {
            match nstr.parse::<u32>() {
                Ok(n) => n,
                Err(_) => {
                    println!("Invalid concurrency option: {}", nstr);
                    print_usage(&opts);
                    return;
                }
            }
        },
        None => DEFAULT_UPLOAD_CONCURRENCY,
    };

    let data = AlgoData::new(&*api_key);

    // Get the USERNAME/COLLECTION arg
    let first_arg = args_iter.next();
    let user_collection: Vec<&str> = match first_arg {
        Some(ref arg) => arg.split('/').collect(),
        None => {
            println!("Did not specify USERNAME/COLLECTION");
            print_usage(&opts);
            return;
        }
    };

    // Get the CMD arg
    let cmd = match args_iter.next() {
        Some(ref arg) => arg.to_ascii_lowercase(),
        None => "show".to_string(),
    };

    match user_collection.as_slice() {
        [user, collection] => {
            match cmd.as_slice() {
                "show" => data.show_collection(user, collection),
                "create" => data.create_collection(user, collection),
                "upload" => {
                    let files: Vec<String> = args_iter.collect();
                    data.upload_files(user, collection, files.as_slice(), concurrency);
                },
                invalid => {
                    println!("Not a valid command: {}", invalid);
                    print_usage(&opts);
                    return;
                }
            }
        },
        invalid => {
            println!("Invalid data repository: {:?}", invalid );
            print_usage(&opts);
            return;
        }
    }
}<|endoftext|>


<commit_before>extern crate coreutils;

use std::io::{self,Write};
use coreutils::extra::{OptionalExt};

static MAN_PAGE: &'static str = r#"
NAME
    basename - strip directory and suffix from filenames
SYNOPSIS
    basename NAME [SUFFIX]
    basename OPTION... NAME...
DESCRIPTION
    Print NAME with any leading directory components removed. If specified, also remove a trailing SUFFIX.
OPTIONS
    -a, --multiple
        support multiple arguments and treat each as a NAME
    -s, --suffix=SUFFIX
        remove a trailing SUFFIX; implies -a
    -z, --zero
        end each output line with NUL, not newline
    -h, --help
        display this help and exit
AUTHOR
    Written by Michael Murphy.
"#;

static HELP_INFO: &'static str       = "Try 'basename --help' for more information.";
static MISSING_OPERAND: &'static str = "basename: missing operand";
static REQUIRES_OPTION: &'static str = "basename: option requires an argument -- 's'";

fn main() {
    let stdout          = io::stdout();
    let mut stdout      = stdout.lock();
    let mut stderr      = io::stderr();
    let mut arguments   = std::env::args().skip(1);
    let mut multiple    = false;
    let mut zero        = false;
    let mut suffix      = String::new();
    let first_name: Option<String>;

    // Check input arguments for options.
    loop {
        if let Some(argument) = arguments.next() {
            // If the first character begins with a `-` then it is an option.
            if argument.chars().take(1).next().unwrap_or(' ') == '-' {
                match argument.as_str() {
                    "-a" | "--multiple" => multiple = true,
                    "-s" | "--suffix"   => {
                        if let Some(arg) = arguments.next() {
                            suffix = arg;
                            multiple = true;
                        } else {
                            stdout.write_all(REQUIRES_OPTION.as_bytes()).try(&mut stderr);
                            stdout.write_all(HELP_INFO.as_bytes()).try(&mut stderr);
                            return;
                        }
                    },
                    "-z" | "--zero"     => zero = true,
                    "-h" | "--help"     => {
                        stdout.write_all(MAN_PAGE.as_bytes()).try(&mut stderr);
                        return;
                    },
                    _ => {
                        println!("basename: invalid option -- '{}'", argument);
                        stdout.write_all(HELP_INFO.as_bytes()).try(&mut stderr);
                        return;
                    }
                }
            } else {
                first_name = Some(argument); // Store the last argument so that it isn't lost.
                break
            }
        } else {
            stdout.write_all(MISSING_OPERAND.as_bytes()).try(&mut stderr);
            stdout.write_all(HELP_INFO.as_bytes()).try(&mut stderr);
            return;
        }
    }

    // Begin printing the basename of each following argument.
    if let Some(name) = first_name {
        basename(zero, &name, &suffix);
    }
    if multiple {
        for argument in arguments {
            basename(zero, &argument, &suffix);
        }
    }
}

/// Takes a file path as input and returns the basename of that path. If `zero` is set to true,
/// the name will be printed without a newline. If a suffix is set and the path contains that
/// suffix, the suffix will be removed.
fn basename(zero: bool, path: &str, suffix: &str) {
    let mut path = String::from(path);
    let path_len = path.len();

    // If the suffix variable is set, remove the suffix.
    if path.ends_with(suffix) {
        path.truncate(path_len - suffix.len());
    }

    // Take only the basename of the path
    let new_path = std::path::Path::new(&path);
    let mut output = match new_path.file_name() {
        Some(base)     => String::from(base.to_str().unwrap()),
        None           => unreachable!()
    };

    // If zero is enabled, do not print a newline.
    if !zero { output.push('\n'); }

    // Print the output directly to stdout.
    io::stdout().write_all(output.as_bytes()).try(&mut io::stderr())
}
<commit_msg>Fix Issues With Basename<commit_after>extern crate coreutils;

use std::io::{self, Write};
use coreutils::extra::OptionalExt;

const MAN_PAGE: &'static str = r#"NAME
    basename - strip directory and suffix from filenames

SYNOPSIS
    basename [NAME [SUFFIX]] [OPTION... NAME...]

DESCRIPTION
    Print NAME with any leading directory components removed. If a SUFFIX is provided, the suffix will be removed from NAME.

OPTIONS
    -a
    --multiple
        Support multiple arguments and treat each as a NAME
    -s
    --suffix=SUFFIX
        remove a trailing SUFFIX; implies -a
    -z
    --zero
        end each output line with NUL, not newline
    -h
    --help
        display this help and exit

EXAMPLE
    basename dir/filename.ext
        > filename.ext
    basename dir/filename.ext .ext
        > filename
    basename -a -s .ext one.ext two.ext three.ext
        > one two three

AUTHOR
    Written by Michael Murphy.
"#;

const HELP_INFO:       &'static str = "Try ‘basename --help’ for more information.\n";
const MISSING_OPERAND: &'static str = "missing operand\n";
const REQUIRES_OPTION: &'static str = "option requires an argument -- ‘s’\n";

fn main() {
    let stdout          = io::stdout();
    let mut stdout      = stdout.lock();
    let mut stderr      = io::stderr();
    let mut arguments   = std::env::args().skip(1);
    let mut multiple    = false;
    let mut zero        = false;
    let mut suffix      = String::new();
    let first_name: Option<String>;

    // Check input arguments for options.
    loop {
        if let Some(argument) = arguments.next() {
            // If the first character begins with a `-` then it is an option.
            if argument.chars().take(1).next().unwrap_or(' ') == '-' {
                match argument.as_str() {
                    "-a" | "--multiple" => multiple = true,
                    "-s" | "--suffix"   => {
                        if let Some(arg) = arguments.next() {
                            suffix = arg;
                            multiple = true;
                        } else {
                            stderr.write_all(REQUIRES_OPTION.as_bytes()).try(&mut stderr);
                            stdout.write_all(HELP_INFO.as_bytes()).try(&mut stderr);
                            stderr.flush().try(&mut stderr);
                            stdout.flush().try(&mut stderr);
                            std::process::exit(1);
                        }
                    },
                    "-z" | "--zero"     => zero = true,
                    "-h" | "--help"     => {
                        stdout.write_all(MAN_PAGE.as_bytes()).try(&mut stderr);
                        stdout.flush().try(&mut stderr);
                        std::process::exit(1);
                    },
                    _ => {
                        stderr.write_all("invalid option -- ‘".as_bytes()).try(&mut stderr);
                        stderr.write_all(argument.as_bytes()).try(&mut stderr);
                        stderr.write_all("’\n".as_bytes()).try(&mut stderr);
                        stdout.write_all(HELP_INFO.as_bytes()).try(&mut stderr);
                        stderr.flush().try(&mut stderr);
                        stdout.flush().try(&mut stderr);
                        std::process::exit(1);
                    }
                }
            } else {
                first_name = Some(argument); // Store the last argument so that it isn't lost.
                break
            }
        } else {
            stdout.write_all(MISSING_OPERAND.as_bytes()).try(&mut stderr);
            stdout.write_all(HELP_INFO.as_bytes()).try(&mut stderr);
            return;
        }
    }

    // Begin printing the basename of each following argument.
    if let Some(name) = first_name {
        if !multiple {
            // If multiple isn't set and there is more than one
            // argument, the second argument is the suffix.
            if let Some(potential_suffix) = arguments.next() {
                // Check if there is an extra operand and exit if true.
                if let Some(extra_operand) = arguments.next() {
                    stderr.write_all("extra operand ‘".as_bytes()).try(&mut stderr);
                    stderr.write_all(extra_operand.as_bytes()).try(&mut stderr);
                    stderr.write_all("’\n".as_bytes()).try(&mut stderr);
                    stdout.write_all(HELP_INFO.as_bytes()).try(&mut stderr);
                    stderr.flush().try(&mut stderr);
                    stdout.flush().try(&mut stderr);
                    std::process::exit(1);
                }

                // Otherwise, set the suffix variable to the argument we found.
                suffix = potential_suffix;
            }
        }
        basename(zero, &name, &suffix, &mut stdout, &mut stderr);
    }

    // If the multiple arguments flag was set, execute a loop to print each name.
    if multiple {
        for argument in arguments {
            basename(zero, &argument, &suffix, &mut stdout, &mut stderr);
        }
    }
}

/// Takes a file path as input and returns the basename of that path. If `zero` is set to true,
/// the name will be printed without a newline. If a suffix is set and the path contains that
/// suffix, the suffix will be removed.
fn basename(zero: bool, input: &str, suffix: &str, stdout: &mut io::StdoutLock, stderr: &mut io::Stderr) {
    // If the suffix variable is set, remove the suffix from the path string.
    let path = if !suffix.is_empty() {
        let (prefix, input_suffix) = input.split_at(input.len() - suffix.len());
        if input_suffix == suffix { prefix } else { input }
    } else {
        input
    };

    // Only print the basename of the the path.
    let new_path = std::path::Path::new(&path);
    match new_path.file_name() {
        Some(base) => {
            if let Some(filename) = base.to_str() {
                stdout.write_all(filename.as_bytes()).try(stderr);
            } else {
                stderr.write_all("invalid unicode in path ‘".as_bytes()).try(stderr);
                stderr.write_all(path.as_bytes()).try(stderr);
                stderr.write_all("’\n".as_bytes()).try(stderr);
                stderr.flush().try(stderr);
                std::process::exit(1);
            }

        },
        None => {
            stderr.write_all("invalid path ‘".as_bytes()).try(stderr);
            stderr.write_all(path.as_bytes()).try(stderr);
            stderr.write_all("’\n".as_bytes()).try(stderr);
            stderr.flush().try(stderr);
            std::process::exit(1);
        }
    };

    // If zero is not enabled, print a newline.
    if !zero { stdout.write_all(b"\n").try(stderr); }
}
<|endoftext|>


<commit_before>#[macro_escape]
macro_rules! wayland_protocol(
    ($name: expr, [$(($import: ident, $interface: ident)),*], [$(($prot_name:ident, $prot_import: ident, $prot_iface: ident)),*]) => {
        #[cfg(feature = "client")]
        pub use self::generated::client;

        #[cfg(feature = "server")]
        pub use self::generated::server;

        #[cfg(all(feature = "native_lib", any(feature = "client", feature = "server")))]
        pub use self::generated::c_interfaces;

        #[cfg(all(not(feature = "native_lib"), any(feature = "client", feature = "server")))]
        mod generated {
            #![allow(dead_code,non_camel_case_types,unused_unsafe,unused_variables)]
            #![allow(non_upper_case_globals,non_snake_case,unused_imports)]
            #![allow(missing_docs)]

            #[cfg(feature = "client")]
            pub mod client {
                //! Client-side API of this protocol
                pub(crate) use wayland_client::{NewProxy, Proxy, ProxyMap, HandledBy, AnonymousObject};
                pub(crate) use wayland_commons::map::{Object, ObjectMetadata};
                pub(crate) use wayland_commons::{Interface, MessageGroup};
                pub(crate) use wayland_commons::wire::{Argument, MessageDesc, ArgumentType, Message};
                pub(crate) use wayland_client::protocol::{$($import),*};
                $(
                    pub(crate) use ::$prot_name::client::$prot_import;
                )*
                include!(concat!(env!("OUT_DIR"), "/", $name, "_rust_client_api.rs"));
            }

            #[cfg(feature = "server")]
            pub mod server {
                //! Server-side API of this protocol
                pub(crate) use wayland_server::{AnonymousObject, NewResource, Resource, ResourceMap, HandledBy};
                pub(crate) use wayland_commons::map::{Object, ObjectMetadata};
                pub(crate) use wayland_commons::{Interface, MessageGroup};
                pub(crate) use wayland_commons::wire::{Argument, MessageDesc, ArgumentType, Message};
                pub(crate) use wayland_server::protocol::{$($import),*};
                $(
                    pub(crate) use ::$prot_name::server::$prot_import;
                )*
                include!(concat!(env!("OUT_DIR"), "/", $name, "_rust_server_api.rs"));
            }
        }

        #[cfg(all(feature = "native_lib", any(feature = "client", feature = "server")))]
        mod generated {
            #![allow(dead_code,non_camel_case_types,unused_unsafe,unused_variables)]
            #![allow(non_upper_case_globals,non_snake_case,unused_imports)]
            #![allow(missing_docs)]

            pub mod c_interfaces {
                //! C interfaces for this protocol

                // import client or server, both are the same anyway
                #[cfg(feature = "client")]
                pub use wayland_client::sys::protocol_interfaces::{$($interface),*};
                #[cfg(all(not(feature = "client"), feature = "server"))]
                pub use wayland_server::sys::protocol_interfaces::{$($interface),*};
                $(
                    pub(crate) use ::$prot_name::c_interfaces::$prot_iface;
                )*
                include!(concat!(env!("OUT_DIR"), "/", $name, "_c_interfaces.rs"));
            }

            #[cfg(feature = "client")]
            pub mod client {
                //! Client-side API of this protocol
                pub(crate) use wayland_client::{NewProxy, Proxy, ProxyMap, HandledBy, AnonymousObject};
                pub(crate) use wayland_commons::map::{Object, ObjectMetadata};
                pub(crate) use wayland_commons::{Interface, MessageGroup};
                pub(crate) use wayland_commons::wire::{Argument, MessageDesc, ArgumentType, Message};
                pub(crate) use wayland_sys as sys;
                pub(crate) use wayland_client::protocol::{$($import),*};
                $(
                    pub(crate) use ::$prot_name::client::$prot_import;
                )*
                include!(concat!(env!("OUT_DIR"), "/", $name, "_c_client_api.rs"));
            }

            #[cfg(feature = "server")]
            pub mod server {
                //! Server-side API of this protocol
                pub(crate) use wayland_server::{AnonymousObject, NewResource, Resource, ResourceMap, HandledBy};
                pub(crate) use wayland_commons::map::{Object, ObjectMetadata};
                pub(crate) use wayland_commons::{Interface, MessageGroup};
                pub(crate) use wayland_commons::wire::{Argument, MessageDesc, ArgumentType, Message};
                pub(crate) use wayland_sys as sys;
                pub(crate) use wayland_server::protocol::{$($import),*};
                $(
                    pub(crate) use ::$prot_name::server::$prot_import;
                )*
                include!(concat!(env!("OUT_DIR"), "/", $name, "_c_server_api.rs"));
            }
        }
    }
);

#[cfg(feature = "unstable_protocols")]
#[macro_escape]
macro_rules! wayland_protocol_versioned(
    ($name: expr, [$($version: ident),*], $std_imports:tt, $prot_imports:tt) => {
        $(
            #[allow(missing_docs)]
            pub mod $version {
                wayland_protocol!(concat!($name, "-", stringify!($version)), $std_imports, $prot_imports);
            }
        )*
    }
);
<commit_msg>protocols: appease clippy<commit_after>#[macro_escape]
macro_rules! wayland_protocol(
    ($name: expr, [$(($import: ident, $interface: ident)),*], [$(($prot_name:ident, $prot_import: ident, $prot_iface: ident)),*]) => {
        #[cfg(feature = "client")]
        pub use self::generated::client;

        #[cfg(feature = "server")]
        pub use self::generated::server;

        #[cfg(all(feature = "native_lib", any(feature = "client", feature = "server")))]
        pub use self::generated::c_interfaces;

        #[cfg(all(not(feature = "native_lib"), any(feature = "client", feature = "server")))]
        mod generated {
            #![allow(dead_code,non_camel_case_types,unused_unsafe,unused_variables)]
            #![allow(non_upper_case_globals,non_snake_case,unused_imports)]
            #![allow(missing_docs, clippy)]

            #[cfg(feature = "client")]
            pub mod client {
                //! Client-side API of this protocol
                pub(crate) use wayland_client::{NewProxy, Proxy, ProxyMap, HandledBy, AnonymousObject};
                pub(crate) use wayland_commons::map::{Object, ObjectMetadata};
                pub(crate) use wayland_commons::{Interface, MessageGroup};
                pub(crate) use wayland_commons::wire::{Argument, MessageDesc, ArgumentType, Message};
                pub(crate) use wayland_client::protocol::{$($import),*};
                $(
                    pub(crate) use ::$prot_name::client::$prot_import;
                )*
                include!(concat!(env!("OUT_DIR"), "/", $name, "_rust_client_api.rs"));
            }

            #[cfg(feature = "server")]
            pub mod server {
                //! Server-side API of this protocol
                pub(crate) use wayland_server::{AnonymousObject, NewResource, Resource, ResourceMap, HandledBy};
                pub(crate) use wayland_commons::map::{Object, ObjectMetadata};
                pub(crate) use wayland_commons::{Interface, MessageGroup};
                pub(crate) use wayland_commons::wire::{Argument, MessageDesc, ArgumentType, Message};
                pub(crate) use wayland_server::protocol::{$($import),*};
                $(
                    pub(crate) use ::$prot_name::server::$prot_import;
                )*
                include!(concat!(env!("OUT_DIR"), "/", $name, "_rust_server_api.rs"));
            }
        }

        #[cfg(all(feature = "native_lib", any(feature = "client", feature = "server")))]
        mod generated {
            #![allow(dead_code,non_camel_case_types,unused_unsafe,unused_variables)]
            #![allow(non_upper_case_globals,non_snake_case,unused_imports)]
            #![allow(missing_docs, clippy)]

            pub mod c_interfaces {
                //! C interfaces for this protocol

                // import client or server, both are the same anyway
                #[cfg(feature = "client")]
                pub use wayland_client::sys::protocol_interfaces::{$($interface),*};
                #[cfg(all(not(feature = "client"), feature = "server"))]
                pub use wayland_server::sys::protocol_interfaces::{$($interface),*};
                $(
                    pub(crate) use ::$prot_name::c_interfaces::$prot_iface;
                )*
                include!(concat!(env!("OUT_DIR"), "/", $name, "_c_interfaces.rs"));
            }

            #[cfg(feature = "client")]
            pub mod client {
                //! Client-side API of this protocol
                pub(crate) use wayland_client::{NewProxy, Proxy, ProxyMap, HandledBy, AnonymousObject};
                pub(crate) use wayland_commons::map::{Object, ObjectMetadata};
                pub(crate) use wayland_commons::{Interface, MessageGroup};
                pub(crate) use wayland_commons::wire::{Argument, MessageDesc, ArgumentType, Message};
                pub(crate) use wayland_sys as sys;
                pub(crate) use wayland_client::protocol::{$($import),*};
                $(
                    pub(crate) use ::$prot_name::client::$prot_import;
                )*
                include!(concat!(env!("OUT_DIR"), "/", $name, "_c_client_api.rs"));
            }

            #[cfg(feature = "server")]
            pub mod server {
                //! Server-side API of this protocol
                pub(crate) use wayland_server::{AnonymousObject, NewResource, Resource, ResourceMap, HandledBy};
                pub(crate) use wayland_commons::map::{Object, ObjectMetadata};
                pub(crate) use wayland_commons::{Interface, MessageGroup};
                pub(crate) use wayland_commons::wire::{Argument, MessageDesc, ArgumentType, Message};
                pub(crate) use wayland_sys as sys;
                pub(crate) use wayland_server::protocol::{$($import),*};
                $(
                    pub(crate) use ::$prot_name::server::$prot_import;
                )*
                include!(concat!(env!("OUT_DIR"), "/", $name, "_c_server_api.rs"));
            }
        }
    }
);

#[cfg(feature = "unstable_protocols")]
#[macro_escape]
macro_rules! wayland_protocol_versioned(
    ($name: expr, [$($version: ident),*], $std_imports:tt, $prot_imports:tt) => {
        $(
            #[allow(missing_docs)]
            pub mod $version {
                wayland_protocol!(concat!($name, "-", stringify!($version)), $std_imports, $prot_imports);
            }
        )*
    }
);
<|endoftext|>


<commit_before><commit_msg>made ptr printer generic in write port, thanks to @bodil<commit_after><|endoftext|>


<commit_before>use futures::stable::{block_on_stable, StableFuture};
use futures::prelude::*;

#[async]
fn foo() -> Result<i32, i32> {
    Ok(1)
}

#[async]
fn bar(x: &i32) -> Result<i32, i32> {
    Ok(*x)
}

#[async]
fn baz(x: i32) -> Result<i32, i32> {
    await!(bar(&x))
}

#[async_move]
fn qux(x: i32) -> Result<i32, i32> {
    await!(baz(x).pin())
}

#[async_stream(item = u64)]
fn _stream1() -> Result<(), i32> {
    fn integer() -> u64 { 1 }
    let x = &integer();
    stream_yield!(0);
    stream_yield!(*x);
    Ok(())
}

#[async]
pub fn uses_async_for() -> Result<Vec<u64>, i32> {
    let mut v = vec![];
    #[async]
    for i in _stream1() {
        v.push(i);
    }
    Ok(v)
}

#[test]
fn main() {
    assert_eq!(block_on_stable(foo()), Ok(1));
    assert_eq!(block_on_stable(bar(&1)), Ok(1));
    assert_eq!(block_on_stable(baz(17)), Ok(17));
    assert_eq!(block_on_stable(qux(17)), Ok(17));
    assert_eq!(block_on_stable(uses_async_for()), Ok(vec![0, 1]));
}
<commit_msg>Add test case checking for macro leakage<commit_after>use futures::stable::{block_on_stable, StableFuture};
use futures::prelude::*;

#[async]
fn foo() -> Result<i32, i32> {
    Ok(1)
}

#[async]
fn bar(x: &i32) -> Result<i32, i32> {
    Ok(*x)
}

#[async]
fn baz(x: i32) -> Result<i32, i32> {
    await!(bar(&x))
}

#[async_move]
fn qux(x: i32) -> Result<i32, i32> {
    await!(baz(x).pin())
}

// This test is to check that the internal __await macro generated in each
// function does not leak across function boundaries. If it did then calling
// the #[async] version of __await in the #[async_move] function should cause
// a 'borrow may still be in use when generator yields' error, while calling
// the #[async_move] version in the #[async] function should fail because `bar`
// does not implement `Future`.
#[async_move]
fn qux2(x: i32) -> Result<i32, i32> {
    #[async]
    fn baz2(x: i32) -> Result<i32, i32> {
        await!(bar(&x))
    }
    await!(baz2(x).pin())
}

#[async_stream(item = u64)]
fn _stream1() -> Result<(), i32> {
    fn integer() -> u64 { 1 }
    let x = &integer();
    stream_yield!(0);
    stream_yield!(*x);
    Ok(())
}

#[async]
pub fn uses_async_for() -> Result<Vec<u64>, i32> {
    let mut v = vec![];
    #[async]
    for i in _stream1() {
        v.push(i);
    }
    Ok(v)
}

#[test]
fn main() {
    assert_eq!(block_on_stable(foo()), Ok(1));
    assert_eq!(block_on_stable(bar(&1)), Ok(1));
    assert_eq!(block_on_stable(baz(17)), Ok(17));
    assert_eq!(block_on_stable(qux(17)), Ok(17));
    assert_eq!(block_on_stable(qux2(17)), Ok(17));
    assert_eq!(block_on_stable(uses_async_for()), Ok(vec![0, 1]));
}
<|endoftext|>


<commit_before>use std::io;
use common;

#[derive(Default)]
pub struct Day25 {
}

impl Day25 {

    pub fn new() -> Day25 {
        Default::default()
    }

}

impl common::Solution for Day25 {

    fn part1(&mut self, _input: &mut io::Read) -> String {
        let initial = 0b101010101010 - 362 * 7;
        println!("Initial value: {}", initial);
        sender_program(initial);
        unreachable!();
    }
}

/// This function is an approximation of what the original code is doing.
pub fn sender_program(mut a: i32) {
    // Placeholder variables
    let mut b = 0;
    let mut d = 0;

    d = a;
    d += 362 * 7;
    loop {
        if a == 0 {
            a = d;
        }
        b = a;
        a = b / 2;
        b = b % 2;
        println!("{}", b);
    }
}
<commit_msg>Fix some warnings.<commit_after>use std::io;
use common;

#[derive(Default)]
pub struct Day25 {
}

impl Day25 {

    pub fn new() -> Day25 {
        Default::default()
    }

}

impl common::Solution for Day25 {

    fn part1(&mut self, _input: &mut io::Read) -> String {
        let initial = 0b101010101010 - 362 * 7;
        println!("Initial value: {}", initial);
        sender_program(initial);
        unreachable!();
    }
}

/// This function is an approximation of what the original code is doing.
pub fn sender_program(mut a: i32) {
    // Placeholder variables
    let mut b;
    let mut d;

    d = a;
    d += 362 * 7;
    loop {
        if a == 0 {
            a = d;
        }
        b = a;
        a = b / 2;
        b = b % 2;
        println!("{}", b);
    }
}
<|endoftext|>


<commit_before>extern crate sdl2;
extern crate sdl2_ttf;
use sdl2::render::{Renderer, TextureQuery, BlendMode};
use sdl2::rect::Rect;
use sdl2::pixels::Color;
use std::vec::Vec;
use std::path::Path;
use font::*;
use std::ops::DerefMut;
use display::{self,Display};
use subtitles::{self,Subtitles};

pub struct Displayer<'a> {
    fonts: FontList,
    renderer: Renderer<'a>,
    #[allow(dead_code)]
    ttf_context: sdl2_ttf::Sdl2TtfContext,
    subtitles:Option<Subtitles>
}

impl<'a> Displayer<'a> {
    pub fn new(mut renderer: Renderer<'a>,subtitles:Option<Subtitles>) -> Result<Displayer<'a>, ()> {
        renderer.set_blend_mode(BlendMode::Blend);
        let ttf_context = sdl2_ttf::init().unwrap();
        let font_list = FontList::new(Path::new("./res/DejaVuSansMono-Bold.ttf"),
                                      &ttf_context)
                            .unwrap();
        let displayer = Displayer {
            fonts: font_list,
            ttf_context: ttf_context,
            renderer: renderer,
            subtitles: subtitles
        };
        Ok(displayer)
    }

    pub fn render_subtitles(&mut self,frame_number:u32){
        let mut text2d_vec = vec![];
        match self.subtitles {
            Some(ref subtitles) => {
                let subtitles = subtitles.get_subtitles();
                let iter = subtitles.iter().enumerate().filter(|&(i,line)|{
                    line.iter().any(|syllabus|{
                        let &(ref syllabus,(frame_begin,frame_end)) = syllabus;
                        (frame_begin <= frame_number) && (frame_number <= frame_end)
                    })
                });
                for (i,line) in iter {
                    let text_pos_y = match i%2 {
                        0 => {display::PosY::FromTopPercent(0.02)},
                        1 => {display::PosY::FromTopPercent(0.12)},
                        _ => unreachable!()
                    };
                    let text_elts = line.iter().fold(vec![],|mut accu_vec,&(ref syllabus,(frame_begin,frame_end))|{
                        if (frame_number < frame_begin){ // not yet
                            if (accu_vec.is_empty()){
                                let text_2d = display::TextElement {
                                    text:syllabus.clone(),
                                    color:Color::RGBA(128,255,0,255),
                                    outline:Some(Color::RGB(0,0,0)),
                                    shadow:None
                                };
                                accu_vec.push(text_2d);
                            } else {
                                let mut text_2d = accu_vec.last_mut().unwrap();
                                text_2d.text.push_str(&syllabus) ;
                            }
                        } else if (frame_begin <= frame_number) && (frame_number <= frame_end) {
                            let text_2d = display::TextElement {
                                text:syllabus.clone(),
                                color:Color::RGBA(255,0,0,255),
                                outline:Some(Color::RGB(0,0,0)),
                                shadow:None
                            };
                            accu_vec.push(text_2d);
                        } else {
                            let text_2d = display::TextElement {
                                text:syllabus.clone(),
                                color:Color::RGBA(128,128,255,255),
                                outline:Some(Color::RGB(0,0,0)),
                                shadow:None
                            };
                            accu_vec.push(text_2d);
                        }
                        accu_vec
                    });
                    let text_2d = display::Text2D {
                        text:text_elts,
                        size:display::Size::FitPercent(Some(0.95),Some(0.1)),
                        pos:(display::PosX::Centered,text_pos_y),
                        anchor:(0.5,0.0)
                    };
                    text2d_vec.push(text_2d);
                }
            },
            None => {}
        };
        for text2D in text2d_vec.into_iter() {
            text2D.draw(self);
        }
    }

    pub fn display(&mut self, text: &str) {
        let size: f32 = 0.039;
        let window_width = self.renderer.window().unwrap().size().0 ;
        let font_set = self.fonts.get_fittest_font_set(text, (Some(window_width),None),true).unwrap();
        let font = font_set.get_regular_font();
        let font_outline = font_set.get_outline_font();
        let surface = font.render(text)
                          .blended(Color::RGB(180, 180, 180))
                          .unwrap();
        let mut surface_outline = font_outline.render(text)
                                              .blended(Color::RGB(0, 0, 0))
                                              .unwrap();
        let outline_width: u32 = 2;
        let (width, height) = surface_outline.size();
        surface.blit(None,
                     surface_outline.deref_mut(),
                     Some(Rect::new(outline_width as i32,
                                    outline_width as i32,
                                    (width - outline_width),
                                    (height - outline_width)))).expect("Failed to blit texture");
        let mut texture = self.renderer.create_texture_from_surface(&surface_outline).unwrap();
        texture.set_blend_mode(BlendMode::Blend);
        texture.set_alpha_mod(128);
        let TextureQuery { width:texture_width, height:texture_height, format:texture_format,.. } = texture.query();
        self.renderer.copy(&mut texture,
                           None,
                           Some(Rect::new(3, 3, texture_width, texture_height)));
    }

    pub fn example(&mut self) {
        let text_element_1 = display::TextElement {
            text:"S".to_string(),
            color:Color::RGBA(0,0,0,255),
            outline:Some(Color::RGB(255,255,255)),
            shadow:None
        };
        let text_element_2 = display::TextElement {
            text:"L".to_string(),
            color:Color::RGBA(255,255,255,255),
            outline:Some(Color::RGB(0,0,0)),
            shadow:None
        };
        let text_element_3 = display::TextElement {
            text:"T".to_string(),
            color:Color::RGBA(255,0,0,200),
            outline:None,
            shadow:None
        };
        let text_2d : display::Text2D = display::Text2D {
            text:vec![text_element_1,text_element_2,text_element_3],
            size:display::Size::FitPercent(Some(0.9),Some(0.1)),
            pos:(display::PosX::Centered,display::PosY::FromTopPercent(0.50)),
            anchor:(0.5,0.5)
        };
        text_2d.draw(self);
    }

    // width and height must be between 0 and 1
    pub fn sub_screen_dims(&self,width:Option<f32>,height:Option<f32>) -> (Option<u32>,Option<u32>){
        let dims : (u32,u32)= self.renderer.window().unwrap().size();
        (
            width.and_then(|width|{
                Some((width *  (dims.0 as f32)) as u32)
            }) ,
            height.and_then(|height|{
                Some((height *  (dims.1 as f32)) as u32)
            })
        )
    }

    pub fn render(&mut self) {
        self.sdl_renderer_mut().window().unwrap().gl_swap_window();
    }

    pub fn sdl_renderer_mut(&mut self) -> &mut Renderer<'a> {
        &mut self.renderer
    }

    pub fn sdl_renderer(&self) -> &Renderer<'a> {
        &self.renderer
    }

    pub fn fonts(&self) -> &FontList {
        &self.fonts
    }
}
<commit_msg>buggy subtitles<commit_after>extern crate sdl2;
extern crate sdl2_ttf;
use sdl2::render::{Renderer, TextureQuery, BlendMode};
use sdl2::rect::Rect;
use sdl2::pixels::Color;
use std::vec::Vec;
use std::path::Path;
use font::*;
use std::ops::DerefMut;
use display::{self,Display};
use subtitles::{self,Subtitles};

pub struct Displayer<'a> {
    fonts: FontList,
    renderer: Renderer<'a>,
    #[allow(dead_code)]
    ttf_context: sdl2_ttf::Sdl2TtfContext,
    subtitles:Option<Subtitles>
}

impl<'a> Displayer<'a> {
    pub fn new(mut renderer: Renderer<'a>,subtitles:Option<Subtitles>) -> Result<Displayer<'a>, ()> {
        renderer.set_blend_mode(BlendMode::Blend);
        let ttf_context = sdl2_ttf::init().unwrap();
        let font_list = FontList::new(Path::new("./res/DejaVuSansMono-Bold.ttf"),
                                      &ttf_context)
                            .unwrap();
        let displayer = Displayer {
            fonts: font_list,
            ttf_context: ttf_context,
            renderer: renderer,
            subtitles: subtitles
        };
        Ok(displayer)
    }

    pub fn render_subtitles(&mut self,frame_number:u32){
        let mut text2d_vec = vec![];
        match self.subtitles {
            Some(ref subtitles) => {
                let subtitles = subtitles.get_subtitles();
                let iter = subtitles.iter().enumerate().filter(|&(i,line)|{
                    line.iter().any(|syllabus|{
                        let &(ref syllabus,(frame_begin,frame_end)) = syllabus;
                        (frame_begin <= frame_number) && (frame_number <= frame_end)
                    })
                });
                for (i,line) in iter {
                    let text_pos_y = match i%2 {
                        0 => {display::PosY::FromTopPercent(0.02)},
                        1 => {display::PosY::FromTopPercent(0.12)},
                        _ => unreachable!()
                    };
                    let text_elts = line.iter().fold(vec![],|mut accu_vec,&(ref syllabus,(frame_begin,frame_end))|{
                        println!("begin:{},\tend:{},\tcurrent:{}",frame_begin,frame_end,frame_current);
                        if (frame_number < frame_begin){ // not yet
                            println!("not yet");
                            if (accu_vec.is_empty()){
                                let text_2d = display::TextElement {
                                    text:syllabus.clone(),
                                    color:Color::RGBA(128,255,0,255),
                                    outline:Some(Color::RGB(0,0,0)),
                                    shadow:None
                                };
                                accu_vec.push(text_2d);
                            } else {
                                let mut text_2d = accu_vec.last_mut().unwrap();
                                text_2d.text.push_str(&syllabus) ;
                            }
                        } else if (frame_begin <= frame_number) && (frame_number <= frame_end) {
                            println!("being played");
                            let text_2d = display::TextElement {
                                text:syllabus.clone(),
                                color:Color::RGBA(255,0,0,255),
                                outline:Some(Color::RGB(0,0,0)),
                                shadow:None
                            };
                            accu_vec.push(text_2d);
                        } else {
                            println!("after play");
                            let text_2d = display::TextElement {
                                text:syllabus.clone(),
                                color:Color::RGBA(128,128,255,255),
                                outline:Some(Color::RGB(0,0,0)),
                                shadow:None
                            };
                            accu_vec.push(text_2d);
                        }
                        accu_vec
                    });
                    let text_2d = display::Text2D {
                        text:text_elts,
                        size:display::Size::FitPercent(Some(0.95),Some(0.1)),
                        pos:(display::PosX::Centered,text_pos_y),
                        anchor:(0.5,0.0)
                    };
                    text2d_vec.push(text_2d);
                }
            },
            None => {}
        };
        for text2D in text2d_vec.into_iter() {
            text2D.draw(self);
        }
    }

    pub fn display(&mut self, text: &str) {
        let size: f32 = 0.039;
        let window_width = self.renderer.window().unwrap().size().0 ;
        let font_set = self.fonts.get_fittest_font_set(text, (Some(window_width),None),true).unwrap();
        let font = font_set.get_regular_font();
        let font_outline = font_set.get_outline_font();
        let surface = font.render(text)
                          .blended(Color::RGB(180, 180, 180))
                          .unwrap();
        let mut surface_outline = font_outline.render(text)
                                              .blended(Color::RGB(0, 0, 0))
                                              .unwrap();
        let outline_width: u32 = 2;
        let (width, height) = surface_outline.size();
        surface.blit(None,
                     surface_outline.deref_mut(),
                     Some(Rect::new(outline_width as i32,
                                    outline_width as i32,
                                    (width - outline_width),
                                    (height - outline_width)))).expect("Failed to blit texture");
        let mut texture = self.renderer.create_texture_from_surface(&surface_outline).unwrap();
        texture.set_blend_mode(BlendMode::Blend);
        texture.set_alpha_mod(128);
        let TextureQuery { width:texture_width, height:texture_height, format:texture_format,.. } = texture.query();
        self.renderer.copy(&mut texture,
                           None,
                           Some(Rect::new(3, 3, texture_width, texture_height)));
    }

    pub fn example(&mut self) {
        let text_element_1 = display::TextElement {
            text:"S".to_string(),
            color:Color::RGBA(0,0,0,255),
            outline:Some(Color::RGB(255,255,255)),
            shadow:None
        };
        let text_element_2 = display::TextElement {
            text:"L".to_string(),
            color:Color::RGBA(255,255,255,255),
            outline:Some(Color::RGB(0,0,0)),
            shadow:None
        };
        let text_element_3 = display::TextElement {
            text:"T".to_string(),
            color:Color::RGBA(255,0,0,200),
            outline:None,
            shadow:None
        };
        let text_2d : display::Text2D = display::Text2D {
            text:vec![text_element_1,text_element_2,text_element_3],
            size:display::Size::FitPercent(Some(0.9),Some(0.1)),
            pos:(display::PosX::Centered,display::PosY::FromTopPercent(0.50)),
            anchor:(0.5,0.5)
        };
        text_2d.draw(self);
    }

    // width and height must be between 0 and 1
    pub fn sub_screen_dims(&self,width:Option<f32>,height:Option<f32>) -> (Option<u32>,Option<u32>){
        let dims : (u32,u32)= self.renderer.window().unwrap().size();
        (
            width.and_then(|width|{
                Some((width *  (dims.0 as f32)) as u32)
            }) ,
            height.and_then(|height|{
                Some((height *  (dims.1 as f32)) as u32)
            })
        )
    }

    pub fn render(&mut self) {
        self.sdl_renderer_mut().window().unwrap().gl_swap_window();
    }

    pub fn sdl_renderer_mut(&mut self) -> &mut Renderer<'a> {
        &mut self.renderer
    }

    pub fn sdl_renderer(&self) -> &Renderer<'a> {
        &self.renderer
    }

    pub fn fonts(&self) -> &FontList {
        &self.fonts
    }
}
<|endoftext|>