<commit_before>// Copyright 2019 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.

// See LICENSE for licensing information.
//
// This build.rs script tries to generate low-level rust bindings for the current ICU library.
// Please refer to README.md for instructions on how to build the library for
// your use.

/// This is all a no-op if `use-bindgen` disabled.
#[cfg(feature = "use-bindgen")]
mod inner {
    use {
        anyhow::{Context, Result},
        bindgen,
        lazy_static::lazy_static,
        std::env,
        std::fs::File,
        std::io::Write,
        std::path::Path,
        std::process,
    };

    lazy_static! {
        // The modules for which bindings will be generated.  Add more if you need them.  The list
        // should be topologicaly sorted based on the inclusion relationship between the respective
        // headers.  Any of these will fail if the required binaries are not present in $PATH.
        static ref BINDGEN_SOURCE_MODULES: Vec<&'static str> = vec![
            "ubrk",
            "ucal",
            "uclean",
            "ucnv",
            "ucol",
            "udat",
            "udatpg",
            "udata",
            "uenum",
            "ufieldpositer",
            "uformattable",
            "ulistformatter",
            "umisc",
            "umsg",
            "unum",
            "unumberformatter",
            "upluralrules",
            "uset",
            "ustring",
            "utext",
            "utrans",
            "unorm2",
        ];

