<commit_before>// Copyright 2016 The xi-editor Authors.
//
// 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.

#[macro_use]
extern crate log;
extern crate chrono;
extern crate fern;

extern crate dirs;

extern crate xi_core_lib;
extern crate xi_rpc;

use std::collections::HashMap;
use std::fs;
use std::io;
use std::path::{Path, PathBuf};

use xi_core_lib::XiCore;
use xi_rpc::RpcLoop;

const XI_LOG_DIR: &str = "xi-core";
const XI_LOG_FILE: &str = "xi-core.log";

fn get_logging_directory_path<P: AsRef<Path>>(directory: P) -> Result<PathBuf, io::Error> {
    match dirs::data_local_dir() {
        Some(mut log_dir) => {
            log_dir.push(directory);
            Ok(log_dir)
        }
        None => Err(io::Error::new(
            io::ErrorKind::NotFound,
            "No standard logging directory known for this platform",
        )),
    }
}

fn setup_logging(logging_path_result: Result<PathBuf, io::Error>) -> Result<(), fern::InitError> {
    let level_filter = match std::env::var("XI_LOG") {
        Ok(level) => match level.to_lowercase().as_ref() {
            "trace" => log::LevelFilter::Trace,
            "debug" => log::LevelFilter::Debug,
            _ => log::LevelFilter::Info,
        },
        // Default to info
        Err(_) => log::LevelFilter::Info,
    };

    let mut fern_dispatch = fern::Dispatch::new()
        .format(|out, message, record| {
            out.finish(format_args!(
                "{}[{}][{}] {}",
                chrono::Local::now().format("[%Y-%m-%d][%H:%M:%S]"),
                record.target(),
                record.level(),
                message,
            ))
        }).level(level_filter)
        .chain(io::stderr());

    if let Ok(logging_file_path) = &logging_path_result {
        // Ensure the logging directory is created
        let parent_path = logging_file_path.parent().ok_or(io::Error::new(
            io::ErrorKind::InvalidInput,
            format!(
                "Unable to get the parent of the following Path: {}",
                logging_file_path.display(),
            ),
        ))?;
        fs::create_dir_all(parent_path)?;
        // Attach it to fern
        fern_dispatch = fern_dispatch.chain(fern::log_file(logging_file_path)?);
    };

    // Start fern
    fern_dispatch.apply()?;
    info!("Logging with fern is setup");

    // Log details of the logging_file_path result using fern/log
    // Either logging the path fern is outputting to or the error from obtaining the path
    match &logging_path_result {
        Ok(logging_file_path) => {
            info!(
                "Logging to the following file: {}",
                logging_file_path.display()
            );
        }
        Err(e) => {
            let message = "There was an issue getting the path for the log file";
            warn!("{}: {:?}, falling back to stderr.", message, e);
        }
    }
    Ok(())
}

fn prepare_logging_path(logfile_config: LogfileConfig) -> Result<PathBuf, io::Error> {
    // Use the file name set in logfile_config or fallback to the default
    let logfile_file_name = match logfile_config.file {
        Some(file_name) => file_name,
        None => XI_LOG_FILE.to_string(),
    };
    // Use the directory name set in logfile_config or fallback to the default
    let logfile_directory_name = match logfile_config.directory {
        Some(dir) => dir,
        None => XI_LOG_DIR.to_string(),
    };

    let mut logging_directory_path = get_logging_directory_path(logfile_directory_name)?;

    // Add the file name & return the full path
    logging_directory_path.push(logfile_file_name);
    Ok(logging_directory_path)
}

struct LogfileConfig {
    directory: Option<String>,
    file: Option<String>,
}

fn get_flags() -> HashMap<String, Option<String>> {
    let mut flags: HashMap<String, Option<String>> = HashMap::new();

    let flag_prefix = "-";
    let mut args_itterator = std::env::args().peekable();
    while let Some(arg) = args_itterator.next() {
        if arg.starts_with(flag_prefix) {
            let key = arg.trim_left_matches(flag_prefix).to_string();

            // Check the next argument doesn't start with the flag prefix
            // map_or accounts for peek returning an Option
            let next_arg_not_a_flag: bool = args_itterator
                .peek()
                .map_or(false, |val| !val.starts_with(flag_prefix));
            if next_arg_not_a_flag {
                flags.insert(key, args_itterator.next());
            }
        }
    }
    flags
}

fn generate_logfile_config(flags: HashMap<String, Option<String>>) -> LogfileConfig {
    // If the key is set, get the Option within
    let log_dir_flag_option = flags.get("log-dir").cloned().unwrap_or(None);
    let log_file_flag_option = flags.get("log-file").cloned().unwrap_or(None);

    LogfileConfig {
        directory: log_dir_flag_option,
        file: log_file_flag_option,
    }
}

fn main() {
    let mut state = XiCore::new();
    let stdin = io::stdin();
    let stdout = io::stdout();
    let mut rpc_looper = RpcLoop::new(stdout);

    let flags: HashMap<String, Option<String>> = get_flags();

    let logfile_config = generate_logfile_config(flags);

    let logging_path: Result<PathBuf, io::Error> = prepare_logging_path(logfile_config);
    if let Err(e) = setup_logging(logging_path) {
        eprintln!(
            "[ERROR] setup_logging returned error, logging disabled: {:?}",
            e
        );
    }

    match rpc_looper.mainloop(|| stdin.lock(), &mut state) {
        Ok(_) => (),
        Err(err) => error!("xi-core exited with error:\n{:?}", err),
    }
}
<commit_msg>Re-added the ability to use env or flags. env gets priority.<commit_after>// Copyright 2016 The xi-editor Authors.
//
// 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.

#[macro_use]
extern crate log;
extern crate chrono;
extern crate fern;

extern crate dirs;

extern crate xi_core_lib;
extern crate xi_rpc;

use std::collections::HashMap;
use std::fs;
use std::io;
use std::path::{Path, PathBuf};

use xi_core_lib::XiCore;
use xi_rpc::RpcLoop;

const XI_LOG_DIR: &str = "xi-core";
const XI_LOG_FILE: &str = "xi-core.log";

fn get_logging_directory_path<P: AsRef<Path>>(directory: P) -> Result<PathBuf, io::Error> {
    match dirs::data_local_dir() {
        Some(mut log_dir) => {
            log_dir.push(directory);
            Ok(log_dir)
        }
        None => Err(io::Error::new(
            io::ErrorKind::NotFound,
            "No standard logging directory known for this platform",
        )),
    }
}

fn setup_logging(logging_path_result: Result<PathBuf, io::Error>) -> Result<(), fern::InitError> {
    let level_filter = match std::env::var("XI_LOG") {
        Ok(level) => match level.to_lowercase().as_ref() {
            "trace" => log::LevelFilter::Trace,
            "debug" => log::LevelFilter::Debug,
            _ => log::LevelFilter::Info,
        },
        // Default to info
        Err(_) => log::LevelFilter::Info,
    };

    let mut fern_dispatch = fern::Dispatch::new()
        .format(|out, message, record| {
            out.finish(format_args!(
                "{}[{}][{}] {}",
                chrono::Local::now().format("[%Y-%m-%d][%H:%M:%S]"),
                record.target(),
                record.level(),
                message,
            ))
        }).level(level_filter)
        .chain(io::stderr());

    if let Ok(logging_file_path) = &logging_path_result {
        // Ensure the logging directory is created
        let parent_path = logging_file_path.parent().ok_or(io::Error::new(
            io::ErrorKind::InvalidInput,
            format!(
                "Unable to get the parent of the following Path: {}",
                logging_file_path.display(),
            ),
        ))?;
        fs::create_dir_all(parent_path)?;
        // Attach it to fern
        fern_dispatch = fern_dispatch.chain(fern::log_file(logging_file_path)?);
    };

    // Start fern
    fern_dispatch.apply()?;
    info!("Logging with fern is setup");

    // Log details of the logging_file_path result using fern/log
    // Either logging the path fern is outputting to or the error from obtaining the path
    match &logging_path_result {
        Ok(logging_file_path) => {
            info!(
                "Logging to the following file: {}",
                logging_file_path.display()
            );
        }
        Err(e) => {
            let message = "There was an issue getting the path for the log file";
            warn!("{}: {:?}, falling back to stderr.", message, e);
        }
    }
    Ok(())
}

fn prepare_logging_path(logfile_config: LogfileConfig) -> Result<PathBuf, io::Error> {
    // Use the file name set in logfile_config or fallback to the default
    let logfile_file_name = match logfile_config.file {
        Some(file_name) => file_name,
        None => XI_LOG_FILE.to_string(),
    };
    // Use the directory name set in logfile_config or fallback to the default
    let logfile_directory_name = match logfile_config.directory {
        Some(dir) => dir,
        None => XI_LOG_DIR.to_string(),
    };

    let mut logging_directory_path = get_logging_directory_path(logfile_directory_name)?;

    // Add the file name & return the full path
    logging_directory_path.push(logfile_file_name);
    Ok(logging_directory_path)
}

struct LogfileConfig {
    directory: Option<String>,
    file: Option<String>,
}

fn get_flags() -> HashMap<String, Option<String>> {
    let mut flags: HashMap<String, Option<String>> = HashMap::new();

    let flag_prefix = "-";
    let mut args_itterator = std::env::args().peekable();
    while let Some(arg) = args_itterator.next() {
        if arg.starts_with(flag_prefix) {
            let key = arg.trim_left_matches(flag_prefix).to_string();

            // Check the next argument doesn't start with the flag prefix
            // map_or accounts for peek returning an Option
            let next_arg_not_a_flag: bool = args_itterator
                .peek()
                .map_or(false, |val| !val.starts_with(flag_prefix));
            if next_arg_not_a_flag {
                flags.insert(key, args_itterator.next());
            }
        }
    }
    flags
}

fn generate_logfile_config(flags: HashMap<String, Option<String>>) -> LogfileConfig {
    // If the key is set, get the Option within
    let log_dir_flag_option = std::env::var("XI_LOG_DIR")
        .ok()
        .or(flags.get("log-dir").cloned().unwrap_or(None));

    let log_file_flag_option = std::env::var("XI_LOG_FILE")
        .ok()
        .or(flags.get("log-file").cloned().unwrap_or(None));

    LogfileConfig {
        directory: log_dir_flag_option,
        file: log_file_flag_option,
    }
}

fn main() {
    let mut state = XiCore::new();
    let stdin = io::stdin();
    let stdout = io::stdout();
    let mut rpc_looper = RpcLoop::new(stdout);

    let flags: HashMap<String, Option<String>> = get_flags();

    let logfile_config = generate_logfile_config(flags);

    let logging_path: Result<PathBuf, io::Error> = prepare_logging_path(logfile_config);
    if let Err(e) = setup_logging(logging_path) {
        eprintln!(
            "[ERROR] setup_logging returned error, logging disabled: {:?}",
            e
        );
    }

    match rpc_looper.mainloop(|| stdin.lock(), &mut state) {
        Ok(_) => (),
        Err(err) => error!("xi-core exited with error:\n{:?}", err),
    }
}
<|endoftext|>


<commit_before>extern crate regex;
extern crate rand;
use rand::Rng;
use std::collections::HashMap;
use regex::Regex;

