<commit_before>use super::{
    flow_control::{ExportAction, LocalAction}, status::*, Shell,
};
use itoa;
use parser::assignments::*;
use shell::history::ShellHistory;
use std::{
    env, ffi::OsStr, fmt::{self, Display}, io::{self, BufWriter, Write}, mem,
    os::unix::ffi::OsStrExt, str,
};

fn list_vars(shell: &Shell) {
    let stdout = io::stdout();
    let mut buffer = BufWriter::new(stdout.lock());

    // Small function for formatting and append an array entry to a string buffer.
    fn print_array<W: Write>(buffer: &mut W, key: &str, array: &[String]) {
        let _ = buffer.write([key, " = [ "].concat().as_bytes());
        if array.len() > 1 {
            let mut vars = array.iter();
            if let Some(ref var) = vars.next() {
                let _ = buffer.write(["'", var, "', "].concat().as_bytes());
                vars.for_each(|var| {
                    let _ = buffer.write(["'", var, "' "].concat().as_bytes());
                });
            }
            let _ = buffer.write(b"]\n");
        } else {
            let _ = buffer.write(["'", &array[0], "' ]\n"].concat().as_bytes());
        }
    }

    // Write all the string variables to the buffer.
    let _ = buffer.write(b"# String Variables\n");
    let mut me = &shell.variables;
    loop {
        me.variables.borrow().iter().for_each(|(key, val)| {
            let _ = buffer.write([key, " = ", val.as_str(), "\n"].concat().as_bytes());
        });
        match me.parent {
            Some(parent) => me = parent,
            None => break
        }
    }

    // Then immediately follow that with a list of array variables.
    let _ = buffer.write(b"\n# Array Variables\n");
    let mut me = &shell.variables;
    loop {
        me.arrays.borrow().iter().for_each(|(key, val)| {
            print_array(&mut buffer, &key, &val)
        });
        match me.parent {
            Some(parent) => me = parent,
            None => break
        }
    }
}

/// Represents: A variable store capable of setting local variables or
/// exporting variables to some global environment
pub(crate) trait VariableStore {
    /// Set a local variable given a binding
    fn local(&mut self, LocalAction) -> i32;
    /// Export a variable to the process environment given a binding
    fn export(&mut self, ExportAction) -> i32;
}

impl VariableStore for Shell {
    fn export(&mut self, action: ExportAction) -> i32 {
        let actions = match action {
            ExportAction::Assign(ref keys, op, ref vals) => AssignmentActions::new(keys, op, vals),
            ExportAction::LocalExport(ref key) => match self.get_var(key) {
                Some(var) => {
                    env::set_var(key, &var);
                    return SUCCESS;
                }
                None => {
                    eprintln!("ion: cannot export {} because it does not exist.", key);
                    return FAILURE;
                }
            },
            ExportAction::List => {
                let stdout = io::stdout();
                let mut stdout = stdout.lock();
                for (key, val) in env::vars() {
                    let _ = writeln!(stdout, "{} =\"{}\"", key, val);
                }
                return SUCCESS;
            }
        };

        for action in actions {
            match action {
                Ok(Action::UpdateArray(key, Operator::Equal, expression)) => {
                    match value_check(self, &expression, key.kind) {
                        Ok(ReturnValue::Vector(values)) => env::set_var(key.name, values.join(" ")),
                        Err(why) => {
                            eprintln!("ion: assignment error: {}: {}", key.name, why);
                            return FAILURE;
                        }
                        _ => unreachable!(),
                    }
                }
                Ok(Action::UpdateArray(..)) => {
                    eprintln!(
                        "ion: arithmetic operators on array expressions aren't supported yet."
                    );
                    return FAILURE;
                }
                Ok(Action::UpdateString(key, operator, expression)) => {
                    match value_check(self, &expression, key.kind) {
                        Ok(ReturnValue::Str(value)) => {
                            let key_name: &str = &key.name;
                            let lhs = self
                                .variables
                                .get_var(key_name)
                                .unwrap_or_else(|| String::from("0"));

                            let result = math(&lhs, key.kind, operator, &value, |value| {
                                env::set_var(key_name, &OsStr::from_bytes(value))
                            });

                            if let Err(why) = result {
                                eprintln!("ion: assignment error: {}", why);
                                return FAILURE;
                            }
                        }
                        Err(why) => {
                            eprintln!("ion: assignment error: {}: {}", key.name, why);
                            return FAILURE;
                        }
                        _ => unreachable!(),
                    }
                }
                Err(why) => {
                    eprintln!("ion: assignment error: {}", why);
                    return FAILURE;
                }
            }
        }

        SUCCESS
    }

    fn local(&mut self, action: LocalAction) -> i32 {
        let actions = match action {
            LocalAction::List => {
                list_vars(&self);
                return SUCCESS;
            }
            LocalAction::Assign(ref keys, op, ref vals) => AssignmentActions::new(keys, op, vals),
        };
        for action in actions {
            match action {
                Ok(Action::UpdateArray(key, Operator::Equal, expression)) => {
                    match value_check(self, &expression, key.kind) {
                        Ok(ReturnValue::Vector(values)) => {
                            // When we changed the HISTORY_IGNORE variable, update the
                            // ignore patterns. This happens first because `set_array`
                            // consumes 'values'
                            if key.name == "HISTORY_IGNORE" {
                                self.update_ignore_patterns(&values);
                            }
                            self.variables.set_array(key.name, values)
                        }
                        Err(why) => {
                            eprintln!("ion: assignment error: {}: {}", key.name, why);
                            return FAILURE;
                        }
                        _ => unreachable!(),
                    }
                }
                Ok(Action::UpdateArray(..)) => {
                    eprintln!(
                        "ion: arithmetic operators on array expressions aren't supported yet."
                    );
                    return FAILURE;
                }
                Ok(Action::UpdateString(key, operator, expression)) => {
                    if ["HOME", "PWD", "MWD", "SWD", "?"].contains(&key.name) {
                        eprintln!("ion: not allowed to set {}", key.name);
                        return FAILURE;
                    }

                    match value_check(self, &expression, key.kind) {
                        Ok(ReturnValue::Str(value)) => {
                            let key_name: &str = &key.name;
                            let lhs = self
                                .variables
                                .get_var(key_name)
                                .unwrap_or_else(|| String::from("0"));
                            let lhs = &*lhs as *const str;

                            let result =
                                math(unsafe { &*lhs }, key.kind, operator, &value, |value| {
                                    self.set_var(key_name, unsafe {
                                        str::from_utf8_unchecked(value)
                                    })
                                });

                            if let Err(why) = result {
                                eprintln!("ion: assignment error: {}", why);
                                return FAILURE;
                            }
                        }
                        Err(why) => {
                            eprintln!("ion: assignment error: {}: {}", key.name, why);
                            return FAILURE;
                        }
                        _ => unreachable!(),
                    }
                }
                Err(why) => {
                    eprintln!("ion: assignment error: {}", why);
                    return FAILURE;
                }
            }
        }

        SUCCESS
    }
}

enum MathError {
    RHS,
    LHS,
    Unsupported,
}

impl Display for MathError {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            MathError::RHS => write!(fmt, "right hand side has invalid type"),
            MathError::LHS => write!(fmt, "left hand side has invalid type"),
            MathError::Unsupported => write!(fmt, "type does not support operation"),
        }
    }
}

fn parse_f64<F: Fn(f64, f64) -> f64>(lhs: &str, rhs: &str, operation: F) -> Result<f64, MathError> {
    lhs.parse::<f64>()
        .map_err(|_| MathError::LHS)
        .and_then(|lhs| {
            rhs.parse::<f64>()
                .map_err(|_| MathError::RHS)
                .map(|rhs| operation(lhs, rhs))
        })
}

fn parse_i64<F: Fn(i64, i64) -> i64>(lhs: &str, rhs: &str, operation: F) -> Result<i64, MathError> {
    lhs.parse::<i64>()
        .map_err(|_| MathError::LHS)
        .and_then(|lhs| {
            rhs.parse::<i64>()
                .map_err(|_| MathError::RHS)
                .map(|rhs| operation(lhs, rhs))
        })
}

fn write_integer<F: FnMut(&[u8])>(integer: i64, mut func: F) {
    let mut buffer: [u8; 20] = unsafe { mem::uninitialized() };
    let capacity = itoa::write(&mut buffer[..], integer).unwrap();
    func(&buffer[..capacity]);
}

fn math<'a, F: FnMut(&[u8])>(
    lhs: &str,
    key: Primitive,
    operator: Operator,
    value: &'a str,
    mut writefn: F,
) -> Result<(), MathError> {
    match operator {
        Operator::Add => if Primitive::Any == key || Primitive::Float == key {
            writefn(
                parse_f64(lhs, value, |lhs, rhs| lhs + rhs)?
                    .to_string()
                    .as_bytes(),
            );
        } else if let Primitive::Integer = key {
            write_integer(parse_i64(lhs, value, |lhs, rhs| lhs + rhs)?, writefn);
        } else {
            return Err(MathError::Unsupported);
        },
        Operator::Divide => {
            if Primitive::Any == key || Primitive::Float == key || Primitive::Integer == key {
                writefn(
                    parse_f64(lhs, value, |lhs, rhs| lhs / rhs)?
                        .to_string()
                        .as_bytes(),
                );
            } else {
                return Err(MathError::Unsupported);
            }
        }
        Operator::IntegerDivide => if Primitive::Any == key || Primitive::Float == key {
            write_integer(parse_i64(lhs, value, |lhs, rhs| lhs / rhs)?, writefn);
        } else {
            return Err(MathError::Unsupported);
        },
        Operator::Subtract => if Primitive::Any == key || Primitive::Float == key {
            writefn(
                parse_f64(lhs, value, |lhs, rhs| lhs - rhs)?
                    .to_string()
                    .as_bytes(),
            );
        } else if let Primitive::Integer = key {
            write_integer(parse_i64(lhs, value, |lhs, rhs| lhs - rhs)?, writefn);
        } else {
            return Err(MathError::Unsupported);
        },
        Operator::Multiply => if Primitive::Any == key || Primitive::Float == key {
            writefn(
                parse_f64(lhs, value, |lhs, rhs| lhs * rhs)?
                    .to_string()
                    .as_bytes(),
            );
        } else if let Primitive::Integer = key {
            write_integer(parse_i64(lhs, value, |lhs, rhs| lhs * rhs)?, writefn);
        } else {
            return Err(MathError::Unsupported);
        },
        Operator::Exponent => if Primitive::Any == key || Primitive::Float == key {
            writefn(
                parse_f64(lhs, value, |lhs, rhs| lhs.powf(rhs))?
                    .to_string()
                    .as_bytes(),
            );
        } else if let Primitive::Integer = key {
            write_integer(
                parse_i64(lhs, value, |lhs, rhs| lhs.pow(rhs as u32))?,
                writefn,
            );
        } else {
            return Err(MathError::Unsupported);
        },
        Operator::Equal => writefn(value.as_bytes()),
    };

    Ok(())
}
<commit_msg>Fix multiple variable assignments to the way humans think (Fixes #774)<commit_after>use super::{
    flow_control::{ExportAction, LocalAction}, status::*, Shell,
};
use itoa;
use parser::assignments::*;
use shell::history::ShellHistory;
use std::{
    collections::HashMap,
    env, ffi::OsStr, fmt::{self, Display}, io::{self, BufWriter, Write}, mem,
    os::unix::ffi::OsStrExt, str,
};

