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

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

extern crate dirs;

extern crate xi_core_lib;
extern crate xi_rpc;

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

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

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

fn get_logfile_directory_name() -> String {
    match std::env::var("XI_LOG_DIR") {
        Ok(name) => name,
        Err(_) => String::from(XI_LOG_DIR),
    }
}

fn get_logfile_file_name() -> String {
    match std::env::var("XI_LOG_FILE") {
        Ok(name) => name,
        Err(_) => String::from(XI_LOG_FILE),
    }
}

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

fn path_for_log_file<P: AsRef<Path>>(filename: P) -> Result<PathBuf, io::Error> {
    let mut logging_directory = get_logging_directory(get_logfile_directory_name())?;
    // Create the logging directory
    fs::create_dir_all(&logging_directory)?;
    // Pushing the filename to the end
    logging_directory.push(filename.as_ref());
    Ok(logging_directory)
}

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

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

    let path_result = path_for_log_file(get_logfile_file_name());
    // If the logging_file_path returned successfully, add the logfile capability to fern
    if let Ok(logging_file_path) = &path_result {
        fern_dispatch = fern_dispatch.chain(fern::log_file(logging_file_path)?);
    }

    // Start fern
    fern_dispatch.apply()?;

    // Log details of the fern setup using fern/log
    match &path_result {
        Err(e) => {
            let message = "There was an issue getting the path for the log file";
            warn!("{}: {:?}, falling back to stderr.", message, e);
        }
        Ok(logging_file_path) => info!("Logging to the following file: {:?}", logging_file_path),
    }

    info!("Logging with fern is setup");
    Ok(())
}

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

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

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

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

    if let Err(e) = setup_logging() {
        eprintln!(
            "[ERROR] setup_logging returned error, logging disabled: {:?}",
            e
        );
    }

    match rpc_looper.mainloop(|| stdin.lock(), &mut state) {
        Ok(_) => (),
        Err(err) => error!("xi-core exited with error:\n{:?}", err),
    }
}
<commit_msg>Deleted the functions that retrive values from the env. Might add them back in eventually??<commit_after>// Copyright 2016 The xi-editor Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

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

extern crate dirs;

extern crate xi_core_lib;
extern crate xi_rpc;

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

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

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

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

fn path_for_log_file<P: AsRef<Path>>(filename: P) -> Result<PathBuf, io::Error> {
    let mut logging_directory = get_logging_directory(get_logfile_directory_name())?;
    // Create the logging directory
    fs::create_dir_all(&logging_directory)?;
    // Pushing the filename to the end
    logging_directory.push(filename.as_ref());
    Ok(logging_directory)
}

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

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

    let path_result = path_for_log_file(get_logfile_file_name());
    // If the logging_file_path returned successfully, add the logfile capability to fern
    if let Ok(logging_file_path) = &path_result {
        fern_dispatch = fern_dispatch.chain(fern::log_file(logging_file_path)?);
    }

    // Start fern
    fern_dispatch.apply()?;

    // Log details of the fern setup using fern/log
    match &path_result {
        Err(e) => {
            let message = "There was an issue getting the path for the log file";
            warn!("{}: {:?}, falling back to stderr.", message, e);
        }
        Ok(logging_file_path) => info!("Logging to the following file: {:?}", logging_file_path),
    }

    info!("Logging with fern is setup");
    Ok(())
}

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

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

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

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

    if let Err(e) = setup_logging() {
        eprintln!(
            "[ERROR] setup_logging returned error, logging disabled: {:?}",
            e
        );
    }

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


<commit_before>// based on define_flags by lexs
#[macro_escape];

macro_rules! define_flags (
    (
        $name:ident {
            $($flag:ident = $value:expr),+
        }
    ) => {
        define_flags!($name: u32 { $($flag = $value),+ })
    };

    (
        $name:ident: $T:ty {
            $($flag:ident $(= $v:expr)*),*
        }
    ) => {
        #[packed]
        pub struct $name($T);

        impl $name {
            /// Return the value.
            pub fn get(self) -> $T {
                match self { $name(x) => x }
            }

            /// Maps by applying a function to a contained value.
            pub fn map(self, f: |$T| -> $T) -> $name {
                match self { $name(x) => $name(f(x)) }
            }
        }

        impl core::ops::BitOr<$name, $name> for $name {
            #[inline(always)]
            fn bitor(&self, other: &$name) -> $name {
                match (self, other) {
                    (&$name(flags1), &$name(flags2)) => $name(flags1 | flags2)
                }
            }
        }

        impl core::ops::BitAnd<$name, bool> for $name {
            #[inline(always)]
            fn bitand(&self, other: &$name) -> bool {
                match (self, other) {
                    (&$name(flags1), &$name(flags2)) => flags1 & flags2 != 0
                }
            }
        }

        impl core::ops::Not<$name> for $name {
            #[inline(always)]
            fn not(&self) -> $name {
                match self {
                    &$name(flags) => $name(!flags)
                }
            }
        }

        define_flags_rec!($name, 1, $( $flag $(= $v)* ),+)
    };
)
macro_rules! define_flags_rec (
    // full list (original behavior)
    (
        $name:ident,
        $default:expr,
        $($flag:ident = $value:expr),*
    ) => (
        $( pub static $flag: $name = $name($value); )+
    );
    // ----------
    // only one default value
    (
        $name:ident,
        $default:expr,
        $flag:ident
    ) => (
        pub static $flag: $name = $name($default);
    );
    // only one value
    (
        $name:ident,
        $default:expr,
        $flag:ident = $value:expr
    ) => (
        pub static $flag: $name = $name($value);
    );
    // ----------
    // without value (default)
    (
        $name:ident,
        $default:expr,
        $flag:ident,
        $($f:ident $(= $v:expr)*),*
    ) => (
        pub static $flag: $name = $name($default);
        define_flags_rec!($name, $default << 1, $($f $(= $v)*),+)
    );
    // with value
    (
        $name:ident,
        $default:expr,
        $flag:ident = $value:expr,
        $($f:ident $(= $v:expr)*),*
    ) => (
        pub static $flag: $name = $name($value);
        define_flags_rec!($name, $value << 1, $( $f $(= $v)* ),+)
    );
)
<commit_msg>Update macros<commit_after>// based on define_flags by lexs
#[macro_escape];

