<commit_before>use std::fmt;
use std::str;
use num::FromPrimitive;

#[derive(Debug, Default, Clone)]
pub struct FuncConst {
    pub name: String,
    pub arg_count: u32,
    pub local_count: u32,
    pub body: Vec<u8>
}

#[derive(Default)]
pub struct ConstTable {
    pub funcs: Vec<FuncConst>,
    pub bc_counter: usize
}

impl fmt::Debug for ConstTable {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        //TODO
        unimplemented!()
    }
}

// Eats a null byte terminated string
fn eat_string(data: &[u8], const_table: &mut ConstTable) -> String {
    use std::ffi::CString;

    let str_start = const_table.bc_counter;
    let mut str_len: usize = 0;
    while data[str_start + str_len] != 0x00 {
        str_len += 1;
    }
    let string = CString::new(&data[str_start..(str_start+str_len)]).unwrap();
    const_table.bc_counter += str_len + 1; // + 1 for null byte
    //debug!("Ate string {:?} of length {}", string, str_len);
    string.into_string().unwrap()
}

#[inline]
fn get_next_4_bytes(data: &[u8], const_table: &mut ConstTable) -> u32 {

    let val = (data[const_table.bc_counter] as u32) << 24 |
        (data[const_table.bc_counter + 1] as u32) << 16 |
        (data[const_table.bc_counter + 2] as u32) << 8 |
        (data[const_table.bc_counter + 3] as u32);
    const_table.bc_counter += 4;
    debug!("get_next_4_bytes: 0x{:04X}", val);
    val
}

pub fn read_const_table(data: &[u8]) -> ConstTable {

    let mut const_table: ConstTable = Default::default();

    macro_rules! get_next_4_bytes {
        () => (get_next_4_bytes(&data, &mut const_table))
    }

    while const_table.bc_counter != data.len() {
        let instr = ConstInstr::from_u8(data[const_table.bc_counter]);

        const_table.bc_counter += 1;
        if instr.is_none() {
            warn!("Unimplemented constants table instruction: {:04X}",
                  data[const_table.bc_counter - 1]);
            continue;
        }

        let instr = instr.unwrap();

        match instr {
            ConstInstr::FUNC => {
                // TODO: use this id
                let id = get_next_4_bytes!() as usize;
                let name = eat_string(&data, &mut const_table);
                let arg_count = get_next_4_bytes!();
                let local_count = get_next_4_bytes!();
                let bc_length = get_next_4_bytes!() as usize;
                let body = data[const_table.bc_counter..{
                    const_table.bc_counter += bc_length;
                    const_table.bc_counter + 1
                }].to_vec();

                if id >= const_table.funcs.len() {
                    const_table.funcs.resize(id + 1,FuncConst{
                        ..Default::default()
                    })
                }

                info!("Added function \"{}\" to the constants table", name);
                const_table.funcs[id] = FuncConst {
                    name: name,
                    arg_count: arg_count,
                    local_count: local_count,
                    body: body
                };
            },
            ConstInstr::END => {
                debug!("Reached end of constants table");
                break;
            }
        }
    }
    const_table
}

enum_from_primitive! {
    #[allow(non_camel_case_types)]
    #[derive(Debug, PartialEq)]
    pub enum ConstInstr {
        FUNC = 0xF0,
        END = 0xED
    }
}
<commit_msg>Eliminate warnings (by adding default Debug behaviour)<commit_after>use std::str;
use num::FromPrimitive;

#[derive(Debug, Default, Clone)]
pub struct FuncConst {
    pub name: String,
    pub arg_count: u32,
    pub local_count: u32,
    pub body: Vec<u8>
}

#[derive(Debug, Default)]
pub struct ConstTable {
    pub funcs: Vec<FuncConst>,
    pub bc_counter: usize
}

// Eats a null byte terminated string
fn eat_string(data: &[u8], const_table: &mut ConstTable) -> String {
    use std::ffi::CString;

    let str_start = const_table.bc_counter;
    let mut str_len: usize = 0;
    while data[str_start + str_len] != 0x00 {
        str_len += 1;
    }
    let string = CString::new(&data[str_start..(str_start+str_len)]).unwrap();
    const_table.bc_counter += str_len + 1; // + 1 for null byte
    //debug!("Ate string {:?} of length {}", string, str_len);
    string.into_string().unwrap()
}

#[inline]
fn get_next_4_bytes(data: &[u8], const_table: &mut ConstTable) -> u32 {

    let val = (data[const_table.bc_counter] as u32) << 24 |
        (data[const_table.bc_counter + 1] as u32) << 16 |
        (data[const_table.bc_counter + 2] as u32) << 8 |
        (data[const_table.bc_counter + 3] as u32);
    const_table.bc_counter += 4;
    debug!("get_next_4_bytes: 0x{:04X}", val);
    val
}

pub fn read_const_table(data: &[u8]) -> ConstTable {

    let mut const_table: ConstTable = Default::default();

    macro_rules! get_next_4_bytes {
        () => (get_next_4_bytes(&data, &mut const_table))
    }

    while const_table.bc_counter != data.len() {
        let instr = ConstInstr::from_u8(data[const_table.bc_counter]);

        const_table.bc_counter += 1;
        if instr.is_none() {
            warn!("Unimplemented constants table instruction: {:04X}",
                  data[const_table.bc_counter - 1]);
            continue;
        }

        let instr = instr.unwrap();

        match instr {
            ConstInstr::FUNC => {
                // TODO: use this id
                let id = get_next_4_bytes!() as usize;
                let name = eat_string(&data, &mut const_table);
                let arg_count = get_next_4_bytes!();
                let local_count = get_next_4_bytes!();
                let bc_length = get_next_4_bytes!() as usize;
                let body = data[const_table.bc_counter..{
                    const_table.bc_counter += bc_length;
                    const_table.bc_counter + 1
                }].to_vec();

                if id >= const_table.funcs.len() {
                    const_table.funcs.resize(id + 1,FuncConst{
                        ..Default::default()
                    })
                }

                info!("Added function \"{}\" to the constants table", name);
                const_table.funcs[id] = FuncConst {
                    name: name,
                    arg_count: arg_count,
                    local_count: local_count,
                    body: body
                };
            },
            ConstInstr::END => {
                debug!("Reached end of constants table");
                break;
            }
        }
    }
    const_table
}

enum_from_primitive! {
    #[allow(non_camel_case_types)]
    #[derive(Debug, PartialEq)]
    pub enum ConstInstr {
        FUNC = 0xF0,
        END = 0xED
    }
}
<|endoftext|>


<commit_before>mod ffi_api;
mod ffi_wrappers;
mod main_loop;
mod renderer;

use std::{os::unix::net::UnixStream, thread::JoinHandle};

use smithay::{
    reexports::calloop,
    utils::{Logical, Point},
};

use ffi_api::{WlcsExtensionDescriptor, WlcsIntegrationDescriptor};

macro_rules! extension_list {
    ($(($name: expr, $version: expr)),* $(,)?) => {
        &[$(
            WlcsExtensionDescriptor {
                name: concat!($name, "\0").as_ptr() as *const std::os::raw::c_char,
                version: $version
            }
        ),*]
    };
}

static SUPPORTED_EXTENSIONS: &[WlcsExtensionDescriptor] = extension_list!(
    ("wl_compositor", 4),
    ("wl_subcompositor", 1),
    ("wl_data_device_manager", 3),
    ("wl_shell", 1),
    ("wl_seat", 5),
    ("wl_output", 3),
    ("xdg_wm_base", 1),
);

static DESCRIPTOR: WlcsIntegrationDescriptor = WlcsIntegrationDescriptor {
    version: 1,
    num_extensions: SUPPORTED_EXTENSIONS.len(),
    supported_extensions: SUPPORTED_EXTENSIONS.as_ptr(),
};

/// Event sent by WLCS to control the compositor
#[derive(Debug)]
pub enum WlcsEvent {
    /// Stop the running server
    Exit,
    /// Create a new client from given RawFd
    NewClient {
        stream: UnixStream,
        client_id: i32,
    },
    /// Position this window from the client associated with this Fd on the global space
    PositionWindow {
        client_id: i32,
        surface_id: u32,
        location: Point<i32, Logical>,
    },
    /* Pointer related events */
    /// A new pointer device is available
    NewPointer {
        device_id: u32,
    },
    /// Move the pointer in absolute coordinate space
    PointerMoveAbsolute {
        device_id: u32,
        location: Point<f64, Logical>,
    },
    /// Move the pointer in relative coordinate space
    PointerMoveRelative {
        device_id: u32,
        delta: Point<f64, Logical>,
    },
    /// Press a pointer button
    PointerButtonDown {
        device_id: u32,
        button_id: i32,
    },
    /// Release a pointer button
    PointerButtonUp {
        device_id: u32,
        button_id: i32,
    },
    /// A pointer device is removed
    PointerRemoved {
        device_id: u32,
    },
    /* Touch related events */
    /// A new touch device is available
    NewTouch {
        device_id: u32,
    },
    /// A touch point is down
    TouchDown {
        device_id: u32,
        location: Point<f64, Logical>,
    },
    /// A touch point moved
    TouchMove {
        device_id: u32,
        location: Point<f64, Logical>,
    },
    /// A touch point is up
    TouchUp {
        device_id: u32,
    },
    TouchRemoved {
        device_id: u32,
    },
}

fn start_anvil(channel: calloop::channel::Channel<WlcsEvent>) -> JoinHandle<()> {
    std::thread::spawn(move || main_loop::run(channel))
}
<commit_msg>bump xdg_wm_base in wlcs supported extensions<commit_after>mod ffi_api;
mod ffi_wrappers;
mod main_loop;
mod renderer;

use std::{os::unix::net::UnixStream, thread::JoinHandle};

use smithay::{
    reexports::calloop,
    utils::{Logical, Point},
};

use ffi_api::{WlcsExtensionDescriptor, WlcsIntegrationDescriptor};

macro_rules! extension_list {
    ($(($name: expr, $version: expr)),* $(,)?) => {
        &[$(
            WlcsExtensionDescriptor {
                name: concat!($name, "\0").as_ptr() as *const std::os::raw::c_char,
                version: $version
            }
        ),*]
    };
}