fn list_vars(shell: &Shell) {
    let stdout = io::stdout();
    let mut buffer = BufWriter::new(stdout.lock());

    // Small function for formatting and append an array entry to a string buffer.
    fn print_array<W: Write>(buffer: &mut W, key: &str, array: &[String]) {
        let _ = buffer.write([key, " = [ "].concat().as_bytes());
        if array.len() > 1 {
            let mut vars = array.iter();
            if let Some(ref var) = vars.next() {
                let _ = buffer.write(["'", var, "', "].concat().as_bytes());
                vars.for_each(|var| {
                    let _ = buffer.write(["'", var, "' "].concat().as_bytes());
                });
            }
            let _ = buffer.write(b"]\n");
        } else {
            let _ = buffer.write(["'", &array[0], "' ]\n"].concat().as_bytes());
        }
    }

    // Write all the string variables to the buffer.
    let _ = buffer.write(b"# String Variables\n");
    let mut me = &shell.variables;
    loop {
        me.variables.borrow().iter().for_each(|(key, val)| {
            let _ = buffer.write([key, " = ", val.as_str(), "\n"].concat().as_bytes());
        });
        match me.parent {
            Some(parent) => me = parent,
            None => break
        }
    }

    // Then immediately follow that with a list of array variables.
    let _ = buffer.write(b"\n# Array Variables\n");
    let mut me = &shell.variables;
    loop {
        me.arrays.borrow().iter().for_each(|(key, val)| {
            print_array(&mut buffer, &key, &val)
        });
        match me.parent {
            Some(parent) => me = parent,
            None => break
        }
    }
}

/// Represents: A variable store capable of setting local variables or
/// exporting variables to some global environment
pub(crate) trait VariableStore {
    /// Set a local variable given a binding
    fn local(&mut self, LocalAction) -> i32;
    /// Export a variable to the process environment given a binding
    fn export(&mut self, ExportAction) -> i32;
}

impl VariableStore for Shell {
    fn export(&mut self, action: ExportAction) -> i32 {
        let actions = match action {
            ExportAction::Assign(ref keys, op, ref vals) => AssignmentActions::new(keys, op, vals),
            ExportAction::LocalExport(ref key) => match self.get_var(key) {
                Some(var) => {
                    env::set_var(key, &var);
                    return SUCCESS;
                }
                None => {
                    eprintln!("ion: cannot export {} because it does not exist.", key);
                    return FAILURE;
                }
            },
            ExportAction::List => {
                let stdout = io::stdout();
                let mut stdout = stdout.lock();
                for (key, val) in env::vars() {
                    let _ = writeln!(stdout, "{} =\"{}\"", key, val);
                }
                return SUCCESS;
            }
        };

        for action in actions {
            match action {
                Ok(Action::UpdateArray(key, Operator::Equal, expression)) => {
                    match value_check(self, &expression, key.kind) {
                        Ok(ReturnValue::Vector(values)) => env::set_var(key.name, values.join(" ")),
                        Err(why) => {
                            eprintln!("ion: assignment error: {}: {}", key.name, why);
                            return FAILURE;
                        }
                        _ => unreachable!(),
                    }
                }
                Ok(Action::UpdateArray(..)) => {
                    eprintln!(
                        "ion: arithmetic operators on array expressions aren't supported yet."
                    );
                    return FAILURE;
                }
                Ok(Action::UpdateString(key, operator, expression)) => {
                    match value_check(self, &expression, key.kind) {
                        Ok(ReturnValue::Str(value)) => {
                            let key_name: &str = &key.name;
                            let lhs = self
                                .variables
                                .get_var(key_name)
                                .unwrap_or_else(|| String::from("0"));

                            let result = math(&lhs, key.kind, operator, &value, |value| {
                                env::set_var(key_name, &OsStr::from_bytes(value))
                            });

                            if let Err(why) = result {
                                eprintln!("ion: assignment error: {}", why);
                                return FAILURE;
                            }
                        }
                        Err(why) => {
                            eprintln!("ion: assignment error: {}: {}", key.name, why);
                            return FAILURE;
                        }
                        _ => unreachable!(),
                    }
                }
                Err(why) => {
                    eprintln!("ion: assignment error: {}", why);
                    return FAILURE;
                }
            }
        }

        SUCCESS
    }

    fn local(&mut self, action: LocalAction) -> i32 {
        let mut collected: HashMap<&str, ReturnValue> = HashMap::new();
        let (actions_step1, actions_step2) = match action {
            LocalAction::List => {
                list_vars(&self);
                return SUCCESS;
            }
            LocalAction::Assign(ref keys, op, ref vals) => (AssignmentActions::new(keys, op.clone(), vals), AssignmentActions::new(keys, op, vals)),
        };
        for action in actions_step1 {
            match action {
                Ok(Action::UpdateArray(key, Operator::Equal, expression)) => {
                    match value_check(self, &expression, key.kind) {
                        Ok(ReturnValue::Vector(values)) => {
                            // When we changed the HISTORY_IGNORE variable, update the
                            // ignore patterns. This happens first because `set_array`
                            // consumes 'values'
                            if key.name == "HISTORY_IGNORE" {
                                self.update_ignore_patterns(&values);
                            }
                            collected.insert(key.name, ReturnValue::Vector(values));
                        }
                        Err(why) => {
                            eprintln!("ion: assignment error: {}: {}", key.name, why);
                            return FAILURE;
                        }
                        _ => unreachable!(),
                    }
                }
                Ok(Action::UpdateArray(..)) => {
                    eprintln!(
                        "ion: arithmetic operators on array expressions aren't supported yet."
                    );
                    return FAILURE;
                }
                Ok(Action::UpdateString(key, operator, expression)) => {
                    if ["HOME", "HOST", "PWD", "MWD", "SWD", "?"].contains(&key.name) {
                        eprintln!("ion: not allowed to set {}", key.name);
                        return FAILURE;
                    }

                    match value_check(self, &expression, key.kind) {
                        Ok(ReturnValue::Str(value)) => {
                            let lhs = self
                                .variables
                                .get_var(key.name)
                                .unwrap_or_else(|| String::from("0"));

                            let result =
                                math(&lhs, key.kind, operator, &value, |value| {
                                    collected.insert(key.name, ReturnValue::Str(unsafe { str::from_utf8_unchecked(value) }.to_owned()));
                                });

                            if let Err(why) = result {
                                eprintln!("ion: assignment error: {}", why);
                                return FAILURE;
                            }
                        }
                        Err(why) => {
                            eprintln!("ion: assignment error: {}: {}", key.name, why);
                            return FAILURE;
                        }
                        _ => unreachable!(),
                    }
                }
                Err(why) => {
                    eprintln!("ion: assignment error: {}", why);
                    return FAILURE;
                }
            }
        }

        for action in actions_step2 {
            match action {
                Ok(Action::UpdateArray(key, _, _)) => {
                    if let ReturnValue::Vector(ref values) = collected[key.name] {
                        self.variables.set_array(key.name, (*values).clone());
                    }
                }
                Ok(Action::UpdateString(key, _, _)) => {
                    if let ReturnValue::Str(ref value) = collected[key.name] {
                        self.set_var(key.name, value);
                    }
                }
                _ => unreachable!(),
            }
        }

        SUCCESS
    }
}

enum MathError {
    RHS,
    LHS,
    Unsupported,
}

impl Display for MathError {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            MathError::RHS => write!(fmt, "right hand side has invalid type"),
            MathError::LHS => write!(fmt, "left hand side has invalid type"),
            MathError::Unsupported => write!(fmt, "type does not support operation"),
        }
    }
}

fn parse_f64<F: Fn(f64, f64) -> f64>(lhs: &str, rhs: &str, operation: F) -> Result<f64, MathError> {
    lhs.parse::<f64>()
        .map_err(|_| MathError::LHS)
        .and_then(|lhs| {
            rhs.parse::<f64>()
                .map_err(|_| MathError::RHS)
                .map(|rhs| operation(lhs, rhs))
        })
}

fn parse_i64<F: Fn(i64, i64) -> i64>(lhs: &str, rhs: &str, operation: F) -> Result<i64, MathError> {
    lhs.parse::<i64>()
        .map_err(|_| MathError::LHS)
        .and_then(|lhs| {
            rhs.parse::<i64>()
                .map_err(|_| MathError::RHS)
                .map(|rhs| operation(lhs, rhs))
        })
}

fn write_integer<F: FnMut(&[u8])>(integer: i64, mut func: F) {
    let mut buffer: [u8; 20] = unsafe { mem::uninitialized() };
    let capacity = itoa::write(&mut buffer[..], integer).unwrap();
    func(&buffer[..capacity]);
}

fn math<'a, F: FnMut(&[u8])>(
    lhs: &str,
    key: Primitive,
    operator: Operator,
    value: &'a str,
    mut writefn: F,
) -> Result<(), MathError> {
    match operator {
        Operator::Add => if Primitive::Any == key || Primitive::Float == key {
            writefn(
                parse_f64(lhs, value, |lhs, rhs| lhs + rhs)?
                    .to_string()
                    .as_bytes(),
            );
        } else if let Primitive::Integer = key {
            write_integer(parse_i64(lhs, value, |lhs, rhs| lhs + rhs)?, writefn);
        } else {
            return Err(MathError::Unsupported);
        },
        Operator::Divide => {
            if Primitive::Any == key || Primitive::Float == key || Primitive::Integer == key {
                writefn(
                    parse_f64(lhs, value, |lhs, rhs| lhs / rhs)?
                        .to_string()
                        .as_bytes(),
                );
            } else {
                return Err(MathError::Unsupported);
            }
        }
        Operator::IntegerDivide => if Primitive::Any == key || Primitive::Float == key {
            write_integer(parse_i64(lhs, value, |lhs, rhs| lhs / rhs)?, writefn);
        } else {
            return Err(MathError::Unsupported);
        },
        Operator::Subtract => if Primitive::Any == key || Primitive::Float == key {
            writefn(
                parse_f64(lhs, value, |lhs, rhs| lhs - rhs)?
                    .to_string()
                    .as_bytes(),
            );
        } else if let Primitive::Integer = key {
            write_integer(parse_i64(lhs, value, |lhs, rhs| lhs - rhs)?, writefn);
        } else {
            return Err(MathError::Unsupported);
        },
        Operator::Multiply => if Primitive::Any == key || Primitive::Float == key {
            writefn(
                parse_f64(lhs, value, |lhs, rhs| lhs * rhs)?
                    .to_string()
                    .as_bytes(),
            );
        } else if let Primitive::Integer = key {
            write_integer(parse_i64(lhs, value, |lhs, rhs| lhs * rhs)?, writefn);
        } else {
            return Err(MathError::Unsupported);
        },
        Operator::Exponent => if Primitive::Any == key || Primitive::Float == key {
            writefn(
                parse_f64(lhs, value, |lhs, rhs| lhs.powf(rhs))?
                    .to_string()
                    .as_bytes(),
            );
        } else if let Primitive::Integer = key {
            write_integer(
                parse_i64(lhs, value, |lhs, rhs| lhs.pow(rhs as u32))?,
                writefn,
            );
        } else {
            return Err(MathError::Unsupported);
        },
        Operator::Equal => writefn(value.as_bytes()),
    };

    Ok(())
}
<|endoftext|>


<commit_before>extern crate serde;
extern crate serde_json;

use flowgger::Decoder;
use flowgger::config::Config;
use flowgger::record::{Record, StructuredData, SDValue};
use self::serde_json::de;
use self::serde_json::value::Value;