fn main() {
    let mut dict = HashMap::new();
    let mut prefix = ["", ""];

    let lorem = "Lorem ipsum dolor sit amet, consectetur adipisicing elit. Eum debitis earum quidem dolorem quos consequatur perspiciatis architecto! Reiciendis rem est blanditiis fugiat quidem similique suscipit soluta, ab veniam, laborum numquam. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Eum debitis earum quidem dolorem quos consequatur perspiciatis architecto! Reiciendis rem est blanditiis fugiat quidem similique suscipit soluta, ab veniam, laborum numquam.";

    for token in lorem.split_whitespace() {
        if prefix[0] != "" {

            let key = prefix.join(" ");

            if !dict.contains_key(&key) {
                dict.insert(key, vec![token]);
            } else {
                let v = dict.get_mut(&key).unwrap();
                v.push(token);
            }
        }

        prefix[0] = prefix[1];
        prefix[1] = token;
    }

    // get init key
    let mut init_key = "";
    for key in dict.keys() {
        let c = &key[..1];
        if c.to_uppercase() == c {
            init_key = &key;
            break;
        }
    }

    let mut sentence: Vec<&str> = init_key.split(" ").collect();
    while true {
        let search = [ sentence[sentence.len()-2], sentence[sentence.len()-1] ].join(" ");
        let word = dict.get(&search).unwrap();
        let breakRegex = Regex::new(r"\.|!|\?").unwrap();
        let rand_el = rand::thread_rng().gen_range(0, word.len());
        sentence.push(word[rand_el]);

        if breakRegex.is_match(sentence[sentence.len()-1]) {
            break;
        }
    }

    println!("{:?}", sentence.join(" "));
}
<commit_msg>add base code<commit_after>use std::collections::HashMap;

extern crate rand;
use rand::Rng;

extern crate regex;
use regex::Regex;

fn tokenize(s: &str) -> HashMap<String, Vec<&str>>{
    let mut dict = HashMap::new();
    let mut prefix = ["",""];
    for token in s.split_whitespace() {
        if prefix[0] != "" {
            let key = prefix.join(" ");
            if !dict.contains_key(&key) {
                dict.insert(key, vec![token]);
            } else {
                dict.get_mut(&key).unwrap().push(token);
            }
        }
        prefix[0] = prefix[1];
        prefix[1] = token;
    }
    return dict;
}

#[allow(dead_code)]
struct Generator<'a> {
    dict: HashMap<String, Vec<&'a str>>,
    text: &'a str,
    max: i32
}

impl<'a> Generator<'a> {
    fn new(t: &str) -> Generator{
        let d = tokenize(t);
        Generator { text:t, dict: d, max: 10}
    }

    fn get_init_key(&self) -> &str {
        let mut init_key = "";
        for key in self.dict.keys() {
            let c = &key[..1];
            if c.to_uppercase() == c { // ADD matcher for no punct
                init_key = &key;
                break;
            }
        }
        return init_key;
    }

    fn generate_sentence(&self) -> &str {
        let mut sentence: Vec<&str> = self.get_init_key().split(" ").collect();

        while true {
            let search = [ sentence[sentence.len()-2], sentence[sentence.len()-1] ].join(" ");
            let word = self.dict.get(&search).unwrap();
            sentence.push(word[rand::thread_rng().gen_range(0, word.len())]);

            if Regex::new(r"\.|!|\?").unwrap().is_match(sentence[sentence.len()-1]) {
                break;
            }
        }

        return sentence.join(" ");
    }

    fn generate(&self) -> &str {
        let mut sentences = vec![];
        while count > 0 {
            sentences.push(self.generate_sentence());
            count -= 1;
        }

        return sentences.join(" ");
    }
}

fn main() {
    let g = Generator::new("Lorem ipsum dolor sit amet, consectetur adipisicing elit. Suscipit, assumenda! Error, deserunt quas cumque labore minima obcaecati facere vero temporibus, voluptatem aperiam veritatis rem tempora sequi rerum maxime officia aliquam?");

    // println!("{:?}", g.get_init_key());
}

// fn get_init_token(d: Dict) -> &str {
//     let mut init_key = "";
//     for key in d.keys() {
//         let c = &key[..1];
//         if c.to_uppercase() == c {
//             init_key = &key;
//             break;
//         }
//     }
//     return init_key;
// }

// fn main() {
//     let lorem = "Lorem ipsum dolor sit amet, consectetur adipisicing elit. Quae facilis molestias quos quasi reprehenderit laboriosam ab vel ut, at aliquam in. Corporis veniam ad odio, quisquam voluptatibus fugit nobis facere!";

//     let dict = tokenize(lorem);
//     let init_key = get_init_token(dict);
// }

// // fn main() {
// //     // let mut dict = HashMap::new();
// //     // let mut prefix = ["", ""];

// //     let lorem = "Lorem ipsum dolor sit amet, consectetur adipisicing elit. Soluta molestiae ipsum, ad ab quia dolore, mollitia alias voluptatem modi officia minus ea ratione. Aliquid et dolor atque cupiditate tenetur quaerat!";

// //     let mut dict =tokenize(lorem);

// //     let numSentence = 10;

// //     // get init key
// //     let mut init_key = "";
// //     for key in dict.keys() {
// //         let c = &key[..1];
// //         if c.to_uppercase() == c {
// //             init_key = &key;
// //             break;
// //         }
// //     }

// //     let mut sentence: Vec<&str> = init_key.split(" ").collect();
// //     while true {
// //         let search = [ sentence[sentence.len()-2], sentence[sentence.len()-1] ].join(" ");
// //         let word = dict.get(&search).unwrap();
// //         let breakRegex = Regex::new(r"\.|!|\?").unwrap();let breakRegex = Regex::new(r"\.|!|\?").unwrap();
// //         let rand_el = rand::thread_rng().gen_range(0, word.len());
// //         sentence.push(word[rand_el]);

// //         if breakRegex.is_match(sentence[sentence.len()-1]) {
// //             break;
// //         }
// //     }

// //     println!("{:?}", sentence.join(" "));
// // }
<|endoftext|>


<commit_before>use std::io;
use std::string::String;
use std::io::Write; // Used for flush implicitly?
use std::str;

struct Topping<'a> {
    name: &'a str,
    price: f32
}

struct Pizza<'a> {
    toppings: Vec<Box<Topping<'a>>>
}

fn main() {
    let stdin = io::stdin();
    let name  = get_name(stdin);
    println!("Hello {}", name);
    str_topping(get_topping());
}

fn get_topping<'a>() -> Topping<'a> {
    return Topping {name: "Salami", price: 0.7}
}

fn str_topping(topping: Topping) {
    println!("{} - {}", topping.name, topping.price)
}

fn get_name(stdin: io::Stdin) -> String {
    print!("Enter name: ");
    io::stdout().flush();
    let mut name = String::new();
    stdin.read_line(&mut name);
    return name;
}
<commit_msg>Pizza with to string<commit_after>use std::io;
use std::string::String;
use std::io::Write; // Used for flush implicitly?
use std::str;

struct Topping<'a> {
    name: &'a str,
    price: f32
}

struct Pizza<'a> {
//    toppings: Vec<Box<Topping<'a>>>
    toppings: Vec<Topping<'a>>
}

impl <'a> Pizza<'a> {
    pub fn to_string(&self) -> String {
        return format!("Pizza with {} has price {}", self.toppings[0].name, self.toppings[0].price);
    }
}

fn main() {
    let stdin = io::stdin();
    let name  = get_name(stdin);
    println!("Hello {}", name);
    str_topping(get_topping());
    println!("Pizza is {}", get_pizza().to_string());
}

fn get_pizza<'a>() -> Pizza<'a> {
    return Pizza{toppings:vec!(get_topping())}
}

fn get_topping<'a>() -> Topping<'a> {
    return Topping {name: "Salami", price: 0.7}
}

fn str_topping(topping: Topping) {
    println!("{} - {}", topping.name, topping.price)
}

fn get_name(stdin: io::Stdin) -> String {
    print!("Enter name: ");
    io::stdout().flush();
    let mut name = String::new();
    stdin.read_line(&mut name);
    return name;
}
<|endoftext|>


<commit_before>// Copyright 2016 The xi-editor Authors.
//
// 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.

#[macro_use]
extern crate log;
extern crate chrono;
extern crate fern;

extern crate dirs;

extern crate xi_core_lib;
extern crate xi_rpc;

use std::collections::HashMap;
use std::fs;
use std::io;
use std::path::{Path, PathBuf};

use xi_core_lib::XiCore;
use xi_rpc::RpcLoop;

const XI_LOG_DIR: &str = "xi-core";
const XI_LOG_FILE: &str = "xi-core.log";

fn get_logging_directory_path<P: AsRef<Path>>(directory: P) -> Result<PathBuf, io::Error> {
    match dirs::data_local_dir() {
        Some(mut log_dir) => {
            log_dir.push(directory);
            Ok(log_dir)
        }
        None => Err(io::Error::new(
            io::ErrorKind::NotFound,
            "No standard logging directory known for this platform",
        )),
    }
}

/// This function tries to create the parent directories for a file
///
/// It wraps around the `parent()` function of `Path` which returns an `Option<&Path>` and
/// `fs::create_dir_all` which returns an `io::Result<()`.
///
/// This allows you to use `?`/`try!()` to create the dir and you recive the additional custom error for when `parent()`
/// returns nothing.
///
/// # Errors
/// This can return an `io::Error` if `fs::create_dir_all` fails or if `parent()` returns `None`.
/// See `Path`'s `parent()` function for more details.
/// # Examples
/// ```
/// use std::path::PathBuf;
/// let path_with_file = PathBuf::from("/some/directory/then/file");
/// assert_eq!(Some(OsStr::new("file")), path_with_file.file_name());
/// assert_eq!(create_log_directory(path_with_file).is_ok(), true);
///
/// let path_with_other_file = PathBuf::from("/other_file");
/// assert_eq!(Some(OsStr::new("other_file")), path_with_other_file.file_name());
/// assert_eq!(create_log_directory(path_with_file).is_ok(), true);
///
/// // Path that is just the root or prefix:
/// let path_without_file = PathBuf::from("/");
/// assert_eq!(None, path_with_file.file_name());
/// assert_eq!(create_log_directory(path_with_file).is_ok(), false);
/// ```
fn create_log_directory(path_with_file: &PathBuf) -> Result<(), io::Error> {
    let log_dir = path_with_file.parent().ok_or(io::Error::new(
        io::ErrorKind::InvalidInput,
        format!(
            "Unable to get the parent of the following Path: {}, Your path should contain a file name",
            path_with_file.display(),
        ),
    ))?;
    // Try to create the directory.
    fs::create_dir_all(log_dir)?;
    Ok(())
}