macro_rules! define_flags (
    (
        $name:ident {
            $($flag:ident = $value:expr),+
        }
    ) => {
        define_flags!($name: uint { $($flag = $value),+ })
    };

    (
        $name:ident: $T:ty {
            $($flag:ident $(= $v:expr)*),*
        }
    ) => {
        #[allow(dead_code)]
        pub struct $name($T);

        #[allow(dead_code)]
        impl $name {
            /// Return the value.
            pub fn get(self) -> $T {
                match self { $name(x) => x }
            }

            /// Maps by applying a function to a contained value.
            pub fn map(self, f: |$T| -> $T) -> $name {
                match self { $name(x) => $name(f(x)) }
            }

            /// Returns `true` if no flags are currently stored.
            pub fn is_zero(&self) -> bool {
                match *self {
                    $name(0) => true,
                    _ => false
                }
            }

            pub fn zero() -> $name {
                $name(0)
            }
        }

        impl_ops!($name, $name)

        impl core::ops::Not<$name> for $name {
            #[inline(always)]
            fn not(&self) -> $name {
                match self {
                    &$name(flags) => $name(!flags)
                }
            }
        }

        define_flags_rec!($name, 1, $( $flag $(= $v)* ),+)
    };
)
macro_rules! define_flags_rec (
    // full list (original behavior)
    (
        $name:ident,
        $default:expr,
        $($flag:ident = $value:expr),*
    ) => (
        $( #[allow(dead_code)] pub static $flag: $name = $name($value); )+
    );
    // ----------
    // only one default value
    (
        $name:ident,
        $default:expr,
        $flag:ident
    ) => (
        #[allow(dead_code)]
        pub static $flag: $name = $name($default);
    );
    // only one value
    (
        $name:ident,
        $default:expr,
        $flag:ident = $value:expr
    ) => (
        #[allow(dead_code)]
        pub static $flag: $name = $name($value);
    );
    // ----------
    // without value (default)
    (
        $name:ident,
        $default:expr,
        $flag:ident,
        $($f:ident $(= $v:expr)*),*
    ) => (
        #[allow(dead_code)]
        pub static $flag: $name = $name($default);
        define_flags_rec!($name, $default << 1, $($f $(= $v)*),+)
    );
    // with value
    (
        $name:ident,
        $default:expr,
        $flag:ident = $value:expr,
        $($f:ident $(= $v:expr)*),*
    ) => (
        #[allow(dead_code)]
        pub static $flag: $name = $name($value);
        define_flags_rec!($name, $value << 1, $( $f $(= $v)* ),+)
    );
)

macro_rules! define_reg (
    (
        $Reg:ident, $flags:ident: $T:ty {
            $($flag:ident $(= $v:expr)*),*
        }
    ) => (
        define_flags!($flags: $T { $( $flag $(= $v)* ),* })

        pub struct $Reg;

        impl_ops!($Reg, $flags, $flags, $Reg::read(), $flags)
    )
)

macro_rules! impl_ops (
    ($T:ident, $RHS:ident) => (
        impl_ops!($T, $RHS, $T, *self, $T)
    );

    ($LHS:ident, $RHS:ident, $T:ident, $e:expr, $X:ident) => (
        impl core::ops::BitOr<$RHS, $T> for $LHS {
            #[inline(always)]
            fn bitor(&self, other: &$RHS) -> $T {
                match ($e, other) {
                    ($X(p), &$RHS(f)) => $T(p | f)
                }
            }
        }

        impl core::ops::BitAnd<$RHS, $T> for $LHS {
            #[inline(always)]
            fn bitand(&self, other: &$RHS) -> $T {
                match ($e, other) {
                    ($X(p), &$RHS(f)) => $T(p & f)
                }
            }
        }

        impl core::ops::Sub<$RHS, $T> for $LHS {
            #[inline(always)]
            fn sub(&self, other: &$RHS) -> $T {
                match ($e, other) {
                    ($X(flags1), &$RHS(flags2)) => $T(flags1 & !flags2)
                }
            }
        }
    )
)
<|endoftext|>


<commit_before>//! Db executor actor
use std::io;

use actix::prelude::*;
use diesel;
use diesel::prelude::*;
use diesel::result::Error;
use rand::{thread_rng, Rng, ThreadRng};

use crate::models;

pub struct DbExecutor {
    conn: PgConnection,
    rng: ThreadRng,
}

unsafe impl Send for DbExecutor {}

impl Actor for DbExecutor {
    type Context = SyncContext<Self>;
}

impl DbExecutor {
    pub fn new(db_url: &str) -> DbExecutor {
        DbExecutor {
            conn: PgConnection::establish(db_url)
                .expect(&format!("Error connecting to {}", db_url)),
            rng: thread_rng(),
        }
    }
}

pub struct RandomWorld;

impl Message for RandomWorld {
    type Result = io::Result<models::World>;
}

impl Handler<RandomWorld> for DbExecutor {
    type Result = io::Result<models::World>;

    fn handle(&mut self, _: RandomWorld, _: &mut Self::Context) -> Self::Result {
        use crate::schema::world::dsl::*;

        let random_id = self.rng.gen_range(1, 10_001);
        match world
            .filter(id.eq(random_id))
            .load::<models::World>(&self.conn)
        {
            Ok(mut items) => Ok(items.pop().unwrap()),
            Err(_) => Err(io::Error::new(io::ErrorKind::Other, "Database error")),
        }
    }
}

pub struct RandomWorlds(pub u16);

impl Message for RandomWorlds {
    type Result = io::Result<Vec<models::World>>;
}

impl Handler<RandomWorlds> for DbExecutor {
    type Result = io::Result<Vec<models::World>>;

    fn handle(&mut self, msg: RandomWorlds, _: &mut Self::Context) -> Self::Result {
        use crate::schema::world::dsl::*;

        let mut worlds = Vec::with_capacity(msg.0 as usize);
        for _ in 0..msg.0 {
            let w_id = self.rng.gen_range(1, 10_001);
            let w = match world.filter(id.eq(w_id)).load::<models::World>(&self.conn) {
                Ok(mut items) => items.pop().unwrap(),
                Err(_) => {
                    return Err(io::Error::new(io::ErrorKind::Other, "Database error"));
                }
            };
            worlds.push(w)
        }
        Ok(worlds)
    }
}

pub struct UpdateWorld(pub u16);

impl Message for UpdateWorld {
    type Result = io::Result<Vec<models::World>>;
}

impl Handler<UpdateWorld> for DbExecutor {
    type Result = io::Result<Vec<models::World>>;

    fn handle(&mut self, msg: UpdateWorld, _: &mut Self::Context) -> Self::Result {
        use crate::schema::world::dsl::*;

        let mut worlds = Vec::with_capacity(msg.0 as usize);
        for _ in 0..msg.0 {
            let w_id = self.rng.gen_range::<i32>(1, 10_001);
            let mut w = match world.filter(id.eq(w_id)).load::<models::World>(&self.conn)
            {
                Ok(mut items) => items.pop().unwrap(),
                Err(_) => {
                    return Err(io::Error::new(io::ErrorKind::Other, "Database error"));
                }
            };
            w.randomnumber = self.rng.gen_range(1, 10_001);
            worlds.push(w);
        }
        worlds.sort_by_key(|w| w.id);

        let _ = self.conn.transaction::<(), Error, _>(|| {
            for w in &worlds {
                let _ = diesel::update(world)
                    .filter(id.eq(w.id))
                    .set(randomnumber.eq(w.randomnumber))
                    .execute(&self.conn);
            }
            Ok(())
        });

        Ok(worlds)
    }
}

pub struct TellFortune;

impl Message for TellFortune {
    type Result = io::Result<Vec<models::Fortune>>;
}

impl Handler<TellFortune> for DbExecutor {
    type Result = io::Result<Vec<models::Fortune>>;

    fn handle(&mut self, _: TellFortune, _: &mut Self::Context) -> Self::Result {
        use crate::schema::fortune::dsl::*;

        match fortune.load::<models::Fortune>(&self.conn) {
            Ok(mut items) => {
                items.push(models::Fortune {
                    id: 0,
                    message: "Additional fortune added at request time.".to_string(),
                });
                items.sort_by(|it, next| it.message.cmp(&next.message));
                Ok(items)
            }
            Err(e) => Err(io::Error::new(io::ErrorKind::Other, e)),
        }
    }
}
<commit_msg>Remove unnecessary `unsafe impl Send` from actix (#5290)<commit_after>//! Db executor actor
use std::io;

use actix::prelude::*;
use diesel;
use diesel::prelude::*;
use diesel::result::Error;
use rand::{thread_rng, Rng, ThreadRng};

use crate::models;

pub struct DbExecutor {
    conn: PgConnection,
    rng: ThreadRng,
}

impl Actor for DbExecutor {
    type Context = SyncContext<Self>;
}

impl DbExecutor {
    pub fn new(db_url: &str) -> DbExecutor {
        DbExecutor {
            conn: PgConnection::establish(db_url)
                .expect(&format!("Error connecting to {}", db_url)),
            rng: thread_rng(),
        }
    }
}

pub struct RandomWorld;

impl Message for RandomWorld {
    type Result = io::Result<models::World>;
}

impl Handler<RandomWorld> for DbExecutor {
    type Result = io::Result<models::World>;

    fn handle(&mut self, _: RandomWorld, _: &mut Self::Context) -> Self::Result {
        use crate::schema::world::dsl::*;

        let random_id = self.rng.gen_range(1, 10_001);
        match world
            .filter(id.eq(random_id))
            .load::<models::World>(&self.conn)
        {
            Ok(mut items) => Ok(items.pop().unwrap()),
            Err(_) => Err(io::Error::new(io::ErrorKind::Other, "Database error")),
        }
    }
}

pub struct RandomWorlds(pub u16);

impl Message for RandomWorlds {
    type Result = io::Result<Vec<models::World>>;
}

impl Handler<RandomWorlds> for DbExecutor {
    type Result = io::Result<Vec<models::World>>;

    fn handle(&mut self, msg: RandomWorlds, _: &mut Self::Context) -> Self::Result {
        use crate::schema::world::dsl::*;

        let mut worlds = Vec::with_capacity(msg.0 as usize);
        for _ in 0..msg.0 {
            let w_id = self.rng.gen_range(1, 10_001);
            let w = match world.filter(id.eq(w_id)).load::<models::World>(&self.conn) {
                Ok(mut items) => items.pop().unwrap(),
                Err(_) => {
                    return Err(io::Error::new(io::ErrorKind::Other, "Database error"));
                }
            };
            worlds.push(w)
        }
        Ok(worlds)
    }
}

pub struct UpdateWorld(pub u16);

impl Message for UpdateWorld {
    type Result = io::Result<Vec<models::World>>;
}

impl Handler<UpdateWorld> for DbExecutor {
    type Result = io::Result<Vec<models::World>>;

    fn handle(&mut self, msg: UpdateWorld, _: &mut Self::Context) -> Self::Result {
        use crate::schema::world::dsl::*;

        let mut worlds = Vec::with_capacity(msg.0 as usize);
        for _ in 0..msg.0 {
            let w_id = self.rng.gen_range::<i32>(1, 10_001);
            let mut w = match world.filter(id.eq(w_id)).load::<models::World>(&self.conn)
            {
                Ok(mut items) => items.pop().unwrap(),
                Err(_) => {
                    return Err(io::Error::new(io::ErrorKind::Other, "Database error"));
                }
            };
            w.randomnumber = self.rng.gen_range(1, 10_001);
            worlds.push(w);
        }
        worlds.sort_by_key(|w| w.id);

        let _ = self.conn.transaction::<(), Error, _>(|| {
            for w in &worlds {
                let _ = diesel::update(world)
                    .filter(id.eq(w.id))
                    .set(randomnumber.eq(w.randomnumber))
                    .execute(&self.conn);
            }
            Ok(())
        });

        Ok(worlds)
    }
}

pub struct TellFortune;

impl Message for TellFortune {
    type Result = io::Result<Vec<models::Fortune>>;
}

impl Handler<TellFortune> for DbExecutor {
    type Result = io::Result<Vec<models::Fortune>>;

    fn handle(&mut self, _: TellFortune, _: &mut Self::Context) -> Self::Result {
        use crate::schema::fortune::dsl::*;

        match fortune.load::<models::Fortune>(&self.conn) {
            Ok(mut items) => {
                items.push(models::Fortune {
                    id: 0,
                    message: "Additional fortune added at request time.".to_string(),
                });
                items.sort_by(|it, next| it.message.cmp(&next.message));
                Ok(items)
            }
            Err(e) => Err(io::Error::new(io::ErrorKind::Other, e)),
        }
    }
}
<|endoftext|>


<commit_before>//! AccReader is like a BufReader, but supports partial consumption
//! import new data with `fill_buf`, get the current buffer with
//! `current_slice`, and indicate with `consume` how many bytes
//! were used

use std::io;
use std::io::{BufRead, Read, Result, Seek, SeekFrom};
use std::iter::Iterator;
use std::cmp;
use std::iter;
use buffer::Buffered;
// use std::fmt;
// use std::str;

pub struct AccReader<R> {
    inner: R,
    buf: Vec<u8>,
    pos: usize,
    end: usize,
    // position in the stream of the buffer's beginning
    index: usize,
}

impl<R: Read + Seek> AccReader<R> {
    pub fn new(inner: R) -> AccReader<R> {
        AccReader::with_capacity(10, inner)
    }

    pub fn with_capacity(cap: usize, inner: R) -> AccReader<R> {
        let mut buf = Vec::with_capacity(cap);
        buf.extend(iter::repeat(0).take(cap));
        AccReader {
            inner: inner,
            buf: buf,
            pos: 0,
            end: 0,
            index: 0,
        }
    }

    /// Gets a reference to the underlying reader.
    pub fn get_ref(&self) -> &R {
        &self.inner
    }

    /// Gets a mutable reference to the underlying reader.
    pub fn get_mut(&mut self) -> &mut R {
        &mut self.inner
    }

    /// Unwraps this `AccReader`, returning the underlying reader.
    ///
    /// Note that any leftover data in the internal buffer is lost.
    pub fn into_inner(self) -> R {
        self.inner
    }

    pub fn reset_buffer_position(&mut self) {
        // println!("resetting buffer at pos: {} capacity: {}", self.pos, self.end);
        if self.end - self.pos > 0 {
            for i in 0..(self.end - self.pos) {
                // println!("buf[{}] = buf[{}]", i, self.pos + i);
                self.buf[i] = self.buf[self.pos + i];
            }
        }
        self.end = self.end - self.pos;
        self.pos = 0;
    }

    pub fn current_slice(&self) -> &[u8] {
        // println!("current slice pos: {}, cap: {}", self.pos, self.end);
        &self.buf[self.pos..self.end]
    }

    pub fn capacity(&self) -> usize {
        self.end - self.pos
    }
}

impl<R: Read + Seek> Buffered for AccReader<R> {
    fn data(&self) -> &[u8] {
        &self.buf[self.pos..self.end]
    }
    fn grow(&mut self, len: usize) {
        let l = self.buf.len() + len;
        self.buf.resize(l, 0);
    }
}

impl<R: Read + Seek> Read for AccReader<R> {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        // println!("read pos: {} cap: {} buflen: {}", self.pos, self.end, buf.len());
        if buf.len() < self.end - self.pos {
            match (&self.buf[self.pos..(self.pos + buf.len())]).read(buf) {
                Ok(len) => {
                    self.consume(len);
                    Ok(len)
                }
                Err(e) => Err(e),
            }
        } else {
            // If we don't have any buffered data and we're doing a massive read
            // (larger than our internal buffer), bypass our internal buffer
            // entirely.
            if buf.len() > self.buf.len() {
                match (&self.buf[self.pos..self.end]).read(buf) {
                    Ok(len) => {
                        self.consume(len);
                        self.inner.read(&mut buf[self.end..])
                    }
                    Err(e) => Err(e),
                }
            } else {
                let nread = {
                    let mut rem = try!(self.fill_buf());
                    try!(rem.read(buf))
                };
                self.consume(nread);
                Ok(nread)
            }
        }
    }
}

impl<R: Read + Seek> BufRead for AccReader<R> {
    fn fill_buf(&mut self) -> io::Result<&[u8]> {
        // println!("fillbuf current: {:?}", str::from_utf8(&self.buf[self.pos..self.end]).unwrap());
        if self.pos != 0 || self.end != self.buf.len() {
            self.reset_buffer_position();
            // println!("buffer reset ended");
            let read = try!(self.inner.read(&mut self.buf[self.end..]));
            if read == 0 {
                return Err(io::Error::new(io::ErrorKind::UnexpectedEof, "EOF"));
            }
            self.end += read;
            // println!("new pos: {} and cap: {} -> current: {:?}", self.pos, self.end, str::from_utf8(&self.buf[self.pos..self.end]).unwrap());
        }
        Ok(&self.buf[self.pos..self.end])
    }

    fn consume(&mut self, amt: usize) {
        // println!("consumed {} bytes", amt);
        self.pos = cmp::min(self.pos + amt, self.end);
        self.index += amt;
    }
}

impl<R: Read + Seek> Seek for AccReader<R> {
    fn seek(&mut self, pos: SeekFrom) -> Result<u64> {
        match pos {
            SeekFrom::Start(sz) => {
                let mv = sz as usize;
                if mv >= self.index && mv < self.index + self.end - self.pos {
                    self.pos += mv - self.index;
                    self.index = mv;

                    return Ok(mv as u64);
                }
            }
            SeekFrom::End(_) => {}
            SeekFrom::Current(sz) => {
                if sz >= 0 && sz as usize <= self.end - self.pos {
                    self.index = sz as usize;
                    self.pos += sz as usize;
                    return Ok(sz as u64);
                }
            }
        };

        match self.inner.seek(pos) {
            Ok(sz) => {
                self.index = sz as usize;
                self.pos = 0;
                self.end = 0;
                try!(self.fill_buf());
                Ok(sz)
            }
            Err(e) => Err(e),
        }
    }
}
// impl<R> fmt::Debug for AccReader<R> where R: fmt::Debug {
// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
// fmt.debug_struct("AccReader")
// .field("reader", &self.inner)
// .field("buffer", &format_args!("{}/{}", self.end - self.pos, self.buf.len()))
// .finish()
// }
// }

#[cfg(test)]
mod tests {
    use super::*;
    use std::io::{Cursor, BufRead};
    use buffer::Buffered;

    #[test]
    fn acc_reader_test() {
        let buf = b"AAAA\nAAAB\nAAACAAADAAAEAAAF\ndabcdEEEE";
        let c = Cursor::new(&buf[..]);

        let acc = AccReader::with_capacity(20, c);

        // for l in acc.lines() {
        // println!("l: {:?}", l);
        // }
        // assert!(false);
        assert_eq!(4, acc.lines().count());
    }

    #[test]
    fn grow() {
        let buf = b"abcdefghilmnopqrst";
        let c = Cursor::new(&buf[..]);

        let mut acc = AccReader::with_capacity(4, c);
        acc.fill_buf().unwrap();
        acc.consume(2);
        acc.grow(4);
        assert_eq!(b"cd", acc.data());
        acc.fill_buf().unwrap();
        assert_eq!(b"cdefghil", acc.data());
    }
}
<commit_msg>format: Use the standard io::Error for eof<commit_after>//! AccReader is like a BufReader, but supports partial consumption
//! import new data with `fill_buf`, get the current buffer with
//! `current_slice`, and indicate with `consume` how many bytes
//! were used

use std::io;
use std::io::{BufRead, Read, Result, Seek, SeekFrom};
use std::iter::Iterator;
use std::cmp;
use std::iter;
use buffer::Buffered;
// use std::fmt;
// use std::str;

pub struct AccReader<R> {
    inner: R,
    buf: Vec<u8>,
    pos: usize,
    end: usize,
    // position in the stream of the buffer's beginning
    index: usize,
}

impl<R: Read + Seek> AccReader<R> {
    pub fn new(inner: R) -> AccReader<R> {
        AccReader::with_capacity(10, inner)
    }

    pub fn with_capacity(cap: usize, inner: R) -> AccReader<R> {
        let mut buf = Vec::with_capacity(cap);
        buf.extend(iter::repeat(0).take(cap));
        AccReader {
            inner: inner,
            buf: buf,
            pos: 0,
            end: 0,
            index: 0,
        }
    }

    /// Gets a reference to the underlying reader.
    pub fn get_ref(&self) -> &R {
        &self.inner
    }

    /// Gets a mutable reference to the underlying reader.
    pub fn get_mut(&mut self) -> &mut R {
        &mut self.inner
    }

    /// Unwraps this `AccReader`, returning the underlying reader.
    ///
    /// Note that any leftover data in the internal buffer is lost.
    pub fn into_inner(self) -> R {
        self.inner
    }

    pub fn reset_buffer_position(&mut self) {
        // println!("resetting buffer at pos: {} capacity: {}", self.pos, self.end);
        if self.end - self.pos > 0 {
            for i in 0..(self.end - self.pos) {
                // println!("buf[{}] = buf[{}]", i, self.pos + i);
                self.buf[i] = self.buf[self.pos + i];
            }
        }
        self.end = self.end - self.pos;
        self.pos = 0;
    }

    pub fn current_slice(&self) -> &[u8] {
        // println!("current slice pos: {}, cap: {}", self.pos, self.end);
        &self.buf[self.pos..self.end]
    }

    pub fn capacity(&self) -> usize {
        self.end - self.pos
    }
}

impl<R: Read + Seek> Buffered for AccReader<R> {
    fn data(&self) -> &[u8] {
        &self.buf[self.pos..self.end]
    }
    fn grow(&mut self, len: usize) {
        let l = self.buf.len() + len;
        self.buf.resize(l, 0);
    }
}

impl<R: Read + Seek> Read for AccReader<R> {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        // println!("read pos: {} cap: {} buflen: {}", self.pos, self.end, buf.len());
        if buf.len() < self.end - self.pos {
            match (&self.buf[self.pos..(self.pos + buf.len())]).read(buf) {
                Ok(len) => {
                    self.consume(len);
                    Ok(len)
                }
                Err(e) => Err(e),
            }
        } else {
            // If we don't have any buffered data and we're doing a massive read
            // (larger than our internal buffer), bypass our internal buffer
            // entirely.
            if buf.len() > self.buf.len() {
                match (&self.buf[self.pos..self.end]).read(buf) {
                    Ok(len) => {
                        self.consume(len);
                        self.inner.read(&mut buf[self.end..])
                    }
                    Err(e) => Err(e),
                }
            } else {
                let nread = {
                    let mut rem = try!(self.fill_buf());
                    try!(rem.read(buf))
                };
                self.consume(nread);
                Ok(nread)
            }
        }
    }
}

