<commit_before>use std::cmp::min;

use cssparser::Parser;
use markup5ever::{expanded_name, local_name, namespace_url, ns};

use crate::document::AcquiredNodes;
use crate::drawing_ctx::DrawingCtx;
use crate::element::{Draw, Element, ElementResult, SetAttributes};
use crate::error::*;
use crate::node::{Node, NodeBorrow};
use crate::parsers::{NumberList, NumberListLength, Parse, ParseValue};
use crate::surface_utils::{
    iterators::Pixels, shared_surface::ExclusiveImageSurface, ImageSurfaceDataExt, Pixel,
};
use crate::util::clamp;
use crate::xml::Attributes;

use super::context::{FilterContext, FilterOutput, FilterResult};
use super::{FilterEffect, FilterError, FilterRender, PrimitiveWithInput};

/// The `feComponentTransfer` filter primitive.
pub struct FeComponentTransfer {
    base: PrimitiveWithInput,
}

impl Default for FeComponentTransfer {
    /// Constructs a new `ComponentTransfer` with empty properties.
    #[inline]
    fn default() -> FeComponentTransfer {
        FeComponentTransfer {
            base: PrimitiveWithInput::new::<Self>(),
        }
    }
}

impl SetAttributes for FeComponentTransfer {
    fn set_attributes(&mut self, attrs: &Attributes) -> ElementResult {
        self.base.set_attributes(attrs)
    }
}

/// Pixel components that can be influenced by `feComponentTransfer`.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum Channel {
    R,
    G,
    B,
    A,
}

/// Component transfer function types.
enum FunctionType {
    Identity,
    Table,
    Discrete,
    Linear,
    Gamma,
}

impl Parse for FunctionType {
    fn parse<'i>(parser: &mut Parser<'i, '_>) -> Result<Self, ParseError<'i>> {
        Ok(parse_identifiers!(
            parser,
            "identity" => FunctionType::Identity,
            "table" => FunctionType::Table,
            "discrete" => FunctionType::Discrete,
            "linear" => FunctionType::Linear,
            "gamma" => FunctionType::Gamma,
        )?)
    }
}

/// The compute function parameters.
struct FunctionParameters<'a> {
    table_values: &'a Vec<f64>,
    slope: f64,
    intercept: f64,
    amplitude: f64,
    exponent: f64,
    offset: f64,
}

/// The compute function type.
type Function = fn(&FunctionParameters<'_>, f64) -> f64;

/// The identity component transfer function.
fn identity(_: &FunctionParameters<'_>, value: f64) -> f64 {
    value
}

/// The table component transfer function.
fn table(params: &FunctionParameters<'_>, value: f64) -> f64 {
    let n = params.table_values.len() - 1;
    let k = (value * (n as f64)).floor() as usize;

    let k = min(k, n); // Just in case.

    if k == n {
        return params.table_values[k];
    }

    let vk = params.table_values[k];
    let vk1 = params.table_values[k + 1];
    let k = k as f64;
    let n = n as f64;

    vk + (value - k / n) * n * (vk1 - vk)
}

/// The discrete component transfer function.
fn discrete(params: &FunctionParameters<'_>, value: f64) -> f64 {
    let n = params.table_values.len();
    let k = (value * (n as f64)).floor() as usize;

    params.table_values[min(k, n - 1)]
}

/// The linear component transfer function.
fn linear(params: &FunctionParameters<'_>, value: f64) -> f64 {
    params.slope * value + params.intercept
}

/// The gamma component transfer function.
fn gamma(params: &FunctionParameters<'_>, value: f64) -> f64 {
    params.amplitude * value.powf(params.exponent) + params.offset
}

trait FeComponentTransferFunc {
    /// Returns the component transfer function.
    fn function(&self) -> Function;

    /// Returns the component transfer function parameters.
    fn function_parameters(&self) -> FunctionParameters<'_>;

    /// Returns the channel.
    fn channel(&self) -> Channel;
}

macro_rules! func_x {
    ($func_name:ident, $channel:expr) => {
        pub struct $func_name {
            channel: Channel,
            function_type: FunctionType,
            table_values: Vec<f64>,
            slope: f64,
            intercept: f64,
            amplitude: f64,
            exponent: f64,
            offset: f64,
        }

        impl Default for $func_name {
            #[inline]
            fn default() -> Self {
                Self {
                    channel: $channel,
                    function_type: FunctionType::Identity,
                    table_values: Vec::new(),
                    slope: 1.0,
                    intercept: 0.0,
                    amplitude: 1.0,
                    exponent: 1.0,
                    offset: 0.0,
                }
            }
        }

        impl FeComponentTransferFunc for $func_name {
            #[inline]
            fn function_parameters(&self) -> FunctionParameters<'_> {
                FunctionParameters {
                    table_values: &self.table_values,
                    slope: self.slope,
                    intercept: self.intercept,
                    amplitude: self.amplitude,
                    exponent: self.exponent,
                    offset: self.offset,
                }
            }

            #[inline]
            fn function(&self) -> Function {
                match self.function_type {
                    FunctionType::Identity => identity,
                    FunctionType::Table => table,
                    FunctionType::Discrete => discrete,
                    FunctionType::Linear => linear,
                    FunctionType::Gamma => gamma,
                }
            }

            #[inline]
            fn channel(&self) -> Channel {
                self.channel
            }
        }

        impl SetAttributes for $func_name {
            #[inline]
            fn set_attributes(&mut self, attrs: &Attributes) -> ElementResult {
                for (attr, value) in attrs.iter() {
                    match attr.expanded() {
                        expanded_name!("", "type") => self.function_type = attr.parse(value)?,
                        expanded_name!("", "tableValues") => {
                            let NumberList(v) =
                                NumberList::parse_str(value, NumberListLength::Unbounded)
                                    .attribute(attr)?;
                            self.table_values = v;
                        }
                        expanded_name!("", "slope") => self.slope = attr.parse(value)?,
                        expanded_name!("", "intercept") => self.intercept = attr.parse(value)?,
                        expanded_name!("", "amplitude") => self.amplitude = attr.parse(value)?,
                        expanded_name!("", "exponent") => self.exponent = attr.parse(value)?,
                        expanded_name!("", "offset") => self.offset = attr.parse(value)?,

                        _ => (),
                    }
                }

                // The table function type with empty table_values is considered
                // an identity function.
                match self.function_type {
                    FunctionType::Table | FunctionType::Discrete => {
                        if self.table_values.is_empty() {
                            self.function_type = FunctionType::Identity;
                        }
                    }
                    _ => (),
                }

                Ok(())
            }
        }

        impl Draw for $func_name {}
    };
}

// The `<feFuncR>` element
func_x!(FeFuncR, Channel::R);

// The `<feFuncG>` element
func_x!(FeFuncG, Channel::G);

// The `<feFuncB>` element
func_x!(FeFuncB, Channel::B);

// The `<feFuncA>` element
func_x!(FeFuncA, Channel::A);

macro_rules! func_or_default {
    ($func_node:ident, $func_type:ident, $func_data:ident, $func_default:ident) => {
        match $func_node {
            Some(ref f) => {
                $func_data = f.borrow_element();
                match *$func_data {
                    Element::$func_type(ref e) => &*e,
                    _ => unreachable!(),
                }
            }
            _ => &$func_default,
        };
    };
}

macro_rules! get_func_x_node {
    ($func_node:ident, $func_type:ident, $channel:expr) => {
        $func_node
            .children()
            .rev()
            .filter(|c| c.is_element())
            .find(|c| match *c.borrow_element() {
                Element::$func_type(ref f) => f.channel() == $channel,
                _ => false,
            })
    };
}

impl FilterRender for FeComponentTransfer {
    fn render(
        &self,
        node: &Node,
        ctx: &FilterContext,
        acquired_nodes: &mut AcquiredNodes<'_>,
        draw_ctx: &mut DrawingCtx,
    ) -> Result<FilterResult, FilterError> {
        let input = self.base.get_input(ctx, acquired_nodes, draw_ctx)?;
        let bounds = self
            .base
            .get_bounds(ctx)?
            .add_input(&input)
            .into_irect(ctx, draw_ctx);

        // Create the output surface.
        let mut surface = ExclusiveImageSurface::new(
            ctx.source_graphic().width(),
            ctx.source_graphic().height(),
            input.surface().surface_type(),
        )?;

        let func_r_node = get_func_x_node!(node, FeFuncR, Channel::R);
        let func_g_node = get_func_x_node!(node, FeFuncG, Channel::G);
        let func_b_node = get_func_x_node!(node, FeFuncB, Channel::B);
        let func_a_node = get_func_x_node!(node, FeFuncA, Channel::A);

        for node in [&func_r_node, &func_g_node, &func_b_node, &func_a_node]
            .iter()
            .filter_map(|x| x.as_ref())
        {
            if node.borrow_element().is_in_error() {
                return Err(FilterError::ChildNodeInError);
            }
        }

        // These are the default funcs that perform an identity transformation.
        let func_r_default = FeFuncR::default();
        let func_g_default = FeFuncG::default();
        let func_b_default = FeFuncB::default();
        let func_a_default = FeFuncA::default();

        // We need to tell the borrow checker that these live long enough
        let func_r_element;
        let func_g_element;
        let func_b_element;
        let func_a_element;

        let func_r = func_or_default!(func_r_node, FeFuncR, func_r_element, func_r_default);
        let func_g = func_or_default!(func_g_node, FeFuncG, func_g_element, func_g_default);
        let func_b = func_or_default!(func_b_node, FeFuncB, func_b_element, func_b_default);
        let func_a = func_or_default!(func_a_node, FeFuncA, func_a_element, func_a_default);

        #[inline]
        fn compute_func<F>(func: &F) -> impl Fn(u8, f64, f64) -> u8 + '_
        where
            F: FeComponentTransferFunc,
        {
            let compute = func.function();
            let params = func.function_parameters();

            move |value, alpha, new_alpha| {
                let value = f64::from(value) / 255f64;

                let unpremultiplied = if alpha == 0f64 { 0f64 } else { value / alpha };

                let new_value = compute(&params, unpremultiplied);
                let new_value = clamp(new_value, 0f64, 1f64);

                ((new_value * new_alpha * 255f64) + 0.5) as u8
            }
        }

        let compute_r = compute_func::<FeFuncR>(&func_r);
        let compute_g = compute_func::<FeFuncG>(&func_g);
        let compute_b = compute_func::<FeFuncB>(&func_b);

        // Alpha gets special handling since everything else depends on it.
        let compute_a = func_a.function();
        let params_a = func_a.function_parameters();
        let compute_a = |alpha| compute_a(&params_a, alpha);

        // Do the actual processing.
        surface.modify(&mut |data, stride| {
            for (x, y, pixel) in Pixels::within(input.surface(), bounds) {
                let alpha = f64::from(pixel.a) / 255f64;
                let new_alpha = compute_a(alpha);

                let output_pixel = Pixel {
                    r: compute_r(pixel.r, alpha, new_alpha),
                    g: compute_g(pixel.g, alpha, new_alpha),
                    b: compute_b(pixel.b, alpha, new_alpha),
                    a: ((new_alpha * 255f64) + 0.5) as u8,
                };

                data.set_pixel(stride, output_pixel, x, y);
            }
        });

        Ok(FilterResult {
            name: self.base.result.clone(),
            output: FilterOutput {
                surface: surface.share()?,
                bounds,
            },
        })
    }
}

impl FilterEffect for FeComponentTransfer {
    fn is_affected_by_color_interpolation_filters(&self) -> bool {
        true
    }
}
<commit_msg>feComponentTransfer: clone the table_values instead of keeping a reference to them<commit_after>use std::cmp::min;

use cssparser::Parser;
use markup5ever::{expanded_name, local_name, namespace_url, ns};