static SUPPORTED_EXTENSIONS: &[WlcsExtensionDescriptor] = extension_list!(
    ("wl_compositor", 4),
    ("wl_subcompositor", 1),
    ("wl_data_device_manager", 3),
    ("wl_shell", 1),
    ("wl_seat", 5),
    ("wl_output", 3),
    ("xdg_wm_base", 3),
);

static DESCRIPTOR: WlcsIntegrationDescriptor = WlcsIntegrationDescriptor {
    version: 1,
    num_extensions: SUPPORTED_EXTENSIONS.len(),
    supported_extensions: SUPPORTED_EXTENSIONS.as_ptr(),
};

/// Event sent by WLCS to control the compositor
#[derive(Debug)]
pub enum WlcsEvent {
    /// Stop the running server
    Exit,
    /// Create a new client from given RawFd
    NewClient {
        stream: UnixStream,
        client_id: i32,
    },
    /// Position this window from the client associated with this Fd on the global space
    PositionWindow {
        client_id: i32,
        surface_id: u32,
        location: Point<i32, Logical>,
    },
    /* Pointer related events */
    /// A new pointer device is available
    NewPointer {
        device_id: u32,
    },
    /// Move the pointer in absolute coordinate space
    PointerMoveAbsolute {
        device_id: u32,
        location: Point<f64, Logical>,
    },
    /// Move the pointer in relative coordinate space
    PointerMoveRelative {
        device_id: u32,
        delta: Point<f64, Logical>,
    },
    /// Press a pointer button
    PointerButtonDown {
        device_id: u32,
        button_id: i32,
    },
    /// Release a pointer button
    PointerButtonUp {
        device_id: u32,
        button_id: i32,
    },
    /// A pointer device is removed
    PointerRemoved {
        device_id: u32,
    },
    /* Touch related events */
    /// A new touch device is available
    NewTouch {
        device_id: u32,
    },
    /// A touch point is down
    TouchDown {
        device_id: u32,
        location: Point<f64, Logical>,
    },
    /// A touch point moved
    TouchMove {
        device_id: u32,
        location: Point<f64, Logical>,
    },
    /// A touch point is up
    TouchUp {
        device_id: u32,
    },
    TouchRemoved {
        device_id: u32,
    },
}

fn start_anvil(channel: calloop::channel::Channel<WlcsEvent>) -> JoinHandle<()> {
    std::thread::spawn(move || main_loop::run(channel))
}
<|endoftext|>


<commit_before>use calx::V2;
use entity::Entity;
use terrain::TerrainType;
use geom::HexGeom;
use terrain;
use world;

/// Unambiguous location in the game world.
#[deriving(Eq, PartialEq, Clone, Hash, Show, Encodable, Decodable)]
pub struct Location {
    pub x: i8,
    pub y: i8,
    // TODO: Add third dimension for multiple persistent levels.
}

impl Location {
    pub fn new(x: i8, y: i8) -> Location { Location { x: x, y: y } }

    /// Return terrain at the location.
    pub fn terrain(&self) -> TerrainType {
        let mut ret = world::get().borrow().area.terrain(*self);
        // Mobs standing on doors make the doors open.
        if ret == terrain::Door && self.has_mobs() {
            ret = terrain::OpenDoor;
        }
        ret
    }

    pub fn blocks_sight(&self) -> bool {
        self.terrain().blocks_sight()
    }

    pub fn blocks_walk(&self) -> bool {
        if self.terrain().blocks_walk() { return true; }
        if self.entities().iter().any(|e| e.blocks_walk()) {
            return true;
        }
        false
    }

    pub fn entities(&self) -> Vec<Entity> {
        world::get().borrow().spatial.entities_at(*self)
    }

    pub fn has_entities(&self) -> bool { !self.entities().is_empty() }

    pub fn has_mobs(&self) -> bool {
        self.entities().iter().any(|e| e.is_mob())
    }

    pub fn distance_from(&self, other: Location) -> Option<int> {
        // Return None for pairs on different floors if multi-floor support is
        // added.
        Some((V2(self.x as int, self.y as int) - V2(other.x as int, other.y as int)).hex_dist())
    }
}

impl Add<V2<int>, Location> for Location {
    fn add(&self, other: &V2<int>) -> Location {
        Location::new(
            (self.x as int + other.0) as i8,
            (self.y as int + other.1) as i8)
    }
}

/// An abstract type that maps a 2D plane into game world Locations. This can
/// be just a straightforward mapping, or it can involve something exotic like
/// a non-Euclidean space where the lines from the Chart origin are raycast
/// through portals.
pub trait Chart: Add<V2<int>, Location> {}

impl Chart for Location {}

/// The other half of a Chart, mapping Locations into 2D plane positions, if a
/// mapping exists. It depends on the weirdness of a space how trivial this is
/// to do.
pub trait Unchart {
    fn chart_pos(&self, loc: Location) -> Option<V2<int>>;
}

impl Unchart for Location {
    fn chart_pos(&self, loc: Location) -> Option<V2<int>> {
        Some(V2(loc.x as int - self.x as int, loc.y as int - self.y as int))
    }
}
<commit_msg>Support Dijkstraing on Locations<commit_after>use calx::dijkstra;
use calx::V2;
use dir6::Dir6;
use entity::Entity;
use terrain::TerrainType;
use geom::HexGeom;
use terrain;
use world;

/// Unambiguous location in the game world.
#[deriving(Eq, PartialEq, Clone, Hash, Show, Encodable, Decodable)]
pub struct Location {
    pub x: i8,
    pub y: i8,
    // TODO: Add third dimension for multiple persistent levels.
}

impl Location {
    pub fn new(x: i8, y: i8) -> Location { Location { x: x, y: y } }

    /// Return terrain at the location.
    pub fn terrain(&self) -> TerrainType {
        let mut ret = world::get().borrow().area.terrain(*self);
        // Mobs standing on doors make the doors open.
        if ret == terrain::Door && self.has_mobs() {
            ret = terrain::OpenDoor;
        }
        ret
    }

    pub fn blocks_sight(&self) -> bool {
        self.terrain().blocks_sight()
    }

    pub fn blocks_walk(&self) -> bool {
        if self.terrain().blocks_walk() { return true; }
        if self.entities().iter().any(|e| e.blocks_walk()) {
            return true;
        }
        false
    }

    pub fn entities(&self) -> Vec<Entity> {
        world::get().borrow().spatial.entities_at(*self)
    }

    pub fn has_entities(&self) -> bool { !self.entities().is_empty() }

    pub fn has_mobs(&self) -> bool {
        self.entities().iter().any(|e| e.is_mob())
    }

    /// Vector pointing from this location into the other one if the locations
    /// are on the same Euclidean plane.
    pub fn v2_at(&self, other: Location) -> Option<V2<int>> {
        // Return None for pairs on different floors if multi-floor support is
        // added.
        Some(V2(other.x as int, other.y as int) - V2(self.x as int, self.y as int))
    }

    /// Hex distance from this location to the other one, if applicable.
    pub fn distance_from(&self, other: Location) -> Option<int> {
        if let Some(v) = self.v2_at(other) { Some(v.hex_dist()) } else { None }
    }

    pub fn dir6_towards(&self, other: Location) -> Option<Dir6> {
        if let Some(v) = self.v2_at(other) { Some(Dir6::from_v2(v)) } else { None }
    }
}

impl Add<V2<int>, Location> for Location {
    fn add(&self, other: &V2<int>) -> Location {
        Location::new(
            (self.x as int + other.0) as i8,
            (self.y as int + other.1) as i8)
    }
}

/// An abstract type that maps a 2D plane into game world Locations. This can
/// be just a straightforward mapping, or it can involve something exotic like
/// a non-Euclidean space where the lines from the Chart origin are raycast
/// through portals.
pub trait Chart: Add<V2<int>, Location> {}

impl Chart for Location {}

/// The other half of a Chart, mapping Locations into 2D plane positions, if a
/// mapping exists. It depends on the weirdness of a space how trivial this is
/// to do.
pub trait Unchart {
    fn chart_pos(&self, loc: Location) -> Option<V2<int>>;
}

impl Unchart for Location {
    fn chart_pos(&self, loc: Location) -> Option<V2<int>> {
        Some(V2(loc.x as int - self.x as int, loc.y as int - self.y as int))
    }
}

impl dijkstra::Node for Location {
    fn neighbors(&self) -> Vec<Location> {
        Dir6::iter().map(|d| self + d.to_v2()).collect()
    }
}
<|endoftext|>


<commit_before>use std::any::{Any, TypeId};
use std::error::Error;
use std::fmt;

use chrono::NaiveDateTime;
use conduit::Response;
use diesel::result::Error as DieselError;

use crate::util::json_response;

mod http;

/// Returns an error with status 200 and the provided description as JSON
///
/// This is for backwards compatibility with cargo endpoints.  For all other
/// endpoints, use helpers like `bad_request` or `server_error` which set a
/// correct status code.
pub fn cargo_err<S: ToString + ?Sized>(error: &S) -> Box<dyn AppError> {
    Box::new(http::Ok(error.to_string()))
}

// The following are intended to be used for errors being sent back to the Ember
// frontend, not to cargo as cargo does not handle non-200 response codes well
// (see <https://github.com/rust-lang/cargo/issues/3995>), but Ember requires
// non-200 response codes for its stores to work properly.

/// Returns an error with status 500 and the provided description as JSON
pub fn server_error<S: ToString + ?Sized>(error: &S) -> Box<dyn AppError> {
    Box::new(http::ServerError(error.to_string()))
}

#[derive(Serialize)]
struct StringError {
    detail: String,
}
#[derive(Serialize)]
struct Bad {
    errors: Vec<StringError>,
}

// =============================================================================
// AppError trait

pub trait AppError: Send + fmt::Display + fmt::Debug + 'static {
    fn cause(&self) -> Option<&(dyn AppError)> {
        None
    }

    /// Generate an HTTP response for the error
    ///
    /// If none is returned, the error will bubble up the middleware stack
    /// where it is eventually logged and turned into a status 500 response.
    fn response(&self) -> Option<Response>;

    fn get_type_id(&self) -> TypeId {
        TypeId::of::<Self>()
    }
}

impl dyn AppError {
    pub fn is<T: Any>(&self) -> bool {
        self.get_type_id() == TypeId::of::<T>()
    }

    pub fn from_std_error(err: Box<dyn Error + Send>) -> Box<dyn AppError> {
        Self::try_convert(&*err).unwrap_or_else(|| internal(&err))
    }