impl<R: Read + Seek> BufRead for AccReader<R> {
    fn fill_buf(&mut self) -> io::Result<&[u8]> {
        // println!("fillbuf current: {:?}", str::from_utf8(&self.buf[self.pos..self.end]).unwrap());
        if self.pos != 0 || self.end != self.buf.len() {
            self.reset_buffer_position();
            // println!("buffer reset ended");
            let read = try!(self.inner.read(&mut self.buf[self.end..]));
            if read == 0 {
                return Err(io::ErrorKind::UnexpectedEof.into());
            }
            self.end += read;
            // println!("new pos: {} and cap: {} -> current: {:?}", self.pos, self.end, str::from_utf8(&self.buf[self.pos..self.end]).unwrap());
        }
        Ok(&self.buf[self.pos..self.end])
    }

    fn consume(&mut self, amt: usize) {
        // println!("consumed {} bytes", amt);
        self.pos = cmp::min(self.pos + amt, self.end);
        self.index += amt;
    }
}

impl<R: Read + Seek> Seek for AccReader<R> {
    fn seek(&mut self, pos: SeekFrom) -> Result<u64> {
        match pos {
            SeekFrom::Start(sz) => {
                let mv = sz as usize;
                if mv >= self.index && mv < self.index + self.end - self.pos {
                    self.pos += mv - self.index;
                    self.index = mv;

                    return Ok(mv as u64);
                }
            }
            SeekFrom::End(_) => {}
            SeekFrom::Current(sz) => {
                if sz >= 0 && sz as usize <= self.end - self.pos {
                    self.index = sz as usize;
                    self.pos += sz as usize;
                    return Ok(sz as u64);
                }
            }
        };

        match self.inner.seek(pos) {
            Ok(sz) => {
                self.index = sz as usize;
                self.pos = 0;
                self.end = 0;
                try!(self.fill_buf());
                Ok(sz)
            }
            Err(e) => Err(e),
        }
    }
}
// impl<R> fmt::Debug for AccReader<R> where R: fmt::Debug {
// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
// fmt.debug_struct("AccReader")
// .field("reader", &self.inner)
// .field("buffer", &format_args!("{}/{}", self.end - self.pos, self.buf.len()))
// .finish()
// }
// }

#[cfg(test)]
mod tests {
    use super::*;
    use std::io::{Cursor, BufRead};
    use buffer::Buffered;

    #[test]
    fn acc_reader_test() {
        let buf = b"AAAA\nAAAB\nAAACAAADAAAEAAAF\ndabcdEEEE";
        let c = Cursor::new(&buf[..]);

        let acc = AccReader::with_capacity(20, c);

        // for l in acc.lines() {
        // println!("l: {:?}", l);
        // }
        // assert!(false);
        assert_eq!(4, acc.lines().count());
    }

    #[test]
    fn grow() {
        let buf = b"abcdefghilmnopqrst";
        let c = Cursor::new(&buf[..]);

        let mut acc = AccReader::with_capacity(4, c);
        acc.fill_buf().unwrap();
        acc.consume(2);
        acc.grow(4);
        assert_eq!(b"cd", acc.data());
        acc.fill_buf().unwrap();
        assert_eq!(b"cdefghil", acc.data());
    }
}
<|endoftext|>


<commit_before>use cast::transmute;
use cmp::Eq;
use num::from_int;
use ptr::to_unsafe_ptr;
use vec::raw::buf_as_slice;
use std::cmp::FuzzyEq;