fn setup_logging(logging_path: Option<PathBuf>) -> Result<(), fern::InitError> {
    let level_filter = match std::env::var("XI_LOG") {
        Ok(level) => match level.to_lowercase().as_ref() {
            "trace" => log::LevelFilter::Trace,
            "debug" => log::LevelFilter::Debug,
            _ => log::LevelFilter::Info,
        },
        // Default to info
        Err(_) => log::LevelFilter::Info,
    };

    let mut fern_dispatch = fern::Dispatch::new()
        .format(|out, message, record| {
            out.finish(format_args!(
                "{}[{}][{}] {}",
                chrono::Local::now().format("[%Y-%m-%d][%H:%M:%S]"),
                record.target(),
                record.level(),
                message,
            ))
        }).level(level_filter)
        .chain(io::stderr());

    if let Some(logging_file_path) = &logging_path {
        // Try to create the parent directories for the logging file in the logging file path
        create_log_directory(&logging_file_path)?;

        // Attach it to fern
        fern_dispatch = fern_dispatch.chain(fern::log_file(logging_file_path)?);
    };

    // Start fern
    fern_dispatch.apply()?;
    info!("Logging with fern is set up");

    // Log details of the logging_file_path result using fern/log
    // Either logging the path fern is outputting to or the error from obtaining the path
    match &logging_path {
        Some(logging_file_path) => info!("Writing logs to: {}", logging_file_path.display()),
        None => warn!("No path was supplied for the log file. Not saving logs to disk, falling back to just stderr"),
    }
    Ok(())
}

fn generate_logging_path(logfile_config: LogfileConfig) -> Result<PathBuf, io::Error> {
    // Use the file name set in logfile_config or fallback to the default
    let logfile_file_name = match logfile_config.file {
        Some(file_name) => file_name,
        None => PathBuf::from(XI_LOG_FILE),
    };
    if logfile_file_name.eq(Path::new("")) {
        return Err(io::Error::new(
            io::ErrorKind::InvalidInput,
            "A blank file name was supplied",
        ));
    };
    // Use the directory name set in logfile_config or fallback to the default
    let logfile_directory_name = match logfile_config.directory {
        Some(dir) => dir,
        None => PathBuf::from(XI_LOG_DIR),
    };

    let mut logging_directory_path = get_logging_directory_path(logfile_directory_name)?;

    // Add the file name & return the full path
    logging_directory_path.push(logfile_file_name);
    Ok(logging_directory_path)
}

fn get_flags() -> HashMap<String, Option<String>> {
    let mut flags: HashMap<String, Option<String>> = HashMap::new();

    let flag_prefix = "-";
    let mut args_iterator = std::env::args().peekable();
    while let Some(arg) = args_iterator.next() {
        if arg.starts_with(flag_prefix) {
            let key = arg.trim_left_matches(flag_prefix).to_string();

            // Check the next argument doesn't start with the flag prefix
            // map_or accounts for peek returning an Option
            let next_arg_not_a_flag: bool = args_iterator
                .peek()
                .map_or(false, |val| !val.starts_with(flag_prefix));
            if next_arg_not_a_flag {
                flags.insert(key, args_iterator.next());
            }
        }
    }
    flags
}

struct EnvFlagConfig {
    env_name: &'static str,
    flag_name: &'static str,
}

/// Extracts a value from the flags and the env.
///
/// In this order: `String` from the flags, then `String` from the env, then `None`
fn extract_env_or_flag(
    flags: &HashMap<String, Option<String>>,
    conf: EnvFlagConfig,
) -> Option<String> {
    flags
        .get(conf.flag_name)
        .cloned()
        .unwrap_or(std::env::var(conf.env_name).ok())
}

struct LogfileConfig {
    directory: Option<PathBuf>,
    file: Option<PathBuf>,
}

fn generate_logfile_config(flags: &HashMap<String, Option<String>>) -> LogfileConfig {
    // If the key is set, get the Option within
    let log_dir_env_flag = EnvFlagConfig {
        env_name: "XI_LOG_DIR",
        flag_name: "log-dir",
    };
    let log_file_env_flag = EnvFlagConfig {
        env_name: "XI_LOG_FILE",
        flag_name: "log-file",
    };
    let log_dir_flag_option = extract_env_or_flag(&flags, log_dir_env_flag).map(PathBuf::from);

    let log_file_flag_option = extract_env_or_flag(&flags, log_file_env_flag).map(PathBuf::from);

    LogfileConfig {
        directory: log_dir_flag_option,
        file: log_file_flag_option,
    }
}

fn main() {
    let mut state = XiCore::new();
    let stdin = io::stdin();
    let stdout = io::stdout();
    let mut rpc_looper = RpcLoop::new(stdout);

    let flags: HashMap<String, Option<String>> = get_flags();

    let logfile_config = generate_logfile_config(&flags);

    let logging_path_result: Result<PathBuf, io::Error> = generate_logging_path(logfile_config);

    let mut logging_path: Option<PathBuf> = None;
    let mut logging_error: Option<io::Error> = None;
    match logging_path_result {
        Ok(val) => logging_path = Some(val),
        Err(e) => logging_error = Some(e),
    };
    if let Err(e) = setup_logging(logging_path) {
        eprintln!(
            "[ERROR] setup_logging returned error, logging not enabled: {:?}",
            e
        );
    }
    if let Some(e) = logging_error {
        warn!(
            "Unable to generate the logging path to pass to set up: {}",
            e
        )
    }

    match rpc_looper.mainloop(|| stdin.lock(), &mut state) {
        Ok(_) => (),
        Err(err) => error!("xi-core exited with error:\n{:?}", err),
    }
}
<commit_msg>Removed some unnecessary comments and type definitions.<commit_after>// Copyright 2016 The xi-editor Authors.
//
// 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.

#[macro_use]
extern crate log;
extern crate chrono;
extern crate fern;

extern crate dirs;

extern crate xi_core_lib;
extern crate xi_rpc;

use std::collections::HashMap;
use std::fs;
use std::io;
use std::path::{Path, PathBuf};

use xi_core_lib::XiCore;
use xi_rpc::RpcLoop;

const XI_LOG_DIR: &str = "xi-core";
const XI_LOG_FILE: &str = "xi-core.log";

fn get_logging_directory_path<P: AsRef<Path>>(directory: P) -> Result<PathBuf, io::Error> {
    match dirs::data_local_dir() {
        Some(mut log_dir) => {
            log_dir.push(directory);
            Ok(log_dir)
        }
        None => Err(io::Error::new(
            io::ErrorKind::NotFound,
            "No standard logging directory known for this platform",
        )),
    }
}

/// This function tries to create the parent directories for a file
///
/// It wraps around the `parent()` function of `Path` which returns an `Option<&Path>` and
/// `fs::create_dir_all` which returns an `io::Result<()`.
///
/// This allows you to use `?`/`try!()` to create the dir and you recive the additional custom error for when `parent()`
/// returns nothing.
///
/// # Errors
/// This can return an `io::Error` if `fs::create_dir_all` fails or if `parent()` returns `None`.
/// See `Path`'s `parent()` function for more details.
/// # Examples
/// ```
/// use std::path::PathBuf;
/// let path_with_file = PathBuf::from("/some/directory/then/file");
/// assert_eq!(Some(OsStr::new("file")), path_with_file.file_name());
/// assert_eq!(create_log_directory(path_with_file).is_ok(), true);
///
/// let path_with_other_file = PathBuf::from("/other_file");
/// assert_eq!(Some(OsStr::new("other_file")), path_with_other_file.file_name());
/// assert_eq!(create_log_directory(path_with_file).is_ok(), true);
///
/// // Path that is just the root or prefix:
/// let path_without_file = PathBuf::from("/");
/// assert_eq!(None, path_with_file.file_name());
/// assert_eq!(create_log_directory(path_with_file).is_ok(), false);
/// ```
fn create_log_directory(path_with_file: &PathBuf) -> Result<(), io::Error> {
    let log_dir = path_with_file.parent().ok_or(io::Error::new(
        io::ErrorKind::InvalidInput,
        format!(
            "Unable to get the parent of the following Path: {}, Your path should contain a file name",
            path_with_file.display(),
        ),
    ))?;
    fs::create_dir_all(log_dir)?;
    Ok(())
}

fn setup_logging(logging_path: Option<PathBuf>) -> Result<(), fern::InitError> {
    let level_filter = match std::env::var("XI_LOG") {
        Ok(level) => match level.to_lowercase().as_ref() {
            "trace" => log::LevelFilter::Trace,
            "debug" => log::LevelFilter::Debug,
            _ => log::LevelFilter::Info,
        },
        // Default to info
        Err(_) => log::LevelFilter::Info,
    };

    let mut fern_dispatch = fern::Dispatch::new()
        .format(|out, message, record| {
            out.finish(format_args!(
                "{}[{}][{}] {}",
                chrono::Local::now().format("[%Y-%m-%d][%H:%M:%S]"),
                record.target(),
                record.level(),
                message,
            ))
        }).level(level_filter)
        .chain(io::stderr());

    if let Some(logging_file_path) = &logging_path {
        create_log_directory(&logging_file_path)?;

        fern_dispatch = fern_dispatch.chain(fern::log_file(logging_file_path)?);
    };

    // Start fern
    fern_dispatch.apply()?;
    info!("Logging with fern is set up");

    // Log details of the logging_file_path result using fern/log
    // Either logging the path fern is outputting to or the error from obtaining the path
    match &logging_path {
        Some(logging_file_path) => info!("Writing logs to: {}", logging_file_path.display()),
        None => warn!("No path was supplied for the log file. Not saving logs to disk, falling back to just stderr"),
    }
    Ok(())
}

fn generate_logging_path(logfile_config: LogfileConfig) -> Result<PathBuf, io::Error> {
    // Use the file name set in logfile_config or fallback to the default
    let logfile_file_name = match logfile_config.file {
        Some(file_name) => file_name,
        None => PathBuf::from(XI_LOG_FILE),
    };
    if logfile_file_name.eq(Path::new("")) {
        return Err(io::Error::new(
            io::ErrorKind::InvalidInput,
            "A blank file name was supplied",
        ));
    };
    // Use the directory name set in logfile_config or fallback to the default
    let logfile_directory_name = match logfile_config.directory {
        Some(dir) => dir,
        None => PathBuf::from(XI_LOG_DIR),
    };

    let mut logging_directory_path = get_logging_directory_path(logfile_directory_name)?;

    // Add the file name & return the full path
    logging_directory_path.push(logfile_file_name);
    Ok(logging_directory_path)
}

fn get_flags() -> HashMap<String, Option<String>> {
    let mut flags: HashMap<String, Option<String>> = HashMap::new();

    let flag_prefix = "-";
    let mut args_iterator = std::env::args().peekable();
    while let Some(arg) = args_iterator.next() {
        if arg.starts_with(flag_prefix) {
            let key = arg.trim_left_matches(flag_prefix).to_string();

            // Check the next argument doesn't start with the flag prefix
            // map_or accounts for peek returning an Option
            let next_arg_not_a_flag: bool = args_iterator
                .peek()
                .map_or(false, |val| !val.starts_with(flag_prefix));
            if next_arg_not_a_flag {
                flags.insert(key, args_iterator.next());
            }
        }
    }
    flags
}

struct EnvFlagConfig {
    env_name: &'static str,
    flag_name: &'static str,
}

/// Extracts a value from the flags and the env.
///
/// In this order: `String` from the flags, then `String` from the env, then `None`
fn extract_env_or_flag(
    flags: &HashMap<String, Option<String>>,
    conf: EnvFlagConfig,
) -> Option<String> {
    flags
        .get(conf.flag_name)
        .cloned()
        .unwrap_or(std::env::var(conf.env_name).ok())
}