    fn try_convert(err: &(dyn Error + Send + 'static)) -> Option<Box<Self>> {
        match err.downcast_ref() {
            Some(DieselError::NotFound) => Some(Box::new(NotFound)),
            Some(DieselError::DatabaseError(_, info))
                if info.message().ends_with("read-only transaction") =>
            {
                Some(Box::new(ReadOnlyMode))
            }
            _ => None,
        }
    }
}

impl AppError for Box<dyn AppError> {
    fn cause(&self) -> Option<&dyn AppError> {
        (**self).cause()
    }
    fn response(&self) -> Option<Response> {
        (**self).response()
    }
}

pub type AppResult<T> = Result<T, Box<dyn AppError>>;

// =============================================================================
// Chaining errors

pub trait ChainError<T> {
    fn chain_error<E, F>(self, callback: F) -> AppResult<T>
    where
        E: AppError,
        F: FnOnce() -> E;
}

#[derive(Debug)]
struct ChainedError<E> {
    error: E,
    cause: Box<dyn AppError>,
}

impl<T, F> ChainError<T> for F
where
    F: FnOnce() -> AppResult<T>,
{
    fn chain_error<E, C>(self, callback: C) -> AppResult<T>
    where
        E: AppError,
        C: FnOnce() -> E,
    {
        self().chain_error(callback)
    }
}

impl<T, E: AppError> ChainError<T> for Result<T, E> {
    fn chain_error<E2, C>(self, callback: C) -> AppResult<T>
    where
        E2: AppError,
        C: FnOnce() -> E2,
    {
        self.map_err(move |err| {
            Box::new(ChainedError {
                error: callback(),
                cause: Box::new(err),
            }) as Box<dyn AppError>
        })
    }
}

impl<T> ChainError<T> for Option<T> {
    fn chain_error<E, C>(self, callback: C) -> AppResult<T>
    where
        E: AppError,
        C: FnOnce() -> E,
    {
        match self {
            Some(t) => Ok(t),
            None => Err(Box::new(callback())),
        }
    }
}

impl<E: AppError> AppError for ChainedError<E> {
    fn cause(&self) -> Option<&dyn AppError> {
        Some(&*self.cause)
    }
    fn response(&self) -> Option<Response> {
        self.error.response()
    }
}

impl<E: AppError> fmt::Display for ChainedError<E> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{} caused by {}", self.error, self.cause)
    }
}

// =============================================================================
// Error impls

impl<E: Error + Send + 'static> AppError for E {
    fn response(&self) -> Option<Response> {
        None
    }
}

impl<E: Error + Send + 'static> From<E> for Box<dyn AppError> {
    fn from(err: E) -> Box<dyn AppError> {
        AppError::try_convert(&err).unwrap_or_else(|| Box::new(err))
    }
}
// =============================================================================
// Concrete errors

#[derive(Debug)]
struct InternalAppError {
    description: String,
}

impl fmt::Display for InternalAppError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}", self.description)?;
        Ok(())
    }
}

impl AppError for InternalAppError {
    fn response(&self) -> Option<Response> {
        None
    }
}

#[derive(Debug, Clone, Copy)]
pub struct NotFound;

impl AppError for NotFound {
    fn response(&self) -> Option<Response> {
        let mut response = json_response(&Bad {
            errors: vec![StringError {
                detail: "Not Found".to_string(),
            }],
        });
        response.status = (404, "Not Found");
        Some(response)
    }
}

impl fmt::Display for NotFound {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        "Not Found".fmt(f)
    }
}

#[derive(Debug, Clone, Copy)]
pub struct Unauthorized;

impl AppError for Unauthorized {
    fn response(&self) -> Option<Response> {
        let mut response = json_response(&Bad {
            errors: vec![StringError {
                detail: "must be logged in to perform that action".to_string(),
            }],
        });
        response.status = (403, "Forbidden");
        Some(response)
    }
}

impl fmt::Display for Unauthorized {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        "must be logged in to perform that action".fmt(f)
    }
}

#[derive(Debug)]
struct BadRequest(String);

impl AppError for BadRequest {
    fn response(&self) -> Option<Response> {
        let mut response = json_response(&Bad {
            errors: vec![StringError {
                detail: self.0.clone(),
            }],
        });
        response.status = (400, "Bad Request");
        Some(response)
    }
}

impl fmt::Display for BadRequest {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        self.0.fmt(f)
    }
}

pub fn internal<S: ToString + ?Sized>(error: &S) -> Box<dyn AppError> {
    Box::new(InternalAppError {
        description: error.to_string(),
    })
}

/// This is intended to be used for errors being sent back to the Ember
/// frontend, not to cargo as cargo does not handle non-200 response codes well
/// (see <https://github.com/rust-lang/cargo/issues/3995>), but Ember requires
/// non-200 response codes for its stores to work properly.
///
/// Since this is going back to the UI these errors are treated the same as
/// `cargo_err` errors, other than the HTTP status code.
pub fn bad_request<S: ToString + ?Sized>(error: &S) -> Box<dyn AppError> {
    Box::new(BadRequest(error.to_string()))
}

#[derive(Debug)]
pub struct AppErrToStdErr(pub Box<dyn AppError>);

impl Error for AppErrToStdErr {}

impl fmt::Display for AppErrToStdErr {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}", self.0)?;

        let mut err = &*self.0;
        while let Some(cause) = err.cause() {
            err = cause;
            write!(f, "\nCaused by: {}", err)?;
        }

        Ok(())
    }
}

pub(crate) fn std_error(e: Box<dyn AppError>) -> Box<dyn Error + Send> {
    Box::new(AppErrToStdErr(e))
}

pub(crate) fn std_error_no_send(e: Box<dyn AppError>) -> Box<dyn Error> {
    Box::new(AppErrToStdErr(e))
}

#[derive(Debug, Clone, Copy)]
pub struct ReadOnlyMode;

impl AppError for ReadOnlyMode {
    fn response(&self) -> Option<Response> {
        let mut response = json_response(&Bad {
            errors: vec![StringError {
                detail: "Crates.io is currently in read-only mode for maintenance. \
                         Please try again later."
                    .to_string(),
            }],
        });
        response.status = (503, "Service Unavailable");
        Some(response)
    }
}

impl fmt::Display for ReadOnlyMode {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        "Tried to write in read only mode".fmt(f)
    }
}

#[derive(Debug, Clone, Copy)]
pub struct TooManyRequests {
    pub retry_after: NaiveDateTime,
}

impl AppError for TooManyRequests {
    fn response(&self) -> Option<Response> {
        const HTTP_DATE_FORMAT: &str = "%a, %d %b %Y %H:%M:%S GMT";
        let retry_after = self.retry_after.format(HTTP_DATE_FORMAT);

        let mut response = json_response(&Bad {
            errors: vec![StringError {
                detail: format!(
                    "You have published too many crates in a \
                     short period of time. Please try again after {} or email \
                     help@crates.io to have your limit increased.",
                    retry_after
                ),
            }],
        });
        response.status = (429, "TOO MANY REQUESTS");
        response
            .headers
            .insert("Retry-After".into(), vec![retry_after.to_string()]);
        Some(response)
    }
}

impl fmt::Display for TooManyRequests {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        "Too many requests".fmt(f)
    }
}
<commit_msg>Remove duplicate error "caused by" logging<commit_after>use std::any::{Any, TypeId};
use std::error::Error;
use std::fmt;

use chrono::NaiveDateTime;
use conduit::Response;
use diesel::result::Error as DieselError;

use crate::util::json_response;

mod http;

/// Returns an error with status 200 and the provided description as JSON
///
/// This is for backwards compatibility with cargo endpoints.  For all other
/// endpoints, use helpers like `bad_request` or `server_error` which set a
/// correct status code.
pub fn cargo_err<S: ToString + ?Sized>(error: &S) -> Box<dyn AppError> {
    Box::new(http::Ok(error.to_string()))
}

// The following are intended to be used for errors being sent back to the Ember
// frontend, not to cargo as cargo does not handle non-200 response codes well
// (see <https://github.com/rust-lang/cargo/issues/3995>), but Ember requires
// non-200 response codes for its stores to work properly.

/// Returns an error with status 500 and the provided description as JSON
pub fn server_error<S: ToString + ?Sized>(error: &S) -> Box<dyn AppError> {
    Box::new(http::ServerError(error.to_string()))
}

#[derive(Serialize)]
struct StringError {
    detail: String,
}
#[derive(Serialize)]
struct Bad {
    errors: Vec<StringError>,
}

// =============================================================================
// AppError trait

pub trait AppError: Send + fmt::Display + fmt::Debug + 'static {
    /// Generate an HTTP response for the error
    ///
    /// If none is returned, the error will bubble up the middleware stack
    /// where it is eventually logged and turned into a status 500 response.
    fn response(&self) -> Option<Response>;

    fn get_type_id(&self) -> TypeId {
        TypeId::of::<Self>()
    }
}

impl dyn AppError {
    pub fn is<T: Any>(&self) -> bool {
        self.get_type_id() == TypeId::of::<T>()
    }

    pub fn from_std_error(err: Box<dyn Error + Send>) -> Box<dyn AppError> {
        Self::try_convert(&*err).unwrap_or_else(|| internal(&err))
    }

    fn try_convert(err: &(dyn Error + Send + 'static)) -> Option<Box<Self>> {
        match err.downcast_ref() {
            Some(DieselError::NotFound) => Some(Box::new(NotFound)),
            Some(DieselError::DatabaseError(_, info))
                if info.message().ends_with("read-only transaction") =>
            {
                Some(Box::new(ReadOnlyMode))
            }
            _ => None,
        }
    }
}

impl AppError for Box<dyn AppError> {
    fn response(&self) -> Option<Response> {
        (**self).response()
    }
}

pub type AppResult<T> = Result<T, Box<dyn AppError>>;

// =============================================================================
// Chaining errors

pub trait ChainError<T> {
    fn chain_error<E, F>(self, callback: F) -> AppResult<T>
    where
        E: AppError,
        F: FnOnce() -> E;
}

#[derive(Debug)]
struct ChainedError<E> {
    error: E,
    cause: Box<dyn AppError>,
}

impl<T, F> ChainError<T> for F
where
    F: FnOnce() -> AppResult<T>,
{
    fn chain_error<E, C>(self, callback: C) -> AppResult<T>
    where
        E: AppError,
        C: FnOnce() -> E,
    {
        self().chain_error(callback)
    }
}

impl<T, E: AppError> ChainError<T> for Result<T, E> {
    fn chain_error<E2, C>(self, callback: C) -> AppResult<T>
    where
        E2: AppError,
        C: FnOnce() -> E2,
    {
        self.map_err(move |err| {
            Box::new(ChainedError {
                error: callback(),
                cause: Box::new(err),
            }) as Box<dyn AppError>
        })
    }
}

impl<T> ChainError<T> for Option<T> {
    fn chain_error<E, C>(self, callback: C) -> AppResult<T>
    where
        E: AppError,
        C: FnOnce() -> E,
    {
        match self {
            Some(t) => Ok(t),
            None => Err(Box::new(callback())),
        }
    }
}

impl<E: AppError> AppError for ChainedError<E> {
    fn response(&self) -> Option<Response> {
        self.error.response()
    }
}

impl<E: AppError> fmt::Display for ChainedError<E> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{} caused by {}", self.error, self.cause)
    }
}