#[derive(Clone)]
pub struct GelfDecoder;

impl GelfDecoder {
    pub fn new(config: &Config) -> GelfDecoder {
        let _ = config;
        GelfDecoder
    }
}

impl Decoder for GelfDecoder {
    fn decode(&self, line: &str) -> Result<Record, &'static str> {
        let mut sd = StructuredData::new(None);
        let mut ts = None;
        let mut hostname = None;
        let mut msg = None;
        let mut full_msg = None;
        let mut severity = None;

        let obj: Value = try!(de::from_str(line).or(Err("Invalid GELF input, unable to parse as a JSON object")));
        let obj = try!(obj.as_object().ok_or("Empty GELF input"));
        for (key, value) in obj {
            match key.as_ref() {
                "timestamp" => {
                    ts = Some(try!(value.as_f64().ok_or("Invalid GELF timestamp")) as i64);
                }
                "host" => {
                    hostname = Some(try!(value.as_string().ok_or("GELF host name must be a string")).to_owned());
                }
                "short_message" => {
                    msg = Some(try!(value.as_string().ok_or("GELF short message must be a string")).to_owned());
                }
                "full_message" => {
                    full_msg = Some(try!(value.as_string().ok_or("GELF full message must be a string")).to_owned());
                }
                "version" => {
                    if try!(value.as_string().ok_or("GELF version must be a string")) != "1.1" {
                        return Err("Unsupported GELF version");
                    }
                }
                "level" => {
                    let level = try!(value.as_u64().ok_or("Invalid severity level"));
                    if level > 7 {
                        return Err("Severity level should be <= 7")
                    }
                    severity = Some(level as u8)
                },
                name @ _ => {
                    let sd_value: SDValue = match *value {
                        Value::String(ref value) => SDValue::String(value.to_owned()),
                        Value::Bool(value) => SDValue::Bool(value),
                        Value::F64(value) => SDValue::F64(value),
                        Value::I64(value) => SDValue::I64(value),
                        Value::U64(value) => SDValue::U64(value),
                        Value::Null => SDValue::Null,
                        _ => return Err("Invalid value type in structured data")
                    };
                    let name = if name.starts_with("_") {
                        name.to_owned()
                    } else {
                        format!("_{}", name)
                    };
                    sd.pairs.push((name, sd_value));
                }
            }
        }
        let record = Record {
            ts: try!(ts.ok_or("Missing timestamp")),
            hostname: try!(hostname.ok_or("Missing hostname")),
            facility: None,
            severity: severity,
            appname: None,
            procid: None,
            msgid: None,
            sd: if sd.pairs.is_empty() { None } else { Some(sd) },
            msg: msg,
            full_msg: full_msg
        };
        Ok(record)
    }
}

#[test]
fn test_gelf() {
    let msg = r#"{"version":"1.1", "host": "example.org", "short_message": "A short message that helps you identify what is going on", "full_message": "Backtrace here\n\nmore stuff", "timestamp": 1385053862.3072, "level": 1, "_user_id": 9001, "_some_info": "foo", "_some_env_var": "bar"}"#;
    let res = GelfDecoder.decode(msg).unwrap();
    assert!(res.ts == 1385053862);
    assert!(res.hostname == "example.org");
    assert!(res.msg.unwrap() == "A short message that helps you identify what is going on");
    assert!(res.full_msg.unwrap() == "Backtrace here\n\nmore stuff");
    assert!(res.severity.unwrap() == 1);

    let sd = res.sd.unwrap();
    let pairs = sd.pairs;
    assert!(pairs.iter().cloned().any(|(k, v)|
        if let SDValue::U64(v) = v { k == "_user_id" && v == 9001 } else { false }
    ));
    assert!(pairs.iter().cloned().any(|(k, v)|
        if let SDValue::String(v) = v { k == "_some_info" && v == "foo" } else { false }
    ));
    assert!(pairs.iter().cloned().any(|(k, v)|
        if let SDValue::String(v) = v { k == "_some_env_var" && v == "bar" } else { false }
    ));
}
<commit_msg>Support GELF 1.0 in addition to 1.1<commit_after>extern crate serde;
extern crate serde_json;

use flowgger::Decoder;
use flowgger::config::Config;
use flowgger::record::{Record, StructuredData, SDValue};
use self::serde_json::de;
use self::serde_json::value::Value;

#[derive(Clone)]
pub struct GelfDecoder;

impl GelfDecoder {
    pub fn new(config: &Config) -> GelfDecoder {
        let _ = config;
        GelfDecoder
    }
}

impl Decoder for GelfDecoder {
    fn decode(&self, line: &str) -> Result<Record, &'static str> {
        let mut sd = StructuredData::new(None);
        let mut ts = None;
        let mut hostname = None;
        let mut msg = None;
        let mut full_msg = None;
        let mut severity = None;

        let obj: Value = try!(de::from_str(line).or(Err("Invalid GELF input, unable to parse as a JSON object")));
        let obj = try!(obj.as_object().ok_or("Empty GELF input"));
        for (key, value) in obj {
            match key.as_ref() {
                "timestamp" => {
                    ts = Some(try!(value.as_f64().ok_or("Invalid GELF timestamp")) as i64);
                }
                "host" => {
                    hostname = Some(try!(value.as_string().ok_or("GELF host name must be a string")).to_owned());
                }
                "short_message" => {
                    msg = Some(try!(value.as_string().ok_or("GELF short message must be a string")).to_owned());
                }
                "full_message" => {
                    full_msg = Some(try!(value.as_string().ok_or("GELF full message must be a string")).to_owned());
                }
                "version" => {
                    match try!(value.as_string().ok_or("GELF version must be a string")) {
                        "1.0" | "1.1" => { }
                        _ => return Err("Unsupported GELF version")
                    }
                }
                "level" => {
                    let level = try!(value.as_u64().ok_or("Invalid severity level"));
                    if level > 7 {
                        return Err("Severity level should be <= 7")
                    }
                    severity = Some(level as u8)
                },
                name @ _ => {
                    let sd_value: SDValue = match *value {
                        Value::String(ref value) => SDValue::String(value.to_owned()),
                        Value::Bool(value) => SDValue::Bool(value),
                        Value::F64(value) => SDValue::F64(value),
                        Value::I64(value) => SDValue::I64(value),
                        Value::U64(value) => SDValue::U64(value),
                        Value::Null => SDValue::Null,
                        _ => return Err("Invalid value type in structured data")
                    };
                    let name = if name.starts_with("_") {
                        name.to_owned()
                    } else {
                        format!("_{}", name)
                    };
                    sd.pairs.push((name, sd_value));
                }
            }
        }
        let record = Record {
            ts: try!(ts.ok_or("Missing timestamp")),
            hostname: try!(hostname.ok_or("Missing hostname")),
            facility: None,
            severity: severity,
            appname: None,
            procid: None,
            msgid: None,
            sd: if sd.pairs.is_empty() { None } else { Some(sd) },
            msg: msg,
            full_msg: full_msg
        };
        Ok(record)
    }
}

#[test]
fn test_gelf() {
    let msg = r#"{"version":"1.1", "host": "example.org", "short_message": "A short message that helps you identify what is going on", "full_message": "Backtrace here\n\nmore stuff", "timestamp": 1385053862.3072, "level": 1, "_user_id": 9001, "_some_info": "foo", "_some_env_var": "bar"}"#;
    let res = GelfDecoder.decode(msg).unwrap();
    assert!(res.ts == 1385053862);
    assert!(res.hostname == "example.org");
    assert!(res.msg.unwrap() == "A short message that helps you identify what is going on");
    assert!(res.full_msg.unwrap() == "Backtrace here\n\nmore stuff");
    assert!(res.severity.unwrap() == 1);

    let sd = res.sd.unwrap();
    let pairs = sd.pairs;
    assert!(pairs.iter().cloned().any(|(k, v)|
        if let SDValue::U64(v) = v { k == "_user_id" && v == 9001 } else { false }
    ));
    assert!(pairs.iter().cloned().any(|(k, v)|
        if let SDValue::String(v) = v { k == "_some_info" && v == "foo" } else { false }
    ));
    assert!(pairs.iter().cloned().any(|(k, v)|
        if let SDValue::String(v) = v { k == "_some_env_var" && v == "bar" } else { false }
    ));
}
<|endoftext|>


<commit_before>use redox::Box;
use redox::fs::File;
use redox::io::*;
use redox::mem;
use redox::ops::DerefMut;
use redox::slice;
use redox::syscall::sys_yield;
use redox::String;
use redox::ToString;
use redox::Vec;

use super::Event;
use super::Color;

/// A window
pub struct Window {
    /// The x coordinate of the window
    x: isize,
    /// The y coordinate of the window
    y: isize,
    /// The width of the window
    w: usize,
    /// The height of the window
    h: usize,
    /// The title of the window
    t: String,
    /// The input scheme
    file: File,
    /// Font file
    font: Vec<u8>,
    /// Window data
    data: Vec<u32>,
}

impl Window {
    /// Create a new window
    pub fn new(x: isize, y: isize, w: usize, h: usize, title: &str) -> Option<Box<Self>> {
        let mut font = Vec::new();
        if let Some(mut font_file) = File::open("file:///ui/unifont.font") {
            font_file.read_to_end(&mut font);
        }

        match File::open(&format!("window:///{}/{}/{}/{}/{}", x, y, w, h, title)) {
            Some(file) => Some(box Window {
                x: x,
                y: y,
                w: w,
                h: h,
                t: title.to_string(),
                file: file,
                font: font,
                data: vec![0; w * h * 4],
            }),
            None => None
        }
    }

    /// Get x
    //TODO: Sync with window movements
    pub fn x(&self) -> isize {
        self.x
    }

    /// Get y
    //TODO: Sync with window movements
    pub fn y(&self) -> isize {
        self.y
    }

    /// Get width
    pub fn width(&self) -> usize {
        self.w
    }

    /// Get height
    pub fn height(&self) -> usize {
        self.h
    }

    /// Get title
    pub fn title(&self) -> String {
        self.t.clone()
    }

    /// Set title
    pub fn set_title(&mut self, title: &str) {
        //TODO
    }

    /// Draw a pixel
    pub fn pixel(&mut self, x: isize, y: isize, color: Color) {
        if x >= 0 && y >= 0 && x < self.w as isize && y < self.h as isize {
            let offset = y as usize * self.w + x as usize;
            self.data[offset] = color.data;
        }
    }

    /// Draw a character, using the loaded font
    pub fn char(&mut self, x: isize, y: isize, c: char, color: Color) {
        let mut offset = (c as usize) * 16;
        for row in 0..16 {
            let row_data;
            if offset < self.font.len() {
                row_data = self.font[offset];
            } else {
                row_data = 0;
            }

            for col in 0..8 {
                let pixel = (row_data >> (7 - col)) & 1;
                if pixel > 0 {
                    self.pixel(x + col as isize, y + row as isize, color);
                }
            }
            offset += 1;
        }
    }

    //TODO move, resize, set_title

    /// Set entire window to a color
    // TODO: Improve speed
    #[allow(unused_variables)]
    pub fn set(&mut self, color: Color) {
        let w = self.w;
        let h = self.h;
        self.rect(0, 0, w, h, color);
    }

    /// Draw rectangle
    // TODO: Improve speed
    #[allow(unused_variables)]
    pub fn rect(&mut self, start_x: isize, start_y: isize, w: usize, h: usize, color: Color) {
        for y in start_y..start_y + h as isize {
            for x in start_x..start_x + w as isize {
                self.pixel(x, y, color);
            }
        }
    }