struct LogfileConfig {
    directory: Option<PathBuf>,
    file: Option<PathBuf>,
}

fn generate_logfile_config(flags: &HashMap<String, Option<String>>) -> LogfileConfig {
    // If the key is set, get the Option within
    let log_dir_env_flag = EnvFlagConfig {
        env_name: "XI_LOG_DIR",
        flag_name: "log-dir",
    };
    let log_file_env_flag = EnvFlagConfig {
        env_name: "XI_LOG_FILE",
        flag_name: "log-file",
    };
    let log_dir_flag_option = extract_env_or_flag(&flags, log_dir_env_flag).map(PathBuf::from);

    let log_file_flag_option = extract_env_or_flag(&flags, log_file_env_flag).map(PathBuf::from);

    LogfileConfig {
        directory: log_dir_flag_option,
        file: log_file_flag_option,
    }
}

fn main() {
    let mut state = XiCore::new();
    let stdin = io::stdin();
    let stdout = io::stdout();
    let mut rpc_looper = RpcLoop::new(stdout);

    let flags = get_flags();

    let logfile_config = generate_logfile_config(&flags);

    let logging_path_result = generate_logging_path(logfile_config);

    let mut logging_path: Option<PathBuf> = None;
    let mut logging_error: Option<io::Error> = None;
    match logging_path_result {
        Ok(val) => logging_path = Some(val),
        Err(e) => logging_error = Some(e),
    };
    if let Err(e) = setup_logging(logging_path) {
        eprintln!(
            "[ERROR] setup_logging returned error, logging not enabled: {:?}",
            e
        );
    }
    if let Some(e) = logging_error {
        warn!(
            "Unable to generate the logging path to pass to set up: {}",
            e
        )
    }

    match rpc_looper.mainloop(|| stdin.lock(), &mut state) {
        Ok(_) => (),
        Err(err) => error!("xi-core exited with error:\n{:?}", err),
    }
}
<|endoftext|>


<commit_before>#[macro_export]
#[doc(hidden)]
macro_rules! __diesel_operator_body {
    (
        notation = $notation:ident,
        struct_name = $name:ident,
        operator = $operator:expr,
        return_ty = $return_ty:ty,
        ty_params = ($($ty_param:ident,)+),
        field_names = ($($field_name:ident,)+),
        backend_ty_params = ($($backend_ty_param:ident,)*),
        backend_ty = $backend_ty:ty,
    ) => {
        #[derive(Debug, Clone, Copy)]
        pub struct $name<$($ty_param,)+> {
            $($field_name: $ty_param,)+
        }

        impl<$($ty_param,)+> $name<$($ty_param,)+> {
            pub fn new($($field_name: $ty_param,)+) -> Self {
                $name { $($field_name,)+ }
            }
        }

        impl_query_id!($name<$($ty_param),+>);
        impl_selectable_expression!($name<$($ty_param),+>);

        impl<$($ty_param,)+> $crate::expression::Expression for $name<$($ty_param,)+> where
            $($ty_param: $crate::expression::Expression,)+
        {
            type SqlType = $return_ty;
        }

        impl<$($ty_param,)+> $crate::expression::NonAggregate for $name<$($ty_param,)+> where
            $($ty_param: $crate::expression::NonAggregate,)+
        {
        }

        impl<$($ty_param,)+ $($backend_ty_param,)*> $crate::query_builder::QueryFragment<$backend_ty>
            for $name<$($ty_param,)+> where
                $($ty_param: $crate::query_builder::QueryFragment<$backend_ty>,)+
                $($backend_ty_param: $crate::backend::Backend,)*
        {
            fn walk_ast(&self, mut out: $crate::query_builder::AstPass<$backend_ty>) -> $crate::result::QueryResult<()> {
                __diesel_operator_to_sql!(
                    notation = $notation,
                    operator_expr = out.push_sql($operator),
                    field_exprs = ($(self.$field_name.walk_ast(out.reborrow())?),+),
                );
                Ok(())
            }
        }

        __diesel_operator_debug_query_fragment_if_needed!(
            backend_ty_params = ($($backend_ty_param,)*),
            notation = $notation,
            struct_name = $name,
            operator = $operator,
            return_ty = $return_ty,
            ty_params = ($($ty_param,)+),
            field_names = ($($field_name,)+),
        );
    }
}

#[macro_export]
#[doc(hidden)]
macro_rules! __diesel_operator_to_sql {
    (
        notation = infix,
        operator_expr = $op:expr,
        field_exprs = ($left:expr, $right:expr),
    ) => {
        $left;
        $op;
        $right;
    };

    (
        notation = postfix,
        operator_expr = $op:expr,
        field_exprs = ($expr:expr),
    ) => {
        $expr;
        $op;
    };

    (
        notation = prefix,
        operator_expr = $op:expr,
        field_exprs = ($expr:expr),
    ) => {
        $op;
        $expr;
    };
}

#[macro_export]
#[doc(hidden)]
macro_rules! __diesel_operator_debug_query_fragment_if_needed {
    // backend_ty_params is empty. This means that we generated `QueryFragment`
    // for a specific backend. We need to generate it for `Debug` as well.
    (
        backend_ty_params = (),
        notation = $notation:ident,
        struct_name = $name:ident,
        operator = $operator:expr,
        return_ty = $return_ty:ty,
        ty_params = ($($ty_param:ident,)+),
        field_names = ($($field_name:ident,)+),
    ) => {
        impl<$($ty_param,)+> $crate::query_builder::QueryFragment<$crate::backend::Debug>
            for $name<$($ty_param,)+> where
                $($ty_param: $crate::query_builder::QueryFragment<$crate::backend::Debug>,)+
        {
            fn walk_ast(&self, mut out: $crate::query_builder::AstPass<$crate::backend::Debug>) -> $crate::result::QueryResult<()> {
                __diesel_operator_to_sql!(
                    notation = $notation,
                    operator_expr = out.push_sql($operator),
                    field_exprs = ($(self.$field_name.walk_ast(out.reborrow())?),+),
                );
                Ok(())
            }
        }

    };

    // At least one backend_ty_param was given. We generated a generic impl
    // which will cover `Debug`.
    (backend_ty_params = ($($backend_ty_params:ident,)+), $($rest:tt)*) => {};
}

/// Useful for libraries adding support for new SQL types. Apps should never
/// need to call this
///
/// This will create a new type with the given name. It will implement all
/// methods needed to be used as an expression in Diesel, placing the given
/// SQL between the two elements. The third argument specifies the SQL type
/// that the operator returns. If it is not given, the type will be assumed
/// to be `Bool`.
///
/// If the operator is specific to a single backend, you can specify this by
/// adding `backend: Pg` or similar as the last argument.
///
/// It should be noted that the generated impls will not constrain the SQL
/// types of the arguments. You should ensure that they are of the right
/// type in your function which constructs the operator.
///
/// Typically you would not expose the type that this generates directly. You'd
/// expose a function (or trait) used to construct the expression, and a helper
/// type which represents the return type of that function. See the
/// `diesel::expression::expression_methods` and
/// `diesel::expression::helper_types` modules for real world examples of this.
///
/// # Examples
///
/// # Possible invocations
///
/// ```ignore
/// // The SQL type will be boolean. The backend will not be constrained
/// diesel_infix_operator!(Matches, " @@ ");
///
/// // Queries which try to execute `Contains` on a backend other than Pg
/// // will fail to compile
/// diesel_infix_operator!(Contains, " @> ", backend: Pg);
///
/// // The type of `Concat` will be `TsVector` rather than Bool
/// diesel_infix_operator!(Concat, " || ", TsVector);
///
/// // It is perfectly fine to have multiple operators with the same SQL.
/// // Diesel will ensure that the queries are always unambiguous in which
/// // operator applies
/// diesel_infix_operator!(Or, " || ", TsQuery);
///
/// // Specifying both the return types and the backend
/// diesel_infix_operator!(And, " && ", TsQuery, backend: Pg);
/// ```
///
/// ## Example usage
///
/// ```rust
/// # #[macro_use] extern crate diesel;
/// # include!("src/doctest_setup.rs");
/// #
/// # table! {
/// #     users {
/// #         id -> Integer,
/// #         name -> VarChar,
/// #     }
/// # }
/// #
/// # fn main() {
/// #     use self::users::dsl::*;
/// #     let connection = establish_connection();
/// diesel_infix_operator!(MyEq, " = ");
///
/// use diesel::expression::AsExpression;
///
/// // Normally you would put this on a trait instead
/// fn my_eq<T, U>(left: T, right: U) -> MyEq<T, U::Expression> where
///     T: Expression,
///     U: AsExpression<T::SqlType>,
/// {
///     MyEq::new(left, right.as_expression())
/// }
///
/// let users_with_name = users.select(id).filter(my_eq(name, "Sean"));
///
/// assert_eq!(Ok(1), users_with_name.first(&connection));
/// # }
/// ```
#[macro_export]
macro_rules! diesel_infix_operator {
    ($name:ident, $operator:expr) => {
        diesel_infix_operator!($name, $operator, $crate::types::Bool);
    };

    ($name:ident, $operator:expr, backend: $backend:ty) => {
        diesel_infix_operator!($name, $operator, $crate::types::Bool, backend: $backend);
    };

    ($name:ident, $operator:expr, $return_ty:ty) => {
        __diesel_operator_body!(
            notation = infix,
            struct_name = $name,
            operator = $operator,
            return_ty = $return_ty,
            ty_params = (T, U,),
            field_names = (left, right,),
            backend_ty_params = (DB,),
            backend_ty = DB,
        );
    };

    ($name:ident, $operator:expr, $return_ty:ty, backend: $backend:ty) => {
        __diesel_operator_body!(
            notation = infix,
            struct_name = $name,
            operator = $operator,
            return_ty = $return_ty,
            ty_params = (T, U,),
            field_names = (left, right,),
            backend_ty_params = (),
            backend_ty = $backend,
        );
    };
}

/// Useful for libraries adding support for new SQL types. Apps should never
/// need to call this
///
/// Similar to [`diesel_infix_operator!`], but the generated type will only take
/// a single argument rather than two. The operator SQL will be placed after
/// the single argument. See [`diesel_infix_operator!`] for example usage.
///
/// [`diesel_infix_operator!`]: macro.diesel_infix_operator.html
#[macro_export]
macro_rules! diesel_postfix_operator {
    ($name:ident, $operator:expr) => {
        diesel_postfix_operator!($name, $operator, $crate::types::Bool);
    };

    ($name:ident, $operator:expr, backend: $backend:ty) => {
        diesel_postfix_operator!($name, $operator, $crate::types::Bool, backend: $backend);
    };

    ($name:ident, $operator:expr, $return_ty:ty) => {
        __diesel_operator_body!(
            notation = postfix,
            struct_name = $name,
            operator = $operator,
            return_ty = $return_ty,
            ty_params = (Expr,),
            field_names = (expr,),
            backend_ty_params = (DB,),
            backend_ty = DB,
        );
    };

    ($name:ident, $operator:expr, $return_ty:ty, backend: $backend:ty) => {
        __diesel_operator_body!(
            notation = postfix,
            struct_name = $name,
            operator = $operator,
            return_ty = $return_ty,
            ty_params = (Expr,),
            field_names = (expr,),
            backend_ty_params = (),
            backend_ty = $backend,
        );
    };
}