use crate::document::AcquiredNodes;
use crate::drawing_ctx::DrawingCtx;
use crate::element::{Draw, Element, ElementResult, SetAttributes};
use crate::error::*;
use crate::node::{Node, NodeBorrow};
use crate::parsers::{NumberList, NumberListLength, Parse, ParseValue};
use crate::surface_utils::{
    iterators::Pixels, shared_surface::ExclusiveImageSurface, ImageSurfaceDataExt, Pixel,
};
use crate::util::clamp;
use crate::xml::Attributes;

use super::context::{FilterContext, FilterOutput, FilterResult};
use super::{FilterEffect, FilterError, FilterRender, PrimitiveWithInput};

/// The `feComponentTransfer` filter primitive.
pub struct FeComponentTransfer {
    base: PrimitiveWithInput,
}

impl Default for FeComponentTransfer {
    /// Constructs a new `ComponentTransfer` with empty properties.
    #[inline]
    fn default() -> FeComponentTransfer {
        FeComponentTransfer {
            base: PrimitiveWithInput::new::<Self>(),
        }
    }
}

impl SetAttributes for FeComponentTransfer {
    fn set_attributes(&mut self, attrs: &Attributes) -> ElementResult {
        self.base.set_attributes(attrs)
    }
}

/// Pixel components that can be influenced by `feComponentTransfer`.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum Channel {
    R,
    G,
    B,
    A,
}

/// Component transfer function types.
enum FunctionType {
    Identity,
    Table,
    Discrete,
    Linear,
    Gamma,
}

impl Parse for FunctionType {
    fn parse<'i>(parser: &mut Parser<'i, '_>) -> Result<Self, ParseError<'i>> {
        Ok(parse_identifiers!(
            parser,
            "identity" => FunctionType::Identity,
            "table" => FunctionType::Table,
            "discrete" => FunctionType::Discrete,
            "linear" => FunctionType::Linear,
            "gamma" => FunctionType::Gamma,
        )?)
    }
}

/// The compute function parameters.
struct FunctionParameters {
    table_values: Vec<f64>,
    slope: f64,
    intercept: f64,
    amplitude: f64,
    exponent: f64,
    offset: f64,
}

/// The compute function type.
type Function = fn(&FunctionParameters, f64) -> f64;

/// The identity component transfer function.
fn identity(_: &FunctionParameters, value: f64) -> f64 {
    value
}

/// The table component transfer function.
fn table(params: &FunctionParameters, value: f64) -> f64 {
    let n = params.table_values.len() - 1;
    let k = (value * (n as f64)).floor() as usize;

    let k = min(k, n); // Just in case.

    if k == n {
        return params.table_values[k];
    }

    let vk = params.table_values[k];
    let vk1 = params.table_values[k + 1];
    let k = k as f64;
    let n = n as f64;

    vk + (value - k / n) * n * (vk1 - vk)
}

/// The discrete component transfer function.
fn discrete(params: &FunctionParameters, value: f64) -> f64 {
    let n = params.table_values.len();
    let k = (value * (n as f64)).floor() as usize;

    params.table_values[min(k, n - 1)]
}

/// The linear component transfer function.
fn linear(params: &FunctionParameters, value: f64) -> f64 {
    params.slope * value + params.intercept
}

/// The gamma component transfer function.
fn gamma(params: &FunctionParameters, value: f64) -> f64 {
    params.amplitude * value.powf(params.exponent) + params.offset
}

trait FeComponentTransferFunc {
    /// Returns the component transfer function.
    fn function(&self) -> Function;

    /// Returns the component transfer function parameters.
    fn function_parameters(&self) -> FunctionParameters;

    /// Returns the channel.
    fn channel(&self) -> Channel;
}

macro_rules! func_x {
    ($func_name:ident, $channel:expr) => {
        pub struct $func_name {
            channel: Channel,
            function_type: FunctionType,
            table_values: Vec<f64>,
            slope: f64,
            intercept: f64,
            amplitude: f64,
            exponent: f64,
            offset: f64,
        }

        impl Default for $func_name {
            #[inline]
            fn default() -> Self {
                Self {
                    channel: $channel,
                    function_type: FunctionType::Identity,
                    table_values: Vec::new(),
                    slope: 1.0,
                    intercept: 0.0,
                    amplitude: 1.0,
                    exponent: 1.0,
                    offset: 0.0,
                }
            }
        }

        impl FeComponentTransferFunc for $func_name {
            #[inline]
            fn function_parameters(&self) -> FunctionParameters {
                FunctionParameters {
                    table_values: self.table_values.clone(),
                    slope: self.slope,
                    intercept: self.intercept,
                    amplitude: self.amplitude,
                    exponent: self.exponent,
                    offset: self.offset,
                }
            }

            #[inline]
            fn function(&self) -> Function {
                match self.function_type {
                    FunctionType::Identity => identity,
                    FunctionType::Table => table,
                    FunctionType::Discrete => discrete,
                    FunctionType::Linear => linear,
                    FunctionType::Gamma => gamma,
                }
            }

            #[inline]
            fn channel(&self) -> Channel {
                self.channel
            }
        }

        impl SetAttributes for $func_name {
            #[inline]
            fn set_attributes(&mut self, attrs: &Attributes) -> ElementResult {
                for (attr, value) in attrs.iter() {
                    match attr.expanded() {
                        expanded_name!("", "type") => self.function_type = attr.parse(value)?,
                        expanded_name!("", "tableValues") => {
                            let NumberList(v) =
                                NumberList::parse_str(value, NumberListLength::Unbounded)
                                    .attribute(attr)?;
                            self.table_values = v;
                        }
                        expanded_name!("", "slope") => self.slope = attr.parse(value)?,
                        expanded_name!("", "intercept") => self.intercept = attr.parse(value)?,
                        expanded_name!("", "amplitude") => self.amplitude = attr.parse(value)?,
                        expanded_name!("", "exponent") => self.exponent = attr.parse(value)?,
                        expanded_name!("", "offset") => self.offset = attr.parse(value)?,

                        _ => (),
                    }
                }

                // The table function type with empty table_values is considered
                // an identity function.
                match self.function_type {
                    FunctionType::Table | FunctionType::Discrete => {
                        if self.table_values.is_empty() {
                            self.function_type = FunctionType::Identity;
                        }
                    }
                    _ => (),
                }

                Ok(())
            }
        }

        impl Draw for $func_name {}
    };
}

// The `<feFuncR>` element
func_x!(FeFuncR, Channel::R);

// The `<feFuncG>` element
func_x!(FeFuncG, Channel::G);

// The `<feFuncB>` element
func_x!(FeFuncB, Channel::B);

// The `<feFuncA>` element
func_x!(FeFuncA, Channel::A);

macro_rules! func_or_default {
    ($func_node:ident, $func_type:ident, $func_data:ident, $func_default:ident) => {
        match $func_node {
            Some(ref f) => {
                $func_data = f.borrow_element();
                match *$func_data {
                    Element::$func_type(ref e) => &*e,
                    _ => unreachable!(),
                }
            }
            _ => &$func_default,
        };
    };
}

macro_rules! get_func_x_node {
    ($func_node:ident, $func_type:ident, $channel:expr) => {
        $func_node
            .children()
            .rev()
            .filter(|c| c.is_element())
            .find(|c| match *c.borrow_element() {
                Element::$func_type(ref f) => f.channel() == $channel,
                _ => false,
            })
    };
}

impl FilterRender for FeComponentTransfer {
    fn render(
        &self,
        node: &Node,
        ctx: &FilterContext,
        acquired_nodes: &mut AcquiredNodes<'_>,
        draw_ctx: &mut DrawingCtx,
    ) -> Result<FilterResult, FilterError> {
        let input = self.base.get_input(ctx, acquired_nodes, draw_ctx)?;
        let bounds = self
            .base
            .get_bounds(ctx)?
            .add_input(&input)
            .into_irect(ctx, draw_ctx);

        // Create the output surface.
        let mut surface = ExclusiveImageSurface::new(
            ctx.source_graphic().width(),
            ctx.source_graphic().height(),
            input.surface().surface_type(),
        )?;

        let func_r_node = get_func_x_node!(node, FeFuncR, Channel::R);
        let func_g_node = get_func_x_node!(node, FeFuncG, Channel::G);
        let func_b_node = get_func_x_node!(node, FeFuncB, Channel::B);
        let func_a_node = get_func_x_node!(node, FeFuncA, Channel::A);

        for node in [&func_r_node, &func_g_node, &func_b_node, &func_a_node]
            .iter()
            .filter_map(|x| x.as_ref())
        {
            if node.borrow_element().is_in_error() {
                return Err(FilterError::ChildNodeInError);
            }
        }

        // These are the default funcs that perform an identity transformation.
        let func_r_default = FeFuncR::default();
        let func_g_default = FeFuncG::default();
        let func_b_default = FeFuncB::default();
        let func_a_default = FeFuncA::default();

        // We need to tell the borrow checker that these live long enough
        let func_r_element;
        let func_g_element;
        let func_b_element;
        let func_a_element;

        let func_r = func_or_default!(func_r_node, FeFuncR, func_r_element, func_r_default);
        let func_g = func_or_default!(func_g_node, FeFuncG, func_g_element, func_g_default);
        let func_b = func_or_default!(func_b_node, FeFuncB, func_b_element, func_b_default);
        let func_a = func_or_default!(func_a_node, FeFuncA, func_a_element, func_a_default);

        #[inline]
        fn compute_func<F>(func: &F) -> impl Fn(u8, f64, f64) -> u8 + '_
        where
            F: FeComponentTransferFunc,
        {
            let compute = func.function();
            let params = func.function_parameters();

            move |value, alpha, new_alpha| {
                let value = f64::from(value) / 255f64;

                let unpremultiplied = if alpha == 0f64 { 0f64 } else { value / alpha };

                let new_value = compute(&params, unpremultiplied);
                let new_value = clamp(new_value, 0f64, 1f64);

                ((new_value * new_alpha * 255f64) + 0.5) as u8
            }
        }

        let compute_r = compute_func::<FeFuncR>(&func_r);
        let compute_g = compute_func::<FeFuncG>(&func_g);
        let compute_b = compute_func::<FeFuncB>(&func_b);

        // Alpha gets special handling since everything else depends on it.
        let compute_a = func_a.function();
        let params_a = func_a.function_parameters();
        let compute_a = |alpha| compute_a(&params_a, alpha);

        // Do the actual processing.
        surface.modify(&mut |data, stride| {
            for (x, y, pixel) in Pixels::within(input.surface(), bounds) {
                let alpha = f64::from(pixel.a) / 255f64;
                let new_alpha = compute_a(alpha);

                let output_pixel = Pixel {
                    r: compute_r(pixel.r, alpha, new_alpha),
                    g: compute_g(pixel.g, alpha, new_alpha),
                    b: compute_b(pixel.b, alpha, new_alpha),
                    a: ((new_alpha * 255f64) + 0.5) as u8,
                };

                data.set_pixel(stride, output_pixel, x, y);
            }
        });

        Ok(FilterResult {
            name: self.base.result.clone(),
            output: FilterOutput {
                surface: surface.share()?,
                bounds,
            },
        })
    }
}

impl FilterEffect for FeComponentTransfer {
    fn is_affected_by_color_interpolation_filters(&self) -> bool {
        true
    }
}
<|endoftext|>


<commit_before>use std::io::{BufReader, Read};

use rocket::Data;
use rocket::State;

use service::StoreImpl;

#[get("/raw/<id>")]
pub fn get_raw_image(id: String, store: State<StoreImpl>) -> Option<Vec<u8>> {
    if id.len() != 128 {
        return None;
    }
    Some(store.get_raw_image(&id))
}

#[post("/raw", data = "<data>")]
pub fn save_raw_image(data: Data, store: State<StoreImpl>) -> Result<String, ()> {
    let mut reader = BufReader::new(data.open());
    let mut buf = vec![];
    reader.read_to_end(&mut buf).unwrap();
    Ok(store.save_raw_image(buf.as_slice()))
}