    /// Display an image
    //TODO: Improve speed
    pub fn image(&mut self, start_x: isize, start_y: isize, w: usize, h: usize, data: &[Color]) {
        let mut i = 0;
        for y in start_y..start_y + h as isize {
            for x in start_x..start_x + w as isize {
                if i < data.len() {
                    self.pixel(x, y, data[i])
                }
                i += 1;
            }
        }
    }

    /// Poll for an event
    //TODO: clean this up
    pub fn poll(&mut self) -> Option<Event> {
        let mut event = box Event::new();
        let event_ptr: *mut Event = event.deref_mut();
        loop {
            match self.file.read(&mut unsafe {
                slice::from_raw_parts_mut(event_ptr as *mut u8, mem::size_of::<Event>())
            }) {
                Some(0) => unsafe { sys_yield() },
                Some(_) => return Some(*event),
                None => return None,
            }
        }
    }

    /// Flip the window buffer
    pub fn sync(&mut self) -> bool {
        self.file.seek(SeekFrom::Start(0));
        let to_write: &[u8] = unsafe{ mem::transmute::<&[u32],&[u8]>(&self.data) };
        self.file.write(to_write);
        return self.file.sync();
    }

    /// Return a iterator over events
    pub fn event_iter<'a>(&'a mut self) -> EventIter<'a> {
        EventIter {
            window: self,
        }
    }
}

/// Event iterator
pub struct EventIter<'a> {
    window: &'a mut Window,
}

impl<'a> Iterator for EventIter<'a> {
    type Item = Event;
    fn next(&mut self) -> Option<Event> {
        self.window.poll()
    }
}
<commit_msg>Use orbital:///<commit_after>use redox::Box;
use redox::fs::File;
use redox::io::*;
use redox::mem;
use redox::ops::DerefMut;
use redox::slice;
use redox::syscall::sys_yield;
use redox::String;
use redox::ToString;
use redox::Vec;

use super::Event;
use super::Color;

/// A window
pub struct Window {
    /// The x coordinate of the window
    x: isize,
    /// The y coordinate of the window
    y: isize,
    /// The width of the window
    w: usize,
    /// The height of the window
    h: usize,
    /// The title of the window
    t: String,
    /// The input scheme
    file: File,
    /// Font file
    font: Vec<u8>,
    /// Window data
    data: Vec<u32>,
}

impl Window {
    /// Create a new window
    pub fn new(x: isize, y: isize, w: usize, h: usize, title: &str) -> Option<Box<Self>> {
        let mut font = Vec::new();
        if let Some(mut font_file) = File::open("file:/ui/unifont.font") {
            font_file.read_to_end(&mut font);
        }

        match File::open(&format!("orbital:///{}/{}/{}/{}/{}", x, y, w, h, title)) {
            Some(file) => Some(box Window {
                x: x,
                y: y,
                w: w,
                h: h,
                t: title.to_string(),
                file: file,
                font: font,
                data: vec![0; w * h * 4],
            }),
            None => None
        }
    }

    /// Get x
    //TODO: Sync with window movements
    pub fn x(&self) -> isize {
        self.x
    }

    /// Get y
    //TODO: Sync with window movements
    pub fn y(&self) -> isize {
        self.y
    }

    /// Get width
    pub fn width(&self) -> usize {
        self.w
    }

    /// Get height
    pub fn height(&self) -> usize {
        self.h
    }

    /// Get title
    pub fn title(&self) -> String {
        self.t.clone()
    }

    /// Set title
    pub fn set_title(&mut self, title: &str) {
        //TODO
    }

    /// Draw a pixel
    pub fn pixel(&mut self, x: isize, y: isize, color: Color) {
        if x >= 0 && y >= 0 && x < self.w as isize && y < self.h as isize {
            let offset = y as usize * self.w + x as usize;
            self.data[offset] = color.data;
        }
    }

    /// Draw a character, using the loaded font
    pub fn char(&mut self, x: isize, y: isize, c: char, color: Color) {
        let mut offset = (c as usize) * 16;
        for row in 0..16 {
            let row_data;
            if offset < self.font.len() {
                row_data = self.font[offset];
            } else {
                row_data = 0;
            }

            for col in 0..8 {
                let pixel = (row_data >> (7 - col)) & 1;
                if pixel > 0 {
                    self.pixel(x + col as isize, y + row as isize, color);
                }
            }
            offset += 1;
        }
    }

    //TODO move, resize, set_title

    /// Set entire window to a color
    // TODO: Improve speed
    #[allow(unused_variables)]
    pub fn set(&mut self, color: Color) {
        let w = self.w;
        let h = self.h;
        self.rect(0, 0, w, h, color);
    }

    /// Draw rectangle
    // TODO: Improve speed
    #[allow(unused_variables)]
    pub fn rect(&mut self, start_x: isize, start_y: isize, w: usize, h: usize, color: Color) {
        for y in start_y..start_y + h as isize {
            for x in start_x..start_x + w as isize {
                self.pixel(x, y, color);
            }
        }
    }

    /// Display an image
    //TODO: Improve speed
    pub fn image(&mut self, start_x: isize, start_y: isize, w: usize, h: usize, data: &[Color]) {
        let mut i = 0;
        for y in start_y..start_y + h as isize {
            for x in start_x..start_x + w as isize {
                if i < data.len() {
                    self.pixel(x, y, data[i])
                }
                i += 1;
            }
        }
    }

    /// Poll for an event
    //TODO: clean this up
    pub fn poll(&mut self) -> Option<Event> {
        let mut event = box Event::new();
        let event_ptr: *mut Event = event.deref_mut();
        loop {
            match self.file.read(&mut unsafe {
                slice::from_raw_parts_mut(event_ptr as *mut u8, mem::size_of::<Event>())
            }) {
                Some(0) => unsafe { sys_yield() },
                Some(_) => return Some(*event),
                None => return None,
            }
        }
    }

    /// Flip the window buffer
    pub fn sync(&mut self) -> bool {
        self.file.seek(SeekFrom::Start(0));
        let to_write: &[u8] = unsafe{ mem::transmute::<&[u32],&[u8]>(&self.data) };
        self.file.write(to_write);
        return self.file.sync();
    }

    /// Return a iterator over events
    pub fn event_iter<'a>(&'a mut self) -> EventIter<'a> {
        EventIter {
            window: self,
        }
    }
}

/// Event iterator
pub struct EventIter<'a> {
    window: &'a mut Window,
}

impl<'a> Iterator for EventIter<'a> {
    type Item = Event;
    fn next(&mut self) -> Option<Event> {
        self.window.poll()
    }
}
<|endoftext|>


<commit_before>use std::str::pattern::*;

// This macro makes it easier to write
// tests that do a series of iterations
macro_rules! search_asserts {
    ($haystack:expr, $needle:expr, $testname:expr, [$($func:ident),*], $result:expr) => {
        let mut searcher = $needle.into_searcher($haystack);
        let arr = [$( Step::from(searcher.$func()) ),+];
        assert_eq!(&arr[..], &$result, $testname);
    }
}

/// Combined enum for the results of next() and next_match()/next_reject()
#[derive(Debug, PartialEq, Eq)]
enum Step {
    // variant names purposely chosen to
    // be the same length for easy alignment
    Matches(usize, usize),
    Rejects(usize, usize),
    InRange(usize, usize),
    Done
}

use Step::*;

impl From<SearchStep> for Step {
    fn from(x: SearchStep) -> Self {
        match x {
            SearchStep::Match(a, b) => Matches(a, b),
            SearchStep::Reject(a, b) => Rejects(a, b),
            SearchStep::Done => Done
        }
    }
}

impl From<Option<(usize, usize)>> for Step {
    fn from(x: Option<(usize, usize)>) -> Self {
        match x {
            Some((a, b)) => InRange(a, b),
            None => Done
        }
    }
}

#[test]
fn test_simple_iteration() {
    search_asserts! ("abcdeabcd", 'a', "forward iteration for ASCII string",
        // a            b              c              d              e              a              b              c              d              EOF
        [next,          next,          next,          next,          next,          next,          next,          next,          next,          next],
        [Matches(0, 1), Rejects(1, 2), Rejects(2, 3), Rejects(3, 4), Rejects(4, 5), Matches(5, 6), Rejects(6, 7), Rejects(7, 8), Rejects(8, 9), Done]
    );

    search_asserts! ("abcdeabcd", 'a', "reverse iteration for ASCII string",
        // d            c              b              a            e                d              c              b              a             EOF
        [next_back,     next_back,     next_back,     next_back,     next_back,     next_back,     next_back,     next_back,     next_back,     next_back],
        [Rejects(8, 9), Rejects(7, 8), Rejects(6, 7), Matches(5, 6), Rejects(4, 5), Rejects(3, 4), Rejects(2, 3), Rejects(1, 2), Matches(0, 1), Done]
    );

    search_asserts! ("我爱我的猫", '我', "forward iteration for Chinese string",
        // 我           愛             我             的              貓               EOF
        [next,          next,          next,          next,           next,            next],
        [Matches(0, 3), Rejects(3, 6), Matches(6, 9), Rejects(9, 12), Rejects(12, 15), Done]
    );

    search_asserts! ("我的猫说meow", 'm', "forward iteration for mixed string",
        // 我           的             猫             说              m                e                o                w                EOF
        [next,          next,          next,          next,           next,            next,            next,            next,            next],
        [Rejects(0, 3), Rejects(3, 6), Rejects(6, 9), Rejects(9, 12), Matches(12, 13), Rejects(13, 14), Rejects(14, 15), Rejects(15, 16), Done]
    );

    search_asserts! ("我的猫说meow", '猫', "reverse iteration for mixed string",
        // w             o                 e                m                说              猫             的             我             EOF
        [next_back,       next_back,       next_back,       next_back,       next_back,      next_back,      next_back,    next_back,     next_back],
        [Rejects(15, 16), Rejects(14, 15), Rejects(13, 14), Rejects(12, 13), Rejects(9, 12), Matches(6, 9), Rejects(3, 6), Rejects(0, 3), Done]
    );
}
<commit_msg>Add simple search test for pattern API<commit_after>use std::str::pattern::*;

// This macro makes it easier to write
// tests that do a series of iterations
macro_rules! search_asserts {
    ($haystack:expr, $needle:expr, $testname:expr, [$($func:ident),*], $result:expr) => {
        let mut searcher = $needle.into_searcher($haystack);
        let arr = [$( Step::from(searcher.$func()) ),+];
        assert_eq!(&arr[..], &$result, $testname);
    }
}

/// Combined enum for the results of next() and next_match()/next_reject()
#[derive(Debug, PartialEq, Eq)]
enum Step {
    // variant names purposely chosen to
    // be the same length for easy alignment
    Matches(usize, usize),
    Rejects(usize, usize),
    InRange(usize, usize),
    Done
}

use Step::*;

impl From<SearchStep> for Step {
    fn from(x: SearchStep) -> Self {
        match x {
            SearchStep::Match(a, b) => Matches(a, b),
            SearchStep::Reject(a, b) => Rejects(a, b),
            SearchStep::Done => Done
        }
    }
}

impl From<Option<(usize, usize)>> for Step {
    fn from(x: Option<(usize, usize)>) -> Self {
        match x {
            Some((a, b)) => InRange(a, b),
            None => Done
        }
    }
}