/// Useful for libraries adding support for new SQL types. Apps should never
/// need to call this
///
/// Similar to [`diesel_infix_operator!`], but the generated type will only take
/// a single argument rather than two. The operator SQL will be placed before
/// the single argument. See [`diesel_infix_operator!`] for example usage.
///
/// [`diesel_infix_operator!`]: macro.diesel_infix_operator.html
#[macro_export]
macro_rules! diesel_prefix_operator {
    ($name:ident, $operator:expr) => {
        diesel_prefix_operator!($name, $operator, $crate::types::Bool);
    };

    ($name:ident, $operator:expr, backend: $backend:ty) => {
        diesel_prefix_operator!($name, $operator, $crate::types::Bool, backend: $backend);
    };

    ($name:ident, $operator:expr, $return_ty:ty) => {
        __diesel_operator_body!(
            notation = prefix,
            struct_name = $name,
            operator = $operator,
            return_ty = $return_ty,
            ty_params = (Expr,),
            field_names = (expr,),
            backend_ty_params = (DB,),
            backend_ty = DB,
        );
    };

    ($name:ident, $operator:expr, $return_ty:ty, backend: $backend:ty) => {
        __diesel_operator_body!(
            notation = prefix,
            struct_name = $name,
            operator = $operator,
            return_ty = $return_ty,
            ty_params = (Expr,),
            field_names = (expr,),
            backend_ty_params = (),
            backend_ty = $backend,
        );
    };
}

diesel_infix_operator!(Concat, " || ", ::types::Text);
diesel_infix_operator!(And, " AND ");
diesel_infix_operator!(Between, " BETWEEN ");
diesel_infix_operator!(Escape, " ESCAPE ");
diesel_infix_operator!(Eq, " = ");
diesel_infix_operator!(Gt, " > ");
diesel_infix_operator!(GtEq, " >= ");
diesel_infix_operator!(Like, " LIKE ");
diesel_infix_operator!(Lt, " < ");
diesel_infix_operator!(LtEq, " <= ");
diesel_infix_operator!(NotBetween, " NOT BETWEEN ");
diesel_infix_operator!(NotEq, " != ");
diesel_infix_operator!(NotLike, " NOT LIKE ");
diesel_infix_operator!(Or, " OR ");

diesel_postfix_operator!(IsNull, " IS NULL");
diesel_postfix_operator!(IsNotNull, " IS NOT NULL");
diesel_postfix_operator!(Asc, " ASC", ());
diesel_postfix_operator!(Desc, " DESC", ());

diesel_prefix_operator!(Not, "NOT ");

use backend::Backend;
use query_source::Column;
use query_builder::*;
use result::QueryResult;
use super::AppearsOnTable;

impl<T, U, DB> Changeset<DB> for Eq<T, U> where
    DB: Backend,
    T: Column,
    U: AppearsOnTable<T::Table> + QueryFragment<DB>,
{
    fn is_noop(&self) -> bool {
        false
    }

    fn walk_ast(&self, mut out: AstPass<DB>) -> QueryResult<()> {
        try!(out.push_identifier(T::name()));
        out.push_sql(" = ");
        QueryFragment::walk_ast(&self.right, out)
    }
}

impl<T, U> AsChangeset for Eq<T, U> where
    T: Column,
    U: AppearsOnTable<T::Table>,
{
    type Target = T::Table;
    type Changeset = Self;

    fn as_changeset(self) -> Self {
        self
    }
}
<commit_msg>✂ blank line<commit_after>#[macro_export]
#[doc(hidden)]
macro_rules! __diesel_operator_body {
    (
        notation = $notation:ident,
        struct_name = $name:ident,
        operator = $operator:expr,
        return_ty = $return_ty:ty,
        ty_params = ($($ty_param:ident,)+),
        field_names = ($($field_name:ident,)+),
        backend_ty_params = ($($backend_ty_param:ident,)*),
        backend_ty = $backend_ty:ty,
    ) => {
        #[derive(Debug, Clone, Copy)]
        pub struct $name<$($ty_param,)+> {
            $($field_name: $ty_param,)+
        }

        impl<$($ty_param,)+> $name<$($ty_param,)+> {
            pub fn new($($field_name: $ty_param,)+) -> Self {
                $name { $($field_name,)+ }
            }
        }

        impl_query_id!($name<$($ty_param),+>);
        impl_selectable_expression!($name<$($ty_param),+>);

        impl<$($ty_param,)+> $crate::expression::Expression for $name<$($ty_param,)+> where
            $($ty_param: $crate::expression::Expression,)+
        {
            type SqlType = $return_ty;
        }

        impl<$($ty_param,)+> $crate::expression::NonAggregate for $name<$($ty_param,)+> where
            $($ty_param: $crate::expression::NonAggregate,)+
        {
        }

        impl<$($ty_param,)+ $($backend_ty_param,)*> $crate::query_builder::QueryFragment<$backend_ty>
            for $name<$($ty_param,)+> where
                $($ty_param: $crate::query_builder::QueryFragment<$backend_ty>,)+
                $($backend_ty_param: $crate::backend::Backend,)*
        {
            fn walk_ast(&self, mut out: $crate::query_builder::AstPass<$backend_ty>) -> $crate::result::QueryResult<()> {
                __diesel_operator_to_sql!(
                    notation = $notation,
                    operator_expr = out.push_sql($operator),
                    field_exprs = ($(self.$field_name.walk_ast(out.reborrow())?),+),
                );
                Ok(())
            }
        }

        __diesel_operator_debug_query_fragment_if_needed!(
            backend_ty_params = ($($backend_ty_param,)*),
            notation = $notation,
            struct_name = $name,
            operator = $operator,
            return_ty = $return_ty,
            ty_params = ($($ty_param,)+),
            field_names = ($($field_name,)+),
        );
    }
}

#[macro_export]
#[doc(hidden)]
macro_rules! __diesel_operator_to_sql {
    (
        notation = infix,
        operator_expr = $op:expr,
        field_exprs = ($left:expr, $right:expr),
    ) => {
        $left;
        $op;
        $right;
    };

    (
        notation = postfix,
        operator_expr = $op:expr,
        field_exprs = ($expr:expr),
    ) => {
        $expr;
        $op;
    };

    (
        notation = prefix,
        operator_expr = $op:expr,
        field_exprs = ($expr:expr),
    ) => {
        $op;
        $expr;
    };
}

#[macro_export]
#[doc(hidden)]
macro_rules! __diesel_operator_debug_query_fragment_if_needed {
    // backend_ty_params is empty. This means that we generated `QueryFragment`
    // for a specific backend. We need to generate it for `Debug` as well.
    (
        backend_ty_params = (),
        notation = $notation:ident,
        struct_name = $name:ident,
        operator = $operator:expr,
        return_ty = $return_ty:ty,
        ty_params = ($($ty_param:ident,)+),
        field_names = ($($field_name:ident,)+),
    ) => {
        impl<$($ty_param,)+> $crate::query_builder::QueryFragment<$crate::backend::Debug>
            for $name<$($ty_param,)+> where
                $($ty_param: $crate::query_builder::QueryFragment<$crate::backend::Debug>,)+
        {
            fn walk_ast(&self, mut out: $crate::query_builder::AstPass<$crate::backend::Debug>) -> $crate::result::QueryResult<()> {
                __diesel_operator_to_sql!(
                    notation = $notation,
                    operator_expr = out.push_sql($operator),
                    field_exprs = ($(self.$field_name.walk_ast(out.reborrow())?),+),
                );
                Ok(())
            }
        }
    };

    // At least one backend_ty_param was given. We generated a generic impl
    // which will cover `Debug`.
    (backend_ty_params = ($($backend_ty_params:ident,)+), $($rest:tt)*) => {};
}

/// Useful for libraries adding support for new SQL types. Apps should never
/// need to call this
///
/// This will create a new type with the given name. It will implement all
/// methods needed to be used as an expression in Diesel, placing the given
/// SQL between the two elements. The third argument specifies the SQL type
/// that the operator returns. If it is not given, the type will be assumed
/// to be `Bool`.
///
/// If the operator is specific to a single backend, you can specify this by
/// adding `backend: Pg` or similar as the last argument.
///
/// It should be noted that the generated impls will not constrain the SQL
/// types of the arguments. You should ensure that they are of the right
/// type in your function which constructs the operator.
///
/// Typically you would not expose the type that this generates directly. You'd
/// expose a function (or trait) used to construct the expression, and a helper
/// type which represents the return type of that function. See the
/// `diesel::expression::expression_methods` and
/// `diesel::expression::helper_types` modules for real world examples of this.
///
/// # Examples
///
/// # Possible invocations
///
/// ```ignore
/// // The SQL type will be boolean. The backend will not be constrained
/// diesel_infix_operator!(Matches, " @@ ");
///
/// // Queries which try to execute `Contains` on a backend other than Pg
/// // will fail to compile
/// diesel_infix_operator!(Contains, " @> ", backend: Pg);
///
/// // The type of `Concat` will be `TsVector` rather than Bool
/// diesel_infix_operator!(Concat, " || ", TsVector);
///
/// // It is perfectly fine to have multiple operators with the same SQL.
/// // Diesel will ensure that the queries are always unambiguous in which
/// // operator applies
/// diesel_infix_operator!(Or, " || ", TsQuery);
///
/// // Specifying both the return types and the backend
/// diesel_infix_operator!(And, " && ", TsQuery, backend: Pg);
/// ```
///
/// ## Example usage
///
/// ```rust
/// # #[macro_use] extern crate diesel;
/// # include!("src/doctest_setup.rs");
/// #
/// # table! {
/// #     users {
/// #         id -> Integer,
/// #         name -> VarChar,
/// #     }
/// # }
/// #
/// # fn main() {
/// #     use self::users::dsl::*;
/// #     let connection = establish_connection();
/// diesel_infix_operator!(MyEq, " = ");
///
/// use diesel::expression::AsExpression;
///
/// // Normally you would put this on a trait instead
/// fn my_eq<T, U>(left: T, right: U) -> MyEq<T, U::Expression> where
///     T: Expression,
///     U: AsExpression<T::SqlType>,
/// {
///     MyEq::new(left, right.as_expression())
/// }
///
/// let users_with_name = users.select(id).filter(my_eq(name, "Sean"));
///
/// assert_eq!(Ok(1), users_with_name.first(&connection));
/// # }
/// ```
#[macro_export]
macro_rules! diesel_infix_operator {
    ($name:ident, $operator:expr) => {
        diesel_infix_operator!($name, $operator, $crate::types::Bool);
    };

    ($name:ident, $operator:expr, backend: $backend:ty) => {
        diesel_infix_operator!($name, $operator, $crate::types::Bool, backend: $backend);
    };

    ($name:ident, $operator:expr, $return_ty:ty) => {
        __diesel_operator_body!(
            notation = infix,
            struct_name = $name,
            operator = $operator,
            return_ty = $return_ty,
            ty_params = (T, U,),
            field_names = (left, right,),
            backend_ty_params = (DB,),
            backend_ty = DB,
        );
    };

    ($name:ident, $operator:expr, $return_ty:ty, backend: $backend:ty) => {
        __diesel_operator_body!(
            notation = infix,
            struct_name = $name,
            operator = $operator,
            return_ty = $return_ty,
            ty_params = (T, U,),
            field_names = (left, right,),
            backend_ty_params = (),
            backend_ty = $backend,
        );
    };
}