#[get("/sidevar/<id>")]
pub fn get_sidecar(id: String, store: State<StoreImpl>) -> Option<Vec<u8>> {
    if id.len() != 128 {
        return None;
    }
    Some(store.get_sidecar(&id))
}

#[post("/sidecar", data = "<data>")]
pub fn save_sidecar(data: Data, store: State<StoreImpl>) -> Result<String, ()> {
    let mut reader = BufReader::new(data.open());
    let mut buf = vec![];
    reader.read_to_end(&mut buf).unwrap();
    Ok(store.save_sidecar(buf.as_slice()))
}

#[get("/image/<id>")]
pub fn get_image(id: String, store: State<StoreImpl>) -> Option<Vec<u8>> {
    if id.len() != 128 {
        return None;
    }
    Some(store.get_image(&id))
}

#[post("/image", data = "<data>")]
pub fn save_image(data: Data, store: State<StoreImpl>) -> Result<String, ()> {
    let mut reader = BufReader::new(data.open());
    let mut buf = vec![];
    reader.read_to_end(&mut buf).unwrap();
    Ok(store.save_image(buf.as_slice()))
}
<commit_msg>Fix typo<commit_after>use std::io::{BufReader, Read};

use rocket::Data;
use rocket::State;

use service::StoreImpl;

#[get("/raw/<id>")]
pub fn get_raw_image(id: String, store: State<StoreImpl>) -> Option<Vec<u8>> {
    if id.len() != 128 {
        return None;
    }
    Some(store.get_raw_image(&id))
}

#[post("/raw", data = "<data>")]
pub fn save_raw_image(data: Data, store: State<StoreImpl>) -> Result<String, ()> {
    let mut reader = BufReader::new(data.open());
    let mut buf = vec![];
    reader.read_to_end(&mut buf).unwrap();
    Ok(store.save_raw_image(buf.as_slice()))
}

#[get("/sidecar/<id>")]
pub fn get_sidecar(id: String, store: State<StoreImpl>) -> Option<Vec<u8>> {
    if id.len() != 128 {
        return None;
    }
    Some(store.get_sidecar(&id))
}

#[post("/sidecar", data = "<data>")]
pub fn save_sidecar(data: Data, store: State<StoreImpl>) -> Result<String, ()> {
    let mut reader = BufReader::new(data.open());
    let mut buf = vec![];
    reader.read_to_end(&mut buf).unwrap();
    Ok(store.save_sidecar(buf.as_slice()))
}

#[get("/image/<id>")]
pub fn get_image(id: String, store: State<StoreImpl>) -> Option<Vec<u8>> {
    if id.len() != 128 {
        return None;
    }
    Some(store.get_image(&id))
}

#[post("/image", data = "<data>")]
pub fn save_image(data: Data, store: State<StoreImpl>) -> Result<String, ()> {
    let mut reader = BufReader::new(data.open());
    let mut buf = vec![];
    reader.read_to_end(&mut buf).unwrap();
    Ok(store.save_image(buf.as_slice()))
}
<|endoftext|>


<commit_before>pub use libc::dev_t;
pub use libc::stat as FileStat;

use {Errno, Result, NixPath};
use libc::mode_t;
use std::mem;
use std::os::unix::io::RawFd;

mod ffi {
    use libc::{c_char, c_int, mode_t, dev_t};
    pub use libc::{stat, fstat, lstat};

    extern {
        pub fn mknod(pathname: *const c_char, mode: mode_t, dev: dev_t) -> c_int;
        pub fn umask(mask: mode_t) -> mode_t;
    }
}

bitflags!(
    flags SFlag: mode_t {
        const S_IFREG  = 0o100000,
        const S_IFCHR  = 0o020000,
        const S_IFBLK  = 0o060000,
        const S_IFIFO  = 0o010000,
        const S_IFSOCK = 0o140000
    }
);

bitflags! {
    flags Mode: mode_t {
        const S_IRWXU = 0o0700,
        const S_IRUSR = 0o0400,
        const S_IWUSR = 0o0200,
        const S_IXUSR = 0o0100,

        const S_IRWXG = 0o0070,
        const S_IRGRP = 0o0040,
        const S_IWGRP = 0o0020,
        const S_IXGRP = 0o0010,

        const S_IRWXO = 0o0007,
        const S_IROTH = 0o0004,
        const S_IWOTH = 0o0002,
        const S_IXOTH = 0o0001,

        const S_ISUID = 0o4000,
        const S_ISGID = 0o2000,
        const S_ISVTX = 0o1000,
    }
}

pub fn mknod<P: ?Sized + NixPath>(path: &P, kind: SFlag, perm: Mode, dev: dev_t) -> Result<()> {
    let res = try!(path.with_nix_path(|cstr| {
        unsafe {
            ffi::mknod(cstr.as_ptr(), kind.bits | perm.bits() as mode_t, dev)
        }
    }));

    Errno::result(res).map(drop)
}

#[cfg(target_os = "linux")]
const MINORBITS: usize = 20;

#[cfg(target_os = "linux")]
pub fn mkdev(major: u64, minor: u64) -> dev_t {
    (major << MINORBITS) | minor
}

pub fn umask(mode: Mode) -> Mode {
    let prev = unsafe { ffi::umask(mode.bits() as mode_t) };
    Mode::from_bits(prev).expect("[BUG] umask returned invalid Mode")
}

pub fn stat<P: ?Sized + NixPath>(path: &P) -> Result<FileStat> {
    let mut dst = unsafe { mem::uninitialized() };
    let res = try!(path.with_nix_path(|cstr| {
        unsafe {
            ffi::stat(cstr.as_ptr(), &mut dst as *mut FileStat)
        }
    }));

    try!(Errno::result(res));

    Ok(dst)
}

pub fn lstat<P: ?Sized + NixPath>(path: &P) -> Result<FileStat> {
    let mut dst = unsafe { mem::uninitialized() };
    let res = try!(path.with_nix_path(|cstr| {
        unsafe {
            ffi::lstat(cstr.as_ptr(), &mut dst as *mut FileStat)
        }
    }));

    try!(Errno::result(res));

    Ok(dst)
}

pub fn fstat(fd: RawFd) -> Result<FileStat> {
    let mut dst = unsafe { mem::uninitialized() };
    let res = unsafe { ffi::fstat(fd, &mut dst as *mut FileStat) };

    try!(Errno::result(res));

    Ok(dst)
}
<commit_msg>Add some missing SFlags<commit_after>pub use libc::dev_t;
pub use libc::stat as FileStat;

use {Errno, Result, NixPath};
use libc::mode_t;
use std::mem;
use std::os::unix::io::RawFd;

mod ffi {
    use libc::{c_char, c_int, mode_t, dev_t};
    pub use libc::{stat, fstat, lstat};

    extern {
        pub fn mknod(pathname: *const c_char, mode: mode_t, dev: dev_t) -> c_int;
        pub fn umask(mask: mode_t) -> mode_t;
    }
}

bitflags!(
    flags SFlag: mode_t {
        const S_IFIFO  = 0o010000,
        const S_IFCHR  = 0o020000,
        const S_IFDIR  = 0o040000,
        const S_IFBLK  = 0o060000,
        const S_IFREG  = 0o100000,
        const S_IFLNK  = 0o120000,
        const S_IFSOCK = 0o140000,
        const S_IFMT   = 0o170000
    }
);

bitflags! {
    flags Mode: mode_t {
        const S_IRWXU = 0o0700,
        const S_IRUSR = 0o0400,
        const S_IWUSR = 0o0200,
        const S_IXUSR = 0o0100,

        const S_IRWXG = 0o0070,
        const S_IRGRP = 0o0040,
        const S_IWGRP = 0o0020,
        const S_IXGRP = 0o0010,

        const S_IRWXO = 0o0007,
        const S_IROTH = 0o0004,
        const S_IWOTH = 0o0002,
        const S_IXOTH = 0o0001,

        const S_ISUID = 0o4000,
        const S_ISGID = 0o2000,
        const S_ISVTX = 0o1000,
    }
}

pub fn mknod<P: ?Sized + NixPath>(path: &P, kind: SFlag, perm: Mode, dev: dev_t) -> Result<()> {
    let res = try!(path.with_nix_path(|cstr| {
        unsafe {
            ffi::mknod(cstr.as_ptr(), kind.bits | perm.bits() as mode_t, dev)
        }
    }));

    Errno::result(res).map(drop)
}

#[cfg(target_os = "linux")]
const MINORBITS: usize = 20;

#[cfg(target_os = "linux")]
pub fn mkdev(major: u64, minor: u64) -> dev_t {
    (major << MINORBITS) | minor
}

pub fn umask(mode: Mode) -> Mode {
    let prev = unsafe { ffi::umask(mode.bits() as mode_t) };
    Mode::from_bits(prev).expect("[BUG] umask returned invalid Mode")
}

pub fn stat<P: ?Sized + NixPath>(path: &P) -> Result<FileStat> {
    let mut dst = unsafe { mem::uninitialized() };
    let res = try!(path.with_nix_path(|cstr| {
        unsafe {
            ffi::stat(cstr.as_ptr(), &mut dst as *mut FileStat)
        }
    }));

    try!(Errno::result(res));

    Ok(dst)
}

pub fn lstat<P: ?Sized + NixPath>(path: &P) -> Result<FileStat> {
    let mut dst = unsafe { mem::uninitialized() };
    let res = try!(path.with_nix_path(|cstr| {
        unsafe {
            ffi::lstat(cstr.as_ptr(), &mut dst as *mut FileStat)
        }
    }));

    try!(Errno::result(res));

    Ok(dst)
}

pub fn fstat(fd: RawFd) -> Result<FileStat> {
    let mut dst = unsafe { mem::uninitialized() };
    let res = unsafe { ffi::fstat(fd, &mut dst as *mut FileStat) };

    try!(Errno::result(res));

    Ok(dst)
}
<|endoftext|>


<commit_before>use unicode_width::UnicodeWidthStr;

use crate::buffer::Buffer;
use crate::layout::Rect;
use crate::style::Style;
use crate::symbols::line;
use crate::widgets::{Block, Widget};

/// A widget to display available tabs in a multiple panels context.
///
/// # Examples
///
/// ```
/// # use tui::widgets::{Block, Borders, Tabs};
/// # use tui::style::{Style, Color};
/// # fn main() {
/// Tabs::default()
///     .block(Block::default().title("Tabs").borders(Borders::ALL))
///     .titles(&["Tab1", "Tab2", "Tab3", "Tab4"])
///     .style(Style::default().fg(Color::White))
///     .highlight_style(Style::default().fg(Color::Yellow));
/// # }
/// ```
pub struct Tabs<'a, T>
where
    T: AsRef<str> + 'a,
{
    /// A block to wrap this widget in if necessary
    block: Option<Block<'a>>,
    /// One title for each tab
    titles: &'a [T],
    /// The index of the selected tabs
    selected: usize,
    /// The style used to draw the text
    style: Style,
    /// The style used to display the selected item
    highlight_style: Style,
}

impl<'a, T> Default for Tabs<'a, T>
where
    T: AsRef<str>,
{
    fn default() -> Tabs<'a, T> {
        Tabs {
            block: None,
            titles: &[],
            selected: 0,
            style: Default::default(),
            highlight_style: Default::default(),
        }
    }
}

impl<'a, T> Tabs<'a, T>
where
    T: AsRef<str>,
{
    pub fn block(mut self, block: Block<'a>) -> Tabs<'a, T> {
        self.block = Some(block);
        self
    }

    pub fn titles(mut self, titles: &'a [T]) -> Tabs<'a, T> {
        self.titles = titles;
        self
    }

    pub fn select(mut self, selected: usize) -> Tabs<'a, T> {
        self.selected = selected;
        self
    }

    pub fn style(mut self, style: Style) -> Tabs<'a, T> {
        self.style = style;
        self
    }

    pub fn highlight_style(mut self, style: Style) -> Tabs<'a, T> {
        self.highlight_style = style;
        self
    }
}