#[test]
fn test_simple_iteration() {
    search_asserts! ("abcdeabcd", 'a', "forward iteration for ASCII string",
        // a            b              c              d              e              a              b              c              d              EOF
        [next,          next,          next,          next,          next,          next,          next,          next,          next,          next],
        [Matches(0, 1), Rejects(1, 2), Rejects(2, 3), Rejects(3, 4), Rejects(4, 5), Matches(5, 6), Rejects(6, 7), Rejects(7, 8), Rejects(8, 9), Done]
    );

    search_asserts! ("abcdeabcd", 'a', "reverse iteration for ASCII string",
        // d            c              b              a            e                d              c              b              a             EOF
        [next_back,     next_back,     next_back,     next_back,     next_back,     next_back,     next_back,     next_back,     next_back,     next_back],
        [Rejects(8, 9), Rejects(7, 8), Rejects(6, 7), Matches(5, 6), Rejects(4, 5), Rejects(3, 4), Rejects(2, 3), Rejects(1, 2), Matches(0, 1), Done]
    );

    search_asserts! ("我爱我的猫", '我', "forward iteration for Chinese string",
        // 我           愛             我             的              貓               EOF
        [next,          next,          next,          next,           next,            next],
        [Matches(0, 3), Rejects(3, 6), Matches(6, 9), Rejects(9, 12), Rejects(12, 15), Done]
    );

    search_asserts! ("我的猫说meow", 'm', "forward iteration for mixed string",
        // 我           的             猫             说              m                e                o                w                EOF
        [next,          next,          next,          next,           next,            next,            next,            next,            next],
        [Rejects(0, 3), Rejects(3, 6), Rejects(6, 9), Rejects(9, 12), Matches(12, 13), Rejects(13, 14), Rejects(14, 15), Rejects(15, 16), Done]
    );

    search_asserts! ("我的猫说meow", '猫', "reverse iteration for mixed string",
        // w             o                 e                m                说              猫             的             我             EOF
        [next_back,       next_back,       next_back,       next_back,       next_back,      next_back,      next_back,    next_back,     next_back],
        [Rejects(15, 16), Rejects(14, 15), Rejects(13, 14), Rejects(12, 13), Rejects(9, 12), Matches(6, 9), Rejects(3, 6), Rejects(0, 3), Done]
    );
}

#[test]
fn test_simple_search() {
    search_asserts!("abcdeabcdeabcde", 'a', "next_match for ASCII string",
        [next_match,    next_match,    next_match,      next_match],
        [InRange(0, 1), InRange(5, 6), InRange(10, 11), Done]
    );

    search_asserts!("abcdeabcdeabcde", 'a', "next_match_back for ASCII string",
        [next_match_back, next_match_back, next_match_back, next_match_back],
        [InRange(10, 11), InRange(5, 6),   InRange(0, 1),   Done]
    );

    search_asserts!("abcdeab", 'a', "next_reject for ASCII string",
        [next_reject,   next_reject,   next_match,    next_reject,   next_reject],
        [InRange(1, 2), InRange(2, 3), InRange(5, 6), InRange(6, 7), Done]
    );

    search_asserts!("abcdeabcdeabcde", 'a', "next_reject_back for ASCII string",
        [next_reject_back, next_reject_back, next_match_back, next_reject_back, next_reject_back, next_reject_back],
        [InRange(14, 15),  InRange(13, 14),  InRange(10, 11), InRange(9, 10),   InRange(8, 9),    InRange(7, 8)]
    );
}

<|endoftext|>


<commit_before>// Copyright (c) 2017 Gilad Naaman
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