use funs::exp::Exp;
use math::*;
use matrix::{Mat3, Mat4};
use ncast::*;
use vector::Vec3;

// These quaternion type aliases are not actually specified in the GLSL spec
// but they follow the same nomenclature

pub type quat4  = Quat<f32>;         /// a single-precision floating-point quaternion
pub type dquat4 = Quat<f64>;         /// a double-precision floating-point quaternion

//
//  Quaternion
//
pub trait Quaternion<T> {
    pure fn dim() -> uint;

    pure fn mul_t(value: T) -> self;
    pure fn div_t(value: T) -> self;

    // pure fn mul_v(other: &Vec3) -> Vec3;

    pure fn add_q(other: &self) -> self;
    pure fn sub_q(other: &self) -> self;
    pure fn mul_q(other: &self) -> self;

    pure fn dot(other: &self) -> T;

    pure fn conjugate() -> self;
    pure fn inverse() -> self;
    pure fn length2() -> T;
    pure fn length() -> T;
    pure fn normalize() -> self;

    pure fn to_Mat3() -> Mat3<T>;
    pure fn to_Mat4() -> Mat4<T>;
}

pub trait ToQuat<T> {
    pure fn to_Quat() -> Quat<T>;
}

pub struct Quat<T> { w: T, x: T, y: T, z: T }

pub mod Quat {

    #[inline(always)]
    pub pure fn new<T>(w: T, x: T, y: T, z: T) -> Quat<T> {
        Quat { w: move w, x: move x, y: move y, z: move z }
    }

    #[inline(always)]
    pub pure fn from_sv<T:Copy>(s: T, v: Vec3<T>) -> Quat<T> {
        Quat::new(s, v.x, v.y, v.z)
    }

    #[inline(always)]
    pub pure fn zero<T:Copy NumCast>() -> Quat<T> {
        let _0 = cast(0);
        Quat::new(_0, _0, _0, _0)
    }

    #[inline(always)]
    pub pure fn identity<T:Copy NumCast>() -> Quat<T> {
        let _0 = cast(0);
        Quat::new(cast(1), _0, _0, _0)
    }
}

pub impl<T:Copy Num NumCast Exp FuzzyEq> Quat<T>: Quaternion<T> {
    #[inline(always)]
    pure fn dim() -> uint { 4 }

    #[inline(always)]
    pure fn mul_t(value: T) -> Quat<T> {
        Quat::new(self[0] * value,
                  self[1] * value,
                  self[2] * value,
                  self[3] * value)
    }

    #[inline(always)]
    pure fn div_t(value: T) -> Quat<T> {
        Quat::new(self[0] / value,
                  self[1] / value,
                  self[2] / value,
                  self[3] / value)
    }

    #[inline(always)]
    pure fn add_q(other: &Quat<T>) -> Quat<T> {
        Quat::new(self[0] + other[0],
                  self[1] + other[1],
                  self[2] + other[2],
                  self[3] + other[3])
    }

    #[inline(always)]
    pure fn sub_q(other: &Quat<T>) -> Quat<T> {
        Quat::new(self[0] - other[0],
                  self[1] - other[1],
                  self[2] - other[2],
                  self[3] - other[3])
    }

    #[inline(always)]
    pure fn mul_q(other: &Quat<T>) -> Quat<T> {
        Quat::new(self.w * other.w - self.x * other.x - self.y * other.y - self.z * other.z,
                  self.w * other.x + self.x * other.w + self.y * other.z - self.z * other.y,
                  self.w * other.y + self.y * other.w + self.z * other.x - self.x * other.z,
                  self.w * other.z + self.z * other.w + self.x * other.y - self.y * other.x)
    }

    #[inline(always)]
    pure fn dot(other: &Quat<T>) -> T {
        self.w * other.w +
        self.x * other.x +
        self.y * other.y +
        self.z * other.z
    }

    #[inline(always)]
    pure fn conjugate() -> Quat<T> {
        Quat::new(self.w, -self.x, -self.y, -self.z)
    }

    #[inline(always)]
    pure fn inverse() -> Quat<T> {
        let mut n: T = from_int(1);
        n /= self.length2();
        self.conjugate().mul_t(n)
    }

    #[inline(always)]
    pure fn length2() -> T {
        self.w * self.w +
        self.x * self.x +
        self.y * self.y +
        self.z * self.z
    }

    #[inline(always)]
    pure fn length() -> T {
        self.length2().sqrt()
    }

    #[inline(always)]
    pure fn normalize() -> Quat<T> {
        let mut n: T = cast(1);
        n /= self.length();
        return self.mul_t(n);
    }

    #[inline(always)]
    pure fn to_Mat3() -> Mat3<T> {
        let x2 = self.x + self.x;
        let y2 = self.y + self.y;
        let z2 = self.z + self.z;

        let xx2 = x2 * self.x;
        let xy2 = x2 * self.y;
        let xz2 = x2 * self.z;

        let yy2 = y2 * self.y;
        let yz2 = y2 * self.z;
        let zz2 = z2 * self.z;

        let wy2 = y2 * self.w;
        let wz2 = z2 * self.w;
        let wx2 = x2 * self.w;

        let _1: T = from_int(1);

        Mat3::new(_1 - yy2 - zz2,      xy2 - wz2,      xz2 + wy2,
                       xy2 + wz2, _1 - xx2 - zz2,      yz2 - wx2,
                       xz2 - wy2,      yz2 + wx2, _1 - xx2 - yy2)
    }

    #[inline(always)]
    pure fn to_Mat4() -> Mat4<T> {
        self.to_Mat3().to_Mat4()
    }
}

pub impl<T:Copy> Quat<T>: Index<uint, T> {
    #[inline(always)]
    pure fn index(i: uint) -> T {
        unsafe { do buf_as_slice(
            transmute::<*Quat<T>, *T>(
                to_unsafe_ptr(&self)), 4) |slice| { slice[i] }
        }
    }
}

pub impl<T:Copy Neg<T>> Quat<T>: Neg<Quat<T>> {
    #[inline(always)]
    pure fn neg() -> Quat<T> {
        Quat::new(-self[0], -self[1], -self[2], -self[3])
    }
}

// TODO: make work for T:Integer
pub impl<T:Copy FuzzyEq> Quat<T>: Eq {
    #[inline(always)]
    pure fn eq(other: &Quat<T>) -> bool {
        self.fuzzy_eq(other)
    }

    #[inline(always)]
    pure fn ne(other: &Quat<T>) -> bool {
        !(self == *other)
    }
}

pub impl<T:Copy Eq> Quat<T>: ExactEq {
    #[inline(always)]
    pure fn exact_eq(other: &Quat<T>) -> bool {
        self[0] == other[0] &&
        self[1] == other[1] &&
        self[2] == other[2] &&
        self[3] == other[3]
    }
}

pub impl<T:Copy FuzzyEq> Quat<T>: FuzzyEq {
    #[inline(always)]
    pure fn fuzzy_eq(other: &Quat<T>) -> bool {
        self[0].fuzzy_eq(&other[0]) &&
        self[1].fuzzy_eq(&other[1]) &&
        self[2].fuzzy_eq(&other[2]) &&
        self[3].fuzzy_eq(&other[3])
    }
}

pub impl<T:Copy> Quat<T>: ToPtr<T> {
    #[inline(always)]
    pure fn to_ptr() -> *T {
        to_unsafe_ptr(&self[0])
    }
}<commit_msg>Implement nlerp and slerp methods<commit_after>use cast::transmute;
use cmp::Eq;
use num::from_int;
use ptr::to_unsafe_ptr;
use vec::raw::buf_as_slice;
use std::cmp::FuzzyEq;

use funs::exp::*;
use funs::trig::*;
use funs::common::*;
use math::*;
use matrix::{Mat3, Mat4};
use ncast::*;
use vector::Vec3;

// These quaternion type aliases are not actually specified in the GLSL spec
// but they follow the same nomenclature

pub type quat4  = Quat<f32>;         /// a single-precision floating-point quaternion
pub type dquat4 = Quat<f64>;         /// a double-precision floating-point quaternion

//
//  Quaternion
//
pub trait Quaternion<T> {
    pure fn dim() -> uint;

    pure fn mul_t(value: T) -> self;
    pure fn div_t(value: T) -> self;

    // pure fn mul_v(other: &Vec3) -> Vec3;

    pure fn add_q(other: &self) -> self;
    pure fn sub_q(other: &self) -> self;
    pure fn mul_q(other: &self) -> self;

    pure fn dot(other: &self) -> T;

    pure fn conjugate() -> self;
    pure fn inverse() -> self;
    pure fn length2() -> T;
    pure fn length() -> T;
    pure fn normalize() -> self;

    pure fn nlerp(other: &self, amount: T) -> self;
    pure fn slerp(other: &self, amount: T) -> self;

    pure fn to_Mat3() -> Mat3<T>;
    pure fn to_Mat4() -> Mat4<T>;
}

pub trait ToQuat<T> {
    pure fn to_Quat() -> Quat<T>;
}

pub struct Quat<T> { w: T, x: T, y: T, z: T }

pub mod Quat {

    #[inline(always)]
    pub pure fn new<T>(w: T, x: T, y: T, z: T) -> Quat<T> {
        Quat { w: move w, x: move x, y: move y, z: move z }
    }

    #[inline(always)]
    pub pure fn from_sv<T:Copy>(s: T, v: Vec3<T>) -> Quat<T> {
        Quat::new(s, v.x, v.y, v.z)
    }

    #[inline(always)]
    pub pure fn zero<T:Copy NumCast>() -> Quat<T> {
        let _0 = cast(0);
        Quat::new(_0, _0, _0, _0)
    }

    #[inline(always)]
    pub pure fn identity<T:Copy NumCast>() -> Quat<T> {
        let _0 = cast(0);
        Quat::new(cast(1), _0, _0, _0)
    }
}

pub impl<T:Copy Num NumCast Trig Exp Extent Ord FuzzyEq> Quat<T>: Quaternion<T> {
    #[inline(always)]
    pure fn dim() -> uint { 4 }

    #[inline(always)]
    pure fn mul_t(value: T) -> Quat<T> {
        Quat::new(self[0] * value,
                  self[1] * value,
                  self[2] * value,
                  self[3] * value)
    }

    #[inline(always)]
    pure fn div_t(value: T) -> Quat<T> {
        Quat::new(self[0] / value,
                  self[1] / value,
                  self[2] / value,
                  self[3] / value)
    }

    #[inline(always)]
    pure fn add_q(other: &Quat<T>) -> Quat<T> {
        Quat::new(self[0] + other[0],
                  self[1] + other[1],
                  self[2] + other[2],
                  self[3] + other[3])
    }

    #[inline(always)]
    pure fn sub_q(other: &Quat<T>) -> Quat<T> {
        Quat::new(self[0] - other[0],
                  self[1] - other[1],
                  self[2] - other[2],
                  self[3] - other[3])
    }