// =============================================================================
// Error impls

impl<E: Error + Send + 'static> AppError for E {
    fn response(&self) -> Option<Response> {
        None
    }
}

impl<E: Error + Send + 'static> From<E> for Box<dyn AppError> {
    fn from(err: E) -> Box<dyn AppError> {
        AppError::try_convert(&err).unwrap_or_else(|| Box::new(err))
    }
}
// =============================================================================
// Concrete errors

#[derive(Debug)]
struct InternalAppError {
    description: String,
}

impl fmt::Display for InternalAppError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}", self.description)?;
        Ok(())
    }
}

impl AppError for InternalAppError {
    fn response(&self) -> Option<Response> {
        None
    }
}

#[derive(Debug, Clone, Copy)]
pub struct NotFound;

impl AppError for NotFound {
    fn response(&self) -> Option<Response> {
        let mut response = json_response(&Bad {
            errors: vec![StringError {
                detail: "Not Found".to_string(),
            }],
        });
        response.status = (404, "Not Found");
        Some(response)
    }
}

impl fmt::Display for NotFound {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        "Not Found".fmt(f)
    }
}

#[derive(Debug, Clone, Copy)]
pub struct Unauthorized;

impl AppError for Unauthorized {
    fn response(&self) -> Option<Response> {
        let mut response = json_response(&Bad {
            errors: vec![StringError {
                detail: "must be logged in to perform that action".to_string(),
            }],
        });
        response.status = (403, "Forbidden");
        Some(response)
    }
}

impl fmt::Display for Unauthorized {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        "must be logged in to perform that action".fmt(f)
    }
}

#[derive(Debug)]
struct BadRequest(String);

impl AppError for BadRequest {
    fn response(&self) -> Option<Response> {
        let mut response = json_response(&Bad {
            errors: vec![StringError {
                detail: self.0.clone(),
            }],
        });
        response.status = (400, "Bad Request");
        Some(response)
    }
}

impl fmt::Display for BadRequest {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        self.0.fmt(f)
    }
}

pub fn internal<S: ToString + ?Sized>(error: &S) -> Box<dyn AppError> {
    Box::new(InternalAppError {
        description: error.to_string(),
    })
}

/// This is intended to be used for errors being sent back to the Ember
/// frontend, not to cargo as cargo does not handle non-200 response codes well
/// (see <https://github.com/rust-lang/cargo/issues/3995>), but Ember requires
/// non-200 response codes for its stores to work properly.
///
/// Since this is going back to the UI these errors are treated the same as
/// `cargo_err` errors, other than the HTTP status code.
pub fn bad_request<S: ToString + ?Sized>(error: &S) -> Box<dyn AppError> {
    Box::new(BadRequest(error.to_string()))
}

#[derive(Debug)]
pub struct AppErrToStdErr(pub Box<dyn AppError>);

impl Error for AppErrToStdErr {}

impl fmt::Display for AppErrToStdErr {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        self.0.fmt(f)
    }
}

pub(crate) fn std_error(e: Box<dyn AppError>) -> Box<dyn Error + Send> {
    Box::new(AppErrToStdErr(e))
}

pub(crate) fn std_error_no_send(e: Box<dyn AppError>) -> Box<dyn Error> {
    Box::new(AppErrToStdErr(e))
}

#[derive(Debug, Clone, Copy)]
pub struct ReadOnlyMode;

impl AppError for ReadOnlyMode {
    fn response(&self) -> Option<Response> {
        let mut response = json_response(&Bad {
            errors: vec![StringError {
                detail: "Crates.io is currently in read-only mode for maintenance. \
                         Please try again later."
                    .to_string(),
            }],
        });
        response.status = (503, "Service Unavailable");
        Some(response)
    }
}

impl fmt::Display for ReadOnlyMode {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        "Tried to write in read only mode".fmt(f)
    }
}

#[derive(Debug, Clone, Copy)]
pub struct TooManyRequests {
    pub retry_after: NaiveDateTime,
}

impl AppError for TooManyRequests {
    fn response(&self) -> Option<Response> {
        const HTTP_DATE_FORMAT: &str = "%a, %d %b %Y %H:%M:%S GMT";
        let retry_after = self.retry_after.format(HTTP_DATE_FORMAT);

        let mut response = json_response(&Bad {
            errors: vec![StringError {
                detail: format!(
                    "You have published too many crates in a \
                     short period of time. Please try again after {} or email \
                     help@crates.io to have your limit increased.",
                    retry_after
                ),
            }],
        });
        response.status = (429, "TOO MANY REQUESTS");
        response
            .headers
            .insert("Retry-After".into(), vec![retry_after.to_string()]);
        Some(response)
    }
}

impl fmt::Display for TooManyRequests {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        "Too many requests".fmt(f)
    }
}
<|endoftext|>


<commit_before>// ignore-windows: File handling is not implemented yet
// compile-flags: -Zmiri-disable-isolation

use std::fs::{File, remove_file, rename};
use std::io::{Read, Write, ErrorKind, Result, Seek, SeekFrom};
use std::path::{PathBuf, Path};

fn test_metadata(bytes: &[u8], path: &Path) -> Result<()> {
    // Test that the file metadata is correct.
    let metadata = path.metadata()?;
    // `path` should point to a file.
    assert!(metadata.is_file());
    // The size of the file must be equal to the number of written bytes.
    assert_eq!(bytes.len() as u64, metadata.len());
    Ok(())
}

fn main() {
    let tmp = std::env::temp_dir();
    let filename = PathBuf::from("miri_test_fs.txt");
    let path = tmp.join(&filename);
    let symlink_path = tmp.join("miri_test_fs_symlink.txt");
    let bytes = b"Hello, World!\n";
    // Clean the paths for robustness.
    remove_file(&path).ok();
    remove_file(&symlink_path).ok();

    // Test creating, writing and closing a file (closing is tested when `file` is dropped).
    let mut file = File::create(&path).unwrap();
    // Writing 0 bytes should not change the file contents.
    file.write(&mut []).unwrap();
    assert_eq!(file.metadata().unwrap().len(), 0);

    file.write(bytes).unwrap();
    assert_eq!(file.metadata().unwrap().len(), bytes.len() as u64);
    // Test opening, reading and closing a file.
    let mut file = File::open(&path).unwrap();
    let mut contents = Vec::new();
    // Reading 0 bytes should not move the file pointer.
    file.read(&mut []).unwrap();
    // Reading until EOF should get the whole text.
    file.read_to_end(&mut contents).unwrap();
    assert_eq!(bytes, contents.as_slice());

    // Test that seeking to the beginning and reading until EOF gets the text again.
    file.seek(SeekFrom::Start(0)).unwrap();
    let mut contents = Vec::new();
    file.read_to_end(&mut contents).unwrap();
    assert_eq!(bytes, contents.as_slice());
    // Test seeking relative to the end of the file.
    file.seek(SeekFrom::End(-1)).unwrap();
    let mut contents = Vec::new();
    file.read_to_end(&mut contents).unwrap();
    assert_eq!(&bytes[bytes.len() - 1..], contents.as_slice());
    // Test seeking relative to the current position.
    file.seek(SeekFrom::Start(5)).unwrap();
    file.seek(SeekFrom::Current(-3)).unwrap();
    let mut contents = Vec::new();
    file.read_to_end(&mut contents).unwrap();
    assert_eq!(&bytes[2..], contents.as_slice());

    // Test that metadata of an absolute path is correct.
    test_metadata(bytes, &path).unwrap();
    // Test that metadata of a relative path is correct.
    std::env::set_current_dir(&tmp).unwrap();
    test_metadata(bytes, &filename).unwrap();

    // Creating a symbolic link should succeed.
    std::os::unix::fs::symlink(&path, &symlink_path).unwrap();
    // Test that the symbolic link has the same contents as the file.
    let mut symlink_file = File::open(&symlink_path).unwrap();
    let mut contents = Vec::new();
    symlink_file.read_to_end(&mut contents).unwrap();
    assert_eq!(bytes, contents.as_slice());
    // Test that metadata of a symbolic link is correct.
    test_metadata(bytes, &symlink_path).unwrap();
    // Test that the metadata of a symbolic link is correct when not following it.
    assert!(symlink_path.symlink_metadata().unwrap().file_type().is_symlink());
    // Removing symbolic link should succeed.
    remove_file(&symlink_path).unwrap();

    // Removing file should succeed.
    remove_file(&path).unwrap();

    // Renaming a file should succeed.
    let path1 = tmp.join("rename_source.txt");
    let path2 = tmp.join("rename_destination.txt");
    // Clean files for robustness.
    remove_file(&path1).ok();
    remove_file(&path2).ok();
    let file = File::create(&path1).unwrap();
    drop(file);
    rename(&path1, &path2).unwrap();
    assert!(path2.metadata().unwrap().is_file());
    remove_file(&path2).ok();

    // The two following tests also check that the `__errno_location()` shim is working properly.
    // Opening a non-existing file should fail with a "not found" error.
    assert_eq!(ErrorKind::NotFound, File::open(&path).unwrap_err().kind());
    // Removing a non-existing file should fail with a "not found" error.
    assert_eq!(ErrorKind::NotFound, remove_file(&path).unwrap_err().kind());
    // Reading the metadata of a non-existing file should fail with a "not found" error.
    assert_eq!(ErrorKind::NotFound, test_metadata(bytes, &path).unwrap_err().kind());
}
<commit_msg>Test that src path of rename is no longer a file<commit_after>// ignore-windows: File handling is not implemented yet
// compile-flags: -Zmiri-disable-isolation