/// Produces a range instance representing the sub-slice containing the specified member.
///
/// This macro provides 2 forms of differing functionalities.
///
/// The first form is identical to the appearance of the `offset_of!` macro,
/// and just like `offset_of!`, it has no limit on the depth of fields / subscripts used.
///
/// ```ignore
/// span_of!(Struct, member[index].field)
/// ```
///
/// The second form of `span_of!` returns a sub-slice which starts at one field, and ends at another.
/// The general pattern of this form is:
///
/// ```ignore
/// // Exclusive
/// span_of!(Struct, member_a .. member_b)
/// // Inclusive
/// span_of!(Struct, member_a ..= member_b)
///
/// // Open-ended ranges
/// span_of!(Struct, .. end)
/// span_of!(Struct, start ..)
/// ```
///
/// *Note*:
/// This macro uses recursion in order to resolve the range expressions, so there is a limit to the complexity of the expression.
/// In order to raise the limit, the compiler's recursion limit should be lifted.
///
/// *Note*:
/// This macro may not make much sense when used on structs that are not `#[repr(C, packed)]`
///
/// ## Examples
/// ```
/// #[macro_use]
/// extern crate memoffset;
///
/// #[repr(C, packed)]
/// struct Florp {
///     a: u32
/// }
///
/// #[repr(C, packed)]
/// struct Blarg {
///     x: u64,
///     y: [u8; 56],
///     z: Florp,
///     egg: [[u8; 4]; 4]
/// }
///
/// fn main() {
///     assert_eq!(0..8,   span_of!(Blarg, x));
///     assert_eq!(64..68, span_of!(Blarg, z.a));
///     assert_eq!(79..80, span_of!(Blarg, egg[2][3]));
///
///     assert_eq!(8..64,  span_of!(Blarg, y[0]  ..  z));
///     assert_eq!(0..42,  span_of!(Blarg, x     ..  y[34]));
///     assert_eq!(0..64,  span_of!(Blarg, x     ..= y));
///     assert_eq!(58..68, span_of!(Blarg, y[50] ..= z));
///
///     const SPAN: std::ops::Range<usize> = span_of!(Blarg, y[50] ..= z);
///     assert_eq!(58..68, SPAN);
/// }
/// ```
#[macro_export]
#[cfg(memoffset_constant_expression)]
macro_rules! span_of {
    (@helper $root:ident, [] ..=) => (
        compile_error!("Expected a range, found '..='")
    );
    (@helper $root:ident, [] ..) => (
        compile_error!("Expected a range, found '..'")
    );
    (@helper $root:ident, [] ..= $($field:tt)+) => (
        0..($crate::Transmuter { ptr: &$root.$($field)+ }.int + $crate::size_of(&$root.$($field)+))
    );
    (@helper $root:ident, [] .. $($field:tt)+) => (
        0..$crate::Transmuter { ptr: &$root.$($field)+ }.int
    );
    (@helper $root:ident, $(# $begin:tt)+ [] ..= $($end:tt)+) => (
        $crate::Transmuter { ptr: &$root.$($begin)+ }.int..($crate::Transmuter { ptr: &$root.$($end)+ }.int + $crate::size_of(&$root.$($end)+))
    );
    (@helper $root:ident, $(# $begin:tt)+ [] .. $($end:tt)+) => (
        $crate::Transmuter { ptr: &$root.$($begin)+ }.int..$crate::Transmuter { ptr: &$root.$($end)+ }.int
    );
    (@helper $root:ident, $(# $begin:tt)+ [] ..) => (
        $crate::Transmuter { ptr: &$root.$($begin)+ }.int..$crate::size_of($root)
    );
    (@helper $root:ident, $(# $begin:tt)+ [] ..=) => {
        compile_error!(
            "Found inclusive range to the end of a struct. Did you mean '..' instead of '..='?")
    };
    (@helper $root:ident, $(# $begin:tt)+ [] ) => ({
        let start = $crate::Transmuter { ptr: &$root.$($begin)+ }.int;
        start..(start + $crate::size_of(&$root.$($begin)+))
    });
    (@helper $root:ident, $(# $begin:tt)+ [] $tt:tt $($rest:tt)*) => {
        span_of!(@helper $root, $(#$begin)* #$tt [] $($rest)*)
    };
    (@helper $root:ident, [] $tt:tt $($rest:tt)*) => {
        span_of!(@helper $root, #$tt [] $($rest)*)
    };

    ($parent:ty, $($exp:tt)+) => (unsafe {
        let root: &'static $parent = $crate::Transmuter::<$parent> { int: 0 }.ptr;
        span_of!(@helper root, [] $($exp)*)
    });
}

#[macro_export]
#[cfg(not(memoffset_constant_expression))]
macro_rules! span_of {
    (@helper $root:ident, [] ..=) => {
        compile_error!("Expected a range, found '..='")
    };
    (@helper $root:ident, [] ..) => {
        compile_error!("Expected a range, found '..'")
    };
    (@helper $root:ident, [] ..= $($field:tt)+) => {
        (&$root as *const _ as usize,
         &$root.$($field)* as *const _ as usize + $crate::mem::size_of_val(&$root.$($field)*))
    };
    (@helper $root:ident, [] .. $($field:tt)+) => {
        (&$root as *const _ as usize, &$root.$($field)* as *const _ as usize)
    };
    (@helper $root:ident, $(# $begin:tt)+ [] ..= $($end:tt)+) => {
        (&$root.$($begin)* as *const _ as usize,
         &$root.$($end)* as *const _ as usize + $crate::mem::size_of_val(&$root.$($end)*))
    };
    (@helper $root:ident, $(# $begin:tt)+ [] .. $($end:tt)+) => {
        (&$root.$($begin)* as *const _ as usize, &$root.$($end)* as *const _ as usize)
    };
    (@helper $root:ident, $(# $begin:tt)+ [] ..) => {
        (&$root.$($begin)* as *const _ as usize,
         &$root as *const _ as usize + $crate::mem::size_of_val(&$root))
    };
    (@helper $root:ident, $(# $begin:tt)+ [] ..=) => {
        compile_error!(
            "Found inclusive range to the end of a struct. Did you mean '..' instead of '..='?")
    };
    (@helper $root:ident, $(# $begin:tt)+ []) => {
        (&$root.$($begin)* as *const _ as usize,
         &$root.$($begin)* as *const _ as usize + $crate::mem::size_of_val(&$root.$($begin)*))
    };
    (@helper $root:ident, $(# $begin:tt)+ [] $tt:tt $($rest:tt)*) => {
        span_of!(@helper $root, $(#$begin)* #$tt [] $($rest)*)
    };
    (@helper $root:ident, [] $tt:tt $($rest:tt)*) => {
        span_of!(@helper $root, #$tt [] $($rest)*)
    };

    ($sty:ty, $($exp:tt)+) => ({
        unsafe {
            let root: $sty = $crate::mem::uninitialized();
            let base = &root as *const _ as usize;
            let (begin, end) = span_of!(@helper root, [] $($exp)*);
            begin-base..end-base
        }
    });
}

#[cfg(test)]
mod tests {
    use core::mem;

    #[repr(C, packed)]
    struct Foo {
        a: u32,
        b: [u8; 4],
        c: i64,
    }

    #[test]
    fn span_simple() {
        assert_eq!(span_of!(Foo, a), 0..4);
        assert_eq!(span_of!(Foo, b), 4..8);
        assert_eq!(span_of!(Foo, c), 8..16);
    }

    #[test]
    fn span_index() {
        assert_eq!(span_of!(Foo, b[1]), 5..6);
    }

    #[test]
    fn span_forms() {
        #[repr(C, packed)]
        struct Florp {
            a: u32,
        }

        #[repr(C, packed)]
        struct Blarg {
            x: u64,
            y: [u8; 56],
            z: Florp,
            egg: [[u8; 4]; 4],
        }

        // Love me some brute force
        assert_eq!(0..8, span_of!(Blarg, x));
        assert_eq!(64..68, span_of!(Blarg, z.a));
        assert_eq!(79..80, span_of!(Blarg, egg[2][3]));

        assert_eq!(8..64, span_of!(Blarg, y[0]..z));
        assert_eq!(0..42, span_of!(Blarg, x..y[34]));
        assert_eq!(0..64, span_of!(Blarg, x..=y));
        assert_eq!(58..68, span_of!(Blarg, y[50]..=z));
    }

    #[test]
    fn ig_test() {
        #[repr(C)]
        struct Member {
            foo: u32,
        }

        #[repr(C)]
        struct Test {
            x: u64,
            y: [u8; 56],
            z: Member,
            egg: [[u8; 4]; 4],
        }

        assert_eq!(span_of!(Test, ..x), 0..0);
        assert_eq!(span_of!(Test, ..=x), 0..8);
        assert_eq!(span_of!(Test, ..y), 0..8);
        assert_eq!(span_of!(Test, ..=y), 0..64);
        assert_eq!(span_of!(Test, ..y[0]), 0..8);
        assert_eq!(span_of!(Test, ..=y[0]), 0..9);
        assert_eq!(span_of!(Test, ..z), 0..64);
        assert_eq!(span_of!(Test, ..=z), 0..68);
        assert_eq!(span_of!(Test, ..z.foo), 0..64);
        assert_eq!(span_of!(Test, ..=z.foo), 0..68);
        assert_eq!(span_of!(Test, ..egg), 0..68);
        assert_eq!(span_of!(Test, ..=egg), 0..84);
        assert_eq!(span_of!(Test, ..egg[0]), 0..68);
        assert_eq!(span_of!(Test, ..=egg[0]), 0..72);
        assert_eq!(span_of!(Test, ..egg[0][0]), 0..68);
        assert_eq!(span_of!(Test, ..=egg[0][0]), 0..69);
        assert_eq!(
            span_of!(Test, x..),
            offset_of!(Test, x)..mem::size_of::<Test>()
        );
        assert_eq!(
            span_of!(Test, y..),
            offset_of!(Test, y)..mem::size_of::<Test>()
        );

        assert_eq!(
            span_of!(Test, z..),
            offset_of!(Test, z)..mem::size_of::<Test>()
        );
        assert_eq!(
            span_of!(Test, egg..),
            offset_of!(Test, egg)..mem::size_of::<Test>()
        );
        assert_eq!(
            span_of!(Test, x..y),
            offset_of!(Test, x)..offset_of!(Test, y)
        );
        assert_eq!(
            span_of!(Test, x..=y),
            offset_of!(Test, x)..offset_of!(Test, y) + mem::size_of::<[u8; 56]>()
        );
        assert_eq!(
            span_of!(Test, x..=y[4]),
            offset_of!(Test, x)..offset_of!(Test, y) + mem::size_of::<[u8; 5]>()
        );
    }
}
<commit_msg>use the same base_ptr macro for span_of<commit_after>// Copyright (c) 2017 Gilad Naaman
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

/// Produces a range instance representing the sub-slice containing the specified member.
///
/// This macro provides 2 forms of differing functionalities.
///
/// The first form is identical to the appearance of the `offset_of!` macro,
/// and just like `offset_of!`, it has no limit on the depth of fields / subscripts used.
///
/// ```ignore
/// span_of!(Struct, member[index].field)
/// ```
///
/// The second form of `span_of!` returns a sub-slice which starts at one field, and ends at another.
/// The general pattern of this form is:
///
/// ```ignore
/// // Exclusive
/// span_of!(Struct, member_a .. member_b)
/// // Inclusive
/// span_of!(Struct, member_a ..= member_b)
///
/// // Open-ended ranges
/// span_of!(Struct, .. end)
/// span_of!(Struct, start ..)
/// ```
///
/// *Note*:
/// This macro uses recursion in order to resolve the range expressions, so there is a limit to the complexity of the expression.
/// In order to raise the limit, the compiler's recursion limit should be lifted.
///
/// *Note*:
/// This macro may not make much sense when used on structs that are not `#[repr(C, packed)]`
///
/// ## Examples
/// ```
/// #[macro_use]
/// extern crate memoffset;
///
/// #[repr(C, packed)]
/// struct Florp {
///     a: u32
/// }
///
/// #[repr(C, packed)]
/// struct Blarg {
///     x: u64,
///     y: [u8; 56],
///     z: Florp,
///     egg: [[u8; 4]; 4]
/// }
///
/// fn main() {
///     assert_eq!(0..8,   span_of!(Blarg, x));
///     assert_eq!(64..68, span_of!(Blarg, z.a));
///     assert_eq!(79..80, span_of!(Blarg, egg[2][3]));
///
///     assert_eq!(8..64,  span_of!(Blarg, y[0]  ..  z));
///     assert_eq!(0..42,  span_of!(Blarg, x     ..  y[34]));
///     assert_eq!(0..64,  span_of!(Blarg, x     ..= y));
///     assert_eq!(58..68, span_of!(Blarg, y[50] ..= z));
/// }
/// ```
#[macro_export]
macro_rules! span_of {
    (@helper  $root:ident, [] ..=) => {
        compile_error!("Expected a range, found '..='")
    };
    (@helper $root:ident, [] ..) => {
        compile_error!("Expected a range, found '..'")
    };
    // Lots of UB due to taking references to uninitialized fields! But that can currently
    // not be avoided.
    (@helper $root:ident, [] ..= $($field:tt)+) => {
        ($root as usize,
         &(*$root).$($field)* as *const _ as usize + $crate::mem::size_of_val(&(*$root).$($field)*))
    };
    (@helper $root:ident, [] .. $($field:tt)+) => {
        ($root as usize, &(*$root).$($field)* as *const _ as usize)
    };
    (@helper $root:ident, $(# $begin:tt)+ [] ..= $($end:tt)+) => {
        (&(*$root).$($begin)* as *const _ as usize,
         &(*$root).$($end)* as *const _ as usize + $crate::mem::size_of_val(&(*$root).$($end)*))
    };
    (@helper $root:ident, $(# $begin:tt)+ [] .. $($end:tt)+) => {
        (&(*$root).$($begin)* as *const _ as usize,
         &(*$root).$($end)* as *const _ as usize)
    };
    (@helper $root:ident, $(# $begin:tt)+ [] ..) => {
        (&(*$root).$($begin)* as *const _ as usize,
         $root as usize + $crate::mem::size_of_val(&*$root))
    };
    (@helper $root:ident, $(# $begin:tt)+ [] ..=) => {
        compile_error!(
            "Found inclusive range to the end of a struct. Did you mean '..' instead of '..='?")
    };
    (@helper $root:ident, $(# $begin:tt)+ []) => {
        (&(*$root).$($begin)* as *const _ as usize,
         &(*$root).$($begin)* as *const _ as usize + $crate::mem::size_of_val(&(*$root).$($begin)*))
    };
    (@helper $root:ident, $(# $begin:tt)+ [] $tt:tt $($rest:tt)*) => {
        span_of!(@helper $root, $(#$begin)* #$tt [] $($rest)*)
    };
    (@helper $root:ident, [] $tt:tt $($rest:tt)*) => {
        span_of!(@helper $root, #$tt [] $($rest)*)
    };

    ($sty:tt, $($exp:tt)+) => ({
        unsafe {
            // Get a base pointer.
            $crate::let_base_ptr!(root, $sty);
            let base = root as usize;
            let (begin, end) = span_of!(@helper root, [] $($exp)*);
            begin-base..end-base
        }
    });
}

#[cfg(test)]
mod tests {
    use core::mem;

    #[repr(C, packed)]
    struct Foo {
        a: u32,
        b: [u8; 4],
        c: i64,
    }

    #[test]
    fn span_simple() {
        assert_eq!(span_of!(Foo, a), 0..4);
        assert_eq!(span_of!(Foo, b), 4..8);
        assert_eq!(span_of!(Foo, c), 8..16);
    }

    #[test]
    fn span_index() {
        assert_eq!(span_of!(Foo, b[1]), 5..6);
    }

    #[test]
    fn span_forms() {
        #[repr(C, packed)]
        struct Florp {
            a: u32,
        }

        #[repr(C, packed)]
        struct Blarg {
            x: u64,
            y: [u8; 56],
            z: Florp,
            egg: [[u8; 4]; 4],
        }

        // Love me some brute force
        assert_eq!(0..8, span_of!(Blarg, x));
        assert_eq!(64..68, span_of!(Blarg, z.a));
        assert_eq!(79..80, span_of!(Blarg, egg[2][3]));

        assert_eq!(8..64, span_of!(Blarg, y[0]..z));
        assert_eq!(0..42, span_of!(Blarg, x..y[34]));
        assert_eq!(0..64, span_of!(Blarg, x..=y));
        assert_eq!(58..68, span_of!(Blarg, y[50]..=z));
    }

    #[test]
    fn ig_test() {
        #[repr(C)]
        struct Member {
            foo: u32,
        }

        #[repr(C)]
        struct Test {
            x: u64,
            y: [u8; 56],
            z: Member,
            egg: [[u8; 4]; 4],
        }

        assert_eq!(span_of!(Test, ..x), 0..0);
        assert_eq!(span_of!(Test, ..=x), 0..8);
        assert_eq!(span_of!(Test, ..y), 0..8);
        assert_eq!(span_of!(Test, ..=y), 0..64);
        assert_eq!(span_of!(Test, ..y[0]), 0..8);
        assert_eq!(span_of!(Test, ..=y[0]), 0..9);
        assert_eq!(span_of!(Test, ..z), 0..64);
        assert_eq!(span_of!(Test, ..=z), 0..68);
        assert_eq!(span_of!(Test, ..z.foo), 0..64);
        assert_eq!(span_of!(Test, ..=z.foo), 0..68);
        assert_eq!(span_of!(Test, ..egg), 0..68);
        assert_eq!(span_of!(Test, ..=egg), 0..84);
        assert_eq!(span_of!(Test, ..egg[0]), 0..68);
        assert_eq!(span_of!(Test, ..=egg[0]), 0..72);
        assert_eq!(span_of!(Test, ..egg[0][0]), 0..68);
        assert_eq!(span_of!(Test, ..=egg[0][0]), 0..69);
        assert_eq!(
            span_of!(Test, x..),
            offset_of!(Test, x)..mem::size_of::<Test>()
        );
        assert_eq!(
            span_of!(Test, y..),
            offset_of!(Test, y)..mem::size_of::<Test>()
        );

        assert_eq!(
            span_of!(Test, z..),
            offset_of!(Test, z)..mem::size_of::<Test>()
        );
        assert_eq!(
            span_of!(Test, egg..),
            offset_of!(Test, egg)..mem::size_of::<Test>()
        );
        assert_eq!(
            span_of!(Test, x..y),
            offset_of!(Test, x)..offset_of!(Test, y)
        );
        assert_eq!(
            span_of!(Test, x..=y),
            offset_of!(Test, x)..offset_of!(Test, y) + mem::size_of::<[u8; 56]>()
        );
        assert_eq!(
            span_of!(Test, x..=y[4]),
            offset_of!(Test, x)..offset_of!(Test, y) + mem::size_of::<[u8; 5]>()
        );
    }
}
<|endoftext|>


<commit_before>extern mod std;
use std::net_ip;
use std::uv_global_loop;

fn main() {
    let url = "www.google.com";
    let iotask = uv_global_loop::get();
    let address = net_ip::get_addr(url, iotask);
    match address {
        Ok(ips) => {
            for ips.each |ip| {
                io::println(net_ip::format_addr(ip));
            };
        },
        Err(_) => io::println(fmt!("Error: " ))
    };
    return;
}
<commit_msg>Sending and recieving basic HTTP request.<commit_after>extern mod std;
use std::{net_tcp, net_ip};
use std::uv_global_loop;

fn build_request() -> ~str {
    let request = ~"GET / HTTP 1.0\u000D\u000A";
    return move request;
}

fn main() {
    let url = "localhost";
    let iotask = uv_global_loop::get();
    let address = net_ip::get_addr(url, iotask);
    match address {
        Ok(ips) => {
            for ips.each |ip| {
                io::println(net_ip::format_addr(ip));
            };
            io::println("");
            for ips.each |ip| {
                io::println(net_ip::format_addr(ip));
                let ip_addr = copy ip;
                let socket = {
                    let socket = std::net::tcp::connect(*ip_addr, 80, iotask);
                    if socket.is_ok() {
                        result::unwrap(move socket)
                    }
                    else {
                        io::println("Error connecting");
                        return;
                    }
                };
                io::println("Connected!");
                match socket.write(str::to_bytes(build_request())) {
                    Ok(_) =>  {}
                    Err(e) => {
                        io::println(fmt!("Error sending request: %?", e));
                        return;
                    }
                };
                io::println("Wrote data");
                loop {
                    io::println("starting loop");
                    let data = socket.read(1000);
                    io::println("Received some data");
                    if data.is_ok() {
                        let data = result::unwrap(move data);
                        io::println(str::from_bytes(data));
                    }
                    else {
                        let err = result::unwrap_err(move data);
                        io::println(fmt!("Read error: %?", err));
                        break;
                    }
                };
            };
        },
        Err(_) => io::println(fmt!("Error: " ))
    };
    return;
}
<|endoftext|>


<commit_before>// Copyright 2009-2016 compiler-builtins Developers
//
// The compiler-builtins crate is dual licensed under both the University of
// Illinois "BSD-Like" license and the MIT license.  As a user of this code you may
// choose to use it under either license. As a contributor, you agree to allow
// your code to be used under both.
//
// Full text of the relevant licenses is found here:
// https://github.com/rust-lang-nursery/compiler-builtins/blob/master/LICENSE.TXT
//
//
//
// The following code is based on Rust’s [compiler-builtins crate]
// (https://github.com/rust-lang-nursery/compiler-builtins) which
// provides runtime functions for the Rust programs. The Rust
// compiler will automatically link your programs against this crate.
//
// We copied the implementation of '__udivmodti4()' which is an intrinsic
// implementing division with remainder for architectures without 128-bit integer support.
// We have done this two reasons, to work around [bad optimization by LLVM]
// (https://github.com/rust-lang/rust/issues/44545) and to allow function
// inlining which doesn’t happen with the intrinsic.

#[inline]
pub fn udivmod_1e19(n: u128) -> (u128, u64) {
    let d = 10_000_000_000_000_000_000_u64; // 10^19

    let high = (n >> 64) as u64;
    if high == 0 {
        let low = n as u64;
        return ((low / d) as u128, low % d);
    }

    let sr = 65 - high.leading_zeros();

    // 2 <= sr <= 65
    let mut q: u128 = n << (128 - sr);
    let mut r: u128 = n >> sr;
    let mut carry: u64 = 0;

    // Don't use a range because they may generate references to memcpy in unoptimized code
    //
    // Loop invariants:  r < d; carry is 0 or 1
    let mut i = 0;
    while i < sr {
        i += 1;

        // r:q = ((r:q) << 1) | carry
        r = (r << 1) | (q >> 127);
        q = (q << 1) | carry as u128;

        // carry = 0
        // if r >= d {
        //     r -= d;
        //     carry = 1;
        // }
        let s = (d as u128).wrapping_sub(r).wrapping_sub(1) as i128 >> 127;
        carry = (s & 1) as u64;
        r -= (d as u128) & s as u128;
    }

    ((q << 1) | carry as u128, r as u64)
}
<commit_msg>Clarify udiv128 licensing<commit_after>// The code in this file is based on Rust's compiler-builtins crate. The Rust
// compiler automatically links programs against this crate for target-specific
// runtime support. We have copied the implementation of `__udivmodti4()` which
// is an intrinsic implementing division with remainder for architectures
// without 128-bit integers. This implementation works around some poor codegen
// by LLVM (https://github.com/rust-lang/rust/issues/44545) and allows for
// inlining which does not happen with the intrinsic.
//
// The compiler-builtins crate carries the following license, which is available
// in full at:
// https://github.com/rust-lang-nursery/compiler-builtins/blob/master/LICENSE.TXT
//
// ---
//
// Copyright 2009-2016 compiler-builtins Developers
//
// The compiler-builtins crate is dual licensed under both the University of
// Illinois "BSD-Like" license and the MIT license. As a user of this code you
// may choose to use it under either license. As a contributor, you agree to
// allow your code to be used under both.

#[inline]
pub fn udivmod_1e19(n: u128) -> (u128, u64) {
    let d = 10_000_000_000_000_000_000_u64; // 10^19

    let high = (n >> 64) as u64;
    if high == 0 {
        let low = n as u64;
        return ((low / d) as u128, low % d);
    }

    let sr = 65 - high.leading_zeros();

    // 2 <= sr <= 65
    let mut q: u128 = n << (128 - sr);
    let mut r: u128 = n >> sr;
    let mut carry: u64 = 0;

    // Don't use a range because they may generate references to memcpy in unoptimized code
    //
    // Loop invariants:  r < d; carry is 0 or 1
    let mut i = 0;
    while i < sr {
        i += 1;

        // r:q = ((r:q) << 1) | carry
        r = (r << 1) | (q >> 127);
        q = (q << 1) | carry as u128;

        // carry = 0
        // if r >= d {
        //     r -= d;
        //     carry = 1;
        // }
        let s = (d as u128).wrapping_sub(r).wrapping_sub(1) as i128 >> 127;
        carry = (s & 1) as u64;
        r -= (d as u128) & s as u128;
    }

    ((q << 1) | carry as u128, r as u64)
}
<|endoftext|>


<commit_before>use std::net::{Ipv4Addr, Ipv6Addr, SocketAddrV4, SocketAddrV6};

/// Convert a 4 byte value to an array of 4 bytes.
pub fn four_bytes_to_array(bytes: u32) -> [u8; 4] {
    let eight_bytes = eight_bytes_to_array(bytes as u64);

    [eight_bytes[4], eight_bytes[5], eight_bytes[6], eight_bytes[7]]
}

/// Convert an 8 byte value to an array of 8 bytes.
pub fn eight_bytes_to_array(bytes: u64) -> [u8; 8] {
    [(bytes >> 56) as u8, (bytes >> 48) as u8, (bytes >> 40) as u8, (bytes >> 32) as u8,
    (bytes >> 24) as u8, (bytes >> 16) as u8, (bytes >> 8) as u8, (bytes >> 0) as u8]
}

/// Convert an ipv4 address to an array of 4 bytes big endian.
pub fn ipv4_to_bytes_be(v4_addr: Ipv4Addr) -> [u8; 4] {
    v4_addr.octets()
}

/// Convert an ipv6 address to an array of 16 bytes big endian.
pub fn ipv6_to_bytes_be(v6_addr: Ipv6Addr) -> [u8; 16] {
    let segments = v6_addr.segments();
    let mut bytes = [0u8; 16];

    for index in 0..bytes.len() {
        let segment_index = index / 2;

        let segment_byte_index = index % 2;
        let byte_shift_bits = 8 - (segment_byte_index * 8);

        let byte = (segments[segment_index] >> byte_shift_bits) as u8;

        bytes[index] = byte;
    }

    bytes
}

/// Convert an array of 4 bytes big endian to an ipv4 address.
pub fn bytes_be_to_ipv4(bytes: [u8; 4]) -> Ipv4Addr {
    Ipv4Addr::new(bytes[0], bytes[1], bytes[2], bytes[3])
}

/// Convert an array of 16 bytes big endian to an ipv6 address.
pub fn bytes_be_to_ipv6(bytes: [u8; 16]) -> Ipv6Addr {
    let mut combined_bytes = [0u16; 8];

    for (index, &value) in bytes.iter().enumerate() {
        let combined_index = index / 2;
        let should_shift = index % 2 == 0;

        let adjusted_value = if should_shift {
            (value as u16) << 8
        } else { value as u16 };

        combined_bytes[combined_index] |= adjusted_value;
    }

    Ipv6Addr::new(combined_bytes[0], combined_bytes[1], combined_bytes[2], combined_bytes[3],
        combined_bytes[4], combined_bytes[5], combined_bytes[6], combined_bytes[7])
}

/// Convert an array of 2 bytes big endian to a port.
pub fn bytes_be_to_port(bytes: [u8; 2]) -> u16 {
    let (high_byte, low_byte) = (bytes[0] as u16, bytes[1] as u16);

    (high_byte << 8) | low_byte
}

/// Convert an array of 6 bytes big endian to a v4 socket address.
pub fn bytes_be_to_sock_v4(bytes: [u8; 6]) -> SocketAddrV4 {
    let ip_bytes = [bytes[0], bytes[1], bytes[2], bytes[3]];
    let port_bytes = [bytes[4], bytes[5]];

    let (ip, port) = (bytes_be_to_ipv4(ip_bytes), bytes_be_to_port(port_bytes));

    SocketAddrV4::new(ip, port)
}

/// Convert an array of 18 bytes big endian to a v6 socket address.
pub fn bytes_be_to_sock_v6(bytes: [u8; 18]) -> SocketAddrV6 {
    let mut ip_bytes = [0u8; 16];
    let port_bytes = [bytes[16], bytes[17]];

    for (src, dst) in bytes.iter().take(16).zip(ip_bytes.iter_mut()) {
        *dst = *src;
    }

    let (ip, port) = (bytes_be_to_ipv6(ip_bytes), bytes_be_to_port(port_bytes));

    SocketAddrV6::new(ip, port, 0, 0)
}

#[cfg(test)]
mod tests {
    use std::net::{Ipv4Addr, Ipv6Addr, SocketAddrV4, SocketAddrV6};

    #[test]
    fn positive_four_bytes_to_array() {
        let bytes = [25, 26, 0, 60];
        let mut combined_bytes = 0u32;

        let mut shift = 32 - 8;
        for &byte in bytes.iter() {
            let shifted_byte = (byte as u32) << shift;
            combined_bytes |= shifted_byte;

            shift -= 8;
        }
        let result_bytes = super::four_bytes_to_array(combined_bytes);

        assert_eq!(bytes, result_bytes);
    }

    #[test]
    fn positive_eight_bytes_to_array() {
        let bytes = [25, 26, 0, 60, 43, 45, 65, 1];
        let mut combined_bytes = 0u64;

        let mut shift = 64 - 8;
        for &byte in bytes.iter() {
            let shifted_byte = (byte as u64) << shift;
            combined_bytes |= shifted_byte;

            shift -= 8;
        }
        let result_bytes = super::eight_bytes_to_array(combined_bytes);

        assert_eq!(bytes, result_bytes);
    }

    #[test]
    fn positive_ipv4_to_bytes_be() {
        let bytes = [127, 0, 0, 1];
        let ip = Ipv4Addr::new(bytes[0], bytes[1], bytes[2], bytes[3]);

        let result_bytes = super::ipv4_to_bytes_be(ip);

        assert_eq!(bytes, result_bytes);
    }

    #[test]
    fn positive_ipv6_to_bytes_be() {
        let bytes = [1, 0, 0, 0, 0, 0, 0, 1];
        let expected_bytes = [0, 1, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 1];

        let ip = Ipv6Addr::new(bytes[0], bytes[1], bytes[2], bytes[3],
            bytes[4], bytes[5], bytes[6], bytes[7]);

        let result_bytes = super::ipv6_to_bytes_be(ip);

        assert_eq!(expected_bytes, result_bytes);
    }

    #[test]
    fn positive_bytes_be_to_ipv4() {
        let bytes = [127, 0, 0, 1];
        let expected_ip = Ipv4Addr::new(bytes[0], bytes[1], bytes[2], bytes[3]);

        let result_ip = super::bytes_be_to_ipv4(bytes);

        assert_eq!(expected_ip, result_ip);
    }

    #[test]
    fn positive_bytes_be_to_ipv6() {
        let bytes = [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1];
        let expected_ip = Ipv6Addr::new(1, 0, 0, 0, 0, 0, 0, 1);

        let result_ip = super::bytes_be_to_ipv6(bytes);

        assert_eq!(expected_ip, result_ip);
    }

    #[test]
    fn positive_bytes_be_to_port() {
        let bytes = [1, 1];

        let result_port = super::bytes_be_to_port(bytes);

        assert_eq!(257, result_port);
    }

    #[test]
    fn positive_bytes_be_to_sock_v4() {
        let bytes = [127, 0, 0, 1, 1, 1];
        let expected_sock = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 257);

        let result_sock = super::bytes_be_to_sock_v4(bytes);

        assert_eq!(expected_sock, result_sock);
    }

    #[test]
    fn positive_bytes_be_to_sock_v6() {
        let bytes = [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1];
        let expected_sock = SocketAddrV6::new(Ipv6Addr::new(1, 0, 0, 0, 0, 0, 0, 1), 257, 0, 0);

        let result_sock = super::bytes_be_to_sock_v6(bytes);

        assert_eq!(expected_sock, result_sock);
    }
}<commit_msg>Add conversions for socket addresses to bytes<commit_after>use std::net::{Ipv4Addr, Ipv6Addr, SocketAddrV4, SocketAddrV6};

/// Convert a 4 byte value to an array of 4 bytes.
pub fn four_bytes_to_array(bytes: u32) -> [u8; 4] {
    let eight_bytes = eight_bytes_to_array(bytes as u64);

    [eight_bytes[4], eight_bytes[5], eight_bytes[6], eight_bytes[7]]
}

/// Convert an 8 byte value to an array of 8 bytes.
pub fn eight_bytes_to_array(bytes: u64) -> [u8; 8] {
    [(bytes >> 56) as u8, (bytes >> 48) as u8, (bytes >> 40) as u8, (bytes >> 32) as u8,
    (bytes >> 24) as u8, (bytes >> 16) as u8, (bytes >> 8) as u8, (bytes >> 0) as u8]
}

/// Convert an ipv4 address to an array of 4 bytes big endian.
pub fn ipv4_to_bytes_be(v4_addr: Ipv4Addr) -> [u8; 4] {
    v4_addr.octets()
}

/// Convert an ipv6 address to an array of 16 bytes big endian.
pub fn ipv6_to_bytes_be(v6_addr: Ipv6Addr) -> [u8; 16] {
    let segments = v6_addr.segments();
    let mut bytes = [0u8; 16];

    for index in 0..bytes.len() {
        let segment_index = index / 2;

        let segment_byte_index = index % 2;
        let byte_shift_bits = 8 - (segment_byte_index * 8);

        let byte = (segments[segment_index] >> byte_shift_bits) as u8;

        bytes[index] = byte;
    }

    bytes
}

// Convert a port to an array of 2 bytes big endian.
pub fn port_to_bytes_be(port: u16) -> [u8; 2] {
    [(port >> 8) as u8, (port >> 0) as u8]
}

/// Convert a v4 socket address to an array of 6 bytes big endian.
pub fn sock_v4_to_bytes_be(v4_sock: SocketAddrV4) -> [u8; 6] {
    let mut sock_bytes = [0u8; 6];

    let ip_bytes = ipv4_to_bytes_be(*v4_sock.ip());
    let port_bytes = port_to_bytes_be(v4_sock.port());

    for (src, dst) in ip_bytes.iter().chain(port_bytes.iter()).zip(sock_bytes.iter_mut()) {
        *dst = *src;
    }

    sock_bytes
}

/// Convert a v6 socket address to an array of 18 bytes big endian.
pub fn sock_v6_to_bytes_be(v6_sock: SocketAddrV6) -> [u8; 18] {
    let mut sock_bytes = [0u8; 18];

    let ip_bytes = ipv6_to_bytes_be(*v6_sock.ip());
    let port_bytes = port_to_bytes_be(v6_sock.port());

    for (src, dst) in ip_bytes.iter().chain(port_bytes.iter()).zip(sock_bytes.iter_mut()) {
        *dst = *src;
    }

    sock_bytes
}

/// Convert an array of 4 bytes big endian to an ipv4 address.
pub fn bytes_be_to_ipv4(bytes: [u8; 4]) -> Ipv4Addr {
    Ipv4Addr::new(bytes[0], bytes[1], bytes[2], bytes[3])
}

/// Convert an array of 16 bytes big endian to an ipv6 address.
pub fn bytes_be_to_ipv6(bytes: [u8; 16]) -> Ipv6Addr {
    let mut combined_bytes = [0u16; 8];

    for (index, &value) in bytes.iter().enumerate() {
        let combined_index = index / 2;
        let should_shift = index % 2 == 0;

        let adjusted_value = if should_shift {
            (value as u16) << 8
        } else { value as u16 };

        combined_bytes[combined_index] |= adjusted_value;
    }

    Ipv6Addr::new(combined_bytes[0], combined_bytes[1], combined_bytes[2], combined_bytes[3],
        combined_bytes[4], combined_bytes[5], combined_bytes[6], combined_bytes[7])
}

/// Convert an array of 2 bytes big endian to a port.
pub fn bytes_be_to_port(bytes: [u8; 2]) -> u16 {
    let (high_byte, low_byte) = (bytes[0] as u16, bytes[1] as u16);

    (high_byte << 8) | low_byte
}

/// Convert an array of 6 bytes big endian to a v4 socket address.
pub fn bytes_be_to_sock_v4(bytes: [u8; 6]) -> SocketAddrV4 {
    let ip_bytes = [bytes[0], bytes[1], bytes[2], bytes[3]];
    let port_bytes = [bytes[4], bytes[5]];

    let (ip, port) = (bytes_be_to_ipv4(ip_bytes), bytes_be_to_port(port_bytes));

    SocketAddrV4::new(ip, port)
}

/// Convert an array of 18 bytes big endian to a v6 socket address.
pub fn bytes_be_to_sock_v6(bytes: [u8; 18]) -> SocketAddrV6 {
    let mut ip_bytes = [0u8; 16];
    let port_bytes = [bytes[16], bytes[17]];

    for (src, dst) in bytes.iter().take(16).zip(ip_bytes.iter_mut()) {
        *dst = *src;
    }

    let (ip, port) = (bytes_be_to_ipv6(ip_bytes), bytes_be_to_port(port_bytes));

    SocketAddrV6::new(ip, port, 0, 0)
}

#[cfg(test)]
mod tests {
    use std::net::{Ipv4Addr, Ipv6Addr, SocketAddrV4, SocketAddrV6};

    #[test]
    fn positive_port_to_bytes_be() {
        let port = 0xAB00 | 0x00CD;

        let received = super::port_to_bytes_be(port);
        let expected = [0xAB, 0xCD];

        assert_eq!(received, expected);
    }

    #[test]
    fn positive_sock_v4_to_bytes_be() {
        let sock_addr = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1),
            1600);

        let received = super::sock_v4_to_bytes_be(sock_addr);
        let expected = [127, 0, 0, 1, (1600 >> 8) as u8, (1600 >> 0) as u8];

        assert_eq!(received, expected);
    }

    #[test]
    fn positive_sock_v6_to_bytes_be() {
        let sock_addr = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1),
            1821, 0, 0);

        let received = super::sock_v6_to_bytes_be(sock_addr);
        let expected = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
            (1821 >> 8) as u8, (1821 >> 0) as u8];

        assert_eq!(received, expected);
    }

    #[test]
    fn positive_four_bytes_to_array() {
        let bytes = [25, 26, 0, 60];
        let mut combined_bytes = 0u32;

        let mut shift = 32 - 8;
        for &byte in bytes.iter() {
            let shifted_byte = (byte as u32) << shift;
            combined_bytes |= shifted_byte;

            shift -= 8;
        }
        let result_bytes = super::four_bytes_to_array(combined_bytes);

        assert_eq!(bytes, result_bytes);
    }

    #[test]
    fn positive_eight_bytes_to_array() {
        let bytes = [25, 26, 0, 60, 43, 45, 65, 1];
        let mut combined_bytes = 0u64;

        let mut shift = 64 - 8;
        for &byte in bytes.iter() {
            let shifted_byte = (byte as u64) << shift;
            combined_bytes |= shifted_byte;

            shift -= 8;
        }
        let result_bytes = super::eight_bytes_to_array(combined_bytes);

        assert_eq!(bytes, result_bytes);
    }

    #[test]
    fn positive_ipv4_to_bytes_be() {
        let bytes = [127, 0, 0, 1];
        let ip = Ipv4Addr::new(bytes[0], bytes[1], bytes[2], bytes[3]);

        let result_bytes = super::ipv4_to_bytes_be(ip);

        assert_eq!(bytes, result_bytes);
    }

    #[test]
    fn positive_ipv6_to_bytes_be() {
        let bytes = [1, 0, 0, 0, 0, 0, 0, 1];
        let expected_bytes = [0, 1, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 1];

        let ip = Ipv6Addr::new(bytes[0], bytes[1], bytes[2], bytes[3],
            bytes[4], bytes[5], bytes[6], bytes[7]);

        let result_bytes = super::ipv6_to_bytes_be(ip);

        assert_eq!(expected_bytes, result_bytes);
    }

    #[test]
    fn positive_bytes_be_to_ipv4() {
        let bytes = [127, 0, 0, 1];
        let expected_ip = Ipv4Addr::new(bytes[0], bytes[1], bytes[2], bytes[3]);

        let result_ip = super::bytes_be_to_ipv4(bytes);

        assert_eq!(expected_ip, result_ip);
    }

    #[test]
    fn positive_bytes_be_to_ipv6() {
        let bytes = [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1];
        let expected_ip = Ipv6Addr::new(1, 0, 0, 0, 0, 0, 0, 1);

        let result_ip = super::bytes_be_to_ipv6(bytes);

        assert_eq!(expected_ip, result_ip);
    }

    #[test]
    fn positive_bytes_be_to_port() {
        let bytes = [1, 1];

        let result_port = super::bytes_be_to_port(bytes);

        assert_eq!(257, result_port);
    }

    #[test]
    fn positive_bytes_be_to_sock_v4() {
        let bytes = [127, 0, 0, 1, 1, 1];
        let expected_sock = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 257);

        let result_sock = super::bytes_be_to_sock_v4(bytes);

        assert_eq!(expected_sock, result_sock);
    }

    #[test]
    fn positive_bytes_be_to_sock_v6() {
        let bytes = [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1];
        let expected_sock = SocketAddrV6::new(Ipv6Addr::new(1, 0, 0, 0, 0, 0, 0, 1),
            257, 0, 0);

        let result_sock = super::bytes_be_to_sock_v6(bytes);

        assert_eq!(expected_sock, result_sock);
    }
}<|endoftext|>