    #[inline(always)]
    pure fn mul_q(other: &Quat<T>) -> Quat<T> {
        Quat::new(self.w * other.w - self.x * other.x - self.y * other.y - self.z * other.z,
                  self.w * other.x + self.x * other.w + self.y * other.z - self.z * other.y,
                  self.w * other.y + self.y * other.w + self.z * other.x - self.x * other.z,
                  self.w * other.z + self.z * other.w + self.x * other.y - self.y * other.x)
    }

    #[inline(always)]
    pure fn dot(other: &Quat<T>) -> T {
        self.w * other.w +
        self.x * other.x +
        self.y * other.y +
        self.z * other.z
    }

    #[inline(always)]
    pure fn conjugate() -> Quat<T> {
        Quat::new(self.w, -self.x, -self.y, -self.z)
    }

    #[inline(always)]
    pure fn inverse() -> Quat<T> {
        let mut n: T = from_int(1);
        n /= self.length2();
        self.conjugate().mul_t(n)
    }

    #[inline(always)]
    pure fn length2() -> T {
        self.w * self.w +
        self.x * self.x +
        self.y * self.y +
        self.z * self.z
    }

    #[inline(always)]
    pure fn length() -> T {
        self.length2().sqrt()
    }

    #[inline(always)]
    pure fn normalize() -> Quat<T> {
        let mut n: T = cast(1);
        n /= self.length();
        return self.mul_t(n);
    }

    #[inline(always)]
    pure fn nlerp(other: &Quat<T>, amount: T) -> Quat<T> {
        let _1: T = cast(1);
        self.mul_t(_1 - amount).add_q(&other.mul_t(amount)).normalize()
    }

    /**
     * Spherical Linear Intoperlation
     *
     * Both quaternions should be normalized first, or else strange things will
     * will happen...
     *
     * Note: The `acos` used in `slerp` is an expensive operation, so unless your
     * quarternions a far away from each other it's generally more advisable to
     * use nlerp when you know your rotations are going to be small.
     *
     * See *[Understanding Slerp, Then Not Using It]
     * (http://number-none.com/product/Understanding%20Slerp,%20Then%20Not%20Using%20It/)*
     * for more information. The [Arcsynthesis OpenGL tutorial]
     * (http://www.arcsynthesis.org/gltut/Positioning/Tut08%20Interpolation.html)
     * also provides a good explanation.
     */
    #[inline(always)]
    pure fn slerp(other: &Quat<T>, amount: T) -> Quat<T> {
        let dot: T = cast(self.dot(other));

        // if quaternions are close together use `nlerp`
        let dot_threshold = cast(0.9995);
        if dot > dot_threshold { return self.nlerp(other, amount) }

        let robust_dot = dot.clamp(&-cast(1), &cast(1));    // stay within the domain of acos()
        let theta_0 = acos(&robust_dot);                    // the angle between the quaternions
        let theta = theta_0 * amount;                       // the fraction of theta specified by `amount`

        let q = other.sub_q(&self.mul_t(robust_dot))
                     .normalize();

        self.mul_t(cos(&theta)).add_q(&q.mul_t(sin(&theta)))
    }

    #[inline(always)]
    pure fn to_Mat3() -> Mat3<T> {
        let x2 = self.x + self.x;
        let y2 = self.y + self.y;
        let z2 = self.z + self.z;

        let xx2 = x2 * self.x;
        let xy2 = x2 * self.y;
        let xz2 = x2 * self.z;

        let yy2 = y2 * self.y;
        let yz2 = y2 * self.z;
        let zz2 = z2 * self.z;

        let wy2 = y2 * self.w;
        let wz2 = z2 * self.w;
        let wx2 = x2 * self.w;

        let _1: T = from_int(1);

        Mat3::new(_1 - yy2 - zz2,      xy2 - wz2,      xz2 + wy2,
                       xy2 + wz2, _1 - xx2 - zz2,      yz2 - wx2,
                       xz2 - wy2,      yz2 + wx2, _1 - xx2 - yy2)
    }

    #[inline(always)]
    pure fn to_Mat4() -> Mat4<T> {
        self.to_Mat3().to_Mat4()
    }
}

pub impl<T:Copy> Quat<T>: Index<uint, T> {
    #[inline(always)]
    pure fn index(i: uint) -> T {
        unsafe { do buf_as_slice(
            transmute::<*Quat<T>, *T>(
                to_unsafe_ptr(&self)), 4) |slice| { slice[i] }
        }
    }
}

pub impl<T:Copy Neg<T>> Quat<T>: Neg<Quat<T>> {
    #[inline(always)]
    pure fn neg() -> Quat<T> {
        Quat::new(-self[0], -self[1], -self[2], -self[3])
    }
}

// TODO: make work for T:Integer
pub impl<T:Copy FuzzyEq> Quat<T>: Eq {
    #[inline(always)]
    pure fn eq(other: &Quat<T>) -> bool {
        self.fuzzy_eq(other)
    }

    #[inline(always)]
    pure fn ne(other: &Quat<T>) -> bool {
        !(self == *other)
    }
}

pub impl<T:Copy Eq> Quat<T>: ExactEq {
    #[inline(always)]
    pure fn exact_eq(other: &Quat<T>) -> bool {
        self[0] == other[0] &&
        self[1] == other[1] &&
        self[2] == other[2] &&
        self[3] == other[3]
    }
}

pub impl<T:Copy FuzzyEq> Quat<T>: FuzzyEq {
    #[inline(always)]
    pure fn fuzzy_eq(other: &Quat<T>) -> bool {
        self[0].fuzzy_eq(&other[0]) &&
        self[1].fuzzy_eq(&other[1]) &&
        self[2].fuzzy_eq(&other[2]) &&
        self[3].fuzzy_eq(&other[3])
    }
}

pub impl<T:Copy> Quat<T>: ToPtr<T> {
    #[inline(always)]
    pure fn to_ptr() -> *T {
        to_unsafe_ptr(&self[0])
    }
}<|endoftext|>


<commit_before>use semver::{Comparator, Op, Version, VersionReq};
use std::fmt::{self, Display};

#[derive(PartialEq, Eq, Hash, Clone, Debug)]
pub enum OptVersionReq {
    Any,
    Req(VersionReq),
}

pub trait VersionExt {
    fn is_prerelease(&self) -> bool;
}

pub trait VersionReqExt {
    fn exact(version: &Version) -> Self;
}

impl VersionExt for Version {
    fn is_prerelease(&self) -> bool {
        !self.pre.is_empty()
    }
}

impl VersionReqExt for VersionReq {
    fn exact(version: &Version) -> Self {
        VersionReq {
            comparators: vec![Comparator {
                op: Op::Exact,
                major: version.major,
                minor: Some(version.minor),
                patch: Some(version.patch),
                pre: version.pre.clone(),
            }],
        }
    }
}

impl OptVersionReq {
    pub fn exact(version: &Version) -> Self {
        OptVersionReq::Req(VersionReq::exact(version))
    }

    pub fn is_exact(&self) -> bool {
        match self {
            OptVersionReq::Any => false,
            OptVersionReq::Req(req) => {
                req.comparators.len() == 1 && {
                    let cmp = &req.comparators[0];
                    cmp.op == Op::Exact && cmp.minor.is_some() && cmp.patch.is_some()
                }
            }
        }
    }

    pub fn matches(&self, version: &Version) -> bool {
        match self {
            OptVersionReq::Any => true,
            OptVersionReq::Req(req) => req.matches(version),
        }
    }
}

impl Display for OptVersionReq {
    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            OptVersionReq::Any => formatter.write_str("*"),
            OptVersionReq::Req(req) => Display::fmt(req, formatter),
        }
    }
}

impl From<VersionReq> for OptVersionReq {
    fn from(req: VersionReq) -> Self {
        OptVersionReq::Req(req)
    }
}
<commit_msg>Add `Locked` variant for `OptVersionReq`<commit_after>use semver::{Comparator, Op, Version, VersionReq};
use std::fmt::{self, Display};

#[derive(PartialEq, Eq, Hash, Clone, Debug)]
pub enum OptVersionReq {
    Any,
    Req(VersionReq),
    /// The exact locked version and the original version requirement.
    Locked(Version, VersionReq),
}

pub trait VersionExt {
    fn is_prerelease(&self) -> bool;
}

pub trait VersionReqExt {
    fn exact(version: &Version) -> Self;
}

impl VersionExt for Version {
    fn is_prerelease(&self) -> bool {
        !self.pre.is_empty()
    }
}

impl VersionReqExt for VersionReq {
    fn exact(version: &Version) -> Self {
        VersionReq {
            comparators: vec![Comparator {
                op: Op::Exact,
                major: version.major,
                minor: Some(version.minor),
                patch: Some(version.patch),
                pre: version.pre.clone(),
            }],
        }
    }
}

impl OptVersionReq {
    pub fn exact(version: &Version) -> Self {
        OptVersionReq::Req(VersionReq::exact(version))
    }

    pub fn is_exact(&self) -> bool {
        match self {
            OptVersionReq::Any => false,
            OptVersionReq::Req(req) => {
                req.comparators.len() == 1 && {
                    let cmp = &req.comparators[0];
                    cmp.op == Op::Exact && cmp.minor.is_some() && cmp.patch.is_some()
                }
            }
            OptVersionReq::Locked(..) => true,
        }
    }

    pub fn lock_to(&mut self, version: &Version) {
        assert!(self.matches(version), "cannot lock {} to {}", self, version);
        use OptVersionReq::*;
        let version = version.clone();
        *self = match self {
            Any => Locked(version, VersionReq::STAR),
            Req(req) => Locked(version, req.clone()),
            Locked(_, req) => Locked(version, req.clone()),
        };
    }

    pub fn is_locked(&self) -> bool {
        matches!(self, OptVersionReq::Locked(..))
    }

    /// Gets the version to which this req is locked, if any.
    pub fn locked_version(&self) -> Option<&Version> {
        match self {
            OptVersionReq::Locked(version, _) => Some(version),
            _ => None,
        }
    }

    pub fn matches(&self, version: &Version) -> bool {
        match self {
            OptVersionReq::Any => true,
            OptVersionReq::Req(req) => req.matches(version),
            OptVersionReq::Locked(v, _) => VersionReq::exact(v).matches(version),
        }
    }
}

impl Display for OptVersionReq {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            OptVersionReq::Any => f.write_str("*"),
            OptVersionReq::Req(req) => Display::fmt(req, f),
            OptVersionReq::Locked(_, req) => Display::fmt(req, f),
        }
    }
}

impl From<VersionReq> for OptVersionReq {
    fn from(req: VersionReq) -> Self {
        OptVersionReq::Req(req)
    }
}
<|endoftext|>


<commit_before>use wayland_client::EventQueueHandle;
use wayland_client::protocol::wl_output;

/// Used to know how big to make the surface.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct Resolution {
    pub w: u32,
    pub h: u32
}