use std::fs::{File, remove_file, rename};
use std::io::{Read, Write, ErrorKind, Result, Seek, SeekFrom};
use std::path::{PathBuf, Path};

fn test_metadata(bytes: &[u8], path: &Path) -> Result<()> {
    // Test that the file metadata is correct.
    let metadata = path.metadata()?;
    // `path` should point to a file.
    assert!(metadata.is_file());
    // The size of the file must be equal to the number of written bytes.
    assert_eq!(bytes.len() as u64, metadata.len());
    Ok(())
}

fn main() {
    let tmp = std::env::temp_dir();
    let filename = PathBuf::from("miri_test_fs.txt");
    let path = tmp.join(&filename);
    let symlink_path = tmp.join("miri_test_fs_symlink.txt");
    let bytes = b"Hello, World!\n";
    // Clean the paths for robustness.
    remove_file(&path).ok();
    remove_file(&symlink_path).ok();

    // Test creating, writing and closing a file (closing is tested when `file` is dropped).
    let mut file = File::create(&path).unwrap();
    // Writing 0 bytes should not change the file contents.
    file.write(&mut []).unwrap();
    assert_eq!(file.metadata().unwrap().len(), 0);

    file.write(bytes).unwrap();
    assert_eq!(file.metadata().unwrap().len(), bytes.len() as u64);
    // Test opening, reading and closing a file.
    let mut file = File::open(&path).unwrap();
    let mut contents = Vec::new();
    // Reading 0 bytes should not move the file pointer.
    file.read(&mut []).unwrap();
    // Reading until EOF should get the whole text.
    file.read_to_end(&mut contents).unwrap();
    assert_eq!(bytes, contents.as_slice());

    // Test that seeking to the beginning and reading until EOF gets the text again.
    file.seek(SeekFrom::Start(0)).unwrap();
    let mut contents = Vec::new();
    file.read_to_end(&mut contents).unwrap();
    assert_eq!(bytes, contents.as_slice());
    // Test seeking relative to the end of the file.
    file.seek(SeekFrom::End(-1)).unwrap();
    let mut contents = Vec::new();
    file.read_to_end(&mut contents).unwrap();
    assert_eq!(&bytes[bytes.len() - 1..], contents.as_slice());
    // Test seeking relative to the current position.
    file.seek(SeekFrom::Start(5)).unwrap();
    file.seek(SeekFrom::Current(-3)).unwrap();
    let mut contents = Vec::new();
    file.read_to_end(&mut contents).unwrap();
    assert_eq!(&bytes[2..], contents.as_slice());

    // Test that metadata of an absolute path is correct.
    test_metadata(bytes, &path).unwrap();
    // Test that metadata of a relative path is correct.
    std::env::set_current_dir(&tmp).unwrap();
    test_metadata(bytes, &filename).unwrap();

    // Creating a symbolic link should succeed.
    std::os::unix::fs::symlink(&path, &symlink_path).unwrap();
    // Test that the symbolic link has the same contents as the file.
    let mut symlink_file = File::open(&symlink_path).unwrap();
    let mut contents = Vec::new();
    symlink_file.read_to_end(&mut contents).unwrap();
    assert_eq!(bytes, contents.as_slice());
    // Test that metadata of a symbolic link is correct.
    test_metadata(bytes, &symlink_path).unwrap();
    // Test that the metadata of a symbolic link is correct when not following it.
    assert!(symlink_path.symlink_metadata().unwrap().file_type().is_symlink());
    // Removing symbolic link should succeed.
    remove_file(&symlink_path).unwrap();

    // Removing file should succeed.
    remove_file(&path).unwrap();

    // Renaming a file should succeed.
    let path1 = tmp.join("rename_source.txt");
    let path2 = tmp.join("rename_destination.txt");
    // Clean files for robustness.
    remove_file(&path1).ok();
    remove_file(&path2).ok();
    let file = File::create(&path1).unwrap();
    drop(file);
    rename(&path1, &path2).unwrap();
    assert_eq!(ErrorKind::NotFound, path1.metadata().unwrap_err().kind());
    assert!(path2.metadata().unwrap().is_file());
    remove_file(&path2).ok();

    // The two following tests also check that the `__errno_location()` shim is working properly.
    // Opening a non-existing file should fail with a "not found" error.
    assert_eq!(ErrorKind::NotFound, File::open(&path).unwrap_err().kind());
    // Removing a non-existing file should fail with a "not found" error.
    assert_eq!(ErrorKind::NotFound, remove_file(&path).unwrap_err().kind());
    // Reading the metadata of a non-existing file should fail with a "not found" error.
    assert_eq!(ErrorKind::NotFound, test_metadata(bytes, &path).unwrap_err().kind());
}
<|endoftext|>


<commit_before>use std::ops::{Index, IndexMut};

use Dimensions;
use Storage;

/// An array with owned storage.
pub type Array<T, D> = ArrayBase<Box<[T]>, D>;

#[derive(Debug)]
/// ArrayBase implements all the operations on arrays, using a `Storage` and
/// some `Dimensions`.
pub struct ArrayBase<S, D> where D: Dimensions, S: Storage {
    data: S,
    dims: D,
}

impl<S, D> ArrayBase<S, D> where D: Dimensions, S: Storage {
    /// Create a new array using content from the vector.
    ///
    /// ```
    /// use mudi::Array;
    /// // One-dimensional array, with shape (4).
    /// let array = Array::from_vector(vec![1, 2, 3, 4], 4);
    /// assert_eq!(array[2], 3);
    ///
    /// // Two-dimensional array, with shape (2, 2)
    /// let array = Array::from_vector(vec![1, 2, 3, 4], (2, 2));
    /// assert_eq!(array[(1, 0)], 3);
    /// ```
    ///
    /// # Panics
    /// If the size of the vector does not match the size of the dimensions.
    ///
    /// ```should_panic
    /// use mudi::Array;
    /// // The dimension size is 14 here, and the array only contains 4 elements
    /// let array = Array::from_vector(vec![1, 2, 3, 4], (2, 7));
    /// ```
    pub fn from_vector(vec: Vec<S::Item>, dims: D) -> ArrayBase<S, D> {
        assert!(vec.len() == dims.size(), "Data length does not match the dimensions");
        ArrayBase {
            data: S::from_vec(vec),
            dims: dims,
        }
    }

    /// Get the shape of the array.
    ///
    /// ```
    /// use mudi::Array;
    /// let array = Array::from_vector(vec![1, 2, 3, 4], 4);
    /// assert_eq!(array.shape(), 4);
    ///
    /// let array = Array::from_element(vec![1, 2, 3, 4], (2, 7));
    /// assert_eq!(array.shape(), (2, 7));
    /// ```
    pub fn shape(&self) -> D {
        self.dims.clone()
    }
}

impl<S, D> ArrayBase<S, D> where D: Dimensions, S: Storage, S::Item: Clone {
    /// Create a new array by cloning a specific element as needed.
    ///
    /// ```
    /// use mudi::Array;
    /// // Two-dimensional array, with shape (2, 6)
    /// let array = Array::from_element(42, (2, 6));
    /// assert_eq!(array[(1, 4)], 42);
    /// ```
    pub fn from_element(element: S::Item, dims: D) -> ArrayBase<S, D> {
        let data = vec![element; dims.size()];
        ArrayBase {
            data: S::from_vec(data),
            dims: dims,
        }
    }
}

impl<S, D, I: Copy> Index<I> for ArrayBase<S, D>
    where D: Dimensions<Index = I>, S: Storage {
    type Output = S::Item;
    fn index(&self, index: I) -> &S::Item {
        &self.data.as_ref()[self.dims.offset(index)]
    }
}

impl<S, D, I: Copy> IndexMut<I> for ArrayBase<S, D>
    where D: Dimensions<Index = I>, S: Storage {
    fn index_mut(&mut self, index: I) -> &mut S::Item {
        &mut self.data.as_mut()[self.dims.offset(index)]
    }
}

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

    #[test]
    fn indexing() {
        let mut a = Array::from_vector(vec![3, 4, 5], 3);

        assert_eq!(a[0], 3);
        assert_eq!(a[1], 4);
        assert_eq!(a[2], 5);

        a[2] = 42;
        assert_eq!(a[2], 42);
    }

    #[test]
    fn from_vector() {
        let mut a = Array::from_vector(vec![3, 4, 5, 78], 4);
        assert_eq!(a[3], 78);
        a[3] = 42;
        assert_eq!(a[3], 42);
    }

    #[test]
    fn from_element() {
        let mut a = Array::from_element(678, (7, 7));
        assert_eq!(a[(3, 4)], 678);
        a[(3, 4)] = 42;
        assert_eq!(a[(3, 4)], 42);
    }

    #[test]
    fn shape() {
        let a = Array::from_element(678, (7, 7));
        assert_eq!(a.shape(), (7, 7));

        let a = Array::from_element(678, (7, 7..10));
        assert_eq!(a.shape(), (7, 7..10));
    }
}
<commit_msg>Add linear iteration over the arrays<commit_after>use std::ops::{Index, IndexMut};
use std::slice::{Iter, IterMut};

use Dimensions;
use Storage;

/// An array with owned storage.
pub type Array<T, D> = ArrayBase<Box<[T]>, D>;

#[derive(Debug)]
/// ArrayBase implements all the operations on arrays, using a `Storage` and
/// some `Dimensions`.
pub struct ArrayBase<S, D> where D: Dimensions, S: Storage {
    data: S,
    dims: D,
}

impl<S, D> ArrayBase<S, D> where D: Dimensions, S: Storage {
    /// Create a new array using content from the vector.
    ///
    /// ```
    /// use mudi::Array;
    /// // One-dimensional array, with shape (4).
    /// let array = Array::from_vector(vec![1, 2, 3, 4], 4);
    /// assert_eq!(array[2], 3);
    ///
    /// // Two-dimensional array, with shape (2, 2)
    /// let array = Array::from_vector(vec![1, 2, 3, 4], (2, 2));
    /// assert_eq!(array[(1, 0)], 3);
    /// ```
    ///
    /// # Panics
    /// If the size of the vector does not match the size of the dimensions.
    ///
    /// ```should_panic
    /// use mudi::Array;
    /// // The dimension size is 14 here, and the array only contains 4 elements
    /// let array = Array::from_vector(vec![1, 2, 3, 4], (2, 7));
    /// ```
    pub fn from_vector(vec: Vec<S::Item>, dims: D) -> ArrayBase<S, D> {
        assert!(vec.len() == dims.size(), "Data length does not match the dimensions");
        ArrayBase {
            data: S::from_vec(vec),
            dims: dims,
        }
    }