impl<'a, T> Widget for Tabs<'a, T>
where
    T: AsRef<str>,
{
    fn draw(&mut self, area: Rect, buf: &mut Buffer) {
        let tabs_area = match self.block {
            Some(ref mut b) => {
                b.draw(area, buf);
                b.inner(area)
            }
            None => area,
        };

        if tabs_area.height < 1 {
            return;
        }

        self.background(&tabs_area, buf, self.style.bg);

        let mut x = tabs_area.left();
        for (title, style) in self.titles.iter().enumerate().map(|(i, t)| {
            if i == self.selected {
                (t, self.highlight_style)
            } else {
                (t, self.style)
            }
        }) {
            x += 1;
            if x > tabs_area.right() {
                break;
            } else {
                buf.set_string(x, tabs_area.top(), title.as_ref(), style);
                x += title.as_ref().width() as u16 + 1;
                if x >= tabs_area.right() {
                    break;
                } else {
                    buf.get_mut(x, tabs_area.top())
                        .set_symbol(line::VERTICAL)
                        .set_fg(self.style.fg)
                        .set_bg(self.style.bg);
                    x += 1;
                }
            }
        }
    }
}
<commit_msg>Add `divider` to `Tabs`<commit_after>use unicode_width::UnicodeWidthStr;

use crate::buffer::Buffer;
use crate::layout::Rect;
use crate::style::Style;
use crate::symbols::line;
use crate::widgets::{Block, Widget};

/// A widget to display available tabs in a multiple panels context.
///
/// # Examples
///
/// ```
/// # use tui::widgets::{Block, Borders, Tabs};
/// # use tui::style::{Style, Color};
/// # use tui::symbols::{DOT};
/// # fn main() {
/// Tabs::default()
///     .block(Block::default().title("Tabs").borders(Borders::ALL))
///     .titles(&["Tab1", "Tab2", "Tab3", "Tab4"])
///     .style(Style::default().fg(Color::White))
///     .highlight_style(Style::default().fg(Color::Yellow));
///     .divider(DOT);
/// # }
/// ```
pub struct Tabs<'a, T>
where
    T: AsRef<str> + 'a,
{
    /// A block to wrap this widget in if necessary
    block: Option<Block<'a>>,
    /// One title for each tab
    titles: &'a [T],
    /// The index of the selected tabs
    selected: usize,
    /// The style used to draw the text
    style: Style,
    /// The style used to display the selected item
    highlight_style: Style,
    /// Tab divider
    divider: &'a str,
}

impl<'a, T> Default for Tabs<'a, T>
where
    T: AsRef<str>,
{
    fn default() -> Tabs<'a, T> {
        Tabs {
            block: None,
            titles: &[],
            selected: 0,
            style: Default::default(),
            highlight_style: Default::default(),
            divider: line::VERTICAL,
        }
    }
}

impl<'a, T> Tabs<'a, T>
where
    T: AsRef<str>,
{
    pub fn block(mut self, block: Block<'a>) -> Tabs<'a, T> {
        self.block = Some(block);
        self
    }

    pub fn titles(mut self, titles: &'a [T]) -> Tabs<'a, T> {
        self.titles = titles;
        self
    }

    pub fn select(mut self, selected: usize) -> Tabs<'a, T> {
        self.selected = selected;
        self
    }

    pub fn style(mut self, style: Style) -> Tabs<'a, T> {
        self.style = style;
        self
    }

    pub fn highlight_style(mut self, style: Style) -> Tabs<'a, T> {
        self.highlight_style = style;
        self
    }

    pub fn divider(mut self, divider: &'a str) -> Tabs<'a, T> {
        self.divider = divider;
        self
    }
}