impl Resolution {
    pub fn new() -> Self {
        Resolution {
            w: 0,
            h: 0
        }
    }
}

impl wl_output::Handler for Resolution {
    fn mode(&mut self,
            _evqh: &mut EventQueueHandle,
            _proxy: &wl_output::WlOutput,
            _flags: wl_output::Mode,
            width: i32,
            height: i32,
            _refresh: i32) {
        self.w = width as u32;
        self.h = height as u32;
    }
}

declare_handler!(Resolution, wl_output::Handler, wl_output::WlOutput);
<commit_msg>Only set resolution on current mode setting<commit_after>use wayland_client::EventQueueHandle;
use wayland_client::protocol::wl_output;

/// The current mode that the monitor is set to.
/// That is the resolution we should use
const CURRENT_MODE: u32 = 0x1;

/// Used to know how big to make the surface.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct Resolution {
    pub w: u32,
    pub h: u32
}

impl Resolution {
    pub fn new() -> Self {
        Resolution {
            w: 0,
            h: 0
        }
    }
}

impl wl_output::Handler for Resolution {
    fn mode(&mut self,
            _evqh: &mut EventQueueHandle,
            _proxy: &wl_output::WlOutput,
            flags: wl_output::Mode,
            width: i32,
            height: i32,
            _refresh: i32) {
        if flags.to_raw() & CURRENT_MODE != 0 {
            self.w = width as u32;
            self.h = height as u32;
        }
    }
}

declare_handler!(Resolution, wl_output::Handler, wl_output::WlOutput);
<|endoftext|>


<commit_before>//
//  SOS: the Stupid Operating System
//  by Hawk Weisman (hi@hawkweisman.me)
//
//  Copyright (c) 2015 Hawk Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! x86_64 execution contexts.
//!
//! This is inteded to be general-purpose and composable, so that the same
//! code can be reused for interrupts and for multithreading.

use core::mem;
use core::fmt;

/// Registers pushed to the stack when handling an interrupt or context switch.
#[repr(C, packed)]
#[derive(Copy, Clone)]
pub struct Registers { pub rsi: u64
                     , pub rdi: u64
                     , pub r11: u64
                     , pub r10: u64
                     , pub r9:  u64
                     , pub r8:  u64
                     , pub rdx: u64
                     , pub rcx: u64
                     , pub rax: u64
                     }

 impl Registers {
     /// Transform this struct into an array of `u64`s
     /// (if you would ever want to do this)
     pub unsafe fn to_array(&self) -> [u64; 9] {
        //  [ self.rsi, self.rdi, self.r11
        //  , self.r10, self.r9, self.r8
        //  , self.rdx, self.rcx, self.rax
        //  ]
        // using transmute is probably faster and we're already unsafe...
        mem::transmute(*self)
     }

     /// Create a new empty set of Registers
     pub const fn empty() -> Self {
         Registers { rsi: 0, rdi: 0, r11: 0
                   , r10: 0, r9:  0, r8:  0
                   , rdx: 0, rcx: 0, rax: 0
                   }
     }

     /// Push the caller-saved registers to the stack
     /// (such as when handling a context switch or interrupt).
     ///
     /// THIS FUNCTION IS NAKED. DO NOT CALL IT NORMALLY.
     #[naked]
     #[inline(always)]
     unsafe extern "C" fn push() {
         asm!( "push rax
                push rcx
                push rdx
                push r8
                push r9
                push r10
                push r11
                push rdi
                push rsi"
             :::: "intel"
                , "volatile");
     }

     /// Push the caller-saved registers off the stack
     /// (such as when handling a context switch or interrupt).
     ///
     /// THIS FUNCTION IS NAKED. DO NOT CALL IT NORMALLY.
     #[naked]
     #[inline(always)]
     unsafe extern "C" fn pop() {
         asm!( "pop rsi
                pop rdi
                pop r11
                pop r10
                pop r9
                pop r8
                pop rdx
                pop rcx
                pop rax"
             :::: "intel"
                , "volatile");
     }
 }

 impl fmt::Debug for Registers {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         write!( f
               , "    RSI: {:#018x} RDI: {:#018x} R11: {:#018x}\n    \
                      R10: {:#018x} R9:  {:#018x} R8:  {:#018x}\n    \
                      RDX: {:#018x} RCX: {:#018x} RAX: {:#018x}"
              , self.rsi, self.rdi, self.r11
              , self.r10, self.r9,  self.r8
              , self.rdx, self.rcx, self.rax)
     }
 }

/// Thread execution context
#[repr(C, packed)]
pub struct Context { /// Value of the stack pointer (`rsp`) register
                     pub rsp: *mut u8
                   , /// Value of the caller-saved registers
                     pub registers: Registers
                   , /// Value of the instruction pointer (`rip`) register
                     pub rip: *mut u8
                 //, pub stack: [u8] // TODO: should be box
                   }

impl Context {
    pub fn empty() -> Self {
        unsafe {
            Context { rsp: mem::transmute(0u64)
                    , registers: Registers::empty()
                    , rip: mem::transmute(0u64)
                  //, stack: [0u8; 8]
                    }
        }
    }
}
<commit_msg>[x86_84] push() and pop() need to be pub<commit_after>//
//  SOS: the Stupid Operating System
//  by Hawk Weisman (hi@hawkweisman.me)
//
//  Copyright (c) 2015 Hawk Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! x86_64 execution contexts.
//!
//! This is inteded to be general-purpose and composable, so that the same
//! code can be reused for interrupts and for multithreading.

use core::mem;
use core::fmt;

/// Registers pushed to the stack when handling an interrupt or context switch.
#[repr(C, packed)]
#[derive(Copy, Clone)]
pub struct Registers { pub rsi: u64
                     , pub rdi: u64
                     , pub r11: u64
                     , pub r10: u64
                     , pub r9:  u64
                     , pub r8:  u64
                     , pub rdx: u64
                     , pub rcx: u64
                     , pub rax: u64
                     }

 impl Registers {
     /// Transform this struct into an array of `u64`s
     /// (if you would ever want to do this)
     pub unsafe fn to_array(&self) -> [u64; 9] {
        //  [ self.rsi, self.rdi, self.r11
        //  , self.r10, self.r9, self.r8
        //  , self.rdx, self.rcx, self.rax
        //  ]
        // using transmute is probably faster and we're already unsafe...
        mem::transmute(*self)
     }

     /// Create a new empty set of Registers
     pub const fn empty() -> Self {
         Registers { rsi: 0, rdi: 0, r11: 0
                   , r10: 0, r9:  0, r8:  0
                   , rdx: 0, rcx: 0, rax: 0
                   }
     }

     /// Push the caller-saved registers to the stack
     /// (such as when handling a context switch or interrupt).
     ///
     /// THIS FUNCTION IS NAKED. DO NOT CALL IT NORMALLY.
     #[naked]
     #[inline(always)]
     pub unsafe fn push() {
         asm!( "push rax
                push rcx
                push rdx
                push r8
                push r9
                push r10
                push r11
                push rdi
                push rsi"
             :::: "intel"
                , "volatile");
     }

     /// Push the caller-saved registers off the stack
     /// (such as when handling a context switch or interrupt).
     ///
     /// THIS FUNCTION IS NAKED. DO NOT CALL IT NORMALLY.
     #[naked]
     #[inline(always)]
     pub unsafe fn pop() {
         asm!( "pop rsi
                pop rdi
                pop r11
                pop r10
                pop r9
                pop r8
                pop rdx
                pop rcx
                pop rax"
             :::: "intel"
                , "volatile");
     }
 }

 impl fmt::Debug for Registers {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         write!( f
               , "    RSI: {:#018x} RDI: {:#018x} R11: {:#018x}\n    \
                      R10: {:#018x} R9:  {:#018x} R8:  {:#018x}\n    \
                      RDX: {:#018x} RCX: {:#018x} RAX: {:#018x}"
              , self.rsi, self.rdi, self.r11
              , self.r10, self.r9,  self.r8
              , self.rdx, self.rcx, self.rax)
     }
 }

/// Thread execution context
#[repr(C, packed)]
pub struct Context { /// Value of the stack pointer (`rsp`) register
                     pub rsp: *mut u8
                   , /// Value of the caller-saved registers
                     pub registers: Registers
                   , /// Value of the instruction pointer (`rip`) register
                     pub rip: *mut u8
                 //, pub stack: [u8] // TODO: should be box
                   }