    /// Get the shape of the array.
    ///
    /// ```
    /// use mudi::Array;
    /// let array = Array::from_vector(vec![1, 2, 3, 4], 4);
    /// assert_eq!(array.shape(), 4);
    ///
    /// let array = Array::from_element(vec![1, 2, 3, 4], (2, 7));
    /// assert_eq!(array.shape(), (2, 7));
    /// ```
    pub fn shape(&self) -> D {
        self.dims.clone()
    }

    /// Flat (linear) iteration over array elements.
    ///
    /// ```
    /// use mudi::Array;
    /// let mut array = Array::from_element(0, (3, 2));
    /// for i in 0..3 {
    ///     for j in 0..2 {
    ///         array[(i, j)] = i;
    ///     }
    /// }
    ///
    /// for value in array.flat_iter() {
    ///     print!("{} ", value);
    /// }
    /// // This will print "0 0 1 1 2 2"
    /// ```
    pub fn flat_iter(&self) -> Iter<S::Item> {
        self.data.as_ref().iter()
    }

    /// Flat (linear) iteration over mutable array elements. See the
    /// documentation for [`Array::flat_iter`](#method.flat_iter).
    pub fn flat_iter_mut(&mut self) -> IterMut<S::Item> {
        self.data.as_mut().iter_mut()
    }
}

impl<S, D> ArrayBase<S, D> where D: Dimensions, S: Storage, S::Item: Clone {
    /// Create a new array by cloning a specific element as needed.
    ///
    /// ```
    /// use mudi::Array;
    /// // Two-dimensional array, with shape (2, 6)
    /// let array = Array::from_element(42, (2, 6));
    /// assert_eq!(array[(1, 4)], 42);
    /// ```
    pub fn from_element(element: S::Item, dims: D) -> ArrayBase<S, D> {
        let data = vec![element; dims.size()];
        ArrayBase {
            data: S::from_vec(data),
            dims: dims,
        }
    }
}

impl<S, D, I: Copy> Index<I> for ArrayBase<S, D>
    where D: Dimensions<Index = I>, S: Storage {
    type Output = S::Item;
    fn index(&self, index: I) -> &S::Item {
        &self.data.as_ref()[self.dims.offset(index)]
    }
}

impl<S, D, I: Copy> IndexMut<I> for ArrayBase<S, D>
    where D: Dimensions<Index = I>, S: Storage {
    fn index_mut(&mut self, index: I) -> &mut S::Item {
        &mut self.data.as_mut()[self.dims.offset(index)]
    }
}

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

    #[test]
    fn indexing() {
        let mut a = Array::from_vector(vec![3, 4, 5], 3);

        assert_eq!(a[0], 3);
        assert_eq!(a[1], 4);
        assert_eq!(a[2], 5);

        a[2] = 42;
        assert_eq!(a[2], 42);
    }

    #[test]
    fn from_vector() {
        let mut a = Array::from_vector(vec![3, 4, 5, 78], 4);
        assert_eq!(a[3], 78);
        a[3] = 42;
        assert_eq!(a[3], 42);
    }

    #[test]
    fn from_element() {
        let mut a = Array::from_element(678, (7, 7));
        assert_eq!(a[(3, 4)], 678);
        a[(3, 4)] = 42;
        assert_eq!(a[(3, 4)], 42);
    }

    #[test]
    fn shape() {
        let a = Array::from_element(678, (7, 7));
        assert_eq!(a.shape(), (7, 7));

        let a = Array::from_element(678, (7, 7..10));
        assert_eq!(a.shape(), (7, 7..10));
    }
}
<|endoftext|>


<commit_before>extern mod extra;

use std::comm::SharedChan;
use std::io::{Listener, Acceptor, Writer};
use std::io::net::ip::SocketAddr;
use std::io::io_error;
use extra::time::precise_time_ns;

use std::io::net::tcp::TcpListener;

use buffer::BufferedStream;

pub use self::request::{RequestBuffer, Request};
pub use self::response::ResponseWriter;

pub mod request;
pub mod response;

// TODO: when mozilla/rust#7661 is resolved, assuming also that specifying inheritance of kinds for
// the trait works:
// - Scrap ServerUtil (including any using it into the local scope)
// - Change "trait Server" to "trait Server: Send"
// - Shift the serve_forever method into Server
pub trait Server {
	fn handle_request(&self, request: &Request, response: &mut ResponseWriter) -> ();

	// XXX: this could also be implemented on the serve methods
	fn get_config(&self) -> Config;
}

/// A temporary trait to fix current deficiencies in Rust's default methods on traits.
/// You'll need to import `ServerUtil` to be able to call `serve_forever` on a Server.
pub trait ServerUtil {
    fn serve_forever(self);
}

impl<T: Send + Clone + Server> ServerUtil for T {
	/**
	 * Attempt to bind to the address and port and start serving forever.
	 *
	 * This will only return if the initial connection fails or something else blows up.
	 */
    fn serve_forever(self) {
        let config = self.get_config();
        debug!("About to bind to {:?}", config.bind_address);
        match TcpListener::bind(config.bind_address).listen() {
            None => {
                error!("bind or listen failed :-(");
                return;
            },
            Some(ref mut acceptor) => {
                debug!("listening");
                let (perf_po, perf_ch) = stream();
                let perf_ch = SharedChan::new(perf_ch);
                do spawn {
                    perf_dumper(perf_po);
                }
                loop {
                    // OK, we're sort of shadowing an IoError here. Perhaps this should be done in a
                    // separate task so that it can safely fail...
                    let mut error = None;
                    let optstream = io_error::cond.trap(|e| {
                        error = Some(e);
                    }).inside(|| {
                        acceptor.accept()
                    });

                    let time_start = precise_time_ns();
                    if optstream.is_none() {
                        debug!("accept failed: {:?}", error);
                        // Question: is this the correct thing to do? We should probably be more
                        // intelligent, for there are some accept failures that are likely to be
                        // permanent, such that continuing would be a very bad idea, such as
                        // ENOBUFS/ENOMEM; and some where it should just be ignored, e.g.
                        // ECONNABORTED. TODO.
                        continue;
                    }
                    let child_perf_ch = perf_ch.clone();
                    let child_self = self.clone();
                    do spawn {
                        let mut time_start = time_start;
                        let mut stream = BufferedStream::new(optstream.unwrap());
                        debug!("accepted connection, got {:?}", stream);
                        loop {  // A keep-alive loop, condition at end
                            let time_spawned = precise_time_ns();
                            let (request, err_status) = Request::load(&mut stream);
                            let time_request_made = precise_time_ns();
                            let mut response = ~ResponseWriter::new(&mut stream, request);
                            let time_response_made = precise_time_ns();
                            match err_status {
                                Ok(()) => {
                                    child_self.handle_request(request, response);
                                    // Ensure that we actually do send a response:
                                    response.try_write_headers();
                                },
                                Err(status) => {
                                    // Uh oh, it's a response that I as a server cannot cope with.
                                    // No good user-agent should have caused this, so for the moment
                                    // at least I am content to send no body in the response.
                                    response.status = status;
                                    response.headers.content_length = Some(0);
                                    response.write_headers();
                                },
                            }
                            // Ensure the request is flushed, any Transfer-Encoding completed, etc.
                            response.finish_response();
                            let time_finished = precise_time_ns();
                            child_perf_ch.send((time_start, time_spawned, time_request_made, time_response_made, time_finished));

                            // Subsequent requests on this connection have no spawn time
                            time_start = time_finished;

                            if request.close_connection {
                                break;
                            }
                        }
                    }
                }
            }
        }
    }
}

/// The necessary configuration for an HTTP server.
///
/// At present, only the IP address and port to bind to are needed, but it's possible that other
/// options may turn up later.
pub struct Config {
	bind_address: SocketAddr,
}

/* Sorry, but Rust isn't ready for this yet; SimpleServer can't be made Clone just yet. (For
 * starters, ~fn() isn't cloneable.)

/// A simple `Server`-implementing class, allowing code to be written in an imperative style.
pub struct SimpleServer {
    config: Config,
    handler: ~fn(&Request, &mut ResponseWriter),
}

impl SimpleServer {
    /// Create a new `SimpleServer` instance with the provided members.
    pub fn new(config: Config, handler: ~fn(&Request, &mut ResponseWriter)) -> SimpleServer {
        SimpleServer {
            config: config,
            handler: handler,
        }
    }
}

impl Server for SimpleServer {
    /// Handles a request by passing it on to the structure's handler function.
    #[inline]
	pub fn handle_request(&self, request: &Request, response: &mut ResponseWriter) {
        (self.handler)(request, response);
    }

    /// Returns the structure's known config.
    #[inline]
	pub fn get_config(&self) -> Config {
        self.config
    }
}

/// Create a simple server and immediately start serving forever.
///
/// This is equivalent to
///
/// ~~~ {.rust}
/// SimpleServer::new(Config { bind_address: socket_addr }, handler).serve_forever();
/// ~~~
///
/// But it's nicer this way with `do` blocks and closures:
///
/// ~~~ {.rust}
/// do serve_forever(socket_addr) |r, mut w| {
///     // Now you can handle the request here and write the wresponse.
/// }
/// ~~~
///
/// The signature of this method is liable to change if `Config` gets more members.
// Please, pretty please, don't correct the word "wresponse".
#[inline]
pub fn serve_forever(socket_addr: SocketAddr, handler: ~fn(&Request, &mut ResponseWriter)) {
    SimpleServer::new(Config { bind_address: socket_addr }, handler).serve_forever();
}

/// 0.0.0.0, port 80: publicly bound to the standard HTTP port.
/// Not recommended at present as this server is not hardened against the sort of traffic you may
/// encounter on the Internet and is vulnerable to various DoS attacks. Sit it behind a gateway.
static PUBLIC: SocketAddr = SocketAddr { ip: Ipv4Addr(0, 0, 0, 0), port: 80 };
*/