/// Useful for libraries adding support for new SQL types. Apps should never
/// need to call this
///
/// Similar to [`diesel_infix_operator!`], but the generated type will only take
/// a single argument rather than two. The operator SQL will be placed after
/// the single argument. See [`diesel_infix_operator!`] for example usage.
///
/// [`diesel_infix_operator!`]: macro.diesel_infix_operator.html
#[macro_export]
macro_rules! diesel_postfix_operator {
    ($name:ident, $operator:expr) => {
        diesel_postfix_operator!($name, $operator, $crate::types::Bool);
    };

    ($name:ident, $operator:expr, backend: $backend:ty) => {
        diesel_postfix_operator!($name, $operator, $crate::types::Bool, backend: $backend);
    };

    ($name:ident, $operator:expr, $return_ty:ty) => {
        __diesel_operator_body!(
            notation = postfix,
            struct_name = $name,
            operator = $operator,
            return_ty = $return_ty,
            ty_params = (Expr,),
            field_names = (expr,),
            backend_ty_params = (DB,),
            backend_ty = DB,
        );
    };

    ($name:ident, $operator:expr, $return_ty:ty, backend: $backend:ty) => {
        __diesel_operator_body!(
            notation = postfix,
            struct_name = $name,
            operator = $operator,
            return_ty = $return_ty,
            ty_params = (Expr,),
            field_names = (expr,),
            backend_ty_params = (),
            backend_ty = $backend,
        );
    };
}

/// Useful for libraries adding support for new SQL types. Apps should never
/// need to call this
///
/// Similar to [`diesel_infix_operator!`], but the generated type will only take
/// a single argument rather than two. The operator SQL will be placed before
/// the single argument. See [`diesel_infix_operator!`] for example usage.
///
/// [`diesel_infix_operator!`]: macro.diesel_infix_operator.html
#[macro_export]
macro_rules! diesel_prefix_operator {
    ($name:ident, $operator:expr) => {
        diesel_prefix_operator!($name, $operator, $crate::types::Bool);
    };

    ($name:ident, $operator:expr, backend: $backend:ty) => {
        diesel_prefix_operator!($name, $operator, $crate::types::Bool, backend: $backend);
    };

    ($name:ident, $operator:expr, $return_ty:ty) => {
        __diesel_operator_body!(
            notation = prefix,
            struct_name = $name,
            operator = $operator,
            return_ty = $return_ty,
            ty_params = (Expr,),
            field_names = (expr,),
            backend_ty_params = (DB,),
            backend_ty = DB,
        );
    };

    ($name:ident, $operator:expr, $return_ty:ty, backend: $backend:ty) => {
        __diesel_operator_body!(
            notation = prefix,
            struct_name = $name,
            operator = $operator,
            return_ty = $return_ty,
            ty_params = (Expr,),
            field_names = (expr,),
            backend_ty_params = (),
            backend_ty = $backend,
        );
    };
}

diesel_infix_operator!(Concat, " || ", ::types::Text);
diesel_infix_operator!(And, " AND ");
diesel_infix_operator!(Between, " BETWEEN ");
diesel_infix_operator!(Escape, " ESCAPE ");
diesel_infix_operator!(Eq, " = ");
diesel_infix_operator!(Gt, " > ");
diesel_infix_operator!(GtEq, " >= ");
diesel_infix_operator!(Like, " LIKE ");
diesel_infix_operator!(Lt, " < ");
diesel_infix_operator!(LtEq, " <= ");
diesel_infix_operator!(NotBetween, " NOT BETWEEN ");
diesel_infix_operator!(NotEq, " != ");
diesel_infix_operator!(NotLike, " NOT LIKE ");
diesel_infix_operator!(Or, " OR ");

diesel_postfix_operator!(IsNull, " IS NULL");
diesel_postfix_operator!(IsNotNull, " IS NOT NULL");
diesel_postfix_operator!(Asc, " ASC", ());
diesel_postfix_operator!(Desc, " DESC", ());

diesel_prefix_operator!(Not, "NOT ");

use backend::Backend;
use query_source::Column;
use query_builder::*;
use result::QueryResult;
use super::AppearsOnTable;

impl<T, U, DB> Changeset<DB> for Eq<T, U> where
    DB: Backend,
    T: Column,
    U: AppearsOnTable<T::Table> + QueryFragment<DB>,
{
    fn is_noop(&self) -> bool {
        false
    }

    fn walk_ast(&self, mut out: AstPass<DB>) -> QueryResult<()> {
        try!(out.push_identifier(T::name()));
        out.push_sql(" = ");
        QueryFragment::walk_ast(&self.right, out)
    }
}

impl<T, U> AsChangeset for Eq<T, U> where
    T: Column,
    U: AppearsOnTable<T::Table>,
{
    type Target = T::Table;
    type Changeset = Self;

    fn as_changeset(self) -> Self {
        self
    }
}
<|endoftext|>


<commit_before>// Copyright 2017 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use std::result;
use std::io;

use libc::__errno_location;

/// An error number, retrieved from errno (man 3 errno), set by a libc
/// function that returned an error.
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Error(i32);
pub type Result<T> = result::Result<T, Error>;

impl Error {
    /// Constructs a new error with the given errno.
    pub fn new(e: i32) -> Error {
        Error(e)
    }

    /// Constructs an error from the current errno.
    ///
    /// The result of this only has any meaning just after a libc call that returned a value
    /// indicating errno was set.
    pub fn last() -> Error {
        Error(unsafe { *__errno_location() })
    }

    /// Gets the errno for this error
    pub fn errno(&self) -> i32 {
        self.0
    }
}

impl From<io::Error> for Error {
    fn from(e: io::Error) -> Self {
        Error::new(e.raw_os_error().unwrap_or_default())
    }
}

/// Returns the last errno as a Result that is always an error.
pub fn errno_result<T>() -> Result<T> {
    Err(Error::last())
}
<commit_msg>sys_util: implement error trait for sys_util::Error<commit_after>// Copyright 2017 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use std::result;
use std::io;
use std::error;
use std::fmt::{self, Display};

use libc::__errno_location;

/// An error number, retrieved from errno (man 3 errno), set by a libc
/// function that returned an error.
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Error(i32);
pub type Result<T> = result::Result<T, Error>;

impl Error {
    /// Constructs a new error with the given errno.
    pub fn new(e: i32) -> Error {
        Error(e)
    }

    /// Constructs an error from the current errno.
    ///
    /// The result of this only has any meaning just after a libc call that returned a value
    /// indicating errno was set.
    pub fn last() -> Error {
        Error(unsafe { *__errno_location() })
    }

    /// Gets the errno for this error
    pub fn errno(&self) -> i32 {
        self.0
    }
}

impl From<io::Error> for Error {
    fn from(e: io::Error) -> Self {
        Error::new(e.raw_os_error().unwrap_or_default())
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        "System returned an error code"
    }
}

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

/// Returns the last errno as a Result that is always an error.
pub fn errno_result<T>() -> Result<T> {
    Err(Error::last())
}
<|endoftext|>


<commit_before>// Copyright 2017 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use std::result;
use std::io;

use libc::__errno_location;

/// An error number, retrieved from errno (man 3 errno), set by a libc
/// function that returned an error.
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Error(i32);
pub type Result<T> = result::Result<T, Error>;

impl Error {
    /// Constructs a new error with the given errno.
    pub fn new(e: i32) -> Error {
        Error(e)
    }

    /// Constructs an error from the current errno.
    ///
    /// The result of this only has any meaning just after a libc call that returned a value
    /// indicating errno was set.
    pub fn last() -> Error {
        Error(unsafe { *__errno_location() })
    }

    /// Gets the errno for this error
    pub fn errno(&self) -> i32 {
        self.0
    }
}

impl From<io::Error> for Error {
    fn from(e: io::Error) -> Self {
        Error::new(e.raw_os_error().unwrap_or_default())
    }
}

/// Returns the last errno as a Result that is always an error.
pub fn errno_result<T>() -> Result<T> {
    Err(Error::last())
}
<commit_msg>sys_util: errno: add invalid_fd_test<commit_after>// Copyright 2017 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use std::result;
use std::io;

use libc::__errno_location;

/// An error number, retrieved from errno (man 3 errno), set by a libc
/// function that returned an error.
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Error(i32);
pub type Result<T> = result::Result<T, Error>;

impl Error {
    /// Constructs a new error with the given errno.
    pub fn new(e: i32) -> Error {
        Error(e)
    }

    /// Constructs an error from the current errno.
    ///
    /// The result of this only has any meaning just after a libc call that returned a value
    /// indicating errno was set.
    pub fn last() -> Error {
        Error(unsafe { *__errno_location() })
    }

    /// Gets the errno for this error
    pub fn errno(&self) -> i32 {
        self.0
    }
}

impl From<io::Error> for Error {
    fn from(e: io::Error) -> Self {
        Error::new(e.raw_os_error().unwrap_or_default())
    }
}

/// Returns the last errno as a Result that is always an error.
pub fn errno_result<T>() -> Result<T> {
    Err(Error::last())
}

#[cfg(test)]
mod tests {
    use super::*;
    use libc;
    use std::fs::File;
    use std::io::{self, Write};
    use std::os::unix::io::FromRawFd;

    #[test]
    fn invalid_fd() {
        let mut file = unsafe { File::from_raw_fd(-1) };
        assert!(file.write(b"test").is_err());
        let last_err = errno_result::<i32>().unwrap_err();
        assert_eq!(last_err, Error::new(libc::EBADF));
        assert_eq!(last_err.errno(), libc::EBADF);
        assert_eq!(last_err, Error::from(io::Error::last_os_error()));
    }
}
<|endoftext|>


<commit_before>//! Utility functions for testing

use std::path::PathBuf;

// Expose `pretty_assertions` for use by other internal crates
pub use pretty_assertions;

/// Get the path of the home directory of this repository
pub fn home() -> PathBuf {
    PathBuf::from(env!("CARGO_MANIFEST_DIR"))
        .join("../../..")
        .canonicalize()
        .expect("Unable to get repository home directory")
}

/// Get the path of the `fixtures` directory
pub fn fixtures() -> PathBuf {
    home().join("fixtures")
}

/// Assert that two nodes are equal based on their `Debug` display
///
/// Indented debug display is used as it more easily allows differences to be
/// seen. It has the advantage over `assert_json_eq` of not requiring another dependency
#[macro_export]
macro_rules! assert_debug_eq {
    ($a:expr, $b:expr) => {
        test_utils::pretty_assertions::assert_eq!(format!("{:#?}", $a), format!("{:#?}", $b));
    };
}

/// Assert that two nodes are equal based on their JSON representation
#[macro_export]
macro_rules! assert_json_eq {
    ($a:expr, $b:expr) => {
        test_utils::pretty_assertions::assert_eq!(
            serde_json::to_value(&$a).unwrap(),
            serde_json::to_value(&$b).unwrap()
        );
    };
}
<commit_msg>test(Utils): Add `skip_slow_tests` function<commit_after>//! Utility functions for testing