impl<'a, T> Widget for Tabs<'a, T>
where
    T: AsRef<str>,
{
    fn draw(&mut self, area: Rect, buf: &mut Buffer) {
        let tabs_area = match self.block {
            Some(ref mut b) => {
                b.draw(area, buf);
                b.inner(area)
            }
            None => area,
        };

        if tabs_area.height < 1 {
            return;
        }

        self.background(&tabs_area, buf, self.style.bg);

        let mut x = tabs_area.left();
        let divider_width = self.divider.chars().count() as u16;
        for (title, style) in self.titles.iter().enumerate().map(|(i, t)| {
            if i == self.selected {
                (t, self.highlight_style)
            } else {
                (t, self.style)
            }
        }) {
            x += 1;
            if x > tabs_area.right() {
                break;
            } else {
                buf.set_string(x, tabs_area.top(), title.as_ref(), style);
                x += title.as_ref().width() as u16 + 1;
                if x >= tabs_area.right() {
                    break;
                } else {
                    buf.get_mut(x, tabs_area.top())
                        .set_symbol(self.divider)
                        .set_fg(self.style.fg)
                        .set_bg(self.style.bg);
                    x += divider_width;
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2016 Martin Grabmueller. See the LICENSE file at the
// top-level directory of this distribution for license information.

//! Arithmetic encoder.
//!
//! This is a direct translation of the C source in Ian H. Witten,
//! Radford M. Neal and John G. Cleary: Arithmetic Coding for Data
//! Compression, Communications of the ACM, Vol. 30, Number 6, June
//! 1987.  Only the adaptive model is included.

use std::io::{Read, Write, Bytes};
use std::io;

use error::Error;

// You can uncomment the following line and comment the line after to
// try out compression with a smaller word size.  The difference will
// be negligable (less than 0.01% on my experiments.
//const CODE_VALUE_BITS: usize = 16;
const CODE_VALUE_BITS: usize = 32;

type CodeValue = u64;

const TOP_VALUE: CodeValue = (1u64 << CODE_VALUE_BITS) - 1;

const FIRST_QTR: CodeValue = (TOP_VALUE / 4) + 1;
const HALF: CodeValue = 2 * FIRST_QTR;
const THIRD_QTR: CodeValue = 3 * FIRST_QTR;

const NO_OF_CHARS: usize = 256;

const EOF_SYMBOL: usize = NO_OF_CHARS + 1;
const NO_OF_SYMBOLS: usize = EOF_SYMBOL + 1;

// Using a max frequency of 2^14 - 1 actually gives better compression
// than bigger values like 2^30 - 1.  I suppose this is due to better
// locality.
const MAX_FREQUENCY: usize = (1 << 14) - 1;

type Symbol = usize;

struct Model {
    char_to_index: [usize; NO_OF_CHARS],
    index_to_char: [usize; NO_OF_SYMBOLS + 1],
    cum_freq: [usize; NO_OF_SYMBOLS + 1],
    freq: [usize; NO_OF_SYMBOLS + 1],

}

impl Model {
    fn new() -> Self {
        let mut m = Model {
            char_to_index: [0; NO_OF_CHARS],
            index_to_char: [0; NO_OF_SYMBOLS + 1],
            cum_freq: [0; NO_OF_SYMBOLS + 1],
            freq: [0; NO_OF_SYMBOLS + 1],
        };
        for i in 0..NO_OF_CHARS {
            m.char_to_index[i] = i + 1;
            m.index_to_char[i + 1] = i;
        }
        for i in 0..NO_OF_SYMBOLS + 1 {
            m.freq[i] = 1;
            m.cum_freq[i] = NO_OF_SYMBOLS - i;
        }
        m.freq[0] = 0;
        m
    }

    fn update(&mut self, symbol: Symbol) {
        if self.cum_freq[0] == MAX_FREQUENCY {
            let mut cum = 0;
            let mut i = NO_OF_SYMBOLS;
            while i > 0 {
                self.freq[i] = (self.freq[i] + 1) / 2;
                self.cum_freq[i] = cum;
                cum += self.freq[i];
                i -= 1;
            }
            self.freq[0] = (self.freq[0] + 1) / 2;
            self.cum_freq[0] = cum;
        }

        let mut i = symbol;
        while i > 0 && self.freq[i] == self.freq[i - 1] {
            i -= 1;
        }
        if i < symbol {
            let ch_i = self.index_to_char[i];
            let ch_symbol = self.index_to_char[symbol];
            self.index_to_char[i] = ch_symbol;
            self.index_to_char[symbol] = ch_i;
            self.char_to_index[ch_i] = symbol;
            self.char_to_index[ch_symbol] = i;
        }
        self.freq[i] += 1;
        while i > 0 {
            i -= 1;
            self.cum_freq[i] += 1;
        }
    }

}

/// Arithmetic encoder.
struct Encoder<W> {
    inner: W,

    model: Model,

    low: CodeValue,
    high: CodeValue,
    bits_to_follow: usize,

    buffer: u8,
    bits_to_go: usize,
}

impl<W: Write> Encoder<W> {
    pub fn new(output: W) -> Self {
        let enc = Encoder{
            inner: output,

            model: Model::new(),

            low: 0,
            high: TOP_VALUE,
            bits_to_follow: 0,

            buffer: 0,
            bits_to_go: 8,
        };
        enc
    }

    fn encode_symbol(&mut self, symbol: Symbol) -> io::Result<()> {
        let range = (self.high - self.low) + 1;
        let total = self.model.cum_freq[0] as CodeValue;

        debug_assert!(total <= MAX_FREQUENCY as CodeValue);

        let hi_freq = self.model.cum_freq[symbol-1] as CodeValue;
        let lo_freq = self.model.cum_freq[symbol] as CodeValue;

        self.high = self.low + (range * hi_freq) / total - 1;
        self.low = self.low + (range * lo_freq) / total;

        loop {
            if self.high < HALF {
                try!(self.bit_plus_follow(0));
            } else if self.low >= HALF {
                try!(self.bit_plus_follow(1));
                self.low -= HALF;
                self.high -= HALF;
            } else if self.low >= FIRST_QTR && self.high < THIRD_QTR {
                self.bits_to_follow += 1;
                self.low -= FIRST_QTR;
                self.high -= FIRST_QTR;
            } else {
                break;
            }
            self.low = self.low << 1;
            self.high = (self.high << 1) + 1;
        }

        Ok(())
    }

    fn done_encoding(&mut self) -> io::Result<()> {
        self.bits_to_follow += 1;
        if self.low < FIRST_QTR {
            try!(self.bit_plus_follow(0));
        } else {
            try!(self.bit_plus_follow(1));
        }
        Ok(())
    }

    fn bit_plus_follow(&mut self, bit: usize) -> io::Result<()> {
        try!(self.output_bit(bit));
        while self.bits_to_follow > 0 {
            try!(self.output_bit(1 - bit));
            self.bits_to_follow -= 1;
        }
        Ok(())
    }

    fn output_bit(&mut self, bit: usize) -> io::Result<()> {
        self.buffer >>= 1;
        if bit != 0 {
            self.buffer |= 0x80;
        }
        self.bits_to_go -= 1;
        if self.bits_to_go == 0 {
            try!(self.inner.write_all(&[self.buffer]));
            self.bits_to_go = 8;
        }
        Ok(())
    }

    fn done_outputting_bits(&mut self) -> io::Result<()> {
        if self.bits_to_go < 8 {
            try!(self.inner.write_all(&[self.buffer >> self.bits_to_go]));
        }
        Ok(())
    }

    fn into_inner(self) -> W {
        self.inner
    }
}

impl<W: Write> Write for Encoder<W> {
    fn write(&mut self, data: &[u8]) -> io::Result<usize> {
        for b in data {
            let symbol = self.model.char_to_index[*b as usize];
            try!(self.encode_symbol(symbol));
            self.model.update(symbol);
        }
        Ok(data.len())
    }

    fn flush(&mut self) -> io::Result<()> {
        try!(self.encode_symbol(EOF_SYMBOL));
        try!(self.done_encoding());
        self.done_outputting_bits()
    }
}

/// Arithmetic decoder.
struct Decoder<R> {
    inner: Bytes<R>,

    model: Model,

    value: CodeValue,
    low: CodeValue,
    high: CodeValue,

    buffer: u8,
    bits_to_go: usize,
    garbage_bits: usize,

    eof: bool,
}

impl<R: Read> Decoder<R> {
    pub fn new(input: R) -> io::Result<Self> {
        let mut dec = Decoder{
            inner: input.bytes(),

            model: Model::new(),

            value: 0,
            low: 0,
            high: TOP_VALUE,

            buffer: 0,
            bits_to_go: 0,
            garbage_bits: 0,

            eof: false,
        };
        for _ in 0..CODE_VALUE_BITS {
            dec.value = (dec.value << 1) | (try!(dec.input_bit()) as CodeValue);
        }
        Ok(dec)
    }

    fn input_bit(&mut self) -> io::Result<usize> {
        if self.bits_to_go == 0 {
            if let Some(b) = self.inner.next() {
                self.buffer = try!(b);
            } else {
                self.garbage_bits += 1;
                if self.garbage_bits > CODE_VALUE_BITS - 2 {
                    return Err(io::Error::new(io::ErrorKind::UnexpectedEof,
                                              "cannot read from bit stream"));
                } else {
                    self.buffer = 0xff;
                }
            }
            self.bits_to_go = 8;
        }
        let t = self.buffer & 1;
        self.buffer >>= 1;
        self.bits_to_go -= 1;
        Ok(t as usize)
    }

    fn decode_symbol(&mut self) -> io::Result<Symbol> {

        let range = self.high - self.low + 1;
        let total = self.model.cum_freq[0] as CodeValue;
        let cum = ((self.value - self.low + 1) * total - 1) / range;

        // Find symbol with the cumulative frequency that matches the
        // current interval.
        let mut symbol = 1;
        while self.model.cum_freq[symbol] as CodeValue > cum {
            symbol += 1;
        }

        let lo_freq = self.model.cum_freq[symbol] as CodeValue;
        let hi_freq = self.model.cum_freq[symbol - 1] as CodeValue;

        self.high = self.low + (range * hi_freq / total) - 1;
        self.low = self.low + (range * lo_freq / total);

        loop {
            if self.high < HALF {
                // do nothing
            } else if self.low >= HALF {
                self.value -= HALF;
                self.low -= HALF;
                self.high -= HALF;
            } else if self.low >= FIRST_QTR && self.high < THIRD_QTR {
                self.value -= FIRST_QTR;
                self.low -= FIRST_QTR;
                self.high -= FIRST_QTR;
            } else {
                break;
            }
            self.low = self.low << 1;
            self.high = (self.high << 1) + 1;
            self.value = (self.value << 1) + (try!(self.input_bit()) as CodeValue);
        }
        Ok(symbol)
    }
}

impl<R: Read> Read for Decoder<R> {
    fn read(&mut self, data: &mut [u8]) -> io::Result<usize> {
        if self.eof {
            return Ok(0);
        }

        let mut written = 0;
        while written < data.len()  {
            let symbol = try!(self.decode_symbol());
            if symbol == EOF_SYMBOL {
                self.eof = true;
                break;
            }
            let ch = self.model.index_to_char[symbol as usize];
            data[written] = ch as u8;
            written += 1;
            self.model.update(symbol);
        }
        Ok(written)
    }
}

/// Read all data from `input`, compress it using an order-0
/// arithmetic encoder and write the compressed data to `output`.
pub fn compress<R: Read, W: Write>(mut input: R, output: W) -> Result<W, Error> {
    let mut cw = Encoder::new(output);
    try!(io::copy(&mut input, &mut cw));
    try!(cw.flush());
    Ok(cw.into_inner())
}

/// Read all data from `input`, decompress it using an order-0
/// arithmetic encoder and write the decompressed data to `output`.
/// The data must be produced by the `compress` function.
pub fn decompress<R: Read, W: Write>(input: R, mut output: W) -> Result<W, Error> {
    let mut cr = try!(Decoder::new(input));
    try!(io::copy(&mut cr, &mut output));
    Ok(output)
}

#[cfg(test)]
mod test {
    use std::io::Cursor;
    use super::{compress, decompress};

    #[test]
    fn compress_empty() {
        let input = [];
        let compressed = compress(Cursor::new(&input), vec![]).unwrap();
        let expected = [128, 0];
        assert_eq!(&expected[..], &compressed[..]);
    }

    #[test]
    fn decompress_empty() {
        let input = [128, 0];
        let decompressed = decompress(Cursor::new(&input), vec![]).unwrap();
        let expected: [u8;0] = [];
        assert_eq!(&expected[..], &decompressed[..]);
    }

    #[test]
    fn compress_a() {
        let input = b"a";
        let compressed = compress(Cursor::new(&input), vec![]).unwrap();
        let expected = [121, 195, 0];
        assert_eq!(&expected[..], &compressed[..]);
    }

    #[test]
    fn decompress_a() {
        let input = [121, 195, 0];
        let decompressed = decompress(Cursor::new(&input), vec![]).unwrap();
        let expected = b"a";
        assert_eq!(&expected[..], &decompressed[..]);
    }

    #[test]
    fn compress_aaa() {
        let input = b"aaaaaaaaa";
        let compressed = compress(Cursor::new(&input), vec![]).unwrap();
        let expected = [249, 253, 255, 255, 255, 255, 223, 126];
        assert_eq!(&expected[..], &compressed[..]);
    }

    #[test]
    fn decompress_aaa() {
        let input = [249, 253, 255, 255, 255, 255, 223, 126];
        let decompressed = decompress(Cursor::new(&input), vec![]).unwrap();
        let expected = b"aaaaaaaaa";
        assert_eq!(&expected[..], &decompressed[..]);
    }

    #[test]
    fn compress_decompress() {
        let f = include_bytes!("witten_arith.rs");
        let original = &f[..];
        let compressed = compress(Cursor::new(&original), vec![]).unwrap();
        let decompressed = decompress(Cursor::new(compressed), vec![]).unwrap();

        assert_eq!(&original[..], &decompressed[..]);
    }
}
<commit_msg>Fixed tests.<commit_after>// Copyright 2016 Martin Grabmueller. See the LICENSE file at the
// top-level directory of this distribution for license information.

//! Arithmetic encoder.
//!
//! This is a direct translation of the C source in Ian H. Witten,
//! Radford M. Neal and John G. Cleary: Arithmetic Coding for Data
//! Compression, Communications of the ACM, Vol. 30, Number 6, June
//! 1987.  Only the adaptive model is included.

use std::io::{Read, Write, Bytes};
use std::io;

use error::Error;

// You can uncomment the following line and comment the line after to
// try out compression with a smaller word size.  The difference will
// be negligable (less than 0.01% on my experiments.
//const CODE_VALUE_BITS: usize = 16;
const CODE_VALUE_BITS: usize = 32;

type CodeValue = u64;

const TOP_VALUE: CodeValue = (1u64 << CODE_VALUE_BITS) - 1;

const FIRST_QTR: CodeValue = (TOP_VALUE / 4) + 1;
const HALF: CodeValue = 2 * FIRST_QTR;
const THIRD_QTR: CodeValue = 3 * FIRST_QTR;

const NO_OF_CHARS: usize = 256;

const EOF_SYMBOL: usize = NO_OF_CHARS + 1;
const NO_OF_SYMBOLS: usize = EOF_SYMBOL + 1;

// Using a max frequency of 2^14 - 1 actually gives better compression
// than bigger values like 2^30 - 1.  I suppose this is due to better
// locality.
const MAX_FREQUENCY: usize = (1 << 14) - 1;

type Symbol = usize;

struct Model {
    char_to_index: [usize; NO_OF_CHARS],
    index_to_char: [usize; NO_OF_SYMBOLS + 1],
    cum_freq: [usize; NO_OF_SYMBOLS + 1],
    freq: [usize; NO_OF_SYMBOLS + 1],

}

impl Model {
    fn new() -> Self {
        let mut m = Model {
            char_to_index: [0; NO_OF_CHARS],
            index_to_char: [0; NO_OF_SYMBOLS + 1],
            cum_freq: [0; NO_OF_SYMBOLS + 1],
            freq: [0; NO_OF_SYMBOLS + 1],
        };
        for i in 0..NO_OF_CHARS {
            m.char_to_index[i] = i + 1;
            m.index_to_char[i + 1] = i;
        }
        for i in 0..NO_OF_SYMBOLS + 1 {
            m.freq[i] = 1;
            m.cum_freq[i] = NO_OF_SYMBOLS - i;
        }
        m.freq[0] = 0;
        m
    }

    fn update(&mut self, symbol: Symbol) {
        if self.cum_freq[0] == MAX_FREQUENCY {
            let mut cum = 0;
            let mut i = NO_OF_SYMBOLS;
            while i > 0 {
                self.freq[i] = (self.freq[i] + 1) / 2;
                self.cum_freq[i] = cum;
                cum += self.freq[i];
                i -= 1;
            }
            self.freq[0] = (self.freq[0] + 1) / 2;
            self.cum_freq[0] = cum;
        }

        let mut i = symbol;
        while i > 0 && self.freq[i] == self.freq[i - 1] {
            i -= 1;
        }
        if i < symbol {
            let ch_i = self.index_to_char[i];
            let ch_symbol = self.index_to_char[symbol];
            self.index_to_char[i] = ch_symbol;
            self.index_to_char[symbol] = ch_i;
            self.char_to_index[ch_i] = symbol;
            self.char_to_index[ch_symbol] = i;
        }
        self.freq[i] += 1;
        while i > 0 {
            i -= 1;
            self.cum_freq[i] += 1;
        }
    }

}

/// Arithmetic encoder.
struct Encoder<W> {
    inner: W,

    model: Model,

    low: CodeValue,
    high: CodeValue,
    bits_to_follow: usize,

    buffer: u8,
    bits_to_go: usize,
}

impl<W: Write> Encoder<W> {
    pub fn new(output: W) -> Self {
        let enc = Encoder{
            inner: output,

            model: Model::new(),

            low: 0,
            high: TOP_VALUE,
            bits_to_follow: 0,

            buffer: 0,
            bits_to_go: 8,
        };
        enc
    }

    fn encode_symbol(&mut self, symbol: Symbol) -> io::Result<()> {
        let range = (self.high - self.low) + 1;
        let total = self.model.cum_freq[0] as CodeValue;

        debug_assert!(total <= MAX_FREQUENCY as CodeValue);

        let hi_freq = self.model.cum_freq[symbol-1] as CodeValue;
        let lo_freq = self.model.cum_freq[symbol] as CodeValue;

        self.high = self.low + (range * hi_freq) / total - 1;
        self.low = self.low + (range * lo_freq) / total;

        loop {
            if self.high < HALF {
                try!(self.bit_plus_follow(0));
            } else if self.low >= HALF {
                try!(self.bit_plus_follow(1));
                self.low -= HALF;
                self.high -= HALF;
            } else if self.low >= FIRST_QTR && self.high < THIRD_QTR {
                self.bits_to_follow += 1;
                self.low -= FIRST_QTR;
                self.high -= FIRST_QTR;
            } else {
                break;
            }
            self.low = self.low << 1;
            self.high = (self.high << 1) + 1;
        }

        Ok(())
    }

    fn done_encoding(&mut self) -> io::Result<()> {
        self.bits_to_follow += 1;
        if self.low < FIRST_QTR {
            try!(self.bit_plus_follow(0));
        } else {
            try!(self.bit_plus_follow(1));
        }
        Ok(())
    }

    fn bit_plus_follow(&mut self, bit: usize) -> io::Result<()> {
        try!(self.output_bit(bit));
        while self.bits_to_follow > 0 {
            try!(self.output_bit(1 - bit));
            self.bits_to_follow -= 1;
        }
        Ok(())
    }

    fn output_bit(&mut self, bit: usize) -> io::Result<()> {
        self.buffer >>= 1;
        if bit != 0 {
            self.buffer |= 0x80;
        }
        self.bits_to_go -= 1;
        if self.bits_to_go == 0 {
            try!(self.inner.write_all(&[self.buffer]));
            self.bits_to_go = 8;
        }
        Ok(())
    }

    fn done_outputting_bits(&mut self) -> io::Result<()> {
        if self.bits_to_go < 8 {
            try!(self.inner.write_all(&[self.buffer >> self.bits_to_go]));
        }
        Ok(())
    }

    fn into_inner(self) -> W {
        self.inner
    }
}

impl<W: Write> Write for Encoder<W> {
    fn write(&mut self, data: &[u8]) -> io::Result<usize> {
        for b in data {
            let symbol = self.model.char_to_index[*b as usize];
            try!(self.encode_symbol(symbol));
            self.model.update(symbol);
        }
        Ok(data.len())
    }

    fn flush(&mut self) -> io::Result<()> {
        try!(self.encode_symbol(EOF_SYMBOL));
        try!(self.done_encoding());
        self.done_outputting_bits()
    }
}

/// Arithmetic decoder.
struct Decoder<R> {
    inner: Bytes<R>,

    model: Model,

    value: CodeValue,
    low: CodeValue,
    high: CodeValue,

    buffer: u8,
    bits_to_go: usize,
    garbage_bits: usize,

    eof: bool,
}

impl<R: Read> Decoder<R> {
    pub fn new(input: R) -> io::Result<Self> {
        let mut dec = Decoder{
            inner: input.bytes(),

            model: Model::new(),

            value: 0,
            low: 0,
            high: TOP_VALUE,

            buffer: 0,
            bits_to_go: 0,
            garbage_bits: 0,

            eof: false,
        };
        for _ in 0..CODE_VALUE_BITS {
            dec.value = (dec.value << 1) | (try!(dec.input_bit()) as CodeValue);
        }
        Ok(dec)
    }

    fn input_bit(&mut self) -> io::Result<usize> {
        if self.bits_to_go == 0 {
            if let Some(b) = self.inner.next() {
                self.buffer = try!(b);
            } else {
                self.garbage_bits += 1;
                if self.garbage_bits > CODE_VALUE_BITS - 2 {
                    return Err(io::Error::new(io::ErrorKind::UnexpectedEof,
                                              "cannot read from bit stream"));
                } else {
                    self.buffer = 0xff;
                }
            }
            self.bits_to_go = 8;
        }
        let t = self.buffer & 1;
        self.buffer >>= 1;
        self.bits_to_go -= 1;
        Ok(t as usize)
    }

    fn decode_symbol(&mut self) -> io::Result<Symbol> {

        let range = self.high - self.low + 1;
        let total = self.model.cum_freq[0] as CodeValue;
        let cum = ((self.value - self.low + 1) * total - 1) / range;

        // Find symbol with the cumulative frequency that matches the
        // current interval.
        let mut symbol = 1;
        while self.model.cum_freq[symbol] as CodeValue > cum {
            symbol += 1;
        }

        let lo_freq = self.model.cum_freq[symbol] as CodeValue;
        let hi_freq = self.model.cum_freq[symbol - 1] as CodeValue;

        self.high = self.low + (range * hi_freq / total) - 1;
        self.low = self.low + (range * lo_freq / total);

        loop {
            if self.high < HALF {
                // do nothing
            } else if self.low >= HALF {
                self.value -= HALF;
                self.low -= HALF;
                self.high -= HALF;
            } else if self.low >= FIRST_QTR && self.high < THIRD_QTR {
                self.value -= FIRST_QTR;
                self.low -= FIRST_QTR;
                self.high -= FIRST_QTR;
            } else {
                break;
            }
            self.low = self.low << 1;
            self.high = (self.high << 1) + 1;
            self.value = (self.value << 1) + (try!(self.input_bit()) as CodeValue);
        }
        Ok(symbol)
    }
}

impl<R: Read> Read for Decoder<R> {
    fn read(&mut self, data: &mut [u8]) -> io::Result<usize> {
        if self.eof {
            return Ok(0);
        }

        let mut written = 0;
        while written < data.len()  {
            let symbol = try!(self.decode_symbol());
            if symbol == EOF_SYMBOL {
                self.eof = true;
                break;
            }
            let ch = self.model.index_to_char[symbol as usize];
            data[written] = ch as u8;
            written += 1;
            self.model.update(symbol);
        }
        Ok(written)
    }
}

/// Read all data from `input`, compress it using an order-0
/// arithmetic encoder and write the compressed data to `output`.
pub fn compress<R: Read, W: Write>(mut input: R, output: W) -> Result<W, Error> {
    let mut cw = Encoder::new(output);
    try!(io::copy(&mut input, &mut cw));
    try!(cw.flush());
    Ok(cw.into_inner())
}

/// Read all data from `input`, decompress it using an order-0
/// arithmetic encoder and write the decompressed data to `output`.
/// The data must be produced by the `compress` function.
pub fn decompress<R: Read, W: Write>(input: R, mut output: W) -> Result<W, Error> {
    let mut cr = try!(Decoder::new(input));
    try!(io::copy(&mut cr, &mut output));
    Ok(output)
}

#[cfg(test)]
mod test {
    use std::io::Cursor;
    use super::{compress, decompress};

    #[test]
    fn compress_empty() {
        let input = [];
        let compressed = compress(Cursor::new(&input), vec![]).unwrap();
        let expected = [128, 0];
        assert_eq!(&expected[..], &compressed[..]);
    }

    #[test]
    fn decompress_empty() {
        let input = [128, 0];
        let decompressed = decompress(Cursor::new(&input), vec![]).unwrap();
        let expected: [u8;0] = [];
        assert_eq!(&expected[..], &decompressed[..]);
    }

    #[test]
    fn compress_a() {
        let input = b"a";
        let compressed = compress(Cursor::new(&input), vec![]).unwrap();
        let expected = [121, 195, 1];
        assert_eq!(&expected[..], &compressed[..]);
    }

    #[test]
    fn decompress_a() {
        let input = [121, 195, 1];
        let decompressed = decompress(Cursor::new(&input), vec![]).unwrap();
        let expected = b"a";
        assert_eq!(&expected[..], &decompressed[..]);
    }

    #[test]
    fn compress_aaa() {
        let input = b"aaaaaaaaa";
        let compressed = compress(Cursor::new(&input), vec![]).unwrap();
        let expected = [249, 3, 254, 0, 255, 255, 223, 97];
        assert_eq!(&expected[..], &compressed[..]);
    }

    #[test]
    fn decompress_aaa() {
        let input = [249, 3, 254, 0, 255, 255, 223, 97];
        let decompressed = decompress(Cursor::new(&input), vec![]).unwrap();
        let expected = b"aaaaaaaaa";
        assert_eq!(&expected[..], &decompressed[..]);
    }

    #[test]
    fn compress_decompress() {
        let f = include_bytes!("witten_arith.rs");
        let original = &f[..];
        let compressed = compress(Cursor::new(&original), vec![]).unwrap();
        let decompressed = decompress(Cursor::new(compressed), vec![]).unwrap();

        assert_eq!(&original[..], &decompressed[..]);
    }
}
<|endoftext|>


<commit_before>use core::cell::UnsafeCell;
use core::intrinsics::likely;
use core::sync::atomic::{AtomicBool, AtomicU32, AtomicU64, Ordering::SeqCst};

use crate::multitasking::{Process, ProcessSwitch, SCHEDULER};

use d7time::{Duration, Instant, TimeSpec};

use crate::driver::pit::TIME_BETWEEN_E_12;

pub struct SystemClock {
    lock: UnsafeCell<AtomicBool>,
    sec: UnsafeCell<AtomicU64>,
    nsec: UnsafeCell<AtomicU32>,
}
unsafe impl Sync for SystemClock {}
impl SystemClock {
    const unsafe fn new() -> Self {
        Self {
            lock: UnsafeCell::new(AtomicBool::new(false)),
            sec: UnsafeCell::new(AtomicU64::new(0)),
            nsec: UnsafeCell::new(AtomicU32::new(0)),
        }
    }

    /// Only to be used by the IRQ handler for PIT clock ticks
    ///
    /// Returns process switch information (optionally)
    ///
    /// # Time constraints
    /// This function must be complete before PIT fires next interrupt,
    /// otherwise it can deadlock.
    ///
    /// ^^^ That shouldn't be possible, as PIT needs EOI before firing again.
    pub unsafe fn tick(&self) -> ProcessSwitch {
        let inc: u32 = (TIME_BETWEEN_E_12 / 1_000) as u32;

        // The lock is only held for clock updates
        let mut uc_lock = self.lock.get();
        let mut uc_sec = self.sec.get();
        let mut uc_nsec = self.nsec.get();

        // Aquire lock
        if (*uc_lock).compare_and_swap(false, true, SeqCst) {
            panic!("SystemClock already locked");
        }

        // Get values
        let mut sec = (*uc_sec).load(SeqCst);
        let mut nsec = (*uc_nsec).load(SeqCst);

        // Cannot overflow, as (2 * max nanoseconds) < u32::MAX
        if nsec + inc >= 1_000_000_000 {
            sec += 1;
            nsec = (nsec + inc) - 1_000_000_000;
        } else {
            nsec += inc;
        }

        // Set new values
        (*uc_sec).store(sec, SeqCst);
        (*uc_nsec).store(nsec, SeqCst);

        // It must not have been updated during this time, no check here
        (*uc_lock).store(false, SeqCst);

        // Update multitasking scheduler
        SCHEDULER.try_lock().expect("SCHED LOCKED").tick(self.now())
    }

    /// Gets current time
    pub fn now(&self) -> Instant {
        unsafe {
            let mut uc_sec = self.sec.get();
            let mut uc_nsec = self.nsec.get();

            let mut prev_sec = (*uc_sec).load(SeqCst);
            let mut prev_nsec = (*uc_nsec).load(SeqCst);

            // Polling needed to avoid invalid values on second borders
            loop {
                let sec = (*uc_sec).load(SeqCst);
                let nsec = (*uc_nsec).load(SeqCst);

                if likely(prev_sec == sec && prev_nsec <= nsec) {
                    return Instant::create(TimeSpec { sec, nsec });
                } else {
                    prev_sec = sec;
                    prev_nsec = nsec;
                }
            }
        }
    }
}

pub static SYSCLOCK: SystemClock = unsafe { SystemClock::new() };

pub fn init() {
    rprintln!("SYSCLOCK: enabled");
}

pub fn busy_sleep_until(until: Instant) {
    while SYSCLOCK.now() < until {}
}

pub fn sleep_ms(ms: u64) {
    busy_sleep_until(SYSCLOCK.now() + Duration::from_millis(ms));
}
<commit_msg>Clean up clippy warnings<commit_after>use core::cell::UnsafeCell;
use core::intrinsics::likely;
use core::sync::atomic::{AtomicBool, AtomicU32, AtomicU64, Ordering::SeqCst};

use crate::multitasking::{Process, ProcessSwitch, SCHEDULER};

use d7time::{Duration, Instant, TimeSpec};

use crate::driver::pit::TIME_BETWEEN_E_12;

pub struct SystemClock {
    lock: UnsafeCell<AtomicBool>,
    sec: UnsafeCell<AtomicU64>,
    nsec: UnsafeCell<AtomicU32>,
}
unsafe impl Sync for SystemClock {}
impl SystemClock {
    const unsafe fn new() -> Self {
        Self {
            lock: UnsafeCell::new(AtomicBool::new(false)),
            sec: UnsafeCell::new(AtomicU64::new(0)),
            nsec: UnsafeCell::new(AtomicU32::new(0)),
        }
    }

    /// Only to be used by the IRQ handler for PIT clock ticks
    ///
    /// Returns process switch information (optionally)
    ///
    /// # Time constraints
    /// This function must be complete before PIT fires next interrupt,
    /// otherwise it can deadlock.
    ///
    /// ^^^ That shouldn't be possible, as PIT needs EOI before firing again.
    pub unsafe fn tick(&self) -> ProcessSwitch {
        let inc: u32 = (TIME_BETWEEN_E_12 / 1_000) as u32;

        // The lock is only held for clock updates
        let uc_lock = self.lock.get();
        let uc_sec = self.sec.get();
        let uc_nsec = self.nsec.get();

        // Aquire lock
        if (*uc_lock).compare_and_swap(false, true, SeqCst) {
            panic!("SystemClock already locked");
        }

        // Get values
        let mut sec = (*uc_sec).load(SeqCst);
        let mut nsec = (*uc_nsec).load(SeqCst);

        // Cannot overflow, as (2 * max nanoseconds) < u32::MAX
        if nsec + inc >= 1_000_000_000 {
            sec += 1;
            nsec = (nsec + inc) - 1_000_000_000;
        } else {
            nsec += inc;
        }

        // Set new values
        (*uc_sec).store(sec, SeqCst);
        (*uc_nsec).store(nsec, SeqCst);

        // It must not have been updated during this time, no check here
        (*uc_lock).store(false, SeqCst);

        // Update multitasking scheduler
        SCHEDULER.try_lock().expect("SCHED LOCKED").tick(self.now())
    }

    /// Gets current time
    pub fn now(&self) -> Instant {
        unsafe {
            let uc_sec = self.sec.get();
            let uc_nsec = self.nsec.get();

            let mut prev_sec = (*uc_sec).load(SeqCst);
            let mut prev_nsec = (*uc_nsec).load(SeqCst);

            // Polling needed to avoid invalid values on second borders
            loop {
                let sec = (*uc_sec).load(SeqCst);
                let nsec = (*uc_nsec).load(SeqCst);

                if likely(prev_sec == sec && prev_nsec <= nsec) {
                    return Instant::create(TimeSpec { sec, nsec });
                } else {
                    prev_sec = sec;
                    prev_nsec = nsec;
                }
            }
        }
    }
}

pub static SYSCLOCK: SystemClock = unsafe { SystemClock::new() };

pub fn init() {
    rprintln!("SYSCLOCK: enabled");
}

pub fn busy_sleep_until(until: Instant) {
    while SYSCLOCK.now() < until {}
}

pub fn sleep_ms(ms: u64) {
    busy_sleep_until(SYSCLOCK.now() + Duration::from_millis(ms));
}
<|endoftext|>


<commit_before>use core::container::Container;

pub type EFI_HANDLE = *();
pub struct EFI_GUID((u32, u16, u16, u8, u8, u8, u8, u8, u8, u8, u8));

struct EFI_TABLE_HEADER {
    Signature  : u64,
    Revision   : u32,
    HeaderSize : u32,
    CRC32      : u32,
    priv Reserved : u32
}

pub struct EFI_SYSTEM_TABLE {
    Hdr : EFI_TABLE_HEADER,
    FirmwareVendor : *u16,
    FirmwareRevision : u32,
    ConsoleInHandle : EFI_HANDLE,
    ConIn : *EFI_SIMPLE_TEXT_INPUT_PROTOCOL,
    ConsoleOutHandle : EFI_HANDLE,
    ConOut : *EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL,
    ConsoleErrorHandle : EFI_HANDLE,
    StdErr : *EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL,
    RuntimeServices : *EFI_RUNTIME_SERVICES,
    BootServices : *EFI_BOOT_SERVICES,
    NumberOfTableEntries : uint,
    ConfigurationTable : *EFI_CONFIGURATION_TABLE
}

pub static mut SYSTEM_TABLE : *EFI_SYSTEM_TABLE = 0 as *EFI_SYSTEM_TABLE;

struct EFI_SIMPLE_TEXT_INPUT_PROTOCOL;

struct EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL {
    Reset : EFI_TEXT_RESET,
    OutputString : EFI_TEXT_STRING,
    // ... and more stuff that we're ignoring.
}

type EFI_TEXT_RESET = *();

type EFI_TEXT_STRING = extern "win64" fn(*EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL,
                                         *u16);

struct EFI_RUNTIME_SERVICES;

struct EFI_BOOT_SERVICES;

struct EFI_CONFIGURATION_TABLE {
    VendorGuid : EFI_GUID,
    VendorTable : *()
}

pub struct SystemTable(*EFI_SYSTEM_TABLE);

impl SystemTable {
    #[no_split_stack]
    fn console(&self) -> Console {
        unsafe {
            Console {
                input: (***self).ConIn,
                output: (***self).ConOut,
            }
        }
    }
}

fn unpack<T>(slice: &[T]) -> (*T, uint) {
    unsafe {
        transmute(slice)
    }
}

pub trait SimpleTextOutput {
    unsafe fn write_raw(&self, str: *u16);

    #[no_split_stack]
    fn write(&self, str: &str) {
        let mut buf = [0u16, ..4096];

        let mut i = 0;
        while i < buf.len() && i < str.len() {
            // TODO: make sure the characters are all ascii
            buf[i] = str[i] as u16;
            i += 1;
        }
        buf[buf.len() - 1] = 0;

        unsafe {
            let (p, _) = unpack(buf);
            self.write_raw(p);
        }
    }
}

pub trait SimpleTextInput {
}

pub struct Console {
    priv input  : *EFI_SIMPLE_TEXT_INPUT_PROTOCOL,
    priv output : *EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL,
}

impl SimpleTextOutput for Console {
    #[no_split_stack]
    unsafe fn write_raw(&self, str: *u16) {
        ((*(*self).output).OutputString)(self.output, str);
    }
}

impl SimpleTextInput for Console {
}

extern "rust-intrinsic" {
    fn transmute<T,U>(val: T) -> U;
}

#[no_mangle]
#[no_split_stack]
pub extern "win64" fn efi_start(_ImageHandle : EFI_HANDLE,
                                sys_table : *EFI_SYSTEM_TABLE) -> int {
    unsafe { SYSTEM_TABLE = sys_table; }
    ::efi_main(SystemTable(sys_table));
    0
}

#[no_mangle]
#[no_split_stack]
pub fn __morestack() {
    // Horrible things will probably happen if this is ever called.
}

#[no_mangle]
#[no_split_stack]
pub extern fn memset(s : *u8, c : int, n : uint) -> *u8 {
    unsafe {
        let s : &mut [u8] = transmute((s, n));
        let mut i = 0;
        while i < n {
            s[i] = c as u8;
            i += 1;
            // Use inline assembly here to defeat LLVM's loop-idiom pass
            asm!("");
        }
    }

    s
}
<commit_msg>Cleaner EFI_GUID definition.<commit_after>use core::container::Container;

pub type EFI_HANDLE = *();
pub struct EFI_GUID(u32, u16, u16, [u8, ..8]);

struct EFI_TABLE_HEADER {
    Signature  : u64,
    Revision   : u32,
    HeaderSize : u32,
    CRC32      : u32,
    priv Reserved : u32
}

pub struct EFI_SYSTEM_TABLE {
    Hdr : EFI_TABLE_HEADER,
    FirmwareVendor : *u16,
    FirmwareRevision : u32,
    ConsoleInHandle : EFI_HANDLE,
    ConIn : *EFI_SIMPLE_TEXT_INPUT_PROTOCOL,
    ConsoleOutHandle : EFI_HANDLE,
    ConOut : *EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL,
    ConsoleErrorHandle : EFI_HANDLE,
    StdErr : *EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL,
    RuntimeServices : *EFI_RUNTIME_SERVICES,
    BootServices : *EFI_BOOT_SERVICES,
    NumberOfTableEntries : uint,
    ConfigurationTable : *EFI_CONFIGURATION_TABLE
}

pub static mut SYSTEM_TABLE : *EFI_SYSTEM_TABLE = 0 as *EFI_SYSTEM_TABLE;

struct EFI_SIMPLE_TEXT_INPUT_PROTOCOL;

struct EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL {
    Reset : EFI_TEXT_RESET,
    OutputString : EFI_TEXT_STRING,
    // ... and more stuff that we're ignoring.
}

type EFI_TEXT_RESET = *();

type EFI_TEXT_STRING = extern "win64" fn(*EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL,
                                         *u16);

struct EFI_RUNTIME_SERVICES;

struct EFI_BOOT_SERVICES;

struct EFI_CONFIGURATION_TABLE {
    VendorGuid : EFI_GUID,
    VendorTable : *()
}

pub struct SystemTable(*EFI_SYSTEM_TABLE);

impl SystemTable {
    #[no_split_stack]
    fn console(&self) -> Console {
        unsafe {
            Console {
                input: (***self).ConIn,
                output: (***self).ConOut,
            }
        }
    }
}

fn unpack<T>(slice: &[T]) -> (*T, uint) {
    unsafe {
        transmute(slice)
    }
}

pub trait SimpleTextOutput {
    unsafe fn write_raw(&self, str: *u16);

    #[no_split_stack]
    fn write(&self, str: &str) {
        let mut buf = [0u16, ..4096];

        let mut i = 0;
        while i < buf.len() && i < str.len() {
            // TODO: make sure the characters are all ascii
            buf[i] = str[i] as u16;
            i += 1;
        }
        buf[buf.len() - 1] = 0;

        unsafe {
            let (p, _) = unpack(buf);
            self.write_raw(p);
        }
    }
}

pub trait SimpleTextInput {
}

pub struct Console {
    priv input  : *EFI_SIMPLE_TEXT_INPUT_PROTOCOL,
    priv output : *EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL,
}

impl SimpleTextOutput for Console {
    #[no_split_stack]
    unsafe fn write_raw(&self, str: *u16) {
        ((*(*self).output).OutputString)(self.output, str);
    }
}

impl SimpleTextInput for Console {
}

extern "rust-intrinsic" {
    fn transmute<T,U>(val: T) -> U;
}

#[no_mangle]
#[no_split_stack]
pub extern "win64" fn efi_start(_ImageHandle : EFI_HANDLE,
                                sys_table : *EFI_SYSTEM_TABLE) -> int {
    unsafe { SYSTEM_TABLE = sys_table; }
    ::efi_main(SystemTable(sys_table));
    0
}

#[no_mangle]
#[no_split_stack]
pub fn __morestack() {
    // Horrible things will probably happen if this is ever called.
}

#[no_mangle]
#[no_split_stack]
pub extern fn memset(s : *u8, c : int, n : uint) -> *u8 {
    unsafe {
        let s : &mut [u8] = transmute((s, n));
        let mut i = 0;
        while i < n {
            s[i] = c as u8;
            i += 1;
            // Use inline assembly here to defeat LLVM's loop-idiom pass
            asm!("");
        }
    }

    s
}
<|endoftext|>


<commit_before>use std::ascii::AsciiExt;
use core::position::{Size, HasSize};
use core::cellbuffer::CellAccessor;

use ui::core::{
    Alignable,
    HorizontalAlign,
    VerticalAlign,
    Widget,
    Frame,
    Painter,
};

/// Display text to widgets
///
/// # Examples
///
/// ```
/// use rustty::ui::core::{VerticalAlign, HorizontalAlign, Widget};
/// use rustty::ui::{Dialog, Label};
///
/// let mut maindlg = Dialog::new(60, 10);
///
/// let mut label = Label::from_str("Hi, this is an example!");
/// label.pack(&maindlg, HorizontalAlign::Middle, VerticalAlign::Middle, (0,0));
///
/// maindlg.add_label(label);
/// maindlg.draw_box();
/// ```
///
pub struct Label {
    frame: Frame,
    text: Vec<String>,
    x: usize,
    y: usize,
    t_halign: HorizontalAlign,
    t_valign: VerticalAlign,
    t_margin: (usize, usize)
}

impl Label {
    /// Construct a new Label widget `cols` wide by `rols` high. Initial text is empty
    /// and left aligned
    ///
    /// # Examples
    ///
    /// ```
    /// use rustty::ui::Label;
    ///
    /// let mut label = Label::new(60, 10);
    /// ```
    ///
    pub fn new(cols: usize, rows: usize) -> Label {
        Label {
            frame: Frame::new(cols, rows),
            text: Vec::new(),
            x: 0,
            y: 0,
            t_halign: HorizontalAlign::Left,
            t_valign: VerticalAlign::Middle,
            t_margin: (0, 0),
        }
    }

    /// Construct a new label widget from an existing string *s*. *s* can either be a
    /// `&str` or `String` , and a label will be constructed that is the size of the
    /// length of characters in *s*. Text is left aligned by default
    ///
    /// # Examples
    ///
    /// ```
    /// use rustty::ui::Label;
    ///
    /// let mut label1 = Label::from_str("This is a label");    // label is size (15x1)
    ///
    /// let s = "Here's another label".to_string();
    /// let mut label2 = Label::from_str(s);                    // label is size (20x1)
    /// ```
    ///
    pub fn from_str<S: Into<String>>(s: S) -> Label {
        let s = s.into();
        Label {
            frame: Frame::new(s.len(), 1),
            text: vec![s.into()],
            x: 0,
            y: 0,
            t_halign: HorizontalAlign::Left,
            t_valign: VerticalAlign::Middle,
            t_margin: (0, 0),
        }
    }

    /// Specify a custom alignment for the text within the widget. Each line
    /// drawn within the label will adhere to the alignments passed for the
    /// text. *note that text alignment is with respect to the *label*
    ///
    /// # Examples
    ///
    /// ```
    /// use rustty::ui::core::{HorizontalAlign, VerticalAlign};
    /// use rustty::ui::Label;
    ///
    /// let mut label = Label::new(20, 3);
    /// label.set_text("Centered");
    /// label.align_text(HorizontalAlign::Middle, VerticalAlign::Middle, (0,0));
    /// ```
    ///
    pub fn align_text(&mut self, halign: HorizontalAlign, valign: VerticalAlign,
                    margin: (usize, usize)) {
        self.t_halign = halign;
        self.t_valign = valign;
        self.t_margin = margin;
    }

    /// Set the text of the widget to the passed `&str` or `String`. If the
    /// widget does not have enough room to display the new text, the label
    /// will only show the truncated text. *resize()* must be called to extend
    /// the size of the label.
    ///
    /// # Examples
    ///
    /// ```
    /// use rustty::HasSize;
    /// use rustty::ui::core::Widget;
    /// use rustty::ui::Label;
    ///
    /// let mut label1 = Label::new(20, 3);
    /// label1.set_text("Initial text");
    /// ```
    ///
    pub fn set_text<S: Into<String>>(&mut self, new_str: S) {
        let (framex, _) = self.frame.size();
        self.text = Vec::new();
        let mut parse = new_str.into();
        let mut line = String::new();

        // This loop below will accomplish splitting a line of text
        // into lines that adhere to the amount of rows in a label
        loop {
            // Look for a word until a whitespace is reached
            if let Some(loc) = parse.find(char::is_whitespace) {
                let line_len = line.len();
                let tmp = parse[..loc].to_owned();
                // If the word can fit on the current line, add it
                if line_len + tmp.len() + self.t_margin.0 < framex {
                    line.push_str(&tmp);
                } else {
                    line = line.trim_right().to_owned();
                    self.text.push(line);
                    line = tmp.to_owned();
                }
                parse = parse[loc..].to_owned();
            } else {
                // If no whitespace detected, there may still be one
                // more word so attempt to add it
                if parse.len() != 0 {
                    let line_len = line.len();
                    if line_len + parse.len() + self.t_margin.0 < framex {
                        line.push_str(&parse);
                        self.text.push(line);
                    } else {
                        self.text.push(line);
                        self.text.push(parse);
                    }
                }
                break;
            }

            // Look for the range of spaces between words
            if let Some(loc) = parse.find(|c: char| c.is_ascii() && c != ' ') {
                let line_len = line.len();
                let tmp = parse[..loc].to_owned();
                // If the next word can fit on the current line, do so
                if line_len + tmp.len() + self.t_margin.0 < framex {
                    line.push_str(&tmp);
                } else {
                    line = line.trim_right().to_owned();
                    self.text.push(line);
                    line = "".to_string();
                }
                parse = parse[loc..].to_owned();
            } else {
                // We don't care if there's spaces at the end, so don't check
                break;
            }
        }
    }
}

impl Widget for Label {
    fn draw(&mut self, parent: &mut CellAccessor) {
        // For every line to be written, align it correctly as defined by the user in
        // align_text, if not this text will be left and middle aligned by default
        for (i, item) in self.text.iter().enumerate() {
            self.x = self.frame.halign_line(&item, self.t_halign.clone(), self.t_margin.0);
            self.y = self.frame.valign_line(&item, self.t_valign.clone(), self.t_margin.1);
            self.frame.printline(self.x, self.y + i, &item);
        }
        self.frame.draw_into(parent);
    }

    fn pack(&mut self, parent: &HasSize, halign: HorizontalAlign, valign: VerticalAlign,
                margin: (usize, usize)) {
        self.frame.align(parent, halign, valign, margin);
    }

    fn draw_box(&mut self) {
        self.frame.draw_box();
    }

    fn resize(&mut self, new_size: Size) {
        self.frame.resize(new_size);
    }

    fn frame(&self) -> &Frame {
        &self.frame
    }

    fn frame_mut(&mut self) -> &mut Frame {
        &mut self.frame
    }
}
<commit_msg>Modify label to support unicode<commit_after>use std::ascii::AsciiExt;
use core::position::{Size, HasSize};
use core::cellbuffer::CellAccessor;

use ui::core::{
    Alignable,
    HorizontalAlign,
    VerticalAlign,
    Widget,
    Frame,
    Painter,
};

/// Display text to widgets
///
/// # Examples
///
/// ```
/// use rustty::ui::core::{VerticalAlign, HorizontalAlign, Widget};
/// use rustty::ui::{Dialog, Label};
///
/// let mut maindlg = Dialog::new(60, 10);
///
/// let mut label = Label::from_str("Hi, this is an example!");
/// label.pack(&maindlg, HorizontalAlign::Middle, VerticalAlign::Middle, (0,0));
///
/// maindlg.add_label(label);
/// maindlg.draw_box();
/// ```
///
pub struct Label {
    frame: Frame,
    text: Vec<String>,
    x: usize,
    y: usize,
    t_halign: HorizontalAlign,
    t_valign: VerticalAlign,
    t_margin: (usize, usize)
}

impl Label {
    /// Construct a new Label widget `cols` wide by `rols` high. Initial text is empty
    /// and left aligned
    ///
    /// # Examples
    ///
    /// ```
    /// use rustty::ui::Label;
    ///
    /// let mut label = Label::new(60, 10);
    /// ```
    ///
    pub fn new(cols: usize, rows: usize) -> Label {
        Label {
            frame: Frame::new(cols, rows),
            text: Vec::new(),
            x: 0,
            y: 0,
            t_halign: HorizontalAlign::Left,
            t_valign: VerticalAlign::Middle,
            t_margin: (0, 0),
        }
    }

    /// Construct a new label widget from an existing string *s*. *s* can either be a
    /// `&str` or `String` , and a label will be constructed that is the size of the
    /// length of characters in *s*. Text is left aligned by default
    ///
    /// # Examples
    ///
    /// ```
    /// use rustty::ui::Label;
    ///
    /// let mut label1 = Label::from_str("This is a label");    // label is size (15x1)
    ///
    /// let s = "Here's another label".to_string();
    /// let mut label2 = Label::from_str(s);                    // label is size (20x1)
    /// ```
    ///
    pub fn from_str<S: Into<String>>(s: S) -> Label {
        let s = s.into();
        Label {
            frame: Frame::new(s.len(), 1),
            text: vec![s.into()],
            x: 0,
            y: 0,
            t_halign: HorizontalAlign::Left,
            t_valign: VerticalAlign::Middle,
            t_margin: (0, 0),
        }
    }

    /// Specify a custom alignment for the text within the widget. Each line
    /// drawn within the label will adhere to the alignments passed for the
    /// text. *note that text alignment is with respect to the *label*
    ///
    /// # Examples
    ///
    /// ```
    /// use rustty::ui::core::{HorizontalAlign, VerticalAlign};
    /// use rustty::ui::Label;
    ///
    /// let mut label = Label::new(20, 3);
    /// label.set_text("Centered");
    /// label.align_text(HorizontalAlign::Middle, VerticalAlign::Middle, (0,0));
    /// ```
    ///
    pub fn align_text(&mut self, halign: HorizontalAlign, valign: VerticalAlign,
                    margin: (usize, usize)) {
        self.t_halign = halign;
        self.t_valign = valign;
        self.t_margin = margin;
    }

    /// Set the text of the widget to the passed `&str` or `String`. If the
    /// widget does not have enough room to display the new text, the label
    /// will only show the truncated text. *resize()* must be called to extend
    /// the size of the label.
    ///
    /// # Examples
    ///
    /// ```
    /// use rustty::HasSize;
    /// use rustty::ui::core::Widget;
    /// use rustty::ui::Label;
    ///
    /// let mut label1 = Label::new(20, 3);
    /// label1.set_text("Initial text");
    /// ```
    ///
    pub fn set_text<S: Into<String>>(&mut self, new_str: S) {
        let (framex, _) = self.frame.size();
        self.text = Vec::new();
        let mut parse = new_str.into();
        let mut line = String::new();

        // This loop below will accomplish splitting a line of text
        // into lines that adhere to the amount of rows in a label
        loop {
            // Look for a word until a whitespace is reached
            if let Some(loc) = parse.find(char::is_whitespace) {
                let line_len = line.len();
                let tmp = parse[..loc].to_owned();
                // If the word can fit on the current line, add it
                if line_len + tmp.len() + self.t_margin.0 < framex {
                    line.push_str(&tmp);
                } else {
                    line = line.trim_right().to_owned();
                    self.text.push(line);
                    line = tmp.to_owned();
                }
                parse = parse[loc..].to_owned();
            } else {
                // If no whitespace detected, there may still be one
                // more word so attempt to add it
                if parse.len() != 0 {
                    let line_len = line.len();
                    if line_len + parse.len() + self.t_margin.0 < framex {
                        line.push_str(&parse);
                        self.text.push(line);
                    } else {
                        self.text.push(line);
                        self.text.push(parse);
                    }
                }
                break;
            }

            // Look for the range of spaces between words
            if let Some(loc) = parse.find(|c: char| c != ' ') {
                let line_len = line.len();
                let tmp = parse[..loc].to_owned();
                // If the next word can fit on the current line, do so
                if line_len + tmp.len() + self.t_margin.0 < framex {
                    line.push_str(&tmp);
                } else {
                    line = line.trim_right().to_owned();
                    self.text.push(line);
                    line = "".to_string();
                }
                parse = parse[loc..].to_owned();
            } else {
                // We don't care if there's spaces at the end, so don't check
                break;
            }
        }
    }
}

impl Widget for Label {
    fn draw(&mut self, parent: &mut CellAccessor) {
        // For every line to be written, align it correctly as defined by the user in
        // align_text, if not this text will be left and middle aligned by default
        for (i, item) in self.text.iter().enumerate() {
            self.x = self.frame.halign_line(&item, self.t_halign.clone(), self.t_margin.0);
            self.y = self.frame.valign_line(&item, self.t_valign.clone(), self.t_margin.1);
            self.frame.printline(self.x, self.y + i, &item);
        }
        self.frame.draw_into(parent);
    }

    fn pack(&mut self, parent: &HasSize, halign: HorizontalAlign, valign: VerticalAlign,
                margin: (usize, usize)) {
        self.frame.align(parent, halign, valign, margin);
    }

    fn draw_box(&mut self) {
        self.frame.draw_box();
    }

    fn resize(&mut self, new_size: Size) {
        self.frame.resize(new_size);
    }

    fn frame(&self) -> &Frame {
        &self.frame
    }

    fn frame_mut(&mut self) -> &mut Frame {
        &mut self.frame
    }
}
<|endoftext|>