static PERF_DUMP_FREQUENCY : u64 = 10_000;

/// Simple function to dump out perf stats every `PERF_DUMP_FREQUENCY` requests
fn perf_dumper(perf_po: Port<(u64, u64, u64, u64, u64)>) {
    // Total durations
    let mut td_spawn = 0u64;
    let mut td_request = 0u64;
    let mut td_response = 0u64;
    let mut td_handle = 0u64;
    let mut td_total = 0u64;
    let mut i = 0u64;
    loop {
        let data = perf_po.recv();
        let (start, spawned, request_made, response_made, finished) = data;
        td_spawn += spawned - start;
        td_request += request_made - spawned;
        td_response += response_made - request_made;
        td_handle += finished - response_made;
        td_total += finished - start;
        i += 1;
        if i % PERF_DUMP_FREQUENCY == 0 {
            println("");
            println!("{} requests made thus far. Current means:", i);
            println!("- Total:               100%, {:12f}",
                     td_total as f64 / i as f64);
            println!("- Spawn:               {:3f}%, {:12f}",
                     100f64 * td_spawn as f64 / td_total as f64,
                     td_spawn as f64 / i as f64);
            println!("- Load request:        {:3f}%, {:12f}",
                     100f64 * td_request as f64 / td_total as f64,
                     td_request as f64 / i as f64);
            println!("- Initialise response: {:3f}%, {:12f}",
                     100f64 * td_response as f64 / td_total as f64,
                     td_response as f64 / i as f64);
            println!("- Handle:              {:3f}%, {:12f}",
                     100f64 * td_handle as f64 / td_total as f64,
                     td_handle as f64 / i as f64);
        }
    }
}
<commit_msg>Remove the commented-out SimpleServer.<commit_after>extern mod extra;

use std::comm::SharedChan;
use std::io::{Listener, Acceptor, Writer};
use std::io::net::ip::SocketAddr;
use std::io::io_error;
use extra::time::precise_time_ns;

use std::io::net::tcp::TcpListener;

use buffer::BufferedStream;

pub use self::request::{RequestBuffer, Request};
pub use self::response::ResponseWriter;

pub mod request;
pub mod response;

// TODO: when mozilla/rust#7661 is resolved, assuming also that specifying inheritance of kinds for
// the trait works:
// - Scrap ServerUtil (including any using it into the local scope)
// - Change "trait Server" to "trait Server: Send"
// - Shift the serve_forever method into Server
pub trait Server {
	fn handle_request(&self, request: &Request, response: &mut ResponseWriter) -> ();

	// XXX: this could also be implemented on the serve methods
	fn get_config(&self) -> Config;
}

/// A temporary trait to fix current deficiencies in Rust's default methods on traits.
/// You'll need to import `ServerUtil` to be able to call `serve_forever` on a Server.
pub trait ServerUtil {
    fn serve_forever(self);
}

impl<T: Send + Clone + Server> ServerUtil for T {
	/**
	 * Attempt to bind to the address and port and start serving forever.
	 *
	 * This will only return if the initial connection fails or something else blows up.
	 */
    fn serve_forever(self) {
        let config = self.get_config();
        debug!("About to bind to {:?}", config.bind_address);
        match TcpListener::bind(config.bind_address).listen() {
            None => {
                error!("bind or listen failed :-(");
                return;
            },
            Some(ref mut acceptor) => {
                debug!("listening");
                let (perf_po, perf_ch) = stream();
                let perf_ch = SharedChan::new(perf_ch);
                do spawn {
                    perf_dumper(perf_po);
                }
                loop {
                    // OK, we're sort of shadowing an IoError here. Perhaps this should be done in a
                    // separate task so that it can safely fail...
                    let mut error = None;
                    let optstream = io_error::cond.trap(|e| {
                        error = Some(e);
                    }).inside(|| {
                        acceptor.accept()
                    });

                    let time_start = precise_time_ns();
                    if optstream.is_none() {
                        debug!("accept failed: {:?}", error);
                        // Question: is this the correct thing to do? We should probably be more
                        // intelligent, for there are some accept failures that are likely to be
                        // permanent, such that continuing would be a very bad idea, such as
                        // ENOBUFS/ENOMEM; and some where it should just be ignored, e.g.
                        // ECONNABORTED. TODO.
                        continue;
                    }
                    let child_perf_ch = perf_ch.clone();
                    let child_self = self.clone();
                    do spawn {
                        let mut time_start = time_start;
                        let mut stream = BufferedStream::new(optstream.unwrap());
                        debug!("accepted connection, got {:?}", stream);
                        loop {  // A keep-alive loop, condition at end
                            let time_spawned = precise_time_ns();
                            let (request, err_status) = Request::load(&mut stream);
                            let time_request_made = precise_time_ns();
                            let mut response = ~ResponseWriter::new(&mut stream, request);
                            let time_response_made = precise_time_ns();
                            match err_status {
                                Ok(()) => {
                                    child_self.handle_request(request, response);
                                    // Ensure that we actually do send a response:
                                    response.try_write_headers();
                                },
                                Err(status) => {
                                    // Uh oh, it's a response that I as a server cannot cope with.
                                    // No good user-agent should have caused this, so for the moment
                                    // at least I am content to send no body in the response.
                                    response.status = status;
                                    response.headers.content_length = Some(0);
                                    response.write_headers();
                                },
                            }
                            // Ensure the request is flushed, any Transfer-Encoding completed, etc.
                            response.finish_response();
                            let time_finished = precise_time_ns();
                            child_perf_ch.send((time_start, time_spawned, time_request_made, time_response_made, time_finished));

                            // Subsequent requests on this connection have no spawn time
                            time_start = time_finished;

                            if request.close_connection {
                                break;
                            }
                        }
                    }
                }
            }
        }
    }
}

/// The necessary configuration for an HTTP server.
///
/// At present, only the IP address and port to bind to are needed, but it's possible that other
/// options may turn up later.
pub struct Config {
	bind_address: SocketAddr,
}

static PERF_DUMP_FREQUENCY : u64 = 10_000;

/// Simple function to dump out perf stats every `PERF_DUMP_FREQUENCY` requests
fn perf_dumper(perf_po: Port<(u64, u64, u64, u64, u64)>) {
    // Total durations
    let mut td_spawn = 0u64;
    let mut td_request = 0u64;
    let mut td_response = 0u64;
    let mut td_handle = 0u64;
    let mut td_total = 0u64;
    let mut i = 0u64;
    loop {
        let data = perf_po.recv();
        let (start, spawned, request_made, response_made, finished) = data;
        td_spawn += spawned - start;
        td_request += request_made - spawned;
        td_response += response_made - request_made;
        td_handle += finished - response_made;
        td_total += finished - start;
        i += 1;
        if i % PERF_DUMP_FREQUENCY == 0 {
            println("");
            println!("{} requests made thus far. Current means:", i);
            println!("- Total:               100%, {:12f}",
                     td_total as f64 / i as f64);
            println!("- Spawn:               {:3f}%, {:12f}",
                     100f64 * td_spawn as f64 / td_total as f64,
                     td_spawn as f64 / i as f64);
            println!("- Load request:        {:3f}%, {:12f}",
                     100f64 * td_request as f64 / td_total as f64,
                     td_request as f64 / i as f64);
            println!("- Initialise response: {:3f}%, {:12f}",
                     100f64 * td_response as f64 / td_total as f64,
                     td_response as f64 / i as f64);
            println!("- Handle:              {:3f}%, {:12f}",
                     100f64 * td_handle as f64 / td_total as f64,
                     td_handle as f64 / i as f64);
        }
    }
}
<|endoftext|>


<commit_before>use common::util::*;

static UTIL_NAME: &'static str = "base64";

#[test]
fn test_encode() {
    let (_, mut ucmd) = testing(UTIL_NAME);
    let input = "hello, world!";
    ucmd.run_piped_stdin(input.as_bytes())
        .success()
        .stdout_only("aGVsbG8sIHdvcmxkIQ==\n");
}

#[test]
fn test_decode() {
    for decode_param in vec!["-d", "--decode"] {
        let (_, mut ucmd) = testing(UTIL_NAME);
        let input = "aGVsbG8sIHdvcmxkIQ==";
        ucmd.arg(decode_param).run_piped_stdin(input.as_bytes())
            .success()
            .stdout_only("hello, world!");
    }
}

#[test]
fn test_garbage() {
    let (_, mut ucmd) = testing(UTIL_NAME);
    let input = "aGVsbG8sIHdvcmxkIQ==\0";
    ucmd.arg("-d").run_piped_stdin(input.as_bytes())
        .failure()
        .stderr_only("base64: error: invalid character (Invalid character '0' at position 20)\n");
}

#[test]
fn test_ignore_garbage() {
    for ignore_garbage_param in vec!["-i", "--ignore-garbage"] {
        let (_, mut ucmd) = testing(UTIL_NAME);
        let input = "aGVsbG8sIHdvcmxkIQ==\0";
        ucmd.arg("-d").arg(ignore_garbage_param).run_piped_stdin(input.as_bytes())
            .success()
            .stdout_only("hello, world!");
    }
}

#[test]
fn test_wrap() {
    for wrap_param in vec!["-w", "--wrap"] {
        let (_, mut ucmd) = testing(UTIL_NAME);
        let input = "The quick brown fox jumps over the lazy dog.";
        ucmd.arg(wrap_param).arg("20").run_piped_stdin(input.as_bytes())
            .success()
            .stdout_only("VGhlIHF1aWNrIGJyb3du\nIGZveCBqdW1wcyBvdmVy\nIHRoZSBsYXp5IGRvZy4=\n");
    }
}

#[test]
fn test_wrap_no_arg() {
    for wrap_param in vec!["-w", "--wrap"] {
        let (_, mut ucmd) = testing(UTIL_NAME);
        ucmd.arg(wrap_param).run()
            .failure()
            .stderr_only(
                format!("base64: error: Argument to option '{}' missing.",
                        if wrap_param == "-w" { "w" } else { "wrap" }));
    }
}

#[test]
fn test_wrap_bad_arg() {
    for wrap_param in vec!["-w", "--wrap"] {
        let (_, mut ucmd) = testing(UTIL_NAME);
        ucmd.arg(wrap_param).arg("b").run()
            .failure()
            .stderr_only("base64: error: Argument to option 'wrap' improperly formatted: invalid digit found in string");
    }
}
<commit_msg>tests: base64 minor refactor for dryness<commit_after>use common::util::*;