use std::path::PathBuf;

// Expose `pretty_assertions` for use by other internal crates
pub use pretty_assertions;

/// Get the path of the home directory of this repository
pub fn home() -> PathBuf {
    PathBuf::from(env!("CARGO_MANIFEST_DIR"))
        .join("../../..")
        .canonicalize()
        .expect("Unable to get repository home directory")
}

/// Get the path of the `fixtures` directory
pub fn fixtures() -> PathBuf {
    home().join("fixtures")
}

/// Should slow tests be skipped?
///
/// Use at the start of slow tests to return early except on CI or when
/// the env var `RUN_SLOW_TESTS` is set.
///
/// Inspired by https://github.com/rust-analyzer/rust-analyzer/pull/2491
pub fn skip_slow_tests() -> bool {
    if std::env::var("CI").is_err() && std::env::var("RUN_SLOW_TESTS").is_err() {
        eprintln!("Skipping slow test");
        true
    } else {
        false
    }
}

/// Assert that two nodes are equal based on their `Debug` display
///
/// Indented debug display is used as it more easily allows differences to be
/// seen. It has the advantage over `assert_json_eq` of not requiring another dependency
#[macro_export]
macro_rules! assert_debug_eq {
    ($a:expr, $b:expr) => {
        test_utils::pretty_assertions::assert_eq!(format!("{:#?}", $a), format!("{:#?}", $b));
    };
}

/// Assert that two nodes are equal based on their JSON representation
#[macro_export]
macro_rules! assert_json_eq {
    ($a:expr, $b:expr) => {
        test_utils::pretty_assertions::assert_eq!(
            serde_json::to_value(&$a).unwrap(),
            serde_json::to_value(&$b).unwrap()
        );
    };
}
<|endoftext|>


<commit_before>pub enum GTPError {
    NotImplemented,
    InvalidBoardSize,
    InvalidMove,
    BadVertexList,
    BoardNotEmpty,
    CannotUndo,
}

pub enum Colour {
    Black,
    White
}

#[allow(dead_code)]
pub struct Vertex {
    x: u8, // letter
    y: u8  // number
}

pub enum Move {
    Stone(Vertex),
    Pass,
    Resign
}

#[allow(dead_code)]
pub struct ColouredMove {
    player: Colour,
    move: Move
}

pub enum StoneStatus {
    Alive,
    Seki,
    Dead
}

pub trait GoBot {
    // Static functions identifying the bot :

    // name (ex : "My super Bot")
    fn gtp_name() -> &'static str;
    // version (ex : "v2.3-r5")
    fn gtp_version() -> &'static str;

    // Any function returning a GTPError that it is not supposed
    // to return will be fatal to the framework.

    // Basic functions, must be implemented

    // clear_board : clears the board, can never fail
    fn gtp_clear_board(&mut self) -> ();
    // komi : sets the komi, can never fail, must accept absurd values
    fn gtp_komi(&mut self, komi: f32) -> ();
    // boardsize : sets the board size.
    // Returns InvalidBoardSize if the size is not supported.
    fn gtp_boardsize(&mut self, size: uint) -> Result<(), GTPError>;
    // play : plays the provided move on the board
    // Returns InvalidMove is the move is invalid
    fn gtp_play(&mut self, move: ColouredMove) -> Result<(), GTPError>;
    // genmove : ask the bot for a move of the chosen color
    // cannot fail, the bot must provide a move even if the last
    // played move is of the same colour
    // plays the move as well
    fn gtp_genmove(&mut self, player: Colour) -> Move;

    // Optional functions, if not iplemented, the corresponding
    // commands will not be activated
    // All these functions will be called once by the framework
    // at startup, then clear_board will be called

    // genmove_regression : like genmove, but must be deterministic
    // and must not actually play the move
    // should always return Ok(Move), never raise any error
    #[allow(unused_variable)]
    fn gtp_genmove_regression(&self, player: Colour) -> Result<Move, GTPError> {
        Err(NotImplemented)
    }
    // undo : undo last move if possible
    // if not, return Err(CannotUndo)
    // if undo is never possible, should not be implemented
    #[allow(unused_variable)]
    fn gtp_undo(&mut self) -> Result<(), GTPError> {
        Err(NotImplemented)
    }
    // place_free_handicap : The bot places its handicap stones
    // and returns a slice to a vector of Vertexes
    // it can place less stones if the asked number is too high
    // fails with Err(BoardNotEmpty) if board isn't empty
    #[allow(unused_variable)]
    fn gtp_place_free_handicap(&mut self, number: uint) -> Result<&[Vertex], GTPError> {
        Err(NotImplemented)
    }
    // set_free_handicap : uses the provided list as handicap stones
    // for black
    // fails with Err(BoardNotEmpty) if board isn't empty
    // fails woth Err(BadVertexList) if the vertex list is unusable
    // (two stones at the same place, or stones outside the board)
    #[allow(unused_variable)]
    fn gtp_set_free_handicap(&mut self, stones: &[Vertex]) -> Result<(), GTPError> {
        Err(NotImplemented)
    }
    // time_settings : sets the time settings for the game
    // it is only informative, the btot should count it's own time,
    // but the controller is supposed to enforce it
    // time are give in minute, should never fail
    #[allow(unused_variable)]
    fn gtp_time_settings(&mut self, main_time: int, byoyomi_time: int, byoyomi_stones: int) -> Result<(), GTPError> {
        Err(NotImplemented)
    }
    // final_status_list : returns a slice to the list of stones of
    // any color in the given status, in the opinion of the bot
    // should never fail
    #[allow(unused_variable)]
    fn gtp_final_status_list(&self, status: StoneStatus) -> Result<(), GTPError> {
        Err(NotImplemented)
    }
    // final_score : computes the bot's calculation of the final score
    // if it is a draw, float value must be 0 and colour is not important
    // should never fail
    #[allow(unused_variable)]
    fn gtp_final_score(&self) -> Result<(f32, Colour), GTPError> {
        Err(NotImplemented)
    }
    // showboard : returns a description of the board as saw by the bot :
    // (boardsize, black_stones, white_stones, black_captured_count, white_captured_count)
    // should never fail
    #[allow(unused_variable)]
    fn gtp_showboard(&self) -> Result<(int, &[Vertex], &[Vertex], int, int), GTPError> {
        Err(NotImplemented)
    }
}
<commit_msg>Vertex impl.<commit_after>pub enum GTPError {
    NotImplemented,
    InvalidBoardSize,
    InvalidMove,
    BadVertexList,
    BoardNotEmpty,
    CannotUndo,
}

pub enum Colour {
    Black,
    White
}

#[allow(dead_code)]
pub struct Vertex {
    x: u8, // letter
    y: u8  // number
}

pub enum Move {
    Stone(Vertex),
    Pass,
    Resign
}

#[allow(dead_code)]
pub struct ColouredMove {
    player: Colour,
    move: Move
}

pub enum StoneStatus {
    Alive,
    Seki,
    Dead
}

pub trait GoBot {
    // Static functions identifying the bot :

    // name (ex : "My super Bot")
    fn gtp_name() -> &'static str;
    // version (ex : "v2.3-r5")
    fn gtp_version() -> &'static str;

    // Any function returning a GTPError that it is not supposed
    // to return will be fatal to the framework.

    // Basic functions, must be implemented

    // clear_board : clears the board, can never fail
    fn gtp_clear_board(&mut self) -> ();
    // komi : sets the komi, can never fail, must accept absurd values
    fn gtp_komi(&mut self, komi: f32) -> ();
    // boardsize : sets the board size.
    // Returns InvalidBoardSize if the size is not supported.
    fn gtp_boardsize(&mut self, size: uint) -> Result<(), GTPError>;
    // play : plays the provided move on the board
    // Returns InvalidMove is the move is invalid
    fn gtp_play(&mut self, move: ColouredMove) -> Result<(), GTPError>;
    // genmove : ask the bot for a move of the chosen color
    // cannot fail, the bot must provide a move even if the last
    // played move is of the same colour
    // plays the move as well
    fn gtp_genmove(&mut self, player: Colour) -> Move;

    // Optional functions, if not iplemented, the corresponding
    // commands will not be activated
    // All these functions will be called once by the framework
    // at startup, then clear_board will be called

    // genmove_regression : like genmove, but must be deterministic
    // and must not actually play the move
    // should always return Ok(Move), never raise any error
    #[allow(unused_variable)]
    fn gtp_genmove_regression(&self, player: Colour) -> Result<Move, GTPError> {
        Err(NotImplemented)
    }
    // undo : undo last move if possible
    // if not, return Err(CannotUndo)
    // if undo is never possible, should not be implemented
    #[allow(unused_variable)]
    fn gtp_undo(&mut self) -> Result<(), GTPError> {
        Err(NotImplemented)
    }
    // place_free_handicap : The bot places its handicap stones
    // and returns a slice to a vector of Vertexes
    // it can place less stones if the asked number is too high
    // fails with Err(BoardNotEmpty) if board isn't empty
    #[allow(unused_variable)]
    fn gtp_place_free_handicap(&mut self, number: uint) -> Result<&[Vertex], GTPError> {
        Err(NotImplemented)
    }
    // set_free_handicap : uses the provided list as handicap stones
    // for black
    // fails with Err(BoardNotEmpty) if board isn't empty
    // fails woth Err(BadVertexList) if the vertex list is unusable
    // (two stones at the same place, or stones outside the board)
    #[allow(unused_variable)]
    fn gtp_set_free_handicap(&mut self, stones: &[Vertex]) -> Result<(), GTPError> {
        Err(NotImplemented)
    }
    // time_settings : sets the time settings for the game
    // it is only informative, the btot should count it's own time,
    // but the controller is supposed to enforce it
    // time are give in minute, should never fail
    #[allow(unused_variable)]
    fn gtp_time_settings(&mut self, main_time: int, byoyomi_time: int, byoyomi_stones: int) -> Result<(), GTPError> {
        Err(NotImplemented)
    }
    // final_status_list : returns a slice to the list of stones of
    // any color in the given status, in the opinion of the bot
    // should never fail
    #[allow(unused_variable)]
    fn gtp_final_status_list(&self, status: StoneStatus) -> Result<(), GTPError> {
        Err(NotImplemented)
    }
    // final_score : computes the bot's calculation of the final score
    // if it is a draw, float value must be 0 and colour is not important
    // should never fail
    #[allow(unused_variable)]
    fn gtp_final_score(&self) -> Result<(f32, Colour), GTPError> {
        Err(NotImplemented)
    }
    // showboard : returns a description of the board as saw by the bot :
    // (boardsize, black_stones, white_stones, black_captured_count, white_captured_count)
    // should never fail
    #[allow(unused_variable)]
    fn gtp_showboard(&self) -> Result<(int, &[Vertex], &[Vertex], int, int), GTPError> {
        Err(NotImplemented)
    }
}

// Vertex implementation for messing with strings
impl Vertex {
    #[allow(dead_code)]
    pub fn from_coords(x: u8, y:u8) -> Vertex {
        if x == 0 || x > 25 || y == 0 || y > 25 {
            fail!("Vertex coordinates must be in 1-25.");
        }
        Vertex{x: x, y: y}
    }