        // C functions that will be made available to rust code.  Add more to this list if you want to
        // bring in more types.
        static ref BINDGEN_ALLOWLIST_FUNCTIONS: Vec<&'static str> = vec![
            "u_.*",
            "ubrk_.*",
            "ucal_.*",
            "ucnv_.*",
            "ucol_.*",
            "udat_.*",
            "udatpg_.*",
            "udata_.*",
            "uenum_.*",
            "ufieldpositer_.*",
            "ufmt_.*",
            "ulistfmt_.*",
            "uloc_.*",
            "umsg_.*",
            "unum_.*",
            "unumf_.*",
            "uplrules_.*",
            "utext_.*",
            "utrans_.*",
            "unorm2_.*",
        ];

        // C types that will be made available to rust code.  Add more to this list if you want to
        // generate more bindings.
        static ref BINDGEN_ALLOWLIST_TYPES: Vec<&'static str> = vec![
            "UAcceptResult",
            "UBool",
            "UBreakIterator",
            "UBreakIteratorType",
            "UCalendar.*",
            "UChar.*",
            "UCol.*",
            "UCollation.*",
            "UCollator",
            "UConverter.*",
            "UData.*",
            "UDate.*",
            "UDateFormat.*",
            "UDisplayContext.*",
            "UEnumeration.*",
            "UErrorCode",
            "UField.*",
            "UFormat.*",
            "UFormattedList.*",
            "ULineBreakTag",
            "UListFormatter.*",
            "ULoc.*",
            "ULOC.*",
            "UMessageFormat",
            "UNUM.*",
            "UNumber.*",
            "UParseError",
            "UPlural.*",
            "USentenceBreakTag",
            "USet",
            "UText",
            "UTransDirection",
            "UTransPosition",
            "UTransliterator",
            "UWordBreak",
            "UNorm.*",
        ];
    }

    /// A `Command` that also knows its name.
    struct Command {
        name: String,
        rep: process::Command,
    }

    impl Command {
        /// Creates a new command to run, with the executable `name`.
        pub fn new(name: &'static str) -> Self {
            let rep = process::Command::new(&name);
            let name = String::from(name);
            Command { name, rep }
        }

        /// Runs this command with `args` as arguments.
        pub fn run(&mut self, args: &[&str]) -> Result<String> {
            self.rep.args(args);
            let stdout = self.stdout()?;
            Ok(String::from(&stdout).trim().to_string())
        }

        // Captures the stdout of the command.
        fn stdout(&mut self) -> Result<String> {
            let output = self
                .rep
                .output()
                .with_context(|| format!("could not execute command: {}", self.name))?;
            let result = String::from_utf8(output.stdout)
                .with_context(|| "could not convert output to UTF8")?;
            Ok(result.trim().to_string())
        }
    }

    /// A command representing an auto-configuration detector.  Use `ICUConfig::new()` to create.
    struct ICUConfig {
        rep: Command,
    }

    impl ICUConfig {
        /// Creates a new ICUConfig.
        fn new() -> Self {
            ICUConfig {
                rep: Command::new("pkg-config"),
            }
        }
        /// Obtains the prefix directory, e.g. `$HOME/local`
        fn prefix(&mut self) -> Result<String> {
            self.rep
                .run(&["--variable=prefix", "icu-i18n"])
                .with_context(|| "could not get config prefix")
        }

        /// Obtains the default library path for the libraries.
        fn libdir(&mut self) -> Result<String> {
            self.rep
                .run(&["--variable=libdir", "icu-i18n"])
                .with_context(|| "could not get library directory")
        }

        /// Obtains the needed flags for the linker.
        fn ldflags(&mut self) -> Result<String> {
            // Replacements needed because of https://github.com/rust-lang/cargo/issues/7217
            let result = self
                .rep
                .run(&["--libs", "icu-i18n"])
                .with_context(|| "could not get the ld flags")?;
            Ok(result.replace("-L", "-L ").replace("-l", "-l "))
        }

        /// Obtains the needed flags for the C++ compiler.
        fn cppflags(&mut self) -> Result<String> {
            self.rep
                .run(&["--cflags", "icu-i18n"])
                .with_context(|| "while getting the cpp flags")
        }

        /// Obtains the major-minor version number for the library. Returns a string like `64.2`.
        fn version(&mut self) -> Result<String> {
            self.rep
                .run(&["--modversion", "icu-i18n"])
                .with_context(|| "while getting ICU version; is icu-config in $PATH?")
        }

        fn install_dir(&mut self) -> Result<String> {
            self.prefix()
        }

        /// Returns the config major number.  For example, will return "64" for
        /// version "64.2"
        fn version_major() -> Result<String> {
            let version = ICUConfig::new().version()?;<commit_msg>Allow -l and -L in the path where ICU is installed<commit_after>// Copyright 2019 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.

// See LICENSE for licensing information.
//
// This build.rs script tries to generate low-level rust bindings for the current ICU library.
// Please refer to README.md for instructions on how to build the library for
// your use.

/// This is all a no-op if `use-bindgen` disabled.
#[cfg(feature = "use-bindgen")]
mod inner {
    use {
        anyhow::{Context, Result},
        bindgen,
        lazy_static::lazy_static,
        std::env,
        std::fs::File,
        std::io::Write,
        std::path::Path,
        std::process,
    };

    lazy_static! {
        // The modules for which bindings will be generated.  Add more if you need them.  The list
        // should be topologicaly sorted based on the inclusion relationship between the respective
        // headers.  Any of these will fail if the required binaries are not present in $PATH.
        static ref BINDGEN_SOURCE_MODULES: Vec<&'static str> = vec![
            "ubrk",
            "ucal",
            "uclean",
            "ucnv",
            "ucol",
            "udat",
            "udatpg",
            "udata",
            "uenum",
            "ufieldpositer",
            "uformattable",
            "ulistformatter",
            "umisc",
            "umsg",
            "unum",
            "unumberformatter",
            "upluralrules",
            "uset",
            "ustring",
            "utext",
            "utrans",
            "unorm2",
        ];

        // C functions that will be made available to rust code.  Add more to this list if you want to
        // bring in more types.
        static ref BINDGEN_ALLOWLIST_FUNCTIONS: Vec<&'static str> = vec![
            "u_.*",
            "ubrk_.*",
            "ucal_.*",
            "ucnv_.*",
            "ucol_.*",
            "udat_.*",
            "udatpg_.*",
            "udata_.*",
            "uenum_.*",
            "ufieldpositer_.*",
            "ufmt_.*",
            "ulistfmt_.*",
            "uloc_.*",
            "umsg_.*",
            "unum_.*",
            "unumf_.*",
            "uplrules_.*",
            "utext_.*",
            "utrans_.*",
            "unorm2_.*",
        ];

        // C types that will be made available to rust code.  Add more to this list if you want to
        // generate more bindings.
        static ref BINDGEN_ALLOWLIST_TYPES: Vec<&'static str> = vec![
            "UAcceptResult",
            "UBool",
            "UBreakIterator",
            "UBreakIteratorType",
            "UCalendar.*",
            "UChar.*",
            "UCol.*",
            "UCollation.*",
            "UCollator",
            "UConverter.*",
            "UData.*",
            "UDate.*",
            "UDateFormat.*",
            "UDisplayContext.*",
            "UEnumeration.*",
            "UErrorCode",
            "UField.*",
            "UFormat.*",
            "UFormattedList.*",
            "ULineBreakTag",
            "UListFormatter.*",
            "ULoc.*",
            "ULOC.*",
            "UMessageFormat",
            "UNUM.*",
            "UNumber.*",
            "UParseError",
            "UPlural.*",
            "USentenceBreakTag",
            "USet",
            "UText",
            "UTransDirection",
            "UTransPosition",
            "UTransliterator",
            "UWordBreak",
            "UNorm.*",
        ];
    }

    /// A `Command` that also knows its name.
    struct Command {
        name: String,
        rep: process::Command,
    }

    impl Command {
        /// Creates a new command to run, with the executable `name`.
        pub fn new(name: &'static str) -> Self {
            let rep = process::Command::new(&name);
            let name = String::from(name);
            Command { name, rep }
        }

        /// Runs this command with `args` as arguments.
        pub fn run(&mut self, args: &[&str]) -> Result<String> {
            self.rep.args(args);
            let stdout = self.stdout()?;
            Ok(String::from(&stdout).trim().to_string())
        }

        // Captures the stdout of the command.
        fn stdout(&mut self) -> Result<String> {
            let output = self
                .rep
                .output()
                .with_context(|| format!("could not execute command: {}", self.name))?;
            let result = String::from_utf8(output.stdout)
                .with_context(|| "could not convert output to UTF8")?;
            Ok(result.trim().to_string())
        }
    }

    /// A command representing an auto-configuration detector.  Use `ICUConfig::new()` to create.
    struct ICUConfig {
        rep: Command,
    }

    impl ICUConfig {
        /// Creates a new ICUConfig.
        fn new() -> Self {
            ICUConfig {
                rep: Command::new("pkg-config"),
            }
        }
        /// Obtains the prefix directory, e.g. `$HOME/local`
        fn prefix(&mut self) -> Result<String> {
            self.rep
                .run(&["--variable=prefix", "icu-i18n"])
                .with_context(|| "could not get config prefix")
        }

        /// Obtains the default library path for the libraries.
        fn libdir(&mut self) -> Result<String> {
            self.rep
                .run(&["--variable=libdir", "icu-i18n"])
                .with_context(|| "could not get library directory")
        }

        /// Obtains the needed flags for the linker.
        fn ldflags(&mut self) -> Result<String> {
            self.rep
                .run(&["--libs", "icu-i18n"])
                .with_context(|| "could not get the ld flags")
        }

        /// Obtains the needed flags for the C++ compiler.
        fn cppflags(&mut self) -> Result<String> {
            self.rep
                .run(&["--cflags", "icu-i18n"])
                .with_context(|| "while getting the cpp flags")
        }

        /// Obtains the major-minor version number for the library. Returns a string like `64.2`.
        fn version(&mut self) -> Result<String> {
            self.rep
                .run(&["--modversion", "icu-i18n"])
                .with_context(|| "while getting ICU version; is icu-config in $PATH?")
        }

        fn install_dir(&mut self) -> Result<String> {
            self.prefix()
        }

        /// Returns the config major number.  For example, will return "64" for
        /// version "64.2"
        fn version_major() -> Result<String> {
            let version = ICUConfig::new().version()?;
{'fraction_non_alphanumeric': 0.13082675239359842, 'fraction_numerical': 0.004472709483541826, 'mean_word_length': 1.4869655891553701, 'pattern_counts': {'":': 0, '<': 27, '<?xml version=': 0, '>': 49, 'https://': 1, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '621083', 'n_tokens_mistral': 4065, 'n_tokens_neox': 3946, 'n_words': 1173}