impl Context {
    pub fn empty() -> Self {
        unsafe {
            Context { rsp: mem::transmute(0u64)
                    , registers: Registers::empty()
                    , rip: mem::transmute(0u64)
                  //, stack: [0u8; 8]
                    }
        }
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2019, The rav1e contributors. All rights reserved
//
// This source code is subject to the terms of the BSD 2 Clause License and
// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
// was not distributed with this source code in the LICENSE file, you can
// obtain it at www.aomedia.org/license/software. If the Alliance for Open
// Media Patent License 1.0 was not distributed with this source code in the
// PATENTS file, you can obtain it at www.aomedia.org/license/patent.

use arg_enum_proc_macro::ArgEnum;
use num_derive::FromPrimitive;

/// Sample position for subsampled chroma
#[derive(Copy, Clone, Debug, PartialEq, FromPrimitive)]
#[repr(C)]
pub enum ChromaSamplePosition {
  /// The source video transfer function must be signaled
  /// outside the AV1 bitstream.
  Unknown,
  /// Horizontally co-located with (0, 0) luma sample, vertically positioned
  /// in the middle between two luma samples.
  Vertical,
  /// Co-located with (0, 0) luma sample.
  Colocated,
}

impl Default for ChromaSamplePosition {
  fn default() -> Self {
    ChromaSamplePosition::Unknown
  }
}

/// Chroma subsampling format
#[derive(Copy, Clone, Debug, PartialEq, FromPrimitive)]
#[repr(C)]
pub enum ChromaSampling {
  /// Both vertically and horizontally subsampled.
  Cs420,
  /// Horizontally subsampled.
  Cs422,
  /// Not subsampled.
  Cs444,
  /// Monochrome.
  Cs400,
}

impl Default for ChromaSampling {
  fn default() -> Self {
    ChromaSampling::Cs420
  }
}

impl ChromaSampling {
  /// Provides the amount to right shift the luma plane dimensions to get the
  ///  chroma plane dimensions.
  /// Only values 0 or 1 are ever returned.
  /// The plane dimensions must also be rounded up to accommodate odd luma plane
  ///  sizes.
  /// Cs400 returns None, as there are no chroma planes.
  pub fn get_decimation(self) -> Option<(usize, usize)> {
    use self::ChromaSampling::*;
    match self {
      Cs420 => Some((1, 1)),
      Cs422 => Some((1, 0)),
      Cs444 => Some((0, 0)),
      Cs400 => None,
    }
  }

  /// Calculates the size of a chroma plane for this sampling type, given the luma plane dimensions.
  pub fn get_chroma_dimensions(
    self, luma_width: usize, luma_height: usize,
  ) -> (usize, usize) {
    if let Some((ss_x, ss_y)) = self.get_decimation() {
      ((luma_width + ss_x) >> ss_x, (luma_height + ss_y) >> ss_y)
    } else {
      (0, 0)
    }
  }
}

/// Supported Color Primaries
///
/// As defined by “Color primaries” section of ISO/IEC 23091-4/ITU-T H.273
#[derive(ArgEnum, Debug, Clone, Copy, PartialEq, FromPrimitive)]
#[repr(C)]
pub enum ColorPrimaries {
  /// BT.709
  BT709 = 1,
  /// Unspecified, must be signaled or inferred outside of the bitstream
  Unspecified,
  /// BT.470 System M (historical)
  BT470M = 4,
  /// BT.470 System B, G (historical)
  BT470BG,
  /// BT.601-7 525 (SMPTE 170 M)
  BT601,
  /// SMPTE 240M (historical)
  SMPTE240,
  /// Generic film
  GenericFilm,
  /// BT.2020, BT.2100
  BT2020,
  /// SMPTE 248 (CIE 1921 XYZ)
  XYZ,
  /// SMPTE RP 431-2
  SMPTE431,
  /// SMPTE EG 432-1
  SMPTE432,
  /// EBU Tech. 3213-E
  EBU3213 = 22,
}

impl Default for ColorPrimaries {
  fn default() -> Self {
    ColorPrimaries::Unspecified
  }
}

/// Supported Transfer Characteristics
///
/// As defined by “Transfer characteristics” section of ISO/IEC 23091-4/ITU-TH.273.
#[derive(ArgEnum, Debug, Clone, Copy, PartialEq, FromPrimitive)]
#[repr(C)]
pub enum TransferCharacteristics {
  /// BT.709
  BT709 = 1,
  /// Unspecified, must be signaled or inferred outside of the bitstream
  Unspecified,
  /// BT.470 System M (historical)
  BT470M = 4,
  /// BT.470 System B, G (historical)
  BT470BG,
  /// BT.601-7 525 (SMPTE 170 M)
  BT601,
  /// SMPTE 240 M
  SMPTE240,
  /// Linear
  Linear,
  /// Logarithmic (100:1 range)
  Log100,
  /// Logarithmic ((100 * √10):1 range)
  Log100Sqrt10,
  /// IEC 61966-2-4
  IEC61966,
  /// BT.1361 extended color gamut system (historical)
  BT1361,
  /// sRGB or sYCC
  SRGB,
  /// BT.2020 10-bit systems
  BT2020_10Bit,
  /// BT.2020 12-bit systems
  BT2020_12Bit,
  /// SMPTE ST 2084, ITU BT.2100 PQ
  SMPTE2084,
  /// SMPTE ST 428
  SMPTE428,
  /// BT.2100 HLG (Hybrid Log Gamma), ARIB STD-B67
  HLG,
}

impl Default for TransferCharacteristics {
  fn default() -> Self {
    TransferCharacteristics::Unspecified
  }
}

/// Matrix coefficients
///
/// As defined by the “Matrix coefficients” section of ISO/IEC 23091-4/ITU-TH.273.
#[derive(ArgEnum, Debug, Clone, Copy, PartialEq, FromPrimitive)]
#[repr(C)]
pub enum MatrixCoefficients {
  /// Identity matrix
  Identity = 0,
  /// BT.709
  BT709,
  /// Unspecified, must be signaled or inferred outside of the bitstream.
  Unspecified,
  /// US FCC 73.628
  FCC = 4,
  /// BT.470 System B, G (historical)
  BT470BG,
  /// BT.601-7 525 (SMPTE 170 M)
  BT601,
  /// SMPTE 240 M
  SMPTE240,
  /// YCgCo
  YCgCo,
  /// BT.2020 non-constant luminance, BT.2100 YCbCr
  BT2020NCL,
  /// BT.2020 constant luminance
  BT2020CL,
  /// SMPTE ST 2085 YDzDx
  SMPTE2085,
  /// Chromaticity-derived non-constant luminance
  ChromatNCL,
  /// Chromaticity-derived constant luminance
  ChromatCL,
  /// BT.2020 ICtCp
  ICtCp,
}

impl Default for MatrixCoefficients {
  fn default() -> Self {
    MatrixCoefficients::Unspecified
  }
}

/// Signal the content color description
#[derive(Copy, Clone, Debug)]
pub struct ColorDescription {
  /// Color primaries.
  pub color_primaries: ColorPrimaries,
  /// Transfer charasteristics.
  pub transfer_characteristics: TransferCharacteristics,
  /// Matrix coefficients.
  pub matrix_coefficients: MatrixCoefficients,
}

/// Allowed pixel value range
///
/// C.f. VideoFullRangeFlag variable specified in ISO/IEC 23091-4/ITU-T H.273
#[derive(ArgEnum, Debug, Clone, Copy, PartialEq, FromPrimitive)]
#[repr(C)]
pub enum PixelRange {
  /// Studio swing representation
  Limited,
  /// Full swing representation
  Full,
}

impl Default for PixelRange {
  fn default() -> Self {
    PixelRange::Limited
  }
}

/// High dynamic range content light level
///
/// As defined by CEA-861.3, Appendix A.
#[derive(Copy, Clone, Debug)]
pub struct ContentLight {
  /// Maximum content light level
  pub max_content_light_level: u16,
  /// Maximum frame-average light level
  pub max_frame_average_light_level: u16,
}

/// Chromaticity coordinates expressed as 0.16 fixed-point values
#[derive(Clone, Copy, Debug)]
#[repr(C)]
pub struct Point {
  pub x: u16,
  pub y: u16,
}

/// High dynamic range mastering display color volume
///
/// As defined by CIE 1931
#[derive(Copy, Clone, Debug)]
pub struct MasteringDisplay {
  /// Chromaticity coordinates in Red, Green, Blue order
  /// expressed as 0.16 fixed-point
  pub primaries: [Point; 3],
  /// Chromaticity coordinates expressed as 0.16 fixed-point
  pub white_point: Point,
  /// 24.8 fixed-point maximum luminance in candelas per square meter
  pub max_luminance: u32,
  /// 18.14 fixed-point minimum luminance in candelas per square meter
  pub min_luminance: u32,
}
<commit_msg>Document Point<commit_after>// Copyright (c) 2019, The rav1e contributors. All rights reserved
//
// This source code is subject to the terms of the BSD 2 Clause License and
// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
// was not distributed with this source code in the LICENSE file, you can
// obtain it at www.aomedia.org/license/software. If the Alliance for Open
// Media Patent License 1.0 was not distributed with this source code in the
// PATENTS file, you can obtain it at www.aomedia.org/license/patent.

use arg_enum_proc_macro::ArgEnum;
use num_derive::FromPrimitive;

/// Sample position for subsampled chroma
#[derive(Copy, Clone, Debug, PartialEq, FromPrimitive)]
#[repr(C)]
pub enum ChromaSamplePosition {
  /// The source video transfer function must be signaled
  /// outside the AV1 bitstream.
  Unknown,
  /// Horizontally co-located with (0, 0) luma sample, vertically positioned
  /// in the middle between two luma samples.
  Vertical,
  /// Co-located with (0, 0) luma sample.
  Colocated,
}

impl Default for ChromaSamplePosition {
  fn default() -> Self {
    ChromaSamplePosition::Unknown
  }
}

/// Chroma subsampling format
#[derive(Copy, Clone, Debug, PartialEq, FromPrimitive)]
#[repr(C)]
pub enum ChromaSampling {
  /// Both vertically and horizontally subsampled.
  Cs420,
  /// Horizontally subsampled.
  Cs422,
  /// Not subsampled.
  Cs444,
  /// Monochrome.
  Cs400,
}

impl Default for ChromaSampling {
  fn default() -> Self {
    ChromaSampling::Cs420
  }
}

impl ChromaSampling {
  /// Provides the amount to right shift the luma plane dimensions to get the
  ///  chroma plane dimensions.
  /// Only values 0 or 1 are ever returned.
  /// The plane dimensions must also be rounded up to accommodate odd luma plane
  ///  sizes.
  /// Cs400 returns None, as there are no chroma planes.
  pub fn get_decimation(self) -> Option<(usize, usize)> {
    use self::ChromaSampling::*;
    match self {
      Cs420 => Some((1, 1)),
      Cs422 => Some((1, 0)),
      Cs444 => Some((0, 0)),
      Cs400 => None,
    }
  }

  /// Calculates the size of a chroma plane for this sampling type, given the luma plane dimensions.
  pub fn get_chroma_dimensions(
    self, luma_width: usize, luma_height: usize,
  ) -> (usize, usize) {
    if let Some((ss_x, ss_y)) = self.get_decimation() {
      ((luma_width + ss_x) >> ss_x, (luma_height + ss_y) >> ss_y)
    } else {
      (0, 0)
    }
  }
}

/// Supported Color Primaries
///
/// As defined by “Color primaries” section of ISO/IEC 23091-4/ITU-T H.273
#[derive(ArgEnum, Debug, Clone, Copy, PartialEq, FromPrimitive)]
#[repr(C)]
pub enum ColorPrimaries {
  /// BT.709
  BT709 = 1,
  /// Unspecified, must be signaled or inferred outside of the bitstream
  Unspecified,
  /// BT.470 System M (historical)
  BT470M = 4,
  /// BT.470 System B, G (historical)
  BT470BG,
  /// BT.601-7 525 (SMPTE 170 M)
  BT601,
  /// SMPTE 240M (historical)
  SMPTE240,
  /// Generic film
  GenericFilm,
  /// BT.2020, BT.2100
  BT2020,
  /// SMPTE 248 (CIE 1921 XYZ)
  XYZ,
  /// SMPTE RP 431-2
  SMPTE431,
  /// SMPTE EG 432-1
  SMPTE432,
  /// EBU Tech. 3213-E
  EBU3213 = 22,
}

impl Default for ColorPrimaries {
  fn default() -> Self {
    ColorPrimaries::Unspecified
  }
}

/// Supported Transfer Characteristics
///
/// As defined by “Transfer characteristics” section of ISO/IEC 23091-4/ITU-TH.273.
#[derive(ArgEnum, Debug, Clone, Copy, PartialEq, FromPrimitive)]
#[repr(C)]
pub enum TransferCharacteristics {
  /// BT.709
  BT709 = 1,
  /// Unspecified, must be signaled or inferred outside of the bitstream
  Unspecified,
  /// BT.470 System M (historical)
  BT470M = 4,
  /// BT.470 System B, G (historical)
  BT470BG,
  /// BT.601-7 525 (SMPTE 170 M)
  BT601,
  /// SMPTE 240 M
  SMPTE240,
  /// Linear
  Linear,
  /// Logarithmic (100:1 range)
  Log100,
  /// Logarithmic ((100 * √10):1 range)
  Log100Sqrt10,
  /// IEC 61966-2-4
  IEC61966,
  /// BT.1361 extended color gamut system (historical)
  BT1361,
  /// sRGB or sYCC
  SRGB,
  /// BT.2020 10-bit systems
  BT2020_10Bit,
  /// BT.2020 12-bit systems
  BT2020_12Bit,
  /// SMPTE ST 2084, ITU BT.2100 PQ
  SMPTE2084,
  /// SMPTE ST 428
  SMPTE428,
  /// BT.2100 HLG (Hybrid Log Gamma), ARIB STD-B67
  HLG,
}

impl Default for TransferCharacteristics {
  fn default() -> Self {
    TransferCharacteristics::Unspecified
  }
}

/// Matrix coefficients
///
/// As defined by the “Matrix coefficients” section of ISO/IEC 23091-4/ITU-TH.273.
#[derive(ArgEnum, Debug, Clone, Copy, PartialEq, FromPrimitive)]
#[repr(C)]
pub enum MatrixCoefficients {
  /// Identity matrix
  Identity = 0,
  /// BT.709
  BT709,
  /// Unspecified, must be signaled or inferred outside of the bitstream.
  Unspecified,
  /// US FCC 73.628
  FCC = 4,
  /// BT.470 System B, G (historical)
  BT470BG,
  /// BT.601-7 525 (SMPTE 170 M)
  BT601,
  /// SMPTE 240 M
  SMPTE240,
  /// YCgCo
  YCgCo,
  /// BT.2020 non-constant luminance, BT.2100 YCbCr
  BT2020NCL,
  /// BT.2020 constant luminance
  BT2020CL,
  /// SMPTE ST 2085 YDzDx
  SMPTE2085,
  /// Chromaticity-derived non-constant luminance
  ChromatNCL,
  /// Chromaticity-derived constant luminance
  ChromatCL,
  /// BT.2020 ICtCp
  ICtCp,
}

impl Default for MatrixCoefficients {
  fn default() -> Self {
    MatrixCoefficients::Unspecified
  }
}

/// Signal the content color description
#[derive(Copy, Clone, Debug)]
pub struct ColorDescription {
  /// Color primaries.
  pub color_primaries: ColorPrimaries,
  /// Transfer charasteristics.
  pub transfer_characteristics: TransferCharacteristics,
  /// Matrix coefficients.
  pub matrix_coefficients: MatrixCoefficients,
}

/// Allowed pixel value range
///
/// C.f. VideoFullRangeFlag variable specified in ISO/IEC 23091-4/ITU-T H.273
#[derive(ArgEnum, Debug, Clone, Copy, PartialEq, FromPrimitive)]
#[repr(C)]
pub enum PixelRange {
  /// Studio swing representation
  Limited,
  /// Full swing representation
  Full,
}

impl Default for PixelRange {
  fn default() -> Self {
    PixelRange::Limited
  }
}

/// High dynamic range content light level
///
/// As defined by CEA-861.3, Appendix A.
#[derive(Copy, Clone, Debug)]
pub struct ContentLight {
  /// Maximum content light level
  pub max_content_light_level: u16,
  /// Maximum frame-average light level
  pub max_frame_average_light_level: u16,
}

/// Chromaticity coordinates as defined by CIE 1931, expressed as 0.16
/// fixed-point values.
#[derive(Clone, Copy, Debug)]
#[repr(C)]
pub struct Point {
  /// The X coordinate.
  pub x: u16,
  /// The Y coordinate.
  pub y: u16,
}

/// High dynamic range mastering display color volume
///
/// As defined by CIE 1931
#[derive(Copy, Clone, Debug)]
pub struct MasteringDisplay {
  /// Chromaticity coordinates in Red, Green, Blue order
  /// expressed as 0.16 fixed-point
  pub primaries: [Point; 3],
  /// Chromaticity coordinates expressed as 0.16 fixed-point
  pub white_point: Point,
  /// 24.8 fixed-point maximum luminance in candelas per square meter
  pub max_luminance: u32,
  /// 18.14 fixed-point minimum luminance in candelas per square meter
  pub min_luminance: u32,
}
<|endoftext|>


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

use std::borrow::Cow;
use std::env;

pub fn escape(s: Cow<str>) -> Cow<str> {
    if cfg!(unix) {
        unix::escape(s)
    } else if env::var("MSYSTEM").is_ok() {
        unix::escape(s)
    } else {
        windows::escape(s)
    }
}

pub mod windows {
    use std::borrow::Cow;
    use std::iter::repeat;

    /// Escape for the windows cmd.exe shell, for more info see this url:
    ///
    /// http://blogs.msdn.com/b/twistylittlepassagesallalike/archive/2011/04/23
    ///                      /everyone-quotes-arguments-the-wrong-way.aspx
    pub fn escape(s: Cow<str>) -> Cow<str> {
        let mut needs_escape = false;
        for ch in s.chars() {
            match ch {
                '"' | '\t' | '\n' | ' ' => needs_escape = true,
                _ => {}
            }
        }
        if !needs_escape {
            return s
        }
        let mut es = String::with_capacity(s.len());
        es.push('"');
        let mut chars = s.chars().peekable();
        loop {
            let mut nslashes = 0;
            while let Some(&'\\') = chars.peek() {
                chars.next();
                nslashes += 1;
            }

            match chars.next() {
                Some('"') => {
                    es.extend(repeat('\\').take(nslashes * 2 + 1));
                    es.push('"');
                }
                Some(c) => {
                    es.extend(repeat('\\').take(nslashes));
                    es.push(c);
                }
                None => {
                    es.extend(repeat('\\').take(nslashes * 2));
                    break;
                }
            }

        }
        es.push('"');
        es.into()
    }

    #[test]
    fn test_escape() {
        assert_eq!(escape("--aaa=bbb-ccc".into()), "--aaa=bbb-ccc");
        assert_eq!(escape("linker=gcc -L/foo -Wl,bar".into()),
                          r#""linker=gcc -L/foo -Wl,bar""#);
        assert_eq!(escape(r#"--features="default""#.into()),
                          r#""--features=\"default\"""#);
        assert_eq!(escape(r#"\path\to\my documents\"#.into()),
                          r#""\path\to\my documents\\""#);
    }
}

pub mod unix {
    use std::borrow::Cow;

    const SHELL_SPECIAL: &'static str = r#" \$'"`!"#;

    /// Escape characters that may have special meaning in a shell,
    /// including spaces.
    pub fn escape(s: Cow<str>) -> Cow<str> {
        let escape_char = '\\';
        // check if string needs to be escaped
        let clean = SHELL_SPECIAL.chars().all(|sp_char| !s.contains(sp_char));
        if clean {
            return s
        }
        let mut es = String::with_capacity(s.len());
        for ch in s.chars() {
            if SHELL_SPECIAL.contains(ch) {
                es.push(escape_char);
            }
            es.push(ch)
        }
        es.into()
    }

    #[test]
    fn test_escape() {
        assert_eq!(escape("--aaa=bbb-ccc".into()), "--aaa=bbb-ccc");
        assert_eq!(escape("linker=gcc -L/foo -Wl,bar".into()),
                          r#"linker=gcc\ -L/foo\ -Wl,bar"#);
        assert_eq!(escape(r#"--features="default""#.into()),
                          r#"--features=\"default\""#);
        assert_eq!(escape(r#"'!\$`\\\n "#.into()),
                          r#"\'\!\\\$\`\\\\\\n\ "#);
    }
}
<commit_msg>Combine duplicate `if` arm blocks.<commit_after>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::borrow::Cow;
use std::env;

pub fn escape(s: Cow<str>) -> Cow<str> {
    if cfg!(unix) || env::var("MSYSTEM").is_ok() {
        unix::escape(s)
    } else {
        windows::escape(s)
    }
}

pub mod windows {
    use std::borrow::Cow;
    use std::iter::repeat;

    /// Escape for the windows cmd.exe shell, for more info see this url:
    ///
    /// http://blogs.msdn.com/b/twistylittlepassagesallalike/archive/2011/04/23
    ///                      /everyone-quotes-arguments-the-wrong-way.aspx
    pub fn escape(s: Cow<str>) -> Cow<str> {
        let mut needs_escape = false;
        for ch in s.chars() {
            match ch {
                '"' | '\t' | '\n' | ' ' => needs_escape = true,
                _ => {}
            }
        }
        if !needs_escape {
            return s
        }
        let mut es = String::with_capacity(s.len());
        es.push('"');
        let mut chars = s.chars().peekable();
        loop {
            let mut nslashes = 0;
            while let Some(&'\\') = chars.peek() {
                chars.next();
                nslashes += 1;
            }

            match chars.next() {
                Some('"') => {
                    es.extend(repeat('\\').take(nslashes * 2 + 1));
                    es.push('"');
                }
                Some(c) => {
                    es.extend(repeat('\\').take(nslashes));
                    es.push(c);
                }
                None => {
                    es.extend(repeat('\\').take(nslashes * 2));
                    break;
                }
            }

        }
        es.push('"');
        es.into()
    }

    #[test]
    fn test_escape() {
        assert_eq!(escape("--aaa=bbb-ccc".into()), "--aaa=bbb-ccc");
        assert_eq!(escape("linker=gcc -L/foo -Wl,bar".into()),
                          r#""linker=gcc -L/foo -Wl,bar""#);
        assert_eq!(escape(r#"--features="default""#.into()),
                          r#""--features=\"default\"""#);
        assert_eq!(escape(r#"\path\to\my documents\"#.into()),
                          r#""\path\to\my documents\\""#);
    }
}

pub mod unix {
    use std::borrow::Cow;

    const SHELL_SPECIAL: &'static str = r#" \$'"`!"#;

    /// Escape characters that may have special meaning in a shell,
    /// including spaces.
    pub fn escape(s: Cow<str>) -> Cow<str> {
        let escape_char = '\\';
        // check if string needs to be escaped
        let clean = SHELL_SPECIAL.chars().all(|sp_char| !s.contains(sp_char));
        if clean {
            return s
        }
        let mut es = String::with_capacity(s.len());
        for ch in s.chars() {
            if SHELL_SPECIAL.contains(ch) {
                es.push(escape_char);
            }
            es.push(ch)
        }
        es.into()
    }

    #[test]
    fn test_escape() {
        assert_eq!(escape("--aaa=bbb-ccc".into()), "--aaa=bbb-ccc");
        assert_eq!(escape("linker=gcc -L/foo -Wl,bar".into()),
                          r#"linker=gcc\ -L/foo\ -Wl,bar"#);
        assert_eq!(escape(r#"--features="default""#.into()),
                          r#"--features=\"default\""#);
        assert_eq!(escape(r#"'!\$`\\\n "#.into()),
                          r#"\'\!\\\$\`\\\\\\n\ "#);
    }
}
<|endoftext|>