    #[allow(dead_code)]
    pub fn from_str(text: &str) -> Vertex {
        if text.len() < 2 || text.len() > 3 {
            fail!("Invalid text coordinates.");
        }
        let mut x: u8 = text[0];
        if x < ('A' as u8) || x > ('Z' as u8) || (x as char) == 'I' {
            fail!("Invalid text coordinates.");
        }
        x -= ('A' as u8) - 1;
        if x > 9 {
            x -= 1;
        } // eliminate 'I'
        let number = ::std::u8::parse_bytes(text.as_bytes().slice_from(1), 10);
        let mut y: u8 = 0;
        match number {
            Some(num) => y = num,
            _ => (),
        }
        if y == 0 || y > 25 {
            fail!("Invalid text coordinates.");
        }
        Vertex{x: x, y: y}
    }

    #[allow(dead_code)]
    pub fn to_coords(&self) -> (u8, u8) {
        (self.x, self.y)
    }

    #[allow(dead_code)]
    pub fn to_string(&self) -> String {
        let mut letter: u8 = 'A' as u8;
        if self.x >= 9 {
            // eliminate 'I'
            letter += self.x;
        } else {
            letter += self.x-1;
        }
        format!("{:c}{:u}", letter as char, self.y)
    }
}

#[cfg(test)]
mod tests {
    #[test]
    fn vertex_to_string() {
        let vrtx1 = super::Vertex::from_coords(8u8, 7u8);
        assert_eq!(vrtx1.to_string().as_slice(), "H7");
        let vrtx2 = super::Vertex::from_coords(9u8, 13u8);
        assert_eq!(vrtx2.to_string().as_slice(), "J13");
        let vrtx3 = super::Vertex::from_coords(19u8, 1u8);
        assert_eq!(vrtx3.to_string().as_slice(), "T1");
    }

    #[test]
    fn string_to_vertex() {
        let vrtx1 = super::Vertex::from_str("C7");
        assert_eq!(vrtx1.to_coords(), (3u8, 7u8));
        let vrtx2 = super::Vertex::from_str("J11");
        assert_eq!(vrtx2.to_coords(), (9u8, 11u8));
        let vrtx3 = super::Vertex::from_str("Z25");
        assert_eq!(vrtx3.to_coords(), (25u8, 25u8));
    }

    #[test]
    #[should_fail]
    fn too_big_coordinates() {
        let vrtx = super::Vertex::from_coords(26u8, 13u8);
        assert_eq!(vrtx.to_coords(), (26u8, 13u8));
    }

    #[test]
    #[should_fail]
    fn invalid_string() {
        let vrtx = super::Vertex::from_str("I13");
        assert_eq!(vrtx.to_coords(), (9u8, 13u8));
    }

}
<|endoftext|>


<commit_before>use hyper::Client;
use hyper::header::{Headers, Accept, qitem};
use hyper::mime::{Mime, TopLevel, SubLevel};
use std::io::Read;
use serde_json;

use Point;

pub struct Api {}

impl Api {
    pub fn get(&self) {
        let point = Point { x: 1, y: 2 };
        let serialized = serde_json::to_string(&point).unwrap();

        println!("{}", serialized);

        let deserialized: Point = serde_json::from_str(&serialized).unwrap();

        println!("{:?}", deserialized);

        ////////////////////////////////////////////////////////////////////////////////////////////

        let client = Client::new();
        let mut headers = Headers::new();
        headers.set(
            Accept(vec![
            qitem(Mime(TopLevel::Application,
                   SubLevel::Ext("vnd.eventstore.atom+json".to_owned()), vec![]))]));
        let mut response = client
            .get("http://127.0.0.1:2113/streams/newstream")
            .headers(headers)
            .send().unwrap();

        let mut body = String::new();

        response.read_to_string(&mut body);

        let value: serde_json::Value = serde_json::from_str(&body).unwrap();

        // Result: Response { status: Ok, headers: Headers { ETag: "0;248368668", Keep-Alive: timeout=15,max=100, Access-Control-Allow-Headers: Content-Type, X-Requested-With, X-Forwarded-Host, X-PINGOTHER, Authorization, ES-LongPoll, ES-ExpectedVersion, ES-EventId, ES-EventType, ES-RequiresMaster, ES-HardDelete, ES-ResolveLinkTo, Content-Type: application/vnd.eventstore.atom+json; charset=utf-8, Server: Mono-HTTPAPI/1.0, Vary: Accept, Access-Control-Allow-Methods: POST, DELETE, GET, OPTIONS, Access-Control-Expose-Headers: Location, ES-Position, ES-CurrentVersion, Content-Length: 1260, Cache-Control: max-age=0, no-cache, must-revalidate, Date: Tue, 06 Sep 2016 20:51:52 GMT, Access-Control-Allow-Origin: *, }, version: Http11, url: "http://127.0.0.1:2113/streams/newstream", status_raw: RawStatus(200, "OK"), message: Http11Message { is_proxied: false, method: None, stream: Wrapper { obj: Some(Reading(SizedReader(remaining=0))) } } }
        // Body: "{\n  \"title\": \"Event stream \'newstream\'\",\n  \"id\": \"http://127.0.0.1:2113/streams/newstream\",\n  \"updated\": \"2016-09-06T18:14:50.042706Z\",\n  \"streamId\": \"newstream\",\n  \"author\": {\n    \"name\": \"EventStore\"\n  },\n  \"headOfStream\": true,\n  \"selfUrl\": \"http://127.0.0.1:2113/streams/newstream\",\n  \"eTag\": \"0;248368668\",\n  \"links\": [\n    {\n      \"uri\": \"http://127.0.0.1:2113/streams/newstream\",\n      \"relation\": \"self\"\n    },\n    {\n      \"uri\": \"http://127.0.0.1:2113/streams/newstream/head/backward/20\",\n      \"relation\": \"first\"\n    },\n    {\n      \"uri\": \"http://127.0.0.1:2113/streams/newstream/1/forward/20\",\n      \"relation\": \"previous\"\n    },\n    {\n      \"uri\": \"http://127.0.0.1:2113/streams/newstream/metadata\",\n      \"relation\": \"metadata\"\n    }\n  ],\n  \"entries\": [\n    {\n      \"title\": \"0@newstream\",\n      \"id\": \"http://127.0.0.1:2113/streams/newstream/0\",\n      \"updated\": \"2016-09-06T18:14:50.042706Z\",\n      \"author\": {\n        \"name\": \"EventStore\"\n      },\n      \"summary\": \"event-type\",\n      \"links\": [\n        {\n          \"uri\": \"http://127.0.0.1:2113/streams/newstream/0\",\n          \"relation\": \"edit\"\n        },\n        {\n          \"uri\": \"http://127.0.0.1:2113/streams/newstream/0\",\n          \"relation\": \"alternate\"\n        }\n      ]\n    }\n  ]\n}"
        println!("Result: {:?}", response);
//        println!("Body: {:?}", body);
        println!("JSON: {:?}", value);
    }
}
<commit_msg>Modify the first request to EventStore to embed event data<commit_after>use hyper::Client;
use hyper::header::{Headers, Accept, qitem};
use hyper::mime::{Mime, TopLevel, SubLevel};
use std::io::Read;
use serde_json;

use Point;

pub struct Api {}

impl Api {
    pub fn get(&self) {
        let point = Point { x: 1, y: 2 };
        let serialized = serde_json::to_string(&point).unwrap();

        println!("{}", serialized);

        let deserialized: Point = serde_json::from_str(&serialized).unwrap();

        println!("{:?}", deserialized);

        ////////////////////////////////////////////////////////////////////////////////////////////

        let client = Client::new();
        let mut headers = Headers::new();
        headers.set(
            Accept(vec![
            qitem(Mime(TopLevel::Application,
                   SubLevel::Ext("vnd.eventstore.atom+json".to_owned()), vec![]))]));
        let mut response = client
            .get("http://127.0.0.1:2113/streams/newstream?embed=body")
            .headers(headers)
            .send().unwrap();

        let mut body = String::new();

        response.read_to_string(&mut body);

        let value: serde_json::Value = serde_json::from_str(&body).unwrap();

        // Result: Response { status: Ok, headers: Headers { ETag: "0;248368668", Keep-Alive: timeout=15,max=100, Access-Control-Allow-Headers: Content-Type, X-Requested-With, X-Forwarded-Host, X-PINGOTHER, Authorization, ES-LongPoll, ES-ExpectedVersion, ES-EventId, ES-EventType, ES-RequiresMaster, ES-HardDelete, ES-ResolveLinkTo, Content-Type: application/vnd.eventstore.atom+json; charset=utf-8, Server: Mono-HTTPAPI/1.0, Vary: Accept, Access-Control-Allow-Methods: POST, DELETE, GET, OPTIONS, Access-Control-Expose-Headers: Location, ES-Position, ES-CurrentVersion, Content-Length: 1260, Cache-Control: max-age=0, no-cache, must-revalidate, Date: Tue, 06 Sep 2016 20:51:52 GMT, Access-Control-Allow-Origin: *, }, version: Http11, url: "http://127.0.0.1:2113/streams/newstream", status_raw: RawStatus(200, "OK"), message: Http11Message { is_proxied: false, method: None, stream: Wrapper { obj: Some(Reading(SizedReader(remaining=0))) } } }
        // Body: "{\n  \"title\": \"Event stream \'newstream\'\",\n  \"id\": \"http://127.0.0.1:2113/streams/newstream\",\n  \"updated\": \"2016-09-06T18:14:50.042706Z\",\n  \"streamId\": \"newstream\",\n  \"author\": {\n    \"name\": \"EventStore\"\n  },\n  \"headOfStream\": true,\n  \"selfUrl\": \"http://127.0.0.1:2113/streams/newstream\",\n  \"eTag\": \"0;248368668\",\n  \"links\": [\n    {\n      \"uri\": \"http://127.0.0.1:2113/streams/newstream\",\n      \"relation\": \"self\"\n    },\n    {\n      \"uri\": \"http://127.0.0.1:2113/streams/newstream/head/backward/20\",\n      \"relation\": \"first\"\n    },\n    {\n      \"uri\": \"http://127.0.0.1:2113/streams/newstream/1/forward/20\",\n      \"relation\": \"previous\"\n    },\n    {\n      \"uri\": \"http://127.0.0.1:2113/streams/newstream/metadata\",\n      \"relation\": \"metadata\"\n    }\n  ],\n  \"entries\": [\n    {\n      \"title\": \"0@newstream\",\n      \"id\": \"http://127.0.0.1:2113/streams/newstream/0\",\n      \"updated\": \"2016-09-06T18:14:50.042706Z\",\n      \"author\": {\n        \"name\": \"EventStore\"\n      },\n      \"summary\": \"event-type\",\n      \"links\": [\n        {\n          \"uri\": \"http://127.0.0.1:2113/streams/newstream/0\",\n          \"relation\": \"edit\"\n        },\n        {\n          \"uri\": \"http://127.0.0.1:2113/streams/newstream/0\",\n          \"relation\": \"alternate\"\n        }\n      ]\n    }\n  ]\n}"
        println!("Result: {:?}", response);
//        println!("Body: {:?}", body);
        println!("JSON: {:?}", value);
    }
}
<|endoftext|>