static UTIL_NAME: &'static str = "base64";

#[test]
fn test_encode() {
    let (_, mut ucmd) = testing(UTIL_NAME);
    let input = "hello, world!";
    ucmd.pipe_in(input)
        .succeeds()
        .stdout_only("aGVsbG8sIHdvcmxkIQ==\n");
}

#[test]
fn test_decode() {
    for decode_param in vec!["-d", "--decode"] {
        let (_, mut ucmd) = testing(UTIL_NAME);
        let input = "aGVsbG8sIHdvcmxkIQ==";
        ucmd.arg(decode_param)
            .pipe_in(input)
            .succeeds()
            .stdout_only("hello, world!");
    }
}

#[test]
fn test_garbage() {
    let (_, mut ucmd) = testing(UTIL_NAME);
    let input = "aGVsbG8sIHdvcmxkIQ==\0";
    ucmd.arg("-d")
        .pipe_in(input)
        .fails()
        .stderr_only("base64: error: invalid character (Invalid character '0' at position 20)\n");
}

#[test]
fn test_ignore_garbage() {
    for ignore_garbage_param in vec!["-i", "--ignore-garbage"] {
        let (_, mut ucmd) = testing(UTIL_NAME);
        let input = "aGVsbG8sIHdvcmxkIQ==\0";
        ucmd.arg("-d").arg(ignore_garbage_param)
            .pipe_in(input)
            .succeeds()
            .stdout_only("hello, world!");
    }
}

#[test]
fn test_wrap() {
    for wrap_param in vec!["-w", "--wrap"] {
        let (_, mut ucmd) = testing(UTIL_NAME);
        let input = "The quick brown fox jumps over the lazy dog.";
        ucmd.arg(wrap_param).arg("20")
            .pipe_in(input)
            .succeeds()
            .stdout_only("VGhlIHF1aWNrIGJyb3du\nIGZveCBqdW1wcyBvdmVy\nIHRoZSBsYXp5IGRvZy4=\n");
    }
}

#[test]
fn test_wrap_no_arg() {
    for wrap_param in vec!["-w", "--wrap"] {
        let (_, mut ucmd) = testing(UTIL_NAME);
        ucmd.arg(wrap_param)
            .fails()
            .stderr_only(
                format!("base64: error: Argument to option '{}' missing.",
                        if wrap_param == "-w" { "w" } else { "wrap" }));
    }
}

#[test]
fn test_wrap_bad_arg() {
    for wrap_param in vec!["-w", "--wrap"] {
        let (_, mut ucmd) = testing(UTIL_NAME);
        ucmd.arg(wrap_param).arg("b")
            .fails()
            .stderr_only("base64: error: Argument to option 'wrap' improperly formatted: invalid digit found in string");
    }
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) Meta Platforms, Inc. and affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

use common::NamedItem;
use graphql_ir::{FragmentDefinition, OperationDefinition};
use graphql_syntax::OperationKind;
use relay_transforms::{RefetchableMetadata, INLINE_DIRECTIVE_NAME};
use relay_typegen::has_raw_response_type_directive;

/// Specifies the imported and exported generated types of an
/// artifact.
pub struct ArtifactGeneratedTypes {
    pub imported_types: &'static str,
    pub ast_type: &'static str,
    pub exported_type: Option<String>,
}

impl ArtifactGeneratedTypes {
    pub fn from_operation(operation: &OperationDefinition, skip_types: bool) -> Self {
        if skip_types {
            Self {
                imported_types: "ConcreteRequest",
                ast_type: "ConcreteRequest",
                exported_type: None,
            }
        } else {
            let (kind, imported_types) = match operation.kind {
                OperationKind::Query => ("Query", "ConcreteRequest, Query"),
                OperationKind::Mutation => ("Mutation", "ConcreteRequest, Mutation"),
                OperationKind::Subscription => (
                    "GraphQLSubscription",
                    "ConcreteRequest, GraphQLSubscription",
                ),
            };
            let exported_type = if has_raw_response_type_directive(operation) {
                format!(
                    "{kind}<\n  {name}$variables,\n  {name}$data,\n  {name}$rawResponse,\n>",
                    kind = kind,
                    name = operation.name.item
                )
            } else {
                format!(
                    "{kind}<\n  {name}$variables,\n  {name}$data,\n>",
                    kind = kind,
                    name = operation.name.item
                )
            };
            Self {
                imported_types,
                ast_type: "ConcreteRequest",
                exported_type: Some(exported_type),
            }
        }
    }

    pub fn from_fragment(fragment: &FragmentDefinition, skip_types: bool) -> Self {
        let is_inline_data_fragment = fragment.directives.named(*INLINE_DIRECTIVE_NAME).is_some();
        if skip_types {
            if is_inline_data_fragment {
                Self {
                    imported_types: "ReaderInlineDataFragment",
                    ast_type: "ReaderInlineDataFragment",
                    exported_type: None,
                }
            } else {
                Self {
                    imported_types: "ReaderFragment",
                    ast_type: "ReaderFragment",
                    exported_type: None,
                }
            }
        } else if is_inline_data_fragment {
            Self {
                imported_types: "InlineFragment, ReaderInlineDataFragment",
                ast_type: "ReaderInlineDataFragment",
                exported_type: Some(format!(
                    "InlineFragment<\n  {name}$fragmentType,\n  {name}$data,\n>",
                    name = fragment.name.item
                )),
            }
        } else if let Some(refetchable_metadata) = RefetchableMetadata::find(&fragment.directives) {
            Self {
                imported_types: "ReaderFragment, RefetchableFragment",
                ast_type: "ReaderFragment",
                exported_type: Some(format!(
                    "RefetchableFragment<\n  {name}$fragmentType,\n  {name}$data,\n  {refetchable_name}$variables,\n>",
                    name = fragment.name.item,
                    refetchable_name = refetchable_metadata.operation_name
                )),
            }
        } else {
            Self {
                imported_types: "Fragment, ReaderFragment",
                ast_type: "ReaderFragment",
                exported_type: Some(format!(
                    "Fragment<\n  {name}$fragmentType,\n  {name}$data,\n>",
                    name = fragment.name.item
                )),
            }
        }
    }
}
<commit_msg>Emit the correct flow type<commit_after>/*
 * Copyright (c) Meta Platforms, Inc. and affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

use common::NamedItem;
use graphql_ir::{FragmentDefinition, OperationDefinition};
use graphql_syntax::OperationKind;
use relay_transforms::{RefetchableMetadata, INLINE_DIRECTIVE_NAME, UPDATABLE_DIRECTIVE};
use relay_typegen::has_raw_response_type_directive;

/// Specifies the imported and exported generated types of an
/// artifact.
pub struct ArtifactGeneratedTypes {
    pub imported_types: &'static str,
    pub ast_type: &'static str,
    pub exported_type: Option<String>,
}

impl ArtifactGeneratedTypes {
    pub fn from_operation(operation: &OperationDefinition, skip_types: bool) -> Self {
        if skip_types {
            Self {
                imported_types: "ConcreteRequest",
                ast_type: "ConcreteRequest",
                exported_type: None,
            }
        } else {
            let (kind, imported_types) = match operation.kind {
                OperationKind::Query => ("Query", "ConcreteRequest, Query"),
                OperationKind::Mutation => ("Mutation", "ConcreteRequest, Mutation"),
                OperationKind::Subscription => (
                    "GraphQLSubscription",
                    "ConcreteRequest, GraphQLSubscription",
                ),
            };
            let exported_type = if has_raw_response_type_directive(operation) {
                format!(
                    "{kind}<\n  {name}$variables,\n  {name}$data,\n  {name}$rawResponse,\n>",
                    kind = kind,
                    name = operation.name.item
                )
            } else {
                format!(
                    "{kind}<\n  {name}$variables,\n  {name}$data,\n>",
                    kind = kind,
                    name = operation.name.item
                )
            };
            Self {
                imported_types,
                ast_type: "ConcreteRequest",
                exported_type: Some(exported_type),
            }
        }
    }

    pub fn from_fragment(fragment: &FragmentDefinition, skip_types: bool) -> Self {
        let is_inline_data_fragment = fragment.directives.named(*INLINE_DIRECTIVE_NAME).is_some();
        let is_updatable_fragment = fragment.directives.named(*UPDATABLE_DIRECTIVE).is_some();

        if skip_types {
            if is_inline_data_fragment {
                Self {
                    imported_types: "ReaderInlineDataFragment",
                    ast_type: "ReaderInlineDataFragment",
                    exported_type: None,
                }
            } else {
                Self {
                    imported_types: "ReaderFragment",
                    ast_type: "ReaderFragment",
                    exported_type: None,
                }
            }
        } else if is_inline_data_fragment {
            Self {
                imported_types: "InlineFragment, ReaderInlineDataFragment",
                ast_type: "ReaderInlineDataFragment",
                exported_type: Some(format!(
                    "InlineFragment<\n  {name}$fragmentType,\n  {name}$data,\n>",
                    name = fragment.name.item
                )),
            }
        } else if let Some(refetchable_metadata) = RefetchableMetadata::find(&fragment.directives) {
            Self {
                imported_types: "ReaderFragment, RefetchableFragment",
                ast_type: "ReaderFragment",
                exported_type: Some(format!(
                    "RefetchableFragment<\n  {name}$fragmentType,\n  {name}$data,\n  {refetchable_name}$variables,\n>",
                    name = fragment.name.item,
                    refetchable_name = refetchable_metadata.operation_name
                )),
            }
        } else if is_updatable_fragment {
            Self {
                imported_types: "UpdatableFragment, ReaderFragment",
                ast_type: "ReaderFragment",
                exported_type: Some(format!(
                    "UpdatableFragment<\n  {name}$fragmentType,\n  {name}$data,\n>",
                    name = fragment.name.item
                )),
            }
        } else {
            Self {
                imported_types: "Fragment, ReaderFragment",
                ast_type: "ReaderFragment",
                exported_type: Some(format!(
                    "Fragment<\n  {name}$fragmentType,\n  {name}$data,\n>",
                    name = fragment.name.item
                )),
            }
        }
    }
}
<|endoftext|>